Go to most recent revision | Details | 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 | |||
91 | /* Macro to produce a short (signed 16bit) output sample from internal representation, |
||
92 | which may be float, double or indeed some integer for fixed point handling. */ |
||
93 | #define WRITE_SHORT_SAMPLE(samples,sum,clip) \ |
||
94 | if( (sum) > REAL_PLUS_32767) { *(samples) = 0x7fff; (clip)++; } \ |
||
95 | else if( (sum) < REAL_MINUS_32768) { *(samples) = -0x8000; (clip)++; } \ |
||
96 | else { *(samples) = REAL_TO_SHORT(sum); } |
||
97 | |||
98 | /* Same as above, but always using accurate rounding. Would we want softer clipping here, too? */ |
||
99 | #define WRITE_SHORT_SAMPLE_ACCURATE(samples,sum,clip) \ |
||
100 | if( (sum) > REAL_PLUS_32767) { *(samples) = 0x7fff; (clip)++; } \ |
||
101 | else if( (sum) < REAL_MINUS_32768) { *(samples) = -0x8000; (clip)++; } \ |
||
102 | else { *(samples) = REAL_TO_SHORT_ACCURATE(sum); } |
||
103 | |||
104 | /* |
||
105 | 32bit signed |
||
106 | We do clipping with the same old borders... but different conversion. |
||
107 | We see here that we need extra work for non-16bit output... we optimized for 16bit. |
||
108 | -0x7fffffff-1 is the minimum 32 bit signed integer value expressed so that MSVC |
||
109 | does not give a compile time warning. |
||
110 | */ |
||
111 | #define WRITE_S32_SAMPLE(samples,sum,clip) \ |
||
112 | { \ |
||
113 | real tmpsum = REAL_MUL((sum),S32_RESCALE); \ |
||
114 | if( tmpsum > REAL_PLUS_S32 ){ *(samples) = 0x7fffffff; (clip)++; } \ |
||
115 | else if( tmpsum < REAL_MINUS_S32 ) { *(samples) = -0x7fffffff-1; (clip)++; } \ |
||
116 | else { *(samples) = REAL_TO_S32(tmpsum); } \ |
||
117 | } |
||
118 | |||
119 | /* Produce an 8bit sample, via 16bit intermediate. */ |
||
120 | #define WRITE_8BIT_SAMPLE(samples,sum,clip) \ |
||
121 | { \ |
||
122 | short write_8bit_tmp; \ |
||
123 | if( (sum) > REAL_PLUS_32767) { write_8bit_tmp = 0x7fff; (clip)++; } \ |
||
124 | else if( (sum) < REAL_MINUS_32768) { write_8bit_tmp = -0x8000; (clip)++; } \ |
||
125 | else { write_8bit_tmp = REAL_TO_SHORT(sum); } \ |
||
126 | *(samples) = fr->conv16to8[write_8bit_tmp>>AUSHIFT]; \ |
||
127 | } |
||
128 | #ifndef REAL_IS_FIXED |
||
129 | #define WRITE_REAL_SAMPLE(samples,sum,clip) *(samples) = ((real)1./SHORT_SCALE)*(sum) |
||
130 | #endif |
||
131 | |||
132 | #endif>>>>><>><> |