gtkIOStream  1.7.0
GTK+ << C++ IOStream operators for GTK+. Now with ORBing, numerical computation, audio client and more ...
AudioMasker.C
Go to the documentation of this file.
1 /*
2  libaudiomask - hybrid simultaneous audio masking threshold evaluation library
3  Copyright (C) 2000-2018 Dr Matthew Raphael Flax
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include "AudioMask/AudioMasker.H"
20 #include <math.h>
21 //#include <strings.h>
22 
23 #if defined(_MSC_VER) || defined(__MINGW32__)
24 #define bzero(b,len) (memset((b), '\0', (len)), (void) 0)
25 #endif
26 
27 double DepUKFB::p_51_1k=4.0*1000.0/(AM_C1*(AM_C2 + 1.0));
28 
30 AudioMasker(int sampFreq, int fBankCount) : AudioMask(sampFreq, fBankCount) {
31  output=powOutput=NULL;
32  input=NULL;
33  //gtfb=NULL;
34  pfb=NULL;
35  fftData=NULL;
36  fft=NULL;
37 
38  bankCount=fBankCount;
39  std::cout<<"Bank Count "<<bankCount<<std::endl;
40  // sampleFreq=DEFAULT_SAMPLEFREQ;
42  FBMalloc();
43 }
44 
47  output=powOutput=NULL;
48  input=NULL;
49  //gtfb=NULL;
50  pfb=NULL;
51  fftData=NULL;
52  fft=NULL;
53 
55  // std::cout<<"Bank Count "<<bankCount<<std::endl;
56  //sampleFreq=DEFAULT_SAMPLEFREQ;
58  FBMalloc();
59 }
60 
62 ~AudioMasker(void) {
63  //std::cout<<"AudioMasker::~AudioMasker"<<std::endl;
64  FBDeMalloc();
65 }
66 
67 // Filter bank memory de-allocation routine
68 void AudioMasker::
69 FBDeMalloc(void) {
70  //std::cout<<"AudioMasker::FBDeMalloc"<<std::endl;
71  if (output) {
72  for (int i=0; i<bankCount; i++)
73  if (output[i]) delete [] output[i];
74  delete [] output;
75  }
76  output=NULL;
77 
78  if (powOutput) {
79  for (int i=0; i<bankCount; i++)
80  if (powOutput[i]) delete [] powOutput[i];
81  delete [] powOutput;
82  }
83  powOutput=NULL;
84 
85  if (input) delete [] input;
86  input=NULL;
87 
88  if (pfb) delete pfb;
89  pfb=NULL;
90 
91  // if (gtfb) delete gtfb;
92  //gtfb=NULL;
93 
94  if (fftData) delete fftData;
95  fftData=NULL;
96  if (fft) delete fft;
97  fft=NULL;
98 }
99 
100 // Filter bank memory allocation routine
101 void AudioMasker::
102 FBMalloc(void) {
103  FBDeMalloc(); //Ensure not malloced already
104  // Allocate the output matrix of the perceptual filters
105  if (!(output=new double*[bankCount])) {
106  std::cerr<<"AudioMasker::FBMalloc : filter bank malloc error initial"<<std::endl;
107  exit(-1);
108  } else {
109  for (int i=0; i<bankCount; i++)
110  output[i]=NULL;
111  for (int i=0; i<bankCount; i++)
112  if (!(output[i]=new double[sampleCount])) {
113  std::cerr<<"AudioMasker::FBMalloc : filter bank malloc error secondary"<<std::endl;
114  FBDeMalloc();
115  exit(-1);
116  }
117  }
118 
119  // Allocate the powOutput matrix of the perceptual filters
120  if (!(powOutput=new double*[bankCount])) {
121  std::cerr<<"AudioMasker::FBMalloc : filter bank malloc error initial"<<std::endl;
122  exit(-1);
123  } else {
124  for (int i=0; i<bankCount; i++)
125  powOutput[i]=NULL;
126  for (int i=0; i<bankCount; i++)
127  // if (!(powOutput[i]=new double[(int)ceil((double)sampleCount/2.0)])){
128  if (!(powOutput[i]=new double[(int)ceil((double)fs/2.0)])) {
129  std::cerr<<"AudioMasker::FBMalloc : filter bank malloc error secondary"<<std::endl;
130  FBDeMalloc();
131  exit(-1);
132  }
133  }
134 
135  if (!(input=new double[sampleCount])) {
136  std::cerr<<"AudioMasker::FBMalloc : input malloc error"<<std::endl;
137  FBDeMalloc();
138  exit(-1);
139  }
140 
141  // if (!(gtfb= new GTFB(DEFAULT_LOWFERQ, sampleFreq, bankCount))){
142  // std::cerr<<"AudioMasker::FBMalloc : gtfb malloc error"<<std::endl;
143  // FBDeMalloc();
144  // exit(-1);
145  //}
146 
147 
148  if (!(pfb= new DepUKFB(fs, bankCount))) {
149  std::cerr<<"AudioMasker::FBMalloc : pfb malloc error"<<std::endl;
150  FBDeMalloc();
151  exit(-1);
152  }
153 
154  // if (!(fftData=new realFFTData(sampleCount))){
155  if (!(fftData=new RealFFTData(fs))) {
156  std::cerr<<"AudioMasker::FBMalloc : fftData malloc error"<<std::endl;
157  FBDeMalloc();
158  exit(-1);
159  }
160 
161  if (!(fft=new RealFFT(fftData))) {
162  std::cerr<<"AudioMasker::FBMalloc : fft malloc error"<<std::endl;
163  FBDeMalloc();
164  exit(-1);
165  }
166 }
167 
170 void AudioMasker::
171 excite(short int *Input, int sCount) {
172  if (sCount != sampleCount)// Check for matrix re-size
173  FBDeMalloc();
174 
175  sampleCount=sCount;
176 
177  if (!output) // Check for null matrix
178  FBMalloc();
179 
180  for (int i=0; i<sCount; i++) //copy the input as double
181  input[i]=(double)Input[i];
182 
183  process(); //Do the processing
184 }
185 
186 void AudioMasker::
187 excite(double *Input, int sCount) {
188  if (sCount != sampleCount)// Check for matrix re-size
189  FBDeMalloc();
190 
191  sampleCount=sCount;
192 
193  if (!output) // Check for null matrix
194  FBMalloc();
195 
196  for (int i=0; i<sCount; i++) //copy the input as double
197  input[i]=Input[i];
198 
199  process(); //Do the processing
200 }
201 
202 double AudioMasker::
203 findThreshold(double freq) {
204  for (int i=bankCount-1; i>=0; i--) {
205  // if (freq>=gtfb->edgeFreq[i])
206  if (freq>=pfb->ef[i]) {
207  // std::cout<<i<<std::endl;
208  return mask[i];
209  }
210  }
211  std::cerr <<"AudioMasker::findThreshold : freq !=> gtfb->edgeFreq["<<bankCount-1<<"] returning 0"<<std::endl;
212  return 0;
213 }
214 
215 #include <fstream>
216 void AudioMasker::
217 process(void) {
218  bzero(fftData->in, fs*sizeof(fftw_real));//Ensure we start with a zero array
219  for (int j=0; j<sampleCount; j++) //Find pow spec of input
220  fftData->in[j]=input[j];
221  fft->fwdTransform();
224  //ofstream output("w");
225  //int halfSampleCount=(int)rint((double)sampleCount/2.0);
226  int halfFS=(int)rint(fs/2.0);
227  for (int i=0; i<bankCount; i++) { // Find power spectra and copy over
228  // for (int j=0; j<halfSampleCount;j++){
229  for (int j=0; j<halfFS; j++) {
230  // output<<(*pfb)(i,j,halfSampleCount)<<'\t';
231  // //powOutput[i][j]=fftData->power_spectrum[j]*(*pfb)(i,j,halfSampleCount);
232  powOutput[i][j]=fftData->power_spectrum[j]*(*pfb)(i,j,halfFS);
233  }
234  //output<<std::endl;
235  }
236  /*
237  ofstream outF("filter.dat");
238  for (int i=0;i<bankCount;i++){
239  for (int j=0;j<sampleCount/2;j++)
240  outF<<powOutput[i][j]<<'\t';
241  outF<<std::endl;
242  }
243  outF.close();
244  */
245 
246  // gtfb->grab(1);
247  for (int i=0; i<bankCount; i++) //Set up freq of interest (pfb centre freqs.)
248  setCFreq(i, pfb->cf[i]);
249  // setCFreq(i, gtfb->prev()->cf);
250  exciteTerhardt(powOutput, fs);// Find the masking function
251  //exciteTerhardt(powOutput, sampleCount);// Find the masking function
252  //exciteBeerends(powOutput, sampleCount);// Find the masking function
253 }
254 
255 /*
256 #include <fstream>
257 #include "../gammatone/GTSensitivity.H"
258 void AudioMasker::
259 process(void){
260  //for (int i=0;i<bankCount;i++){ //Zero the filter bank output(due to IIR nature)
261  // bzero(output1[i], sampleCount*sizeof(double));
262  // bzero(output2[i], sampleCount*sizeof(double));
263  // bzero(output[i], sampleCount*sizeof(double));
264  // }
265  LinkList<double **> outputs;
266  outputs.add(output1);
267  outputs.add(output2);
268  outputs.grab(1);
269 
270  for (int i=0;i<bankCount;i++) //Zero filter bank output(due to IIR nature)
271  bzero(outputs.current()[i], sampleCount*sizeof(double));
272  for (int i=1; i<=bankCount;i++) // Filter the input
273  gtfb->grab(i)->filter(input, &outputs.current()[i-1][0], sampleCount);
274 
275  double **last, **now;
276  for (int j=1;j<RECURSE;j++){
277  last=outputs.current();
278  now=outputs.next();
279  for (int i=0;i<bankCount;i++) //Zero filter bank output(due to IIR nature)
280  bzero(now[i], sampleCount*sizeof(double));
281  for (int i=1; i<=bankCount;i++) // Filter the input
282  gtfb->grab(i)->filter(&last[i-1][0], &now[i-1][0], sampleCount);
283  }
284 
285  for (int i=1; i<=bankCount;i++) // Filter the input - originally once
286  gtfb->grab(i)->filter(input, &output[i-1][0], sampleCount);
287 
288  // GTSensitivity gts; // sensitivity adjustement for the IIR gammatone filterbank
289 
290  for (int i=0;i<bankCount;i++){ // Find power spectra and copy over
291  for (int j=0; j<sampleCount;j++)
292  fftData->in[j]=outputs.current()[i][j];
293  //fftData->in[j]=output[i][j];
294  fft->fwdTransform();
295  fftData->compPowerSpec();
296 
297  double cf=gtfb->grab(i+1)->cf;
298  for (int j=0; j<(int)rint((double)sampleCount/2.0);j++){
299  // powOutput[i][j]=pow(10.0,gts.find(j,cf,fs)/20.0)*sqrt(fftData->power_spectrum[j]);
300  powOutput[i][j]=sqrt(fftData->power_spectrum[j]);
301  }
302 
303  //double shift=fftData->power_spectrum[fftData->minPowerBin];
305  //if (shift>10.0)
306  // for (int j=0; j<(int)rint((double)sampleCount/2.0);j++)
307  //powOutput[i][j]=sqrt(fftData->power_spectrum[j]/shift);
308  //else
309  // for (int j=0; j<(int)rint((double)sampleCount/2.0);j++)
310  //powOutput[i][j]=sqrt(fftData->power_spectrum[j]);
311  }
312 
313  ofstream outF("filter.dat");
314  for (int i=0;i<bankCount;i++){
315  for (int j=0;j<sampleCount/2;j++)
316  outF<<powOutput[i][j]<<'\t';
317  outF<<std::endl;
318  }
319  outF.close();
320 
321  gtfb->grab(1);
322  for (int i=0; i<bankCount;i++)//Set up freq of interest (pfb centre freqs.)
323  setCFreq(i, gtfb->prev()->cf);
324 
325  exciteTerhardt(powOutput, sampleCount);// Find the masking function
326  //exciteBeerends(powOutput, sampleCount);// Find the masking function
327 }
328 */
RealFFTData * fftData
The FFT data.
Definition: AudioMasker.H:107
RealFFT * fft
The FFT.
Definition: AudioMasker.H:108
void FBDeMalloc(void)
Filter bank output matrix memory de-allocation.
Definition: AudioMasker.C:69
double * cf
The filter centre frequencies.
Definition: depukfb.H:154
int bankCount
The filter bank count.
Definition: AudioMasker.H:105
void setCFreq(int which, double value)
Definition: AudioMask.H:52
double * input
Filter bank input.
Definition: AudioMasker.H:103
#define AM_C1
Definition: depukfb.H:36
double rint(double)
int fs
Sample frequency.
Definition: AudioMask.H:34
#define DEFAULT_SAMPLECOUNT
Definition: AudioMasker.H:58
void exciteTerhardt(double **filterBankOutput, int sampleCount)
Definition: AudioMask.C:59
double * ef
The filter edge frequencies.
Definition: depukfb.H:155
void FBMalloc(void)
Filter bank output matrix memory allocation.
Definition: AudioMasker.C:102
double * mask
The audio mask.
Definition: AudioMask.H:36
int compPowerSpec()
This function computes the power spectrum and returns the max bin.
Definition: RealFFTData.C:117
int sampleCount
The sample count.
Definition: AudioMasker.H:104
class RealFFTData controls and manipulates fft data
Definition: RealFFTData.H:24
static double p_51_1k
Definition: depukfb.H:50
double ** powOutput
Filter bank output power.
Definition: AudioMasker.H:102
int sqrtPowerSpec()
This function computes the square root of the power spectrum and returns the max bin.
Definition: RealFFTData.C:143
#define DEFAULT_SAMPLEFREQ
Definition: AudioMasker.H:59
double ** output
Filter bank output.
Definition: AudioMasker.H:101
fftw_real * power_spectrum
Definition: RealFFTData.H:33
#define DEFAULT_FBCOUNT
Definition: AudioMasker.H:57
double findThreshold(double freq)
Definition: AudioMasker.C:203
void fwdTransform()
Forward transform the data (in to out)
Definition: RealFFT.C:59
fftw_real * in
the input, output and power_spectrum arrays
Definition: RealFFTData.H:33
#define AM_C2
Definition: depukfb.H:37
void process(void)
Process the transformation.
Definition: AudioMasker.C:217
DepUKFB * pfb
roex filters
Definition: AudioMasker.H:116
AudioMasker(void)
Audio masker constructor - allowing specification of fs and sub-band count later. ...
Definition: AudioMasker.C:46
void excite(short int *Input, int sCount)
Definition: AudioMasker.C:171
class RealFFT controls fftw plans and executes fwd/inv transforms
Definition: RealFFT.H:24
~AudioMasker(void)
Audio masker deconstructor.
Definition: AudioMasker.C:62
#define fftw_real
use double by default
Definition: FFTCommon.H:24
gtkIOStream: /tmp/gtkiostream/src/AudioMask/AudioMasker.C Source File
GTK+ IOStream  Beta