Serious-Engine/Sources/Engine/Sound/SoundData.cpp

266 lines
6.1 KiB
C++
Raw Permalink Normal View History

2016-03-12 01:20:51 +01:00
/* Copyright (c) 2002-2012 Croteam Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as published by
the Free Software Foundation
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
2016-03-11 14:57:17 +01:00
#include "Engine/StdH.h"
2016-03-11 14:57:17 +01:00
#include <Engine/Sound/SoundData.h>
#include <Engine/Base/Memory.h>
#include <Engine/Base/Stream.h>
#include <Engine/Base/ListIterator.inl>
#include <Engine/Sound/Wave.h>
#include <Engine/Sound/SoundDecoder.h>
#include <Engine/Sound/SoundLibrary.h>
#include <Engine/Sound/SoundObject.h>
#include <Engine/Templates/Stock_CSoundData.h>
/* ====================================================
*
* Sound data awareness functions
*/
/*
* Pause all playing
*/
void CSoundData::PausePlayingObjects(void)
{
// for all objects linked to data pause playing
FOREACHINLIST(CSoundObject, so_Node, sd_ClhLinkList, itCsoPause) {
// pause playing
itCsoPause->Pause();
}
}
/*
* For all objects resume play
*/
void CSoundData::ResumePlayingObjects(void)
{
// for all objects resume play
FOREACHINLIST(CSoundObject, so_Node, sd_ClhLinkList, itCsoResume) {
// call play method again
itCsoResume->Resume();
}
}
/*
* Add object in sound aware list
*/
void CSoundData::AddObjectLink(CSoundObject &CsoAdd)
{
// add object to list tail
sd_ClhLinkList.AddTail(CsoAdd.so_Node);
}
/*
* Remove a object from aware list
*/
void CSoundData::RemoveObjectLink(CSoundObject &CsoRemove)
{
// remove it from list
CsoRemove.so_Node.Remove();
}
/* ====================================================
*
* Class global methods
*/
// Constructor
CSoundData::CSoundData()
{
sd_pswBuffer = NULL;
}
// Destructor
CSoundData::~CSoundData()
{
Clear();
}
// Free Buffer (and all linked Objects)
void CSoundData::ClearBuffer(void)
{
// if buffer exist
if( sd_pswBuffer!=NULL) {
// release it
FreeMemory( sd_pswBuffer);
sd_pswBuffer = NULL;
}
}
// Get Sound Length in seconds
double CSoundData::GetSecondsLength(void)
{
// if not encoded
if (!(sd_ulFlags&SDF_ENCODED) ) {
// len is read from wave
return sd_dSecondsLength;
// if encoded
} else {
// implement this!!!!
ASSERT(FALSE);
return 0;
}
}
/* ====================================================
*
* Input methods (load sound in SoundData class)
*/
// Read sound in memory
void CSoundData::Read_t(CTStream *inFile) // throw char *
{
// synchronize access to sounds
CTSingleLock slSounds(&_pSound->sl_csSound, TRUE);
ASSERT( sd_pswBuffer==NULL);
sd_ulFlags = NONE;
// get filename
CTFileName fnm = inFile->GetDescription();
// if this is encoded file
if (fnm.FileExt()==".ogg" || fnm.FileExt()==".mp3") {
CSoundDecoder *pmpd = new CSoundDecoder(fnm);
if (pmpd->IsOpen()) {
pmpd->GetFormat(sd_wfeFormat);
}
delete pmpd;
// mark that this is streaming encoded file
sd_ulFlags = SDF_ENCODED|SDF_STREAMING;
// if this is wave file
} else {
// load wave info
PCMWaveInput CpwiLoad;
sd_wfeFormat = CpwiLoad.LoadInfo_t(inFile);
// store sample length in seconds and average byte rate
sd_dSecondsLength = CpwiLoad.GetSecondsLength();
// if sound library is in lower format convert sound to library format
if ((_pSound->sl_SwfeFormat).nSamplesPerSec < sd_wfeFormat.nSamplesPerSec) {
sd_wfeFormat.nSamplesPerSec = (_pSound->sl_SwfeFormat).nSamplesPerSec;
}
// same goes for bits/sample (must be 16)
sd_wfeFormat.wBitsPerSample = 16;
// if library is active create buffer and load sound data
if (_pSound->IsActive()) {
// create Buffer
sd_slBufferSampleSize = CpwiLoad.GetDataLength(sd_wfeFormat);
SLONG slBufferSize = CpwiLoad.DetermineBufferSize(sd_wfeFormat);
sd_pswBuffer = (SWORD*)AllocMemory( slBufferSize+8);
// load data into buffer
CpwiLoad.LoadData_t( inFile, sd_pswBuffer, sd_wfeFormat);
// copy first sample to the last one (this is needed for linear interpolation)
(ULONG&)(((UBYTE*)sd_pswBuffer)[slBufferSize]) = *(ULONG*)sd_pswBuffer;
}
}
// add to sound aware list
_pSound->AddSoundAware(*this);
}
// Sound can't be written to file
void CSoundData::Write_t( CTStream *outFile)
{
ASSERTALWAYS("Cannot write sounds!");
throw TRANS("Cannot write sounds!");
}
/* Get the description of this object. */
CTString CSoundData::GetDescription(void)
{
CTString str;
str.PrintF("%dkHz %dbit %s %.2lfs",
sd_wfeFormat.nSamplesPerSec/1000,
sd_wfeFormat.wBitsPerSample,
sd_wfeFormat.nChannels==1 ? "mono" : "stereo",
sd_dSecondsLength);
return str;
}
/* ====================================================
*
* Class CLEAR method
*/
// Free memory allocated for sound and Release DXBuffer
void CSoundData::Clear(void)
{
// synchronize access to sounds
CTSingleLock slSounds(&_pSound->sl_csSound, TRUE);
// clear BASE class
CSerial::Clear();
// free DXBuffer
ClearBuffer();
// if added as sound aware, remove it from sound aware list
if(IsHooked()) {
_pSound->RemoveSoundAware(*this);
}
}
// check if this kind of objects is auto-freed
BOOL CSoundData::IsAutoFreed(void)
{
return FALSE;
}
// get amount of memory used by this object
SLONG CSoundData::GetUsedMemory(void)
{
SLONG slUsed = sizeof(*this);
if( sd_pswBuffer!=NULL) {
ASSERT( sd_wfeFormat.nChannels==1 || sd_wfeFormat.nChannels==2);
slUsed += sd_slBufferSampleSize * sd_wfeFormat.nChannels *2; // all sounds are 16-bit
}
return slUsed;
}
/* ====================================================
*
* Reference counting functions
*/
// Add one reference
void CSoundData::AddReference(void)
{
ASSERT(this!=NULL);
MarkUsed();
2016-03-11 14:57:17 +01:00
}
// Remove one reference
void CSoundData::RemReference(void)
{
ASSERT(this!=NULL);
_pSoundStock->Release(this);
2016-03-11 14:57:17 +01:00
}