diff options
-rw-r--r-- | apps/codecs/libspeex/speex/speex_stereo.h | 27 | ||||
-rw-r--r-- | apps/codecs/libspeex/stereo.c | 122 | ||||
-rw-r--r-- | apps/codecs/speex.c | 27 |
3 files changed, 111 insertions, 65 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]; |
diff --git a/apps/codecs/speex.c b/apps/codecs/speex.c index 724160b152..c3f1fc8408 100644 --- a/apps/codecs/speex.c +++ b/apps/codecs/speex.c | |||
@@ -206,9 +206,7 @@ int speex_seek_page_granule(spx_int64_t pos, spx_int64_t curpos, | |||
206 | the bitrate is relativly constant. | 206 | the bitrate is relativly constant. |
207 | */ | 207 | */ |
208 | 208 | ||
209 | curoffset = (int)((((float)(*curbyteoffset-(headerssize)) * | 209 | curoffset = (((*curbyteoffset-headerssize) * pos)/curpos)*98/100; |
210 | (float)pos)/(float)curpos)*0.98); | ||
211 | |||
212 | if (curoffset < 0) | 210 | if (curoffset < 0) |
213 | curoffset=0; | 211 | curoffset=0; |
214 | 212 | ||
@@ -347,12 +345,14 @@ static void *process_header(spx_ogg_packet *op, | |||
347 | speex_decoder_ctl(st, SPEEX_SET_ENH, &enh_enabled); | 345 | speex_decoder_ctl(st, SPEEX_SET_ENH, &enh_enabled); |
348 | speex_decoder_ctl(st, SPEEX_GET_FRAME_SIZE, frame_size); | 346 | speex_decoder_ctl(st, SPEEX_GET_FRAME_SIZE, frame_size); |
349 | 347 | ||
350 | if (*channels!=1){ | 348 | if (header->nb_channels!=1){ |
351 | callback.callback_id = SPEEX_INBAND_STEREO; | 349 | callback.callback_id = SPEEX_INBAND_STEREO; |
352 | callback.func = speex_std_stereo_request_handler; | 350 | callback.func = speex_std_stereo_request_handler; |
353 | callback.data = stereo; | 351 | callback.data = stereo; |
354 | speex_decoder_ctl(st, SPEEX_SET_HANDLER, &callback); | 352 | speex_decoder_ctl(st, SPEEX_SET_HANDLER, &callback); |
355 | } | 353 | } |
354 | *channels = header->nb_channels; | ||
355 | |||
356 | if (!*rate) | 356 | if (!*rate) |
357 | *rate = header->rate; | 357 | *rate = header->rate; |
358 | 358 | ||
@@ -360,9 +360,6 @@ static void *process_header(spx_ogg_packet *op, | |||
360 | 360 | ||
361 | *nframes = header->frames_per_packet; | 361 | *nframes = header->frames_per_packet; |
362 | 362 | ||
363 | if (*channels == -1) | ||
364 | *channels = header->nb_channels; | ||
365 | |||
366 | *extra_headers = header->extra_headers; | 363 | *extra_headers = header->extra_headers; |
367 | 364 | ||
368 | return st; | 365 | return st; |
@@ -382,27 +379,25 @@ enum codec_status codec_main(void) | |||
382 | int enh_enabled = 1; | 379 | int enh_enabled = 1; |
383 | int nframes = 2; | 380 | int nframes = 2; |
384 | int eos = 0; | 381 | int eos = 0; |
385 | static const SpeexStereoState stereo_init = SPEEX_STEREO_STATE_INIT; | 382 | SpeexStereoState *stereo; |
386 | SpeexStereoState stereo = stereo_init; | ||
387 | int channels = -1; | 383 | int channels = -1; |
388 | int rate = 0, samplerate = 0; | 384 | int rate = 0, samplerate = 0; |
389 | int extra_headers = 0; | 385 | int extra_headers = 0; |
390 | int stream_init = 0; | 386 | int stream_init = 0; |
391 | int page_nb_packets, frame_size, packet_count = 0; | 387 | int page_nb_packets, frame_size, packet_count = 0; |
392 | int lookahead = 0; | ||
393 | int headerssize = -1; | 388 | int headerssize = -1; |
394 | unsigned long strtoffset = 0; | 389 | unsigned long strtoffset = 0; |
395 | void *st = NULL; | 390 | void *st = NULL; |
396 | int j = 0; | 391 | int j = 0; |
397 | 392 | ||
398 | /* We need to flush reserver memory every track load. */ | 393 | /* Ogg handling still uses mallocs, so reset the malloc buffer per track */ |
399 | next_track: | 394 | next_track: |
400 | 395 | ||
401 | if (codec_init()) { | 396 | if (codec_init()) { |
402 | error = CODEC_ERROR; | 397 | error = CODEC_ERROR; |
403 | goto exit; | 398 | goto exit; |
404 | } | 399 | } |
405 | 400 | stereo = speex_stereo_state_init(); | |
406 | strtoffset = ci->id3->offset; | 401 | strtoffset = ci->id3->offset; |
407 | 402 | ||
408 | while (!*ci->taginfo_ready && !ci->stop_codec) | 403 | while (!*ci->taginfo_ready && !ci->stop_codec) |
@@ -467,9 +462,7 @@ next_page: | |||
467 | if (packet_count==0){ | 462 | if (packet_count==0){ |
468 | st = process_header(&op, enh_enabled, &frame_size, | 463 | st = process_header(&op, enh_enabled, &frame_size, |
469 | &samplerate, &nframes, &channels, | 464 | &samplerate, &nframes, &channels, |
470 | &stereo, &extra_headers); | 465 | stereo, &extra_headers); |
471 | |||
472 | speex_decoder_ctl(st, SPEEX_GET_LOOKAHEAD, &lookahead); | ||
473 | 466 | ||
474 | if (!nframes) | 467 | if (!nframes) |
475 | nframes=1; | 468 | nframes=1; |
@@ -531,7 +524,7 @@ next_page: | |||
531 | break; | 524 | break; |
532 | 525 | ||
533 | if (channels == 2) | 526 | if (channels == 2) |
534 | speex_decode_stereo_int(output, frame_size, &stereo); | 527 | speex_decode_stereo_int(output, frame_size, stereo); |
535 | 528 | ||
536 | if (frame_size > 0) { | 529 | if (frame_size > 0) { |
537 | ci->pcmbuf_insert(output, NULL, frame_size); | 530 | ci->pcmbuf_insert(output, NULL, frame_size); |
@@ -566,8 +559,6 @@ done: | |||
566 | cur_granule = stream_init = rate = samplerate = headerssize | 559 | cur_granule = stream_init = rate = samplerate = headerssize |
567 | = packet_count = eos = 0; | 560 | = packet_count = eos = 0; |
568 | 561 | ||
569 | stereo = stereo_init; | ||
570 | |||
571 | goto next_track; | 562 | goto next_track; |
572 | } | 563 | } |
573 | 564 | ||