Rev 1905 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1905 | serge | 1 | /* |
2 | sample.h: The conversion from internal data to output samples of differing formats. |
||
3 | |||
4 | copyright 2007-9 by the mpg123 project - free software under the terms of the LGPL 2.1 |
||
5 | see COPYING and AUTHORS files in distribution or http://mpg123.org |
||
6 | initially written by Thomas Orgis, taking WRITE_SAMPLE from decode.c |
||
7 | Later added the end-conversion specific macros here, too. |
||
8 | */ |
||
9 | |||
10 | #ifndef SAMPLE_H |
||
11 | #define SAMPLE_H |
||
12 | |||
13 | /* mpg123lib_intern.h is included already, right? */ |
||
14 | |||
15 | /* Special case is fixed point math... which does work, but not that nice yet. */ |
||
16 | #ifdef REAL_IS_FIXED |
||
17 | static inline short idiv_signed_rounded(long x, int shift) |
||
18 | { |
||
19 | x >>= (shift - 1); |
||
20 | x += (x & 1); |
||
21 | return (short)(x >> 1); |
||
22 | } |
||
23 | # define REAL_PLUS_32767 ( 32767 << 15 ) |
||
24 | # define REAL_MINUS_32768 ( -32768 << 15 ) |
||
25 | # define REAL_TO_SHORT(x) (idiv_signed_rounded(x, 15)) |
||
26 | /* No better code (yet). */ |
||
27 | # define REAL_TO_SHORT_ACCURATE(x) REAL_TO_SHORT(x) |
||
28 | /* This is just here for completeness, it is not used! */ |
||
29 | # define REAL_TO_S32(x) (x) |
||
30 | #endif |
||
31 | |||
32 | /* From now on for single precision float... double precision is a possible option once we added some bits. But, it would be rather insane. */ |
||
33 | #ifndef REAL_TO_SHORT |
||
34 | |||
35 | /* Define the accurate rounding function. */ |
||
36 | # if (defined REAL_IS_FLOAT) && (defined IEEE_FLOAT) |
||
37 | /* This function is only available for IEEE754 single-precision values |
||
38 | This is nearly identical to proper rounding, just -+0.5 is rounded to 0 */ |
||
39 | static inline short ftoi16(float x) |
||
40 | { |
||
41 | union |
||
42 | { |
||
43 | float f; |
||
44 | int32_t i; |
||
45 | } u_fi; |
||
46 | u_fi.f = x + 12582912.0f; /* Magic Number: 2^23 + 2^22 */ |
||
47 | return (short)u_fi.i; |
||
48 | } |
||
49 | # define REAL_TO_SHORT_ACCURATE(x) ftoi16(x) |
||
50 | # else |
||
51 | /* The "proper" rounding, plain C, a bit slow. */ |
||
52 | # define REAL_TO_SHORT_ACCURATE(x) (short)((x)>0.0?(x)+0.5:(x)-0.5) |
||
53 | # endif |
||
54 | |||
55 | /* Now define the normal rounding. */ |
||
56 | # ifdef ACCURATE_ROUNDING |
||
57 | # define REAL_TO_SHORT(x) REAL_TO_SHORT_ACCURATE(x) |
||
58 | # else |
||
59 | /* Non-accurate rounding... simple truncation. Fastest, most LSB errors. */ |
||
60 | # define REAL_TO_SHORT(x) (short)(x) |
||
61 | # endif |
||
62 | |||
63 | #endif /* REAL_TO_SHORT */ |
||
64 | |||
65 | /* We should add dithering for S32, too? */ |
||
66 | #ifndef REAL_TO_S32 |
||
67 | # ifdef ACCURATE_ROUNDING |
||
68 | # define REAL_TO_S32(x) (int32_t)((x)>0.0?(x)+0.5:(x)-0.5) |
||
69 | # else |
||
70 | # define REAL_TO_S32(x) (int32_t)(x) |
||
71 | # endif |
||
72 | #endif |
||
73 | |||
74 | #ifndef REAL_PLUS_32767 |
||
75 | # define REAL_PLUS_32767 32767.0 |
||
76 | #endif |
||
77 | #ifndef REAL_MINUS_32768 |
||
78 | # define REAL_MINUS_32768 -32768.0 |
||
79 | #endif |
||
80 | #ifndef REAL_PLUS_S32 |
||
81 | # define REAL_PLUS_S32 2147483647.0 |
||
82 | #endif |
||
83 | #ifndef REAL_MINUS_S32 |
||
84 | # define REAL_MINUS_S32 -2147483648.0 |
||
85 | #endif |
||
86 | |||
87 | |||
88 | /* The actual storage of a decoded sample is separated in the following macros. |
||
89 | We can handle different types, we could also handle dithering here. */ |
||
90 | |||
3960 | Serge | 91 | #ifdef NEWOLD_WRITE_SAMPLE |
92 | |||
93 | /* This is the old new mpg123 WRITE_SAMPLE, fixed for newer GCC by MPlayer folks. |
||
94 | Makes a huge difference on old machines. */ |
||
95 | #if WORDS_BIGENDIAN |
||
96 | #define MANTISSA_OFFSET 1 |
||
97 | #else |
||
98 | #define MANTISSA_OFFSET 0 |
||
99 | #endif |
||
100 | #define WRITE_SHORT_SAMPLE(samples,sum,clip) { \ |
||
101 | union { double dtemp; int itemp[2]; } u; int v; \ |
||
102 | u.dtemp = ((((65536.0 * 65536.0 * 16)+(65536.0 * 0.5))* 65536.0)) + (sum);\ |
||
103 | v = u.itemp[MANTISSA_OFFSET] - 0x80000000; \ |
||
104 | if( v > 32767) { *(samples) = 0x7fff; (clip)++; } \ |
||
105 | else if( v < -32768) { *(samples) = -0x8000; (clip)++; } \ |
||
106 | else { *(samples) = v; } \ |
||
107 | } |
||
108 | |||
109 | #else |
||
1905 | serge | 110 | /* Macro to produce a short (signed 16bit) output sample from internal representation, |
111 | which may be float, double or indeed some integer for fixed point handling. */ |
||
112 | #define WRITE_SHORT_SAMPLE(samples,sum,clip) \ |
||
113 | if( (sum) > REAL_PLUS_32767) { *(samples) = 0x7fff; (clip)++; } \ |
||
114 | else if( (sum) < REAL_MINUS_32768) { *(samples) = -0x8000; (clip)++; } \ |
||
115 | else { *(samples) = REAL_TO_SHORT(sum); } |
||
3960 | Serge | 116 | #endif |
1905 | serge | 117 | |
118 | /* Same as above, but always using accurate rounding. Would we want softer clipping here, too? */ |
||
119 | #define WRITE_SHORT_SAMPLE_ACCURATE(samples,sum,clip) \ |
||
120 | if( (sum) > REAL_PLUS_32767) { *(samples) = 0x7fff; (clip)++; } \ |
||
121 | else if( (sum) < REAL_MINUS_32768) { *(samples) = -0x8000; (clip)++; } \ |
||
122 | else { *(samples) = REAL_TO_SHORT_ACCURATE(sum); } |
||
123 | |||
124 | /* |
||
125 | 32bit signed |
||
126 | We do clipping with the same old borders... but different conversion. |
||
127 | We see here that we need extra work for non-16bit output... we optimized for 16bit. |
||
128 | -0x7fffffff-1 is the minimum 32 bit signed integer value expressed so that MSVC |
||
129 | does not give a compile time warning. |
||
130 | */ |
||
131 | #define WRITE_S32_SAMPLE(samples,sum,clip) \ |
||
132 | { \ |
||
133 | real tmpsum = REAL_MUL((sum),S32_RESCALE); \ |
||
134 | if( tmpsum > REAL_PLUS_S32 ){ *(samples) = 0x7fffffff; (clip)++; } \ |
||
135 | else if( tmpsum < REAL_MINUS_S32 ) { *(samples) = -0x7fffffff-1; (clip)++; } \ |
||
136 | else { *(samples) = REAL_TO_S32(tmpsum); } \ |
||
137 | } |
||
138 | |||
139 | /* Produce an 8bit sample, via 16bit intermediate. */ |
||
140 | #define WRITE_8BIT_SAMPLE(samples,sum,clip) \ |
||
141 | { \ |
||
142 | short write_8bit_tmp; \ |
||
143 | if( (sum) > REAL_PLUS_32767) { write_8bit_tmp = 0x7fff; (clip)++; } \ |
||
144 | else if( (sum) < REAL_MINUS_32768) { write_8bit_tmp = -0x8000; (clip)++; } \ |
||
145 | else { write_8bit_tmp = REAL_TO_SHORT(sum); } \ |
||
146 | *(samples) = fr->conv16to8[write_8bit_tmp>>AUSHIFT]; \ |
||
147 | } |
||
148 | #ifndef REAL_IS_FIXED |
||
149 | #define WRITE_REAL_SAMPLE(samples,sum,clip) *(samples) = ((real)1./SHORT_SCALE)*(sum) |
||
150 | #endif |
||
151 | |||
152 | #endif>>>>>><>><> |