summaryrefslogtreecommitdiff
path: root/apps/dsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/dsp.c')
-rw-r--r--apps/dsp.c111
1 files changed, 61 insertions, 50 deletions
diff --git a/apps/dsp.c b/apps/dsp.c
index 4ea2a0c3c4..94e825c532 100644
--- a/apps/dsp.c
+++ b/apps/dsp.c
@@ -32,10 +32,6 @@
32#include <dsp_asm.h> 32#include <dsp_asm.h>
33#endif 33#endif
34 34
35/* The "dither" code to convert the 24-bit samples produced by libmad was
36 * taken from the coolplayer project - coolplayer.sourceforge.net
37 */
38
39/* 16-bit samples are scaled based on these constants. The shift should be 35/* 16-bit samples are scaled based on these constants. The shift should be
40 * no more than 15. 36 * no more than 15.
41 */ 37 */
@@ -180,6 +176,8 @@ struct dsp_config
180 int stereo_mode; 176 int stereo_mode;
181 int frac_bits; 177 int frac_bits;
182 bool dither_enabled; 178 bool dither_enabled;
179 long dither_bias;
180 long dither_mask;
183 bool new_gain; 181 bool new_gain;
184 bool crossfeed_enabled; 182 bool crossfeed_enabled;
185 bool eq_enabled; 183 bool eq_enabled;
@@ -397,7 +395,7 @@ static long upsample(int32_t **dst, int32_t **src, int count, struct resample_da
397 int i = 0, j; 395 int i = 0, j;
398 int pos; 396 int pos;
399 int num_channels = dsp->stereo_mode == STEREO_MONO ? 1 : 2; 397 int num_channels = dsp->stereo_mode == STEREO_MONO ? 1 : 2;
400 398
401 while ((pos = phase >> 16) == 0) 399 while ((pos = phase >> 16) == 0)
402 { 400 {
403 for (j = 0; j < num_channels; j++) 401 for (j = 0; j < num_channels; j++)
@@ -479,40 +477,60 @@ static inline long clip_sample(int32_t sample, int32_t min, int32_t max)
479 * taken from the coolplayer project - coolplayer.sourceforge.net 477 * taken from the coolplayer project - coolplayer.sourceforge.net
480 */ 478 */
481 479
482static long dither_sample(int32_t sample, int32_t bias, int32_t mask, 480void dsp_dither_enable(bool enable)
483 struct dither_data* dither)
484{ 481{
485 int32_t output; 482 dsp->dither_enabled = enable;
486 int32_t random; 483}
487 int32_t min;
488 int32_t max;
489
490 /* Noise shape and bias */
491
492 sample += dither->error[0] - dither->error[1] + dither->error[2];
493 dither->error[2] = dither->error[1];
494 dither->error[1] = dither->error[0] / 2;
495
496 output = sample + bias;
497
498 /* Dither */
499
500 random = dither->random * 0x0019660dL + 0x3c6ef35fL;
501 sample += (random & mask) - (dither->random & mask);
502 dither->random = random;
503
504 /* Clip and quantize */
505
506 min = dsp->clip_min;
507 max = dsp->clip_max;
508 sample = clip_sample(sample, min, max);
509 output = clip_sample(output, min, max) & ~mask;
510 484
511 /* Error feedback */ 485static void dither_init(void)
486{
487 memset(&dither_data[0], 0, sizeof(dither_data));
488 memset(&dither_data[1], 0, sizeof(dither_data));
489 dsp->dither_bias = (1L << (dsp->frac_bits - NATIVE_DEPTH));
490 dsp->dither_mask = (1L << (dsp->frac_bits + 1 - NATIVE_DEPTH)) - 1;
491}
512 492
513 dither->error[0] = sample - output; 493static void dither_samples(int32_t* src, int num, struct dither_data* dither)
494{
495 int32_t output, sample;
496 int32_t random;
497 int32_t min, max;
498 long mask = dsp->dither_mask;
499 long bias = dsp->dither_bias;
500 int i;
501
502 for (i = 0; i < num; ++i) {
503 /* Noise shape and bias */
504 sample = src[i];
505 sample += dither->error[0] - dither->error[1] + dither->error[2];
506 dither->error[2] = dither->error[1];
507 dither->error[1] = dither->error[0]/2;
508
509 output = sample + bias;
510
511 /* Dither */
512 random = dither->random*0x0019660dL + 0x3c6ef35fL;
513 output += (random & mask) - (dither->random & mask);
514 dither->random = random;
515
516 /* Clip and quantize */
517 min = dsp->clip_min;
518 max = dsp->clip_max;
519 if (output > max) {
520 output = max;
521 if (sample > max)
522 sample = max;
523 } else if (output < min) {
524 output = min;
525 if (sample < min)
526 sample = min;
527 }
528 output &= ~mask;
514 529
515 return output; 530 /* Error feedback */
531 dither->error[0] = sample - output;
532 src[i] = output;
533 }
516} 534}
517 535
518void dsp_set_crossfeed(bool enable) 536void dsp_set_crossfeed(bool enable)
@@ -740,7 +758,7 @@ static void apply_gain(int32_t* _src[], int _count)
740 758
741void channels_set(int value) 759void channels_set(int value)
742{ 760{
743 channels_mode = value; 761 channels_mode = value;
744} 762}
745 763
746void stereo_width_set(int value) 764void stereo_width_set(int value)
@@ -811,15 +829,13 @@ static void write_samples(short* dst, int32_t* src[], int count)
811 829
812 if (dsp->dither_enabled) 830 if (dsp->dither_enabled)
813 { 831 {
814 long bias = (1L << (dsp->frac_bits - NATIVE_DEPTH)); 832 dither_samples(src[0], count, &dither_data[0]);
815 long mask = (1L << scale) - 1; 833 dither_samples(src[1], count, &dither_data[1]);
816 834
817 while (count-- > 0) 835 while (count-- > 0)
818 { 836 {
819 *dst++ = (short) (dither_sample(*s0++, bias, mask, &dither_data[0]) 837 *dst++ = (short) (*s0++ >> scale);
820 >> scale); 838 *dst++ = (short) (*s1++ >> scale);
821 *dst++ = (short) (dither_sample(*s1++, bias, mask, &dither_data[1])
822 >> scale);
823 } 839 }
824 } 840 }
825 else 841 else
@@ -980,7 +996,7 @@ bool dsp_configure(int setting, void *value)
980 /* Fall through!!! */ 996 /* Fall through!!! */
981 case DSP_SWITCH_FREQUENCY: 997 case DSP_SWITCH_FREQUENCY:
982 dsp->codec_frequency = ((long) value == 0) ? NATIVE_FREQUENCY : (long) value; 998 dsp->codec_frequency = ((long) value == 0) ? NATIVE_FREQUENCY : (long) value;
983 /* Account for playback speed adjustment when settingg dsp->frequency 999 /* Account for playback speed adjustment when setting dsp->frequency
984 if we're called from the main audio thread. Voice UI thread should 1000 if we're called from the main audio thread. Voice UI thread should
985 not need this feature. 1001 not need this feature.
986 */ 1002 */
@@ -1001,7 +1017,7 @@ bool dsp_configure(int setting, void *value)
1001 1017
1002 case DSP_SET_SAMPLE_DEPTH: 1018 case DSP_SET_SAMPLE_DEPTH:
1003 dsp->sample_depth = (long) value; 1019 dsp->sample_depth = (long) value;
1004 1020
1005 if (dsp->sample_depth <= NATIVE_DEPTH) 1021 if (dsp->sample_depth <= NATIVE_DEPTH)
1006 { 1022 {
1007 dsp->frac_bits = WORD_FRACBITS; 1023 dsp->frac_bits = WORD_FRACBITS;
@@ -1017,6 +1033,7 @@ bool dsp_configure(int setting, void *value)
1017 dsp->clip_min = -(1 << (long)value); 1033 dsp->clip_min = -(1 << (long)value);
1018 } 1034 }
1019 1035
1036 dither_init();
1020 break; 1037 break;
1021 1038
1022 case DSP_SET_STEREO_MODE: 1039 case DSP_SET_STEREO_MODE:
@@ -1024,7 +1041,6 @@ bool dsp_configure(int setting, void *value)
1024 break; 1041 break;
1025 1042
1026 case DSP_RESET: 1043 case DSP_RESET:
1027 dsp->dither_enabled = false;
1028 dsp->stereo_mode = STEREO_NONINTERLEAVED; 1044 dsp->stereo_mode = STEREO_NONINTERLEAVED;
1029 dsp->clip_max = ((1 << WORD_FRACBITS) - 1); 1045 dsp->clip_max = ((1 << WORD_FRACBITS) - 1);
1030 dsp->clip_min = -((1 << WORD_FRACBITS)); 1046 dsp->clip_min = -((1 << WORD_FRACBITS));
@@ -1038,11 +1054,6 @@ bool dsp_configure(int setting, void *value)
1038 dsp->new_gain = true; 1054 dsp->new_gain = true;
1039 break; 1055 break;
1040 1056
1041 case DSP_DITHER:
1042 memset(dither_data, 0, sizeof(dither_data));
1043 dsp->dither_enabled = (bool) value;
1044 break;
1045
1046 case DSP_SET_TRACK_GAIN: 1057 case DSP_SET_TRACK_GAIN:
1047 dsp->track_gain = (long) value; 1058 dsp->track_gain = (long) value;
1048 dsp->new_gain = true; 1059 dsp->new_gain = true;