gtkIOStream  1.7.0
GTK+ << C++ IOStream operators for GTK+. Now with ORBing, numerical computation, audio client and more ...
WSOLA.C
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 #include "WSOLA.H"
18 
19 #include <stdlib.h>
20 
22  fs=FS_DEFAULT; // set the sample rate to default
23  init();
25 }
26 
27 WSOLA::WSOLA(int chCnt){
28  fs=FS_DEFAULT; // set the sample rate to default
29  init();
30  reset(chCnt);
31 }
32 
34 }
35 
36 void WSOLA::init(void){
37  N=(int)(2.*floor((fs*TAU)/2.)); // audio samples in one window - an even number
38  NO2=N/2; // half the window size
39  M=M_DEFAULT; // vectors of NO2 audio samples
40  if ((M*N)%2)
42 }
43 
44 void WSOLA::OLAWnd(void) {
45  int chCnt=buffer.rows();
46  wnd.resize(chCnt,N);
47  wnd.row(0)=Array<FP_TYPE, 1, Dynamic>::LinSpaced(N,0.,M_PI-M_PI/N).sin().square();
48  for (int i=1; i<chCnt; i++)
49  wnd.row(i)=wnd.row(0);
50 // cout<<"wnd "<<endl;
51 // cout<<wnd<<endl;
52 // cout<<"wnd overlap check"<<endl;
53 // cout<<wnd.block(0,NO2,1,NO2)+wnd.block(0,0,1,NO2)<<endl;
54 }
55 
56 template<typename Derived>
57 int WSOLA::findSimilarityInBuffer(const DenseBase<Derived> &buffer) {
58 // cout<<nextOutput<<endl;
59 // cout<<buffer.block(0,0,1,N)*wnd<<endl;
60 // cout<<"similarity "<<nextOutput-buffer.block(0,0,1,N)*wnd<<endl;
61 
62  FP_TYPE bestMeasure=3e8;
63  int bestI=0;
64 // for (int i=0; i<M; i++) {
65 // FP_TYPE measureTest=findSimilarity(buffer.block(0,i*NO2,1,N));
66  for (int i=0; i<(M-1)*NO2; i++) {
67  FP_TYPE measureTest=findSimilarity(buffer.block(0,i,buffer.rows(),N));
68 // cout<<"measureTest="<<measureTest<<" bestMeasure "<<bestMeasure<<endl;
69  if (measureTest<bestMeasure) {
70  bestMeasure=measureTest;
71  bestI=i;
72  }
73 // cout<<"measureTest="<<measureTest<<" bestMeasure "<<bestMeasure<<endl;
74  }
75 // cout<<"bestI "<<bestI<<endl;
76 // cout<<"similarity "<<nextOutput-buffer.block(0,bestI*NO2,1,N)*wnd<<endl;
77 
78  return bestI;
79 }
80 
81 //template<typename Derived>
82 //int WSOLA::findSimilarityInBufferDFT(const DenseBase<Derived> &buffer) {
83 // Array<FFT<FP_TYPE>::Complex, Dynamic, 1> WND(buffer.cols(),1);
84 // Array<FFT<FP_TYPE>::Complex, Dynamic, 1> wndPadded(buffer.cols(),1);
85 // wndPadded.block(
86 // wnd.rows(),1,wnd.cols(),1)
87 // fft.fwd(chirp.col(0).data(), WND.col(0).data(),M);
88 //
89 // FP_TYPE bestMeasure=3e8;
90 // int bestI=0;
91 // for (int i=0; i<(M-1)*NO2; i++) {
92 // FP_TYPE measureTest=findSimilarity(buffer.block(0,i,1,N));
93 // if (measureTest<bestMeasure) {
94 // bestMeasure=measureTest;
95 // bestI=i;
96 // }
97 // }
98 //
99 // return bestI;
100 //}
101 
103  int chCnt=buffer.rows();
104  if (output.cols()!=0) { // not the first run
105  output.block(0,0,chCnt,NO2)=output.block(0,NO2,chCnt,NO2); // shift the output NO2 on
106  m=findSimilarityInBuffer(buffer); // find the most similar index in the buffer
107 // m=findSimilarityInBufferDFT(buffer); // find the most similar index in the buffer
108 // cout<<"most similar m="<<m<<endl;
109  } else { // this is the first run ... need to inverse window the first half block and pad with zeros
110  output=buffer.block(0,m*NO2,chCnt,N); // the output = the first buffer
111 // cout<<"wnd \n"<<wnd<<endl;
112 // cout<<"output \n"<<output<<endl;
113  output.block(0,0,chCnt,NO2)*=wnd.block(0,NO2,chCnt,NO2); // the first half of the output is inverse windowed
114 // cout<<"output \n"<<output<<endl;
115 // cout<<"output \n"<<output<<endl;
116  }
117  output.block(0,NO2,chCnt,NO2)=Matrix<FP_TYPE, Dynamic, Dynamic>::Zero(chCnt,NO2); // the second half is zero padded
118 
119  // We are now pointing at the most similar vector ...
120  // use nextOutput as a temporary buffer to overlap add the output
121  //nextOutput=buffer.block(0,m*NO2,1,N);
122  nextOutput=buffer.block(0,m,chCnt,N);
123  nextOutput*=wnd;
124  output+=nextOutput; // overlap add
125 // cout<<"output \n"<<output<<endl;
126 
127  // Next output is meant to be the next row
128 // nextOutput=buffer.block(0,(m+1)*NO2,1,N);
129  nextOutput=buffer.block(0,m+NO2,chCnt,N);
130 // cout<<"nextOutput \n"<<nextOutput<<endl;
131  nextOutput*=wnd; // window the next block to match against
132 // cout<<"nextOutput \n"<<nextOutput<<endl;
133 }
134 
135 void WSOLA::reset(int chCnt){
137  buffer=Matrix<FP_TYPE, Dynamic, Dynamic>::Zero(chCnt,inputSamplesRequired);
138  m=0;
139  rem=0.;
140  output.resize(0,0); // this indicates to the inner algporithm that this will be the first run.
141  OLAWnd(); // prepare the window
142  input.resize(chCnt, inputSamplesRequired);
143 }
144 
145 int WSOLA::loadInput(int n, int m, FP_TYPE val){
146  if (n>input.rows()-1 || n<0)
148  if (m>input.cols()-1 || m<0)
150  input(n,m)=val;
151  return 0;
152 }
153 
155  if (n>output.rows()-1 || n<0)
157  if (m>output.cols()-1 || m<0)
159  return output(n,m);
160 }
161 
162 void WSOLA::setFS(float fsIn){
163  fs=fsIn;
164  init();
165  reset(buffer.rows());
166 }
167 
168 
169 #ifdef HAVE_EMSCRIPTEN
170 EMSCRIPTEN_BINDINGS(WSOLA_ex) {
171  emscripten::class_<WSOLA>("WSOLA")
172  .constructor()
173  .constructor<int>()
174  .function("loadInput", &WSOLA::loadInput)
175  .function("unloadOutput", &WSOLA::unloadOutput)
176  .function("getSamplesRequired", &WSOLA::getSamplesRequired)
177  .function("process", &WSOLA::processOurInput)
178  .function("getOutputSize", &WSOLA::getOutputSize)
179  .function("setFS", &WSOLA::setFS)
180 // .function("getFS", &EQ::getFS)
181 // .property("x", &MyClass::getX, &MyClass::setX)
182 // .class_function("getStringFromInstance", &MyClass::getStringFromInstance)
183  ;
184 }
185 #endif
float FP_TYPE
Definition: audioMasker.C:25
int inputSamplesRequired
The number of audio samples required for the next call to process.
Definition: WSOLA.H:134
int NO2
Half the window size.
Definition: WSOLA.H:87
int N
The size of the window.
Definition: WSOLA.H:86
#define WSOLA_COLS_ERROR
Occurs when trying to access a col > the input or output Array cols.
Definition: WSOLA.H:43
virtual int evaluateError(int errorNum)
Definition: Debug.H:132
Array< FP_TYPE, Dynamic, Dynamic > nextOutput
The output vector to search for, each channel per row.
Definition: WSOLA.H:96
double rem
The remainder fraction of a sample to remember for next time (can&#39;t move on by fractions of a sample)...
Definition: WSOLA.H:90
int m
The current row index into the buffer.
Definition: WSOLA.H:89
void processInner(void)
Definition: WSOLA.C:102
#define FS_DEFAULT
Hz the sample rate.
Definition: WSOLA.H:69
virtual ~WSOLA()
Destructor.
Definition: WSOLA.C:33
void OLAWnd(void)
Generate the overlap add window based on the window size N.
Definition: WSOLA.C:44
void init(void)
Definition: WSOLA.C:36
#define WSOLA_ROWS_ERROR
Occurs when trying to access a row > the input or output Array rows.
Definition: WSOLA.H:42
#define TAU
ms The window size
Definition: WSOLA.H:70
FP_TYPE unloadOutput(int n, int m)
Definition: WSOLA.C:154
void reset(int chCnt)
Definition: WSOLA.C:135
#define DEFAULT_CH_CNT
The default number of channels to use.
Definition: WSOLA.H:72
Array< FP_TYPE, Dynamic, Dynamic > wnd
The overlap add window.
Definition: WSOLA.H:94
FP_TYPE findSimilarity(const ArrayBase< Derived > &outputIn)
Definition: WSOLA.H:112
int getSamplesRequired(void)
Definition: WSOLA.H:214
#define M_DEFAULT
The default number of buffers to search.
Definition: WSOLA.H:74
Array< FP_TYPE, Dynamic, Dynamic > input
The input vector, each row is a channel.
Definition: WSOLA.H:142
Array< FP_TYPE, Dynamic, Dynamic > output
The output vector, each row is a channel.
Definition: WSOLA.H:141
Definition: Array.H:24
void setFS(float fsIn)
Definition: WSOLA.C:162
#define WSOLA_MOD2_ERROR
< Provided by GTKIOStream on sf.net
Definition: WSOLA.H:40
int loadInput(int n, int m, FP_TYPE val)
Definition: WSOLA.C:145
int findSimilarityInBuffer(const DenseBase< Derived > &buffer)
Definition: WSOLA.C:57
int getMaxInputSamplesRequired(void)
Definition: WSOLA.H:207
int M
The number of windows in the search buffer.
Definition: WSOLA.H:88
WSOLA()
Definition: WSOLA.C:21
int getOutputSize(void)
Definition: WSOLA.H:220
float fs
The sample rate in Hz.
Definition: WSOLA.H:84
Array< FP_TYPE, Dynamic, Dynamic > buffer
The buffer of audio, each channel on its own row.
Definition: WSOLA.H:92
gtkIOStream: /tmp/gtkiostream/src/WSOLA.C Source File
GTK+ IOStream  Beta