#include "fmod_settings.h" #ifdef FMOD_SUPPORT_RAW #include "fmod.h" #include "fmod_codec_raw.h" #include "fmod_codec_wav.h" #include "fmod_codec_wav_imaadpcm.h" #include "fmod_dsp_codec.h" #include "fmod_debug.h" #include "fmod_file.h" #include "fmod_soundi.h" #include "fmod_string.h" #ifdef PLATFORM_PS3_SPU #include "fmod_systemi_spu.h" #else #include "fmod_systemi.h" #endif #include #ifdef PLATFORM_PS3 extern unsigned int _binary_spu_fmod_codec_raw_pic_start[]; #endif namespace FMOD { FMOD_CODEC_DESCRIPTION_EX rawcodec; #ifdef PLUGIN_EXPORTS #ifdef __cplusplus extern "C" { #endif /* FMODGetCodecDescription is mandantory for every fmod plugin. This is the symbol the registerplugin function searches for. Must be declared with F_API to make it export as stdcall. */ F_DECLSPEC F_DLLEXPORT FMOD_CODEC_DESCRIPTION_EX * F_API FMODGetCodecDescriptionEx() { return CodecRaw::getDescriptionEx(); } #ifdef __cplusplus } #endif #endif /* PLUGIN_EXPORTS */ /* [ [DESCRIPTION] [PARAMETERS] [RETURN_VALUE] [REMARKS] [PLATFORMS] Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube [SEE_ALSO] ] */ FMOD_CODEC_DESCRIPTION_EX *CodecRaw::getDescriptionEx() { #ifndef PLATFORM_PS3_SPU FMOD_memset(&rawcodec, 0, sizeof(FMOD_CODEC_DESCRIPTION_EX)); rawcodec.name = "FMOD Raw Codec"; rawcodec.version = 0x00010100; rawcodec.timeunits = FMOD_TIMEUNIT_PCM | FMOD_TIMEUNIT_RAWBYTES; rawcodec.open = &CodecRaw::openCallback; rawcodec.close = &CodecRaw::closeCallback; rawcodec.read = &CodecRaw::readCallback; rawcodec.setposition = &CodecRaw::setPositionCallback; rawcodec.canpoint = &CodecRaw::canPointCallback; rawcodec.mType = FMOD_SOUND_TYPE_RAW; rawcodec.mSize = sizeof(CodecRaw); #ifdef PLATFORM_PS3 rawcodec.mModule = (FMOD_OS_LIBRARY *)_binary_spu_fmod_codec_raw_pic_start; #endif #else rawcodec.read = &CodecRaw::readCallback; rawcodec.setposition = &CodecRaw::setPositionCallback; #endif return &rawcodec; } #ifndef PLATFORM_PS3_SPU /* [ [DESCRIPTION] [PARAMETERS] [RETURN_VALUE] [REMARKS] [PLATFORMS] Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube [SEE_ALSO] ] */ FMOD_RESULT CodecRaw::openInternal(FMOD_MODE usermode, FMOD_CREATESOUNDEXINFO *userexinfo) { FMOD_RESULT result = FMOD_OK; init(FMOD_SOUND_TYPE_RAW); FLOG((FMOD_DEBUG_LEVEL_LOG, __FILE__, __LINE__, "CodecRaw::openInternal", "attempting to open as RAW..\n")); result = mFile->seek(0, SEEK_SET); if (result != FMOD_OK) { return result; } waveformat = &mWaveFormat; /* Get size of file in bytes */ result = mFile->getSize(&waveformat[0].lengthbytes); if (result != FMOD_OK) { return result; } mSrcDataOffset = 0; if (usermode & FMOD_SOFTWARE) { if (usermode & FMOD_CREATECOMPRESSEDSAMPLE) { if (1 #if defined(FMOD_SUPPORT_IMAADPCM) && userexinfo->format != FMOD_SOUND_FORMAT_IMAADPCM #endif ) { return FMOD_ERR_FORMAT; } } else if (userexinfo->format < FMOD_SOUND_FORMAT_PCM8 || userexinfo->format > FMOD_SOUND_FORMAT_PCMFLOAT) { return FMOD_ERR_FORMAT; } } waveformat[0].format = userexinfo->format; waveformat[0].channels = userexinfo->numchannels; waveformat[0].frequency = userexinfo->defaultfrequency; SoundI::getSamplesFromBytes(waveformat[0].lengthbytes, &waveformat[0].lengthpcm, userexinfo->numchannels, userexinfo->format); waveformat[0].blockalign = waveformat[0].channels * 16 / 8; /* Fill out base class members, also pointing to or allocating storage for them. */ numsubsounds = 0; #if defined(FMOD_SUPPORT_IMAADPCM) && defined(FMOD_SUPPORT_DSPCODEC) if (waveformat[0].format == FMOD_SOUND_FORMAT_IMAADPCM) { int count; if (waveformat[0].channels > 2) { return FMOD_ERR_TOOMANYCHANNELS; /* Sorry we're only allocating memory for a pool of maximum stereo voices. */ } mSamplesPerADPCMBlock = 64; mReadBufferLength = 36 * waveformat[0].channels; if (!mSystem->mDSPCodecPool_ADPCM.mNumDSPCodecs) { result = mSystem->mDSPCodecPool_ADPCM.init(FMOD_DSP_CATEGORY_DSPCODECADPCM, 64, mSystem->mAdvancedSettings.maxADPCMcodecs ? mSystem->mAdvancedSettings.maxADPCMcodecs : FMOD_ADVANCEDSETTINGS_MAXADPCMCODECS); if (result != FMOD_OK) { return result; } for (count = 0; count < mSystem->mDSPCodecPool_ADPCM.mNumDSPCodecs; count++) { DSPCodec *dspcodec = SAFE_CAST(DSPCodec, mSystem->mDSPCodecPool_ADPCM.mPool[count]); CodecWav *wav = (CodecWav *)dspcodec->mCodec; wav->mSrcFormat = &wav->mSrcFormatMemory; wav->mReadBuffer = mSystem->mDSPCodecPool_ADPCM.mReadBuffer; wav->mSrcFormat->Format.wFormatTag = WAVE_FORMAT_IMA_ADPCM; } } } #endif return result; } /* [ [DESCRIPTION] [PARAMETERS] [RETURN_VALUE] [REMARKS] [PLATFORMS] Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube [SEE_ALSO] ] */ FMOD_RESULT CodecRaw::closeInternal() { return FMOD_OK; } #endif /* [ [DESCRIPTION] [PARAMETERS] [RETURN_VALUE] [REMARKS] [PLATFORMS] Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube [SEE_ALSO] ] */ FMOD_RESULT CodecRaw::readInternal(void *buffer, unsigned int sizebytes, unsigned int *bytesread) { FMOD_RESULT result; if (waveformat[0].format == FMOD_SOUND_FORMAT_PCM16) { result = mFile->read(buffer, 2, sizebytes / 2, bytesread); *bytesread *= 2; /* convert from 16bit words back to bytes */ } else { result = mFile->read(buffer, 1, sizebytes, bytesread); } return result; } /* [ [DESCRIPTION] [PARAMETERS] [RETURN_VALUE] [REMARKS] [PLATFORMS] Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube [SEE_ALSO] ] */ FMOD_RESULT CodecRaw::setPositionInternal(int subsound, unsigned int position, FMOD_TIMEUNIT postype) { FMOD_RESULT result; unsigned int raw; if (postype == FMOD_TIMEUNIT_RAWBYTES) { raw = position; } else { raw = (unsigned int)((FMOD_UINT64)position * (FMOD_UINT64)waveformat[0].lengthbytes / (FMOD_UINT64)waveformat[0].lengthpcm); raw /= waveformat[0].blockalign; raw *= waveformat[0].blockalign; } result = mFile->seek(mSrcDataOffset + raw, SEEK_SET); if (result != FMOD_OK) { return result; } return FMOD_OK; } #ifndef PLATFORM_PS3_SPU /* [ [DESCRIPTION] [PARAMETERS] [RETURN_VALUE] [REMARKS] [PLATFORMS] [SEE_ALSO] ] */ FMOD_RESULT CodecRaw::canPointInternal() { return FMOD_OK; } /* [ [DESCRIPTION] [PARAMETERS] [RETURN_VALUE] [REMARKS] [PLATFORMS] Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube [SEE_ALSO] ] */ FMOD_RESULT F_CALLBACK CodecRaw::openCallback(FMOD_CODEC_STATE *codec, FMOD_MODE usermode, FMOD_CREATESOUNDEXINFO *userexinfo) { CodecRaw *raw = (CodecRaw *)codec; return raw->openInternal(usermode, userexinfo); } /* [ [DESCRIPTION] [PARAMETERS] [RETURN_VALUE] [REMARKS] [PLATFORMS] Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube [SEE_ALSO] ] */ FMOD_RESULT F_CALLBACK CodecRaw::closeCallback(FMOD_CODEC_STATE *codec) { CodecRaw *raw = (CodecRaw *)codec; return raw->closeInternal(); } #endif /* [ [DESCRIPTION] [PARAMETERS] [RETURN_VALUE] [REMARKS] [PLATFORMS] Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube [SEE_ALSO] ] */ FMOD_RESULT F_CALLBACK CodecRaw::readCallback(FMOD_CODEC_STATE *codec, void *buffer, unsigned int sizebytes, unsigned int *bytesread) { CodecRaw *raw = (CodecRaw *)codec; return raw->readInternal(buffer, sizebytes, bytesread); } /* [ [DESCRIPTION] [PARAMETERS] [RETURN_VALUE] [REMARKS] [PLATFORMS] Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube [SEE_ALSO] ] */ FMOD_RESULT F_CALLBACK CodecRaw::setPositionCallback(FMOD_CODEC_STATE *codec, int subsound, unsigned int position, FMOD_TIMEUNIT postype) { CodecRaw *raw = (CodecRaw *)codec; return raw->setPositionInternal(subsound, position, postype); } #ifndef PLATFORM_PS3_SPU /* [ [DESCRIPTION] [PARAMETERS] [RETURN_VALUE] [REMARKS] [PLATFORMS] Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube [SEE_ALSO] ] */ FMOD_RESULT F_CALLBACK CodecRaw::canPointCallback(FMOD_CODEC_STATE *codec) { CodecRaw *raw = (CodecRaw *)codec; return raw->canPointInternal(); } #endif } #endif