| /*************************************************************************** |
| * __________ __ ___. |
| * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| * \/ \/ \/ \/ \/ |
| * $Id$ |
| * |
| * Copyright (C) 2007 Thom Johansen |
| * Copyright (C) 2012 Michael Sevakis |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License |
| * as published by the Free Software Foundation; either version 2 |
| * of the License, or (at your option) any later version. |
| * |
| * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| * KIND, either express or implied. |
| * |
| ****************************************************************************/ |
| #include "rbcodecconfig.h" |
| #include "platform.h" |
| #include "fixedpoint.h" |
| #include "dsp_proc_entry.h" |
| #include "dsp_filter.h" |
| #include "tone_controls.h" |
| #include "dsp_misc.h" |
| |
| /* These apply to all DSP streams to remain as consistant as possible with |
| * the behavior of hardware tone controls */ |
| |
| /* Cutoffs in HZ - not adjustable for now */ |
| static const unsigned int tone_bass_cutoff = 200; |
| static const unsigned int tone_treble_cutoff = 3500; |
| |
| /* Current bass and treble gain values */ |
| static int tone_bass = 0; |
| static int tone_treble = 0; |
| |
| /* Current prescaler setting */ |
| static int tone_prescale = 0; |
| |
| /* Data for each DSP */ |
| static struct dsp_filter tone_filters[DSP_COUNT] IBSS_ATTR; |
| |
| static void update_filter(int id, unsigned int fout) |
| { |
| filter_bishelf_coefs(fp_div(tone_bass_cutoff, fout, 32), |
| fp_div(tone_treble_cutoff, fout, 32), |
| tone_bass, tone_treble, -tone_prescale, |
| &tone_filters[id]); |
| } |
| |
| /* Update the filters' coefficients based upon the bass/treble settings */ |
| void tone_set_prescale(int prescale) |
| { |
| int bass = tone_bass; |
| int treble = tone_treble; |
| |
| tone_prescale = prescale; |
| |
| struct dsp_config *dsp; |
| for (int i = 0; (dsp = dsp_get_config(i)); i++) |
| { |
| update_filter(i, dsp_get_output_frequency(dsp)); |
| |
| bool enable = bass != 0 || treble != 0; |
| dsp_proc_enable(dsp, DSP_PROC_TONE_CONTROLS, enable); |
| |
| if (enable && !dsp_proc_active(dsp, DSP_PROC_TONE_CONTROLS)) |
| { |
| filter_flush(&tone_filters[i]); /* Going online */ |
| dsp_proc_activate(dsp, DSP_PROC_TONE_CONTROLS, true); |
| } |
| } |
| } |
| |
| /* Prescaler is always set after setting bass/treble, so we wait with |
| * calculating coefs until such time. */ |
| |
| /* Change the bass setting */ |
| void tone_set_bass(int bass) |
| { |
| tone_bass = bass; |
| } |
| |
| /* Change the treble setting */ |
| void tone_set_treble(int treble) |
| { |
| tone_treble = treble; |
| } |
| |
| /* Apply the tone control filter in-place */ |
| static void tone_process(struct dsp_proc_entry *this, |
| struct dsp_buffer **buf_p) |
| { |
| struct dsp_buffer *buf = *buf_p; |
| filter_process((struct dsp_filter *)this->data, buf->p32, buf->remcount, |
| buf->format.num_channels); |
| } |
| |
| /* DSP message hook */ |
| static intptr_t tone_configure(struct dsp_proc_entry *this, |
| struct dsp_config *dsp, |
| unsigned int setting, |
| intptr_t value) |
| { |
| switch (setting) |
| { |
| case DSP_PROC_INIT: |
| if (value != 0) |
| break; /* Already enabled */ |
| |
| this->data = (intptr_t)&tone_filters[dsp_get_id(dsp)]; |
| this->process = tone_process; |
| /* Fall-through */ |
| case DSP_FLUSH: |
| filter_flush((struct dsp_filter *)this->data); |
| break; |
| |
| case DSP_SET_OUT_FREQUENCY: |
| update_filter(dsp_get_id(dsp), value); |
| break; |
| } |
| |
| return 0; |
| } |
| |
| /* Database entry */ |
| DSP_PROC_DB_ENTRY(TONE_CONTROLS, |
| tone_configure); |