void onAudio(AudioIOData& io){ while(io()){ float s = src(); if(stft(s)){ // Define the band edges, in Hz float freqLo = 400; float freqHi = 1800; for(unsigned k=0; k<stft.numBins(); ++k){ // Compute the frequency, in Hz, of this bin float freq = k*stft.binFreq(); // If the bin frequency is outside of our band, then zero // the bin. if(freq < freqLo || freq > freqHi){ stft.bin(k) = 0; } } } s = stft(); io.out(0) = s; io.out(1) = s; } }
void onAudio(AudioIOData& io){ float pshift = 1.7831; //pshift = 1./pshift; while(io()){ float s = play(); play.loop(); if(stft(s)){ enum{ PREV_MAG=0, TEMP_MAG, TEMP_FRQ }; // Compute spectral flux (L^1 norm on positive changes) float flux = 0; for(unsigned k=0; k<stft.numBins(); ++k){ float mcurr = stft.bin(k)[0]; float mprev = stft.aux(PREV_MAG)[k]; if(mcurr > mprev){ flux += mcurr - mprev; } } //printf("%g\n", flux); //gam::printPlot(flux); printf("\n"); // Store magnitudes for next frame stft.copyBinsToAux(0, PREV_MAG); // Given an onset, we would like the phases of the output frame // to match the input frame in order to preserve transients. if(flux > 0.2){ stft.resetPhases(); } // Initialize buffers to store pitch-shifted spectrum for(unsigned k=0; k<stft.numBins(); ++k){ stft.aux(TEMP_MAG)[k] = 0.; stft.aux(TEMP_FRQ)[k] = k*stft.binFreq(); } // Perform the pitch shift: // Here we contract or expand the bins. For overlapping bins, // we simply add the magnitudes and replace the frequency. // Reference: // http://oldsite.dspdimension.com/dspdimension.com/src/smbPitchShift.cpp if(pshift > 0){ unsigned kmax = stft.numBins() / pshift; if(kmax >= stft.numBins()) kmax = stft.numBins()-1; for(unsigned k=1; k<kmax; ++k){ unsigned j = k*pshift; stft.aux(TEMP_MAG)[j] += stft.bin(k)[0]; stft.aux(TEMP_FRQ)[j] = stft.bin(k)[1]*pshift; } } // Copy pitch-shifted spectrum over to bins stft.copyAuxToBins(TEMP_MAG, 0); stft.copyAuxToBins(TEMP_FRQ, 1); } s = stft(); io.out(0) = io.out(1) = s; } }