//----------------------------------------------------------------------------- // Danny Dulai July 3, 2005 // // Released in the public domain. You can do as you wish with this code. //----------------------------------------------------------------------------- #include #include "fmod.h" #include "fmod_errors.h" #include "All.h" #include "MACLib.h" #include "io.h" FMOD_RESULT F_CALLBACK macopen(FMOD_CODEC *codec, FMOD_MODE usermode, FMOD_CREATESOUNDEXINFO *userexinfo); FMOD_RESULT F_CALLBACK macclose(FMOD_CODEC *codec); FMOD_RESULT F_CALLBACK macread(FMOD_CODEC *codec, void *buffer, unsigned int size, unsigned int *read); FMOD_RESULT F_CALLBACK macsetposition(FMOD_CODEC *codec, int subsound, unsigned int position, FMOD_TIMEUNIT postype); FMOD_CODEC_DESCRIPTION rawcodec = { "Monkey's Audio player plugin", // Name. 0x00010000, // Version 0xAAAABBBB A = major, B = minor. 0, // defaultasstream FMOD_TIMEUNIT_PCM, // The time format we would like to accept into setposition/getposition. &macopen, // Open callback. &macclose, // Close callback. ¯ead, // Read callback. 0, // Getlength callback. (If not specified FMOD return the length in FMOD_TIMEUNIT_PCM, FMOD_TIMEUNIT_MS or FMOD_TIMEUNIT_PCMBYTES units based on the lengthpcm member of the FMOD_CODEC structure). &macsetposition, // Setposition callback. 0, // Getposition callback. (only used for timeunit types that are not FMOD_TIMEUNIT_PCM, FMOD_TIMEUNIT_MS and FMOD_TIMEUNIT_PCMBYTES). 0, // Sound create callback (don't need it) }; class macio : public CIO { FMOD_CODEC *_codec; int _pos; public: macio(FMOD_CODEC *codec) { _codec = codec; _pos = 0; pAPEDecompress = NULL; memset(&rawwaveformat, 0, sizeof(rawwaveformat)); } ~macio() { delete pAPEDecompress; } IAPEDecompress *pAPEDecompress; FMOD_CODEC_WAVEFORMAT rawwaveformat; virtual int Read(void * pBuffer, unsigned int nBytesToRead, unsigned int * pBytesRead) { _codec->fileread(_codec->filehandle, pBuffer, nBytesToRead, pBytesRead, NULL); _pos += *pBytesRead; // printf("CIO Read %d/%d\n", nBytesToRead, *pBytesRead); fflush(stdout); return 0; } virtual int Seek(int nDistance, unsigned int nMoveMode) { // printf("CIO Seek %d/%d\n", nDistance, nMoveMode); fflush(stdout); if (nMoveMode == 0) { _pos = nDistance; } else if (nMoveMode == 1) { _pos += nDistance; } else if (nMoveMode == 2) { _pos = _codec->filesize + nDistance; } _codec->fileseek(_codec->filehandle, _pos, NULL); return 0; } virtual int GetSize() { // printf("CIO GetSize %d\n", _codec->filesize); fflush(stdout); return _codec->filesize; } virtual int GetPosition() { // printf("CIO GetPosition %d\n", _pos); fflush(stdout); return _pos; } virtual int Open(const wchar_t * pName) { // printf("CIO Open\n"); fflush(stdout); return 0; } virtual int Open(const char * pName) { // printf("CIO Open\n"); fflush(stdout); return 0; } virtual int Close() { // printf("CIO Close\n"); fflush(stdout); return 0; } virtual int Create(const char * pName) { // printf("CIO Create\n"); fflush(stdout); return 0; } virtual int Create(const wchar_t * pName) { // printf("CIO Create\n"); fflush(stdout); return 0; } virtual int Delete() { // printf("CIO Delete\n"); fflush(stdout); return 0; } virtual int SetEOF() { // printf("CIO SetEOF\n"); fflush(stdout); return 0; } virtual int GetName(char * pBuffer) { // printf("CIO GetName\n"); fflush(stdout); return 0; } virtual int GetName(wchar_t * pBuffer) { // printf("CIO GetName\n"); fflush(stdout); return 0; } virtual int Write(const void * pBuffer, unsigned int nBytesToWrite, unsigned int * pBytesWritten) { // printf("CIO Write\n"); fflush(stdout); return 0; } }; #ifdef __cplusplus extern "C" { #endif F_DECLSPEC F_DLLEXPORT FMOD_CODEC_DESCRIPTION * F_API FMODGetCodecDescription() { return &rawcodec; } #ifdef __cplusplus } #endif FMOD_RESULT F_CALLBACK macopen(FMOD_CODEC *codec, FMOD_MODE usermode, FMOD_CREATESOUNDEXINFO *userexinfo) { // printf("mac open\n"); fflush(stdout); int nRetVal=0; macio *m = new macio(codec); m->pAPEDecompress = CreateIAPEDecompressEx(m, &nRetVal); if (m->pAPEDecompress == NULL) { // printf("mac bad\n"); fflush(stdout); return FMOD_ERR_FILE_BAD; } int lenms = m->pAPEDecompress->GetInfo(APE_DECOMPRESS_LENGTH_MS); m->rawwaveformat.name[0] = 0; m->rawwaveformat.channels = m->pAPEDecompress->GetInfo(APE_INFO_CHANNELS); m->rawwaveformat.format = FMOD_SOUND_FORMAT_PCM16; m->rawwaveformat.frequency = m->pAPEDecompress->GetInfo(APE_INFO_SAMPLE_RATE); m->rawwaveformat.blockalign = m->pAPEDecompress->GetInfo(APE_INFO_BLOCK_ALIGN); m->rawwaveformat.lengthpcm = (int)((double)lenms / (double)1000.0 * (double)m->rawwaveformat.frequency);/* PCM samples */ // printf("channels = %d\n", m->rawwaveformat.channels); // printf("freq = %d\n", m->rawwaveformat.frequency); // printf("blockalign = %d\n", m->rawwaveformat.blockalign); // printf("lenpcm = %d\n", m->rawwaveformat.lengthpcm); codec->waveformat = &(m->rawwaveformat); codec->numsubsounds = 0; codec->userdata = m; // printf("mac open done %d\n", lenms/1000); fflush(stdout); return FMOD_OK; } FMOD_RESULT F_CALLBACK macclose(FMOD_CODEC *codec) { // printf("mac close\n"); fflush(stdout); delete (macio*)codec->userdata; // printf("mac close done\n"); fflush(stdout); return FMOD_OK; } FMOD_RESULT F_CALLBACK macread(FMOD_CODEC *codec, void *buffer, unsigned int size, unsigned int *read) { // printf("mac read %d\n", size); fflush(stdout); macio *m = (macio*)codec->userdata; m->pAPEDecompress->GetData((char *)buffer, size/codec->waveformat->blockalign, (int*)read); *read *= codec->waveformat->blockalign; // printf("mac read done %d\n", *read); fflush(stdout); return FMOD_OK; } FMOD_RESULT F_CALLBACK macsetposition(FMOD_CODEC *codec, int subsound, unsigned int position, FMOD_TIMEUNIT postype) { // printf("mac setpos %d %d %d\n", subsound, position, postype); fflush(stdout); macio *m = (macio*)codec->userdata; if (postype == FMOD_TIMEUNIT_PCM) { // printf("mac setpos seeking\n"); fflush(stdout); m->pAPEDecompress->Seek(position); } // printf("mac setpos done\n"); fflush(stdout); return FMOD_OK; }