diff options
author | Thom Johansen <thomj@rockbox.org> | 2007-11-14 00:46:49 +0000 |
---|---|---|
committer | Thom Johansen <thomj@rockbox.org> | 2007-11-14 00:46:49 +0000 |
commit | d75a5486e60d10a74049712d8bdf1fa2816038f8 (patch) | |
tree | 85734ec703eb600faa001859a67138e215566bd7 /apps/codecs/libspeex | |
parent | f554e00b61a2ecfdbf72314414947de57912fe02 (diff) | |
download | rockbox-d75a5486e60d10a74049712d8bdf1fa2816038f8.tar.gz rockbox-d75a5486e60d10a74049712d8bdf1fa2816038f8.zip |
New Speex stereo code in libspeex and speex.c, stereo should be more robust now. Remove last floating point code in speex.c and remove some unused stuff.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15611 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/libspeex')
-rw-r--r-- | apps/codecs/libspeex/speex/speex_stereo.h | 27 | ||||
-rw-r--r-- | apps/codecs/libspeex/stereo.c | 122 |
2 files changed, 102 insertions, 47 deletions
diff --git a/apps/codecs/libspeex/speex/speex_stereo.h b/apps/codecs/libspeex/speex/speex_stereo.h index 904e9b092e..b817a5535e 100644 --- a/apps/codecs/libspeex/speex/speex_stereo.h +++ b/apps/codecs/libspeex/speex/speex_stereo.h | |||
@@ -46,31 +46,28 @@ | |||
46 | extern "C" { | 46 | extern "C" { |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | /** State used for decoding (intensity) stereo information */ | 49 | /** If you access any of these fields directly, I'll personally come and bite you */ |
50 | typedef struct SpeexStereoState { | 50 | typedef struct SpeexStereoState { |
51 | #ifndef FIXED_POINT | ||
52 | float balance; /**< Left/right balance info */ | 51 | float balance; /**< Left/right balance info */ |
53 | float e_ratio; /**< Ratio of energies: E(left+right)/[E(left)+E(right)] */ | 52 | float e_ratio; /**< Ratio of energies: E(left+right)/[E(left)+E(right)] */ |
54 | float smooth_left; /**< Smoothed left channel gain */ | 53 | float smooth_left; /**< Smoothed left channel gain */ |
55 | float smooth_right; /**< Smoothed right channel gain */ | 54 | float smooth_right; /**< Smoothed right channel gain */ |
56 | float reserved1; /**< Reserved for future use */ | 55 | float reserved1; /**< Reserved for future use */ |
57 | float reserved2; /**< Reserved for future use */ | 56 | float reserved2; /**< Reserved for future use */ |
58 | #else | ||
59 | spx_int32_t balance; /**< Left/right balance info */ | ||
60 | spx_int16_t e_ratio; /**< Ratio of energies: E(left+right)/[E(left)+E(right)] */ | ||
61 | spx_int16_t smooth_left; /**< Smoothed left channel gain */ | ||
62 | spx_int16_t smooth_right; /**< Smoothed right channel gain */ | ||
63 | spx_int32_t reserved1; /**< Reserved for future use */ | ||
64 | spx_int32_t reserved2; /**< Reserved for future use */ | ||
65 | #endif | ||
66 | } SpeexStereoState; | 57 | } SpeexStereoState; |
67 | 58 | ||
68 | /** Initialization value for a stereo state */ | 59 | /** Deprecated. Use speex_stereo_state_init() instead. */ |
69 | #ifndef FIXED_POINT | ||
70 | #define SPEEX_STEREO_STATE_INIT {1,.5,1,1,0,0} | 60 | #define SPEEX_STEREO_STATE_INIT {1,.5,1,1,0,0} |
71 | #else | 61 | |
72 | #define SPEEX_STEREO_STATE_INIT {65536,16384,16384,16384,0,0} | 62 | /** Initialise/create a stereo stereo state */ |
73 | #endif | 63 | SpeexStereoState *speex_stereo_state_init(); |
64 | |||
65 | /** Reset/re-initialise an already allocated stereo state */ | ||
66 | void speex_stereo_state_reset(SpeexStereoState *stereo); | ||
67 | |||
68 | /** Destroy a stereo stereo state */ | ||
69 | void speex_stereo_state_destroy(SpeexStereoState *stereo); | ||
70 | |||
74 | /** Transforms a stereo frame into a mono frame and stores intensity stereo info in 'bits' */ | 71 | /** Transforms a stereo frame into a mono frame and stores intensity stereo info in 'bits' */ |
75 | void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits); | 72 | void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits); |
76 | 73 | ||
diff --git a/apps/codecs/libspeex/stereo.c b/apps/codecs/libspeex/stereo.c index 695dfe0fb0..c63c974798 100644 --- a/apps/codecs/libspeex/stereo.c +++ b/apps/codecs/libspeex/stereo.c | |||
@@ -38,6 +38,17 @@ | |||
38 | #include "math_approx.h" | 38 | #include "math_approx.h" |
39 | #include "vq.h" | 39 | #include "vq.h" |
40 | #include <math.h> | 40 | #include <math.h> |
41 | #include "os_support.h" | ||
42 | |||
43 | typedef struct RealSpeexStereoState { | ||
44 | spx_word32_t balance; /**< Left/right balance info */ | ||
45 | spx_word32_t e_ratio; /**< Ratio of energies: E(left+right)/[E(left)+E(right)] */ | ||
46 | spx_word32_t smooth_left; /**< Smoothed left channel gain */ | ||
47 | spx_word32_t smooth_right; /**< Smoothed right channel gain */ | ||
48 | spx_int32_t reserved1; /**< Reserved for future use */ | ||
49 | spx_int32_t reserved2; /**< Reserved for future use */ | ||
50 | } RealSpeexStereoState; | ||
51 | |||
41 | 52 | ||
42 | /*float e_ratio_quant[4] = {1, 1.26, 1.587, 2};*/ | 53 | /*float e_ratio_quant[4] = {1, 1.26, 1.587, 2};*/ |
43 | #ifndef FIXED_POINT | 54 | #ifndef FIXED_POINT |
@@ -46,6 +57,50 @@ static const float e_ratio_quant[4] = {.25f, .315f, .397f, .5f}; | |||
46 | static const spx_word16_t e_ratio_quant[4] = {8192, 10332, 13009, 16384}; | 57 | static const spx_word16_t e_ratio_quant[4] = {8192, 10332, 13009, 16384}; |
47 | #endif | 58 | #endif |
48 | 59 | ||
60 | /* This is an ugly compatibility hack that properly resets the stereo state | ||
61 | In case it it compiled in fixed-point, but initialised with the deprecated | ||
62 | floating point static initialiser */ | ||
63 | #ifdef FIXED_POINT | ||
64 | #define COMPATIBILITY_HACK(s) do {if ((s)->reserved1 != 0xdeadbeef) speex_stereo_state_init(s); } while (0); | ||
65 | #else | ||
66 | #define COMPATIBILITY_HACK(s) | ||
67 | #endif | ||
68 | |||
69 | static SpeexStereoState global_stereo_state; | ||
70 | SpeexStereoState *speex_stereo_state_init() | ||
71 | { | ||
72 | /* SpeexStereoState *stereo = speex_alloc(sizeof(SpeexStereoState)); */ | ||
73 | SpeexStereoState *stereo = &global_stereo_state; | ||
74 | speex_stereo_state_reset(stereo); | ||
75 | return stereo; | ||
76 | } | ||
77 | |||
78 | void speex_stereo_state_reset(SpeexStereoState *_stereo) | ||
79 | { | ||
80 | RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo; | ||
81 | #ifdef FIXED_POINT | ||
82 | stereo->balance = 65536; | ||
83 | stereo->e_ratio = 16384; | ||
84 | stereo->smooth_left = 16384; | ||
85 | stereo->smooth_right = 16384; | ||
86 | stereo->reserved1 = 0xdeadbeef; | ||
87 | stereo->reserved2 = 0; | ||
88 | #else | ||
89 | stereo->balance = 1.0f; | ||
90 | stereo->e_ratio = .5f; | ||
91 | stereo->smooth_left = 1.f; | ||
92 | stereo->smooth_right = 1.f; | ||
93 | stereo->reserved1 = 0; | ||
94 | stereo->reserved2 = 0; | ||
95 | #endif | ||
96 | } | ||
97 | |||
98 | void speex_stereo_state_destroy(SpeexStereoState *stereo) | ||
99 | { | ||
100 | (void)stereo; | ||
101 | /* speex_free(stereo); */ | ||
102 | } | ||
103 | |||
49 | #ifndef SPEEX_DISABLE_ENCODER | 104 | #ifndef SPEEX_DISABLE_ENCODER |
50 | void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits) | 105 | void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits) |
51 | { | 106 | { |
@@ -79,7 +134,7 @@ void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits) | |||
79 | 134 | ||
80 | speex_bits_pack(bits, (int)balance, 5); | 135 | speex_bits_pack(bits, (int)balance, 5); |
81 | 136 | ||
82 | /*Quantize energy ratio*/ | 137 | /* FIXME: Convert properly */ |
83 | tmp=vq_index(&e_ratio, e_ratio_quant, 1, 4); | 138 | tmp=vq_index(&e_ratio, e_ratio_quant, 1, 4); |
84 | speex_bits_pack(bits, tmp, 2); | 139 | speex_bits_pack(bits, tmp, 2); |
85 | } | 140 | } |
@@ -116,7 +171,7 @@ void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits) | |||
116 | 171 | ||
117 | speex_bits_pack(bits, (int)balance, 5); | 172 | speex_bits_pack(bits, (int)balance, 5); |
118 | 173 | ||
119 | /*Quantize energy ratio*/ | 174 | /* FIXME: Convert properly */ |
120 | tmp=vq_index(&e_ratio, e_ratio_quant, 1, 4); | 175 | tmp=vq_index(&e_ratio, e_ratio_quant, 1, 4); |
121 | speex_bits_pack(bits, tmp, 2); | 176 | speex_bits_pack(bits, tmp, 2); |
122 | } | 177 | } |
@@ -124,73 +179,76 @@ void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits) | |||
124 | 179 | ||
125 | /* We don't want to decode to floats yet, disable */ | 180 | /* We don't want to decode to floats yet, disable */ |
126 | #if 0 | 181 | #if 0 |
127 | void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *stereo) | 182 | void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *_stereo) |
128 | { | 183 | { |
129 | float balance, e_ratio; | ||
130 | int i; | 184 | int i; |
131 | float e_tot=0, e_left, e_right, e_sum; | 185 | spx_word32_t balance; |
132 | 186 | spx_word16_t e_left, e_right, e_ratio; | |
187 | RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo; | ||
188 | |||
189 | COMPATIBILITY_HACK(stereo); | ||
190 | |||
133 | balance=stereo->balance; | 191 | balance=stereo->balance; |
134 | e_ratio=stereo->e_ratio; | 192 | e_ratio=stereo->e_ratio; |
135 | for (i=frame_size-1;i>=0;i--) | 193 | |
136 | { | 194 | /* These two are Q14, with max value just below 2. */ |
137 | e_tot += ((float)data[i])*data[i]; | 195 | e_right = DIV32(QCONST32(1., 22), spx_sqrt(MULT16_32_Q15(e_ratio, ADD32(QCONST32(1., 16), balance)))); |
138 | } | 196 | e_left = SHR32(MULT16_16(spx_sqrt(balance), e_right), 8); |
139 | e_sum=e_tot/e_ratio; | ||
140 | e_left = e_sum*balance / (1+balance); | ||
141 | e_right = e_sum-e_left; | ||
142 | |||
143 | e_left = sqrt(e_left/(e_tot+.01)); | ||
144 | e_right = sqrt(e_right/(e_tot+.01)); | ||
145 | 197 | ||
146 | for (i=frame_size-1;i>=0;i--) | 198 | for (i=frame_size-1;i>=0;i--) |
147 | { | 199 | { |
148 | float ftmp=data[i]; | 200 | spx_word16_t tmp=data[i]; |
149 | stereo->smooth_left = .98*stereo->smooth_left + .02*e_left; | 201 | stereo->smooth_left = EXTRACT16(PSHR32(MAC16_16(MULT16_16(stereo->smooth_left, QCONST16(0.98, 15)), e_left, QCONST16(0.02, 15)), 15)); |
150 | stereo->smooth_right = .98*stereo->smooth_right + .02*e_right; | 202 | stereo->smooth_right = EXTRACT16(PSHR32(MAC16_16(MULT16_16(stereo->smooth_right, QCONST16(0.98, 15)), e_right, QCONST16(0.02, 15)), 15)); |
151 | data[2*i] = stereo->smooth_left*ftmp; | 203 | data[2*i] = (float)MULT16_16_P14(stereo->smooth_left, tmp); |
152 | data[2*i+1] = stereo->smooth_right*ftmp; | 204 | data[2*i+1] = (float)MULT16_16_P14(stereo->smooth_right, tmp); |
153 | } | 205 | } |
154 | } | 206 | } |
155 | #endif | 207 | #endif |
156 | 208 | ||
157 | void speex_decode_stereo_int(spx_int16_t *data, int frame_size, SpeexStereoState *stereo) | 209 | void speex_decode_stereo_int(spx_int16_t *data, int frame_size, SpeexStereoState *_stereo) |
158 | { | 210 | { |
159 | int i; | 211 | int i; |
160 | spx_word32_t balance; | 212 | spx_word32_t balance; |
161 | spx_word16_t e_left, e_right, e_ratio; | 213 | spx_word16_t e_left, e_right, e_ratio; |
214 | RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo; | ||
162 | 215 | ||
216 | COMPATIBILITY_HACK(stereo); | ||
217 | |||
163 | balance=stereo->balance; | 218 | balance=stereo->balance; |
164 | e_ratio=stereo->e_ratio; | 219 | e_ratio=stereo->e_ratio; |
165 | 220 | ||
166 | /* These two are Q14, with max value just below 2. */ | 221 | /* These two are Q14, with max value just below 2. */ |
167 | e_right = DIV32(QCONST32(1., 22), spx_sqrt(MULT16_32_Q15(e_ratio, ADD32(QCONST32(1., 16), balance)))); | 222 | e_right = DIV32(QCONST32(1., 22), spx_sqrt(MULT16_32_Q15(e_ratio, ADD32(QCONST32(1., 16), balance)))); |
168 | e_left = SHR32(MULT16_16(spx_sqrt(balance), e_right), 8); | 223 | e_left = SHR32(MULT16_16(spx_sqrt(balance), e_right), 8); |
169 | 224 | ||
170 | for (i=frame_size-1;i>=0;i--) | 225 | for (i=frame_size-1;i>=0;i--) |
171 | { | 226 | { |
172 | spx_word16_t tmp=data[i]; | 227 | spx_int16_t tmp=data[i]; |
173 | stereo->smooth_left = EXTRACT16(PSHR32(MAC16_16(MULT16_16(stereo->smooth_left, QCONST16(0.98, 15)), e_left, QCONST16(0.02, 15)), 15)); | 228 | stereo->smooth_left = EXTRACT16(PSHR32(MAC16_16(MULT16_16(stereo->smooth_left, QCONST16(0.98, 15)), e_left, QCONST16(0.02, 15)), 15)); |
174 | stereo->smooth_right = EXTRACT16(PSHR32(MAC16_16(MULT16_16(stereo->smooth_right, QCONST16(0.98, 15)), e_right, QCONST16(0.02, 15)), 15)); | 229 | stereo->smooth_right = EXTRACT16(PSHR32(MAC16_16(MULT16_16(stereo->smooth_right, QCONST16(0.98, 15)), e_right, QCONST16(0.02, 15)), 15)); |
175 | data[2*i] = MULT16_16_P14(stereo->smooth_left, tmp); | 230 | data[2*i] = (spx_int16_t)MULT16_16_P14(stereo->smooth_left, tmp); |
176 | data[2*i+1] = MULT16_16_P14(stereo->smooth_right, tmp); | 231 | data[2*i+1] = (spx_int16_t)MULT16_16_P14(stereo->smooth_right, tmp); |
177 | } | 232 | } |
178 | } | 233 | } |
179 | 234 | ||
180 | int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data) | 235 | int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data) |
181 | { | 236 | { |
182 | SpeexStereoState *stereo; | 237 | RealSpeexStereoState *stereo; |
183 | spx_word16_t sign=1; | 238 | spx_word16_t sign=1, dexp; |
184 | int tmp; | 239 | int tmp; |
185 | 240 | ||
186 | stereo = (SpeexStereoState*)data; | 241 | stereo = (RealSpeexStereoState*)data; |
242 | |||
243 | COMPATIBILITY_HACK(stereo); | ||
244 | |||
187 | if (speex_bits_unpack_unsigned(bits, 1)) | 245 | if (speex_bits_unpack_unsigned(bits, 1)) |
188 | sign=-1; | 246 | sign=-1; |
189 | tmp = speex_bits_unpack_unsigned(bits, 5); | 247 | dexp = speex_bits_unpack_unsigned(bits, 5); |
190 | #ifndef FIXED_POINT | 248 | #ifndef FIXED_POINT |
191 | stereo->balance = exp(sign*.25*tmp); | 249 | stereo->balance = exp(sign*.25*dexp); |
192 | #else | 250 | #else |
193 | stereo->balance = spx_exp(MULT16_16(sign, SHL16(tmp, 9))); | 251 | stereo->balance = spx_exp(MULT16_16(sign, SHL16(dexp, 9))); |
194 | #endif | 252 | #endif |
195 | tmp = speex_bits_unpack_unsigned(bits, 2); | 253 | tmp = speex_bits_unpack_unsigned(bits, 2); |
196 | stereo->e_ratio = e_ratio_quant[tmp]; | 254 | stereo->e_ratio = e_ratio_quant[tmp]; |