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.
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.
38 #ifndef PCMFMTCVT_DBL_TYPE
39 #define PCMFMTCVT_DBL_TYPE double
42 static inline int float2int(PCMFMTCVT_DBL_TYPE d
)
46 // __asm__ __volatile__ ("fistpl %0" : "=m" (tmp) : "t" (d) : "st") ;
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
)
74 if (v
< -1.0) *i32
= 0x80000000;
75 else *i32
=float2int(v
*2147483648.0-0.5);
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
;
95 if (v
< -1.0) *i32
= 0x80000000;
96 else *i32
=float2int(v
*2147483648.0-0.5);
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);
113 *p
= (float) ((((double) val
)) * (1.0 / (8388608.0)));
118 *p
= (float) ((((double) val
)) * (1.0 / (8388608.0)));
123 static inline void float_to_i24(float *vv
, unsigned char *i24
)
135 int i
=float2int(v
*8388608.0-0.5);
143 if (v
>= (8388606.5f
/8388608.0f
))
151 int i
=float2int(v
*8388608.0+0.5);
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);
166 *p
= ((((PCMFMTCVT_DBL_TYPE
) val
)) * (1.0 / (8388608.0)));
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
;
188 int i
=float2int(v
*8388608.0-0.5);
196 if (v
>= (8388606.5/8388608.0))
204 int i
=float2int(v
*8388608.0+0.5);
212 static void pcmToFloats(void *src
, int items
, int bps
, int src_spacing
, float *dest
, int dest_spacing
)
219 i32_to_float(*i1
,dest
);
226 unsigned char *i1
=(unsigned char *)src
;
227 int adv
=3*src_spacing
;
230 i24_to_float(i1
,dest
);
237 short *i1
=(short *)src
;
240 INT16_TO_float(*dest
,*i1
);
247 static void floatsToPcm(float *src
, int src_spacing
, int items
, void *dest
, int bps
, int dest_spacing
)
254 float_to_i32(src
,o1
);
261 unsigned char *o1
=(unsigned char*)dest
;
262 int adv
=dest_spacing
*3;
265 float_to_i24(src
,o1
);
272 short *o1
=(short*)dest
;
275 float_TO_INT16(*o1
,*src
);
283 static void pcmToDoubles(void *src
, int items
, int bps
, int src_spacing
, PCMFMTCVT_DBL_TYPE
*dest
, int dest_spacing
, int byteadvancefor24
=0)
290 i32_to_double(*i1
,dest
);
297 unsigned char *i1
=(unsigned char *)src
;
298 int adv
=3*src_spacing
+byteadvancefor24
;
301 i24_to_double(i1
,dest
);
308 short *i1
=(short *)src
;
311 INT16_TO_double(*dest
,*i1
);
318 static void doublesToPcm(PCMFMTCVT_DBL_TYPE
*src
, int src_spacing
, int items
, void *dest
, int bps
, int dest_spacing
, int byteadvancefor24
=0)
325 double_to_i32(src
,o1
);
332 unsigned char *o1
=(unsigned char*)dest
;
333 int adv
=dest_spacing
*3+byteadvancefor24
;
336 double_to_i24(src
,o1
);
343 short *o1
=(short*)dest
;
346 double_TO_INT16(*o1
,*src
);
353 static int resampleLengthNeeded(int src_srate
, int dest_srate
, int dest_len
, double *state
)
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
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
;
380 if (pan
< 0.0f
) vol2
*= 1.0f
+pan
;
381 else if (pan
> 0.0f
) vol1
*= 1.0f
-pan
;
385 double drspos
= (double)src_srate
/(double)dest_srate
;
387 for (x
= 0; x
< dest_len
; x
++)
392 if (src_srate
!= dest_srate
)
394 int ipos
= (int)rspos
;
395 double fracpos
=rspos
-ipos
;
399 ls
=src
[ipos
]*(1.0-fracpos
) + src
[ipos
+2]*fracpos
;
400 rs
=src
[ipos
+1]*(1.0-fracpos
) + src
[ipos
+3]*fracpos
;
404 rs
=ls
=src
[ipos
]*(1.0-fracpos
) + src
[ipos
+1]*fracpos
;
424 if (ls
> 1.0) ls
=1.0;
425 else if (ls
<-1.0) ls
=-1.0;
430 if (rs
> 1.0) rs
=1.0;
431 else if (rs
<-1.0) rs
=-1.0;
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
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];
466 if (pan
< 0.0f
) vol2
*= 1.0f
+pan
;
467 else if (pan
> 0.0f
) vol1
*= 1.0f
-pan
;
473 if (src_srate
!= dest_srate
) drspos
=(double)src_srate
/(double)dest_srate
;
475 for (x
= 0; x
< dest_len
; x
++)
478 if (src_srate
!= dest_srate
)
480 int ipos
= (int)rspos
;
481 double fracpos
=rspos
-ipos
;
485 ls
=src
[ipos
]*(1.0-fracpos
) + src
[ipos
+2]*fracpos
;
486 rs
=src
[ipos
+1]*(1.0-fracpos
) + src
[ipos
+3]*fracpos
;
490 rs
=ls
=src
[ipos
]*(1.0-fracpos
) + src
[ipos
+1]*fracpos
;
510 if (ls
> 1.0) ls
=1.0;
511 else if (ls
<-1.0) ls
=-1.0;
513 *dest1
++ +=(float) ls
;
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_