diff options
Diffstat (limited to 'apps/dsp.c')
-rw-r--r-- | apps/dsp.c | 122 |
1 files changed, 65 insertions, 57 deletions
diff --git a/apps/dsp.c b/apps/dsp.c index f10bdfe2a6..1da7372de6 100644 --- a/apps/dsp.c +++ b/apps/dsp.c | |||
@@ -112,7 +112,7 @@ struct crossfeed_data | |||
112 | int32_t coefs[3]; /* 04h - Coefficients for the shelving filter */ | 112 | int32_t coefs[3]; /* 04h - Coefficients for the shelving filter */ |
113 | int32_t history[4]; /* 10h - Format is x[n - 1], y[n - 1] for both channels */ | 113 | int32_t history[4]; /* 10h - Format is x[n - 1], y[n - 1] for both channels */ |
114 | int32_t delay[13][2]; /* 20h */ | 114 | int32_t delay[13][2]; /* 20h */ |
115 | int index; /* 88h - Current index into the delay line */ | 115 | int index; /* 88h - Current index/pointer into the delay line */ |
116 | /* 8ch */ | 116 | /* 8ch */ |
117 | }; | 117 | }; |
118 | 118 | ||
@@ -129,13 +129,21 @@ struct eq_state | |||
129 | 129 | ||
130 | /* Include header with defines which functions are implemented in assembly | 130 | /* Include header with defines which functions are implemented in assembly |
131 | code for the target */ | 131 | code for the target */ |
132 | #ifndef SIMULATOR | ||
133 | #include <dsp_asm.h> | 132 | #include <dsp_asm.h> |
134 | #endif | ||
135 | 133 | ||
136 | #ifndef DSP_HAVE_ASM_CROSSFEED | 134 | /* Typedefs keep things much neater in this case */ |
137 | static void apply_crossfeed(int32_t *buf[], int count); | 135 | typedef int (*sample_input_fn_type)(int count, const char *src[], |
138 | #endif | 136 | int32_t *dst[]); |
137 | typedef int (*resample_fn_type)(int count, struct dsp_data *data, | ||
138 | int32_t *src[], int32_t *dst[]); | ||
139 | typedef void (*sample_output_fn_type)(int count, struct dsp_data *data, | ||
140 | int32_t *src[], int16_t *dst); | ||
141 | /* If ACF_SWITCHPARAM is no longer needed, make apply_crossfeed of type | ||
142 | channels_process_fn_type since it is really just that */ | ||
143 | typedef void (*apply_crossfeed_fn_type)(ACF_SWITCHPARAM(int count, | ||
144 | int32_t *buf[])); | ||
145 | typedef void (*channels_process_fn_type)(int count, int32_t *buf[]); | ||
146 | |||
139 | /* | 147 | /* |
140 | ***************************************************************************/ | 148 | ***************************************************************************/ |
141 | 149 | ||
@@ -151,15 +159,13 @@ struct dsp_config | |||
151 | long gain; /* Note that this is in S8.23 format. */ | 159 | long gain; /* Note that this is in S8.23 format. */ |
152 | /* Functions that change depending upon settings - NULL if stage is | 160 | /* Functions that change depending upon settings - NULL if stage is |
153 | disabled */ | 161 | disabled */ |
154 | int (*input_samples)(int count, const char *src[], int32_t *dst[]); | 162 | sample_input_fn_type input_samples; |
155 | int (*resample)(int count, struct dsp_data *data, | 163 | resample_fn_type resample; |
156 | int32_t *src[], int32_t *dst[]); | 164 | sample_output_fn_type output_samples; |
157 | void (*output_samples)(int count, struct dsp_data *data, | ||
158 | int32_t *src[], int16_t *dst); | ||
159 | /* These will be NULL for the voice codec and is more economical that | 165 | /* These will be NULL for the voice codec and is more economical that |
160 | way */ | 166 | way */ |
161 | void (*apply_crossfeed)(int32_t *src[], int count); | 167 | apply_crossfeed_fn_type apply_crossfeed; |
162 | void (*channels_process)(int count, int32_t *buf[]); | 168 | channels_process_fn_type channels_process; |
163 | }; | 169 | }; |
164 | 170 | ||
165 | /* General DSP config */ | 171 | /* General DSP config */ |
@@ -169,7 +175,14 @@ static struct dither_data dither_data[2] IBSS_ATTR; /* 0=left, 1=right */ | |||
169 | static long dither_mask IBSS_ATTR; | 175 | static long dither_mask IBSS_ATTR; |
170 | static long dither_bias IBSS_ATTR; | 176 | static long dither_bias IBSS_ATTR; |
171 | /* Crossfeed */ | 177 | /* Crossfeed */ |
172 | struct crossfeed_data crossfeed_data IBSS_ATTR; /* A */ | 178 | struct crossfeed_data crossfeed_data IDATA_ATTR = /* A */ |
179 | { | ||
180 | #ifdef DSP_CROSSFEED_DELAY_PTR | ||
181 | .index = (intptr_t)crossfeed_data.delay | ||
182 | #else | ||
183 | .index = 0 | ||
184 | #endif | ||
185 | }; | ||
173 | /* Equalizer */ | 186 | /* Equalizer */ |
174 | static struct eq_state eq_data; /* A/V */ | 187 | static struct eq_state eq_data; /* A/V */ |
175 | #ifdef HAVE_SW_TONE_CONTROLS | 188 | #ifdef HAVE_SW_TONE_CONTROLS |
@@ -401,8 +414,7 @@ static int sample_input_gt_native_ni_stereo( | |||
401 | */ | 414 | */ |
402 | static void sample_input_new_format(void) | 415 | static void sample_input_new_format(void) |
403 | { | 416 | { |
404 | static int (* const sample_input_functions[])( | 417 | static const sample_input_fn_type sample_input_functions[] = |
405 | int count, const char* src[], int32_t *dst[]) = | ||
406 | { | 418 | { |
407 | [SAMPLE_INPUT_LE_NATIVE_MONO] = sample_input_lte_native_mono, | 419 | [SAMPLE_INPUT_LE_NATIVE_MONO] = sample_input_lte_native_mono, |
408 | [SAMPLE_INPUT_LE_NATIVE_I_STEREO] = sample_input_lte_native_i_stereo, | 420 | [SAMPLE_INPUT_LE_NATIVE_I_STEREO] = sample_input_lte_native_i_stereo, |
@@ -539,9 +551,7 @@ static void sample_output_dithered(int count, struct dsp_data *data, | |||
539 | */ | 551 | */ |
540 | static void sample_output_new_format(void) | 552 | static void sample_output_new_format(void) |
541 | { | 553 | { |
542 | static void (* const sample_output_functions[])( | 554 | static const sample_output_fn_type sample_output_functions[] = |
543 | int count, struct dsp_data *data, | ||
544 | int32_t *src[], int16_t *dst) = | ||
545 | { | 555 | { |
546 | sample_output_mono, | 556 | sample_output_mono, |
547 | sample_output_stereo, | 557 | sample_output_stereo, |
@@ -695,42 +705,13 @@ void dsp_dither_enable(bool enable) | |||
695 | switch_dsp(old_dsp); | 705 | switch_dsp(old_dsp); |
696 | } | 706 | } |
697 | 707 | ||
698 | /** | ||
699 | * dsp_set_crossfeed(bool enable) | ||
700 | * | ||
701 | * !DSPPARAMSYNC | ||
702 | * needs syncing with changes to the following dsp parameters: | ||
703 | * * dsp->stereo_mode (A) | ||
704 | */ | ||
705 | void dsp_set_crossfeed(bool enable) | ||
706 | { | ||
707 | crossfeed_enabled = enable; | ||
708 | audio_dsp->apply_crossfeed = | ||
709 | (enable && audio_dsp->data.num_channels > 1) | ||
710 | ? apply_crossfeed : NULL; | ||
711 | } | ||
712 | |||
713 | void dsp_set_crossfeed_direct_gain(int gain) | ||
714 | { | ||
715 | crossfeed_data.gain = get_replaygain_int(gain * -10) << 7; | ||
716 | } | ||
717 | |||
718 | void dsp_set_crossfeed_cross_params(long lf_gain, long hf_gain, long cutoff) | ||
719 | { | ||
720 | long g1 = get_replaygain_int(lf_gain * -10) << 3; | ||
721 | long g2 = get_replaygain_int(hf_gain * -10) << 3; | ||
722 | |||
723 | filter_shelf_coefs(0xffffffff/NATIVE_FREQUENCY*cutoff, g1, g2, | ||
724 | crossfeed_data.coefs); | ||
725 | } | ||
726 | |||
727 | /* Applies crossfeed to the stereo signal in src. | 708 | /* Applies crossfeed to the stereo signal in src. |
728 | * Crossfeed is a process where listening over speakers is simulated. This | 709 | * Crossfeed is a process where listening over speakers is simulated. This |
729 | * is good for old hard panned stereo records, which might be quite fatiguing | 710 | * is good for old hard panned stereo records, which might be quite fatiguing |
730 | * to listen to on headphones with no crossfeed. | 711 | * to listen to on headphones with no crossfeed. |
731 | */ | 712 | */ |
732 | #ifndef DSP_HAVE_ASM_CROSSFEED | 713 | #ifndef DSP_HAVE_ASM_CROSSFEED |
733 | static void apply_crossfeed(int32_t *buf[], int count) | 714 | static void apply_crossfeed(int count, int32_t *buf[]) |
734 | { | 715 | { |
735 | int32_t *hist_l = &crossfeed_data.history[0]; | 716 | int32_t *hist_l = &crossfeed_data.history[0]; |
736 | int32_t *hist_r = &crossfeed_data.history[2]; | 717 | int32_t *hist_r = &crossfeed_data.history[2]; |
@@ -775,7 +756,36 @@ static void apply_crossfeed(int32_t *buf[], int count) | |||
775 | /* Write back local copies of data we've modified */ | 756 | /* Write back local copies of data we've modified */ |
776 | crossfeed_data.index = di; | 757 | crossfeed_data.index = di; |
777 | } | 758 | } |
778 | #endif | 759 | #endif /* DSP_HAVE_ASM_CROSSFEED */ |
760 | |||
761 | /** | ||
762 | * dsp_set_crossfeed(bool enable) | ||
763 | * | ||
764 | * !DSPPARAMSYNC | ||
765 | * needs syncing with changes to the following dsp parameters: | ||
766 | * * dsp->stereo_mode (A) | ||
767 | */ | ||
768 | void dsp_set_crossfeed(bool enable) | ||
769 | { | ||
770 | crossfeed_enabled = enable; | ||
771 | audio_dsp->apply_crossfeed = | ||
772 | (enable && audio_dsp->data.num_channels > 1) | ||
773 | ? apply_crossfeed : NULL; | ||
774 | } | ||
775 | |||
776 | void dsp_set_crossfeed_direct_gain(int gain) | ||
777 | { | ||
778 | crossfeed_data.gain = get_replaygain_int(gain * -10) << 7; | ||
779 | } | ||
780 | |||
781 | void dsp_set_crossfeed_cross_params(long lf_gain, long hf_gain, long cutoff) | ||
782 | { | ||
783 | long g1 = get_replaygain_int(lf_gain * -10) << 3; | ||
784 | long g2 = get_replaygain_int(hf_gain * -10) << 3; | ||
785 | |||
786 | filter_shelf_coefs(0xffffffff/NATIVE_FREQUENCY*cutoff, g1, g2, | ||
787 | crossfeed_data.coefs); | ||
788 | } | ||
779 | 789 | ||
780 | /* Combine all gains to a global gain. */ | 790 | /* Combine all gains to a global gain. */ |
781 | static void set_gain(struct dsp_config *dsp) | 791 | static void set_gain(struct dsp_config *dsp) |
@@ -1056,10 +1066,9 @@ static void channels_process_sound_chan_karaoke(int count, int32_t *buf[]) | |||
1056 | 1066 | ||
1057 | do | 1067 | do |
1058 | { | 1068 | { |
1059 | int32_t l = *sl/2; | 1069 | int32_t ch = *sl/2 - *sr/2; |
1060 | int32_t r = *sr/2; | 1070 | *sl++ = ch; |
1061 | *sl++ = l - r; | 1071 | *sr++ = -ch; |
1062 | *sr++ = r - l; | ||
1063 | } | 1072 | } |
1064 | while (--count > 0); | 1073 | while (--count > 0); |
1065 | } | 1074 | } |
@@ -1067,8 +1076,7 @@ static void channels_process_sound_chan_karaoke(int count, int32_t *buf[]) | |||
1067 | 1076 | ||
1068 | void channels_set(int value) | 1077 | void channels_set(int value) |
1069 | { | 1078 | { |
1070 | static void (* const channels_process_functions[])( | 1079 | static const channels_process_fn_type channels_process_functions[] = |
1071 | int count, int32_t *buf[]) = | ||
1072 | { | 1080 | { |
1073 | /* SOUND_CHAN_STEREO = All-purpose index for no channel processing */ | 1081 | /* SOUND_CHAN_STEREO = All-purpose index for no channel processing */ |
1074 | [SOUND_CHAN_STEREO] = NULL, | 1082 | [SOUND_CHAN_STEREO] = NULL, |
@@ -1118,7 +1126,7 @@ int dsp_process(char *dst, const char *src[], int count) | |||
1118 | if ((samples = resample(samples, tmp)) <= 0) | 1126 | if ((samples = resample(samples, tmp)) <= 0) |
1119 | break; /* I'm pretty sure we're downsampling here */ | 1127 | break; /* I'm pretty sure we're downsampling here */ |
1120 | if (dsp->apply_crossfeed) | 1128 | if (dsp->apply_crossfeed) |
1121 | dsp->apply_crossfeed(tmp, samples); | 1129 | dsp->apply_crossfeed(ACF_SWITCHPARAM(samples, tmp)); |
1122 | /* TODO: EQ and tone controls need separate structs for audio and voice | 1130 | /* TODO: EQ and tone controls need separate structs for audio and voice |
1123 | * DSP processing thanks to filter history. isn't really audible now, but | 1131 | * DSP processing thanks to filter history. isn't really audible now, but |
1124 | * might be the day we start handling voice more delicately. | 1132 | * might be the day we start handling voice more delicately. |