Add embedded sound support

This commit is contained in:
BeaR 2014-10-11 14:50:16 +02:00
parent 96a6d6d85b
commit b5d0034674
8 changed files with 158 additions and 83 deletions

View file

@ -67,6 +67,10 @@ static int m_NextVoice = 0;
static int *m_pMixBuffer = 0; // buffer only used by the thread callback function
static unsigned m_MaxFrames = 0;
static const void *ms_pWVBuffer = 0x0;
static int ms_WVBufferPosition = 0;
static int ms_WVBufferSize = 0;
// TODO: there should be a faster way todo this
static short Int2Short(int i)
{
@ -330,23 +334,85 @@ void CSound::RateConvert(int SampleID)
int CSound::ReadData(void *pBuffer, int Size)
{
return io_read(ms_File, pBuffer, Size);
int ChunkSize = min(Size, ms_WVBufferSize - ms_WVBufferPosition);
mem_copy(pBuffer, (const char *)ms_pWVBuffer + ms_WVBufferPosition, ChunkSize);
ms_WVBufferPosition += ChunkSize;
return ChunkSize;
}
int CSound::DecodeWV(int SampleID, const void *pData, unsigned DataSize)
{
if(SampleID == -1 || SampleID >= NUM_SAMPLES)
return -1;
CSample *pSample = &m_aSamples[SampleID];
char aError[100];
WavpackContext *pContext;
ms_pWVBuffer = pData;
ms_WVBufferSize = DataSize;
ms_WVBufferPosition = 0;
pContext = WavpackOpenFileInput(ReadData, aError);
if (pContext)
{
int NumSamples = WavpackGetNumSamples(pContext);
int BitsPerSample = WavpackGetBitsPerSample(pContext);
unsigned int SampleRate = WavpackGetSampleRate(pContext);
int NumChannels = WavpackGetNumChannels(pContext);
int *pSrc;
short *pDst;
int i;
pSample->m_Channels = NumChannels;
pSample->m_Rate = SampleRate;
if(pSample->m_Channels > 2)
{
dbg_msg("sound/wv", "file is not mono or stereo.");
return -1;
}
if(BitsPerSample != 16)
{
dbg_msg("sound/wv", "bps is %d, not 16", BitsPerSample);
return -1;
}
int *pBuffer = (int *)mem_alloc(4*NumSamples*NumChannels, 1);
WavpackUnpackSamples(pContext, pBuffer, NumSamples); // TODO: check return value
pSrc = pBuffer;
pSample->m_pData = (short *)mem_alloc(2*NumSamples*NumChannels, 1);
pDst = pSample->m_pData;
for (i = 0; i < NumSamples*NumChannels; i++)
*pDst++ = (short)*pSrc++;
mem_free(pBuffer);
pSample->m_NumFrames = NumSamples;
pSample->m_LoopStart = -1;
pSample->m_LoopEnd = -1;
pSample->m_PausedAt = 0;
}
else
{
dbg_msg("sound/wv", "failed to decode sample (%s)", aError);
}
return SampleID;
}
int CSound::LoadWV(const char *pFilename)
{
CSample *pSample;
int SampleID = -1;
char aError[100];
WavpackContext *pContext;
// don't waste memory on sound when we are stress testing
if(g_Config.m_DbgStress)
return -1;
// no need to load sound when we are running with no sound
if(!m_SoundEnabled)
return 1;
return -1;
if(!m_pStorage)
return -1;
@ -358,67 +424,19 @@ int CSound::LoadWV(const char *pFilename)
return -1;
}
SampleID = AllocID();
int SampleID = AllocID();
if(SampleID < 0)
return -1;
pSample = &m_aSamples[SampleID];
// read the whole file into memory
int DataSize = io_length(ms_File);
char *pData = new char[DataSize];
io_read(ms_File, pData, DataSize);
io_close(ms_File);
pContext = WavpackOpenFileInput(ReadData, aError);
if (pContext)
{
int m_aSamples = WavpackGetNumSamples(pContext);
int BitsPerSample = WavpackGetBitsPerSample(pContext);
unsigned int SampleRate = WavpackGetSampleRate(pContext);
int m_aChannels = WavpackGetNumChannels(pContext);
int *pData;
int *pSrc;
short *pDst;
int i;
pSample->m_Channels = m_aChannels;
pSample->m_Rate = SampleRate;
if(pSample->m_Channels > 2)
{
dbg_msg("sound/wv", "file is not mono or stereo. filename='%s'", pFilename);
return -1;
}
/*
if(snd->rate != 44100)
{
dbg_msg("sound/wv", "file is %d Hz, not 44100 Hz. filename='%s'", snd->rate, filename);
return -1;
}*/
if(BitsPerSample != 16)
{
dbg_msg("sound/wv", "bps is %d, not 16, filname='%s'", BitsPerSample, pFilename);
return -1;
}
pData = (int *)mem_alloc(4*m_aSamples*m_aChannels, 1);
WavpackUnpackSamples(pContext, pData, m_aSamples); // TODO: check return value
pSrc = pData;
pSample->m_pData = (short *)mem_alloc(2*m_aSamples*m_aChannels, 1);
pDst = pSample->m_pData;
for (i = 0; i < m_aSamples*m_aChannels; i++)
*pDst++ = (short)*pSrc++;
mem_free(pData);
pSample->m_NumFrames = m_aSamples;
pSample->m_LoopStart = -1;
pSample->m_LoopEnd = -1;
pSample->m_PausedAt = 0;
}
else
{
dbg_msg("sound/wv", "failed to open %s: %s", pFilename, aError);
}
SampleID = DecodeWV(SampleID, pData, DataSize);
delete[] pData;
io_close(ms_File);
ms_File = NULL;
@ -429,6 +447,29 @@ int CSound::LoadWV(const char *pFilename)
return SampleID;
}
int CSound::LoadWVFromMem(const void *pData, unsigned DataSize)
{
// don't waste memory on sound when we are stress testing
if(g_Config.m_DbgStress)
return -1;
// no need to load sound when we are running with no sound
if(!m_SoundEnabled)
return -1;
if(!pData)
return -1;
int SampleID = AllocID();
if(SampleID < 0)
return -1;
SampleID = DecodeWV(SampleID, pData, DataSize);
RateConvert(SampleID);
return SampleID;
}
void CSound::UnloadSample(int SampleID)
{
if(SampleID == -1 || SampleID >= NUM_SAMPLES)

View file

@ -24,10 +24,12 @@ public:
// TODO: Refactor: clean this mess up
static IOHANDLE ms_File;
static int ReadData(void *pBuffer, int Size);
static int DecodeWV(int SampleID, const void *pData, unsigned DataSize);
virtual bool IsSoundEnabled() { return m_SoundEnabled != 0; }
virtual int LoadWV(const char *pFilename);
virtual int LoadWVFromMem(const void *pData, unsigned DataSize);
virtual void UnloadSample(int SampleID);
virtual float GetSampleDuration(int SampleID); // in s

View file

@ -19,6 +19,7 @@ public:
virtual bool IsSoundEnabled() = 0;
virtual int LoadWV(const char *pFilename) = 0;
virtual int LoadWVFromMem(const void *pData, unsigned DataSize) = 0;
virtual void UnloadSample(int SampleID) = 0;
virtual float GetSampleDuration(int SampleID) = 0; // in s

View file

@ -42,11 +42,9 @@ void CMapSounds::OnMapLoad()
}
else
{
/*
void *pData = pMap->GetData(pImg->m_ImageData);
m_aTextures[i] = Graphics()->LoadTextureRaw(pImg->m_Width, pImg->m_Height, CImageInfo::FORMAT_RGBA, pData, CImageInfo::FORMAT_RGBA, 0);
pMap->UnloadData(pImg->m_ImageData);
*/
void *pData = pMap->GetData(pSound->m_SoundData);
m_aSounds[i] = Sound()->LoadWVFromMem(pData, pSound->m_SoundDataSize);
pMap->UnloadData(pSound->m_SoundData);
}
}

