zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

commit 824a93aef8992b0cbfb7c689a3a9a3b32000541b
parent f3b25056efb53f2d4c56a27c4cec0ed98614ce6a
Author: fundamental <[email protected]>
Date:   Fri, 18 Dec 2009 13:21:27 -0500

Misc: Added appending and resampling to Samples

Diffstat:
Msrc/Samples/Sample.cpp | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/Samples/Sample.h | 12+++++++++---
Msrc/Tests/SampleTest.h | 27+++++++++++++++++++++++++++
3 files changed, 106 insertions(+), 3 deletions(-)

diff --git a/src/Samples/Sample.cpp b/src/Samples/Sample.cpp @@ -19,8 +19,10 @@ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <cmath> +#include <cstring>//for memcpy/memset #include "Sample.h" +#warning TODO Think about renaming Sample to Frame /**\TODO start using pointer math here as these will be Frequency called * functions throughout the code*/ Sample::Sample(const Sample &smp) @@ -92,6 +94,74 @@ bool Sample::operator==(const Sample &smp) const return true; } +/** + * Linear point estimation + * @param ya Y of point a + * @param yb Y of point b + * @param xt X of test point + * @param xa X of point a + * @param xb X of point b + * @return estimated Y of test point + */ +float linearEstimate(float ya, float yb, float xt, float xa = 0.0, float xb =1.0) +{ +#warning TODO this could be done with a good bit less computation + //Lets make this simple by normalizing the x axis + + //Normalize point a + xb -= xa; + xt -= xa; + xa -= xa; + + //Normalize point b + xt /= xb; + xb /= xb; + + //Now xa=0 xb=1 0<=xt<=1 + //simpily use y=mx+b + return (yb-ya) * xt + ya; +} + + +void Sample::resample(const unsigned int rate, const unsigned int nrate) +{ + if(rate == nrate) + return; //no resampling here + else {//resampling occurs here + int itr = 0; + float ratio = (nrate * 1.0) / (rate * 1.0); + + int nBufferSize = (int)bufferSize * ratio; + float *nBuffer = new float[nBufferSize]; + + //addition is done to avoid 0 edge case + for(int i = 0; i < nBufferSize; ++i) + nBuffer[i] = linearEstimate(buffer[(int)floor(i/ratio)], + buffer[(int)ceil((i+1)/ratio)], + i, + floor(i/ratio), + ceil((i+1)/ratio)); + + //put the new data in + delete buffer; + buffer = nBuffer; + bufferSize = nBufferSize; + } +} + +void Sample::append(const Sample &smp) +{ + int nbufferSize = bufferSize + smp.bufferSize; + float *nbuffer = new float[nbufferSize]; + + memcpy(nbuffer, buffer, bufferSize * sizeof(float)); + memcpy(nbuffer + bufferSize, smp.buffer, smp.bufferSize * sizeof(float)); + delete buffer; + + buffer = nbuffer; + bufferSize = nbufferSize; +} + REALTYPE Sample::max() const { REALTYPE max = -1500; //a good low considering that samples should store values -1.0 to 1.0 diff --git a/src/Samples/Sample.h b/src/Samples/Sample.h @@ -50,13 +50,19 @@ class Sample void operator=(const Sample &smp); /**Provides the == operator*/ bool operator==(const Sample &smp) const; + /**Provides direct access to the buffer to allow for transition * * This method is like c_str() from the string class and should be used * sparingly*/ - const REALTYPE *c_buf() { - return buffer; - } + const REALTYPE *c_buf() const {return buffer;} + + /**Change the sampling rate of the Sample*/ + void resample(const unsigned int rate, const unsigned int nrate); + + /**Appends another Sample to this Sample*/ + void append(const Sample &smp); + REALTYPE max() const; REALTYPE min() const; REALTYPE absMax() const; diff --git a/src/Tests/SampleTest.h b/src/Tests/SampleTest.h @@ -71,5 +71,32 @@ class SampleTest:public CxxTest::TestSuite for(int i = 0; i < 50; ++i) TS_ASSERT_EQUALS(smp[i], 0); } + + void testAppend() { + Sample smp1(54, 2); + Sample smp2(20, 17); + smp1.append(smp2); + TS_ASSERT_EQUALS(smp1.size(), 74); + for(int i = 0; i < 74; ++i) + TS_ASSERT_DELTA(smp1[i], (i < 54 ? 2 : 17), 0.001); + } + + void testResample() { + Sample orig(32,2); + Sample cpy(orig); + + //test for no resampleing + orig.resample(128,128); + TS_ASSERT_EQUALS(cpy,orig); + + //test for no bad distortions + orig.resample(128,256); + orig.resample(256,128); + TS_ASSERT_EQUALS(cpy,orig); + + //test for downsample + orig.resample(256,128); + TS_ASSERT_EQUALS(orig.size(),cpy.size()/2); + } };