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