diff options
author | Dave Bryant <bryant@rockbox.org> | 2006-02-06 07:40:35 +0000 |
---|---|---|
committer | Dave Bryant <bryant@rockbox.org> | 2006-02-06 07:40:35 +0000 |
commit | ff40af42babedfccd767ccf48a78e9a8eecb9a95 (patch) | |
tree | 6885acab801d878639159b6d36b98ef6a8549b8b | |
parent | f17e35d27b7c16f2f2962a15b22cc8db832c1183 (diff) | |
download | rockbox-ff40af42babedfccd767ccf48a78e9a8eecb9a95.tar.gz rockbox-ff40af42babedfccd767ccf48a78e9a8eecb9a95.zip |
Streamlined WavPack decoder by utilizing dsp functionality where it was
applicable (like mono conversion and clipping) and eliminating the
conversion to 16-bit samples (everything is now returned as 28-bit).
This reduced boost ratio (on iRiver) by about 7% on those tracks that
require it.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8598 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/codecs/libwavpack/unpack.c | 50 | ||||
-rw-r--r-- | apps/codecs/wavpack.c | 76 |
2 files changed, 19 insertions, 107 deletions
diff --git a/apps/codecs/libwavpack/unpack.c b/apps/codecs/libwavpack/unpack.c index a3a689ebb6..8f5c1ee46f 100644 --- a/apps/codecs/libwavpack/unpack.c +++ b/apps/codecs/libwavpack/unpack.c | |||
@@ -675,11 +675,17 @@ static void decorr_mono_pass (struct decorr_pass *dpp, long *buffer, long sample | |||
675 | // it is clipped and shifted in a single operation. Otherwise, if it's | 675 | // it is clipped and shifted in a single operation. Otherwise, if it's |
676 | // lossless then the last step is to apply the final shift (if any). | 676 | // lossless then the last step is to apply the final shift (if any). |
677 | 677 | ||
678 | // This function has been modified for RockBox to return all integer samples | ||
679 | // as 28-bits, and clipping (for lossy mode) has been eliminated because this | ||
680 | // now happens in the dsp module. | ||
681 | |||
678 | static void fixup_samples (WavpackStream *wps, long *buffer, ulong sample_count) | 682 | static void fixup_samples (WavpackStream *wps, long *buffer, ulong sample_count) |
679 | { | 683 | { |
680 | ulong flags = wps->wphdr.flags; | 684 | ulong flags = wps->wphdr.flags; |
681 | int shift = (flags & SHIFT_MASK) >> SHIFT_LSB; | 685 | int shift = (flags & SHIFT_MASK) >> SHIFT_LSB; |
682 | 686 | ||
687 | shift += 20 - (flags & BYTES_STORED) * 8; // this provides RockBox with 28-bit data | ||
688 | |||
683 | if (flags & FLOAT_DATA) { | 689 | if (flags & FLOAT_DATA) { |
684 | float_values (wps, buffer, (flags & MONO_FLAG) ? sample_count : sample_count * 2); | 690 | float_values (wps, buffer, (flags & MONO_FLAG) ? sample_count : sample_count * 2); |
685 | return; | 691 | return; |
@@ -689,7 +695,6 @@ static void fixup_samples (WavpackStream *wps, long *buffer, ulong sample_count) | |||
689 | ulong count = (flags & MONO_FLAG) ? sample_count : sample_count * 2; | 695 | ulong count = (flags & MONO_FLAG) ? sample_count : sample_count * 2; |
690 | int sent_bits = wps->int32_sent_bits, zeros = wps->int32_zeros; | 696 | int sent_bits = wps->int32_sent_bits, zeros = wps->int32_zeros; |
691 | int ones = wps->int32_ones, dups = wps->int32_dups; | 697 | int ones = wps->int32_ones, dups = wps->int32_dups; |
692 | // ulong mask = (1 << sent_bits) - 1; | ||
693 | long *dptr = buffer; | 698 | long *dptr = buffer; |
694 | 699 | ||
695 | if (!(flags & HYBRID_FLAG) && !sent_bits && (zeros + ones + dups)) | 700 | if (!(flags & HYBRID_FLAG) && !sent_bits && (zeros + ones + dups)) |
@@ -707,50 +712,21 @@ static void fixup_samples (WavpackStream *wps, long *buffer, ulong sample_count) | |||
707 | shift += zeros + sent_bits + ones + dups; | 712 | shift += zeros + sent_bits + ones + dups; |
708 | } | 713 | } |
709 | 714 | ||
710 | if (flags & HYBRID_FLAG) { | 715 | if (shift > 0) { |
711 | long min_value, max_value, min_shifted, max_shifted; | ||
712 | |||
713 | switch (flags & BYTES_STORED) { | ||
714 | case 0: | ||
715 | min_shifted = (min_value = -128 >> shift) << shift; | ||
716 | max_shifted = (max_value = 127 >> shift) << shift; | ||
717 | break; | ||
718 | |||
719 | case 1: | ||
720 | min_shifted = (min_value = -32768 >> shift) << shift; | ||
721 | max_shifted = (max_value = 32767 >> shift) << shift; | ||
722 | break; | ||
723 | |||
724 | case 2: | ||
725 | min_shifted = (min_value = -8388608 >> shift) << shift; | ||
726 | max_shifted = (max_value = 8388607 >> shift) << shift; | ||
727 | break; | ||
728 | |||
729 | case 3: | ||
730 | default: | ||
731 | min_shifted = (min_value = (long) 0x80000000 >> shift) << shift; | ||
732 | max_shifted = (max_value = (long) 0x7FFFFFFF >> shift) << shift; | ||
733 | break; | ||
734 | } | ||
735 | |||
736 | if (!(flags & MONO_FLAG)) | 716 | if (!(flags & MONO_FLAG)) |
737 | sample_count *= 2; | 717 | sample_count *= 2; |
738 | 718 | ||
739 | while (sample_count--) { | 719 | while (sample_count--) |
740 | if (*buffer < min_value) | 720 | *buffer++ <<= shift; |
741 | *buffer++ = min_shifted; | ||
742 | else if (*buffer > max_value) | ||
743 | *buffer++ = max_shifted; | ||
744 | else | ||
745 | *buffer++ <<= shift; | ||
746 | } | ||
747 | } | 721 | } |
748 | else if (shift) { | 722 | else if (shift < 0) { |
723 | shift = -shift; | ||
724 | |||
749 | if (!(flags & MONO_FLAG)) | 725 | if (!(flags & MONO_FLAG)) |
750 | sample_count *= 2; | 726 | sample_count *= 2; |
751 | 727 | ||
752 | while (sample_count--) | 728 | while (sample_count--) |
753 | *buffer++ <<= shift; | 729 | *buffer++ >>= shift; |
754 | } | 730 | } |
755 | } | 731 | } |
756 | 732 | ||
diff --git a/apps/codecs/wavpack.c b/apps/codecs/wavpack.c index 19c7581e29..ee21347b73 100644 --- a/apps/codecs/wavpack.c +++ b/apps/codecs/wavpack.c | |||
@@ -24,9 +24,6 @@ CODEC_HEADER | |||
24 | 24 | ||
25 | static struct codec_api *ci; | 25 | static struct codec_api *ci; |
26 | 26 | ||
27 | #define FORCE_DSP_USE /* fixes some WavPack bugs; adds about 12% to boost ratio | ||
28 | (when DSP would not have been used) */ | ||
29 | |||
30 | #define BUFFER_SIZE 4096 | 27 | #define BUFFER_SIZE 4096 |
31 | 28 | ||
32 | static long temp_buffer [BUFFER_SIZE] IBSS_ATTR; | 29 | static long temp_buffer [BUFFER_SIZE] IBSS_ATTR; |
@@ -66,8 +63,7 @@ enum codec_status codec_start(struct codec_api* api) | |||
66 | ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*128)); | 63 | ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*128)); |
67 | 64 | ||
68 | ci->configure(DSP_DITHER, (bool *)false); | 65 | ci->configure(DSP_DITHER, (bool *)false); |
69 | ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_INTERLEAVED); | 66 | ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(27)); // should be 28... |
70 | ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(16)); | ||
71 | 67 | ||
72 | next_track: | 68 | next_track: |
73 | 69 | ||
@@ -79,20 +75,9 @@ enum codec_status codec_start(struct codec_api* api) | |||
79 | while (!*ci->taginfo_ready && !ci->stop_codec) | 75 | while (!*ci->taginfo_ready && !ci->stop_codec) |
80 | ci->sleep(1); | 76 | ci->sleep(1); |
81 | 77 | ||
82 | #ifdef FORCE_DSP_USE | ||
83 | ci->configure(CODEC_DSP_ENABLE, (bool *)true); | 78 | ci->configure(CODEC_DSP_ENABLE, (bool *)true); |
84 | ci->configure(DSP_SET_FREQUENCY, (long *)(ci->id3->frequency)); | 79 | ci->configure(DSP_SET_FREQUENCY, (long *)(ci->id3->frequency)); |
85 | codec_set_replaygain(ci->id3); | 80 | codec_set_replaygain(ci->id3); |
86 | #else | ||
87 | if (ci->id3->frequency != NATIVE_FREQUENCY || | ||
88 | ci->global_settings->replaygain) { | ||
89 | ci->configure(CODEC_DSP_ENABLE, (bool *)true); | ||
90 | ci->configure(DSP_SET_FREQUENCY, (long *)(ci->id3->frequency)); | ||
91 | codec_set_replaygain(ci->id3); | ||
92 | } | ||
93 | else | ||
94 | ci->configure(CODEC_DSP_ENABLE, (bool *)false); | ||
95 | #endif | ||
96 | 81 | ||
97 | /* Create a decoder instance */ | 82 | /* Create a decoder instance */ |
98 | wpc = WavpackOpenFileInput (read_callback, error); | 83 | wpc = WavpackOpenFileInput (read_callback, error); |
@@ -104,6 +89,7 @@ enum codec_status codec_start(struct codec_api* api) | |||
104 | 89 | ||
105 | bps = WavpackGetBytesPerSample (wpc); | 90 | bps = WavpackGetBytesPerSample (wpc); |
106 | nchans = WavpackGetReducedChannels (wpc); | 91 | nchans = WavpackGetReducedChannels (wpc); |
92 | ci->configure(DSP_SET_STEREO_MODE, nchans == 2 ? (int *)STEREO_INTERLEAVED : (int *)STEREO_MONO); | ||
107 | sr_100 = ci->id3->frequency / 100; | 93 | sr_100 = ci->id3->frequency / 100; |
108 | 94 | ||
109 | ci->set_elapsed (0); | 95 | ci->set_elapsed (0); |
@@ -141,71 +127,21 @@ enum codec_status codec_start(struct codec_api* api) | |||
141 | ci->yield (); | 127 | ci->yield (); |
142 | } | 128 | } |
143 | 129 | ||
144 | nsamples = WavpackUnpackSamples (wpc, temp_buffer, BUFFER_SIZE / 2); | 130 | nsamples = WavpackUnpackSamples (wpc, temp_buffer, BUFFER_SIZE / nchans); |
145 | 131 | ||
146 | if (!nsamples || ci->stop_codec || ci->reload_codec) | 132 | if (!nsamples || ci->stop_codec || ci->reload_codec) |
147 | break; | 133 | break; |
148 | 134 | ||
149 | /* convert mono to stereo here, in place */ | 135 | ci->yield (); |
150 | |||
151 | if (nchans == 1) { | ||
152 | long *dst = temp_buffer + (nsamples * 2); | ||
153 | long *src = temp_buffer + nsamples; | ||
154 | long count = nsamples; | ||
155 | |||
156 | while (count--) { | ||
157 | *--dst = *--src; | ||
158 | *--dst = *src; | ||
159 | if (!(count & 0x7f)) | ||
160 | ci->yield (); | ||
161 | } | ||
162 | } | ||
163 | |||
164 | if (bps == 1) { | ||
165 | short *dst = (short *) temp_buffer; | ||
166 | long *src = temp_buffer; | ||
167 | long count = nsamples; | ||
168 | |||
169 | while (count--) { | ||
170 | *dst++ = *src++ << 8; | ||
171 | *dst++ = *src++ << 8; | ||
172 | if (!(count & 0x7f)) | ||
173 | ci->yield (); | ||
174 | } | ||
175 | } | ||
176 | else if (bps == 2) { | ||
177 | short *dst = (short *) temp_buffer; | ||
178 | long *src = temp_buffer; | ||
179 | long count = nsamples; | ||
180 | |||
181 | while (count--) { | ||
182 | *dst++ = *src++; | ||
183 | *dst++ = *src++; | ||
184 | if (!(count & 0x7f)) | ||
185 | ci->yield (); | ||
186 | } | ||
187 | } | ||
188 | else { | ||
189 | short *dst = (short *) temp_buffer; | ||
190 | int shift = (bps - 2) * 8; | ||
191 | long *src = temp_buffer; | ||
192 | long count = nsamples; | ||
193 | |||
194 | while (count--) { | ||
195 | *dst++ = *src++ >> shift; | ||
196 | *dst++ = *src++ >> shift; | ||
197 | if (!(count & 0x7f)) | ||
198 | ci->yield (); | ||
199 | } | ||
200 | } | ||
201 | 136 | ||
202 | if (ci->stop_codec || ci->reload_codec) | 137 | if (ci->stop_codec || ci->reload_codec) |
203 | break; | 138 | break; |
204 | 139 | ||
205 | while (!ci->pcmbuf_insert ((char *) temp_buffer, nsamples * 4)) | 140 | while (!ci->pcmbuf_insert ((char *) temp_buffer, nsamples * nchans * 4)) |
206 | ci->sleep (1); | 141 | ci->sleep (1); |
207 | 142 | ||
208 | ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10); | 143 | ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10); |
144 | ci->yield (); | ||
209 | } | 145 | } |
210 | 146 | ||
211 | if (ci->request_next_track()) | 147 | if (ci->request_next_track()) |