Skip to content

Commit

Permalink
Added Phase Compensation, Latency Reporting, and Updated URL for vers…
Browse files Browse the repository at this point in the history
…ion 1.0
  • Loading branch information
jeremysalwen committed Aug 7, 2011
1 parent 21b9607 commit 18cf172
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 47 deletions.
17 changes: 15 additions & 2 deletions kn0ck0ut.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
@prefix ev: <http://lv2plug.in/ns/ext/event#>.
@prefix ll: <http://ll-plugins.nongnu.org/lv2/namespace#>.

<urn:St3pan0va.plugins.kn0ck0ut> a lv2:Plugin ;
<urn:St3pan0va.plugins.kn0ck0ut.1> a lv2:Plugin ;
doap:name "Kn0ck0ut Vocal Remover" ;
lv2:binary <libkn0ck0ut.so>;
doap:developer [
Expand Down Expand Up @@ -41,7 +41,6 @@
lv2:index 3;
lv2:symbol "mode";
lv2:name "Mode";
lv2:portProperty lv2:toggled;
lv2:portProperty lv2:enumeration;
lv2:default 0;
lv2:scalePoint [ rdfs:label "Extract Centre"; rdf:value 1 ];
Expand Down Expand Up @@ -100,4 +99,18 @@
lv2:default 2;
lv2:minimum 1;
lv2:maximum 32;
],[
a lv2:InputPort;
a lv2:ControlPort;
lv2:index 10;
lv2:symbol "phase";
lv2:name "Phase Compensation";
lv2:portProperty lv2:toggled;
],[
a lv2:OutputPort;
a lv2:ControlPort;
lv2:index 11;
lv2:symbol "latency";
lv2:name "Latency";
lv2:portProperty lv2:reportsLatency;
].
92 changes: 50 additions & 42 deletions kn0ck0ut6.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ void AKnockout::AllocateNewBuffers(unsigned int fftSize) {
FFTRealBuffer=(float*)fftwf_malloc(sizeof(float)*fftSize);
gFFTworksp = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize2);
gOutputAccum = new float [fftSize];
gAnaFreq = new float [fftSize2];
gAnaPhase1 = new float [fftSize2];
gAnaPhase2 = new float [fftSize2];
gAnaMagn = new float [fftSize2];
gInFIFO2 = new float [fftSize];
gFFTworksp2 = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize2);
Expand All @@ -80,7 +81,8 @@ void AKnockout::FreeOldBuffers() {
fftwf_free(FFTRealBuffer);
fftwf_free(gFFTworksp);
delete[] gOutputAccum;
delete[] gAnaFreq;
delete[] gAnaPhase1;
delete[] gAnaPhase2;
delete[] gAnaMagn;
delete[] gAnaMagn2;
delete[] gInFIFO2;
Expand All @@ -98,7 +100,8 @@ void AKnockout::clearBuffers()
memset(gInFIFO, 0, fftSize*sizeof(float));
memset(gFFTworksp, 0, fftSize2*sizeof(fftwf_complex));
memset(gOutputAccum, 0, fftSize*sizeof(float));
memset(gAnaFreq, 0, fftSize2*sizeof(float));
memset(gAnaPhase1, 0, fftSize2*sizeof(float));
memset(gAnaPhase2, 0, fftSize2*sizeof(float));
memset(gAnaMagn, 0, fftSize2*sizeof(float));
memset(gInFIFO2, 0, fftSize*sizeof(float));
memset(gFFTworksp2, 0, fftSize2*sizeof(fftwf_complex));
Expand Down Expand Up @@ -183,11 +186,14 @@ void AKnockout::run(uint32_t sampleFrames)
if(resetbuffers) {
clearBuffers();
}
//Latency works out to be exactly the fft size.
*p(p_latency)=gfftSize;
CLAMP_PORT(int,iBlur,p_blur)
CLAMP_PORT(float,fDecay,p_decay)
CLAMP_PORT(float,fDecay,p_decay)
bool consider_phase = *p(p_phase)>0;
// arguments are number of samples to process, fft window size, sample overlap (4-32), input buffer, output buffer, init flag, gain, R input gain, decay, l cut, hi cut

do_rebuild(sampleFrames, gfftSize, goverlap, sampleRate, p(p_left), p(p_right), p(p_out), fDecay, iBlur, loCut, hiCut, centre);
do_rebuild(sampleFrames, gfftSize, goverlap, sampleRate, p(p_left), p(p_right), p(p_out), fDecay, iBlur, loCut, hiCut, centre, consider_phase);
}
#define DEFINE_CIRC_COPY(NAME, OUTBUFFER, INBUFFER) \
static inline int NAME(int circularsize,\
Expand Down Expand Up @@ -230,15 +236,27 @@ if(centreExtract>0) {\

// -----------------------------------------------------------------------------------------------------------------


float AKnockout::phaseToFrequency(float phase, int k,float dOversampbytwopi, float expct) {
phase-=k*expct;
phase+=PI;
//now bring into range [0, 2*pi)
long qpd = phase/(2*PI);
phase -= 2*PI*qpd;
phase+=2*PI*(phase<0);
//return to [-pi,pi)
phase-=PI;

return ((double)k + phase*dOversampbytwopi);
}
void AKnockout::do_rebuild(long numSampsToProcess, long fftFrameSize, long osamp,
float sampleRate, float *indata, float *indata2, float *outdata,
float fDecayRate, int iBlur, int loCut, int HiCut, int centreExtract) {
float fDecayRate, int iBlur, int loCut, int HiCut, int centreExtract, bool consider_phase) {
//Declare these new local variables, so the compiler knows none of them are aliased.
float* __restrict__ tInFIFO=gInFIFO;
float* __restrict__ tOutputAccum=gOutputAccum;
float* __restrict__ tFFTRealBuffer=FFTRealBuffer;
float* __restrict__ tAnaFreq=gAnaFreq;
float* __restrict__ tAnaPhase1=gAnaPhase1;
float* __restrict__ tAnaPhase2=gAnaPhase2;
float* __restrict__ tAnaMagn=gAnaMagn;
float* __restrict__ tInFIFO2=gInFIFO2;
float* __restrict__ tAnaMagn2=gAnaMagn2;
Expand All @@ -248,13 +266,12 @@ void AKnockout::do_rebuild(long numSampsToProcess, long fftFrameSize, long osamp
/* set up some handy variables */
long fftFrameSize2 = fftFrameSize/2;
long stepSize = fftFrameSize/osamp;
double dOversampbytwopi = (double)osamp/(PI*2);
double freqPerBin = sampleRate/(double)fftFrameSize;
double dFreqfactor = PI/(double)osamp/freqPerBin*2;
double dOutfactor = (double)fftFrameSize2*(double)osamp;
float dOversampbytwopi = osamp/(PI*2);
float freqPerBin = sampleRate/fftFrameSize;
float dOutfactor = fftFrameSize2*osamp;
fDecayRate=(fDecayRate>0)*(4.00001-(fDecayRate*fDecayRate*4));

double expct = 2.*PI*(double)stepSize/(double)fftFrameSize;
float expct = 2.*PI*(double)stepSize/(double)fftFrameSize;
{
int numpro=copiesremaining;
if(numSampsToProcess<copiesremaining) {
Expand Down Expand Up @@ -284,28 +301,12 @@ void AKnockout::do_rebuild(long numSampsToProcess, long fftFrameSize, long osamp
for (long k = 0; k <= fftFrameSize2; k++) {

/* de-interlace FFT buffer */
double real = gFFTworksp[k][0];
double imag = gFFTworksp[k][1];
float real = gFFTworksp[k][0];
float imag = gFFTworksp[k][1];

/* compute magnitude and phase */
tAnaMagn[k] = 2.*sqrt(real*real + imag*imag);
double phase = atan2(imag,real);

double tmp = phase-(double)k*expct;
tmp+=PI;
//now bring into range [0, 2*pi)
long qpd = tmp/(2*PI);
tmp -= 2*PI*(double)qpd;
tmp+=2*PI*(tmp<0);
//return to [-pi,pi)
tmp-=PI;
//Multiply by factor of Oversampbytwopi
tmp *= dOversampbytwopi;

/* store frequency in analysis array */

tAnaFreq[k] = ((double)k + tmp)*freqPerBin;

tAnaPhase1[k]=atan2(imag,real);
}

/* this is the processing section */
Expand All @@ -327,7 +328,8 @@ void AKnockout::do_rebuild(long numSampsToProcess, long fftFrameSize, long osamp
for (long k = loCut; k <= fftFrameSize2-HiCut; k++) {
float real=gFFTworksp2[k][0];
float imag=gFFTworksp2[k][1];
tAnaMagn2[k]=(2.*sqrt(real*real+imag*imag));
tAnaMagn2[k]=(2.*sqrt(real*real+imag*imag));
tAnaPhase2[k]=atan2(imag,real);
}


Expand All @@ -351,27 +353,33 @@ void AKnockout::do_rebuild(long numSampsToProcess, long fftFrameSize, long osamp
if (tAnaMagn2[k+m]>tDecay[k]) {
tDecay[k]=tAnaMagn2[k+m];
}
}

}
//we subtract out the part of the right channel *parallel to* the left
float diff=fabs(tAnaPhase1[k]-tAnaPhase2[k]);
diff*=consider_phase;
float coef=cosf(diff);
if(coef<0) {
coef=0;
}
/* this is the 'knockout' process */

double magn = tAnaMagn[k] - tDecay[k]; // subtract right channel magnitudes from left, with decay
magn = magn * (magn>0); // zero -ve partials
tAnaMagn[k] = tAnaMagn[k] - coef* tDecay[k]; // subtract right channel magnitudes from left, with decay
tAnaMagn[k] = tAnaMagn[k] * (tAnaMagn[k]>0); // zero -ve partials

//(Note by Jeremy): The phase has not been modified at all.
//This exactly undoes the transformation of the phase of the left
//channel which we did during the analysis phase.

/* correct the frequency - sm sprenger method */
/* correct the frequency - sm sprenger method
double tmp = tAnaFreq[k];
tmp -= (double)k*freqPerBin;
tmp *= dFreqfactor;
tmp += (double)k*expct;
tmp += (double)k*expct; */

/* get real and imag part and re-interleave */
myQT.QuickSinCos(tmp,gFFTworksp[k],gFFTworksp[k]+1);
gFFTworksp[k][0] *=magn;
gFFTworksp[k][1] *=magn;
myQT.QuickSinCos(tAnaPhase1[k],gFFTworksp[k],gFFTworksp[k]+1);
gFFTworksp[k][0] *=tAnaMagn[k];
gFFTworksp[k][1] *=tAnaMagn[k];

}

Expand Down
6 changes: 4 additions & 2 deletions kn0ck0ut6.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,15 @@ class AKnockout:public Plugin<AKnockout> {
unsigned int gfftSize;
double sampleRate;

void do_rebuild(long numSampsToProcess, long fftFrameSize, long osamp, float sampleRate, float *indata, float *indata2, float *outdata, float fDecayRate, int iBlur, int loCut, int HiCut, int centreExtract);
void do_rebuild(long numSampsToProcess, long fftFrameSize, long osamp, float sampleRate, float *indata, float *indata2, float *outdata, float fDecayRate, int iBlur, int loCut, int HiCut, int centreExtract, bool consider_phase);
void makelookup(int fftFrameSize);
inline float phaseToFrequency(float phase, int k,float dOversampbytwopi, float expct);

float* __restrict gInFIFO ;
float* __restrict gOutputAccum;
float* __restrict FFTRealBuffer;
float* __restrict gAnaFreq;
float* __restrict gAnaPhase1;
float* __restrict gAnaPhase2;
float* __restrict gAnaMagn;
float* __restrict gInFIFO2;
float* __restrict gAnaMagn2;
Expand Down
2 changes: 1 addition & 1 deletion manifest.ttl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@prefix lv2: <http://lv2plug.in/ns/lv2core#>.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.

<urn:St3pan0va.plugins.kn0ck0ut>
<urn:St3pan0va.plugins.kn0ck0ut.1>
a lv2:Plugin;
rdfs:seeAlso <kn0ck0ut.ttl>.

0 comments on commit 18cf172

Please sign in to comment.