Main Page   Class Hierarchy   Compound List   File List   Compound Members   Related Pages  

gapefunctionunit.cpp

00001 // gapefunctionunit.cpp
00002 // Dave Chisholm dkc@ccrma.stanford.edu 11/21/00
00003 
00004 #include "gapefunctionunit.h"
00005 #include "gapewaveformpalette.h"
00006 #include "WvIn.h"
00007 #include "qstring.h"
00008 #include "AifWvIn.h"
00009 #include "SndWvIn.h"
00010 #include "RawWvIn.h"
00011 #include "WavWvIn.h"
00012 
00013 
00014 GapeFunctionUnit::GapeFunctionUnit(GapeController* c, int nChannels)
00015 : GapeUnit(c, nChannels),
00016 sampleData(NULL),
00017 initialized(false),
00018 currentTime(0.0) {
00019     //if (c != NULL) {
00020         setFreq(GAPE_FUNCTION_UNIT_DEFAULT_FREQ);
00021         setGain(GAPE_FUNCTION_UNIT_DEFAULT_GAIN);
00022         setMute(false);
00023     //}
00024     //GapeConsts::reportError("GFu Cons\n");
00025 }
00026 
00027 
00028 GapeFunctionUnit::~GapeFunctionUnit() {
00029     delete[] sampleData;
00030     sampleData = NULL;
00031 }
00032 
00033 //This function may seem a bit terse. We have a fixed number of samples representing our waveform, and we must
00034 //use a scalar (timeScalar) to "translate" between the requested frequency and the frequency our buffer of data
00035 //would normally have (ie sample rate / dataLength). This timescalar, as well as the varibles which track our
00036 //current "time" must be updated every time our frequency control is changed.
00037 void GapeFunctionUnit::receiveTick(const GapeFloat* values, int numValues) {
00038     if (!initialized) {
00039         fillBuffer();
00040         period = (double) GapeConsts::sampleRate / frequency;
00041         timeScalar = ((double) dataLength) / period;
00042         oldFrequency = frequency;
00043         initialized = true;
00044     }
00045 
00046     if (muted) {
00047         emit emitTick(values,numValues);
00048         return;
00049     }
00050 //if (updateMutex.locked()) GapeConsts::reportError("locked GFU\n");
00051 //else GapeConsts::reportError("UNlocked GFU\n");
00052     //updateMutex.lock();
00053     if (frequency != oldFrequency) {//check if our freq has changed, and if so, recalculate our period information
00054         updateMutex.lock();
00055         double newFrequency = frequency;
00056         updateMutex.unlock();
00057         period = (double) GapeConsts::sampleRate / newFrequency;
00058         timeScalar = ((double) dataLength) / period;
00059         currentTime = currentTime * (oldFrequency / newFrequency);
00060         oldFrequency = newFrequency;
00061     }
00062 
00063 
00064     //Our current position in the waveform is between two samples (possibly right on one). We determine the sample before
00065     //our position, as well as the fraction past it we are. We then use that fraction to linearly interpolate between
00066     //the two samples in question.
00067     double scaledTime = currentTime * timeScalar;
00068     int index = (int) scaledTime;
00069     double indexRemainder = scaledTime - (double)index;
00070     double difference;
00071     if (index + 1 < dataLength) {
00072         difference = difference = sampleData[index+1] - sampleData[index];
00073     } else {
00074         difference = sampleData[0] - sampleData[index];
00075     }
00076     GapeFloat currentValue = sampleData[index] + indexRemainder*difference;
00077 
00078     //updateMutex.unlock();
00079 
00080 
00081     currentTime = currentTime + 1.0;
00082     if (currentTime >= period) {
00083         currentTime = currentTime - period;
00084     }
00085 
00086     GapeFloat sample[GAPE_MAX_NUM_CHANNELS] = {0.0};//aggregate initialization initializes all data to 0
00087     if (numValues > GAPE_MAX_NUM_CHANNELS) {
00088         numValues = GAPE_MAX_NUM_CHANNELS;
00089     }
00090 
00091 
00092     if (numValues == 0 || values == NULL) {//ie we are generating the waveform
00093         numValues = numChannels;
00094         for (int i = 0; i < numChannels; i++) {
00095             sample[i] = (currentValue * gain);
00096         }
00097 
00098     } else {//ie we are acting as a filter
00099         int i;
00100         for (i = 0;i < numValues;i++) {
00101             sample[i] = values[i];
00102         }
00103         for (i = 0; i < numValues; i++) {
00104             sample[i] += (currentValue * gain);
00105         }
00106         if (numValues < numChannels) {
00107             numValues = numChannels;
00108         }
00109     }
00110     emit emitTick(sample,numValues);
00111 
00112 }
00113 
00114 
00115 void GapeFunctionUnit::normalize() {
00116     GapeFloat max = 0.0;
00117     double scalar;
00118     int i;
00119 
00120     for (i = 0;i < dataLength; i++) {
00121         if (sampleData[i] > max) {
00122             max = sampleData[i];
00123         }
00124     }
00125 
00126     for (i = 0;i < dataLength; i++) {
00127         sampleData[i] *= 1.0 / max;
00128     }
00129 }
00130 
00131 
00132 void GapeSineUnit::fillBuffer() {
00133     int i;
00134 
00135     sampleData = new GapeFloat[GAPE_FN_BUFFER_LENGTH];
00136     for(i = 0; i < GAPE_FN_BUFFER_LENGTH; ++i) {
00137         sampleData[i] = sin(i * 2 * PI / (double) GAPE_FN_BUFFER_LENGTH);
00138     }
00139     dataLength = GAPE_FN_BUFFER_LENGTH;
00140     normalize();
00141 }
00142 
00143 
00144 void GapeTriangleUnit::fillBuffer() {
00145     int i, j, maxHarmonic;
00146     maxHarmonic = GAPE_FUNCTION_UNIT_MAX_HARMONICS;
00147     bool positive = true;  // every other term is positive.
00148     sampleData = new GapeFloat[GAPE_FN_BUFFER_LENGTH];
00149 
00150     for(i = 0; i < GAPE_FN_BUFFER_LENGTH; ++i) {
00151         sampleData[i] = 0;
00152         for(j = 1; j < maxHarmonic; j += 2) {
00153             sampleData[i] += ((positive) ? 1 : -1) * sin(j * i * 2 * PI /
00154                 (double) GAPE_FN_BUFFER_LENGTH) /
00155                 ((double) j * j);
00156             positive = !positive;
00157         }
00158     }
00159     dataLength = GAPE_FN_BUFFER_LENGTH;
00160     normalize();
00161 }
00162 
00163 
00164 void GapeSawtoothUnit::fillBuffer() {
00165     int i, j, maxHarmonic;
00166     maxHarmonic = GAPE_FUNCTION_UNIT_MAX_HARMONICS;
00167     sampleData = new GapeFloat[GAPE_FN_BUFFER_LENGTH];
00168 
00169     for(i = 0; i < GAPE_FN_BUFFER_LENGTH; ++i) {
00170         sampleData[i] = 0;
00171         for(j = 1; j < maxHarmonic; ++j) {
00172             sampleData[i] +=  sin(j * i * 2 * PI / (double) GAPE_FN_BUFFER_LENGTH) / (double) j;
00173         }
00174     }
00175     dataLength = GAPE_FN_BUFFER_LENGTH;
00176     normalize();
00177 }
00178 
00179 
00180 void GapeSquareUnit::fillBuffer() {
00181     int i, j, maxHarmonic;
00182     maxHarmonic = GAPE_FUNCTION_UNIT_MAX_HARMONICS;
00183     sampleData = new GapeFloat[GAPE_FN_BUFFER_LENGTH];
00184 
00185     for(i = 0; i < GAPE_FN_BUFFER_LENGTH; ++i) {
00186         sampleData[i] = 0;
00187         for(j = 1; j < maxHarmonic; j+=2) {
00188             sampleData[i] +=  sin(j * i * 2 * PI / (double) GAPE_FN_BUFFER_LENGTH) / (double) j;
00189         }
00190     }
00191     dataLength = GAPE_FN_BUFFER_LENGTH;
00192     normalize();
00193 }
00194 
00195 
00196 void GapeHalfwaveUnit::fillBuffer() {
00197     int i;
00198     sampleData = new GapeFloat[GAPE_FN_BUFFER_LENGTH];
00199 
00200     for(i = 0; i < GAPE_FN_BUFFER_LENGTH / 2; ++i) {
00201         sampleData[i] = sin(i * 2 * PI / (double) GAPE_FN_BUFFER_LENGTH);
00202     }
00203     for(i = GAPE_FN_BUFFER_LENGTH / 2; i < GAPE_FN_BUFFER_LENGTH; ++i) {
00204         sampleData[i] = 0;
00205     }
00206     dataLength = GAPE_FN_BUFFER_LENGTH;
00207     normalize();
00208 }
00209 
00210 
00211 GapeDrawnWaveformUnit::GapeDrawnWaveformUnit(QWidget* parent)
00212 : GapeFunctionUnit(new GapeWaveformPalette(parent,"Drawn Waveform")),
00213 xData(NULL) {
00214     fillBuffer();
00215     period = (double) GapeConsts::sampleRate / frequency;
00216     timeScalar = ((double) dataLength) / period;
00217     oldFrequency = frequency;
00218     initialized = true;
00219     xData = new double[dataLength];
00220     for (int i = 0; i < dataLength; i++) {
00221         xData[i] = (double) i / (double) dataLength;
00222     }
00223     GapeWaveformPalette* c = (GapeWaveformPalette*) controllers[0];
00224     connect(c, SIGNAL(emitPoint(double, double)), this, SLOT(setPoint(double, double)));
00225     c->setRawData(xData, sampleData, dataLength);
00226 }
00227 
00228 
00229 
00230 //void GapeDrawnWaveformUnit::setFreq(double newFreq) {
00231 //  GapeUnit::setFreq(newFreq / GapeConsts::sampleRate);
00232 //}
00233 
00234 
00235 void GapeDrawnWaveformUnit::setPoint(double x, double y) {
00236     int index = (int) (x * ((double) dataLength));
00237     sampleData[index] = y;
00238 }
00239 
00240 
00241 void GapeDrawnWaveformUnit::fillBuffer() {
00242     int i;
00243     sampleData = new GapeFloat[GAPE_DRAWN_WAVEFORM_BUFFER_LENGTH];
00244 
00245     for(i = 0; i < GAPE_DRAWN_WAVEFORM_BUFFER_LENGTH; i++) {
00246         sampleData[i] = 0;
00247     }
00248     dataLength = GAPE_DRAWN_WAVEFORM_BUFFER_LENGTH;
00249 }
00250 
00251 
00252 
00253 
00254 GapeFileSampleUnit::GapeFileSampleUnit (QWidget* parent, const QString& file)
00255 : GapeFunctionUnit(new GapeSimpleController(parent,"SampleLoadedFromFile")),
00256 dataReader(NULL),
00257 validFile(false) {
00258     filename = new QString(file.latin1());
00259     fillBuffer();
00260     period = (double) GapeConsts::sampleRate / frequency;
00261     timeScalar = ((double) dataLength) / period;
00262     oldFrequency = frequency;
00263     initialized = true;
00264     ((GapeSimpleController*) controllers[0])->setFreqRange(1.0, GAPE_SIMPLE_CONTROLLER_FREQ_MAX, GAPE_SIMPLE_CONTROLLER_FREQ_STEP);
00265     controllers[0]->setFreq(1.0);
00266 }
00267 
00268 
00269 GapeFileSampleUnit::~GapeFileSampleUnit () {delete filename;}
00270 
00271 void GapeFileSampleUnit::fillBuffer() {
00272     char buffer[512];
00273     validFile = true;
00274 
00275     //we must use a bufer for our file name b/c stk doesn't use the const keyword...
00276     strncpy(buffer, filename->latin1(), 512);
00277 
00278     try {
00279         if (filename->find(".aif",-5,false) >= 0) {//we have an aiff format file
00280             dataReader = new AifWvIn(buffer,"oneshot");
00281         } else if (filename->find(".raw",-4,false) >= 0) {//we have a raw sound file
00282             dataReader = new RawWvIn(buffer,"oneshot");
00283         } else if (filename->find(".wav",-4,false) >= 0) {//we have a wav format sound file
00284             dataReader = new WavWvIn(buffer,"oneshot");
00285         } else if (filename->find(".snd",-4,false) >= 0) {//we have an snd format sound file
00286             dataReader = new SndWvIn(buffer,"oneshot");
00287         } else {
00288             //validFile = false;
00289             QString errorMessage("Vague filename for GapeFileSampleUnit (should end in .raw/wav/snd/aif/aiff) - ");
00290             errorMessage.append(*filename);
00291             errorMessage.append("\n Opening as raw file \n");
00292             GapeConsts::reportError(errorMessage.latin1());
00293             dataReader = new WavWvIn(buffer,"oneshot");
00294         }
00295     } catch(StkError& e) {
00296         validFile = false;
00297         QString errorMessage("Error opening file - ");
00298         errorMessage.append(*filename);
00299         GapeConsts::reportError(errorMessage.latin1());
00300     }
00301     setNumChannels(1);
00302 
00303     if (dataReader->getSize() > GAPE_FILE_SAMPLE_UNIT_MAX_SIZE) {
00304         validFile = false;
00305         QString errorMessage("File: ");
00306         errorMessage.append(*filename);
00307         errorMessage.append("too large for GapeFileSampleUnit \n");
00308         GapeConsts::reportError(errorMessage.latin1());
00309     }
00310 
00311     if (!validFile) return;
00312 
00313     //I have no idea why this is needed but STK seems to be acting unexspectedly
00314     dataReader->setRate(1.5);
00315 
00316     //dataReader->setRate(dataReader->getRate() * SRATE/GapeConsts::sampleRate);
00317 
00318     dataLength = dataReader->getSize();// * GapeConsts::sampleRate/SRATE;
00319     sampleData = new GapeFloat[dataLength];
00320 
00321     for (int i = 0; i < dataLength; i++) {
00322         if (dataReader->isFinished()) break;
00323         for (int j = 0; j < numChannels; j++) {
00324             sampleData[i] = dataReader->tick();
00325         }
00326     }
00327 
00328     delete dataReader;
00329 }
00330 
00331 
00332 void GapeFileSampleUnit::receiveTick(const GapeFloat* values, int numValues) {
00333     if (validFile) {
00334         GapeFunctionUnit::receiveTick(values, numValues);
00335     } else {
00336         emit emitTick(values, numValues);
00337     }
00338 }

Generated at Thu Jun 21 13:28:49 2001 for GAPE by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001