mirror of
https://github.com/clangen/musikcube.git
synced 2025-04-16 14:42:41 +00:00
Working MP3 decoder!
This commit is contained in:
parent
5207bb36de
commit
8cd06ea886
@ -1,20 +1,72 @@
|
||||
#include "StdAfx.h"
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
#include "mp3decoder.h"
|
||||
|
||||
MP3Decoder::MP3Decoder() :
|
||||
m_hFile(NULL),
|
||||
m_pDecoder(NULL)
|
||||
{
|
||||
static bool splitFrame(musik::core::io::IDataStream *dataStream, Frame &fr) {
|
||||
unsigned char headerbuf[4] = { 0, 0, 0, 0 };
|
||||
unsigned char crcbuf[2];
|
||||
unsigned char sideInfoBuffer[32];
|
||||
unsigned long bytesRead;
|
||||
unsigned long errorCount = 0;
|
||||
unsigned long currentOffset = dataStream->Position();
|
||||
|
||||
if (dataStream->Read(headerbuf, 4) != 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (!fr.m_Header.Load(headerbuf)) {
|
||||
headerbuf[0] = headerbuf[1];
|
||||
headerbuf[1] = headerbuf[2];
|
||||
headerbuf[2] = headerbuf[3];
|
||||
|
||||
if (dataStream->Read(&headerbuf[3], 1) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (errorCount++ >= fr.m_Header.GetDataSize()) {
|
||||
fr.m_Header.Reset();
|
||||
}
|
||||
|
||||
currentOffset++;
|
||||
}
|
||||
|
||||
if (fr.m_Header.IsCRC()) {
|
||||
if (dataStream->Read(crcbuf, 2) != 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
fr.m_CRC.Load(crcbuf);
|
||||
}
|
||||
|
||||
if (fr.m_Header.GetLayer() == LAYER3) {
|
||||
unsigned count = fr.m_Header.GetSideInfoSize();
|
||||
|
||||
if (dataStream->Read(sideInfoBuffer, count) != count) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fr.m_SI.Load(&fr.m_Header, sideInfoBuffer)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned frameBytes = fr.m_Header.GetDataSize();
|
||||
if (dataStream->Read(fr.m_Data, frameBytes) != frameBytes) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MP3Decoder::~MP3Decoder(void)
|
||||
{
|
||||
Close();
|
||||
MP3Decoder::MP3Decoder()
|
||||
: m_pDecoder(NULL) {
|
||||
}
|
||||
|
||||
unsigned long MP3Decoder::GetID3HeaderLength(unsigned char * buffer)
|
||||
{
|
||||
MP3Decoder::~MP3Decoder() {
|
||||
}
|
||||
|
||||
unsigned long MP3Decoder::GetID3HeaderLength(unsigned char * buffer) {
|
||||
unsigned char VerMajor;
|
||||
unsigned char VerMinor;
|
||||
unsigned char Flags;
|
||||
@ -22,7 +74,7 @@ unsigned long MP3Decoder::GetID3HeaderLength(unsigned char * buffer)
|
||||
|
||||
if( (toupper(buffer[0]) == 'I') &&
|
||||
(toupper(buffer[1]) == 'D') &&
|
||||
(toupper(buffer[2]) == '3') )
|
||||
(toupper(buffer[2]) == '3'))
|
||||
{
|
||||
VerMajor = buffer[3];
|
||||
VerMinor = buffer[4];
|
||||
@ -34,50 +86,55 @@ unsigned long MP3Decoder::GetID3HeaderLength(unsigned char * buffer)
|
||||
return(Length);
|
||||
}
|
||||
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool MP3Decoder::GetXingHeader(unsigned char * XingBuffer)
|
||||
{
|
||||
#define FRAMES_FLAG 0x0001
|
||||
#define BYTES_FLAG 0x0002
|
||||
#define TOC_FLAG 0x0004
|
||||
#define VBR_SCALE_FLAG 0x0008
|
||||
#define GET_INT32BE(b) (i = (b[0] << 24) | (b[1] << 16) | b[2] << 8 | b[3], b += 4, i)
|
||||
bool MP3Decoder::GetXingHeader(unsigned char * xingBuffer) {
|
||||
#define FRAMES_FLAG 0x0001
|
||||
#define BYTES_FLAG 0x0002
|
||||
#define TOC_FLAG 0x0004
|
||||
#define VBR_SCALE_FLAG 0x0008
|
||||
#define GET_INT32BE(b) (i = (b[0] << 24) | (b[1] << 16) | b[2] << 8 | b[3], b += 4, i) /* windows only? */
|
||||
|
||||
unsigned long i;
|
||||
|
||||
m_bXingValid = false;
|
||||
|
||||
if(strncmp((char *)XingBuffer, "Xing", 4))
|
||||
if(strncmp((char *)XingBuffer, "Info", 4))
|
||||
if (strncmp((char *) xingBuffer, "Xing", 4)) {
|
||||
if (strncmp((char *)xingBuffer, "Info", 4)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
XingBuffer += 4;
|
||||
xingBuffer += 4;
|
||||
|
||||
unsigned long HeadFlags = GET_INT32BE(XingBuffer);
|
||||
unsigned long headFlags = GET_INT32BE(xingBuffer);
|
||||
|
||||
m_NumFrames = 0;
|
||||
if(HeadFlags & FRAMES_FLAG)
|
||||
m_NumFrames = GET_INT32BE(XingBuffer);
|
||||
if(m_NumFrames < 1)
|
||||
if (headFlags & FRAMES_FLAG) {
|
||||
m_NumFrames = GET_INT32BE(xingBuffer);
|
||||
}
|
||||
|
||||
if (m_NumFrames < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_StreamDataLength = 0;
|
||||
if(HeadFlags & BYTES_FLAG)
|
||||
m_StreamDataLength = GET_INT32BE(XingBuffer);
|
||||
if (headFlags & BYTES_FLAG) {
|
||||
m_StreamDataLength = GET_INT32BE(xingBuffer);
|
||||
}
|
||||
|
||||
if(HeadFlags & TOC_FLAG)
|
||||
{
|
||||
for (i = 0; i < 100; i++)
|
||||
m_TOC[i] = XingBuffer[i];
|
||||
XingBuffer += 100;
|
||||
if (headFlags & TOC_FLAG) {
|
||||
for (i = 0; i < 100; i++) {
|
||||
m_TOC[i] = xingBuffer[i];
|
||||
}
|
||||
|
||||
xingBuffer += 100;
|
||||
}
|
||||
|
||||
m_VbrScale = -1;
|
||||
if(HeadFlags & VBR_SCALE_FLAG)
|
||||
{
|
||||
m_VbrScale = GET_INT32BE(XingBuffer);
|
||||
if (headFlags & VBR_SCALE_FLAG) {
|
||||
m_VbrScale = GET_INT32BE(xingBuffer);
|
||||
}
|
||||
|
||||
m_bXingValid = true;
|
||||
@ -85,37 +142,35 @@ bool MP3Decoder::GetXingHeader(unsigned char * XingBuffer)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MP3Decoder::GetStreamData(void)
|
||||
{
|
||||
bool MP3Decoder::GetStreamData() {
|
||||
unsigned char tbuf[11];
|
||||
unsigned long bytesread;
|
||||
Frame fr;
|
||||
|
||||
ReadFile(m_hFile, tbuf, 10, &bytesread, NULL);
|
||||
|
||||
this->dataStream->Read(tbuf, 10);
|
||||
m_ID3v2Length = GetID3HeaderLength(tbuf);
|
||||
SetFilePointer(m_hFile, m_ID3v2Length, NULL, FILE_BEGIN);
|
||||
this->dataStream->SetPosition(m_ID3v2Length);
|
||||
|
||||
if(m_Splitter.Process(m_hFile, fr))
|
||||
{
|
||||
if(splitFrame(this->dataStream, fr)) {
|
||||
unsigned char * pHeader = fr.m_Data;
|
||||
if(!GetXingHeader(pHeader))
|
||||
{
|
||||
// analyse file here
|
||||
SetFilePointer(m_hFile, m_ID3v2Length, NULL, FILE_BEGIN);
|
||||
// just guesstimate the number of frames!
|
||||
this->dataStream->SetPosition(m_ID3v2Length);
|
||||
|
||||
// just guesstimate the number of frames!
|
||||
/* DANGEROUS -- ASSUMES FINITE LENGTH*/
|
||||
m_StreamDataLength = this->dataStream->Filesize() - m_ID3v2Length;
|
||||
|
||||
m_StreamDataLength = GetFileSize(m_hFile, NULL) - m_ID3v2Length;
|
||||
// TODO: check for ID3 TAG at the end of the file and subtract
|
||||
// also remove the size of this current header
|
||||
m_StreamDataLength -= fr.m_Header.GetTotalFrameSize();
|
||||
|
||||
m_NumFrames = m_StreamDataLength / fr.m_Header.GetTotalFrameSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_bXingValid == false)
|
||||
LogConsoleMessage(TEXT("MP3 Decoder"), TEXT("Mp3 has Xing header but it is invalid."));
|
||||
else {
|
||||
if (m_bXingValid == false) {
|
||||
std::cout << "Mp3Decoder.cpp: Mp3 has Xing header but it is invalid.";
|
||||
}
|
||||
}
|
||||
|
||||
double bs[3] = { 384.0, 1152.0, 1152.0 };
|
||||
@ -123,8 +178,9 @@ bool MP3Decoder::GetStreamData(void)
|
||||
|
||||
m_StreamLengthMS = TimePerFrame * m_NumFrames;
|
||||
|
||||
if(fr.m_Header.GetMpegVersion() != MPEG1)
|
||||
if (fr.m_Header.GetMpegVersion() != MPEG1) {
|
||||
m_StreamLengthMS /= 2;
|
||||
}
|
||||
|
||||
m_SampleRate = fr.m_Header.GetSampleFrequency();
|
||||
m_NumChannels = fr.m_Header.GetChannels();
|
||||
@ -137,78 +193,29 @@ bool MP3Decoder::GetStreamData(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MP3Decoder::Open(const utfchar* sourcePath)
|
||||
{
|
||||
m_LastLayer = -1;
|
||||
|
||||
m_hFile = CreateFile( sourcePath,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_SEQUENTIAL_SCAN,
|
||||
NULL);
|
||||
|
||||
if(m_hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
m_hFile = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
this->sourcePath = sourcePath;
|
||||
|
||||
bool MP3Decoder::Open(musik::core::io::IDataStream *dataStream) {
|
||||
this->dataStream = dataStream;
|
||||
this->m_LastLayer = -1;
|
||||
return GetStreamData();
|
||||
}
|
||||
|
||||
bool MP3Decoder::Close(void)
|
||||
{
|
||||
if(m_pDecoder)
|
||||
{
|
||||
delete m_pDecoder;
|
||||
m_pDecoder = NULL;
|
||||
}
|
||||
|
||||
if(m_hFile)
|
||||
{
|
||||
CloseHandle(m_hFile);
|
||||
m_hFile = NULL;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MP3Decoder::Destroy(void)
|
||||
{
|
||||
void MP3Decoder::Destroy(void) {
|
||||
delete this;
|
||||
}
|
||||
|
||||
bool MP3Decoder::GetFormat(unsigned long * SampleRate, unsigned long * Channels)
|
||||
{
|
||||
*SampleRate = m_SampleRate;
|
||||
*Channels = m_NumChannels;
|
||||
#define MP3_BUFFER_FLOAT_ALLOWANCE 2304 /* why? */
|
||||
|
||||
return true;
|
||||
}
|
||||
bool MP3Decoder::GetBuffer(IBuffer *buffer) {
|
||||
buffer->SetChannels(this->m_NumChannels);
|
||||
buffer->SetSamples(MP3_BUFFER_FLOAT_ALLOWANCE / buffer->Channels());
|
||||
buffer->SetSampleRate(this->m_SampleRate);
|
||||
|
||||
bool MP3Decoder::SetState(unsigned long State)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MP3Decoder::GetBuffer(float ** ppBuffer, unsigned long * NumSamples)
|
||||
{
|
||||
static float SampleBuffer[2304];
|
||||
|
||||
if(m_Splitter.Process(m_hFile, m_Frame))
|
||||
{
|
||||
if((m_Frame.m_Header.GetLayer() != m_LastLayer) || (m_pDecoder == NULL))
|
||||
{
|
||||
switch(m_Frame.m_Header.GetLayer())
|
||||
{
|
||||
case LAYER3:
|
||||
{
|
||||
if(m_pDecoder)
|
||||
{
|
||||
if (splitFrame(this->dataStream, m_Frame)) {
|
||||
/* bail if the mpeg layer is incorrect*/
|
||||
if ((m_Frame.m_Header.GetLayer() != m_LastLayer) || (m_pDecoder == NULL)) {
|
||||
switch (m_Frame.m_Header.GetLayer()) {
|
||||
case LAYER3: {
|
||||
if (m_pDecoder) {
|
||||
delete m_pDecoder;
|
||||
m_pDecoder = NULL;
|
||||
}
|
||||
@ -217,73 +224,61 @@ bool MP3Decoder::GetBuffer(float ** ppBuffer, unsigned long * NumSamples)
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LogConsoleMessage(TEXT("MP3 Decoder"), TEXT("Unsupported Layer (Only Layer 3 supported)."));
|
||||
default: {
|
||||
LogConsoleMessage(
|
||||
L"MP3 Decoder",
|
||||
L"Unsupported Layer (Only Layer 3 supported).");
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!m_pDecoder->ProcessFrame(&m_Frame, SampleBuffer, NumSamples))
|
||||
{
|
||||
*ppBuffer = NULL;
|
||||
*NumSamples = 0;
|
||||
|
||||
unsigned long bufferCount = 0;
|
||||
if (!m_pDecoder->ProcessFrame(&m_Frame, buffer->BufferPointer(), &bufferCount)) {
|
||||
m_Frame.m_Header.Reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
*ppBuffer = SampleBuffer;
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
buffer->SetSamples(bufferCount / buffer->Channels());
|
||||
}
|
||||
|
||||
bool MP3Decoder::GetLength(unsigned long * MS)
|
||||
{
|
||||
*MS = m_StreamLengthMS;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MP3Decoder::SetPosition(unsigned long * MS)
|
||||
{
|
||||
unsigned long newMS = *MS;
|
||||
float percent = 100.00f * ((float)newMS / (float)m_StreamLengthMS);
|
||||
double MP3Decoder::SetPosition(double seconds, double totalLength) {
|
||||
float milliseconds = (float) seconds * 1000.0f;
|
||||
float percent = 100.00f * ((float) milliseconds / (float) m_StreamLengthMS);
|
||||
unsigned long offset;
|
||||
|
||||
if(m_bXingValid)
|
||||
if (m_bXingValid)
|
||||
{
|
||||
/* interpolate in TOC to get file seek point in bytes */
|
||||
int a;
|
||||
int a = min(percent, 99);
|
||||
float fa, fb, fx;
|
||||
|
||||
a = min(percent, 99);
|
||||
|
||||
fa = m_TOC[a];
|
||||
|
||||
if (a < 99)
|
||||
if (a < 99) {
|
||||
fb = m_TOC[a + 1];
|
||||
else
|
||||
}
|
||||
else {
|
||||
fb = 256;
|
||||
}
|
||||
|
||||
fx = fa + (fb - fa) * (percent - a);
|
||||
offset = (1.0f / 256.0f) * fx * m_StreamDataLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = (float)m_StreamDataLength * (float)(percent/ 100.0f) ;
|
||||
else {
|
||||
offset = (float) m_StreamDataLength * (float)(percent/ 100.0f) ;
|
||||
}
|
||||
|
||||
SetFilePointer(m_hFile, offset + m_ID3v2Length, NULL, FILE_BEGIN);
|
||||
this->dataStream->SetPosition(offset + m_ID3v2Length);
|
||||
bool result = splitFrame(this->dataStream, m_Frame);
|
||||
|
||||
m_Splitter.Process(m_hFile, m_Frame);
|
||||
if(m_pDecoder)
|
||||
{
|
||||
if (m_pDecoder) {
|
||||
delete m_pDecoder;
|
||||
m_pDecoder = NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
return result ? seconds : -1;
|
||||
}
|
||||
|
@ -1,57 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <core/audio/IAudioSource.h>
|
||||
#include <core/sdk/IDecoder.h>
|
||||
|
||||
#include "FrameSplitter.h"
|
||||
#include "Layer3Decoder.h"
|
||||
|
||||
using namespace musik::core::audio;
|
||||
|
||||
class MP3Decoder : public IAudioSource
|
||||
class MP3Decoder : public IDecoder
|
||||
{
|
||||
public:
|
||||
|
||||
MP3Decoder();
|
||||
~MP3Decoder();
|
||||
|
||||
bool Open(musik::core::io::IDataStream *dataStream);
|
||||
double SetPosition(double seconds, double totalLength);
|
||||
bool GetBuffer(IBuffer *buffer);
|
||||
void Destroy();
|
||||
|
||||
protected:
|
||||
CFrameSplitter m_Splitter;
|
||||
IMPEGDecoder *m_pDecoder;
|
||||
Frame m_Frame;
|
||||
IMPEGDecoder * m_pDecoder;
|
||||
|
||||
HANDLE m_hFile;
|
||||
|
||||
unsigned long m_LastLayer;
|
||||
|
||||
unsigned long m_SampleRate;
|
||||
unsigned long m_NumChannels;
|
||||
|
||||
unsigned long m_ID3v2Length;
|
||||
unsigned long m_StreamLengthMS;
|
||||
unsigned long m_NumFrames;
|
||||
unsigned long m_StreamDataLength;
|
||||
unsigned long m_VbrScale;
|
||||
unsigned char m_TOC[100];
|
||||
|
||||
bool m_bXingValid;
|
||||
|
||||
unsigned long GetID3HeaderLength(unsigned char * buffer);
|
||||
bool GetXingHeader(unsigned char * XingBuffer);
|
||||
bool GetStreamData(void);
|
||||
|
||||
public:
|
||||
|
||||
MP3Decoder(void);
|
||||
~MP3Decoder(void);
|
||||
|
||||
bool Open(const utfchar* sourcePath);
|
||||
bool Close(void);
|
||||
void Destroy(void);
|
||||
bool GetLength(unsigned long * MS);
|
||||
bool SetPosition(unsigned long * MS);
|
||||
bool SetState(unsigned long State);
|
||||
bool GetFormat(unsigned long * SampleRate, unsigned long * Channels);
|
||||
bool GetBuffer(float ** ppBuffer, unsigned long * NumSamples);
|
||||
|
||||
const utfchar* GetSource() const { return sourcePath.c_str(); };
|
||||
bool GetStreamData();
|
||||
|
||||
private:
|
||||
utfstring sourcePath;
|
||||
musik::core::io::IDataStream *dataStream;
|
||||
|
||||
// Stubs
|
||||
void LogConsoleMessage(LPTSTR szModuleName, LPTSTR szMessage) {}; // TODO: replace with sigslot
|
||||
|
@ -36,42 +36,36 @@
|
||||
#include "boost/algorithm/string.hpp"
|
||||
#include "boost/filesystem.hpp"
|
||||
|
||||
#include "MP3SourceSupplier.h"
|
||||
|
||||
#include "Mp3DecoderFactory.h"
|
||||
#include "MP3Decoder.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
MP3SourceSupplier::MP3SourceSupplier()
|
||||
{
|
||||
Mp3DecoderFactory::Mp3DecoderFactory() {
|
||||
}
|
||||
|
||||
MP3SourceSupplier::~MP3SourceSupplier()
|
||||
{
|
||||
Mp3DecoderFactory::~Mp3DecoderFactory() {
|
||||
}
|
||||
|
||||
void MP3SourceSupplier::Destroy()
|
||||
{
|
||||
void Mp3DecoderFactory::Destroy() {
|
||||
delete this;
|
||||
}
|
||||
|
||||
IAudioSource* MP3SourceSupplier::CreateAudioSource()
|
||||
{
|
||||
IDecoder* Mp3DecoderFactory::CreateDecoder() {
|
||||
return new MP3Decoder();
|
||||
}
|
||||
|
||||
bool MP3SourceSupplier::CanHandle(const utfchar* source) const
|
||||
bool Mp3DecoderFactory::CanHandle(const char* source) const
|
||||
{
|
||||
using namespace boost::filesystem;
|
||||
using namespace boost::algorithm;
|
||||
|
||||
wpath sourcepath(source);
|
||||
|
||||
if (!is_regular(sourcepath))
|
||||
return false;
|
||||
|
||||
if (to_lower_copy(extension(sourcepath)) != TEXT(".mp3"))
|
||||
return false;
|
||||
std::string str(source);
|
||||
|
||||
if (str.find("mp3") != std::string::npos ||
|
||||
str.find("audio/mpeg3") != std::string::npos ||
|
||||
str.find("audio/x-mpeg-3") != std::string::npos ||
|
||||
str.find("audio/mp3") != std::string::npos)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
@ -33,16 +33,17 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <core\audio\IAudioSource.h>
|
||||
#include <core\sdk\IDecoderFactory.h>
|
||||
|
||||
using namespace musik::core::audio;
|
||||
|
||||
class MP3SourceSupplier : public IAudioSourceSupplier
|
||||
class Mp3DecoderFactory : public IDecoderFactory
|
||||
{
|
||||
public: MP3SourceSupplier();
|
||||
public: ~MP3SourceSupplier();
|
||||
public:
|
||||
Mp3DecoderFactory();
|
||||
~Mp3DecoderFactory();
|
||||
|
||||
public: IAudioSource* CreateAudioSource();
|
||||
public: void Destroy();
|
||||
public: bool CanHandle(const utfchar* source) const;
|
||||
IDecoder* CreateDecoder();
|
||||
void Destroy();
|
||||
bool CanHandle(const char* type) const;
|
||||
};
|
@ -53,7 +53,7 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>.;../..;../../3rdparty/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>.;../..;../../3rdparty/include;../../../../boost_1_60_0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
@ -65,7 +65,7 @@
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>../../3rdparty/lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>../../3rdparty/lib;../../../../boost_1_60_0/lib32-msvc-14.0;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -94,7 +94,7 @@
|
||||
<ClCompile Include="SideInfo.cpp" />
|
||||
<ClCompile Include="MP3Decoder.cpp" />
|
||||
<ClCompile Include="mp3decoder_plugin.cpp" />
|
||||
<ClCompile Include="MP3SourceSupplier.cpp" />
|
||||
<ClCompile Include="Mp3DecoderFactory.cpp" />
|
||||
<ClCompile Include="stdafx.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -110,7 +110,7 @@
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="SideInfo.h" />
|
||||
<ClInclude Include="MP3Decoder.h" />
|
||||
<ClInclude Include="MP3SourceSupplier.h" />
|
||||
<ClInclude Include="Mp3DecoderFactory.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
@ -35,31 +35,26 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <core/sdk/IPlugin.h>
|
||||
#include <core/sdk/IDecoder.h>
|
||||
#include "Mp3DecoderFactory.h"
|
||||
|
||||
#include "core/IPlugin.h"
|
||||
|
||||
#include "MP3SourceSupplier.h"
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
||||
{
|
||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
|
||||
return true;
|
||||
}
|
||||
|
||||
class MP3DecoderPlugin : public musik::core::IPlugin
|
||||
{
|
||||
void Destroy() { delete this; };
|
||||
|
||||
const utfchar* Name() { return TEXT("MP3 decoder"); };
|
||||
const utfchar* Version() { return TEXT("1"); };
|
||||
const utfchar* Author() { return TEXT("Björn Olievier"); };
|
||||
void Destroy() { delete this; }
|
||||
const char* Name() { return "MP3 decoder"; };
|
||||
const char* Version() { return "1"; };
|
||||
const char* Author() { return "Björn Olievier"; };
|
||||
};
|
||||
|
||||
extern "C" __declspec(dllexport) musik::core::IPlugin* GetPlugin()
|
||||
{
|
||||
extern "C" __declspec(dllexport) musik::core::IPlugin* GetPlugin() {
|
||||
return new MP3DecoderPlugin();
|
||||
}
|
||||
|
||||
extern "C" __declspec(dllexport) IAudioSourceSupplier* CreateAudioSourceSupplier()
|
||||
{
|
||||
return new MP3SourceSupplier();
|
||||
extern "C" __declspec(dllexport) IDecoderFactory* GetDecoderFactory() {
|
||||
return new Mp3DecoderFactory();
|
||||
}
|
||||
|
@ -51,22 +51,23 @@ IDecoder* OggDecoderFactory::CreateDecoder() {
|
||||
}
|
||||
|
||||
bool OggDecoderFactory::CanHandle(const char* type) const {
|
||||
if (type) {
|
||||
std::string typeString(type);
|
||||
|
||||
if (typeString.find("ogg") != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeString.find("oga") != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeString.find("audio/ogg") != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeString.find("audio/vorbis") != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -81,6 +81,8 @@ void WaveOut::SetVolume(double volume) {
|
||||
void WaveOut::Stop() {
|
||||
boost::recursive_mutex::scoped_lock lock(this->outputDeviceMutex);
|
||||
|
||||
/* reset waveout first. if we don't do this, it seems like it'll still
|
||||
try to send events to the thread, and fail with a runtime exception. */
|
||||
if (this->waveHandle != NULL) {
|
||||
waveOutReset(this->waveHandle);
|
||||
}
|
||||
@ -88,7 +90,7 @@ void WaveOut::Stop() {
|
||||
/* stop the thread so nothing else is processed */
|
||||
this->StopWaveOutThread();
|
||||
|
||||
/* reset will free the buffers, close deallocs */
|
||||
/* dealloc the handle, we'll create a new one later if we need to... */
|
||||
if (this->waveHandle != NULL) {
|
||||
waveOutClose(this->waveHandle);
|
||||
this->waveHandle = NULL;
|
||||
|
@ -148,7 +148,7 @@ void Buffer::CopyFormat(BufferPtr fromBuffer) {
|
||||
void Buffer::ResizeBuffer() {
|
||||
long requiredBufferSize = this->sampleSize * this->channels;
|
||||
if (requiredBufferSize > this->internalBufferSize) {
|
||||
if(this->buffer) {
|
||||
if (this->buffer) {
|
||||
delete this->buffer;
|
||||
this->buffer = NULL;
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ namespace musik { namespace core { namespace io {
|
||||
///\returns
|
||||
///how much has acctually been read
|
||||
//////////////////////////////////////////
|
||||
virtual PositionType Read(void* buffer, PositionType readBytes) = 0;
|
||||
virtual PositionType Read(void *buffer, PositionType readBytes) = 0;
|
||||
|
||||
//////////////////////////////////////////
|
||||
///\brief
|
||||
|
@ -61,7 +61,7 @@ class IDecoder{
|
||||
///\returns
|
||||
///The actual position set
|
||||
//////////////////////////////////////////
|
||||
virtual double SetPosition(double seconds,double totalLength) = 0;
|
||||
virtual double SetPosition(double seconds, double totalLength) = 0;
|
||||
|
||||
//////////////////////////////////////////
|
||||
///\brief
|
||||
@ -70,7 +70,7 @@ class IDecoder{
|
||||
///\returns
|
||||
///false is there is nothing left
|
||||
//////////////////////////////////////////
|
||||
virtual bool GetBuffer(IBuffer *buffer) = 0; // return false to signal that we are done decoding.
|
||||
virtual bool GetBuffer(IBuffer *buffer) = 0;
|
||||
|
||||
//////////////////////////////////////////
|
||||
///\brief
|
||||
|
@ -65,7 +65,6 @@ class IDecoderFactory{
|
||||
///The "type" can either be a file extension or a mimetype
|
||||
//////////////////////////////////////////
|
||||
virtual bool CanHandle(const char* type) const = 0;
|
||||
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -85,6 +85,8 @@ void ConsoleUI::Run()
|
||||
{
|
||||
std::string command;
|
||||
|
||||
transport.SetVolume(0.1);
|
||||
|
||||
while (!this->shouldQuit)
|
||||
{
|
||||
this->PrintCommands();
|
||||
|
Loading…
x
Reference in New Issue
Block a user