summaryrefslogtreecommitdiff
path: root/apps/dsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/dsp.c')
-rw-r--r--apps/dsp.c122
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 */
137static void apply_crossfeed(int32_t *buf[], int count); 135typedef int (*sample_input_fn_type)(int count, const char *src[],
138#endif 136 int32_t *dst[]);
137typedef int (*resample_fn_type)(int count, struct dsp_data *data,
138 int32_t *src[], int32_t *dst[]);
139typedef 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 */
143typedef void (*apply_crossfeed_fn_type)(ACF_SWITCHPARAM(int count,
144 int32_t *buf[]));
145typedef 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 */
169static long dither_mask IBSS_ATTR; 175static long dither_mask IBSS_ATTR;
170static long dither_bias IBSS_ATTR; 176static long dither_bias IBSS_ATTR;
171/* Crossfeed */ 177/* Crossfeed */
172struct crossfeed_data crossfeed_data IBSS_ATTR; /* A */ 178struct 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 */
174static struct eq_state eq_data; /* A/V */ 187static 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 */
402static void sample_input_new_format(void) 415static 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 */
540static void sample_output_new_format(void) 552static 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 */
705void 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
713void dsp_set_crossfeed_direct_gain(int gain)
714{
715 crossfeed_data.gain = get_replaygain_int(gain * -10) << 7;
716}
717
718void 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
733static void apply_crossfeed(int32_t *buf[], int count) 714static 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 */
768void 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
776void dsp_set_crossfeed_direct_gain(int gain)
777{
778 crossfeed_data.gain = get_replaygain_int(gain * -10) << 7;
779}
780
781void 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. */
781static void set_gain(struct dsp_config *dsp) 791static 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
1068void channels_set(int value) 1077void 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.