diff --git a/assets/saloon_outside.wav b/assets/saloon_outside.wav new file mode 100644 index 0000000..7648454 Binary files /dev/null and b/assets/saloon_outside.wav differ diff --git a/code/first.c b/code/first.c index 20adab5..aff318b 100644 --- a/code/first.c +++ b/code/first.c @@ -25,6 +25,8 @@ #include "game/impl/npc.c" #include "game/impl/bandit.c" + + int main(int argc, char **argv) { (void) argc; @@ -43,30 +45,6 @@ int main(int argc, char **argv) return 1; } - SDL_AudioStream *austream; - Str8 audio_data; - M_TempScope(0, 0) { - SDL_AudioSpec spec; - spec.format = SDL_AUDIO_S16LE; - spec.channels = 2; - spec.freq = 44100; - - austream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, 0, 0); - - if (!austream) { - printf("Failed to open audio stream (%s)\n", SDL_GetError()); - } - - Str8 exec = FS_SystemPath(temp.arena, FS_SYSTEM_PATH_EXE); - Str8 path = Sf(temp.arena, "%.*s/assets/outside_ambience.wav", Sv(exec)); - - SDL_AudioSpec wav_spec; - U32 count; - - SDL_LoadWAV((const char *) path.data, &wav_spec, &audio_data.data, &count); - audio_data.count = count; - } - Vk_Setup(window); G_State *game = 0; @@ -83,6 +61,13 @@ int main(int argc, char **argv) G_PipelinesLoad(game); G_AudioLoad(game); + Audio_Context *audio = M_ArenaPush(game->arena, Audio_Context); + Audio_Init(game->arena, audio, 0.15f); + + Audio_Play(audio, 1); + + SDL_ResumeAudioStreamDevice(audio->stream); + G_Camera *camera = &game->camera; camera->x = V3F(1, 0, 0); diff --git a/code/game/impl/bandit.c b/code/game/impl/bandit.c index d24f62c..02f4314 100644 --- a/code/game/impl/bandit.c +++ b/code/game/impl/bandit.c @@ -13,12 +13,10 @@ void UpdateBandit(F32 delta, Bandit *bandit, World *world) { if ( world->player.controls.shot && AABB_Slab(world->player.collision.pos, world->player.shotPos, bandit->collision) && bandit->currentArea == world->player.currentArea) { - printf("You shot the bandit %*.s\n", Sv(bandit->name)); bandit->health--; } if (AABB_Circle(bandit->agroRadius, AABB_Centre(bandit->collision), world->player.collision) && !(bandit->mode == BANDIT_SHOOTING || bandit->mode == BANDIT_SHOOTOUT)) { - printf("begin shootout"); // shootout time o.o bandit->mode = BANDIT_SHOOTOUT; } @@ -56,7 +54,7 @@ void UpdateBandit(F32 delta, Bandit *bandit, World *world) { bandit->collision.pos.y = cNav.pos.y * (1 - bandit->walkTimer/NPC_SPEED) + tNav.pos.y * bandit->walkTimer/NPC_SPEED; break; case BANDIT_SHOOTOUT: - bandit->shootoutTimer-=delta; + bandit->shootoutTimer-=delta; if(bandit->shootoutTimer < 0){ bandit->mode=BANDIT_SHOOTING; } @@ -66,17 +64,14 @@ void UpdateBandit(F32 delta, Bandit *bandit, World *world) { bandit->reloadTimer -= delta; if (bandit->shootCooldownTimer < 0 && bandit->reloadTimer < 0) { - printf("shoot at player"); bandit->bullets--; bandit->shootCooldownTimer = bandit->shootDelay; V2f banditShot = shootTowards(bandit, world->player.collision.pos, &world->random); if(AABB_Slab(bandit->collision.pos, banditShot, world->player.collision)){ // gets shot lmao - printf("hit"); world->player.health--; } if(bandit->bullets == 0){ - printf("enemy reload"); bandit->bullets = 6; bandit->reloadTimer = bandit->reloadTime; } diff --git a/code/game/impl/player.c b/code/game/impl/player.c index 4ebdfc3..678b2cc 100644 --- a/code/game/impl/player.c +++ b/code/game/impl/player.c @@ -128,7 +128,6 @@ void PlayerUpdate(F32 delta, Player *player) { player->controls.shot = false; V2f dir = V2F(0, 0); if(player->health == 0){ - printf("dead :("); player->health = 3; } if(player->controls.upDown) { diff --git a/code/os/audio.h b/code/os/audio.h new file mode 100644 index 0000000..a8b70e4 --- /dev/null +++ b/code/os/audio.h @@ -0,0 +1,39 @@ +#if !defined(LD_OS_AUDIO_H_) +#define LD_OS_AUDIO_H_ + +typedef struct Audio_Data Audio_Data; +struct Audio_Data { + S16 *samples; + U32 n_frames; +}; + +typedef struct Audio_Track Audio_Track; +struct Audio_Track { + B32 playing; + + Audio_Data *data; + + U32 n_played; + U32 next; // to play if playing, free otherwise +}; + +typedef struct Audio_Context Audio_Context; +struct Audio_Context { + SDL_AudioStream *stream; + + U32 n_tracks; + Audio_Track tracks[16]; + + U32 head; + U32 free; + + F32 volume; + + U32 n_sounds; + Audio_Data *sounds; +}; + +function void Audio_Init(M_Arena *arena, Audio_Context *audio, F32 volume); +function void Audio_Play(Audio_Context *audio, U32 index); + +#endif // LD_OS_AUDIO_H_ diff --git a/code/os/core.c b/code/os/core.c index dd739ff..324c21c 100644 --- a/code/os/core.c +++ b/code/os/core.c @@ -4,7 +4,6 @@ #include "impl/linux/core.c" #endif - Str8 FS_ReadEntireFile(M_Arena *arena, Str8 path) { Str8 result = { 0 }; @@ -19,3 +18,154 @@ Str8 FS_ReadEntireFile(M_Arena *arena, Str8 path) { return result; } + +internal void SDL_SubmitAudio(void *user, SDL_AudioStream *stream, int needed, int total) { + Audio_Context *audio = cast(Audio_Context *) user; + + (void) total; + + M_TempScope(0, 0) { + U32 prev = 0; + U32 it = audio->head; + + U32 n_samples = needed >> 1; + U32 n_frames = n_samples >> 1; + + F32 *left_f32 = M_ArenaPush(temp.arena, F32, .count = n_frames); + F32 *right_f32 = M_ArenaPush(temp.arena, F32, .count = n_frames); + + while (it != 0) { + Audio_Track *track = &audio->tracks[it]; + U32 next = track->next; + + F32 *l0 = left_f32; + F32 *r0 = right_f32; + + Assert(track->playing); + + U32 remain = track->data->n_frames - track->n_played; + U32 play = Min(n_frames, remain); + U32 off = track->n_played << 1; // played n frames, thus double to n samples + + for (U32 f = 0; f < play; ++f) { + *l0++ += cast(F32) (track->data->samples[off + (2 * f) + 0]) * audio->volume; + *r0++ += cast(F32) (track->data->samples[off + (2 * f) + 1]) * audio->volume; + } + + track->n_played += play; + + if (track->n_played == track->data->n_frames) { + if (prev == 0) { + // Head has finished playing + // + audio->head = track->next; + track->next = audio->free; + audio->free = it; + } + else { + // We're in the middle somewhere so prev->next == it->next + // + audio->tracks[prev].next = track->next; + track->next = audio->free; + audio->free = it; + } + + track->playing = false; + } + + it = next; + } + + F32 *l0 = left_f32; + F32 *r0 = right_f32; + + S16 *interleaved = M_ArenaPush(temp.arena, S16, .count = n_samples); + S16 *i0 = interleaved; + + for (U32 n = 0; n < n_frames; ++n) { + *i0++ = cast(S16) (l0[n] + 0.5f); + *i0++ = cast(S16) (r0[n] + 0.5f); + } + + SDL_PutAudioStreamData(stream, interleaved, needed); + } +} + +void Audio_Init(M_Arena *arena, Audio_Context *audio, F32 volume) { + SDL_AudioSpec spec = { 0 }; + spec.format = SDL_AUDIO_S16LE; + spec.channels = 2; + spec.freq = 44100; + + audio->stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, SDL_SubmitAudio, audio); + + if (audio->stream) { + M_TempScope(0, 0) { + Str8 exec = FS_SystemPath(temp.arena, FS_SYSTEM_PATH_EXE); + Str8 path = Sf(temp.arena, "%.*s/assets", Sv(exec)); + + FS_List files = FS_PathList(temp.arena, path); + + U32 n_audio = 0; + for (FS_Entry *it = files.first; it != 0; it = it->next) { + if (Str8_EndsWith(it->basename, S("wav"))) { + n_audio += 1; + } + } + + audio->n_sounds = 0; + audio->sounds = M_ArenaPush(arena, Audio_Data, .count = n_audio); + + for (FS_Entry *it = files.first; it != 0; it = it->next) { + if (Str8_EndsWith(it->basename, S("wav"))) { + Audio_Data *sound = &audio->sounds[audio->n_sounds]; + + U8 *data; + U32 count; + SDL_AudioSpec wav; + + SDL_LoadWAV((const char *) it->path.data, &wav, &data, &count); + + Assert(wav.freq == 44100); + + sound->samples = (S16 *) data; + sound->n_frames = (count >> 2); + + audio->n_sounds += 1; + } + } + + audio->n_tracks = 16; + //audio->tracks = M_ArenaPush(arena, Audio_Track, audio->n_tracks); + + for (U32 it = 1; it < audio->n_tracks; ++it) { + audio->tracks[it].next = it + 1; + } + + audio->tracks[audio->n_tracks - 1].next = 0; + + audio->volume = volume; + audio->head = 0; + audio->free = 1; + + printf("--- Loaded %d sounds ---\n", audio->n_sounds); + } + } +} + +void Audio_Play(Audio_Context *audio, U32 index) { + if (audio->free != 0 && SDL_LockAudioStream(audio->stream)) { + U32 idx = audio->free; + + Audio_Track *track = &audio->tracks[idx]; + audio->free = track->next; + + track->playing = true; + track->data = &audio->sounds[index]; + track->n_played = 0; + track->next = audio->head; + audio->head = idx; + + SDL_UnlockAudioStream(audio->stream); + } +} diff --git a/code/os/core.h b/code/os/core.h index efca174..dc34b5c 100644 --- a/code/os/core.h +++ b/code/os/core.h @@ -17,5 +17,6 @@ function void VM_Decommit(void *base, U64 size); function void VM_Release(void *base, U64 size); #include "filesystem.h" +#include "audio.h" #endif // LD_OS_CORE_H_