set base sdk to 10.9
[wdl/wdl-ol.git] / WDL / simple_pitchshift2.h
bloba5bfff503964c777b9cae3ca74141feb43146721
1 #ifndef _WDL_SIMPLEPITCHSHIFT_H_
2 #define _WDL_SIMPLEPITCHSHIFT_H_
5 #include "queue.h"
7 #ifndef WDL_SIMPLEPITCHSHIFT_SAMPLETYPE
8 #define WDL_SIMPLEPITCHSHIFT_SAMPLETYPE double
9 #endif
12 // this one isnt done yet, but stretches, then (optionally) resamples
14 #ifdef WDL_SIMPLEPITCHSHIFT_PARENTCLASS
15 class WDL_SimplePitchShifter2 : public WDL_SIMPLEPITCHSHIFT_PARENTCLASS
16 #else
17 class WDL_SimplePitchShifter2
18 #endif
20 public:
21 WDL_SimplePitchShifter2()
23 m_last_nch=1;
24 m_srate=44100.0;
25 m_last_tempo=1.0;
26 m_last_shift=1.0;
27 m_qual=0;
29 Reset();
31 ~WDL_SimplePitchShifter2() { }
33 void Reset()
35 m_hadinput=0;
36 m_pspos=0.0;
37 m_pswritepos=0;
38 m_tempo_fracpos=0.0;
39 m_queue.Clear();
40 m_rsbuf.Resize(0,false);
41 m_psbuf.Resize(0,false);
44 bool IsReset()
46 return !m_queue.Available() && !m_hadinput;
51 void set_srate(double srate) { m_srate=srate; }
52 void set_nch(int nch) { if (m_last_nch!=nch) { m_queue.Clear(); m_last_nch=nch; m_tempo_fracpos=0.0; } }
53 void set_shift(double shift) { m_last_shift=shift; }
54 void set_tempo(double tempo) { m_last_tempo=tempo; }
55 void set_formant_shift(double shift)
59 WDL_SIMPLEPITCHSHIFT_SAMPLETYPE *GetBuffer(int size)
61 return m_inbuf.Resize(size*m_last_nch);
63 void BufferDone(int input_filled);
64 void FlushSamples() {}
66 static char *enumQual(int q);
67 static bool GetSizes(int qv, int *ws, int *os);
69 int GetSamples(int requested_output, WDL_SIMPLEPITCHSHIFT_SAMPLETYPE *buffer);
72 void SetQualityParameter(int parm)
74 m_qual=parm;
78 int Stretch(WDL_SIMPLEPITCHSHIFT_SAMPLETYPE *inputs, WDL_SIMPLEPITCHSHIFT_SAMPLETYPE *outputs, int nch, int length, int maxoutlen, double stretch, double srate, int ws_ms, int os_ms);
80 private:
81 int StretchBlock(WDL_SIMPLEPITCHSHIFT_SAMPLETYPE *inputs, WDL_SIMPLEPITCHSHIFT_SAMPLETYPE *outputs, int nch, int length, int maxoutlen, double stretch, int bsize, int olsize, double srate);
84 private:
85 double m_pspos WDL_FIXALIGN;
86 double m_tempo_fracpos;
87 double m_srate,m_last_tempo,m_last_shift;
89 WDL_TypedBuf<WDL_SIMPLEPITCHSHIFT_SAMPLETYPE> m_psbuf;
90 WDL_Queue m_queue;
91 WDL_TypedBuf<WDL_SIMPLEPITCHSHIFT_SAMPLETYPE> m_inbuf;
92 WDL_TypedBuf<WDL_SIMPLEPITCHSHIFT_SAMPLETYPE> m_rsbuf;
94 int m_pswritepos;
95 int m_last_nch;
96 int m_qual;
97 int m_hadinput;
102 #ifdef WDL_SIMPLEPITCHSHIFT_IMPLEMENT
103 void WDL_SimplePitchShifter2::BufferDone(int input_filled)
105 if (input_filled>0)
107 m_hadinput=1;
108 int ws,os;
109 GetSizes(m_qual,&ws,&os);
110 int max_outputlen=(int) (input_filled * m_last_shift / m_last_tempo * 1.1f + 32.0f);
112 if (fabs(m_last_shift-1.0)<0.0000000001)
114 int valid_amt = Stretch(m_inbuf.Get(),(WDL_SIMPLEPITCHSHIFT_SAMPLETYPE *)m_queue.Add(NULL,max_outputlen*m_last_nch*sizeof(WDL_SIMPLEPITCHSHIFT_SAMPLETYPE)),m_last_nch,
115 input_filled,max_outputlen,1.0/m_last_tempo,m_srate,ws,os);
117 if (valid_amt < max_outputlen)
118 m_queue.Add(NULL,(valid_amt-max_outputlen)*m_last_nch*sizeof(WDL_SIMPLEPITCHSHIFT_SAMPLETYPE));
120 else
122 int needclear=m_rsbuf.GetSize()<m_last_nch;
124 WDL_SIMPLEPITCHSHIFT_SAMPLETYPE *bufi=m_rsbuf.Resize((max_outputlen+1)*m_last_nch,false);
125 if (needclear)
126 memset(bufi,0,m_last_nch*sizeof(WDL_SIMPLEPITCHSHIFT_SAMPLETYPE));
128 int valid_amt = Stretch(m_inbuf.Get(),bufi+m_last_nch,m_last_nch,input_filled,max_outputlen,m_last_shift/m_last_tempo,m_srate,ws,os);
130 double adv=m_last_shift;
131 double fp=m_tempo_fracpos;
133 int out_max = (int) (input_filled / m_last_tempo * 1.1f + 32.0f);
135 WDL_SIMPLEPITCHSHIFT_SAMPLETYPE *bufo = (WDL_SIMPLEPITCHSHIFT_SAMPLETYPE *)m_queue.Add(NULL,out_max*m_last_nch*sizeof(WDL_SIMPLEPITCHSHIFT_SAMPLETYPE));
136 // resample bufi to bufo
137 int i,nch=m_last_nch;
138 for (i = 0; i < out_max; i ++)
140 double rdpos=floor(fp);
141 int idx=((int)rdpos);
142 if (idx>=valid_amt)
144 // un-add any missing samples
145 m_queue.Add(NULL,(i-out_max)*m_last_nch*sizeof(WDL_SIMPLEPITCHSHIFT_SAMPLETYPE));
146 break;
148 rdpos = (fp-rdpos);
149 int a;
150 idx*=nch;
151 for (a = 0; a < nch; a ++)
153 *bufo++ = bufi[idx+a]*(1.0-rdpos)+bufi[idx+nch+a]*rdpos;
155 fp += adv;
158 memcpy(bufi,bufi+m_last_nch*valid_amt,m_last_nch*sizeof(WDL_SIMPLEPITCHSHIFT_SAMPLETYPE)); // save last sample for interpolation later
160 m_tempo_fracpos=fp-floor(fp);
165 char *WDL_SimplePitchShifter2::enumQual(int q)
167 int ws,os;
168 if (!GetSizes(q,&ws,&os)) return NULL;
169 static char buf[128];
170 sprintf(buf,"%dms window, %dms fade",ws,os);
171 return buf;
174 bool WDL_SimplePitchShifter2::GetSizes(int qv, int *ws, int *os)
176 int windows[]={50,75,100,150,225,300,40,30,20,10,5,3};
177 int divs[]={2,3,5,7};
179 int wd=qv/(sizeof(divs)/sizeof(divs[0]));
180 if (wd >= sizeof(windows)/sizeof(windows[0])) wd=-1;
182 *ws=windows[wd>=0?wd:0];
183 *os = *ws / divs[qv%(sizeof(divs)/sizeof(divs[0]))];
184 if (*os<1) *os=1;
186 return wd>=0;
189 int WDL_SimplePitchShifter2::GetSamples(int requested_output, WDL_SIMPLEPITCHSHIFT_SAMPLETYPE *buffer)
191 if (!m_last_nch||requested_output<1) return 0;
193 int l=m_queue.Available()/sizeof(WDL_SIMPLEPITCHSHIFT_SAMPLETYPE)/m_last_nch;
194 if (requested_output>l) requested_output=l;
195 int sz=requested_output*sizeof(WDL_SIMPLEPITCHSHIFT_SAMPLETYPE)*m_last_nch;
196 memcpy(buffer,m_queue.Get(),sz);
197 m_queue.Advance(sz);
198 m_queue.Compact();
199 return requested_output;
202 int WDL_SimplePitchShifter2::Stretch(WDL_SIMPLEPITCHSHIFT_SAMPLETYPE *inputs, WDL_SIMPLEPITCHSHIFT_SAMPLETYPE *outputs, int nch, int length, int maxoutlen, double stretch, double srate, int ws_ms, int os_ms)
204 int bsize=(int) (ws_ms * 0.001 * srate);
205 if (bsize<16) bsize=16;
206 else if (bsize>128*1024)bsize=128*1024;
208 int olsize=(int) (os_ms * 0.001 * srate);
209 if (olsize > bsize/2) olsize=bsize/2;
210 if (olsize<1)olsize=1;
211 if (m_psbuf.GetSize() != bsize*nch)
213 memset(m_psbuf.Resize(bsize*nch,false),0,sizeof(WDL_SIMPLEPITCHSHIFT_SAMPLETYPE)*bsize*nch);
214 m_pspos=(double) (bsize/2);
215 m_pswritepos=0;
218 return StretchBlock(inputs,outputs,nch,length,maxoutlen,stretch,bsize,olsize,srate);
221 int WDL_SimplePitchShifter2::StretchBlock(WDL_SIMPLEPITCHSHIFT_SAMPLETYPE *inputs, WDL_SIMPLEPITCHSHIFT_SAMPLETYPE *outputs, int nch, int length, int maxoutlen, double stretch, int bsize, int olsize, double srate)
223 double iolsize=1.0/olsize;
225 WDL_SIMPLEPITCHSHIFT_SAMPLETYPE *psbuf=m_psbuf.Get();
227 double pspos=m_pspos;
228 int writepos=m_pswritepos;
229 int writeposnch = writepos*nch;
230 int bsizench = bsize*nch;
231 int olsizench = olsize*nch;
232 int output_used=0;
233 int i=length;
234 int chunksize = nch*sizeof(WDL_SIMPLEPITCHSHIFT_SAMPLETYPE);
235 while (i--)
237 int cnt = (int) (pspos + stretch) - (int) pspos;
238 double pspos_fracadd=stretch - cnt;
239 while (cnt-- > 0)
241 if (output_used>=maxoutlen) return maxoutlen;
242 int ipos1=(int)pspos;
244 ipos1*=nch;
246 memcpy(outputs,psbuf+ipos1,chunksize);
248 double tv=pspos;
249 if (stretch >= 1.0)
251 if (tv > writepos) tv-=bsize;
253 if (tv >= writepos-olsize && tv < writepos)
255 double tfrac=(writepos-tv)*iolsize;
256 int tmp=ipos1+olsizench;
257 if (tmp>=bsizench) tmp-=bsizench;
259 int a;
260 for(a=0;a<nch;a++) outputs[a]= outputs[a]*tfrac + (1-tfrac)*psbuf[tmp+a];
262 if (tv+stretch >= writepos)
264 pspos+=olsize;
269 else
271 if (tv<writepos) tv+=bsize;
273 if (tv >= writepos && tv < writepos+olsize)
275 double tfrac=(tv-writepos)*iolsize;
276 int tmp=ipos1+olsizench;
277 if (tmp>=bsizench) tmp -= bsizench;
278 int a;
279 for(a=0;a<nch;a++) outputs[a] = outputs[a]*tfrac + (1-tfrac)*psbuf[tmp+a];
281 // this is wrong, but blehhh?
282 if (tv+stretch < writepos+1)
284 // pspos += olsize;
286 if (tv+stretch >= writepos+olsize) pspos += olsize;
291 if ((pspos+=1) >= bsize) pspos -= bsize;
292 outputs += nch;
293 output_used++;
295 pspos += pspos_fracadd;
296 if (pspos>=bsize) pspos-=bsize;
300 memcpy(psbuf+writeposnch,inputs,chunksize);
302 writeposnch += nch;
303 if (++writepos >= bsize) writeposnch = writepos=0;
305 inputs += nch;
306 } // sample loop
307 m_pspos=pspos;
308 m_pswritepos=writepos;
309 return output_used;
313 #endif
315 #endif