Use std::span for sound resample buffers

This commit is contained in:
Kp 2022-11-12 19:31:52 +00:00
parent 10d0bbc4e8
commit fcfd237954

View file

@ -15,6 +15,7 @@
*/
#include <bitset>
#include <span>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@ -189,12 +190,12 @@ static int32_t coeffs_halfband[FILTER_LEN] =
// Fixed-point FIR filtering
// Not optimal: consider optimization with 1/4, 1/2 band filters, and symmetric kernels
static std::unique_ptr<int16_t[]> filter_fir(int16_t *signal, int signalLen, const int32_t (&coeffs)[FILTER_LEN])
static std::unique_ptr<int16_t[]> filter_fir(const std::span<const int16_t> signal, const std::span<const int32_t, FILTER_LEN> coeffs)
{
auto output = std::make_unique<int16_t[]>(signalLen);
auto output = std::make_unique<int16_t[]>(signal.size());
// A FIR filter is just a 1D convolution
// Keep only signalLen samples
for(int nn = 0; nn < signalLen; nn++)
for (const auto nn : xrange(signal.size()))
{
// Determine start/stop indices for convolved chunk
constexpr std::size_t coeffsLen = FILTER_LEN;
@ -202,7 +203,7 @@ static std::unique_ptr<int16_t[]> filter_fir(int16_t *signal, int signalLen, con
* unsigned subtraction to underflow.
*/
const std::size_t min_idx = (nn + 1 > coeffsLen ? nn + 1 - coeffsLen : 0u);
const std::size_t max_idx = std::min(nn, signalLen - 1);
const std::size_t max_idx = std::min(nn, signal.size() - 1);
if (min_idx > max_idx)
continue;
@ -220,14 +221,14 @@ static std::unique_ptr<int16_t[]> filter_fir(int16_t *signal, int signalLen, con
return output;
}
static std::unique_ptr<int16_t[]> upsample(uint8_t *input, const std::size_t upsampledLen, int inputLen, int factor)
static std::unique_ptr<int16_t[]> upsample(const std::span<const uint8_t> input, const std::size_t upsampledLen, const int factor)
{
/* Caution: `output` is sparsely initialized, so the value-initialization
* from `make_unique` is necessary. This site cannot be converted to
* `make_unique_for_overwrite`.
*/
auto output = std::make_unique<int16_t[]>(upsampledLen);
for(int ii = 0; ii < inputLen; ii++)
for (const auto ii : xrange(input.size()))
{
// Save input sample, convert to signed, and scale
output[ii*factor] = 256 * (int16_t(input[ii]) - 128);
@ -235,10 +236,9 @@ static std::unique_ptr<int16_t[]> upsample(uint8_t *input, const std::size_t ups
return output;
}
static void replicateChannel(int16_t *input, int16_t *output, int inputLen, int chFactor)
static void replicateChannel(const std::span<const int16_t> input, int16_t *const output, int chFactor)
{
for(int ii = 0; ii < inputLen; ii++)
for (const auto ii : xrange(input.size()))
{
// Duplicate and interleave as many channels as needed
for(int jj = 0; jj < chFactor; jj++)
@ -249,13 +249,11 @@ static void replicateChannel(int16_t *input, int16_t *output, int inputLen, int
}
}
static void convert_audio(uint8_t *input, int16_t *output, int inputLen, int upFactor, int chFactor)
static void convert_audio(const std::span<const uint8_t> input, int16_t *const output, int upFactor, int chFactor)
{
// First upsample
int upsampledLen = inputLen*upFactor;
auto stage1 = upsample(input, upsampledLen, inputLen, upFactor);
const auto upsampledLen = input.size() * upFactor;
auto stage1 = upsample(input, upsampledLen, upFactor);
// We expect a 4x upscaling 11025 -> 44100
// But maybe 2x for d2x in some cases
@ -263,10 +261,10 @@ static void convert_audio(uint8_t *input, int16_t *output, int inputLen, int upF
// Apply LPF filter to smooth out upscaled points
// There will be some uniform amplitude loss here, but less than -3dB
auto stage2 = filter_fir(stage1.get(), upsampledLen, coeffs);
auto stage2 = filter_fir({stage1.get(), upsampledLen}, coeffs);
// Replicate channel
replicateChannel(stage2.get(), output, upsampledLen, chFactor);
replicateChannel({stage2.get(), upsampledLen}, output, chFactor);
}
}
@ -310,7 +308,7 @@ static void mixdigi_convert_sound(const unsigned i)
int convertedSize = dlen * upFactor * out_channels * formatFactor;
auto cvtbuf = std::make_unique<Uint8[]>(convertedSize);
convert_audio(data, reinterpret_cast<int16_t*>(cvtbuf.get()), dlen, upFactor, out_channels);
convert_audio({data, dlen}, reinterpret_cast<int16_t*>(cvtbuf.get()), upFactor, out_channels);
SoundChunks[i].abuf = cvtbuf.release();
SoundChunks[i].alen = convertedSize;