[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