Added audio playback
Playing music
This commit is contained in:
BIN
assets/saloon_outside.wav
Normal file
BIN
assets/saloon_outside.wav
Normal file
Binary file not shown.
33
code/first.c
33
code/first.c
@@ -25,6 +25,8 @@
|
|||||||
#include "game/impl/npc.c"
|
#include "game/impl/npc.c"
|
||||||
#include "game/impl/bandit.c"
|
#include "game/impl/bandit.c"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
(void) argc;
|
(void) argc;
|
||||||
@@ -43,30 +45,6 @@ int main(int argc, char **argv)
|
|||||||
return 1;
|
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);
|
Vk_Setup(window);
|
||||||
|
|
||||||
G_State *game = 0;
|
G_State *game = 0;
|
||||||
@@ -83,6 +61,13 @@ int main(int argc, char **argv)
|
|||||||
G_PipelinesLoad(game);
|
G_PipelinesLoad(game);
|
||||||
G_AudioLoad(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;
|
G_Camera *camera = &game->camera;
|
||||||
|
|
||||||
camera->x = V3F(1, 0, 0);
|
camera->x = V3F(1, 0, 0);
|
||||||
|
|||||||
@@ -13,12 +13,10 @@ void UpdateBandit(F32 delta, Bandit *bandit, World *world) {
|
|||||||
if (
|
if (
|
||||||
world->player.controls.shot && AABB_Slab(world->player.collision.pos, world->player.shotPos, bandit->collision) && bandit->currentArea == world->player.currentArea)
|
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--;
|
bandit->health--;
|
||||||
}
|
}
|
||||||
if (AABB_Circle(bandit->agroRadius, AABB_Centre(bandit->collision), world->player.collision) && !(bandit->mode == BANDIT_SHOOTING || bandit->mode == BANDIT_SHOOTOUT))
|
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
|
// shootout time o.o
|
||||||
bandit->mode = BANDIT_SHOOTOUT;
|
bandit->mode = BANDIT_SHOOTOUT;
|
||||||
}
|
}
|
||||||
@@ -66,17 +64,14 @@ void UpdateBandit(F32 delta, Bandit *bandit, World *world) {
|
|||||||
bandit->reloadTimer -= delta;
|
bandit->reloadTimer -= delta;
|
||||||
if (bandit->shootCooldownTimer < 0 && bandit->reloadTimer < 0)
|
if (bandit->shootCooldownTimer < 0 && bandit->reloadTimer < 0)
|
||||||
{
|
{
|
||||||
printf("shoot at player");
|
|
||||||
bandit->bullets--;
|
bandit->bullets--;
|
||||||
bandit->shootCooldownTimer = bandit->shootDelay;
|
bandit->shootCooldownTimer = bandit->shootDelay;
|
||||||
V2f banditShot = shootTowards(bandit, world->player.collision.pos, &world->random);
|
V2f banditShot = shootTowards(bandit, world->player.collision.pos, &world->random);
|
||||||
if(AABB_Slab(bandit->collision.pos, banditShot, world->player.collision)){
|
if(AABB_Slab(bandit->collision.pos, banditShot, world->player.collision)){
|
||||||
// gets shot lmao
|
// gets shot lmao
|
||||||
printf("hit");
|
|
||||||
world->player.health--;
|
world->player.health--;
|
||||||
}
|
}
|
||||||
if(bandit->bullets == 0){
|
if(bandit->bullets == 0){
|
||||||
printf("enemy reload");
|
|
||||||
bandit->bullets = 6;
|
bandit->bullets = 6;
|
||||||
bandit->reloadTimer = bandit->reloadTime;
|
bandit->reloadTimer = bandit->reloadTime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,7 +128,6 @@ void PlayerUpdate(F32 delta, Player *player) {
|
|||||||
player->controls.shot = false;
|
player->controls.shot = false;
|
||||||
V2f dir = V2F(0, 0);
|
V2f dir = V2F(0, 0);
|
||||||
if(player->health == 0){
|
if(player->health == 0){
|
||||||
printf("dead :(");
|
|
||||||
player->health = 3;
|
player->health = 3;
|
||||||
}
|
}
|
||||||
if(player->controls.upDown) {
|
if(player->controls.upDown) {
|
||||||
|
|||||||
39
code/os/audio.h
Normal file
39
code/os/audio.h
Normal file
@@ -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_
|
||||||
152
code/os/core.c
152
code/os/core.c
@@ -4,7 +4,6 @@
|
|||||||
#include "impl/linux/core.c"
|
#include "impl/linux/core.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
Str8 FS_ReadEntireFile(M_Arena *arena, Str8 path) {
|
Str8 FS_ReadEntireFile(M_Arena *arena, Str8 path) {
|
||||||
Str8 result = { 0 };
|
Str8 result = { 0 };
|
||||||
|
|
||||||
@@ -19,3 +18,154 @@ Str8 FS_ReadEntireFile(M_Arena *arena, Str8 path) {
|
|||||||
|
|
||||||
return result;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,5 +17,6 @@ function void VM_Decommit(void *base, U64 size);
|
|||||||
function void VM_Release(void *base, U64 size);
|
function void VM_Release(void *base, U64 size);
|
||||||
|
|
||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
|
#include "audio.h"
|
||||||
|
|
||||||
#endif // LD_OS_CORE_H_
|
#endif // LD_OS_CORE_H_
|
||||||
|
|||||||
Reference in New Issue
Block a user