1
/* ------------------------------------------------------------------
3
libofa -- the Open Fingerprint Architecture library
5
Copyright (C) 2006 MusicIP Corporation
8
-------------------------------------------------------------------*/
9
// FILE: "signal_op.cpp"
10
// MODULE: Implementation for class Signal_op
12
// DATE CREATED: 1/12/06
16
#include "signal_op.h"
17
#include "AFLIB/aflibConverter.h"
21
Signal_op::Signal_op()
31
Signal_op::~Signal_op()
39
Signal_op::Load(short* samples, long size, int sRate, bool stereo)
43
NumChannels = stereo ? 2 : 1;
45
NumBlocks = BufSize / NumChannels;
50
// CutSignal deletes samples from the sample buffer
52
Signal_op::CutSignal(double start, double dur)
55
short* samples = Data;
57
long startS = (long)(start * Rate / 1000.0);
58
long stopS = (long)(startS + dur * Rate / 1000.0);
60
NumBlocks = (stopS-startS);
62
throw OnePrintError("Programming error: CutSignal");
64
BufSize = NumBlocks * NumChannels;
65
short* tmpBuf = new short[BufSize];
67
startS *= NumChannels;
71
for (i=startS, n=0; i<stopS; i++, n++)
72
tmpBuf[n] = samples[i];
81
Signal_op::PrepareStereo(long newRate, double silTh)
84
if (GetCrossCorrelation() < -0.98)
89
PrepareMono(newRate, silTh);
94
Signal_op::PrepareMono(long newRate, double silTh)
96
RemoveSilence(silTh, silTh);
100
// Check for rate conversion
102
ConvertSampleRate(newRate);
108
// Add left and right channels
110
void Signal_op::LPlusR()
112
if (NumChannels != 2)
114
short* tmpBuf = new short[NumBlocks];
115
short* samples = Data;
116
for (long i=0, n=0; i<NumBlocks*2; i+=2, n++)
118
int sum = samples[i] + samples[i+1];
130
// Subtract left and right channels.
132
void Signal_op::LMinusR()
134
if (NumChannels != 2)
136
short * tmpBuf = new short[NumBlocks];
137
short * samples = Data;
138
for (long i=0, n=0; i<NumBlocks*2; i+=2, n++)
140
int sum = samples[i] - samples[i+1];
153
Signal_op::RemoveSilence(double startTh, double endTh)
157
short* samples = Data;
159
// Truncate leading and trailing silence
160
long stop = NumBlocks;
161
int silBlock = (int) (Rate*2.2/400);
166
// Front silence removal
169
sum += abs(samples[start]);
171
if (count >= silBlock)
173
double av = (double)sum/silBlock;
185
if (start < 0) start = 0;
187
// Back silence removal
192
sum += abs(samples[stop-1]);
194
if (count >= silBlock)
196
double av = (double)sum/silBlock;
208
if (stop > NumBlocks) stop = NumBlocks;
211
throw OnePrintError("Signal has silence only", SILENCEONLY);
213
NumBlocks = (stop-start);
215
throw OnePrintError("Signal is corrupt");
218
short* tmpBuf = new short[BufSize];
220
// Copy to new buffer
221
for (i=start, n=0; i<stop; i++, n++)
222
tmpBuf[n] = samples[i];
231
Signal_op::RemoveDCOffset()
233
long len = GetLength();
238
double ramp = 1000.0; // Ramp-up time (ms)
239
long lim = (long) ((ramp/1000)*GetRate());
240
double k = 1000.0/(GetRate()*ramp);
241
double maxP = 0, maxN = 0;
242
for (long n=1; n<=len; n++)
244
yn = yn1 + k*((double)x[n-1] - yn1);
257
double dcOffset = sum/(double)cnt;
259
// Remove if greater than this
260
if (fabs(dcOffset) > 15) // otherwise don't bother
262
// Check to se if we have to "denormalize" to make sure there's headroom for the DC removal
263
double factorP=0, factorN=0, factor=0;
264
if (maxP - dcOffset > MaxSample)
265
factorP = ((double)MaxSample - dcOffset) / maxP;
266
if (maxN - dcOffset < MinSample)
267
factorN = ((double)MinSample + dcOffset) / maxN;
268
// only one can apply
271
else if (factorN > 0)
274
for (long i=0; i<len; i++)
276
double sample = (double)x[i];
282
x[i] = (short) floor(sample + 0.5);
284
x[i] = (short) ceil(sample - 0.5);
291
Signal_op::Normalize()
293
short* samples = Data;
299
for (i=0; i<NumBlocks; i++)
301
if (abs(samples[i]) > max)
302
max = abs(samples[i]);
305
if (max >= MaxSample) {
308
factor = MaxSample / (double) max;
309
for (i=0; i<NumBlocks; i++)
311
double tmp = (double)samples[i] * factor;
314
samples[i] = (short) floor(tmp + 0.5);
316
samples[i] = (short) ceil(tmp - 0.5);
325
Signal_op::ConvertSampleRate(long targetSR)
327
if (NumChannels > 1) return;
329
aflibConverter srConv(true, false, true); // Large filter with coefficients interpolation
331
double factor = (double)targetSR/(double)Rate;
333
long tmpSize = (long) (BufSize * factor + 2);
334
short* tmpBuf = new short[tmpSize];
336
srConv.initialize(factor, 1);
338
int inCount = BufSize;
339
int outCount = (int) (BufSize * factor);
341
outRet = srConv.resample(inCount, outCount, GetBuffer(), tmpBuf);
348
NumBlocks = BufSize = outRet;
353
Signal_op::GetCrossCorrelation()
355
// Cross Channel Correlation - stereo signals only
357
double C12 = 0, C11 = 0, C22 = 0;
358
short* samples = Data;
360
for (k=0; k<NumBlocks*2; k+=2)
362
C12 += samples[k]*samples[k+1];
363
C11 += samples[k]*samples[k];
364
C22 += samples[k+1]*samples[k+1];
367
return C12/sqrt(C11*C22);