From: <wha...@us...> - 2011-06-29 21:00:05
|
Revision: 7477 http://planeshift.svn.sourceforge.net/planeshift/?rev=7477&view=rev Author: whacko88 Date: 2011-06-29 20:59:59 +0000 (Wed, 29 Jun 2011) Log Message: ----------- Implemented SndSysSongStream, only the musical sheet parsing is now missing Modified Paths: -------------- soc/2011/sound/src/plugins/common/soundmanager/instrument.cpp soc/2011/sound/src/plugins/common/soundmanager/instrument.h soc/2011/sound/src/plugins/common/soundmanager/songstream.cpp soc/2011/sound/src/plugins/common/soundmanager/songstream.h Modified: soc/2011/sound/src/plugins/common/soundmanager/instrument.cpp =================================================================== --- soc/2011/sound/src/plugins/common/soundmanager/instrument.cpp 2011-06-29 14:24:17 UTC (rev 7476) +++ soc/2011/sound/src/plugins/common/soundmanager/instrument.cpp 2011-06-29 20:59:59 UTC (rev 7477) @@ -213,6 +213,12 @@ SetEnharmonic(pitch, alter, octave, buffer, streamSize); + // updating longestBufferSize + if(longestBufferSize < streamSize) + { + longestBufferSize = streamSize; + } + // reading and copying data noteStream->ResetPosition(); // the position of the stream is now 0 positionMarker = 0; Modified: soc/2011/sound/src/plugins/common/soundmanager/instrument.h =================================================================== --- soc/2011/sound/src/plugins/common/soundmanager/instrument.h 2011-06-29 14:24:17 UTC (rev 7476) +++ soc/2011/sound/src/plugins/common/soundmanager/instrument.h 2011-06-29 20:59:59 UTC (rev 7477) @@ -104,6 +104,12 @@ const csSndSysSoundFormat* GetFormat() const { return format; } /** + * Gets the size of the note with the longest buffer. + * @return the size of the note with the longest buffer. + */ + size_t GetLongestNoteSize() const { return longestBufferSize; } + + /** * Add the given note to the sounds that this instruments can play. If the * given note has already been defined, nothing happens. * @@ -140,6 +146,7 @@ private: uint polyphony; ///< number of notes that this instrument can play at the same time. + size_t longestBufferSize; ///< keeps the size of note with the longest buffer. csSndSysSoundFormat* format; ///< the format shared by all the notes' streams. csHash<csHash<Note*, char>, uint> notes; ///< the notes' streams. Modified: soc/2011/sound/src/plugins/common/soundmanager/songstream.cpp =================================================================== --- soc/2011/sound/src/plugins/common/soundmanager/songstream.cpp 2011-06-29 14:24:17 UTC (rev 7476) +++ soc/2011/sound/src/plugins/common/soundmanager/songstream.cpp 2011-06-29 20:59:59 UTC (rev 7477) @@ -24,38 +24,184 @@ //==================================================================================== #include "songdata.h" -SndSysSongStream::SndSysSongStream(csRef<SndSysSongData> songData, SongData* data, csSndSysSoundFormat* renderFormat, int mode3D): - SndSysBasicStream(renderFormat, mode3D) + +SndSysSongStream::SndSysSongStream(csRef<SndSysSongData> sndData, SongData* data, csSndSysSoundFormat* renderFormat, int mode3D): + SndSysBasicStream(renderFormat, mode3D), soundData(sndData) { - sndData = songData; - song = data; + isFinished = false; + currentMeasure = 0; + currentNote = 0; + + noteBuffer = new uint8[songData->instrument->GetLongestNoteSize()]; + noteBufferSize = 0; + lastNoteDuration = 0; + + songData = data; + + // conversion variables are set during the first AdvancePosition() because m_OutputFrequency = 0 + conversionFactor = 0; + conversionNeeded = false; + + // TODO create cyclic buffer } SndSysSongStream::~SndSysSongStream() { - // song->instrument is deleted by InstrumentManager - // song is deleted by SndSysSongData + // songData is deleted by SndSysSongData + delete[] noteBuffer; } const char* SndSysSongStream::GetDescription() { - // TODO check the SndSysSongData description - return "Song Stream"; + const char* desc = soundData->GetDescription(); + if(desc == 0) + { + return "Song Stream"; + } + return desc; } size_t SndSysSongStream::GetFrameCount() { - // TODO adapth the data format to this one - return 0; + // Note that the stream's format can be different from + // the data's one. The count must be adjusted according + // to the frequencies + const csSndSysSoundFormat* dataFormat = soundData->GetFormat(); + + uint64 frameCount = soundData->GetFrameCount(); + frameCount *= m_RenderFormat.Freq; + frameCount /= dataFormat->Freq; + + return frameCount; } -void SndSysSongStream::AdvancePosition(size_t frame_delta) +void SndSysSongStream::AdvancePosition(size_t frameDelta) { - // TODO + bool isFinished; + size_t neededBytes; + size_t neededBuffer; + const csSndSysSoundFormat* dataFormat = soundData->GetFormat(); + + // if the stream is in pause or we have already finished to read don't advance + if(m_bPaused || m_bPlaybackReadComplete || frameDelta == 0) + { + return; + } + + // Computing how many bytes we need to fill for this advancement + neededBytes = frameDelta * (m_RenderFormat.Bits / 8) * m_RenderFormat.Channels; + + // If we need more space than is available in the whole cyclic buffer, then we already underbuffered, reduce to just 1 cycle full + if((size_t)neededBytes > m_pCyclicBuffer->GetLength()) + { + needed_bytes=(size_t)(m_pCyclicBuffer->GetLength() & 0x7FFFFFFF); + } + + // Free space in the cyclic buffer if necessary + if ((size_t)needed_bytes > m_pCyclicBuffer->GetFreeBytes()) + { + m_pCyclicBuffer->AdvanceStartValue(neededBytes - (size_t)(m_pCyclicBuffer->GetFreeBytes() & 0x7FFFFFFF)); + } + + // Fill in leftover decoded data if needed + if (m_PreparedDataBufferUsage > 0) + { + neededBytes -= CopyBufferBytes(neededBytes); + } + + // if the end of the sheet has been reached and the prepared buffer + // is empty no more data cab be copied to the cyclic buffer + if(isFinished && m_PreparedDataBufferUsage == 0) + { + if(!m_bLooping) + { + m_bPlaybackReadComplete = true; + neededBytes = 0; // no more data + } + else + { + currentMeasure = 0; + currentNote = 0; + } + } + + // set back m_NewPosition to invalid if the last note has been + // completely copied. Needed for PendingSeek() to work. + if(m_PreparedDataBufferUsage == 0 && m_NewPosition != InvalidPosition) + { + m_NewPosition = InvalidPosition; + } + + while(neededBytes > 0) + { + // Handle a frequency change + if (m_NewOutputFrequency != m_OutputFrequency) + { + m_OutputFrequency = m_NewOutputFrequency; + + // Create the pcm sample converter if it's not yet created + if (m_pPCMConverter == 0) + { + m_pPCMConverter = new PCMSampleConverter(dataFormat->Channels, dataFormat->Bits, dataFormat->Freq); + } + + // check if the conversion is needed + if((dataFormat->Bits == m_RenderFormat.Bits) && + (dataFormat->Channels == m_RenderFormat.Channels) && + (dataFormat->Freq == m_RenderFormat.Freq)) + { + conversionFactor = 1; + conversionNeeded = false; + } + else + { + conversionFactor = m_pPCMConverter->GetRequiredOutputBufferMultiple(m_RenderFormat.Channels,m_RenderFormat.Bits,m_OutputFrequency)/1024; + conversionNeeded = true; + } + } + + // converting the musical sheet + isFinished = GetNextChord(); + + // expanding m_pPreparedDataBuffer if needed (it's empty at this point so it can be deleted) + neededBuffer = conversionFactor * (lastNoteDuration + (dataFormat->Bits / 8) * dataFormat->Channels); + if(m_PreparedDataBufferSize < neededBuffer) + { + delete[] m_pPreparedDataBuffer; + m_pPreparedDataBuffer = new char[neededBuffer]; + m_PreparedDataBufferSize=neededBuffer; + } + + // copying to m_pPreparedDataBuffer + CopyNoteIntoBuffer(); + + // copying to the cyclic buffer + if(m_PreparedDataBufferUsage > 0) + { + neededBytes -= CopyBufferBytes(neededBytes); + } + } } -void SndSysSongStream::GetDataPointers(size_t* positionMarker, size_t maxRequestedLength, - void** buffer1, size_t* buffer1Bytes, void** buffer2, size_t* buffer2Bytes) +bool SndSysSongStream::ResetPosition() { + currentMeasure = 0; + currentNote = 0; + + // this will be set to invalid in AdvancePosition() + // it's need for PendingSeek() to work + m_NewPosition = 0; + + return true; +} + +bool SndSysSongStream::GetNextChord() +{ + // TODO support loop notes + return true; +} + +void SndSysSongStream::CopyNoteIntoBuffer() +{ // TODO } Modified: soc/2011/sound/src/plugins/common/soundmanager/songstream.h =================================================================== --- soc/2011/sound/src/plugins/common/soundmanager/songstream.h 2011-06-29 14:24:17 UTC (rev 7476) +++ soc/2011/sound/src/plugins/common/soundmanager/songstream.h 2011-06-29 20:59:59 UTC (rev 7477) @@ -51,19 +51,52 @@ class SndSysSongStream: public SndSysBasicStream { public: - SndSysSongStream(csRef<SndSysSongData> songData, SongData* data, csSndSysSoundFormat* renderFormat, int mode3D); + SndSysSongStream(csRef<SndSysSongData> soundData, SongData* songData, csSndSysSoundFormat* renderFormat, int mode3D); virtual ~SndSysSongStream(); // From iSndSysStream + //-------------------- + virtual void AdvancePosition(size_t frameDelta); virtual const char* GetDescription(); virtual size_t GetFrameCount(); - virtual void AdvancePosition(size_t frame_delta); - virtual void GetDataPointers(size_t* positionMarker, size_t maxRequestedLength, - void** buffer1, size_t* buffer1Bytes, void** buffer2, size_t* buffer2Bytes); + // SndSysBasicStream overriding + //------------------------------ + virtual bool AlwaysStream() const { return true; } + virtual bool ResetPosition(); + virtual bool SetPosition(size_t newPosition) { return false; } // not supported + virtual bool SetLoopBoundaries(size_t &startPosition, size_t &endPosition) { return false; } // not supported + private: - SongData* song; - csRef<SndSysSongData> sndData; + bool isFinished; ///< true if it has been reach the end of the musical sheet. + size_t currentMeasure; ///< keeps track of the current measure of the musical sheet. + size_t currentNote; ///< keeps track of the current note in the current measure. + + uint8* noteBuffer; ///< temporary buffer used to get the note from the instrument. + size_t noteBufferSize; ///< current size of noteBuffer in bytes. + size_t lastNoteDuration; ///< duration of the last chord read by GetNextChord() in bytes. + + SongData* songData; ///< the song's data. + csRef<SndSysSongData> soundData; ///< the sound data object. + + int conversionFactor; ///< the multiplier used to get the data size from the data's format to the stream's one. + bool conversionNeeded; ///< true if the data from the instrument must be converted into the stream's format. + + /** + * Fills noteBuffer with the next chord of the song if it is not finished yet. + * Updates noteBuffer, noteBufferSize, lastDuration, currentMeasure and + * currentNote. + * + * @return true if the noteBuffer has been filled, false if the song is ended. + */ + bool GetNextChord(); + + /** + * Copies the note in noteBuffer into m_pPreparedDataBuffer and add 0 at its + * end if lastNoteDuration > noteBufferSize. This method assumes that the + * prepared data buffer is already large enough. + */ + void CopyNoteIntoBuffer(); }; #endif /* SONGSTREAM_H */ \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |