libgui 2.01
libgui is a GUI library for the GameCube, Wii, and Wii U
 
Loading...
Searching...
No Matches
OgcAudioDriver.cpp
1/****************************************************************************
2 * Platform Abstraction Layer (OGC driver)
3 * Daryl Borth 2026
4 * OgcAudioDriver.cpp
5 ***************************************************************************/
6#include <ogcsys.h>
7#include <asndlib.h>
8#include <unistd.h>
9
10#include "OgcAudioDriver.h"
11
12static OgcAudioDriver *instance = nullptr;
13
14static void stream_callback(int voice) {
15 if (instance)
16 instance->handleStreamCallback(voice);
17}
18
20 if (voice != 0 || !oggPlayer.isPlaying() || oggPlayer.isPaused())
21 return;
22
23 int32_t size = 0;
24 const uint8_t *buf = oggPlayer.getReadyBuffer(&size);
25
26 if (buf && size > 0) {
27 if (ASND_AddVoice(0, (void*) buf, size) == 0) {
28 oggPlayer.consumeBuffer();
29 }
30 }
31}
32
34 instance = this;
35 ASND_Init();
36 streamVolume = 127;
37}
38
40 DSP_Unhalt();
41 ASND_Init();
42 ASND_Pause(0);
43}
44
46 ASND_Pause(1);
47 ASND_End();
48 AUDIO_StopDMA();
49 AUDIO_RegisterDMACallback(NULL);
50 DSP_Halt();
51}
52
54 stopStream();
55 ASND_Pause(1);
56 ASND_End();
57 AUDIO_StopDMA();
58 AUDIO_RegisterDMACallback(NULL);
59 DSP_Halt(); // fully stop the DSP - without this it's left mid-stream,
60 // which can turn into a squeal/lockup if the process exits
61 // (or the console is powered off) right after this returns
62 instance = nullptr;
63}
64
65int32_t OgcAudioDriver::playVoice(const uint8_t *data, int32_t length, int volume) {
66 int32_t voice = ASND_GetFirstUnusedVoice();
67 if (voice >= 0)
68 ASND_SetVoice(voice, VOICE_STEREO_16BIT, 48000, 0, (uint8_t*) data, length, volume, volume, nullptr);
69 return voice;
70}
71
72void OgcAudioDriver::stopVoice(int32_t voice) {
73 ASND_StopVoice(voice);
74}
75void OgcAudioDriver::pauseVoice(int32_t voice) {
76 ASND_PauseVoice(voice, 1);
77}
78void OgcAudioDriver::resumeVoice(int32_t voice) {
79 ASND_PauseVoice(voice, 0);
80}
81
82bool OgcAudioDriver::isVoicePlaying(int32_t voice) {
83 return ASND_StatusVoice(voice) == SND_WORKING || ASND_StatusVoice(voice) == SND_WAITING;
84}
85
86void OgcAudioDriver::setVoiceVolume(int32_t voice, int volume) {
87 ASND_ChangeVolumeVoice(voice, volume, volume);
88}
89
90void OgcAudioDriver::playStream(const uint8_t *data, int32_t length, bool loop, int volume) {
91 stopStream();
92 streamVolume = volume;
93
94 if (oggPlayer.play(data, length, 0, loop)) {
95 int32_t size = 0;
96 const uint8_t *buf = nullptr;
97
98 // Block momentarily until the worker thread decodes the first buffer chunk
99 while (oggPlayer.isPlaying() && !(buf = oggPlayer.getReadyBuffer(&size))) {
100 usleep(1000);
101 }
102
103 if (buf && size > 0) {
104 int format =(oggPlayer.getChannels() == 2) ? VOICE_STEREO_16BIT : VOICE_MONO_16BIT;
105 ASND_SetVoice(0, format, oggPlayer.getSampleRate(), 0, (void*) buf, size, streamVolume, streamVolume, stream_callback);
106 oggPlayer.consumeBuffer();
107 }
108 }
109}
110
112 ASND_StopVoice(0);
113 oggPlayer.stop();
114}
115
117 ASND_PauseVoice(0, 1);
118 oggPlayer.pause(true);
119}
120
122 ASND_PauseVoice(0, 0);
123 oggPlayer.pause(false);
124}
125
127 return oggPlayer.isPlaying();
128}
129
131 streamVolume = volume;
132 ASND_ChangeVolumeVoice(0, volume, volume);
133}
GC/Wii AudioDriver: AESND-based fixed voices for one-shots, wraps a GuiSoundOggPlayer for the backgro...
void resumeVoice(int32_t voice) override
Resumes a voice paused with pauseVoice().
void shutdown() override
Releases everything init() allocated. Call stop() first.
void stop() override
Stops the audio backend.
void setVoiceVolume(int32_t voice, int volume) override
Changes the volume of a playing voice.
int32_t playVoice(const uint8_t *data, int32_t length, int volume) override
Start a one-shot/short PCM voice.
void pauseVoice(int32_t voice) override
Pauses a playing voice, keeping its position and slot.
void init() override
Allocates the backend's audio resources. Does not start playback; see start().
bool isStreamPlaying() override
void start() override
Starts the audio backend running (eg. registers the DSP/AX callback).
void playStream(const uint8_t *data, int32_t length, bool loop, int volume) override
Streamed (OGG) playback.
void resumeStream() override
Resumes a stream paused with pauseStream().
void stopStream() override
Stops the stream started by playStream().
bool isVoicePlaying(int32_t voice) override
void setStreamVolume(int volume) override
Changes the stream volume.
void pauseStream() override
Pauses the stream, keeping its position.
void handleStreamCallback(int voice)
AESND callback hook, called from interrupt context to refill the stream voice.
void stopVoice(int32_t voice) override
Stops a voice returned by playVoice() and frees its slot.