diff options
Diffstat (limited to 'firmware/sound.c')
-rw-r--r-- | firmware/sound.c | 109 |
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 | ||
115 | static int current_volume = 0; /* tenth dB */ | ||
116 | static int current_balance = 0; /* percent */ | ||
117 | #ifdef AUDIOHW_HAVE_TREBLE | ||
118 | static int current_treble = 0; /* tenth dB */ | ||
119 | #endif | ||
120 | #ifdef AUDIOHW_HAVE_BASS | ||
121 | static int current_bass = 0; /* tenth dB */ | ||
122 | #endif | ||
123 | #ifdef AUDIOHW_HAVE_EQ | ||
124 | static 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) */ |
128 | static int sound_value_to_cb(int setting, int value) | 116 | static 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 | ||
124 | static 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 | |||
136 | static void set_prescaled_volume(void) | 144 | static 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) |
225 | void sound_set_bass(int value) | 242 | void 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) |
240 | void sound_set_treble(int value) | 257 | void 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) |
265 | void sound_set_treble_cutoff(int value) | 282 | void 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 | ||
274 | void sound_set_channels(int value) | 291 | void 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) |
301 | int sound_enum_hw_eq_band_setting(unsigned int band, | 318 | int 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 | ||
380 | void sound_set_hw_eq_band1_gain(int value) | 399 | void 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) |
561 | void sound_set_pitch(int32_t pitch) | 580 | void sound_set_pitch(int32_t pitch) |
562 | { | 581 | { |
563 | if (!audio_is_initialized) | 582 | if (!audio_is_initialized) |