Skip to content

Commit 488d1e0

Browse files
author
Kevin Ahrendt
authored
Ensure single precision floating point arithmetic and rename utils (#13)
* rename files and introduce new namespace * ensure all values are floating point * use new file header and ensure floating point * use floating point math operations
1 parent ccc1197 commit 488d1e0

File tree

4 files changed

+53
-49
lines changed

4 files changed

+53
-49
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <stdint.h>
55

66
namespace esp_audio_libs {
7+
namespace quantization_utils {
78

89
/// @brief Converts an array of quantized samples with the specified number of bits into floating point samples.
910
/// @param input_buffer Pointer to the input quantized samples aligned to the byte
@@ -23,4 +24,5 @@ void quantized_to_float(const uint8_t *input_buffer, float *output_buffer, uint3
2324
uint32_t float_to_quantized(const float *input_buffer, uint8_t *output_buffer, uint32_t num_samples,
2425
uint8_t output_bits);
2526

27+
} // namespace quantization_utils
2628
} // namespace esp_audio_libs

src/utils.cpp renamed to src/quantization_utils.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
1-
#include "utils.h"
1+
#include "quantization_utils.h"
22

33
namespace esp_audio_libs {
4+
namespace quantization_utils {
45

56
void quantized_to_float(const uint8_t *input_buffer, float *output_buffer, uint32_t num_samples, uint8_t input_bits,
67
float gain_db) {
7-
float gain = pow(10.0, gain_db / 20.0);
8+
float gain = powf(10.0f, gain_db / 20.0f);
89

910
if (input_bits <= 8) {
10-
float gain_factor = gain / 128.0;
11+
float gain_factor = gain / 128.0f;
1112

1213
for (unsigned int i = 0; i < num_samples; ++i) {
1314
output_buffer[i] = ((int) input_buffer[i] - 128) * gain_factor;
1415
}
1516

1617
} else if (input_bits <= 16) {
17-
float gain_factor = gain / 32768.0;
18+
float gain_factor = gain / 32768.0f;
1819
unsigned int i, j;
1920

2021
for (i = j = 0; i < num_samples; ++i) {
@@ -23,7 +24,7 @@ void quantized_to_float(const uint8_t *input_buffer, float *output_buffer, uint3
2324
output_buffer[i] = value * gain_factor;
2425
}
2526
} else if (input_bits <= 24) {
26-
float gain_factor = gain / 8388608.0;
27+
float gain_factor = gain / 8388608.0f;
2728
unsigned int i, j;
2829

2930
for (i = j = 0; i < num_samples; ++i) {
@@ -33,7 +34,7 @@ void quantized_to_float(const uint8_t *input_buffer, float *output_buffer, uint3
3334
output_buffer[i] = value * gain_factor;
3435
}
3536
} else if (input_bits <= 32) {
36-
float gain_factor = gain / 2147483648.0;
37+
float gain_factor = gain / 2147483648.0f;
3738
unsigned int i, j;
3839

3940
for (i = j = 0; i < num_samples; ++i) {
@@ -48,7 +49,7 @@ void quantized_to_float(const uint8_t *input_buffer, float *output_buffer, uint3
4849

4950
uint32_t float_to_quantized(const float *input_buffer, uint8_t *output_buffer, uint32_t num_samples,
5051
uint8_t output_bits) {
51-
float scalar = (static_cast<uint64_t>(1) << output_bits) / 2.0;
52+
float scalar = (static_cast<uint64_t>(1) << output_bits) / 2.0f;
5253
int32_t offset = (output_bits <= 8) * 128;
5354
int32_t high_clip = (1 << (output_bits - 1)) - 1;
5455
int32_t low_clip = ~high_clip;
@@ -57,7 +58,7 @@ uint32_t float_to_quantized(const float *input_buffer, uint8_t *output_buffer, u
5758
uint32_t clipped_samples = 0;
5859

5960
for (i = j = 0; i < num_samples; ++i) {
60-
int32_t output = floor((input_buffer[i] * scalar) + 0.5);
61+
int32_t output = floorf((input_buffer[i] * scalar) + 0.5f);
6162
if (output_bits < 32) {
6263
if (output > high_clip) {
6364
++clipped_samples;
@@ -92,4 +93,5 @@ uint32_t float_to_quantized(const float *input_buffer, uint8_t *output_buffer, u
9293
return clipped_samples;
9394
}
9495

95-
}
96+
} // namespace quantization_utils
97+
} // namespace esp_audio_libs

src/resample/art_resampler.cpp

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,11 @@ Resample *resampleInit(int numChannels, int numTaps, int numFilters, float lowpa
8080
Resample *cxt = (Resample *) calloc(1, sizeof(Resample));
8181
int i;
8282

83-
if (lowpassRatio > 0.0 && lowpassRatio < 1.0)
83+
if (lowpassRatio > 0.0f && lowpassRatio < 1.0f)
8484
flags |= INCLUDE_LOWPASS;
8585
else {
8686
flags &= ~INCLUDE_LOWPASS;
87-
lowpassRatio = 1.0;
87+
lowpassRatio = 1.0f;
8888
}
8989

9090
if ((numTaps & 3) || numTaps <= 0 || numTaps > 1024) {
@@ -183,7 +183,7 @@ ResampleResult resampleProcess(Resample *cxt, const float *const *input, int num
183183
for (i = 0; i < cxt->numChannels; ++i)
184184
output[i][res.output_generated] = subsample(cxt, cxt->buffers[i], cxt->outputOffset);
185185

186-
cxt->outputOffset += (1.0 / ratio);
186+
cxt->outputOffset += (1.0f / ratio);
187187
res.output_generated++;
188188
numOutputFrames--;
189189
}
@@ -224,7 +224,7 @@ ResampleResult resampleProcessInterleaved(Resample *cxt, const float *input, int
224224
for (i = 0; i < cxt->numChannels; ++i)
225225
*output++ = subsample(cxt, cxt->buffers[i], cxt->outputOffset);
226226

227-
cxt->outputOffset += (1.0 / ratio);
227+
cxt->outputOffset += (1.0f / ratio);
228228
res.output_generated++;
229229
numOutputFrames--;
230230
}
@@ -261,7 +261,7 @@ unsigned int resampleGetRequiredSamples(Resample *cxt, int numOutputFrames, floa
261261
input_index++;
262262
res.input_used++;
263263
} else {
264-
offset += (1.0 / ratio);
264+
offset += (1.0f / ratio);
265265
numOutputFrames--;
266266
}
267267
}
@@ -288,7 +288,7 @@ unsigned int resampleGetExpectedOutput(Resample *cxt, int numInputFrames, float
288288
} else
289289
break;
290290
} else {
291-
offset += (1.0 / ratio);
291+
offset += (1.0f / ratio);
292292
res.output_generated++;
293293
}
294294
}
@@ -302,7 +302,7 @@ unsigned int resampleGetExpectedOutput(Resample *cxt, int numInputFrames, float
302302
// phase shift. The resampler cannot be reversed.
303303

304304
void resampleAdvancePosition(Resample *cxt, float delta) {
305-
if (delta < 0.0)
305+
if (delta < 0.0f)
306306
fprintf(stderr, "resampleAdvancePosition() can only advance forward!\n");
307307
else
308308
cxt->outputOffset += delta;
@@ -336,7 +336,7 @@ void resampleAdvancePosition(Resample *cxt, float delta) {
336336
// break;
337337
// }
338338

339-
float resampleGetPosition(Resample *cxt) { return cxt->outputOffset + (cxt->numTaps / 2.0) - cxt->inputIndex; }
339+
float resampleGetPosition(Resample *cxt) { return cxt->outputOffset + (cxt->numTaps / 2.0f) - cxt->inputIndex; }
340340

341341
// Free all resources associated with the resampler context, including the context pointer
342342
// itself. Do not use the context after this call.
@@ -368,11 +368,11 @@ static float apply_filter(float *A, float *B, int num_taps) {
368368
#endif
369369

370370
static void init_filter(Resample *cxt, float *filter, float fraction, float lowpass_ratio) {
371-
const float a0 = 0.35875;
372-
const float a1 = 0.48829;
373-
const float a2 = 0.14128;
374-
const float a3 = 0.01168;
375-
float filter_sum = 0.0;
371+
const float a0 = 0.35875f;
372+
const float a1 = 0.48829f;
373+
const float a2 = 0.14128f;
374+
const float a3 = 0.01168f;
375+
float filter_sum = 0.0f;
376376
int i;
377377

378378
// "dist" is the absolute distance from the sinc maximum to the filter tap to be calculated, in radians
@@ -386,22 +386,22 @@ static void init_filter(Resample *cxt, float *filter, float fraction, float lowp
386386
float ratio = dist / (cxt->numTaps / 2);
387387
float value;
388388

389-
if (dist != 0.0) {
389+
if (dist != 0.0f) {
390390
value = sin(dist * lowpass_ratio) / (dist * lowpass_ratio);
391391

392392
if (cxt->flags & BLACKMAN_HARRIS)
393393
value *= a0 + a1 * cos(ratio) + a2 * cos(2 * ratio) + a3 * cos(3 * ratio);
394394
else
395-
value *= 0.5 * (1.0 + cos(ratio)); // Hann window
395+
value *= 0.5f * (1.0f + cos(ratio)); // Hann window
396396
} else
397-
value = 1.0;
397+
value = 1.0f;
398398

399399
filter_sum += cxt->tempFilter[i] = value;
400400
}
401401

402402
// filter should have unity DC gain
403403

404-
float scaler = 1.0 / filter_sum, error = 0.0;
404+
float scaler = 1.0f / filter_sum, error = 0.0f;
405405

406406
for (i = cxt->numTaps / 2; i < cxt->numTaps; i = cxt->numTaps - i - (i >= cxt->numTaps / 2)) {
407407
filter[i] = (cxt->tempFilter[i] *= scaler) - error;
@@ -413,10 +413,10 @@ static float subsample_no_interpolate(Resample *cxt, float *source, float offset
413413
source += (int) floor(offset);
414414
offset -= floor(offset);
415415

416-
if (offset == 0.0 && !(cxt->flags & INCLUDE_LOWPASS))
416+
if (offset == 0.0f && !(cxt->flags & INCLUDE_LOWPASS))
417417
return *source;
418418

419-
return apply_filter(cxt->filters[(int) floor(offset * cxt->numFilters + 0.5)], source - cxt->numTaps / 2 + 1,
419+
return apply_filter(cxt->filters[(int) floor(offset * cxt->numFilters + 0.5f)], source - cxt->numTaps / 2 + 1,
420420
cxt->numTaps);
421421
}
422422

@@ -427,18 +427,18 @@ static float subsample_interpolate(Resample *cxt, float *source, float offset) {
427427
source += (int) floor(offset);
428428
offset -= floor(offset);
429429

430-
if (offset == 0.0 && !(cxt->flags & INCLUDE_LOWPASS))
430+
if (offset == 0.0f && !(cxt->flags & INCLUDE_LOWPASS))
431431
return *source;
432432

433433
i = (int) floor(offset *= cxt->numFilters);
434434
sum1 = apply_filter(cxt->filters[i], source - cxt->numTaps / 2 + 1, cxt->numTaps);
435435

436-
if ((offset -= i) == 0.0 && !(cxt->flags & INCLUDE_LOWPASS))
436+
if ((offset -= i) == 0.0f && !(cxt->flags & INCLUDE_LOWPASS))
437437
return sum1;
438438

439439
sum2 = apply_filter(cxt->filters[i + 1], source - cxt->numTaps / 2 + 1, cxt->numTaps);
440440

441-
return sum2 * offset + sum1 * (1.0 - offset);
441+
return sum2 * offset + sum1 * (1.0f - offset);
442442
}
443443

444444
static float subsample(Resample *cxt, float *source, float offset) {

src/resample/resampler.cpp

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#include "resampler.h"
2-
#include "utils.h"
2+
#include "quantization_utils.h"
33

44
namespace esp_audio_libs {
55
namespace resampler {
@@ -44,48 +44,48 @@ bool Resampler::initialize(ResamplerConfiguration &config) {
4444

4545
this->sample_ratio_ = config.target_sample_rate / config.source_sample_rate;
4646

47-
if (this->sample_ratio_ < 1.0) {
48-
this->lowpass_ratio_ -= (10.24 / this->number_of_taps_);
47+
if (this->sample_ratio_ < 1.0f) {
48+
this->lowpass_ratio_ -= (10.24f / this->number_of_taps_);
4949

50-
if (this->lowpass_ratio_ < 0.84) {
51-
this->lowpass_ratio_ = 0.84;
50+
if (this->lowpass_ratio_ < 0.84f) {
51+
this->lowpass_ratio_ = 0.84f;
5252
}
5353

5454
if (this->lowpass_ratio_ < this->sample_ratio_) {
5555
// avoid discontinuities near unity sample ratios
5656
this->lowpass_ratio_ = this->sample_ratio_;
5757
}
5858
}
59-
if (this->lowpass_ratio_ * this->sample_ratio_ < 0.98 && config.use_pre_or_post_filter) {
60-
float cutoff = this->lowpass_ratio_ * this->sample_ratio_ / 2.0;
59+
if (this->lowpass_ratio_ * this->sample_ratio_ < 0.98f && config.use_pre_or_post_filter) {
60+
float cutoff = this->lowpass_ratio_ * this->sample_ratio_ / 2.0f;
6161
art_resampler::biquad_lowpass(&this->lowpass_coeff_, cutoff);
6262
this->pre_filter_ = true;
6363
}
6464

65-
if (this->lowpass_ratio_ / this->sample_ratio_ < 0.98 && config.use_pre_or_post_filter && !this->pre_filter_) {
66-
float cutoff = this->lowpass_ratio_ / this->sample_ratio_ / 2.0;
65+
if (this->lowpass_ratio_ / this->sample_ratio_ < 0.98f && config.use_pre_or_post_filter && !this->pre_filter_) {
66+
float cutoff = this->lowpass_ratio_ / this->sample_ratio_ / 2.0f;
6767
art_resampler::biquad_lowpass(&this->lowpass_coeff_, cutoff);
6868
this->post_filter_ = true;
6969
}
7070

7171
if (this->pre_filter_ || this->post_filter_) {
7272
for (int i = 0; i < this->channels_; ++i) {
73-
art_resampler::biquad_init(&this->lowpass_[i][0], &this->lowpass_coeff_, 1.0);
74-
art_resampler::biquad_init(&this->lowpass_[i][1], &this->lowpass_coeff_, 1.0);
73+
art_resampler::biquad_init(&this->lowpass_[i][0], &this->lowpass_coeff_, 1.0f);
74+
art_resampler::biquad_init(&this->lowpass_[i][1], &this->lowpass_coeff_, 1.0f);
7575
}
7676
}
7777

78-
if (this->sample_ratio_ < 1.0) {
78+
if (this->sample_ratio_ < 1.0f) {
7979
this->resampler_ = art_resampler::resampleInit(this->channels_, this->number_of_taps_, this->number_of_filters_,
8080
this->sample_ratio_ * this->lowpass_ratio_, flags | INCLUDE_LOWPASS);
81-
} else if (this->lowpass_ratio_ < 1.0) {
81+
} else if (this->lowpass_ratio_ < 1.0f) {
8282
this->resampler_ = art_resampler::resampleInit(this->channels_, this->number_of_taps_, this->number_of_filters_,
8383
this->lowpass_ratio_, flags | INCLUDE_LOWPASS);
8484
} else {
85-
this->resampler_ = art_resampler::resampleInit(this->channels_, this->number_of_taps_, this->number_of_filters_, 1.0, flags);
85+
this->resampler_ = art_resampler::resampleInit(this->channels_, this->number_of_taps_, this->number_of_filters_, 1.0f, flags);
8686
}
8787

88-
art_resampler::resampleAdvancePosition(this->resampler_, this->number_of_taps_ / 2.0);
88+
art_resampler::resampleAdvancePosition(this->resampler_, this->number_of_taps_ / 2.0f);
8989
}
9090

9191
return true;
@@ -104,11 +104,11 @@ ResamplerResults Resampler::resample(const uint8_t *input_buffer, uint8_t *outpu
104104
}
105105
uint32_t conversion_time = 0;
106106
if (this->requires_resampling_) {
107-
quantized_to_float(input_buffer, this->float_input_buffer_, frames_to_process * this->channels_, this->input_bits_,
107+
quantization_utils::quantized_to_float(input_buffer, this->float_input_buffer_, frames_to_process * this->channels_, this->input_bits_,
108108
gain_db);
109109
} else {
110110
// Just converting the bits per sample
111-
quantized_to_float(input_buffer, this->float_output_buffer_, frames_to_process * this->channels_, this->input_bits_,
111+
quantization_utils::quantized_to_float(input_buffer, this->float_output_buffer_, frames_to_process * this->channels_, this->input_bits_,
112112
gain_db);
113113
}
114114

@@ -139,7 +139,7 @@ ResamplerResults Resampler::resample(const uint8_t *input_buffer, uint8_t *outpu
139139
}
140140
}
141141

142-
uint32_t clipped_samples = float_to_quantized(this->float_output_buffer_, output_buffer,
142+
uint32_t clipped_samples = quantization_utils::float_to_quantized(this->float_output_buffer_, output_buffer,
143143
frames_generated * this->channels_, this->output_bits_);
144144

145145
ResamplerResults results = {.frames_used = frames_used,

0 commit comments

Comments
 (0)