[IPLUG/AU] add IParam::mIsMeta and related setter/getter in order to get params that...
[wdl/wdl-ol.git] / WDL / pcmfmtcvt.h
blobd498865f3230b05ad3b78ae2b4f1f777563bac62
1 /*
2 WDL - pcmfmtcvt.h
3 Copyright (C) 2005 and later, Cockos Incorporated
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
25 This file provides some simple functions for dealing with PCM audio.
26 Specifically:
27 + convert between 16/24/32 bit integer samples and flaots (only really tested on little-endian (i.e. x86) systems)
28 + mix (and optionally resample, using low quality linear interpolation) a block of floats to another.
32 #ifndef _PCMFMTCVT_H_
33 #define _PCMFMTCVT_H_
36 #include "wdltypes.h"
38 #ifndef PCMFMTCVT_DBL_TYPE
39 #define PCMFMTCVT_DBL_TYPE double
40 #endif
42 static inline int float2int(PCMFMTCVT_DBL_TYPE d)
44 return (int) d;
45 // int tmp;
46 // __asm__ __volatile__ ("fistpl %0" : "=m" (tmp) : "t" (d) : "st") ;
47 // return tmp;
51 #define float_TO_INT16(out,in) \
52 if ((in)<0.0) { if ((in) <= -1.0) (out) = -32768; else (out) = (short) (float2int(((in) * 32768.0)-0.5)); } \
53 else { if ((in) >= (32766.5f/32768.0f)) (out) = 32767; else (out) = (short) float2int((in) * 32768.0 + 0.5); }
55 #define INT16_TO_float(out,in) { (out) = (float)(((double)in)/32768.0); }
57 #define double_TO_INT16(out,in) \
58 if ((in)<0.0) { if ((in) <= -1.0) (out) = -32768; else (out) = (short) (float2int(((in) * 32768.0)-0.5)); } \
59 else { if ((in) >= (32766.5/32768.0)) (out) = 32767; else (out) = (short) float2int((in) * 32768.0 + 0.5); }
61 #define INT16_TO_double(out,in) { (out) = (((PCMFMTCVT_DBL_TYPE)in)/32768.0); }
64 static inline void i32_to_float(int i32, float *p)
66 *p = (float) ((((double) i32)) * (1.0 / (2147483648.0)));
69 static inline void float_to_i32(float *vv, int *i32)
71 float v = *vv;
72 if (v < 0.0)
74 if (v < -1.0) *i32 = 0x80000000;
75 else *i32=float2int(v*2147483648.0-0.5);
77 else
79 if (v >= (2147483646.5f/2147483648.0f)) *i32 = 0x7FFFFFFF;
80 else *i32=float2int(v*2147483648.0+0.5);
85 static inline void i32_to_double(int i32, PCMFMTCVT_DBL_TYPE *p)
87 *p = ((((PCMFMTCVT_DBL_TYPE) i32)) * (1.0 / (2147483648.0)));
90 static inline void double_to_i32(PCMFMTCVT_DBL_TYPE *vv, int *i32)
92 PCMFMTCVT_DBL_TYPE v = *vv;
93 if (v < 0.0)
95 if (v < -1.0) *i32 = 0x80000000;
96 else *i32=float2int(v*2147483648.0-0.5);
98 else
100 if (v >= (2147483646.5/2147483648.0)) *i32 = 0x7FFFFFFF;
101 else *i32=float2int(v*2147483648.0+0.5);
107 static inline void i24_to_float(unsigned char *i24, float *p)
109 int val=(i24[0]) | (i24[1]<<8) | (i24[2]<<16);
110 if (val&0x800000)
112 val|=0xFF000000;
113 *p = (float) ((((double) val)) * (1.0 / (8388608.0)));
115 else
117 val&=0xFFFFFF;
118 *p = (float) ((((double) val)) * (1.0 / (8388608.0)));
123 static inline void float_to_i24(float *vv, unsigned char *i24)
125 float v = *vv;
126 if (v < 0.0)
128 if (v < -1.0)
130 i24[0]=i24[1]=0x00;
131 i24[2]=0x80;
133 else
135 int i=float2int(v*8388608.0-0.5);
136 i24[0]=(i)&0xff;
137 i24[1]=(i>>8)&0xff;
138 i24[2]=(i>>16)&0xff;
141 else
143 if (v >= (8388606.5f/8388608.0f))
145 i24[0]=i24[1]=0xff;
146 i24[2]=0x7f;
148 else
151 int i=float2int(v*8388608.0+0.5);
152 i24[0]=(i)&0xff;
153 i24[1]=(i>>8)&0xff;
154 i24[2]=(i>>16)&0xff;
160 static inline void i24_to_double(unsigned char *i24, PCMFMTCVT_DBL_TYPE *p)
162 int val=(i24[0]) | (i24[1]<<8) | (i24[2]<<16);
163 if (val&0x800000)
165 val|=0xFF000000;
166 *p = ((((PCMFMTCVT_DBL_TYPE) val)) * (1.0 / (8388608.0)));
168 else
170 val&=0xFFFFFF;
171 *p = ((((PCMFMTCVT_DBL_TYPE) val)) * (1.0 / (8388608.0)));
176 static inline void double_to_i24(PCMFMTCVT_DBL_TYPE *vv, unsigned char *i24)
178 PCMFMTCVT_DBL_TYPE v = *vv;
179 if (v < 0.0)
181 if (v < -1.0)
183 i24[0]=i24[1]=0x00;
184 i24[2]=0x80;
186 else
188 int i=float2int(v*8388608.0-0.5);
189 i24[0]=(i)&0xff;
190 i24[1]=(i>>8)&0xff;
191 i24[2]=(i>>16)&0xff;
194 else
196 if (v >= (8388606.5/8388608.0))
198 i24[0]=i24[1]=0xff;
199 i24[2]=0x7f;
201 else
204 int i=float2int(v*8388608.0+0.5);
205 i24[0]=(i)&0xff;
206 i24[1]=(i>>8)&0xff;
207 i24[2]=(i>>16)&0xff;
212 static void pcmToFloats(void *src, int items, int bps, int src_spacing, float *dest, int dest_spacing)
214 if (bps == 32)
216 int *i1=(int *)src;
217 while (items--)
219 i32_to_float(*i1,dest);
220 i1+=src_spacing;
221 dest+=dest_spacing;
224 else if (bps == 24)
226 unsigned char *i1=(unsigned char *)src;
227 int adv=3*src_spacing;
228 while (items--)
230 i24_to_float(i1,dest);
231 dest+=dest_spacing;
232 i1+=adv;
235 else if (bps == 16)
237 short *i1=(short *)src;
238 while (items--)
240 INT16_TO_float(*dest,*i1);
241 i1+=src_spacing;
242 dest+=dest_spacing;
247 static void floatsToPcm(float *src, int src_spacing, int items, void *dest, int bps, int dest_spacing)
249 if (bps==32)
251 int *o1=(int*)dest;
252 while (items--)
254 float_to_i32(src,o1);
255 src+=src_spacing;
256 o1+=dest_spacing;
259 else if (bps == 24)
261 unsigned char *o1=(unsigned char*)dest;
262 int adv=dest_spacing*3;
263 while (items--)
265 float_to_i24(src,o1);
266 src+=src_spacing;
267 o1+=adv;
270 else if (bps==16)
272 short *o1=(short*)dest;
273 while (items--)
275 float_TO_INT16(*o1,*src);
276 src+=src_spacing;
277 o1+=dest_spacing;
283 static void pcmToDoubles(void *src, int items, int bps, int src_spacing, PCMFMTCVT_DBL_TYPE *dest, int dest_spacing, int byteadvancefor24=0)
285 if (bps == 32)
287 int *i1=(int *)src;
288 while (items--)
290 i32_to_double(*i1,dest);
291 i1+=src_spacing;
292 dest+=dest_spacing;
295 else if (bps == 24)
297 unsigned char *i1=(unsigned char *)src;
298 int adv=3*src_spacing+byteadvancefor24;
299 while (items--)
301 i24_to_double(i1,dest);
302 dest+=dest_spacing;
303 i1+=adv;
306 else if (bps == 16)
308 short *i1=(short *)src;
309 while (items--)
311 INT16_TO_double(*dest,*i1);
312 i1+=src_spacing;
313 dest+=dest_spacing;
318 static void doublesToPcm(PCMFMTCVT_DBL_TYPE *src, int src_spacing, int items, void *dest, int bps, int dest_spacing, int byteadvancefor24=0)
320 if (bps==32)
322 int *o1=(int*)dest;
323 while (items--)
325 double_to_i32(src,o1);
326 src+=src_spacing;
327 o1+=dest_spacing;
330 else if (bps == 24)
332 unsigned char *o1=(unsigned char*)dest;
333 int adv=dest_spacing*3+byteadvancefor24;
334 while (items--)
336 double_to_i24(src,o1);
337 src+=src_spacing;
338 o1+=adv;
341 else if (bps==16)
343 short *o1=(short*)dest;
344 while (items--)
346 double_TO_INT16(*o1,*src);
347 src+=src_spacing;
348 o1+=dest_spacing;
353 static int resampleLengthNeeded(int src_srate, int dest_srate, int dest_len, double *state)
355 // safety
356 if (!src_srate) src_srate=48000;
357 if (!dest_srate) dest_srate=48000;
358 if (src_srate == dest_srate) return dest_len;
359 return (int) (((double)src_srate*(double)dest_len/(double)dest_srate)+*state);
363 static void mixFloats(float *src, int src_srate, int src_nch, // lengths are sample pairs
364 float *dest, int dest_srate, int dest_nch,
365 int dest_len, float vol, float pan, double *state)
367 // fucko: better resampling, this is shite
368 int x;
369 if (pan < -1.0f) pan=-1.0f;
370 else if (pan > 1.0f) pan=1.0f;
371 if (vol > 4.0f) vol=4.0f;
372 if (vol < 0.0f) vol=0.0f;
374 if (!src_srate) src_srate=48000;
375 if (!dest_srate) dest_srate=48000;
377 double vol1=vol,vol2=vol;
378 if (dest_nch == 2)
380 if (pan < 0.0f) vol2 *= 1.0f+pan;
381 else if (pan > 0.0f) vol1 *= 1.0f-pan;
384 double rspos=*state;
385 double drspos = (double)src_srate/(double)dest_srate;
387 for (x = 0; x < dest_len; x ++)
390 double ls;
391 double rs;
392 if (src_srate != dest_srate)
394 int ipos = (int)rspos;
395 double fracpos=rspos-ipos;
396 if (src_nch == 2)
398 ipos+=ipos;
399 ls=src[ipos]*(1.0-fracpos) + src[ipos+2]*fracpos;
400 rs=src[ipos+1]*(1.0-fracpos) + src[ipos+3]*fracpos;
402 else
404 rs=ls=src[ipos]*(1.0-fracpos) + src[ipos+1]*fracpos;
407 else
409 if (src_nch == 2)
411 int t=x+x;
412 ls=src[t];
413 rs=src[t+1];
415 else
417 rs=ls=src[x];
421 rspos+=drspos;
423 ls *= vol1;
424 if (ls > 1.0) ls=1.0;
425 else if (ls<-1.0) ls=-1.0;
427 if (dest_nch == 2)
429 rs *= vol2;
430 if (rs > 1.0) rs=1.0;
431 else if (rs<-1.0) rs=-1.0;
433 dest[0]+=(float) ls;
434 dest[1]+=(float) rs;
435 dest+=2;
437 else
439 dest[0]+=(float) ls;
440 dest++;
443 *state = rspos - (int)rspos;
446 static void mixFloatsNIOutput(float *src, int src_srate, int src_nch, // lengths are sample pairs. input is interleaved samples, output not
447 float **dest, int dest_srate, int dest_nch,
448 int dest_len, float vol, float pan, double *state)
450 // fucko: better resampling, this is shite
451 int x;
452 if (pan < -1.0f) pan=-1.0f;
453 else if (pan > 1.0f) pan=1.0f;
454 if (vol > 4.0f) vol=4.0f;
455 if (vol < 0.0f) vol=0.0f;
457 if (!src_srate) src_srate=48000;
458 if (!dest_srate) dest_srate=48000;
460 double vol1=vol,vol2=vol;
461 float *dest1=dest[0];
462 float *dest2=NULL;
463 if (dest_nch > 1)
465 dest2=dest[1];
466 if (pan < 0.0f) vol2 *= 1.0f+pan;
467 else if (pan > 0.0f) vol1 *= 1.0f-pan;
471 double rspos=*state;
472 double drspos = 1.0;
473 if (src_srate != dest_srate) drspos=(double)src_srate/(double)dest_srate;
475 for (x = 0; x < dest_len; x ++)
477 double ls,rs;
478 if (src_srate != dest_srate)
480 int ipos = (int)rspos;
481 double fracpos=rspos-ipos;
482 if (src_nch == 2)
484 ipos+=ipos;
485 ls=src[ipos]*(1.0-fracpos) + src[ipos+2]*fracpos;
486 rs=src[ipos+1]*(1.0-fracpos) + src[ipos+3]*fracpos;
488 else
490 rs=ls=src[ipos]*(1.0-fracpos) + src[ipos+1]*fracpos;
492 rspos+=drspos;
495 else
497 if (src_nch == 2)
499 int t=x+x;
500 ls=src[t];
501 rs=src[t+1];
503 else
505 rs=ls=src[x];
509 ls *= vol1;
510 if (ls > 1.0) ls=1.0;
511 else if (ls<-1.0) ls=-1.0;
513 *dest1++ +=(float) ls;
515 if (dest_nch > 1)
517 rs *= vol2;
518 if (rs > 1.0) rs=1.0;
519 else if (rs<-1.0) rs=-1.0;
521 *dest2++ += (float) rs;
524 *state = rspos - (int)rspos;
528 #endif //_PCMFMTCVT_H_