This repository has been archived by the owner on Oct 4, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
1,521 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
#pragma once | ||
|
||
#include <SDL2/SDL_audio.h> | ||
#include <libavutil/samplefmt.h> | ||
#include <stdbool.h> | ||
#include <stddef.h> | ||
#include <stdint.h> | ||
|
||
#define AUDIO_MAX_SAMPLES 1000 | ||
#define AUDIO_MAX_ACTIVE_SAMPLES 50 | ||
#define AUDIO_MAX_ACTIVE_STREAMS 10 | ||
#define AUDIO_NO_SOUND (-1) | ||
|
||
bool Audio_Init(void); | ||
bool Audio_Shutdown(void); | ||
|
||
bool Audio_Stream_Pause(int32_t sound_id); | ||
bool Audio_Stream_Unpause(int32_t sound_id); | ||
int32_t Audio_Stream_CreateFromFile(const char *path); | ||
bool Audio_Stream_Close(int32_t sound_id); | ||
bool Audio_Stream_IsLooped(int32_t sound_id); | ||
bool Audio_Stream_SetVolume(int32_t sound_id, float volume); | ||
bool Audio_Stream_SetIsLooped(int32_t sound_id, bool is_looped); | ||
bool Audio_Stream_SetFinishCallback( | ||
int32_t sound_id, void (*callback)(int32_t sound_id, void *user_data), | ||
void *user_data); | ||
double Audio_Stream_GetTimestamp(int32_t sound_id); | ||
double Audio_Stream_GetDuration(int32_t sound_id); | ||
bool Audio_Stream_SeekTimestamp(int32_t sound_id, double timestamp); | ||
bool Audio_Stream_SetStartTimestamp(int32_t sound_id, double timestamp); | ||
bool Audio_Stream_SetStopTimestamp(int32_t sound_id, double timestamp); | ||
|
||
bool Audio_Sample_ClearAll(void); | ||
bool Audio_Sample_Load(size_t count, const char **contents, size_t *sizes); | ||
|
||
int32_t Audio_Sample_Play( | ||
int32_t sample_id, int32_t volume, float pitch, int32_t pan, | ||
bool is_looped); | ||
bool Audio_Sample_IsPlaying(int32_t sound_id); | ||
bool Audio_Sample_Pause(int32_t sound_id); | ||
bool Audio_Sample_PauseAll(void); | ||
bool Audio_Sample_Unpause(int32_t sound_id); | ||
bool Audio_Sample_UnpauseAll(void); | ||
bool Audio_Sample_Close(int32_t sound_id); | ||
bool Audio_Sample_CloseAll(void); | ||
bool Audio_Sample_SetPan(int32_t sound_id, int32_t pan); | ||
bool Audio_Sample_SetVolume(int32_t sound_id, int32_t volume); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
#include "audio.h" | ||
|
||
#include "log.h" | ||
#include "memory.h" | ||
|
||
#include <SDL2/SDL.h> | ||
#include <SDL2/SDL_error.h> | ||
#include <SDL2/SDL_stdinc.h> | ||
#include <stdint.h> | ||
#include <string.h> | ||
|
||
SDL_AudioDeviceID g_AudioDeviceID = 0; | ||
static int32_t m_RefCount = 0; | ||
static size_t m_WorkingBufferSize = 0; | ||
static float *m_WorkingBuffer = NULL; | ||
static Uint8 m_WorkingSilence = 0; | ||
|
||
static void Audio_MixerCallback( | ||
void *userdata, Uint8 *stream_data, int32_t len); | ||
|
||
static void Audio_MixerCallback(void *userdata, Uint8 *stream_data, int32_t len) | ||
{ | ||
memset(m_WorkingBuffer, m_WorkingSilence, len); | ||
Audio_Stream_Mix(m_WorkingBuffer, len); | ||
Audio_Sample_Mix(m_WorkingBuffer, len); | ||
memcpy(stream_data, m_WorkingBuffer, len); | ||
} | ||
|
||
bool Audio_Init(void) | ||
{ | ||
m_RefCount++; | ||
if (g_AudioDeviceID) { | ||
// already initialized | ||
return true; | ||
} | ||
|
||
int32_t result = SDL_Init(SDL_INIT_AUDIO); | ||
if (result < 0) { | ||
LOG_ERROR("Error while calling SDL_Init: 0x%lx", result); | ||
return false; | ||
} | ||
|
||
Audio_Sample_Init(); | ||
Audio_Stream_Init(); | ||
|
||
SDL_AudioSpec desired; | ||
SDL_memset(&desired, 0, sizeof(desired)); | ||
desired.freq = AUDIO_WORKING_RATE; | ||
desired.format = AUDIO_WORKING_FORMAT; | ||
desired.channels = AUDIO_WORKING_CHANNELS; | ||
desired.samples = AUDIO_SAMPLES; | ||
desired.callback = Audio_MixerCallback; | ||
desired.userdata = NULL; | ||
|
||
SDL_AudioSpec delivered; | ||
g_AudioDeviceID = SDL_OpenAudioDevice(NULL, 0, &desired, &delivered, 0); | ||
|
||
if (!g_AudioDeviceID) { | ||
LOG_ERROR("Failed to open audio device: %s", SDL_GetError()); | ||
return false; | ||
} | ||
|
||
m_WorkingSilence = desired.silence; | ||
m_WorkingBufferSize = desired.samples * desired.channels | ||
* SDL_AUDIO_BITSIZE(desired.format) / 8; | ||
|
||
m_WorkingBuffer = Memory_Alloc(m_WorkingBufferSize); | ||
|
||
SDL_PauseAudioDevice(g_AudioDeviceID, 0); | ||
|
||
return true; | ||
} | ||
|
||
bool Audio_Shutdown(void) | ||
{ | ||
m_RefCount--; | ||
if (m_RefCount > 0) { | ||
return false; | ||
} | ||
|
||
Audio_Sample_Shutdown(); | ||
Audio_Stream_Shutdown(); | ||
|
||
if (g_AudioDeviceID) { | ||
SDL_PauseAudioDevice(g_AudioDeviceID, 1); | ||
SDL_CloseAudioDevice(g_AudioDeviceID); | ||
g_AudioDeviceID = 0; | ||
} | ||
|
||
Memory_FreePointer(&m_WorkingBuffer); | ||
return true; | ||
} | ||
|
||
int32_t Audio_GetAVAudioFormat(const int32_t sample_fmt) | ||
{ | ||
// clang-format off | ||
switch (sample_fmt) { | ||
case AUDIO_U8: return AV_SAMPLE_FMT_U8; | ||
case AUDIO_S16: return AV_SAMPLE_FMT_S16; | ||
case AUDIO_S32: return AV_SAMPLE_FMT_S32; | ||
case AUDIO_F32: return AV_SAMPLE_FMT_FLT; | ||
default: return -1; | ||
} | ||
// clang-format on | ||
} | ||
|
||
int32_t Audio_GetSDLAudioFormat(const enum AVSampleFormat sample_fmt) | ||
{ | ||
// clang-format off | ||
switch (sample_fmt) { | ||
case AV_SAMPLE_FMT_U8: return AUDIO_U8; | ||
case AV_SAMPLE_FMT_S16: return AUDIO_S16; | ||
case AV_SAMPLE_FMT_S32: return AUDIO_S32; | ||
case AV_SAMPLE_FMT_FLT: return AUDIO_F32; | ||
default: return -1; | ||
} | ||
// clang-format on | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#pragma once | ||
|
||
#include "engine/audio.h" | ||
|
||
#include <libavformat/avformat.h> | ||
#include <SDL2/SDL.h> | ||
|
||
#define AUDIO_WORKING_RATE 44100 | ||
#define AUDIO_WORKING_FORMAT AUDIO_F32 | ||
#define AUDIO_SAMPLES 500 | ||
#define AUDIO_WORKING_CHANNELS 2 | ||
|
||
extern SDL_AudioDeviceID g_AudioDeviceID; | ||
|
||
int32_t Audio_GetAVAudioFormat(const int32_t sample_fmt); | ||
int32_t Audio_GetSDLAudioFormat(const enum AVSampleFormat sample_fmt); | ||
|
||
void Audio_Sample_Init(void); | ||
void Audio_Sample_Shutdown(void); | ||
void Audio_Sample_Mix(float *dst_buffer, size_t len); | ||
|
||
void Audio_Stream_Init(void); | ||
void Audio_Stream_Shutdown(void); | ||
void Audio_Stream_Mix(float *dst_buffer, size_t len); |
Oops, something went wrong.