summaryrefslogtreecommitdiff
path: root/firmware/sound.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/sound.c')
-rw-r--r--firmware/sound.c109
1 files changed, 64 insertions, 45 deletions
diff --git a/firmware/sound.c b/firmware/sound.c
index f8358c690d..336fe90c25 100644
--- a/firmware/sound.c
+++ b/firmware/sound.c
@@ -112,18 +112,6 @@ void sound_set(int setting, int value)
112 * by 12 dB after processing. 112 * by 12 dB after processing.
113 */ 113 */
114 114
115static int current_volume = 0; /* tenth dB */
116static int current_balance = 0; /* percent */
117#ifdef AUDIOHW_HAVE_TREBLE
118static int current_treble = 0; /* tenth dB */
119#endif
120#ifdef AUDIOHW_HAVE_BASS
121static int current_bass = 0; /* tenth dB */
122#endif
123#ifdef AUDIOHW_HAVE_EQ
124static int current_eq_band_gain[AUDIOHW_EQ_BAND_NUM]; /* tenth dB */
125#endif
126
127/* Return the sound value scaled to centibels (tenth-decibels) */ 115/* Return the sound value scaled to centibels (tenth-decibels) */
128static int sound_value_to_cb(int setting, int value) 116static int sound_value_to_cb(int setting, int value)
129{ 117{
@@ -133,20 +121,44 @@ static int sound_value_to_cb(int setting, int value)
133 return value; 121 return value;
134} 122}
135 123
124static struct
125{
126 int volume; /* tenth dB */
127 int balance; /* percent */
128#if defined(AUDIOHW_HAVE_BASS)
129 int bass; /* tenth dB */
130#endif
131#if defined(AUDIOHW_HAVE_TREBLE)
132 int treble; /* tenth dB */
133#endif
134#if defined(AUDIOHW_HAVE_EQ)
135 int eq_gain[AUDIOHW_EQ_BAND_NUM]; /* tenth dB */
136#endif
137} sound_prescaler;
138
139#if defined(AUDIOHW_HAVE_BASS) || defined (AUDIOHW_HAVE_TREBLE) \
140 || defined(AUDIOHW_HAVE_EQ)
141#define TONE_PRESCALER
142#endif
143
136static void set_prescaled_volume(void) 144static void set_prescaled_volume(void)
137{ 145{
138 int prescale = 0; 146#if defined(TONE_PRESCALER) || !defined(AUDIOHW_HAVE_MONO_VOLUME)
147 const int minvol = sound_value_to_cb(SOUND_VOLUME, sound_min(SOUND_VOLUME));
148#endif
149 int volume = sound_prescaler.volume;
139 150
140#if defined(AUDIOHW_HAVE_BASS) || defined(AUDIOHW_HAVE_TREBLE) \ 151#if defined(TONE_PRESCALER)
141 || defined(AUDIOHW_HAVE_EQ) 152 int prescale = 0;
142 153
143 /* Note: Having Tone + EQ isn't prohibited */ 154 /* Note: Having Tone + EQ isn't prohibited */
144#if defined(AUDIOHW_HAVE_BASS) && defined(AUDIOHW_HAVE_TREBLE) 155#if defined(AUDIOHW_HAVE_BASS) && defined(AUDIOHW_HAVE_TREBLE)
145 prescale = MAX(current_bass, current_treble); 156 prescale = MAX(sound_prescaler.bass, sound_prescaler.treble);
146#endif 157#endif
158
147#if defined(AUDIOHW_HAVE_EQ) 159#if defined(AUDIOHW_HAVE_EQ)
148 for (int i = 0; i < AUDIOHW_EQ_BAND_NUM; i++) 160 for (int i = 0; i < AUDIOHW_EQ_BAND_NUM; i++)
149 prescale = MAX(current_eq_band_gain[i], prescale); 161 prescale = MAX(sound_prescaler.eq_gain[i], prescale);
150#endif 162#endif
151 163
152 if (prescale < 0) 164 if (prescale < 0)
@@ -156,31 +168,38 @@ static void set_prescaled_volume(void)
156 /* Gain up the analog volume to compensate the prescale gain reduction, 168 /* Gain up the analog volume to compensate the prescale gain reduction,
157 * but if this would push the volume over the top, reduce prescaling 169 * but if this would push the volume over the top, reduce prescaling
158 * instead (might cause clipping). */ 170 * instead (might cause clipping). */
159 if (current_volume + prescale > VOLUME_MAX) 171 const int maxvol = sound_value_to_cb(SOUND_VOLUME, sound_max(SOUND_VOLUME));
160 prescale = VOLUME_MAX - current_volume; 172
173 if (volume + prescale > maxvol)
174 prescale = maxvol - volume;
161 175
162 audiohw_set_prescaler(prescale); 176 audiohw_set_prescaler(prescale);
163 177
164 if (current_volume < VOLUME_MIN) 178 if (volume <= minvol)
165 prescale = 0; /* Make sure the audio gets muted */ 179 prescale = 0; /* Make sure the audio gets muted */
166#endif /* AUDIOHW_HAVE_BASS || AUDIOHW_HAVE_TREBLE || AUDIOHW_HAVE_EQ */ 180
181#ifndef AUDIOHW_HAVE_MONO_VOLUME
182 /* At the moment, such targets have lousy volume resolution and so minute
183 boost won't work how we'd like */
184 volume += prescale;
185#endif
186#endif /* TONE_PRESCALER */
167 187
168#if defined(AUDIOHW_HAVE_MONO_VOLUME) 188#if defined(AUDIOHW_HAVE_MONO_VOLUME)
169 audiohw_set_volume(current_volume); 189 audiohw_set_volume(volume);
170#else /* Stereo volume */ 190#else /* Stereo volume */
171 int l = current_volume + prescale, r = l; 191 int l = volume, r = volume;
172 192
173 /* Balance the channels scaled by the current volume and min volume. */ 193 /* Balance the channels scaled by the current volume and min volume */
174 /* Subtract a dB from VOLUME_MIN to get it to a mute level */ 194 int balance = sound_prescaler.balance; /* percent */
175 int volshift = current_balance * VOLUME_RANGE / 100; /* tenth of dB */
176 195
177 if (volshift > 0) 196 if (balance > 0)
178 { 197 {
179 l -= ((l - (VOLUME_MIN - ONE_DB)) * volshift) / VOLUME_RANGE; 198 l -= (l - minvol) * balance / 100;
180 } 199 }
181 else if (volshift < 0) 200 else if (balance < 0)
182 { 201 {
183 r += ((r - (VOLUME_MIN - ONE_DB)) * volshift) / VOLUME_RANGE; 202 r += (r - minvol) * balance / 100;
184 } 203 }
185 204
186 audiohw_set_volume(l, r); 205 audiohw_set_volume(l, r);
@@ -190,8 +209,6 @@ static void set_prescaled_volume(void)
190 /* For now, lineout stays at unity */ 209 /* For now, lineout stays at unity */
191 audiohw_set_lineout_volume(0, 0); 210 audiohw_set_lineout_volume(0, 0);
192#endif /* AUDIOHW_HAVE_LINEOUT */ 211#endif /* AUDIOHW_HAVE_LINEOUT */
193
194 (void)prescale; /* In case of no tone controls + mono volume */
195} 212}
196#endif /* AUDIOIHW_HAVE_CLIPPING */ 213#endif /* AUDIOIHW_HAVE_CLIPPING */
197 214
@@ -203,7 +220,7 @@ void sound_set_volume(int value)
203#if defined(AUDIOHW_HAVE_CLIPPING) 220#if defined(AUDIOHW_HAVE_CLIPPING)
204 audiohw_set_volume(value); 221 audiohw_set_volume(value);
205#else 222#else
206 current_volume = sound_value_to_cb(SOUND_VOLUME, value); 223 sound_prescaler.volume = sound_value_to_cb(SOUND_VOLUME, value);
207 set_prescaled_volume(); 224 set_prescaled_volume();
208#endif 225#endif
209} 226}
@@ -216,12 +233,12 @@ void sound_set_balance(int value)
216#if defined(AUDIOHW_HAVE_BALANCE) 233#if defined(AUDIOHW_HAVE_BALANCE)
217 audiohw_set_balance(value); 234 audiohw_set_balance(value);
218#else 235#else
219 current_balance = value; 236 sound_prescaler.balance = value;
220 set_prescaled_volume(); 237 set_prescaled_volume();
221#endif 238#endif
222} 239}
223 240
224#ifdef AUDIOHW_HAVE_BASS 241#if defined(AUDIOHW_HAVE_BASS)
225void sound_set_bass(int value) 242void sound_set_bass(int value)
226{ 243{
227 if (!audio_is_initialized) 244 if (!audio_is_initialized)
@@ -230,13 +247,13 @@ void sound_set_bass(int value)
230 audiohw_set_bass(value); 247 audiohw_set_bass(value);
231 248
232#if !defined(AUDIOHW_HAVE_CLIPPING) 249#if !defined(AUDIOHW_HAVE_CLIPPING)
233 current_bass = sound_value_to_cb(SOUND_BASS, value); 250 sound_prescaler.bass = sound_value_to_cb(SOUND_BASS, value);
234 set_prescaled_volume(); 251 set_prescaled_volume();
235#endif 252#endif
236} 253}
237#endif /* AUDIOHW_HAVE_BASS */ 254#endif /* AUDIOHW_HAVE_BASS */
238 255
239#ifdef AUDIOHW_HAVE_TREBLE 256#if defined(AUDIOHW_HAVE_TREBLE)
240void sound_set_treble(int value) 257void sound_set_treble(int value)
241{ 258{
242 if (!audio_is_initialized) 259 if (!audio_is_initialized)
@@ -245,7 +262,7 @@ void sound_set_treble(int value)
245 audiohw_set_treble(value); 262 audiohw_set_treble(value);
246 263
247#if !defined(AUDIOHW_HAVE_CLIPPING) 264#if !defined(AUDIOHW_HAVE_CLIPPING)
248 current_treble = sound_value_to_cb(SOUND_TREBLE, value); 265 sound_prescaler.treble = sound_value_to_cb(SOUND_TREBLE, value);
249 set_prescaled_volume(); 266 set_prescaled_volume();
250#endif 267#endif
251} 268}
@@ -259,7 +276,7 @@ void sound_set_bass_cutoff(int value)
259 276
260 audiohw_set_bass_cutoff(value); 277 audiohw_set_bass_cutoff(value);
261} 278}
262#endif 279#endif /* AUDIOHW_HAVE_BASS_CUTOFF */
263 280
264#if defined(AUDIOHW_HAVE_TREBLE_CUTOFF) 281#if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
265void sound_set_treble_cutoff(int value) 282void sound_set_treble_cutoff(int value)
@@ -269,7 +286,7 @@ void sound_set_treble_cutoff(int value)
269 286
270 audiohw_set_treble_cutoff(value); 287 audiohw_set_treble_cutoff(value);
271} 288}
272#endif 289#endif /* AUDIOHW_HAVE_TREBLE_CUTOFF */
273 290
274void sound_set_channels(int value) 291void sound_set_channels(int value)
275{ 292{
@@ -295,7 +312,7 @@ void sound_set_depth_3d(int value)
295 312
296 audiohw_set_depth_3d(value); 313 audiohw_set_depth_3d(value);
297} 314}
298#endif 315#endif /* AUDIOHW_HAVE_DEPTH_3D */
299 316
300#if defined(AUDIOHW_HAVE_EQ) 317#if defined(AUDIOHW_HAVE_EQ)
301int sound_enum_hw_eq_band_setting(unsigned int band, 318int sound_enum_hw_eq_band_setting(unsigned int band,
@@ -370,11 +387,13 @@ static void sound_set_hw_eq_band_gain(unsigned int band, int value)
370 if (!audio_is_initialized) 387 if (!audio_is_initialized)
371 return; 388 return;
372 389
373 int setting = sound_enum_hw_eq_band_setting(band, AUDIOHW_EQ_GAIN);
374 current_eq_band_gain[band] = sound_value_to_cb(setting, value);
375
376 audiohw_set_eq_band_gain(band, value); 390 audiohw_set_eq_band_gain(band, value);
391
392#if !defined (AUDIOHW_HAVE_CLIPPING)
393 int setting = sound_enum_hw_eq_band_setting(band, AUDIOHW_EQ_GAIN);
394 sound_prescaler.eq_gain[band] = sound_value_to_cb(setting, value);
377 set_prescaled_volume(); 395 set_prescaled_volume();
396#endif /* AUDIOHW_HAVE_CLIPPING */
378} 397}
379 398
380void sound_set_hw_eq_band1_gain(int value) 399void sound_set_hw_eq_band1_gain(int value)
@@ -557,7 +576,7 @@ void sound_set_superbass(int value)
557} 576}
558#endif /* CONFIG_CODEC == MAS3587F || CONFIG_CODEC == MAS3539F */ 577#endif /* CONFIG_CODEC == MAS3587F || CONFIG_CODEC == MAS3539F */
559 578
560#ifdef HAVE_PITCHCONTROL 579#if defined(HAVE_PITCHCONTROL)
561void sound_set_pitch(int32_t pitch) 580void sound_set_pitch(int32_t pitch)
562{ 581{
563 if (!audio_is_initialized) 582 if (!audio_is_initialized)