You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
3.2 KiB
170 lines
3.2 KiB
#include "interface.h" |
|
|
|
#define MINIMP3_IMPLEMENTATION |
|
#include "minimp3_ex.h" |
|
#include "vaudio/ivaudio.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
#include <csignal> |
|
|
|
struct AudioStream_s |
|
{ |
|
IAudioStreamEvent *stream_event; |
|
int offset; |
|
unsigned int decode_size; |
|
}; |
|
|
|
size_t mp3dec_read_callback(void *buf, size_t size, void *user_data) |
|
{ |
|
AudioStream_s *stream = static_cast<AudioStream_s*>( (void*)user_data); |
|
int ret_size = stream->stream_event->StreamRequestData( buf, size, stream->offset ); |
|
printf("mp3dec_read_callback size: %d, ret_size: %d\n", (int)size, ret_size); |
|
stream->offset += ret_size; |
|
|
|
return ret_size; |
|
} |
|
|
|
|
|
int mp3dec_seek_callback(uint64_t position, void *user_data) |
|
{ |
|
struct AudioStream_s *stream = static_cast<AudioStream_s*>( (void*)user_data); |
|
stream->offset = position; |
|
printf("mp3dec_seek_callback position: %d\n", (int)position); |
|
|
|
return 0; |
|
} |
|
|
|
class CMiniMP3 : public IAudioStream |
|
{ |
|
public: |
|
CMiniMP3(); |
|
bool Init( IAudioStreamEvent *pHandler ); |
|
~CMiniMP3(); |
|
|
|
// IAudioStream functions |
|
virtual int Decode( void *pBuffer, unsigned int bufferSize ); |
|
virtual int GetOutputBits(); |
|
virtual int GetOutputRate(); |
|
virtual int GetOutputChannels(); |
|
virtual unsigned int GetPosition(); |
|
virtual void SetPosition( unsigned int position ); |
|
private: |
|
|
|
short pcm[MINIMP3_MAX_SAMPLES_PER_FRAME]; |
|
mp3dec_ex_t mp3d; |
|
mp3dec_io_t mp3io; |
|
struct AudioStream_s audio_stream; |
|
}; |
|
|
|
CMiniMP3::CMiniMP3() |
|
{ |
|
} |
|
|
|
bool CMiniMP3::Init( IAudioStreamEvent *pHandler ) |
|
{ |
|
printf("CMiniMP3::Init\n"); |
|
|
|
audio_stream.stream_event = pHandler; |
|
audio_stream.offset = 0; |
|
audio_stream.decode_size = 0; |
|
|
|
mp3io.read = &mp3dec_read_callback; |
|
mp3io.read_data = &audio_stream; |
|
mp3io.seek = &mp3dec_seek_callback; |
|
mp3io.seek_data = &audio_stream; |
|
if( mp3dec_ex_open_cb(&mp3d, &mp3io, MP3D_SEEK_TO_SAMPLE) ) |
|
{ |
|
printf("mp3dec_ex_open_cb failed\n"); |
|
return false; |
|
} |
|
|
|
if ( mp3dec_ex_seek(&mp3d, 0) ) |
|
{ |
|
printf("mp3dec_ex_seek failed\n"); |
|
return false; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
|
|
CMiniMP3::~CMiniMP3() |
|
{ |
|
|
|
} |
|
|
|
|
|
// IAudioStream functions |
|
int CMiniMP3::Decode( void *pBuffer, unsigned int bufferSize ) |
|
{ |
|
size_t readed = mp3dec_ex_read(&mp3d, pBuffer, bufferSize/2); |
|
return readed*2; |
|
} |
|
|
|
|
|
int CMiniMP3::GetOutputBits() |
|
{ |
|
return 16; |
|
} |
|
|
|
|
|
int CMiniMP3::GetOutputRate() |
|
{ |
|
return mp3d.info.hz; |
|
} |
|
|
|
|
|
int CMiniMP3::GetOutputChannels() |
|
{ |
|
return mp3d.info.channels; |
|
} |
|
|
|
|
|
unsigned int CMiniMP3::GetPosition() |
|
{ |
|
return audio_stream.offset; |
|
} |
|
|
|
// NOTE: Only supports seeking forward right now |
|
void CMiniMP3::SetPosition( unsigned int position ) |
|
{ |
|
audio_stream.offset = position; |
|
mp3dec_ex_seek(&mp3d, position); |
|
} |
|
|
|
|
|
class CVAudio : public IVAudio |
|
{ |
|
public: |
|
CVAudio() |
|
{ |
|
// Assume the user will be creating multiple miles objects, so |
|
// keep miles running while this exists |
|
//IncrementRefMiles(); |
|
} |
|
|
|
~CVAudio() |
|
{ |
|
//DecrementRefMiles(); |
|
} |
|
|
|
IAudioStream *CreateMP3StreamDecoder( IAudioStreamEvent *pEventHandler ) |
|
{ |
|
CMiniMP3 *pMP3 = new CMiniMP3; |
|
if ( !pMP3->Init( pEventHandler ) ) |
|
{ |
|
delete pMP3; |
|
return NULL; |
|
} |
|
return pMP3; |
|
} |
|
|
|
void DestroyMP3StreamDecoder( IAudioStream *pDecoder ) |
|
{ |
|
delete pDecoder; |
|
} |
|
}; |
|
|
|
EXPOSE_INTERFACE( CVAudio, IVAudio, VAUDIO_INTERFACE_VERSION ); |
|
|
|
|