1c2c66affSColin Finck /*
2c2c66affSColin Finck sample.h: The conversion from internal data to output samples of differing formats.
3c2c66affSColin Finck
4c2c66affSColin Finck copyright 2007-9 by the mpg123 project - free software under the terms of the LGPL 2.1
5c2c66affSColin Finck see COPYING and AUTHORS files in distribution or http://mpg123.org
6c2c66affSColin Finck initially written by Thomas Orgis, taking WRITE_SAMPLE from decode.c
7c2c66affSColin Finck Later added the end-conversion specific macros here, too.
8c2c66affSColin Finck */
9c2c66affSColin Finck
10c2c66affSColin Finck #ifndef SAMPLE_H
11c2c66affSColin Finck #define SAMPLE_H
12c2c66affSColin Finck
13c2c66affSColin Finck /* mpg123lib_intern.h is included already, right? */
14c2c66affSColin Finck
15c2c66affSColin Finck /* Special case is fixed point math... which does work, but not that nice yet. */
16c2c66affSColin Finck #ifdef REAL_IS_FIXED
idiv_signed_rounded(int32_t x,int shift)17c2c66affSColin Finck static inline int16_t idiv_signed_rounded(int32_t x, int shift)
18c2c66affSColin Finck {
19c2c66affSColin Finck x >>= (shift - 1);
20c2c66affSColin Finck x += (x & 1);
21c2c66affSColin Finck return (int16_t)(x >> 1);
22c2c66affSColin Finck }
23c2c66affSColin Finck # define REAL_PLUS_32767 ( 32767 << 15 )
24c2c66affSColin Finck # define REAL_MINUS_32768 ( -32768 << 15 )
25c2c66affSColin Finck # define REAL_TO_SHORT(x) (idiv_signed_rounded(x, 15))
26c2c66affSColin Finck /* No better code (yet). */
27c2c66affSColin Finck # define REAL_TO_SHORT_ACCURATE(x) REAL_TO_SHORT(x)
28c2c66affSColin Finck /* This is just here for completeness, it is not used! */
29c2c66affSColin Finck # define REAL_TO_S32(x) (x)
30c2c66affSColin Finck #endif
31c2c66affSColin Finck
32c2c66affSColin Finck /* From now on for single precision float... double precision is a possible option once we added some bits. But, it would be rather insane. */
33c2c66affSColin Finck #ifndef REAL_TO_SHORT
34c2c66affSColin Finck
35c2c66affSColin Finck #if (defined FORCE_ACCURATE) || (defined ACCURATE_ROUNDING)
36c2c66affSColin Finck /* Define the accurate rounding function. */
37c2c66affSColin Finck # if (defined REAL_IS_FLOAT) && (defined IEEE_FLOAT)
38c2c66affSColin Finck /* This function is only available for IEEE754 single-precision values
39c2c66affSColin Finck This is nearly identical to proper rounding, just -+0.5 is rounded to 0 */
ftoi16(float x)40c2c66affSColin Finck static inline int16_t ftoi16(float x)
41c2c66affSColin Finck {
42c2c66affSColin Finck union
43c2c66affSColin Finck {
44c2c66affSColin Finck float f;
45c2c66affSColin Finck int32_t i;
46c2c66affSColin Finck } u_fi;
47c2c66affSColin Finck u_fi.f = x + 12582912.0f; /* Magic Number: 2^23 + 2^22 */
48c2c66affSColin Finck return (int16_t)u_fi.i;
49c2c66affSColin Finck }
50c2c66affSColin Finck # define REAL_TO_SHORT_ACCURATE(x) ftoi16(x)
51c2c66affSColin Finck # else
52c2c66affSColin Finck /* The "proper" rounding, plain C, a bit slow. */
53c2c66affSColin Finck # define REAL_TO_SHORT_ACCURATE(x) (short)((x)>0.0?(x)+0.5:(x)-0.5)
54c2c66affSColin Finck # endif
55c2c66affSColin Finck #endif
56c2c66affSColin Finck
57c2c66affSColin Finck /* Now define the normal rounding. */
58c2c66affSColin Finck # ifdef ACCURATE_ROUNDING
59c2c66affSColin Finck # define REAL_TO_SHORT(x) REAL_TO_SHORT_ACCURATE(x)
60c2c66affSColin Finck # else
61c2c66affSColin Finck /* Non-accurate rounding... simple truncation. Fastest, most LSB errors. */
62c2c66affSColin Finck # define REAL_TO_SHORT(x) (short)(x)
63c2c66affSColin Finck # endif
64c2c66affSColin Finck
65c2c66affSColin Finck #endif /* REAL_TO_SHORT */
66c2c66affSColin Finck
67c2c66affSColin Finck /* We should add dithering for S32, too? */
68c2c66affSColin Finck #ifndef REAL_TO_S32
69c2c66affSColin Finck # ifdef ACCURATE_ROUNDING
70c2c66affSColin Finck # define REAL_TO_S32(x) (int32_t)((x)>0.0?(x)+0.5:(x)-0.5)
71c2c66affSColin Finck # else
72c2c66affSColin Finck # define REAL_TO_S32(x) (int32_t)(x)
73c2c66affSColin Finck # endif
74c2c66affSColin Finck #endif
75c2c66affSColin Finck
76c2c66affSColin Finck #ifndef REAL_PLUS_32767
77c2c66affSColin Finck # define REAL_PLUS_32767 32767.0
78c2c66affSColin Finck #endif
79c2c66affSColin Finck #ifndef REAL_MINUS_32768
80c2c66affSColin Finck # define REAL_MINUS_32768 -32768.0
81c2c66affSColin Finck #endif
82c2c66affSColin Finck #ifndef REAL_PLUS_S32
83c2c66affSColin Finck # define REAL_PLUS_S32 2147483647.0
84c2c66affSColin Finck #endif
85c2c66affSColin Finck #ifndef REAL_MINUS_S32
86c2c66affSColin Finck # define REAL_MINUS_S32 -2147483648.0
87c2c66affSColin Finck #endif
88c2c66affSColin Finck
89c2c66affSColin Finck
90c2c66affSColin Finck /* The actual storage of a decoded sample is separated in the following macros.
91c2c66affSColin Finck We can handle different types, we could also handle dithering here. */
92c2c66affSColin Finck
93c2c66affSColin Finck #ifdef NEWOLD_WRITE_SAMPLE
94c2c66affSColin Finck
95c2c66affSColin Finck /* This is the old new mpg123 WRITE_SAMPLE, fixed for newer GCC by MPlayer folks.
96c2c66affSColin Finck Makes a huge difference on old machines. */
97c2c66affSColin Finck #if WORDS_BIGENDIAN
98c2c66affSColin Finck #define MANTISSA_OFFSET 1
99c2c66affSColin Finck #else
100c2c66affSColin Finck #define MANTISSA_OFFSET 0
101c2c66affSColin Finck #endif
102c2c66affSColin Finck #define WRITE_SHORT_SAMPLE(samples,sum,clip) { \
103c2c66affSColin Finck union { double dtemp; int itemp[2]; } u; int v; \
104c2c66affSColin Finck u.dtemp = ((((65536.0 * 65536.0 * 16)+(65536.0 * 0.5))* 65536.0)) + (sum);\
105c2c66affSColin Finck v = u.itemp[MANTISSA_OFFSET] - 0x80000000; \
106c2c66affSColin Finck if( v > 32767) { *(samples) = 0x7fff; (clip)++; } \
107c2c66affSColin Finck else if( v < -32768) { *(samples) = -0x8000; (clip)++; } \
108c2c66affSColin Finck else { *(samples) = v; } \
109c2c66affSColin Finck }
110c2c66affSColin Finck
111c2c66affSColin Finck #else
112c2c66affSColin Finck /* Macro to produce a short (signed 16bit) output sample from internal representation,
113c2c66affSColin Finck which may be float, double or indeed some integer for fixed point handling. */
114c2c66affSColin Finck #define WRITE_SHORT_SAMPLE(samples,sum,clip) \
115c2c66affSColin Finck if( (sum) > REAL_PLUS_32767) { *(samples) = 0x7fff; (clip)++; } \
116c2c66affSColin Finck else if( (sum) < REAL_MINUS_32768) { *(samples) = -0x8000; (clip)++; } \
117c2c66affSColin Finck else { *(samples) = REAL_TO_SHORT(sum); }
118c2c66affSColin Finck #endif
119c2c66affSColin Finck
120c2c66affSColin Finck /* Same as above, but always using accurate rounding. Would we want softer clipping here, too? */
121c2c66affSColin Finck #define WRITE_SHORT_SAMPLE_ACCURATE(samples,sum,clip) \
122c2c66affSColin Finck if( (sum) > REAL_PLUS_32767) { *(samples) = 0x7fff; (clip)++; } \
123c2c66affSColin Finck else if( (sum) < REAL_MINUS_32768) { *(samples) = -0x8000; (clip)++; } \
124c2c66affSColin Finck else { *(samples) = REAL_TO_SHORT_ACCURATE(sum); }
125c2c66affSColin Finck
126c2c66affSColin Finck /*
127c2c66affSColin Finck 32bit signed
128c2c66affSColin Finck We do clipping with the same old borders... but different conversion.
129c2c66affSColin Finck We see here that we need extra work for non-16bit output... we optimized for 16bit.
130c2c66affSColin Finck -0x7fffffff-1 is the minimum 32 bit signed integer value expressed so that MSVC
131c2c66affSColin Finck does not give a compile time warning.
132c2c66affSColin Finck */
133c2c66affSColin Finck #define WRITE_S32_SAMPLE(samples,sum,clip) \
134c2c66affSColin Finck { \
135c2c66affSColin Finck real tmpsum = REAL_MUL((sum),S32_RESCALE); \
136c2c66affSColin Finck if( tmpsum > REAL_PLUS_S32 ){ *(samples) = 0x7fffffff; (clip)++; } \
137c2c66affSColin Finck else if( tmpsum < REAL_MINUS_S32 ) { *(samples) = -0x7fffffff-1; (clip)++; } \
138c2c66affSColin Finck else { *(samples) = REAL_TO_S32(tmpsum); } \
139c2c66affSColin Finck }
140c2c66affSColin Finck
141c2c66affSColin Finck /* Produce an 8bit sample, via 16bit intermediate. */
142c2c66affSColin Finck #define WRITE_8BIT_SAMPLE(samples,sum,clip) \
143c2c66affSColin Finck { \
144c2c66affSColin Finck int16_t write_8bit_tmp; \
145c2c66affSColin Finck if( (sum) > REAL_PLUS_32767) { write_8bit_tmp = 0x7fff; (clip)++; } \
146c2c66affSColin Finck else if( (sum) < REAL_MINUS_32768) { write_8bit_tmp = -0x8000; (clip)++; } \
147c2c66affSColin Finck else { write_8bit_tmp = REAL_TO_SHORT(sum); } \
148c2c66affSColin Finck *(samples) = fr->conv16to8[write_8bit_tmp>>AUSHIFT]; \
149c2c66affSColin Finck }
150c2c66affSColin Finck #ifndef REAL_IS_FIXED
151c2c66affSColin Finck #define WRITE_REAL_SAMPLE(samples,sum,clip) *(samples) = ((real)1./SHORT_SCALE)*(sum)
152c2c66affSColin Finck #endif
153c2c66affSColin Finck
154*aa811c00SThomas Faber /* Finished 32 bit sample to unsigned 32 bit sample. */
155*aa811c00SThomas Faber #define CONV_SU32(s) \
156*aa811c00SThomas Faber ( (s >= 0) \
157*aa811c00SThomas Faber ? ((uint32_t)s + (uint32_t)2147483648UL) \
158*aa811c00SThomas Faber : (s == -2147483647-1 /* Work around to prevent a non-conformant MSVC warning/error */ \
159*aa811c00SThomas Faber ? 0 /* Separate because negation would overflow. */ \
160*aa811c00SThomas Faber : (uint32_t)2147483648UL - (uint32_t)(-s) ) \
161*aa811c00SThomas Faber )
162*aa811c00SThomas Faber
163*aa811c00SThomas Faber /* Finished 16 bit sample to unsigned 16 bit sample. */
164*aa811c00SThomas Faber #define CONV_SU16(s) (uint16_t)((int32_t)(s)+32768)
165*aa811c00SThomas Faber
166*aa811c00SThomas Faber /* Same style for syn123 generic conversion. */
167*aa811c00SThomas Faber #define CONV_SU8(s) (uint8_t)((int16_t)s+128)
168*aa811c00SThomas Faber
169*aa811c00SThomas Faber /* Unsigned 32 bit sample to signed 32 bit sample. */
170*aa811c00SThomas Faber #define CONV_US32(u) \
171*aa811c00SThomas Faber ( (u >= 2147483648UL) \
172*aa811c00SThomas Faber ? (int32_t)((uint32_t)u - (uint32_t)2147483648UL) \
173*aa811c00SThomas Faber : ((u == 0) \
174*aa811c00SThomas Faber ? (int32_t)-2147483648UL \
175*aa811c00SThomas Faber : -(int32_t)((uint32_t)2147483648UL - u) ) \
176*aa811c00SThomas Faber )
177*aa811c00SThomas Faber
178*aa811c00SThomas Faber /* Unsigned 16 bit sample to signed 16 bit sample. */
179*aa811c00SThomas Faber #define CONV_US16(s) (int16_t)((int32_t)s-32768)
180*aa811c00SThomas Faber
181*aa811c00SThomas Faber /* Same style for syn123 generic conversion. */
182*aa811c00SThomas Faber #define CONV_US8(s) (int8_t)((int16_t)s-128)
183*aa811c00SThomas Faber
184*aa811c00SThomas Faber /* 24 bit conversion: drop or add a least significant byte. */
185*aa811c00SThomas Faber #ifdef WORDS_BIGENDIAN
186*aa811c00SThomas Faber /* Highest byte first. Drop last. */
187*aa811c00SThomas Faber #define DROP4BYTE(w,r) {(w)[0]=(r)[0]; (w)[1]=(r)[1]; (w)[2]=(r)[2];}
188*aa811c00SThomas Faber #define ADD4BYTE(w,r) {(w)[0]=(r)[0]; (w)[1]=(r)[1]; (w)[2]=(r)[2]; (w)[3]=0;}
189*aa811c00SThomas Faber #else
190*aa811c00SThomas Faber /* Lowest byte first, drop that. */
191*aa811c00SThomas Faber #define DROP4BYTE(w,r) {(w)[0]=(r)[1]; (w)[1]=(r)[2]; (w)[2]=(r)[3];}
192*aa811c00SThomas Faber #define ADD4BYTE(w,r) {(w)[0]=0; (w)[1]=(r)[0]; (w)[2]=(r)[1]; (w)[3]=(r)[2];}
193*aa811c00SThomas Faber #endif
194*aa811c00SThomas Faber
195c2c66affSColin Finck #endif
196