mirror of
https://github.com/NoelFB/blah.git
synced 2024-11-25 16:18:57 +08:00
Integrate cute_sound.h
This commit is contained in:
parent
20a6d9411d
commit
4cc0f8b608
|
@ -21,6 +21,7 @@ add_library(blah
|
||||||
src/blah_font.cpp
|
src/blah_font.cpp
|
||||||
src/blah_image.cpp
|
src/blah_image.cpp
|
||||||
src/blah_packer.cpp
|
src/blah_packer.cpp
|
||||||
|
src/blah_audio.cpp
|
||||||
src/internal/blah_renderer_opengl.cpp
|
src/internal/blah_renderer_opengl.cpp
|
||||||
src/internal/blah_renderer_d3d11.cpp
|
src/internal/blah_renderer_d3d11.cpp
|
||||||
src/internal/blah_platform_sdl2.cpp
|
src/internal/blah_platform_sdl2.cpp
|
||||||
|
|
|
@ -47,6 +47,9 @@ namespace Blah
|
||||||
// defaults to 60.
|
// defaults to 60.
|
||||||
int target_framerate = 60;
|
int target_framerate = 60;
|
||||||
|
|
||||||
|
// The expected freqeuncy of audio files and how quickly to play audio.
|
||||||
|
int audio_frequency_in_Hz = 44100;
|
||||||
|
|
||||||
// default starting flags
|
// default starting flags
|
||||||
u32 flags = Flags::VSync | Flags::Resizable | Flags::FixedTimestep;
|
u32 flags = Flags::VSync | Flags::Resizable | Flags::FixedTimestep;
|
||||||
|
|
||||||
|
|
139
include/blah_audio.h
Normal file
139
include/blah_audio.h
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <blah_common.h>
|
||||||
|
#include <blah_stream.h>
|
||||||
|
#include <blah_filesystem.h>
|
||||||
|
|
||||||
|
namespace Blah
|
||||||
|
{
|
||||||
|
class Audio;
|
||||||
|
class Sound;
|
||||||
|
using AudioRef = Ref<Audio>;
|
||||||
|
|
||||||
|
class Audio
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Load audio from a .wav file or .ogg file.
|
||||||
|
static AudioRef create(const FilePath& path);
|
||||||
|
|
||||||
|
// Load audio from a .ogg Stream.
|
||||||
|
static AudioRef create_from_ogg(Stream& stream);
|
||||||
|
|
||||||
|
// Load audio from a .wav Stream.
|
||||||
|
static AudioRef create_from_wav(Stream& stream);
|
||||||
|
|
||||||
|
~Audio();
|
||||||
|
inline void* get_backend_handle() { return m_ptr; }
|
||||||
|
u64 get_sample_count();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Audio(void* audio);
|
||||||
|
void* m_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set the global panning control for left/right stereo, from 0.0f (left) to 1.0f (right).
|
||||||
|
// 0.5f is the default for playing both speakers equal.
|
||||||
|
void set_global_pan(float pan);
|
||||||
|
|
||||||
|
// Set the global volume control for all audio, sounds + music included.
|
||||||
|
void set_global_volume(float volume);
|
||||||
|
|
||||||
|
// Set the global pause control for all audio, sounds + music included.
|
||||||
|
void set_global_pause(bool true_for_paused);
|
||||||
|
|
||||||
|
// Set the volume control for *just sounds*, not music.
|
||||||
|
void set_sound_volume(float volume);
|
||||||
|
|
||||||
|
// Set the volume control for *just music*, not sounds.
|
||||||
|
void set_music_volume(float volume);
|
||||||
|
|
||||||
|
namespace Music
|
||||||
|
{
|
||||||
|
// Play audio track using the music controls.
|
||||||
|
// Can optionally fade the volume in over a number of seconds.
|
||||||
|
void play(AudioRef audio, float fade_in_time = 0);
|
||||||
|
|
||||||
|
// Stop any music playing.
|
||||||
|
// Can optionally fade out the music volume over a number of seconds.
|
||||||
|
void stop(float fade_out_time = 0);
|
||||||
|
|
||||||
|
// Sets the volume for music.
|
||||||
|
void set_volume(float volume);
|
||||||
|
|
||||||
|
// Turns on or off whether or not to loop music.
|
||||||
|
void set_loop(bool true_to_loop);
|
||||||
|
|
||||||
|
// Pauses the music.
|
||||||
|
void pause();
|
||||||
|
|
||||||
|
// Resumes the music from a pause.
|
||||||
|
void resume();
|
||||||
|
|
||||||
|
// Switches to another audio track.
|
||||||
|
// Can optionally fade out over a number of seconds.
|
||||||
|
// Then can optinoally fade in the next track over a number of seconds.
|
||||||
|
void switch_to(AudioRef audio, float fade_out_time = 0, float fade_in_time = 0);
|
||||||
|
|
||||||
|
// Crossfades from the current music to another track over a number of seconds.
|
||||||
|
void crossfade(AudioRef audio, float cross_fade_time = 0);
|
||||||
|
|
||||||
|
// Get the index of the music sample currently playing.
|
||||||
|
u64 get_sample_index();
|
||||||
|
|
||||||
|
// Set the index for next sample of music to play.
|
||||||
|
// You can use this to manually sync to a specific part in the audio.
|
||||||
|
void set_sample_index(u64 sample_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SoundParams
|
||||||
|
{
|
||||||
|
bool paused = false;
|
||||||
|
bool looped = false;
|
||||||
|
float volume = 1.0f;
|
||||||
|
float pan = 0.5f; // 0 means left, 1 means right, 0.5f means balanced.
|
||||||
|
float delay = 0; // A number of seconds before playing the sound.
|
||||||
|
};
|
||||||
|
|
||||||
|
class Sound
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Play a sound, returns a new `Sound` instance.
|
||||||
|
// Returns a sound instance. The instance will destroy itself internally when
|
||||||
|
// it finishes playing, unless `looped` is set to true.
|
||||||
|
// Once destroyed other functions like `set_volume` will be ignored.
|
||||||
|
static Sound play(AudioRef audio, SoundParams params = SoundParams());
|
||||||
|
|
||||||
|
// Tells whether or not this sound instance is still alive.
|
||||||
|
bool is_active();
|
||||||
|
|
||||||
|
// Returns if this sound instance is alive and paused.
|
||||||
|
bool is_paused();
|
||||||
|
|
||||||
|
// Returns if this sound instance is alive and looped.
|
||||||
|
bool is_looped();
|
||||||
|
|
||||||
|
// Gets the volume of the sound instance.
|
||||||
|
float get_volume();
|
||||||
|
|
||||||
|
// Gets the sample index currently playing.
|
||||||
|
u64 get_sample_index();
|
||||||
|
|
||||||
|
// Pauses the sound.
|
||||||
|
void set_is_paused(bool true_for_paused);
|
||||||
|
|
||||||
|
// Sets whether or not this sound will continually playing.
|
||||||
|
void set_is_looped(bool true_for_looped);
|
||||||
|
|
||||||
|
// Sets the volume for this sound.
|
||||||
|
void set_volume(float volume);
|
||||||
|
|
||||||
|
// Sets the sample index for this sound to play next.
|
||||||
|
// You can use this to manually sync to a specific part in the audio.
|
||||||
|
void set_sample_index(u64 sample_index);
|
||||||
|
|
||||||
|
u64 id = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -20,6 +20,9 @@ Platform* App::Internal::platform = nullptr;
|
||||||
// Internal Renderer Pointer
|
// Internal Renderer Pointer
|
||||||
Renderer* App::Internal::renderer = nullptr;
|
Renderer* App::Internal::renderer = nullptr;
|
||||||
|
|
||||||
|
// Internal Audio bool
|
||||||
|
bool Audio::Internal::is_init = false;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
// Global App State
|
// Global App State
|
||||||
|
@ -112,6 +115,17 @@ bool App::run(const Config* c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initialize audio
|
||||||
|
{
|
||||||
|
if (!Audio::Internal::is_init) {
|
||||||
|
int more_on_emscripten = 1;
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
more_on_emscripten = 4;
|
||||||
|
#endif
|
||||||
|
Audio::Internal::is_init = Audio::Internal::init(NULL, c->audio_frequency_in_Hz, 1024 * more_on_emscripten);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// initialize graphics
|
// initialize graphics
|
||||||
{
|
{
|
||||||
Internal::renderer = Renderer::try_make_renderer(app_config.renderer_type);
|
Internal::renderer = Renderer::try_make_renderer(app_config.renderer_type);
|
||||||
|
@ -286,6 +300,9 @@ void App::Internal::shutdown()
|
||||||
delete platform;
|
delete platform;
|
||||||
platform = nullptr;
|
platform = nullptr;
|
||||||
|
|
||||||
|
Audio::Internal::shutdown();
|
||||||
|
Audio::Internal::is_init = false;
|
||||||
|
|
||||||
// clear static App state
|
// clear static App state
|
||||||
app_config = Config();
|
app_config = Config();
|
||||||
app_is_running = false;
|
app_is_running = false;
|
||||||
|
|
258
src/blah_audio.cpp
Normal file
258
src/blah_audio.cpp
Normal file
|
@ -0,0 +1,258 @@
|
||||||
|
#include "blah_audio.h"
|
||||||
|
|
||||||
|
#define STB_VORBIS_HEADER_ONLY
|
||||||
|
#include "third_party/stb_vorbis.c"
|
||||||
|
|
||||||
|
#define CUTE_SOUND_IMPLEMENTATION
|
||||||
|
#define CUTE_SOUND_FORCE_SDL
|
||||||
|
#include "third_party/cute_sound.h"
|
||||||
|
|
||||||
|
namespace Blah
|
||||||
|
{
|
||||||
|
namespace Internal
|
||||||
|
{
|
||||||
|
bool init(void* os_handle, unsigned play_frequency_in_Hz, int buffered_samples)
|
||||||
|
{
|
||||||
|
cs_error_t err = cs_init(os_handle, play_frequency_in_Hz, buffered_samples, NULL);
|
||||||
|
if (err != CUTE_SOUND_ERROR_NONE) {
|
||||||
|
Log::error(cs_error_as_string(err));
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void shutdown()
|
||||||
|
{
|
||||||
|
cs_shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Audio::Audio(void* audio)
|
||||||
|
{
|
||||||
|
m_ptr = audio;
|
||||||
|
}
|
||||||
|
|
||||||
|
Audio::~Audio()
|
||||||
|
{
|
||||||
|
cs_free_audio_source((cs_audio_source_t*)m_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 Audio::get_sample_count()
|
||||||
|
{
|
||||||
|
return m_ptr ? ((cs_audio_source_t*)m_ptr)->sample_count : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioRef Audio::create(const FilePath& path)
|
||||||
|
{
|
||||||
|
FileStream fs(path, FileMode::OpenRead);
|
||||||
|
if (!fs.is_readable())
|
||||||
|
return AudioRef();
|
||||||
|
|
||||||
|
if (path.ends_with(".ogg")) {
|
||||||
|
return create_from_ogg(fs);
|
||||||
|
} else if (path.ends_with(".wav")) {
|
||||||
|
return create_from_wav(fs);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::error("Unable to load unrecognized audio file type.");
|
||||||
|
return AudioRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioRef Audio::create_from_wav(Stream& stream)
|
||||||
|
{
|
||||||
|
if (!stream.is_readable())
|
||||||
|
{
|
||||||
|
Log::error("Unable to load audio as the Stream was not readable");
|
||||||
|
return AudioRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
// read into buffer
|
||||||
|
Vector<u8> buffer;
|
||||||
|
buffer.reserve((int)stream.length());
|
||||||
|
stream.read(buffer.data(), stream.length());
|
||||||
|
|
||||||
|
// load wav file from memory using cute_sound.h
|
||||||
|
cs_error_t err;
|
||||||
|
void* audio = cs_read_mem_wav((void*)buffer.data(), (size_t)buffer.size(), &err);
|
||||||
|
if (!audio) {
|
||||||
|
Log::error(cs_error_as_string(err));
|
||||||
|
return AudioRef();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return AudioRef(new Audio(audio));
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioRef Audio::create_from_ogg(Stream& stream)
|
||||||
|
{
|
||||||
|
if (!stream.is_readable())
|
||||||
|
{
|
||||||
|
Log::error("Unable to load audio as the Stream was not readable");
|
||||||
|
return AudioRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
// read into buffer
|
||||||
|
Vector<u8> buffer;
|
||||||
|
buffer.reserve((int)stream.length());
|
||||||
|
stream.read(buffer.data(), stream.length());
|
||||||
|
|
||||||
|
// load ogg file from memory using cute_sound.h
|
||||||
|
cs_error_t err;
|
||||||
|
void* audio = cs_read_mem_ogg((void*)buffer.data(), (size_t)buffer.size(), &err);
|
||||||
|
if (!audio) {
|
||||||
|
Log::error(cs_error_as_string(err));
|
||||||
|
return AudioRef();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return AudioRef(new Audio(audio));
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_global_pan(float pan)
|
||||||
|
{
|
||||||
|
cs_set_global_pan(pan);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_global_volume(float volume)
|
||||||
|
{
|
||||||
|
cs_set_global_volume(volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_global_pause(bool true_for_paused)
|
||||||
|
{
|
||||||
|
cs_set_global_pause(true_for_paused);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_sound_volume(float volume)
|
||||||
|
{
|
||||||
|
cs_set_playing_sounds_volume(volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_music_volume(float volume)
|
||||||
|
{
|
||||||
|
cs_music_set_volume(volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Music
|
||||||
|
{
|
||||||
|
void play(AudioRef audio, float fade_in_time)
|
||||||
|
{
|
||||||
|
cs_music_play((cs_audio_source_t*)audio->get_backend_handle(), fade_in_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop(float fade_out_time)
|
||||||
|
{
|
||||||
|
cs_music_stop(fade_out_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_volume(float volume)
|
||||||
|
{
|
||||||
|
cs_music_set_volume(volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_loop(bool true_to_loop)
|
||||||
|
{
|
||||||
|
cs_music_set_loop(true_to_loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pause()
|
||||||
|
{
|
||||||
|
cs_music_pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
void resume()
|
||||||
|
{
|
||||||
|
cs_music_resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
void switch_to(AudioRef audio, float fade_out_time, float fade_in_time)
|
||||||
|
{
|
||||||
|
cs_music_switch_to((cs_audio_source_t*)audio->get_backend_handle(), fade_out_time, fade_in_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void crossfade(AudioRef audio, float cross_fade_time)
|
||||||
|
{
|
||||||
|
cs_music_crossfade((cs_audio_source_t*)audio->get_backend_handle(), cross_fade_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 get_sample_index()
|
||||||
|
{
|
||||||
|
return cs_music_get_sample_index();
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_sample_index(u64 sample_index)
|
||||||
|
{
|
||||||
|
cs_music_set_sample_index(sample_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Sound Sound::play(AudioRef audio, SoundParams params)
|
||||||
|
{
|
||||||
|
cs_sound_params_t csparams;
|
||||||
|
csparams.paused = params.paused;
|
||||||
|
csparams.looped = params.looped;
|
||||||
|
csparams.volume = params.volume;
|
||||||
|
csparams.pan = params.pan;
|
||||||
|
csparams.delay = params.delay;
|
||||||
|
cs_playing_sound_t cssound = cs_play_sound((cs_audio_source_t*)audio->get_backend_handle(), csparams);
|
||||||
|
Sound sound;
|
||||||
|
sound.id = cssound.id;
|
||||||
|
return sound;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Sound::is_active()
|
||||||
|
{
|
||||||
|
cs_playing_sound_t cssound = { id };
|
||||||
|
return cs_sound_is_active(cssound);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Sound::is_paused()
|
||||||
|
{
|
||||||
|
cs_playing_sound_t cssound = { id };
|
||||||
|
return cs_sound_get_is_paused(cssound);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Sound::is_looped()
|
||||||
|
{
|
||||||
|
cs_playing_sound_t cssound = { id };
|
||||||
|
return cs_sound_get_is_looped(cssound);
|
||||||
|
}
|
||||||
|
|
||||||
|
float Sound::get_volume()
|
||||||
|
{
|
||||||
|
cs_playing_sound_t cssound = { id };
|
||||||
|
return cs_sound_get_volume(cssound);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 Sound::get_sample_index()
|
||||||
|
{
|
||||||
|
cs_playing_sound_t cssound = { id };
|
||||||
|
return cs_sound_get_sample_index(cssound);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sound::set_is_paused(bool true_for_paused)
|
||||||
|
{
|
||||||
|
cs_playing_sound_t cssound = { id };
|
||||||
|
cs_sound_set_is_paused(cssound, true_for_paused);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sound::set_is_looped(bool true_for_looped)
|
||||||
|
{
|
||||||
|
cs_playing_sound_t cssound = { id };
|
||||||
|
cs_sound_set_is_looped(cssound, true_for_looped);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sound::set_volume(float volume)
|
||||||
|
{
|
||||||
|
cs_playing_sound_t cssound = { id };
|
||||||
|
cs_sound_set_volume(cssound, volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sound::set_sample_index(u64 sample_index)
|
||||||
|
{
|
||||||
|
cs_playing_sound_t cssound = { id };
|
||||||
|
cs_sound_set_sample_index(cssound, sample_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef STB_VORBIS_HEADER_ONLY
|
||||||
|
#include "third_party/stb_vorbis.c"
|
|
@ -36,4 +36,18 @@ namespace Blah
|
||||||
void shutdown();
|
void shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Audio
|
||||||
|
{
|
||||||
|
namespace Internal
|
||||||
|
{
|
||||||
|
extern bool is_init;
|
||||||
|
|
||||||
|
// Pass in NULL for `os_handle`, except for the DirectSound backend this should be hwnd.
|
||||||
|
// play_frequency_in_Hz depends on your audio file, 44100 seems to be fine.
|
||||||
|
// buffered_samples is clamped to be at least 1024.
|
||||||
|
bool init(void* os_handle, unsigned play_frequency_in_Hz, int buffered_samples);
|
||||||
|
void shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
3169
src/third_party/cute_sound.h
vendored
Normal file
3169
src/third_party/cute_sound.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5397
src/third_party/stb_vorbis.c
vendored
Normal file
5397
src/third_party/stb_vorbis.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user