/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2005 Miika Pekkarinen * Copyright (C) 2005 Magnus Holmgren * 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 "fixedpoint.h" #include "replaygain.h" #include "dsp_proc_entry.h" #include "dsp_misc.h" #include "pga.h" #include "channel_mode.h" #ifdef HAVE_SW_TONE_CONTROLS #include "tone_controls.h" #endif #include /** Replaygain settings **/ static struct replaygain_settings current_settings; static struct dsp_replay_gains current_gains; static void dsp_replaygain_update( const struct replaygain_settings *settings, const struct dsp_replay_gains *gains) { if (settings != ¤t_settings) current_settings = *settings; /* Stash settings */ if (gains != ¤t_gains) current_gains = *gains; /* Stash gains */ int32_t gain = PGA_UNITY; if (settings->type != REPLAYGAIN_OFF || settings->noclip) { bool track_mode = settings->type == REPLAYGAIN_TRACK && gains->track_gain != 0; int32_t peak = (track_mode || gains->album_peak == 0) ? gains->track_peak : gains->album_peak; if (settings->type != REPLAYGAIN_OFF) { gain = (track_mode || gains->album_gain == 0) ? gains->track_gain : gains->album_gain; if (settings->preamp != 0) { int32_t preamp = get_replaygain_int(settings->preamp * 10); gain = fp_mul(gain, preamp, 24); } } if (gain == 0) { /* So that noclip can work even with no gain information. */ gain = PGA_UNITY; } if (settings->noclip && peak != 0 && fp_mul(gain, peak, 24) >= PGA_UNITY) { gain = fp_div(PGA_UNITY, peak, 24); } } pga_set_gain(PGA_REPLAYGAIN, gain); pga_enable_gain(PGA_REPLAYGAIN, gain != PGA_UNITY); } static void dsp_replaygain_set_gains(const struct dsp_replay_gains *gains) { if (gains == NULL) { /* Set defaults */ gains = ¤t_gains; memset((void *)gains, 0, sizeof (*gains)); } dsp_replaygain_update(¤t_settings, gains); } void dsp_replaygain_set_settings(const struct replaygain_settings *settings) { dsp_replaygain_update(settings, ¤t_gains); } /** Pitch Settings **/ #ifdef HAVE_PITCHCONTROL static int32_t pitch_ratio = PITCH_SPEED_100; static void dsp_pitch_update(struct dsp_config *dsp) { dsp_configure(dsp, DSP_SET_PITCH, fp_div(pitch_ratio, PITCH_SPEED_100, 16)); } void dsp_set_pitch(int32_t percent) { if (percent <= 0) percent = PITCH_SPEED_100; if (percent == pitch_ratio) return; pitch_ratio = percent; dsp_pitch_update(dsp_get_config(CODEC_IDX_AUDIO)); } int32_t dsp_get_pitch(void) { return pitch_ratio; } #endif /* HAVE_PITCHCONTROL */ /* Set output samplerate for all DSPs */ void dsp_set_all_output_frequency(unsigned int samplerate) { struct dsp_config *dsp; for (int i = 0; (dsp = dsp_get_config(i)); i++) dsp_configure(dsp, DSP_SET_OUT_FREQUENCY, samplerate); } /* Return DSP's output samplerate */ unsigned int dsp_get_output_frequency(struct dsp_config *dsp) { return dsp_configure(dsp, DSP_GET_OUT_FREQUENCY, 0); } static void INIT_ATTR misc_dsp_init(struct dsp_config *dsp, enum dsp_ids dsp_id) { /* Enable us for the audio DSP at startup */ if (dsp_id == CODEC_IDX_AUDIO) dsp_proc_enable(dsp, DSP_PROC_MISC_HANDLER, true); } /* This is a null-processing stage that monitors as an enabled stage but never * becomes active in processing samples. It only hooks messages. */ /* DSP message hook */ static intptr_t misc_handler_configure(struct dsp_proc_entry *this, struct dsp_config *dsp, unsigned setting, intptr_t value) { switch (setting) { case DSP_INIT: misc_dsp_init(dsp, (enum dsp_ids)value); break; case DSP_PROC_CLOSE: /* This stage should be enabled at all times */ DEBUGF("DSP_PROC_MISC_HANDLER - Error: Closing!\n"); break; case DSP_RESET: #ifdef HAVE_PITCHCONTROL dsp_pitch_update(dsp); #endif value = (intptr_t)NULL; /* Default gains */ case REPLAYGAIN_SET_GAINS: dsp_replaygain_set_gains((void *)value); break; #ifdef HAVE_PITCHCONTROL case DSP_SET_FREQUENCY: dsp_pitch_update(dsp); break; #endif } return 0; (void)this; } /* Database entry */ DSP_PROC_DB_ENTRY( MISC_HANDLER, misc_handler_configure);