View file

@ -59,6 +59,11 @@ CEditorImage::~CEditorImage()
CEditorSound::~CEditorSound()
{
m_pEditor->Sound()->UnloadSample(m_SoundID);
if(m_pData)
{
delete[] m_pData;
m_pData = 0x0;
}
}
CLayerGroup::CLayerGroup()
@ -2873,8 +2878,19 @@ void CEditor::AddSound(const char *pFileName, int StorageType, void *pUser)
return;
}
// load external
IOHANDLE SoundFile = pEditor->Storage()->OpenFile(pFileName, IOFLAG_READ, IStorage::TYPE_ALL);
if(!SoundFile)
return;
// read the whole file into memory
unsigned DataSize = io_length(SoundFile);
void *pData = new char[DataSize];
io_read(SoundFile, pData, DataSize);
io_close(SoundFile);
// load sound
int SoundId = pEditor->Sound()->LoadWV(pFileName);
int SoundId = pEditor->Sound()->LoadWVFromMem(pData, DataSize);
if(SoundId == -1)
return;
@ -2882,6 +2898,8 @@ void CEditor::AddSound(const char *pFileName, int StorageType, void *pUser)
CEditorSound *pSound = new CEditorSound(pEditor);
pSound->m_SoundID = SoundId;
pSound->m_External = 1; // external by default
pSound->m_DataSize = DataSize;
pSound->m_pData = pData;
str_copy(pSound->m_aName, aBuf, sizeof(pSound->m_aName));
pEditor->m_Map.m_lSounds.add(pSound);

