1 #ifndef _WDL_SIMPLEPITCHSHIFT_H_
2 #define _WDL_SIMPLEPITCHSHIFT_H_
7 #ifndef WDL_SIMPLEPITCHSHIFT_SAMPLETYPE
8 #define WDL_SIMPLEPITCHSHIFT_SAMPLETYPE double
12 // this one isnt done yet, but stretches, then (optionally) resamples
14 #ifdef WDL_SIMPLEPITCHSHIFT_PARENTCLASS
15 class WDL_SimplePitchShifter2
: public WDL_SIMPLEPITCHSHIFT_PARENTCLASS
17 class WDL_SimplePitchShifter2
21 WDL_SimplePitchShifter2()
31 ~WDL_SimplePitchShifter2() { }
40 m_rsbuf
.Resize(0,false);
41 m_psbuf
.Resize(0,false);
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
)
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
);
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
);
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
;
91 WDL_TypedBuf
<WDL_SIMPLEPITCHSHIFT_SAMPLETYPE
> m_inbuf
;
92 WDL_TypedBuf
<WDL_SIMPLEPITCHSHIFT_SAMPLETYPE
> m_rsbuf
;
102 #ifdef WDL_SIMPLEPITCHSHIFT_IMPLEMENT
103 void WDL_SimplePitchShifter2::BufferDone(int input_filled
)
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
));
122 int needclear
=m_rsbuf
.GetSize()<m_last_nch
;
124 WDL_SIMPLEPITCHSHIFT_SAMPLETYPE
*bufi
=m_rsbuf
.Resize((max_outputlen
+1)*m_last_nch
,false);
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
);
144 // un-add any missing samples
145 m_queue
.Add(NULL
,(i
-out_max
)*m_last_nch
*sizeof(WDL_SIMPLEPITCHSHIFT_SAMPLETYPE
));
151 for (a
= 0; a
< nch
; a
++)
153 *bufo
++ = bufi
[idx
+a
]*(1.0-rdpos
)+bufi
[idx
+nch
+a
]*rdpos
;
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
)
168 if (!GetSizes(q
,&ws
,&os
)) return NULL
;
169 static char buf
[128];
170 sprintf(buf
,"%dms window, %dms fade",ws
,os
);
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]))];
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
);
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);
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
;
234 int chunksize
= nch
*sizeof(WDL_SIMPLEPITCHSHIFT_SAMPLETYPE
);
237 int cnt
= (int) (pspos
+ stretch
) - (int) pspos
;
238 double pspos_fracadd
=stretch
- cnt
;
241 if (output_used
>=maxoutlen
) return maxoutlen
;
242 int ipos1
=(int)pspos
;
246 memcpy(outputs
,psbuf
+ipos1
,chunksize
);
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
;
260 for(a
=0;a
<nch
;a
++) outputs
[a
]= outputs
[a
]*tfrac
+ (1-tfrac
)*psbuf
[tmp
+a
];
262 if (tv
+stretch
>= writepos
)
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
;
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)
286 if (tv
+stretch
>= writepos
+olsize
) pspos
+= olsize
;
291 if ((pspos
+=1) >= bsize
) pspos
-= bsize
;
295 pspos
+= pspos_fracadd
;
296 if (pspos
>=bsize
) pspos
-=bsize
;
300 memcpy(psbuf
+writeposnch
,inputs
,chunksize
);
303 if (++writepos
>= bsize
) writeposnch
= writepos
=0;
308 m_pswritepos
=writepos
;