Refactor Audio

This commit is contained in:
SimoneN64
2024-05-10 21:24:57 +02:00
committed by Simone
parent 423647d69a
commit e44646b870
5 changed files with 52 additions and 39 deletions

View File

@@ -2,7 +2,6 @@
#include <log.hpp> #include <log.hpp>
#include <core/Mem.hpp> #include <core/Mem.hpp>
#include <core/registers/Registers.hpp> #include <core/registers/Registers.hpp>
#include <Audio.hpp>
namespace n64 { namespace n64 {
void AI::Reset() { void AI::Reset() {
@@ -56,12 +55,12 @@ void AI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
InterruptLower(mem.mmio.mi, regs, Interrupt::AI); InterruptLower(mem.mmio.mi, regs, Interrupt::AI);
break; break;
case 0x04500010: { case 0x04500010: {
u32 old_dac_freq = dac.freq; u32 oldDacFreq = dac.freq;
dacRate = val & 0x3FFF; dacRate = val & 0x3FFF;
dac.freq = std::max(1u, GetVideoFrequency(mem.IsROMPAL()) / (dacRate + 1)); dac.freq = std::max(1u, GetVideoFrequency(mem.IsROMPAL()) / (dacRate + 1));
dac.period = N64_CPU_FREQ / dac.freq; dac.period = N64_CPU_FREQ / dac.freq;
if(old_dac_freq != dac.freq) { if(oldDacFreq != dac.freq) {
AdjustSampleRate(dac.freq); device.AdjustSampleRate(dac.freq);
} }
} break; } break;
case 0x04500014: case 0x04500014:
@@ -87,7 +86,7 @@ void AI::Step(Mem& mem, Registers& regs, u32 cpuCycles, float volumeL, float vol
s16 r = s16(data); s16 r = s16(data);
if(volumeR > 0 && volumeL > 0) { if(volumeR > 0 && volumeL > 0) {
PushSample((float) l / INT16_MAX, volumeL, (float) r / INT16_MAX, volumeR); device.PushSample((float) l / INT16_MAX, volumeL, (float) r / INT16_MAX, volumeR);
} }
u32 addrLo = (dmaAddr[0] + 4) & 0x1FFF; u32 addrLo = (dmaAddr[0] + 4) & 0x1FFF;

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <common.hpp> #include <common.hpp>
#include <core/mmio/Interrupt.hpp> #include <core/mmio/Interrupt.hpp>
#include "Audio.hpp"
namespace n64 { namespace n64 {
struct Mem; struct Mem;
@@ -20,6 +21,7 @@ struct AI {
u32 dmaAddr[2]{}; u32 dmaAddr[2]{};
bool dmaAddrCarry{}; bool dmaAddrCarry{};
u32 cycles{}; u32 cycles{};
AudioDevice device;
struct { struct {
u32 freq{44100}; u32 freq{44100};

View File

@@ -1,6 +1,5 @@
#include <Audio.hpp> #include <Audio.hpp>
#include <log.hpp> #include <log.hpp>
#include <SDL2/SDL.h>
namespace n64 { namespace n64 {
#define AUDIO_SAMPLE_RATE 44100 #define AUDIO_SAMPLE_RATE 44100
@@ -8,56 +7,47 @@ namespace n64 {
#define SYSTEM_SAMPLE_SIZE 4 #define SYSTEM_SAMPLE_SIZE 4
#define BYTES_PER_HALF_SECOND (((float)AUDIO_SAMPLE_RATE / 2) * SYSTEM_SAMPLE_SIZE) #define BYTES_PER_HALF_SECOND (((float)AUDIO_SAMPLE_RATE / 2) * SYSTEM_SAMPLE_SIZE)
static SDL_AudioStream* audioStream = nullptr; void audioCallback(void* user, Uint8* stream, int length) {
SDL_mutex* audioStreamMutex; auto audioDevice = (AudioDevice*)user;
SDL_AudioSpec audioSpec;
SDL_AudioSpec request;
SDL_AudioDeviceID audioDev{};
#define LockAudioMutex() SDL_LockMutex(audioStreamMutex)
#define UnlockAudioMutex() SDL_UnlockMutex(audioStreamMutex)
void audioCallback(void*, Uint8* stream, int length) {
int gotten = 0; int gotten = 0;
LockAudioMutex(); audioDevice->LockMutex();
int available = SDL_AudioStreamAvailable(audioStream); int available = SDL_AudioStreamAvailable(audioDevice->GetStream());
if (available > 0) { if (available > 0) {
gotten = SDL_AudioStreamGet(audioStream, stream, length); gotten = SDL_AudioStreamGet(audioDevice->GetStream(), stream, length);
} }
UnlockAudioMutex(); audioDevice->UnlockMutex();
int gotten_samples = (int)(gotten / sizeof(float)); int gottenSamples = (int)(gotten / sizeof(float));
auto* out = (float*)stream; auto* out = (float*)stream;
out += gotten_samples; out += gottenSamples;
for (int i = gotten_samples; i < length / sizeof(float); i++) { for (int i = gottenSamples; i < length / sizeof(float); i++) {
float sample = 0; float sample = 0;
*out++ = sample; *out++ = sample;
} }
} }
void InitAudio() { AudioDevice::AudioDevice() {
SDL_InitSubSystem(SDL_INIT_AUDIO); SDL_InitSubSystem(SDL_INIT_AUDIO);
AdjustSampleRate(AUDIO_SAMPLE_RATE); AdjustSampleRate(AUDIO_SAMPLE_RATE);
memset(&request, 0, sizeof(request));
request.freq = AUDIO_SAMPLE_RATE; request.freq = AUDIO_SAMPLE_RATE;
request.format = SYSTEM_SAMPLE_FORMAT; request.format = SYSTEM_SAMPLE_FORMAT;
request.channels = 2; request.channels = 2;
request.samples = 1024; request.samples = 1024;
request.callback = audioCallback; request.callback = audioCallback;
request.userdata = nullptr; request.userdata = (void*)this;
if(!audioDev) { if(!handle) {
audioDev = SDL_OpenAudioDevice(nullptr, 0, &request, &audioSpec, 0); handle = SDL_OpenAudioDevice(nullptr, 0, &request, &audioSpec, 0);
} }
if(!audioDev) { if(!handle) {
Util::panic("Failed to initialize SDL Audio: {}", SDL_GetError()); Util::panic("Failed to initialize SDL Audio: {}", SDL_GetError());
} }
SDL_PauseAudioDevice(audioDev, false); SDL_PauseAudioDevice(handle, false);
audioStreamMutex = SDL_CreateMutex(); audioStreamMutex = SDL_CreateMutex();
@@ -66,7 +56,7 @@ void InitAudio() {
} }
} }
void PushSample(float left, float volumeL, float right, float volumeR) { void AudioDevice::PushSample(float left, float volumeL, float right, float volumeR) {
float adjustedL = left * volumeL; float adjustedL = left * volumeL;
float adjustedR = right * volumeR; float adjustedR = right * volumeR;
float samples[2]{ adjustedL, adjustedR }; float samples[2]{ adjustedL, adjustedR };
@@ -77,12 +67,11 @@ void PushSample(float left, float volumeL, float right, float volumeR) {
} }
} }
void AdjustSampleRate(int sampleRate) { void AudioDevice::AdjustSampleRate(int sampleRate) {
LockAudioMutex(); LockMutex();
if(audioStream) SDL_FreeAudioStream(audioStream); if(audioStream) SDL_FreeAudioStream(audioStream);
audioStream = SDL_NewAudioStream(AUDIO_F32SYS, 2, sampleRate, SYSTEM_SAMPLE_FORMAT, 2, AUDIO_SAMPLE_RATE); audioStream = SDL_NewAudioStream(AUDIO_F32SYS, 2, sampleRate, SYSTEM_SAMPLE_FORMAT, 2, AUDIO_SAMPLE_RATE);
UnlockAudioMutex(); UnlockMutex();
} }
} }

View File

@@ -1,8 +1,31 @@
#pragma once #pragma once
#include <common.hpp> #include <common.hpp>
#include <SDL2/SDL.h>
namespace n64 { namespace n64 {
void PushSample(float, float, float, float); struct AudioDevice {
void InitAudio(); AudioDevice();
void AdjustSampleRate(int); ~AudioDevice() {
SDL_FreeAudioStream(audioStream);
SDL_DestroyMutex(audioStreamMutex);
}
void PushSample(float, float, float, float);
void AdjustSampleRate(int);
void LockMutex() {
SDL_LockMutex(audioStreamMutex);
}
void UnlockMutex() {
SDL_UnlockMutex(audioStreamMutex);
}
SDL_AudioStream* GetStream() { return audioStream; }
private:
SDL_AudioStream* audioStream = nullptr;
SDL_mutex* audioStreamMutex = nullptr;
SDL_AudioSpec audioSpec{};
SDL_AudioSpec request{};
SDL_AudioDeviceID handle{};
};
} }

View File

@@ -9,7 +9,7 @@ EmuThread::EmuThread(std::unique_ptr<QtInstanceFactory>&& instance, std::unique_
[[noreturn]] void EmuThread::run() noexcept { [[noreturn]] void EmuThread::run() noexcept {
LoadWSIPlatform(instance.get(), std::move(wsiPlatform), std::move(windowInfo)); LoadWSIPlatform(instance.get(), std::move(wsiPlatform), std::move(windowInfo));
LoadParallelRDP(core->cpu->mem.GetRDRAM()); LoadParallelRDP(core->cpu->mem.GetRDRAM());
n64::InitAudio();
while (true) { while (true) {
if (!core->pause) { if (!core->pause) {
core->Run(settings->getVolumeL(), settings->getVolumeR()); core->Run(settings->getVolumeL(), settings->getVolumeR());