fmodex/src/fmod_codec_raw.cpp

458 lines
8.8 KiB
C++
Executable file

#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