From 952f5526016226e04defaa5fb130bd9fc2af5d8e Mon Sep 17 00:00:00 2001 From: JJ Bliss Date: Tue, 7 Jul 2026 17:44:14 -0400 Subject: [PATCH] Added audio.ha --- uxn/audio.ha | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 uxn/audio.ha diff --git a/uxn/audio.ha b/uxn/audio.ha new file mode 100644 index 0000000..05b7645 --- /dev/null +++ b/uxn/audio.ha @@ -0,0 +1,169 @@ +use fmt; +use sdl3; + +def SAMPLE_FREQUENCY = 44100; +def POLYPHONY = 4; +def NOTE_PERIOD = (SAMPLE_FREQUENCY * 0x4000 / 11025); +def ADSR_STEP = (SAMPLE_FREQUENCY / 0xf); + +export fn init_audio() void = { + let aspec = sdl3::AudioSpec { + format = sdl3::AudioFormat::S16, + channels = 2, + freq = SAMPLE_FREQUENCY, + }; + // sdl3::zero(as); + // as.freq = SAMPLE_FREQUENCY; + // as.format = AUDIO_S16SYS; + // as.channels = 2; + // as.callback = audio_callback; + // as.samples = 512; + // as.userdata = NULL; + // sdl3::OpenAudioDeviceStream(null,0,&as,null,0); + const device = *(sdl3::GetAudioPlaybackDevices(&1)!); + const audio_id = sdl3::OpenAudioDeviceStream(device,&aspec,&audio_callback,null); +}; + +fn audio_callback(userdata: nullable *opaque,stream: nullable *sdl3::AudioStream, additional_amount: int, total_amount: int) void = { + + // int instance, running = 0; + let instance = 0; + let running = 0; + // Sint16 *samples = (Sint16 *)stream; + match(stream) { + case let s: *sdl3::AudioStream => + const samples = (s: *[*]i16)[0..additional_amount];//TODO verify this makes sense + for(let instance = 0; instance < POLYPHONY; instance+=1){ + running += audio_render(instance,samples); + }; + + case null => + return; + }; + // USED(u); + // SDL_memset(stream, 0, len); + // for(instance = 0; instance < POLYPHONY; instance++) + // running += audio_render(instance, samples, samples + len / 2); + // if(!running) + // SDL_PauseAudioDevice(audio_id, 1); +}; + +// static void +// audio_finished_handler(int instance) +// { +// SDL_Event event; +// event.type = audio0_event + instance; +// SDL_PushEvent(&event); +// } + +// static Sint32 +// envelope(UxnAudio *c, Uint32 age) +// { +// if(!c->r) return 0x0888; +// if(age < c->a) return 0x0888 * age / c->a; +// if(age < c->d) return 0x0444 * (2 * c->d - c->a - age) / (c->d - c->a); +// if(age < c->s) return 0x0444; +// if(age < c->r) return 0x0444 * (c->r - age) / (c->r - c->s); +// c->advance = 0; +// return 0x0000; +// } + + +// int +// audio_render(int instance, Sint16 *sample, Sint16 *end) +// { +// UxnAudio *c = &uxn_audio[instance]; +// Sint32 s; +// if(!c->advance || !c->period) return 0; +// while(sample < end) { +// c->count += c->advance; +// c->i += c->count / c->period; +// c->count %= c->period; +// if(c->i >= c->len) { +// if(!c->repeat) { +// c->advance = 0; +// break; +// } +// c->i %= c->len; +// } +// s = (Sint8)(c->addr[c->i] + 0x80) * envelope(c, c->age++); +// *sample++ += s * c->volume[0] / 0x180; +// *sample++ += s * c->volume[1] / 0x180; +// } +// if(!c->advance) audio_finished_handler(instance); +// return 1; +// } +fn audio_render(instance: int, samples: []i16) int = { + return 0; +}; + + +// static void +// audio_start(int instance, Uint8 *d) +// { +// UxnAudio *c = &uxn_audio[instance]; +// Uint8 pitch = d[0xf] & 0x7f; +// Uint16 addr = peek2(d + 0xc); +// Uint16 adsr = peek2(d + 0x8); +// c->len = peek2(d + 0xa); +// if(c->len > 0x10000 - addr) +// c->len = 0x10000 - addr; +// c->addr = &ram[addr]; +// c->volume[0] = d[0xe] >> 4; +// c->volume[1] = d[0xe] & 0xf; +// c->repeat = !(d[0xf] & 0x80); +// if(pitch < 108 && c->len) +// c->advance = advances[pitch % 12] >> (8 - pitch / 12); +// else { +// c->advance = 0; +// return; +// } +// c->a = ADSR_STEP * (adsr >> 12); +// c->d = ADSR_STEP * (adsr >> 8 & 0xf) + c->a; +// c->s = ADSR_STEP * (adsr >> 4 & 0xf) + c->d; +// c->r = ADSR_STEP * (adsr >> 0 & 0xf) + c->s; +// c->age = 0; +// c->i = 0; +// if(c->len <= 0x100) /* single cycle mode */ +// c->period = NOTE_PERIOD * 337 / 2 / c->len; +// else /* sample repeat mode */ +// c->period = NOTE_PERIOD; +// } + +// static void +// audio_play(int instance, Uint8 *d) +// { +// SDL_LockAudioDevice(audio_id); +// audio_start(instance, d); +// SDL_UnlockAudioDevice(audio_id); +// SDL_PauseAudioDevice(audio_id, 0); +// } + +// Uint8 +// audio_get_vu(int instance) +// { +// int i; +// UxnAudio *c = &uxn_audio[instance]; +// Sint32 sum[2] = {0, 0}; +// if(!c->advance || !c->period) return 0; +// for(i = 0; i < 2; i++) { +// if(!c->volume[i]) continue; +// sum[i] = 1 + envelope(c, c->age) * c->volume[i] / 0x800; +// if(sum[i] > 0xf) sum[i] = 0xf; +// } +// return (sum[0] << 4) | sum[1]; +// } + +// Uint16 +// audio_get_position(int instance) +// { +// return uxn_audio[instance].i; +// } + +fn audio_pitch(device: u8, state: *uxn) void = { + if(device > 3){ + fmt::fatal("Trying to use non-existant audio device!"); + }; + + return; +};