diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2007-02-07 00:51:50 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2007-02-07 00:51:50 +0000 |
commit | aba6ca0881d1481b4047b2d7834d70ca2eb5c64b (patch) | |
tree | 6635b98840dcf4936b3c1ca641c00c32ea1b3e7f /apps/dsp.c | |
parent | dd50c863e60488662dee8f28f7292389ade42bac (diff) | |
download | rockbox-aba6ca0881d1481b4047b2d7834d70ca2eb5c64b.tar.gz rockbox-aba6ca0881d1481b4047b2d7834d70ca2eb5c64b.zip |
Fix resampling clicking as much as possible at the moment. 1) Upsampling clicked because of size inaccuracies returned by DSP. Fix by simplifying audio system to use per-channel sample count from codec to pcm buffer. 2) Downsampling affected by 1) and was often starting passed the end of the data when not enough was available to generate an output sample. Fix by clamping input range to last sample in buffer and using the last sample value in the buffer. A perfect fix will require a double buffering scheme on the resampler to sufficient data during small data transients on both ends at all times of the down ratio on input and the up ratio on output.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12218 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/dsp.c')
-rw-r--r-- | apps/dsp.c | 130 |
1 files changed, 53 insertions, 77 deletions
diff --git a/apps/dsp.c b/apps/dsp.c index c4630ada77..f7eb48ed03 100644 --- a/apps/dsp.c +++ b/apps/dsp.c | |||
@@ -40,8 +40,8 @@ | |||
40 | #define WORD_FRACBITS 27 | 40 | #define WORD_FRACBITS 27 |
41 | 41 | ||
42 | #define NATIVE_DEPTH 16 | 42 | #define NATIVE_DEPTH 16 |
43 | #define SAMPLE_BUF_SIZE 256 | 43 | #define SAMPLE_BUF_COUNT 256 |
44 | #define RESAMPLE_BUF_SIZE (256 * 4) /* Enough for 11,025 Hz -> 44,100 Hz*/ | 44 | #define RESAMPLE_BUF_COUNT (256 * 4) /* Enough for 11,025 Hz -> 44,100 Hz*/ |
45 | #define DEFAULT_GAIN 0x01000000 | 45 | #define DEFAULT_GAIN 0x01000000 |
46 | 46 | ||
47 | struct dsp_config | 47 | struct dsp_config |
@@ -116,8 +116,8 @@ static struct dsp_config *dsp; | |||
116 | * of copying needed is minimized for that case. | 116 | * of copying needed is minimized for that case. |
117 | */ | 117 | */ |
118 | 118 | ||
119 | static int32_t sample_buf[SAMPLE_BUF_SIZE] IBSS_ATTR; | 119 | static int32_t sample_buf[SAMPLE_BUF_COUNT] IBSS_ATTR; |
120 | static int32_t resample_buf[RESAMPLE_BUF_SIZE] IBSS_ATTR; | 120 | static int32_t resample_buf[RESAMPLE_BUF_COUNT] IBSS_ATTR; |
121 | 121 | ||
122 | int sound_get_pitch(void) | 122 | int sound_get_pitch(void) |
123 | { | 123 | { |
@@ -139,14 +139,14 @@ void sound_set_pitch(int permille) | |||
139 | */ | 139 | */ |
140 | static int convert_to_internal(const char* src[], int count, int32_t* dst[]) | 140 | static int convert_to_internal(const char* src[], int count, int32_t* dst[]) |
141 | { | 141 | { |
142 | count = MIN(SAMPLE_BUF_SIZE / 2, count); | 142 | count = MIN(SAMPLE_BUF_COUNT / 2, count); |
143 | 143 | ||
144 | if ((dsp->sample_depth <= NATIVE_DEPTH) | 144 | if ((dsp->sample_depth <= NATIVE_DEPTH) |
145 | || (dsp->stereo_mode == STEREO_INTERLEAVED)) | 145 | || (dsp->stereo_mode == STEREO_INTERLEAVED)) |
146 | { | 146 | { |
147 | dst[0] = &sample_buf[0]; | 147 | dst[0] = &sample_buf[0]; |
148 | dst[1] = (dsp->stereo_mode == STEREO_MONO) | 148 | dst[1] = (dsp->stereo_mode == STEREO_MONO) |
149 | ? dst[0] : &sample_buf[SAMPLE_BUF_SIZE / 2]; | 149 | ? dst[0] : &sample_buf[SAMPLE_BUF_COUNT / 2]; |
150 | } | 150 | } |
151 | else | 151 | else |
152 | { | 152 | { |
@@ -231,7 +231,7 @@ static void resampler_set_delta(int frequency) | |||
231 | 231 | ||
232 | /* TODO: we really should have a separate set of resample functions for both | 232 | /* TODO: we really should have a separate set of resample functions for both |
233 | mono and stereo to avoid all this internal branching and looping. */ | 233 | mono and stereo to avoid all this internal branching and looping. */ |
234 | static long downsample(int32_t **dst, int32_t **src, int count, | 234 | static int downsample(int32_t **dst, int32_t **src, int count, |
235 | struct resample_data *r) | 235 | struct resample_data *r) |
236 | { | 236 | { |
237 | long phase = r->phase; | 237 | long phase = r->phase; |
@@ -246,11 +246,14 @@ static long downsample(int32_t **dst, int32_t **src, int count, | |||
246 | last_sample = r->last_sample[j]; | 246 | last_sample = r->last_sample[j]; |
247 | /* Do we need last sample of previous frame for interpolation? */ | 247 | /* Do we need last sample of previous frame for interpolation? */ |
248 | if (pos > 0) | 248 | if (pos > 0) |
249 | { | ||
250 | last_sample = src[j][pos - 1]; | 249 | last_sample = src[j][pos - 1]; |
251 | } | 250 | |
252 | *d[j]++ = last_sample + FRACMUL((phase & 0xffff) << 15, | 251 | /* Be sure starting position isn't passed the available data */ |
253 | src[j][pos] - last_sample); | 252 | if (pos < count) |
253 | *d[j]++ = last_sample + FRACMUL((phase & 0xffff) << 15, | ||
254 | src[j][pos] - last_sample); | ||
255 | else /* This is kinda nasty but works somewhat well for now */ | ||
256 | *d[j]++ = src[j][count - 1]; | ||
254 | } | 257 | } |
255 | phase += delta; | 258 | phase += delta; |
256 | 259 | ||
@@ -316,7 +319,7 @@ static inline int resample(int32_t* src[], int count) | |||
316 | 319 | ||
317 | if (dsp->frequency != NATIVE_FREQUENCY) | 320 | if (dsp->frequency != NATIVE_FREQUENCY) |
318 | { | 321 | { |
319 | int32_t* dst[2] = {&resample_buf[0], &resample_buf[RESAMPLE_BUF_SIZE / 2]}; | 322 | int32_t* dst[2] = {&resample_buf[0], &resample_buf[RESAMPLE_BUF_COUNT / 2]}; |
320 | 323 | ||
321 | if (dsp->frequency < NATIVE_FREQUENCY) | 324 | if (dsp->frequency < NATIVE_FREQUENCY) |
322 | { | 325 | { |
@@ -619,7 +622,7 @@ static void apply_gain(int32_t* _src[], int _count) | |||
619 | 622 | ||
620 | if (s0 != s1) | 623 | if (s0 != s1) |
621 | { | 624 | { |
622 | d = &sample_buf[SAMPLE_BUF_SIZE / 2]; | 625 | d = &sample_buf[SAMPLE_BUF_COUNT / 2]; |
623 | src[1] = d; | 626 | src[1] = d; |
624 | s = *s1++; | 627 | s = *s1++; |
625 | 628 | ||
@@ -736,18 +739,17 @@ static void write_samples(short* dst, int32_t* src[], int count) | |||
736 | } | 739 | } |
737 | 740 | ||
738 | /* Process and convert src audio to dst based on the DSP configuration, | 741 | /* Process and convert src audio to dst based on the DSP configuration, |
739 | * reading size bytes of audio data. dst is assumed to be large enough; use | 742 | * reading count number of audio samples. dst is assumed to be large |
740 | * dst_get_dest_size() to get the required size. src is an array of | 743 | * enough; use dsp_output_count() to get the required number. src is an |
741 | * pointers; for mono and interleaved stereo, it contains one pointer to the | 744 | * array of pointers; for mono and interleaved stereo, it contains one |
742 | * start of the audio data; for non-interleaved stereo, it contains two | 745 | * pointer to the start of the audio data and the other is ignored; for |
743 | * pointers, one for each audio channel. Returns number of bytes written to | 746 | * non-interleaved stereo, it contains two pointers, one for each audio |
744 | * dest. | 747 | * channel. Returns number of bytes written to dst. |
745 | */ | 748 | */ |
746 | long dsp_process(char* dst, const char* src[], long size) | 749 | int dsp_process(char *dst, const char *src[], int count) |
747 | { | 750 | { |
748 | int32_t* tmp[2]; | 751 | int32_t* tmp[2]; |
749 | long written = 0; | 752 | int written = 0; |
750 | long factor; | ||
751 | int samples; | 753 | int samples; |
752 | 754 | ||
753 | #if defined(CPU_COLDFIRE) && !defined(SIMULATOR) | 755 | #if defined(CPU_COLDFIRE) && !defined(SIMULATOR) |
@@ -759,14 +761,12 @@ long dsp_process(char* dst, const char* src[], long size) | |||
759 | 761 | ||
760 | dsp = &dsp_conf[current_codec]; | 762 | dsp = &dsp_conf[current_codec]; |
761 | 763 | ||
762 | factor = (dsp->stereo_mode != STEREO_MONO) ? 2 : 1; | ||
763 | size /= dsp->sample_bytes * factor; | ||
764 | dsp_set_replaygain(false); | 764 | dsp_set_replaygain(false); |
765 | 765 | ||
766 | while (size > 0) | 766 | while (count > 0) |
767 | { | 767 | { |
768 | samples = convert_to_internal(src, size, tmp); | 768 | samples = convert_to_internal(src, count, tmp); |
769 | size -= samples; | 769 | count -= samples; |
770 | apply_gain(tmp, samples); | 770 | apply_gain(tmp, samples); |
771 | samples = resample(tmp, samples); | 771 | samples = resample(tmp, samples); |
772 | if (dsp->crossfeed_enabled && dsp->stereo_mode != STEREO_MONO) | 772 | if (dsp->crossfeed_enabled && dsp->stereo_mode != STEREO_MONO) |
@@ -780,85 +780,61 @@ long dsp_process(char* dst, const char* src[], long size) | |||
780 | dst += samples * sizeof(short) * 2; | 780 | dst += samples * sizeof(short) * 2; |
781 | yield(); | 781 | yield(); |
782 | } | 782 | } |
783 | |||
783 | #if defined(CPU_COLDFIRE) && !defined(SIMULATOR) | 784 | #if defined(CPU_COLDFIRE) && !defined(SIMULATOR) |
784 | /* set old macsr again */ | 785 | /* set old macsr again */ |
785 | coldfire_set_macsr(old_macsr); | 786 | coldfire_set_macsr(old_macsr); |
786 | #endif | 787 | #endif |
787 | return written * sizeof(short) * 2; | 788 | return written; |
788 | } | 789 | } |
789 | 790 | ||
790 | /* Given size bytes of input data, calculate the maximum number of bytes of | 791 | /* Given count number of input samples, calculate the maximum number of |
791 | * output data that would be generated (the calculation is not entirely | 792 | * samples of output data that would be generated (the calculation is not |
792 | * exact and rounds upwards to be on the safe side; during resampling, | 793 | * entirely exact and rounds upwards to be on the safe side; during |
793 | * the number of samples generated depends on the current state of the | 794 | * resampling, the number of samples generated depends on the current state |
794 | * resampler). | 795 | * of the resampler). |
795 | */ | 796 | */ |
796 | /* dsp_input_size MUST be called afterwards */ | 797 | /* dsp_input_size MUST be called afterwards */ |
797 | long dsp_output_size(long size) | 798 | int dsp_output_count(int count) |
798 | { | 799 | { |
799 | dsp = &dsp_conf[current_codec]; | 800 | dsp = &dsp_conf[current_codec]; |
800 | 801 | ||
801 | if (dsp->sample_depth > NATIVE_DEPTH) | ||
802 | { | ||
803 | size /= 2; | ||
804 | } | ||
805 | |||
806 | if (dsp->frequency != NATIVE_FREQUENCY) | 802 | if (dsp->frequency != NATIVE_FREQUENCY) |
807 | { | 803 | { |
808 | size = (long) ((((unsigned long) size * NATIVE_FREQUENCY) | 804 | count = (int)(((unsigned long)count * NATIVE_FREQUENCY |
809 | + (dsp->frequency - 1)) / dsp->frequency); | 805 | + (dsp->frequency - 1)) / dsp->frequency); |
810 | } | ||
811 | |||
812 | /* round to the next multiple of 2 (these are shorts) */ | ||
813 | size = (size + 1) & ~1; | ||
814 | |||
815 | if (dsp->stereo_mode == STEREO_MONO) | ||
816 | { | ||
817 | size *= 2; | ||
818 | } | 806 | } |
819 | 807 | ||
820 | /* now we have the size in bytes for two resampled channels, | 808 | /* Now we have the resampled sample count which must not exceed |
821 | * and the size in (short) must not exceed RESAMPLE_BUF_SIZE to | 809 | * RESAMPLE_BUF_COUNT/2 to avoid resample buffer overflow. One |
822 | * avoid resample buffer overflow. One must call dsp_input_size() | 810 | * must call dsp_input_count() to get the correct input sample |
823 | * to get the correct input buffer size. */ | 811 | * count. |
824 | if (size > RESAMPLE_BUF_SIZE*2) | 812 | */ |
825 | size = RESAMPLE_BUF_SIZE*2; | 813 | if (count > RESAMPLE_BUF_COUNT/2) |
814 | count = RESAMPLE_BUF_COUNT/2; | ||
826 | 815 | ||
827 | return size; | 816 | return count; |
828 | } | 817 | } |
829 | 818 | ||
830 | /* Given size bytes of output buffer, calculate number of bytes of input | 819 | /* Given count output samples, calculate number of input samples |
831 | * data that would be consumed in order to fill the output buffer. | 820 | * that would be consumed in order to fill the output buffer. |
832 | */ | 821 | */ |
833 | long dsp_input_size(long size) | 822 | int dsp_input_count(int count) |
834 | { | 823 | { |
835 | dsp = &dsp_conf[current_codec]; | 824 | dsp = &dsp_conf[current_codec]; |
836 | |||
837 | /* convert to number of output stereo samples. */ | ||
838 | size /= 2; | ||
839 | 825 | ||
840 | /* Mono means we need half input samples to fill the output buffer */ | 826 | /* count is now the number of resampled input samples. Convert to |
841 | if (dsp->stereo_mode == STEREO_MONO) | ||
842 | size /= 2; | ||
843 | |||
844 | /* size is now the number of resampled input samples. Convert to | ||
845 | original input samples. */ | 827 | original input samples. */ |
846 | if (dsp->frequency != NATIVE_FREQUENCY) | 828 | if (dsp->frequency != NATIVE_FREQUENCY) |
847 | { | 829 | { |
848 | /* Use the real resampling delta = | 830 | /* Use the real resampling delta = |
849 | * (unsigned long) dsp->frequency * 65536 / NATIVE_FREQUENCY, and | 831 | * dsp->frequency * 65536 / NATIVE_FREQUENCY, and |
850 | * round towards zero to avoid buffer overflows. */ | 832 | * round towards zero to avoid buffer overflows. */ |
851 | size = ((unsigned long)size * | 833 | count = (int)(((unsigned long)count * |
852 | resample_data[current_codec].delta) >> 16; | 834 | resample_data[current_codec].delta) >> 16); |
853 | } | 835 | } |
854 | 836 | ||
855 | /* Convert back to bytes. */ | 837 | return count; |
856 | if (dsp->sample_depth > NATIVE_DEPTH) | ||
857 | size *= 4; | ||
858 | else | ||
859 | size *= 2; | ||
860 | |||
861 | return size; | ||
862 | } | 838 | } |
863 | 839 | ||
864 | int dsp_stereo_mode(void) | 840 | int dsp_stereo_mode(void) |