int main() { // Set the global sample rate before creating class instances. Stk::setSampleRate( 44100.0 ); int nFrames = 100000; FileLoop input; FileWvOut output; try { // Load the sine wave file. input.openFile( "rawwaves/sinewave.raw", true ); // Open a 16-bit, one-channel WAV formatted output file output.openFile( "hellosine.wav", 1, FileWrite::FILE_WAV, Stk::STK_SINT16 ); } catch ( StkError & ) { exit( 1 ); } input.setFrequency( 440.0 ); // Option 1: Use StkFrames /* StkFrames frames( nFrames, 1 ); try { output.tick( input.tick( frames ) ); } catch ( StkError & ) { exit( 1 ); } */ // Option 2: Single-sample computations for ( int i=0; i<nFrames; i++ ) { try { output.tick( input.tick() ); } catch ( StkError & ) { exit( 1 ); } } return 0; }
int main(int argc, char *argv[]) { double velSource; double velReciver; double distX; double distY; double velRelativeX; double totalTime; unsigned long numSamples; if ( argc < 7 || argc > 8 ) { std::cout<<"\n\n\n****Doppler shift example*****\n\n"; std::cout<<"Will produce output assuming source is travelling towards\n"; std::cout<<"and then past receiver in straight line\n\n"; std::cout<<"Will start simulation at d0=-D and end at d1=+D\n"; std::cout<<"Simulation time = 2D/(relative velocity)\n"; std::cout<<"input will be looped for duration of simulation\n\n"; std::cout<< "usage: doppler [spd src (m/s)] [spd recv (m/s)] [distX (m)] [distY (m)] [input file (wav)] [output file (wav)] [0/1: no mix/mix]\n"; std::cout<< "NOTE: if source and receiver are diverging, fix simulation duration to 5s\n"; return 0; } else { std::cout<<"INPUT OK...\n parsed values:"; velSource = atof(argv[1]); velReciver = atof(argv[2]); distX = atof(argv[3]); distY = atof(argv[4]); //visual check to make sure input was parsed properly std::cout<<"velSource=" << velSource << " velReciver=" << velReciver << " distX=" << distX << " distY=" <<distY << " if=" << argv[5] << "\n\n"; velRelativeX = velSource-velReciver; double distAbs = sqrt(distX*distX + distY*distY); totalTime = 2*distX/velRelativeX; //total simulation time, if not diverging/constant //do some basic input checking: if ((velSource - velReciver) <= 0) { //this is for the "not so interesting" case where //the source and receiver will never "cross" // will just have a boring, constant frequency... //so we force a fixed simulation time here. std::cout<<"DIVERGING! clamping time to 5 seconds\n"; totalTime = 5.0; } numSamples = totalTime * SAMPLE_RATE; std::cout<<"relative speedX = " << velRelativeX<<"; simulation time = " << totalTime<< "s; numSamples = "<< numSamples<<"\n"; } Stk::setSampleRate( SAMPLE_RATE ); //file i/o FileWvOut outputFile; FileLoop inputLoop; try { outputFile.openFile( argv[6], 1, FileWrite::FILE_WAV, Stk::STK_SINT16 ); inputLoop.openFile(argv[5]); } catch (StkError &) { exit( 1 ); } //the doppler effect's frequency shift is implemented using a delay line whose write // pointer is incremented sample by sample and read using a variable delay. DelayL delay(1.0, DELAY_SIZE); //initialize: since read pointer can increment faster than write pointer, we should // fill up the delay line with initial values for continuity's sake... // since our input is a loop, it doesn't matter too much where the "starting" point // in the audio sample is... for (int i=0; i<DELAY_SIZE; i++) { delay.tick(inputLoop.tick()); } stk::StkFrames frames( numSamples, 1); double readPtr = 0; unsigned int writePtr = 0; double g=0; // set initial locations double xSrcCurr = 0, xSrcPrev = 0; double xRcvCurr = distX, xRcvPrev = distX; double dT = totalTime/numSamples; for (int i=0; i<numSamples; i++) { //basic kinematic model for estimating current relative speed: double timeElapsed = (double)totalTime*i/numSamples; xSrcCurr+=dT*velSource; xRcvCurr+=dT*velReciver; //distY is constant! //velRelative = ( sqrt((xSrcCurr-xSrcPrev)*(xSrcCurr-xSrcPrev)+distY*distY) + // sqrt((xRcvPrev-xRcvCurr)*(-xRcvCurr)+distY*distY) ) / dT; //double velRelative = ( (xRcvCurr-xSrcCurr) - (xRcvPrev-xSrcPrev) ) / dT; //bit of a hack to get the right behaviour, as my quickly cobbled together model // was bit sloppy when it came to managing the sign double velRelative = -fabs( sqrt((xRcvCurr-xSrcCurr)*(xRcvCurr-xSrcCurr)+distY*distY) - sqrt((xRcvPrev-xSrcPrev)*(xRcvPrev-xSrcPrev)+distY*distY) ) / dT; if (xRcvCurr < xSrcCurr) velRelative = -velRelative; //std::cout <<xSrcCurr<<" "<<xRcvCurr<< " "<< velRelative <<"\n"; xSrcPrev = xSrcCurr; xRcvPrev = xRcvCurr; //if (i < numSamples/2) // g = - velRelative/SPEED_OF_SOUND; // "growth parameter" //else g = + velRelative/SPEED_OF_SOUND; readPtr+=g; //update read pointer with variable delay //wraparound checks: if (readPtr < 0) readPtr+=DELAY_SIZE; if (readPtr>DELAY_SIZE-1) readPtr-=DELAY_SIZE; //write pointer simply increments... writePtr++; if (writePtr>DELAY_SIZE) writePtr-=DELAY_SIZE; //where the magic happens: the variable delay creates the frequency shift delay.setDelay(1+readPtr); //User Selectable switching of the "Mixing": gets rid of discontinuities // when the read pointer crosses the write location by // linearly mixing between half a delay line away. // maximum amplitude is respected, but at the cost // of additional artifacts. better mixing techniques could reduce these... double mix = ( (int)(readPtr-writePtr) % (DELAY_SIZE) ) / (double) DELAY_SIZE ; if (atoi(argv[7]) == 0) mix = 1; // overrides the mixing calculation. i.e. no mixing. //update output sample float outsample = mix*delay.tick(inputLoop.tick()); //apply mixing (if any) outsample += (1-mix)*delay.tapOut(DELAY_SIZE/2); //put into frames frames[i] = outsample; //std::cout<<"tE = " << timeElapsed<<"\n"; } //dump frames into outputFile file. (could have incrementally done it directly above...) outputFile.tick(frames); return 0; }
int main() { StkFloat d; // sample data unsigned long inputSize; // size of the input file in sample frames double inputDuration; // duration of the input file loop unsigned int channels = 1; //set global sample rate Stk::setSampleRate(44100.0); int nFrames=100000; FileLoop input; FileWvOut output; // open the input and output files, with error checking try { // load the input file input.openFile("rawwaves/Noisy_Miner_chirp_stereo.wav", false); // open a 16 bit, one channel WAV formatted output output.openFile("many_chirps.wav", 1, FileWrite::FILE_WAV, Stk::STK_SINT16); } catch (StkError &) { exit(1); } // Set input read rate based on the default STK sample rate. double rate; double inputRate; inputRate = input.getFileRate(); rate = inputRate / Stk::sampleRate(); input.setRate( rate ); // Find out the length of the input file inputSize=input.getSize(); inputDuration = inputSize/inputRate; std::cout << "input file is " << inputSize << " samples long with a duration of " << inputDuration << " sec." << std::endl; // Find out how many channels we have. channels = input.channelsOut(); std::cout << "input file has " << channels << " channels at "<< inputRate << "Hz sample rate " << std::endl; std::cout << " we want to run a rate of " << Stk::sampleRate() << " and will sample the file by a factor of " << rate << std::endl; // we want the chirps to be at the same frequency as they were recorded // so we adjust the looping rate of recorded loop // if you make the frequency negative, it reverses the loop! input.setFrequency(1.0/inputDuration); // run the oscillator for 40000 samples, writing to the output file for (int i=0; i<nFrames; i++){ try { d=input.tick(); // read 1 sample from the input file output.tick(d); // write 1 sample to the output file } catch (StkError &) { exit(1); } // print the first 100 samples to the std output for debugging if (i<10){ std::cout << d << std::endl; } } return 0; }