[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [11568] branches/soc-2007-hcube/intern/ tinySND: Added DataCache and FXSample implemetation.
Csaba Hruska
csaba.hruska at gmail.com
Sun Aug 12 16:41:54 CEST 2007
Revision: 11568
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=11568
Author: hcube
Date: 2007-08-12 16:41:54 +0200 (Sun, 12 Aug 2007)
Log Message:
-----------
Added DataCache and FXSample implemetation.
Modified Paths:
--------------
branches/soc-2007-hcube/intern/tinySND/SND_FXSample.h
branches/soc-2007-hcube/intern/tinySND/intern/SND_FXSample.cpp
Added Paths:
-----------
branches/soc-2007-hcube/intern/tinySND/SND_DataCache.h
branches/soc-2007-hcube/intern/tinySND/intern/SND_DataCache.cpp
Added: branches/soc-2007-hcube/intern/tinySND/SND_DataCache.h
===================================================================
--- branches/soc-2007-hcube/intern/tinySND/SND_DataCache.h (rev 0)
+++ branches/soc-2007-hcube/intern/tinySND/SND_DataCache.h 2007-08-12 14:41:54 UTC (rev 11568)
@@ -0,0 +1,41 @@
+#ifndef __SND_DATACACHE_H__
+#define __SND_DATACACHE_H__
+
+#include "SND_DataProvider.h"
+
+// SND_DataProvider -> SND_DataCache -> SND_FXSample
+
+// cache buffer
+class SND_DataCache
+{
+public:
+
+ SND_DataCache( SND_DataProvider *dataProvider );
+ virtual ~SND_DataCache();
+
+ int getNumFrames();
+ float getDuration(); // in sec
+
+ float getSampleRate();
+ int getBitRate();
+
+ int getNumChannels();
+
+ bool isSeekable();
+
+ virtual void seek( int frameNum );
+
+ virtual float* getPCMDataPtr( int framesNum, int channel );
+
+private:
+
+ float *mBuffer; // it has it s own medium sized sample buffer: ~300Kb
+ int mBufferSize; // number of frames
+ int mBufferPos;
+ int mFrameCounter;
+
+ SND_DataProvider *mDataProvider;
+
+};
+
+#endif //__SND_DATACACHE_H__
Modified: branches/soc-2007-hcube/intern/tinySND/SND_FXSample.h
===================================================================
--- branches/soc-2007-hcube/intern/tinySND/SND_FXSample.h 2007-08-12 14:41:03 UTC (rev 11567)
+++ branches/soc-2007-hcube/intern/tinySND/SND_FXSample.h 2007-08-12 14:41:54 UTC (rev 11568)
@@ -2,6 +2,7 @@
#define __SND_FXSAMPLE_H__
#include "SND_DataProvider.h"
+#include "SND_DataCache.h"
#include "SND_SoundInterface.h"
/* Represents a sound, one channel of dataProvider
@@ -33,7 +34,12 @@
BIDIRECTIONAL = 2
};
+ SND_FXSample( SND_DataCache *dataCache, int channelIdx );
+
+ // Creates its own DataCache instance. Its only for simplier usage.
SND_FXSample( SND_DataProvider *dataProvider, int channelIdx );
+
+ ~SND_FXSample();
PlayState getPlayState();
void play();
@@ -70,15 +76,13 @@
float* getPCMDataPtr( int framesNum ); // incremets frame counter according to play state
private:
- float *mSourceBuffer; // it has it s own medium sized sample buffer max: ~300Kb
- int mSourceBufferSize;
- int mSourceBufferPos;
+
+ float *mBuffer; // it has it s own small sized mix buffer: dynamically can be incremented in 64Kb parts
+ int mBufferSize; // number of frames
- float *mMixBuffer; // it has it s own small sized mix buffer: dynamically can be incremented in 64Kb parts
- int mMixBufferSize;
+ SND_DataCache *mDataCache;
+ bool mDeleteDataCache;
- SND_DataProvider *mDataProvider;
-
float mGain;
bool mIsMuted;
int mFrameCounter;
Added: branches/soc-2007-hcube/intern/tinySND/intern/SND_DataCache.cpp
===================================================================
--- branches/soc-2007-hcube/intern/tinySND/intern/SND_DataCache.cpp (rev 0)
+++ branches/soc-2007-hcube/intern/tinySND/intern/SND_DataCache.cpp 2007-08-12 14:41:54 UTC (rev 11568)
@@ -0,0 +1,263 @@
+#include <assert.h>
+#include <string.h>
+#include "SND_DataCache.h"
+#include "SND_Defines.h"
+
+
+SND_DataCache::SND_DataCache( SND_DataProvider *dataProvider )
+{
+ mDataProvider = dataProvider;
+
+ // allocate source buffer
+ // load whole sample if it fit into buffer size
+ int size = SND_WAVE_BUFFER_FRAMES;
+ int frames = dataProvider->getNumFrames();
+ int numChannels = dataProvider->getNumChannels();
+
+ if( frames < size )
+ {
+ size = frames;
+ }
+
+ mFrameCounter = 0;
+
+ mBufferPos = 0;
+ mBufferSize = size;
+
+ mBuffer = new float[ size * numChannels];
+ mDataProvider->seek( 0 );
+ mDataProvider->fillBuffer( mBuffer, mBufferSize );
+}
+
+SND_DataCache::~SND_DataCache()
+{
+ delete mBuffer;
+}
+
+int SND_DataCache::getNumFrames()
+{
+ assert( mDataProvider != 0 );
+ return mDataProvider->getNumFrames();
+}
+
+float SND_DataCache::getDuration()
+{
+ assert( mDataProvider != 0 );
+ return mDataProvider->getDuration();
+}
+
+float SND_DataCache::getSampleRate()
+{
+ assert( mDataProvider != 0 );
+ return mDataProvider->getSampleRate();
+}
+
+int SND_DataCache::getBitRate()
+{
+ assert( mDataProvider != 0 );
+ return mDataProvider->getBitRate();
+}
+
+int SND_DataCache::getNumChannels()
+{
+ assert( mDataProvider != 0 );
+ return mDataProvider->getNumChannels();
+}
+
+bool SND_DataCache::isSeekable()
+{
+ assert( mDataProvider != 0 );
+ return mDataProvider->isSeekable();
+}
+
+void SND_DataCache::seek( int frameNum )
+{
+ assert( mDataProvider != 0 );
+
+ if( frameNum < 0 )
+ {
+ frameNum = 0;
+ }
+
+ if( frameNum > getNumFrames() )
+ {
+ frameNum = getNumFrames() - 1;
+ }
+
+ mFrameCounter = frameNum;
+}
+
+float* SND_DataCache::getPCMDataPtr( int framesNum, int channel )
+{
+ assert( mDataProvider != 0 );
+
+ // check if the wave buffer has enough data, load if it doesn't
+
+ // check framesNum > mBufferSize, increase if necessary
+ if( framesNum > mBufferSize )
+ {
+ // new buffer structure:
+ // ----------------------------------------------------------------------------
+ // | new data (part A) | currently buffered data (part B) | new data (part C) |
+ // ----------------------------------------------------------------------------
+
+ int numChannels = getNumChannels();
+ int copiedDataNum = 0;
+ int copyOldStart = 0;
+ int copyOldEnd = 0;
+ int copyNewStart = 0;
+ int copyNewEnd = 0;
+
+ // allocate new buffer
+ int newSize = (framesNum / SND_WAVE_BUFFER_FRAMES + 1) * SND_WAVE_BUFFER_FRAMES;
+ float *newBuffer = new float[ newSize * numChannels ];
+
+ // copy datas from the old buffer if there is any usable
+ // calculate (part B) size
+ if( mFrameCounter <= mBufferPos + mBufferSize && mFrameCounter + mBufferSize > mBufferPos )
+ {
+ if( mFrameCounter <= mBufferPos )
+ {
+ copyOldStart = 0;
+ copyNewStart = mBufferPos - mFrameCounter;
+ }
+ else
+ {
+ copyOldStart = mFrameCounter - mBufferPos;
+ copyNewStart = 0;
+ }
+
+ if( mFrameCounter + newSize > mBufferPos + mBufferSize )
+ {
+ copyOldEnd = mBufferSize;
+ copyNewEnd = copyNewStart + mBufferSize;
+ }
+ else
+ {
+ copyOldEnd = mBufferPos + mBufferSize - mFrameCounter - newSize;
+ copyNewEnd = newSize;
+ }
+
+ // copy data
+ copiedDataNum = copyOldEnd - copyOldStart;
+ memcpy( &newBuffer[ copyNewStart*numChannels ], &mBuffer[ copyOldStart*numChannels ], copiedDataNum * numChannels * sizeof(float) );
+ }
+
+ // load new data
+ // (part A)
+ if( copyNewStart > 0 )
+ {
+ mDataProvider->seek( mFrameCounter );
+ mDataProvider->fillBuffer( newBuffer, copyNewStart );
+ }
+
+ // (part C)
+ if( copyNewEnd < newSize )
+ {
+ mDataProvider->seek( mFrameCounter + copyNewEnd );
+ mDataProvider->fillBuffer( &newBuffer[ copyNewEnd*numChannels ], newSize - copyNewEnd );
+ }
+
+ // delete old buffer
+ delete mBuffer;
+
+ mBuffer = newBuffer;
+ mBufferSize = newSize;
+ mBufferPos = mFrameCounter;
+ }
+
+ // check underflow, load data if necessary
+ if( mFrameCounter < mBufferPos )
+ {
+ int offset;
+ int dataOffset;
+ int newPos;
+ int i;
+
+ if( mFrameCounter > mBufferPos - SND_WAVE_BUFFER_FRAMES )
+ {
+ offset = SND_WAVE_BUFFER_STEP_FRAMES;
+ newPos = mBufferPos - offset;
+ }
+ else
+ {
+ offset = mBufferPos - mFrameCounter;
+ newPos = mFrameCounter;
+ }
+
+ // prevent negative frame number
+ if( mBufferPos - offset < 0 )
+ {
+ offset = mBufferPos;
+ }
+
+ // prevent buffer overflow
+ if( offset > mBufferSize )
+ {
+ offset = mBufferSize;
+ }
+
+ dataOffset = offset * getNumChannels();
+
+ for( i = mBufferSize * getNumChannels() - 1 ; i >= dataOffset ; --i )
+ {
+ mBuffer[ i ] = mBuffer[ i - dataOffset ];
+ }
+
+ mBufferPos = newPos;
+ mDataProvider->seek( mBufferPos );
+ mDataProvider->fillBuffer( mBuffer, offset );
+ }
+
+ // check overflow, load data if necessary
+ if( mFrameCounter + framesNum > mBufferPos + mBufferSize )
+ {
+ int offset;
+ int dataOffset;
+ int dataEnd;
+ int newPos;
+ int i;
+
+ if( mFrameCounter + framesNum < mBufferPos + mBufferSize + SND_WAVE_BUFFER_FRAMES )
+ {
+ offset = SND_WAVE_BUFFER_STEP_FRAMES;
+ newPos = mBufferPos + offset;
+ }
+ else
+ {
+ offset = mFrameCounter - mBufferPos;
+ newPos = mFrameCounter;
+ }
+
+ // prevent frame number overflow
+ if( newPos >= getNumFrames() - mBufferSize )
+ {
+ newPos = getNumFrames() - mBufferSize - 1;
+ offset -= mFrameCounter - newPos;
+ }
+
+ // prevent buffer overflow
+ if( offset > mBufferSize )
+ {
+ offset = mBufferSize;
+ }
+
+ dataOffset = offset * getNumChannels();
+ dataEnd = mBufferSize * getNumChannels();
+
+ for( i = 0 ; dataOffset < dataEnd ; ++i, ++dataOffset )
+ {
+ mBuffer[ i ] = mBuffer[ dataOffset ];
+ }
+
+ mBufferPos = newPos;
+ mDataProvider->seek( mBufferPos + offset );
+
+ mDataProvider->fillBuffer( &mBuffer[ (mBufferSize - offset) * getNumChannels() ], offset );
+ }
+
+ int index = (mFrameCounter - mBufferPos) * getNumChannels() + channel;
+
+ return &mBuffer[ index ];
+}
+
Modified: branches/soc-2007-hcube/intern/tinySND/intern/SND_FXSample.cpp
===================================================================
--- branches/soc-2007-hcube/intern/tinySND/intern/SND_FXSample.cpp 2007-08-12 14:41:03 UTC (rev 11567)
+++ branches/soc-2007-hcube/intern/tinySND/intern/SND_FXSample.cpp 2007-08-12 14:41:54 UTC (rev 11568)
@@ -9,35 +9,58 @@
#include "SND_FXSample.h"
#include "SND_Defines.h"
+SND_FXSample::SND_FXSample( SND_DataCache *dataCache, int channelIdx )
+{
+ mDataCache = dataCache;
+ mPlayState = SND_FXSample::STOPPED;
+ mPlayDirection = SND_FXSample::FORWARD;
+ mLoopMode = SND_FXSample::OFF;
+
+ mChannelNum = channelIdx;
+
+ mLoopStartFrame = 0;
+ mLoopEndFrame = mDataCache->getNumFrames();
+ mIsMuted = false;
+ mGain = 1.0;
+
+ mBuffer = new float[ SND_MIX_BUFFER_FRAMES ];
+ mBufferSize = SND_MIX_BUFFER_FRAMES;
+
+ mDeleteDataCache = false;
+}
+
SND_FXSample::SND_FXSample( SND_DataProvider *dataProvider, int channelIdx )
{
- mDataProvider = dataProvider;
+ SND_DataCache *dataCache = new SND_DataCache( dataProvider );
+
+
+ mDataCache = dataCache;
mPlayState = SND_FXSample::STOPPED;
mPlayDirection = SND_FXSample::FORWARD;
mLoopMode = SND_FXSample::OFF;
mChannelNum = channelIdx;
- // allocate source buffer
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list