Use std::span for sound resample buffers
This commit is contained in:
parent
10d0bbc4e8
commit
fcfd237954
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue