diff options
author | Andree Buschmann <AndreeBuschmann@t-online.de> | 2010-02-21 19:47:05 +0000 |
---|---|---|
committer | Andree Buschmann <AndreeBuschmann@t-online.de> | 2010-02-21 19:47:05 +0000 |
commit | 3d6faa08bf95da6e0f65a070a11f014e78c0b682 (patch) | |
tree | fdffd82b1972b735b5e82b1258d578f61f64b2bb /apps/codecs | |
parent | a31624e76e45230aa9f94b16709f86e0042bad91 (diff) | |
download | rockbox-3d6faa08bf95da6e0f65a070a11f014e78c0b682.tar.gz rockbox-3d6faa08bf95da6e0f65a070a11f014e78c0b682.zip |
Optimization for cook codec. Rework sample output to be able to use highly optimized dsp routines. Moved some functions to iram. Speeds up codec by 1.3 MHz on PP5022.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24815 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs')
-rw-r--r-- | apps/codecs/cook.c | 14 | ||||
-rw-r--r-- | apps/codecs/libcook/cook.c | 12 | ||||
-rw-r--r-- | apps/codecs/libcook/cook.h | 2 | ||||
-rw-r--r-- | apps/codecs/libcook/cook_fixpoint.h | 60 | ||||
-rw-r--r-- | apps/codecs/libcook/main.c | 2 |
5 files changed, 34 insertions, 56 deletions
diff --git a/apps/codecs/cook.c b/apps/codecs/cook.c index 4214d30f38..30255d4fd7 100644 --- a/apps/codecs/cook.c +++ b/apps/codecs/cook.c | |||
@@ -31,6 +31,7 @@ CODEC_HEADER | |||
31 | RMContext rmctx; | 31 | RMContext rmctx; |
32 | RMPacket pkt; | 32 | RMPacket pkt; |
33 | COOKContext q IBSS_ATTR; | 33 | COOKContext q IBSS_ATTR; |
34 | int32_t rm_outbuf[2048]; | ||
34 | 35 | ||
35 | static void init_rm(RMContext *rmctx) | 36 | static void init_rm(RMContext *rmctx) |
36 | { | 37 | { |
@@ -43,7 +44,6 @@ enum codec_status codec_main(void) | |||
43 | static size_t buff_size; | 44 | static size_t buff_size; |
44 | int datasize, res, consumed, i, time_offset; | 45 | int datasize, res, consumed, i, time_offset; |
45 | uint8_t *bit_buffer; | 46 | uint8_t *bit_buffer; |
46 | int16_t outbuf[2048] __attribute__((aligned(32))); | ||
47 | uint16_t fs,sps,h; | 47 | uint16_t fs,sps,h; |
48 | uint32_t packet_count; | 48 | uint32_t packet_count; |
49 | int scrambling_unit_size, num_units; | 49 | int scrambling_unit_size, num_units; |
@@ -65,9 +65,11 @@ next_track: | |||
65 | init_rm(&rmctx); | 65 | init_rm(&rmctx); |
66 | 66 | ||
67 | ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); | 67 | ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); |
68 | ci->configure(DSP_SET_SAMPLE_DEPTH, 16); | 68 | /* cook's sample representation is 21.11 |
69 | * DSP_SET_SAMPLE_DEPTH = 11 (FRACT) + 16 (NATIVE) - 1 (SIGN) = 26 */ | ||
70 | ci->configure(DSP_SET_SAMPLE_DEPTH, 26); | ||
69 | ci->configure(DSP_SET_STEREO_MODE, rmctx.nb_channels == 1 ? | 71 | ci->configure(DSP_SET_STEREO_MODE, rmctx.nb_channels == 1 ? |
70 | STEREO_MONO : STEREO_INTERLEAVED); | 72 | STEREO_MONO : STEREO_NONINTERLEAVED); |
71 | 73 | ||
72 | packet_count = rmctx.nb_packets; | 74 | packet_count = rmctx.nb_packets; |
73 | rmctx.audio_framesize = rmctx.block_align; | 75 | rmctx.audio_framesize = rmctx.block_align; |
@@ -155,7 +157,7 @@ seek_start : | |||
155 | ci->set_elapsed(rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i); | 157 | ci->set_elapsed(rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i); |
156 | ci->seek_complete(); | 158 | ci->seek_complete(); |
157 | } | 159 | } |
158 | res = cook_decode_frame(&rmctx,&q, outbuf, &datasize, pkt.frames[i], rmctx.block_align); | 160 | res = cook_decode_frame(&rmctx,&q, rm_outbuf, &datasize, pkt.frames[i], rmctx.block_align); |
159 | rmctx.frame_number++; | 161 | rmctx.frame_number++; |
160 | 162 | ||
161 | /* skip the first two frames; no valid audio */ | 163 | /* skip the first two frames; no valid audio */ |
@@ -166,7 +168,9 @@ seek_start : | |||
166 | return CODEC_ERROR; | 168 | return CODEC_ERROR; |
167 | } | 169 | } |
168 | 170 | ||
169 | ci->pcmbuf_insert(outbuf, NULL, q.samples_per_frame / rmctx.nb_channels); | 171 | ci->pcmbuf_insert(rm_outbuf, |
172 | rm_outbuf+q.samples_per_channel, | ||
173 | q.samples_per_channel); | ||
170 | ci->set_elapsed(rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i); | 174 | ci->set_elapsed(rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i); |
171 | } | 175 | } |
172 | packet_count -= rmctx.audio_pkt_cnt; | 176 | packet_count -= rmctx.audio_pkt_cnt; |
diff --git a/apps/codecs/libcook/cook.c b/apps/codecs/libcook/cook.c index 8d9611c4d9..814250ea32 100644 --- a/apps/codecs/libcook/cook.c +++ b/apps/codecs/libcook/cook.c | |||
@@ -598,7 +598,7 @@ decode_bytes_and_gain(COOKContext *q, const uint8_t *inbuffer, | |||
598 | static void | 598 | static void |
599 | mlt_compensate_output(COOKContext *q, REAL_T *decode_buffer, | 599 | mlt_compensate_output(COOKContext *q, REAL_T *decode_buffer, |
600 | cook_gains *gains, REAL_T *previous_buffer, | 600 | cook_gains *gains, REAL_T *previous_buffer, |
601 | int16_t *out, int chan) | 601 | int32_t *out, int chan) |
602 | { | 602 | { |
603 | REAL_T *buffer = q->mono_mdct_output; | 603 | REAL_T *buffer = q->mono_mdct_output; |
604 | int i; | 604 | int i; |
@@ -618,7 +618,9 @@ mlt_compensate_output(COOKContext *q, REAL_T *decode_buffer, | |||
618 | memcpy(previous_buffer, buffer+q->samples_per_channel, | 618 | memcpy(previous_buffer, buffer+q->samples_per_channel, |
619 | sizeof(REAL_T)*q->samples_per_channel); | 619 | sizeof(REAL_T)*q->samples_per_channel); |
620 | 620 | ||
621 | output_math(q, out, chan); | 621 | /* Copy output to non-interleaved sample buffer */ |
622 | memcpy(out + (chan * q->samples_per_channel), buffer, | ||
623 | sizeof(REAL_T)*q->samples_per_channel); | ||
622 | } | 624 | } |
623 | 625 | ||
624 | 626 | ||
@@ -634,7 +636,7 @@ mlt_compensate_output(COOKContext *q, REAL_T *decode_buffer, | |||
634 | 636 | ||
635 | 637 | ||
636 | static int decode_subpacket(COOKContext *q, const uint8_t *inbuffer, | 638 | static int decode_subpacket(COOKContext *q, const uint8_t *inbuffer, |
637 | int sub_packet_size, int16_t *outbuffer) { | 639 | int sub_packet_size, int32_t *outbuffer) { |
638 | /* packet dump */ | 640 | /* packet dump */ |
639 | // for (i=0 ; i<sub_packet_size ; i++) { | 641 | // for (i=0 ; i<sub_packet_size ; i++) { |
640 | // DEBUGF("%02x", inbuffer[i]); | 642 | // DEBUGF("%02x", inbuffer[i]); |
@@ -666,7 +668,7 @@ static int decode_subpacket(COOKContext *q, const uint8_t *inbuffer, | |||
666 | q->mono_previous_buffer2, outbuffer, 1); | 668 | q->mono_previous_buffer2, outbuffer, 1); |
667 | } | 669 | } |
668 | } | 670 | } |
669 | return q->samples_per_frame * sizeof(int16_t); | 671 | return q->samples_per_frame * sizeof(int32_t); |
670 | } | 672 | } |
671 | 673 | ||
672 | 674 | ||
@@ -677,7 +679,7 @@ static int decode_subpacket(COOKContext *q, const uint8_t *inbuffer, | |||
677 | */ | 679 | */ |
678 | 680 | ||
679 | int cook_decode_frame(RMContext *rmctx,COOKContext *q, | 681 | int cook_decode_frame(RMContext *rmctx,COOKContext *q, |
680 | int16_t *outbuffer, int *data_size, | 682 | int32_t *outbuffer, int *data_size, |
681 | const uint8_t *inbuffer, int buf_size) { | 683 | const uint8_t *inbuffer, int buf_size) { |
682 | //COOKContext *q = avctx->priv_data; | 684 | //COOKContext *q = avctx->priv_data; |
683 | //COOKContext *q; | 685 | //COOKContext *q; |
diff --git a/apps/codecs/libcook/cook.h b/apps/codecs/libcook/cook.h index 0672553895..93abf9a52d 100644 --- a/apps/codecs/libcook/cook.h +++ b/apps/codecs/libcook/cook.h | |||
@@ -97,6 +97,6 @@ typedef struct cook { | |||
97 | 97 | ||
98 | int cook_decode_init(RMContext *rmctx, COOKContext *q); | 98 | int cook_decode_init(RMContext *rmctx, COOKContext *q); |
99 | int cook_decode_frame(RMContext *rmctx,COOKContext *q, | 99 | int cook_decode_frame(RMContext *rmctx,COOKContext *q, |
100 | int16_t *outbuffer, int *data_size, | 100 | int32_t *outbuffer, int *data_size, |
101 | const uint8_t *inbuffer, int buf_size); | 101 | const uint8_t *inbuffer, int buf_size); |
102 | #endif /*_COOK_H */ | 102 | #endif /*_COOK_H */ |
diff --git a/apps/codecs/libcook/cook_fixpoint.h b/apps/codecs/libcook/cook_fixpoint.h index 30e5a3eee2..57c217dc43 100644 --- a/apps/codecs/libcook/cook_fixpoint.h +++ b/apps/codecs/libcook/cook_fixpoint.h | |||
@@ -79,28 +79,28 @@ static inline FIXP fixp_pow2_neg(FIXP x, int i) | |||
79 | #else | 79 | #else |
80 | static inline FIXP fixp_mult_su(FIXP a, FIXPU b) | 80 | static inline FIXP fixp_mult_su(FIXP a, FIXPU b) |
81 | { | 81 | { |
82 | int32_t hb = (a >> 16) * b; | 82 | int32_t hb = (a >> 16) * b; |
83 | uint32_t lb = (a & 0xffff) * b; | 83 | uint32_t lb = (a & 0xffff) * b; |
84 | 84 | ||
85 | return hb + (lb >> 16) + ((lb & 0x8000) >> 15); | 85 | return hb + (lb >> 16) + ((lb & 0x8000) >> 15); |
86 | } | 86 | } |
87 | #endif | 87 | #endif |
88 | 88 | ||
89 | /* Faster version of the above using 32x32=64 bit multiply */ | 89 | /* Faster version of the above using 32x32=64 bit multiply */ |
90 | #ifdef ROCKBOX | 90 | #ifdef ROCKBOX |
91 | #define fixmul31(x,y) (MULT31(x,y)) | 91 | #define fixmul31(x,y) (MULT31(x,y)) |
92 | #else | 92 | #else |
93 | static inline int32_t fixmul31(int32_t x, int32_t y) | 93 | static inline int32_t fixmul31(int32_t x, int32_t y) |
94 | { | 94 | { |
95 | int64_t temp; | 95 | int64_t temp; |
96 | 96 | ||
97 | temp = x; | 97 | temp = x; |
98 | temp *= y; | 98 | temp *= y; |
99 | 99 | ||
100 | temp >>= 31; //16+31-16 = 31 bits | 100 | temp >>= 31; //16+31-16 = 31 bits |
101 | 101 | ||
102 | return (int32_t)temp; | 102 | return (int32_t)temp; |
103 | } | 103 | } |
104 | #endif | 104 | #endif |
105 | 105 | ||
106 | /** | 106 | /** |
@@ -166,7 +166,8 @@ static void scalar_dequant_math(COOKContext *q, int index, | |||
166 | */ | 166 | */ |
167 | #include "../lib/mdct_lookup.h" | 167 | #include "../lib/mdct_lookup.h" |
168 | 168 | ||
169 | static inline void imlt_math(COOKContext *q, FIXP *in) | 169 | void imlt_math(COOKContext *q, FIXP *in) ICODE_ATTR; |
170 | void imlt_math(COOKContext *q, FIXP *in) | ||
170 | { | 171 | { |
171 | const int n = q->samples_per_channel; | 172 | const int n = q->samples_per_channel; |
172 | const int step = 2 << (10 - av_log2(n)); | 173 | const int step = 2 << (10 - av_log2(n)); |
@@ -203,7 +204,8 @@ static inline void imlt_math(COOKContext *q, FIXP *in) | |||
203 | * @param gain gain correction to apply first to output buffer | 204 | * @param gain gain correction to apply first to output buffer |
204 | * @param buffer data to overlap | 205 | * @param buffer data to overlap |
205 | */ | 206 | */ |
206 | static inline void overlap_math(COOKContext *q, int gain, FIXP buffer[]) | 207 | void overlap_math(COOKContext *q, int gain, FIXP buffer[]) ICODE_ATTR; |
208 | void overlap_math(COOKContext *q, int gain, FIXP buffer[]) | ||
207 | { | 209 | { |
208 | int i; | 210 | int i; |
209 | #ifdef ROCKBOX | 211 | #ifdef ROCKBOX |
@@ -280,33 +282,3 @@ static inline FIXP cplscale_math(FIXP x, int table, int i) | |||
280 | { | 282 | { |
281 | return fixp_mult_su(x, cplscales[table-2][i]); | 283 | return fixp_mult_su(x, cplscales[table-2][i]); |
282 | } | 284 | } |
283 | |||
284 | |||
285 | /** | ||
286 | * Final converion from floating point values to | ||
287 | * signed, 16 bit sound samples. Round and clip. | ||
288 | * | ||
289 | * @param q pointer to the COOKContext | ||
290 | * @param out pointer to the output buffer | ||
291 | * @param chan 0: left or single channel, 1: right channel | ||
292 | */ | ||
293 | static inline void output_math(COOKContext *q, register int16_t *out, int chan) | ||
294 | { | ||
295 | #ifdef ROCKBOX | ||
296 | register REAL_T * mono_output_ptr = q->mono_mdct_output; | ||
297 | register REAL_T * mono_output_end = mono_output_ptr + q->samples_per_channel; | ||
298 | out += chan; | ||
299 | const int STEP = q->nb_channels; | ||
300 | while( mono_output_ptr < mono_output_end ) | ||
301 | { | ||
302 | *out = CLIP_TO_15(fixp_pow2_neg(*mono_output_ptr++, 11)); | ||
303 | out += STEP; | ||
304 | } | ||
305 | #else | ||
306 | int j; | ||
307 | for (j = 0; j < q->samples_per_channel; j++) { | ||
308 | out[chan + q->nb_channels * j] = | ||
309 | av_clip(fixp_pow2(q->mono_mdct_output[j], -11), -32768, 32767); | ||
310 | } | ||
311 | #endif | ||
312 | } | ||
diff --git a/apps/codecs/libcook/main.c b/apps/codecs/libcook/main.c index 3f5d3e8528..71d02fb736 100644 --- a/apps/codecs/libcook/main.c +++ b/apps/codecs/libcook/main.c | |||
@@ -120,7 +120,7 @@ int main(int argc, char *argv[]) | |||
120 | char filename[15]; | 120 | char filename[15]; |
121 | int fd_out; | 121 | int fd_out; |
122 | #endif | 122 | #endif |
123 | int16_t outbuf[2048]; | 123 | int32_t outbuf[2048]; |
124 | uint16_t fs,sps,h; | 124 | uint16_t fs,sps,h; |
125 | uint32_t packet_count; | 125 | uint32_t packet_count; |
126 | COOKContext q; | 126 | COOKContext q; |