Skip to content

Commit f8c5c0b

Browse files
authored
Fixedpoint math for VolumeStream (#945)
works at 16bit, too slow for 32bit
1 parent cefb1ba commit f8c5c0b

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

src/AudioConfig.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828

2929
#define AUDIOTOOLS_VERSION "0.9.4"
3030

31+
//#define PREFER_FIXEDPOINT //uses fixed point multiplication instead float for VolumeStream for slightly better performance on platforms without float hardware. Tested on RP2040 at 16 bit per second (still too slow for 32bit)
32+
3133
/**
3234
* -------------------------------------------------------------------------
3335
* @brief Logging

src/AudioTools/VolumeStream.h

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,15 @@ class VolumeStream : public AudioStream {
187187
LOGI("setVolume: %f", volume_value);
188188
float factor = volumeControl().getVolumeFactor(volume_value);
189189
volume_values[channel]=volume_value;
190+
#ifdef PREFER_FIXEDPOINT
191+
//convert float to fixed point 2.6
192+
//Fixedpoint-Math from https://github.com/earlephilhower/ESP8266Audio/blob/0abcf71012f6128d52a6bcd155ed1404d6cc6dcd/src/AudioOutput.h#L67
193+
if(factor > 4.0) factor = 4.0;//factor can only be >1 if allow_boost == true TODO: should we update volume_values[channel] if factor got clipped to 4.0?
194+
uint8_t factorF2P6 = (uint8_t) (factor*(1<<6));
195+
factor_for_channel[channel] = factorF2P6;
196+
#else
190197
factor_for_channel[channel]=factor;
198+
#endif
191199
} else {
192200
LOGE("Invalid channel %d - max: %d", channel, info.channels-1);
193201
}
@@ -211,7 +219,11 @@ class VolumeStream : public AudioStream {
211219
SimulatedAudioPot pot_vc;
212220
CachedVolumeControl cached_volume{pot_vc};
213221
Vector<float> volume_values;
222+
#ifdef PREFER_FIXEDPOINT
223+
Vector<uint8_t> factor_for_channel; //Fixed point 2.6
224+
#else
214225
Vector<float> factor_for_channel;
226+
#endif
215227
bool is_started = false;
216228
float max_value = 32767; // max value for clipping
217229
int max_channels=0;
@@ -256,7 +268,11 @@ class VolumeStream : public AudioStream {
256268
return cached_volume;
257269
}
258270

271+
#ifdef PREFER_FIXEDPOINT
272+
uint8_t factorForChannel(int channel){
273+
#else
259274
float factorForChannel(int channel){
275+
#endif
260276
return factor_for_channel.size()==0? 1.0 : factor_for_channel[channel];
261277
}
262278

@@ -266,7 +282,7 @@ class VolumeStream : public AudioStream {
266282
applyVolume16((int16_t*)buffer, size/2);
267283
break;
268284
case 24:
269-
applyVolume24((int24_t*)buffer, size/3);
285+
applyVolume24((int24_t*)buffer, size/3);//TODO is that size/3 right? sizeof(int24_t) is 4
270286
break;
271287
case 32:
272288
applyVolume32((int32_t*)buffer, size/4);
@@ -278,7 +294,11 @@ class VolumeStream : public AudioStream {
278294

279295
void applyVolume16(int16_t* data, size_t size){
280296
for (size_t j=0;j<size;j++){
297+
#ifdef PREFER_FIXEDPOINT
298+
int32_t result = (data[j] * factorForChannel(j%info.channels)) >> 6; //Fixedpoint-Math from https://github.com/earlephilhower/ESP8266Audio/blob/0abcf71012f6128d52a6bcd155ed1404d6cc6dcd/src/AudioOutput.h#L67
299+
#else
281300
float result = factorForChannel(j%info.channels) * data[j];
301+
#endif
282302
if (!info.allow_boost){
283303
if (result>max_value) result = max_value;
284304
if (result<-max_value) result = -max_value;
@@ -289,7 +309,11 @@ class VolumeStream : public AudioStream {
289309

290310
void applyVolume24(int24_t* data, size_t size) {
291311
for (size_t j=0;j<size;j++){
312+
#ifdef PREFER_FIXEDPOINT
313+
int32_t result = (data[j] * factorForChannel(j%info.channels)) >> 6; //8bits * 24bits = fits into 32
314+
#else
292315
float result = factorForChannel(j%info.channels) * data[j];
316+
#endif
293317
if (!info.allow_boost){
294318
if (result>max_value) result = max_value;
295319
if (result<-max_value) result = -max_value;
@@ -301,7 +325,11 @@ class VolumeStream : public AudioStream {
301325

302326
void applyVolume32(int32_t* data, size_t size) {
303327
for (size_t j=0;j<size;j++){
328+
#ifdef PREFER_FIXEDPOINT
329+
int64_t result = (static_cast<int64_t>(data[j]) * static_cast<int64_t>(factorForChannel(j%info.channels))) >> 6;
330+
#else
304331
float result = factorForChannel(j%info.channels) * data[j];
332+
#endif
305333
if (!info.allow_boost){
306334
if (result>max_value) result = max_value;
307335
if (result<-max_value) result = -max_value;

0 commit comments

Comments
 (0)