diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/SOURCES | 4 | ||||
-rw-r--r-- | apps/dsp.c | 34 | ||||
-rw-r--r-- | apps/eq_cf.S | 61 |
3 files changed, 99 insertions, 0 deletions
diff --git a/apps/SOURCES b/apps/SOURCES index cf17bbc27c..cd2316fc24 100644 --- a/apps/SOURCES +++ b/apps/SOURCES | |||
@@ -76,4 +76,8 @@ playback.c | |||
76 | metadata.c | 76 | metadata.c |
77 | codecs.c | 77 | codecs.c |
78 | dsp.c | 78 | dsp.c |
79 | eq.c | ||
80 | #if defined(CPU_COLDFIRE) && !defined(SIMULATOR) | ||
81 | eq_cf.S | ||
82 | #endif | ||
79 | #endif | 83 | #endif |
diff --git a/apps/dsp.c b/apps/dsp.c index 19cb669a06..b2fc0ce7a2 100644 --- a/apps/dsp.c +++ b/apps/dsp.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <inttypes.h> | 19 | #include <inttypes.h> |
20 | #include <string.h> | 20 | #include <string.h> |
21 | #include "dsp.h" | 21 | #include "dsp.h" |
22 | #include "eq.h" | ||
22 | #include "kernel.h" | 23 | #include "kernel.h" |
23 | #include "playback.h" | 24 | #include "playback.h" |
24 | #include "system.h" | 25 | #include "system.h" |
@@ -166,10 +167,21 @@ struct crossfeed_data | |||
166 | int index; | 167 | int index; |
167 | }; | 168 | }; |
168 | 169 | ||
170 | /* Current setup is one lowshelf filters, three peaking filters and one | ||
171 | highshelf filter. Varying the number of shelving filters make no sense, | ||
172 | but adding peaking filters are possible. */ | ||
173 | struct eq_state { | ||
174 | char enabled[5]; /* Flags for active filters */ | ||
175 | struct eqfilter ls; | ||
176 | struct eqfilter pk[3]; | ||
177 | struct eqfilter hs; | ||
178 | }; | ||
179 | |||
169 | static struct dsp_config dsp_conf[2] IBSS_ATTR; | 180 | static struct dsp_config dsp_conf[2] IBSS_ATTR; |
170 | static struct dither_data dither_data[2] IBSS_ATTR; | 181 | static struct dither_data dither_data[2] IBSS_ATTR; |
171 | static struct resample_data resample_data[2] IBSS_ATTR; | 182 | static struct resample_data resample_data[2] IBSS_ATTR; |
172 | struct crossfeed_data crossfeed_data IBSS_ATTR; | 183 | struct crossfeed_data crossfeed_data IBSS_ATTR; |
184 | static struct eq_state eq_data; | ||
173 | 185 | ||
174 | static int pitch_ratio = 1000; | 186 | static int pitch_ratio = 1000; |
175 | 187 | ||
@@ -608,6 +620,25 @@ static void apply_crossfeed(long* src[], int count) | |||
608 | } | 620 | } |
609 | #endif | 621 | #endif |
610 | 622 | ||
623 | /* Apply EQ filters to those bands that have got it switched on. */ | ||
624 | void eq_process(long **x, unsigned num) | ||
625 | { | ||
626 | int i; | ||
627 | unsigned int channels = dsp->stereo_mode != STEREO_MONO ? 2 : 1; | ||
628 | |||
629 | /* filter configuration currently is 1 low shelf filter, 3 band peaking | ||
630 | filters and 1 high shelf filter, in that order. | ||
631 | */ | ||
632 | if (eq_data.enabled[0]) | ||
633 | eq_filter(x, &eq_data.ls, num, channels, EQ_SHELF_SHIFT); | ||
634 | for (i = 0; i < 3; i++) { | ||
635 | if (eq_data.enabled[1 + i]) | ||
636 | eq_filter(x, &eq_data.pk[i], num, channels, EQ_PEAK_SHIFT); | ||
637 | } | ||
638 | if (eq_data.enabled[4]) | ||
639 | eq_filter(x, &eq_data.hs, num, channels, EQ_SHELF_SHIFT); | ||
640 | } | ||
641 | |||
611 | /* Apply a constant gain to the samples (e.g., for ReplayGain). May update | 642 | /* Apply a constant gain to the samples (e.g., for ReplayGain). May update |
612 | * the src array if gain was applied. | 643 | * the src array if gain was applied. |
613 | * Note that this must be called before the resampler. | 644 | * Note that this must be called before the resampler. |
@@ -713,6 +744,9 @@ long dsp_process(char* dst, char* src[], long size) | |||
713 | samples = resample(tmp, samples); | 744 | samples = resample(tmp, samples); |
714 | if (dsp->crossfeed_enabled && dsp->stereo_mode != STEREO_MONO) | 745 | if (dsp->crossfeed_enabled && dsp->stereo_mode != STEREO_MONO) |
715 | apply_crossfeed(tmp, samples); | 746 | apply_crossfeed(tmp, samples); |
747 | /* TODO: Might want to wrap this with a generic eq_enabled when the | ||
748 | settings are in place */ | ||
749 | eq_process(tmp, samples); | ||
716 | write_samples((short*) dst, tmp, samples); | 750 | write_samples((short*) dst, tmp, samples); |
717 | written += samples; | 751 | written += samples; |
718 | dst += samples * sizeof(short) * 2; | 752 | dst += samples * sizeof(short) * 2; |
diff --git a/apps/eq_cf.S b/apps/eq_cf.S new file mode 100644 index 0000000000..3876ca72d6 --- /dev/null +++ b/apps/eq_cf.S | |||
@@ -0,0 +1,61 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2006 Thom Johansen | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | .text | ||
21 | .global eq_filter | ||
22 | eq_filter: | ||
23 | lea.l (-11*4, %sp), %sp | ||
24 | movem.l %d2-%d7/%a2-%a6, (%sp) | save clobbered regs | ||
25 | move.l (11*4+8, %sp), %a5 | fetch filter structure address | ||
26 | movem.l (11*4+16, %sp), %d6-%d7 | load num. channels and shift count | ||
27 | movem.l (%a5), %a0-%a4 | load coefs | ||
28 | lea.l (5*4, %a5), %a5 | point to filter history | ||
29 | moveq.l #2, %d6 | number of channels (hardcode to stereo) | ||
30 | |||
31 | .filterloop: | ||
32 | move.l (11*4+4, %sp), %a6 | load input channel pointer | ||
33 | move.l (%a6), %a6 | ||
34 | move.l (11*4+12, %sp), %d5 | number of samples | ||
35 | addq.l #4, (11*4+4, %sp) | point x to next channel | ||
36 | movem.l (%a5), %d0-%d3 | load filter history | ||
37 | .loop: | ||
38 | move.l (%a6), %d4 | ||
39 | mac.l %a0, %d4, %acc0 | acc = b0*x[i] | ||
40 | mac.l %a1, %d0, %acc0 | acc += b1*x[i - 1] | ||
41 | mac.l %a2, %d1, %acc0 | acc += b2*x[i - 2] | ||
42 | msac.l %a3, %d2, %acc0 | acc -= a1*y[i - 1] | ||
43 | msac.l %a4, %d3, %acc0 | acc -= a2*y[i - 2] | ||
44 | move.l %d0, %d1 | fix history | ||
45 | move.l %d4, %d0 | ||
46 | move.l %d2, %d3 | ||
47 | movclr.l %acc0, %d2 | fetch and write result | ||
48 | asl.l %d7, %d2 | restore fixed point format | ||
49 | move.l %d2, (%a6)+ | save result | ||
50 | subq.l #1, %d5 | are we done with this channel? | ||
51 | jne .loop | ||
52 | |||
53 | movem.l %d0-%d3, (%a5) | save history back to struct | ||
54 | lea.l (4*4, %a5), %a5 | point to next channel's history | ||
55 | subq.l #1, %d6 | have we processed both channels? | ||
56 | jne .filterloop | ||
57 | |||
58 | movem.l (%sp), %d2-%d7/%a2-%a6 | ||
59 | lea.l (11*4, %sp), %sp | ||
60 | rts | ||
61 | |||