Resample audio with SDL3

This commit is contained in:
PJB3005
2026-03-14 15:50:39 +01:00
parent 602f69673b
commit 5eaec7360b
3 changed files with 78 additions and 21 deletions
+2 -1
View File
@@ -35,7 +35,7 @@ static void InitSDL3Output() {
constexpr SDL_AudioSpec spec = {
SDL_AUDIO_S16,
1,
32000,
SampleRate,
};
PlaybackStream = SDL_OpenAudioDeviceStream(
SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK,
@@ -46,6 +46,7 @@ static void InitSDL3Output() {
void dusk::audio::Initialize() {
InitSDL3Output();
DspInit();
JASDsp::initBuffer();
JASDSPChannel::initAll();
+70 -20
View File
@@ -5,7 +5,6 @@
#include <algorithm>
#include <cassert>
#include <iosfwd>
#include "Adpcm.hpp"
#include "global.h"
@@ -58,9 +57,18 @@ static void RenderChannel(
ChannelAuxData& channelAux,
DspSubframe& subframe);
static void ResetChannel(JASDsp::TChannel& channel) {
static void ResetChannel(JASDsp::TChannel& channel, const ChannelAuxData& aux) {
channel.mSamplesLeft = channel.mEndSample - channel.mSamplePosition;
const SDL_AudioSpec spec = {
SDL_AUDIO_S16,
1,
static_cast<int>(static_cast<u64>(SampleRate) * channel.mPitch / 4096)
};
SDL_ClearAudioStream(aux.resampleStream);
SDL_SetAudioStreamFormat(aux.resampleStream, &spec, nullptr);
channel.mResetFlag = false;
}
@@ -92,13 +100,21 @@ void dusk::audio::DspRender(DspSubframe& subframe) {
}
}
static void RenderChannel(
JASDsp::TChannel& channel,
ChannelAuxData& channelAux,
DspSubframe& subframe) {
if (channel.mResetFlag) {
ResetChannel(channel);
}
static void SDLCALL ReadChannelSamples(
void *userdata,
SDL_AudioStream *stream,
int additional_amount,
int) {
const auto index = static_cast<u32>(reinterpret_cast<uintptr_t>(userdata));
auto& channel = JASDsp::CH_BUF[index];
auto& aux = ChannelAux[index];
additional_amount = ALIGN_NEXT(additional_amount, channel.mSamplesPerBlock);
int requestedSize = static_cast<int>(sizeof(s16) * additional_amount);
auto requested = static_cast<s16*>(alloca(requestedSize));
memset(requested, 0, requestedSize);
auto aramBase = static_cast<u8*>(ARGetStorageAddress()) + channel.mWaveAramAddress;
@@ -107,15 +123,15 @@ static void RenderChannel(
auto curSamplePosition = channel.mEndSample - channel.mSamplesLeft;
auto dataPosition = ConvertSamplesToDataLength(channel, curSamplePosition);
u32 renderSamples = std::min(channel.mSamplesLeft, static_cast<u32>(DSP_SUBFRAME_SIZE));
u32 renderSamples = std::min(channel.mSamplesLeft, static_cast<u32>(additional_amount));
Adpcm4ToPcm16(
aramBase + dataPosition,
ConvertSamplesToDataLength(channel, renderSamples),
subframe.data(),
requested,
renderSamples,
channelAux.hist1,
channelAux.hist0);
aux.hist1,
aux.hist0);
channel.mSamplesLeft -= renderSamples;
channel.mSamplePosition += renderSamples;
@@ -135,16 +151,50 @@ static void RenderChannel(
Adpcm4ToPcm16(
aramBase + dataPosition,
ConvertSamplesToDataLength(channel, DSP_SUBFRAME_SIZE - renderSamples),
subframe.data() + renderSamples,
subframe.size() - renderSamples,
channelAux.hist1,
channelAux.hist0);
ConvertSamplesToDataLength(channel, additional_amount - renderSamples),
requested + renderSamples,
additional_amount - renderSamples,
aux.hist1,
aux.hist0);
channel.mSamplesLeft -= (DSP_SUBFRAME_SIZE - renderSamples);
channel.mSamplePosition += (DSP_SUBFRAME_SIZE - renderSamples);
channel.mSamplesLeft -= (additional_amount - renderSamples);
channel.mSamplePosition += (additional_amount - renderSamples);
}
channel.mAramStreamPosition = channel.mWaveAramAddress
+ ConvertSamplesToDataLength(channel, channel.mSamplePosition);
SDL_PutAudioStreamData(stream, requested, requestedSize);
}
static void RenderChannel(
JASDsp::TChannel& channel,
ChannelAuxData& channelAux,
DspSubframe& subframe) {
if (channel.mResetFlag) {
ResetChannel(channel, channelAux);
}
SDL_GetAudioStreamData(
channelAux.resampleStream,
subframe.data(),
static_cast<int>(subframe.size() * sizeof(s16)));
}
void dusk::audio::DspInit() {
constexpr SDL_AudioSpec spec = {
SDL_AUDIO_S16,
1,
SampleRate
};
for (int i = 0; i < DSP_CHANNELS; i++) {
auto& aux = ChannelAux[i];
aux.resampleStream = SDL_CreateAudioStream(&spec, &spec);
SDL_SetAudioStreamGetCallback(
aux.resampleStream,
ReadChannelSamples,
reinterpret_cast<void*>(i));
}
}
+6
View File
@@ -4,15 +4,21 @@
#include <array>
#include "SDL3/SDL_audio.h"
namespace dusk::audio {
constexpr int SampleRate = 32000;
struct ChannelAuxData {
s16 hist1;
s16 hist0;
SDL_AudioStream* resampleStream;
};
extern ChannelAuxData ChannelAux[DSP_CHANNELS];
using DspSubframe = std::array<s16, DSP_SUBFRAME_SIZE>;
void DspInit();
void DspRender(DspSubframe& subframe);
}