View file

@ -314,6 +314,9 @@ public:
m_aName[0] = 0;
m_External = 0;
m_SoundID = 0;
m_pData = 0x0;
m_DataSize = 0;
}
~CEditorSound();
@ -321,6 +324,9 @@ public:
int m_SoundID;
int m_External;
char m_aName[128];
void *m_pData;
unsigned m_DataSize;
};
class CEditorMap

View file

@ -284,11 +284,14 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName)
Item.m_External = pSound->m_External;
Item.m_SoundName = df.AddData(str_length(pSound->m_aName)+1, pSound->m_aName);
if(pSound->m_External)
{
Item.m_SoundDataSize = 0;
Item.m_SoundData = -1;
}
else
{
// TODO
// Item.m_ImageData = df.AddData(Item.m_Width*Item.m_Height*4, pImg->m_pData);
Item.m_SoundData = df.AddData(pSound->m_DataSize, pSound->m_pData);
Item.m_SoundDataSize = pSound->m_DataSize;
}
df.AddItem(MAPITEMTYPE_SOUND, i, sizeof(Item), &Item);
@ -645,21 +648,26 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag
str_format(aBuf, sizeof(aBuf),"mapres/%s.wv", pName);
// load external
pSound->m_SoundID = m_pEditor->Sound()->LoadWV(aBuf);
IOHANDLE SoundFile = pStorage->OpenFile(pName, IOFLAG_READ, IStorage::TYPE_ALL);
if(SoundFile)
{
// read the whole file into memory
pSound->m_DataSize = io_length(SoundFile);
pSound->m_pData = new char[pSound->m_DataSize];
io_read(SoundFile, pSound->m_pData, pSound->m_DataSize);
io_close(SoundFile);
pSound->m_SoundID = m_pEditor->Sound()->LoadWVFromMem(pSound->m_pData, pSound->m_DataSize);
}
}
else
{
/*
pImg->m_Width = pItem->m_Width;
pImg->m_Height = pItem->m_Height;
pImg->m_Format = CImageInfo::FORMAT_RGBA;
pSound->m_DataSize = pItem->m_SoundDataSize;
// copy image data
void *pData = DataFile.GetData(pItem->m_ImageData);
pImg->m_pData = mem_alloc(pImg->m_Width*pImg->m_Height*4, 1);
mem_copy(pImg->m_pData, pData, pImg->m_Width*pImg->m_Height*4);
pImg->m_TexID = m_pEditor->Graphics()->LoadTextureRaw(pImg->m_Width, pImg->m_Height, pImg->m_Format, pImg->m_pData, CImageInfo::FORMAT_AUTO, 0);
*/
// copy sample data
void *pData = DataFile.GetData(pItem->m_SoundData);
pSound->m_pData = mem_alloc(pSound->m_DataSize, 1);
mem_copy(pSound->m_pData, pData, pSound->m_DataSize);
pSound->m_SoundID = m_pEditor->Sound()->LoadWVFromMem(pSound->m_pData, pSound->m_DataSize);
}
// copy image name

View file

@ -362,6 +362,7 @@ struct CMapItemSound
int m_SoundName;
int m_SoundData;
int m_SoundDataSize;
} ;