Files
meadow/uxn/audio.ha
T
2026-07-07 17:44:14 -04:00

170 lines
4.3 KiB
Hare

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;
};