summaryrefslogtreecommitdiff
path: root/lib/rbcodec/dsp/dsp_misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/dsp/dsp_misc.c')
-rw-r--r--lib/rbcodec/dsp/dsp_misc.c238
1 files changed, 238 insertions, 0 deletions
diff --git a/lib/rbcodec/dsp/dsp_misc.c b/lib/rbcodec/dsp/dsp_misc.c
new file mode 100644
index 0000000000..7b4589151c
--- /dev/null
+++ b/lib/rbcodec/dsp/dsp_misc.c
@@ -0,0 +1,238 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 Miika Pekkarinen
11 * Copyright (C) 2005 Magnus Holmgren
12 * Copyright (C) 2007 Thom Johansen
13 * Copyright (C) 2012 Michael Sevakis
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 ****************************************************************************/
24#include "config.h"
25#include "system.h"
26#include "dsp.h"
27#include "dsp_sample_io.h"
28#include "replaygain.h"
29#include "sound.h"
30#include "settings.h"
31#include "fixedpoint.h"
32#include <string.h>
33#include "dsp_proc_entry.h"
34
35/** Firmware callback interface **/
36
37/* Hook back from firmware/ part of audio, which can't/shouldn't call apps/
38 * code directly. */
39int dsp_callback(int msg, intptr_t param)
40{
41 switch (msg)
42 {
43#ifdef HAVE_SW_TONE_CONTROLS
44 case DSP_CALLBACK_SET_PRESCALE:
45 tone_set_prescale(param);
46 break;
47 case DSP_CALLBACK_SET_BASS:
48 tone_set_bass(param);
49 break;
50 case DSP_CALLBACK_SET_TREBLE:
51 tone_set_treble(param);
52 break;
53 /* FIXME: This must be done by bottom-level PCM driver so it works with
54 all PCM, not here and not in mixer. I won't fully support it
55 here with all streams. -- jethead71 */
56#ifdef HAVE_SW_VOLUME_CONTROL
57 case DSP_CALLBACK_SET_SW_VOLUME:
58 if (global_settings.volume < SW_VOLUME_MAX ||
59 global_settings.volume > SW_VOLUME_MIN)
60 {
61 int vol_gain = get_replaygain_int(global_settings.volume * 100);
62 pga_set_gain(PGA_VOLUME, vol_gain);
63 }
64 break;
65#endif /* HAVE_SW_VOLUME_CONTROL */
66#endif /* HAVE_SW_TONE_CONTROLS */
67 case DSP_CALLBACK_SET_CHANNEL_CONFIG:
68 channel_mode_set_config(param);
69 break;
70 case DSP_CALLBACK_SET_STEREO_WIDTH:
71 channel_mode_custom_set_width(param);
72 break;
73 default:
74 break;
75 }
76
77 return 0;
78}
79
80/** Replaygain settings **/
81static struct dsp_replay_gains current_rpgains;
82
83static void dsp_replaygain_update(const struct dsp_replay_gains *gains)
84{
85 if (gains == NULL)
86 {
87 /* Use defaults */
88 memset(&current_rpgains, 0, sizeof (current_rpgains));
89 gains = &current_rpgains;
90 }
91 else
92 {
93 current_rpgains = *gains; /* Stash settings */
94 }
95
96 int32_t gain = PGA_UNITY;
97
98 if (global_settings.replaygain_type != REPLAYGAIN_OFF ||
99 global_settings.replaygain_noclip)
100 {
101 bool track_mode =
102 get_replaygain_mode(gains->track_gain != 0,
103 gains->album_gain != 0) == REPLAYGAIN_TRACK;
104
105 int32_t peak = (track_mode || gains->album_peak == 0) ?
106 gains->track_peak : gains->album_peak;
107
108 if (global_settings.replaygain_type != REPLAYGAIN_OFF)
109 {
110 gain = (track_mode || gains->album_gain == 0) ?
111 gains->track_gain : gains->album_gain;
112
113 if (global_settings.replaygain_preamp)
114 {
115 int32_t preamp = get_replaygain_int(
116 global_settings.replaygain_preamp * 10);
117
118 gain = fp_mul(gain, preamp, 24);
119 }
120 }
121
122 if (gain == 0)
123 {
124 /* So that noclip can work even with no gain information. */
125 gain = PGA_UNITY;
126 }
127
128 if (global_settings.replaygain_noclip && peak != 0 &&
129 fp_mul(gain, peak, 24) >= PGA_UNITY)
130 {
131 gain = fp_div(PGA_UNITY, peak, 24);
132 }
133 }
134
135 pga_set_gain(PGA_REPLAYGAIN, gain);
136 pga_enable_gain(PGA_REPLAYGAIN, gain != PGA_UNITY);
137}
138
139int get_replaygain_mode(bool have_track_gain, bool have_album_gain)
140{
141 bool track = false;
142
143 switch (global_settings.replaygain_type)
144 {
145 case REPLAYGAIN_TRACK:
146 track = true;
147 break;
148
149 case REPLAYGAIN_SHUFFLE:
150 track = global_settings.playlist_shuffle;
151 break;
152 }
153
154 return (!track && have_album_gain) ?
155 REPLAYGAIN_ALBUM : (have_track_gain ? REPLAYGAIN_TRACK : -1);
156}
157
158void dsp_set_replaygain(void)
159{
160 dsp_replaygain_update(&current_rpgains);
161}
162
163
164/** Pitch Settings **/
165
166#ifdef HAVE_PITCHSCREEN
167static int32_t pitch_ratio = PITCH_SPEED_100;
168
169static void dsp_pitch_update(struct dsp_config *dsp)
170{
171 /* Account for playback speed adjustment when setting dsp->frequency
172 if we're called from the main audio thread. Voice playback thread
173 does not support this feature. */
174 struct sample_io_data *data = (void *)dsp;
175 data->format.frequency =
176 (int64_t)pitch_ratio * data->format.codec_frequency / PITCH_SPEED_100;
177}
178
179int32_t sound_get_pitch(void)
180{
181 return pitch_ratio;
182}
183
184void sound_set_pitch(int32_t percent)
185{
186 pitch_ratio = percent > 0 ? percent : PITCH_SPEED_100;
187 struct dsp_config *dsp = dsp_get_config(CODEC_IDX_AUDIO);
188 struct sample_io_data *data = (void *)dsp;
189 dsp_configure(dsp, DSP_SWITCH_FREQUENCY, data->format.codec_frequency);
190}
191#endif /* HAVE_PITCHSCREEN */
192
193/* This is a null-processing stage that monitors as an enabled stage but never
194 * becomes active in processing samples. It only hooks messages. */
195
196/* DSP message hook */
197static intptr_t misc_handler_configure(struct dsp_proc_entry *this,
198 struct dsp_config *dsp,
199 unsigned setting,
200 intptr_t value)
201{
202 switch (setting)
203 {
204 case DSP_INIT:
205 /* Enable us for the audio DSP at startup */
206 if (value == CODEC_IDX_AUDIO)
207 dsp_proc_enable(dsp, DSP_PROC_MISC_HANDLER, true);
208 break;
209
210 case DSP_PROC_CLOSE:
211 /* This stage should be enabled at all times */
212 DEBUGF("DSP_PROC_MISC_HANDLER - Error: Closing!\n");
213 break;
214
215 case DSP_RESET:
216#ifdef HAVE_PITCHSCREEN
217 dsp_pitch_update(dsp);
218#endif
219 value = (intptr_t)NULL; /* Default gains */
220 case REPLAYGAIN_SET_GAINS:
221 dsp_replaygain_update((void *)value);
222 break;
223
224#ifdef HAVE_PITCHSCREEN
225 case DSP_SET_FREQUENCY:
226 dsp_pitch_update(dsp);
227 break;
228#endif
229 }
230
231 return 1;
232 (void)this;
233}
234
235/* Database entry */
236DSP_PROC_DB_ENTRY(
237 MISC_HANDLER,
238 misc_handler_configure);