gtkIOStream  1.7.0
GTK+ << C++ IOStream operators for GTK+. Now with ORBing, numerical computation, audio client and more ...
OverlapAdd.H
Go to the documentation of this file.
1 /* Copyright 2000-2018 Matt Flax <flatmax@flatmax.org>
2  This file is part of GTK+ IOStream class set
3 
4  GTK+ IOStream is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  GTK+ IOStream is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You have received a copy of the GNU General Public License
15  along with GTK+ IOStream
16 */
17 #ifndef OVERLAPADD_H_
18 #define OVERLAPADD_H_
19 
20 #ifndef _MSC_VER
21 #include "Sox.H"
22 #else
23 // Note : Microsoft doesn't understand the different between upper and lower case in file names.
24 // on microsoft, you have to manually rename Sox.H to SoxWindows.H
25 #include "SoxWindows.H"
26 #endif
27 
28 #define OVERLAP_DEFAULT 0.5
29 #define WINDOWSIZE_DEFAULT 2048
30 
31 #include "Debug.H"
32 #define OVERLAPADD_CHCNT_ERROR OVERLAPADD_ERROR_OFFSET-1
33 #define OVERLAPADD_FILESIZE_MISMATCH_ERROR OVERLAPADD_ERROR_OFFSET-2
34 #define OVERLAPADD_FACTOR_TOO_LARGE_ERROR OVERLAPADD_ERROR_OFFSET-3
35 
36 
39 class OverlapAddDebug : public SoxDebug {
40 public:
44 #ifndef NDEBUG
45  errors[OVERLAPADD_CHCNT_ERROR]=string("OverlapAdd: The requested channel is larger then the number available in the input audio file. If in the last window, this error will not be thrown. ");
46  errors[OVERLAPADD_FILESIZE_MISMATCH_ERROR]=string("OverlapAdd: The requested number of audio samples can't be read from the input audio file. ");
47 #endif
48  }
49 };
50 
59 template<class TYPE>
60 class OverlapAdd {
61  float overlapFactor;
62 
66  void init(float factor) {
67  if (factor >= 1.) {
68  cerr<<"OverlapAdd::init The specified factor "<<factor<<" is >= 1. This is not allowed : ERROR : exiting."<<endl;
70  }
71  overlapFactor=factor;
72  data.resize(WINDOWSIZE_DEFAULT,2); // ensure that the default window size is reasonable
73  }
74 
75 protected:
79  Eigen::Matrix<TYPE, Eigen::Dynamic, Eigen::Dynamic> data;
80 
81 public:
82 
84  OverlapAdd(void) {
85  init(OVERLAP_DEFAULT);
86  }
87 
91  OverlapAdd(float factor) {
92  init(factor);
93  }
94 
96  virtual ~OverlapAdd() {
97  }
98 //
99 // template<class TYPE>
100 // void loadData(const Eigen::Matrix<TYPE, Eigen::Dynamic, 1> &dataIn, uint windowSize){
101 // uint windowCnt=(int)floor((float)dataIn.rows()/(float)windowSize); // find the number of full segments
102 // uint rem=dataIn.rows()-windowCnt*windowSize; // find the remainder
103 // uint totalWindowCnt=windowCnt+((rem)?1:0);
104 // if (data.rows()!=windowSize || data.columns()!=totalWindowCnt)
105 // data.resize(windowSize,totalWindowCnt);
106 // data.block(0,0,windowSize, windowCnt)=dataIn.block(0,0,windowCnt*windowSize,1).reshape(windowSize,windowCnt);
107 // if (totalWindowCnt!=windowCnt){
108 // data.block(0,totalWindowCnt-1,windowSize, 1)=Eigen::Matrix<TYPE, Eigen::Dynamic, 1>::Zeros(windowSize,1);
109 // data.block(0,totalWindowCnt-1,rem, 1)=dataIn.block(windowSize*windowCnt, 0, rem, 1);
110 // }
111 // }
112 
121  int loadData(Sox<float> &sox, uint windowSize, uint sampleCount, int whichCh=0) {
122  int ret=NO_ERROR;
123  if ((ret=sox.getChCntIn())<0) // check whether the file is opened
124  return ret;
125  if (whichCh+1>sox.getChCntIn())
126  return OVERLAPADD_CHCNT_ERROR;
127 
128  uint N=(uint)floor((float)windowSize*overlapFactor); // the number of samples in the overlap region
129  uint M=windowSize-N; // the number of samples to load in each time the audio file is read
130 
131 // cout<<"N="<<N<<endl;
132 // cout<<"M="<<M<<endl;
133 
134  //cout<<15.-(float)sampleCount/(float)windowSize/(1.-overlapFactor)<<endl;
135  uint windowCnt=(int)(ceil((float)((float)sampleCount/(float)windowSize/(1.-overlapFactor)))); // find the number of full segments
136  cout<<"sampleCount="<<sampleCount<<endl;
137  cout<<"windowCnt="<<windowCnt<<'\t'<<15.-windowCnt<<endl;
138  cout<<"windowSize="<<windowSize<<endl;
139 
140  if (data.cols()!=windowSize || data.rows()!=windowCnt)
141  data.resize(windowSize, windowCnt);
142  data=Eigen::Matrix<TYPE, Eigen::Dynamic, Eigen::Dynamic>::Zero(windowSize, windowCnt);
143 
144  ret=NO_ERROR;
145  Eigen::Matrix<TYPE, Eigen::Dynamic, Eigen::Dynamic> audioData;
146  for (int i=0; i<windowCnt; i++) {
147  int toRead=M;
148  (i==0) ? toRead=windowSize : toRead=M;
149  if (i==windowCnt-1) toRead+=N; // if this is the last window, then try to read an extra overlap region
150  if (toRead>sampleCount+N)
151  toRead=sampleCount+N; // make sure not to read too many samples
152  //cout<<"toRead "<<toRead<<'\t';
153  if (toRead>0) {
154  int cnt=sox.read(audioData, toRead);
155  //cout<<"read "<<audioData.rows()<<endl;
156  if (cnt<0 && cnt!=SOX_EOF_OR_ERROR)
157  return SoxDebug().evaluateError(cnt);
158  if (audioData.rows()!=toRead) {
159  ret=windowCnt-toRead;
160  if (i!=windowCnt-1)
162  }
163  } else
164  audioData=Eigen::Matrix<TYPE, Eigen::Dynamic, Eigen::Dynamic>::Zero(M, whichCh+1);
165  //cout<<audioData.transpose()<<endl;
166  sampleCount-=audioData.rows(); // keep track of the number read
167  if (i==0) // The first window contains a full window of data
168  data.block(0, i, audioData.rows(), 1)=audioData.block(0, whichCh, audioData.rows(), 1); // load in the new samples to the end of the window
169  else
170  data.block(N, i, audioData.rows(), 1)=audioData.block(0, whichCh, audioData.rows(), 1); // load in the new samples to the end of the window
171  if (i<windowCnt-1) // copy the overlap to the beginning of the next window - except the last window, in which case, don't copy as there are no more subsequent windows.
172  data.block(0, i+1, N, 1)=data.block(windowSize-N, i, N, 1);
173  }
174 
175  //cout<<data.transpose()<<endl;
176  return ret;
177  }
178 
182  int unloadData(Sox<float> &sox) {
183  cout<<"OverlapAdd::unloadData"<<endl;
184  int ret=NO_ERROR;
185  if ((ret=sox.getChCntOut())<0) // check whether the file is opened
186  return ret;
187  uint windowSize=data.rows();
188  uint N=(uint)floor((float)windowSize*overlapFactor); // the number of samples in the overlap region
189  uint M=windowSize-N; // the number of samples to write out each time the audio file is written to.
190 
191 // cout<<"N="<<N<<endl;
192 // cout<<"M="<<M<<endl;
193 
194  uint windowCnt=data.cols(); // find the number of output segments
195 // cout<<"sampleCount="<<sampleCount<<endl;
196 // cout<<"windowCnt="<<windowCnt<<endl;
197 // cout<<"windowSize="<<windowSize<<endl;
198 
199  ret=NO_ERROR;
200  Eigen::Matrix<TYPE, Eigen::Dynamic, Eigen::Dynamic> audioData(M,1); // the audio data is written out N+M samples at a time
201  // create the windowing data using wndData as a temporary buffer.
202  Eigen::Array<TYPE, Eigen::Dynamic, Eigen::Dynamic> wndFront, wndBack, wndData=Eigen::Array<TYPE, 1, Eigen::Dynamic>::LinSpaced(2*N,0.,M_PI-M_PI/(2*N)).sin().square().transpose();
203  wndFront=wndData.block(0, 0, N, 1); // ramp up window
204  wndBack=wndData.block(N, 0, N, 1); // ramp down window
205  //cout<<wndFront<<"\n\n"<<wndBack<<endl;
206  for (int i=0; i<windowCnt; i++) {
207  int toWrite=M;
208  (i==0) ? toWrite=N: toWrite=M;
209 
210 // cout<<"wndData = "<<wndData<<endl;
211  if (i==0) // The first output
212  wndData=data.block(0, i, N, 1); // simply copy the first N samples to the output buffer
213  else
214  wndData+=data.block(0, i, N, 1).array()*wndFront;
215 // cout<<"wndData = "<<wndData<<endl;
216 // cout<<endl;
217  audioData.block(0, 0, N, 1)=wndData; // copy the windowed data into the first N samples
218  if (windowSize-2*N > 0) // if we are underlapping, copy any extra unwindowed data over (NOTE: windowSize-2N = M-N)
219  audioData.block(N, 0, M-N, 1)=data.block(N, i, M-N, 1); // copy the
220 
221  cout<<audioData.transpose()<<endl;
222 
223  wndData=data.block(windowSize-N, i, N, 1).array()*wndBack;
224 
225 // data.block(0, i, audioData.rows(), 1)=audioData.block(0, whichCh, audioData.rows(), 1); // load in the new samples to the end of the window
226 // else
227 // data.block(N, i, audioData.rows(), 1)=audioData.block(0, whichCh, audioData.rows(), 1); // load in the new samples to the end of the window
228 // if (i<windowCnt-1) // copy the overlap to the beginning of the next window - except the last window, in which case, don't copy as there are no more subsequent windows.
229 // data.block(0, i+1, N, 1)=data.block(windowSize-N, i, N, 1);
230 
231 // cout<<audioData<<endl;
232 
233  int cnt=sox.write(audioData);
234  //cout<<"written "<<audioData.rows()<<endl;
235  if (cnt!=audioData.rows())
236  return SoxDebug().evaluateError(cnt);
237 
238  if (i==windowCnt-1) { // last window so copy the last block out.
239  audioData=data.block(windowSize-N, i, N, 1);
240  cout<<audioData.transpose()<<endl;
241  cnt=sox.write(audioData);
242  if (cnt!=audioData.rows())
243  return SoxDebug().evaluateError(cnt);
244  }
245  }
246 
247  //cout<<data.transpose()<<endl;
248  return ret;
249  }
250 
255  return overlapFactor;
256  }
257 
261  float getWindowSize() {
262  return data.rows();
263  }
264 
268  float getWindowCount() {
269  return data.cols();
270  }
271 
274  void dump(void) {
275  cout<<data.transpose()<<endl;
276  }
277 
281  TYPE getMaxVal(){
282  //cout<<"getMaxVal "<<data.cwiseAbs().maxCoeff()<<endl;
283  return data.cwiseAbs().maxCoeff();
284  }
285 };
286 #endif // OVERLAPADD_H_
#define OVERLAPADD_FILESIZE_MISMATCH_ERROR
Error when the number of audio samples required can&#39;t be read from the input audio file...
Definition: OverlapAdd.H:33
int getChCntOut(void)
Definition: Sox.H:342
int N
#define OVERLAPADD_FACTOR_TOO_LARGE_ERROR
Error when the overlap factor is too large.
Definition: OverlapAdd.H:34
int loadData(Sox< float > &sox, uint windowSize, uint sampleCount, int whichCh=0)
Definition: OverlapAdd.H:121
void init(float factor)
Definition: OverlapAdd.H:66
float overlapFactor
Overlap factor, 0.5 for half.
Definition: OverlapAdd.H:61
TYPE getMaxVal()
Definition: OverlapAdd.H:281
#define OVERLAPADD_CHCNT_ERROR
Error when the specified channel is larger then the number of channels in the input audio file...
Definition: OverlapAdd.H:32
std::map< int, std::string > errors
This will contain a map between error numbers and descriptive std::strings for the errors...
Definition: Debug.H:115
#define NO_ERROR
There is no error.
Definition: Debug.H:33
Definition: Sox.H:95
int unloadData(Sox< float > &sox)
Definition: OverlapAdd.H:182
float getWindowCount()
Definition: OverlapAdd.H:268
unsigned int uint
Definition: Box.H:28
Definition: Sox.H:54
int getChCntIn(void)
Definition: Sox.H:333
SoxDebug()
Definition: Sox.H:58
Eigen::Matrix< TYPE, Eigen::Dynamic, Eigen::Dynamic > data
Definition: OverlapAdd.H:79
float getOverlapFactor()
Definition: OverlapAdd.H:254
void dump(void)
Definition: OverlapAdd.H:274
virtual ~OverlapAdd()
Destructor.
Definition: OverlapAdd.H:96
#define WINDOWSIZE_DEFAULT
Definition: OverlapAdd.H:29
float getWindowSize()
Definition: OverlapAdd.H:261
OverlapAdd(float factor)
Definition: OverlapAdd.H:91
OverlapAdd(void)
Empty constructor defaults to OVERLAP_DEFAULT.
Definition: OverlapAdd.H:84
#define OVERLAP_DEFAULT
Definition: OverlapAdd.H:28
#define SOX_EOF_OR_ERROR
Sox returned from a read or write either at the end of the file or in error.
Definition: Sox.H:35
virtual int write(const vector< vector< FP_TYPE_ > > &audioData)
Definition: Sox.C:203
int read(Eigen::DenseBase< Derived > &audioData, int count=0)
Definition: Sox.H:135
gtkIOStream: /tmp/gtkiostream/include/DSP/OverlapAdd.H Source File
GTK+ IOStream  Beta