459 lines
8.8 KiB
C++
459 lines
8.8 KiB
C++
|
|
#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 <stdio.h>
|
||
|
|
|
||
|
|
#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
|
||
|
|
|