ampler/audio.c

153 lines
3.8 KiB
C

// audio.c
// TODO: add something to make sure, we KNOW if we've dropped audio
// eg. buffer has gone unfilled for a frame or more
void trigger_sounds(Ampler_state *state) {
// TODO: Check sound names
// TODO: func to decode orca numbers
// TODO: NOTE SPEED
foreach_ptr(Udp_msg, m, state -> messages)
if m -> state == MSG_TRIGGER do
foreach_ptr(Sound_src, s, state -> sounds)
if s -> state == SND_STOPPED do {
s -> state = SND_PLAYING;
s -> speed = 7.01f;
s -> pos = 0.0f;
break;
}
else if s -> state == SND_PLAYING do {
s -> speed = -1.51f;
break;
}
}
void sound_src_frame(Sound_src *s, s8 *mix[]) {
if s -> state == SND_LOOPING or s -> state == SND_PLAYING do
for int i = 0; i < FRAME_SAMPLES; i += 1 do {
for int c = 0; c < CHANNELS; c += 1 do
mix[c][i] += s -> tracks[c][(int) s -> pos];
s -> pos += s -> speed;
if s -> state == SND_LOOPING do {
while s -> pos < s -> start do
s -> pos += (s->end - s->start);
while s -> pos >= s -> end do
s -> pos -= (s->end - s->start);
}
// TODO: THIS WILL BREAK REVERSE SOUNDS
// FIXME: CHECK SIGN OF SPEED
if s -> state == SND_PLAYING do
if s->pos < s->start or s->pos >= s->end do {
s -> pos = s->start;
s -> state = SND_STOPPED;
}
}
}
int audio_frame(Ampler_state *state) {
int queued = SDL_GetQueuedAudioSize(state -> playdev);
queued /= sizeof s16; // queued is in bytes
if queued > FRAME_SAMPLES * CHANNELS * 2 do return 0;
// else puts("queued audio.");
trigger_sounds(state);
// TODO: We should use CHANNELS here
static s8 mix_l[FRAME_SAMPLES] = { 0 }, mix_r[FRAME_SAMPLES] = { 0 };
SDL_memset(mix_l, 0, sizeof mix_l);
SDL_memset(mix_r, 0, sizeof mix_r);
s8 *mix[] = { mix_l, mix_r };
foreach_ptr(Sound_src, snd, state -> sounds) //for int s = 0; s < arraylen(state -> sounds); s += 1 do
sound_src_frame(snd, mix); //sound_src_frame(&(state -> sounds[s]), mix);
const int vol = 100;
static s16 frame[FRAME_SAMPLES * CHANNELS] = { 0 };
for int i = 0; i < FRAME_SAMPLES; i += 1 do
for int t = 0; t < CHANNELS; t += 1 do
frame[i * CHANNELS + t] = ((s16) (mix[t][i])) * vol;
if SDL_QueueAudio(state -> playdev, frame, sizeof frame) do
puts(SDL_GetError());
return 1; // audio was qued
}
void load_track(Ampler_state *state) {
Sound_src *snd = NULL;
foreach_ptr(Sound_src, s, state -> sounds)
if s -> state == SND_FREE do {
snd = s;
break;
}
if snd == NULL do {
puts("error: all sound sources in use");
return;
}
SDL_AudioSpec spec;
s16 *buffer = NULL;
u32 bytes = 0;
SDL_LoadWAV("sample.wav", &spec, &buffer, &bytes);
if spec.format != AUDIO_S16 do {
puts("error: sample.wav is not s16");
return;
}
const int chans = spec.channels;
const int length = (bytes / sizeof s16) / chans;
snd -> track_len = length;
snd -> speed = 1.0f;
snd -> pos = 0.0f;
snd -> start = 0;
snd -> end = snd->track_len;
snd -> state = SND_STOPPED;
snd -> state = SND_LOOPING;
snd -> end /= 2;
snd -> start = snd -> end / 2;
for int i = 0; i < CHANNELS; i += 1 do
snd -> tracks[i] = malloc(snd -> track_len);
for int i = 0; i < CHANNELS; i += 1 do
if !(snd -> tracks[i]) do
puts("fffuuuck");
for int i = 0; i < snd -> track_len; i += 1 do
for int t = 0; t < chans; t += 1 do
snd -> tracks[t][i] = (s8) (buffer[i * chans + t] >> 8);
SDL_FreeWAV((void *) buffer);
printf("loaded sample.wav %f seconds.\n",
((f32) length) / ((f32) SAMPLE_RATE));
}
void load_track_f32() { // idk if we're ever gonna be loading floats
/*
f32 max = 0.0f;
for int i = 0; i < len; i++ do
if buffer[i] > max do
max = buffer[i];
else if buffer[i] < -max do
max = -buffer[i];
printf("%f max\n", max);
for int i = 0; i < len; i += 2 do {
buffer[i] /= max;
buffer[i + 1] /= max;
state -> track_l[i] = ((s8)(buffer[i] * 127.0f));
state -> track_r[i] = ((s8)(buffer[i + 1] * 127.0f));
}
*/
}