commit
2007fb7edc
200 files changed
+27710
No files matched your search
+170
@@ -0,0 +1,170 @@
|
||||
#include "audio.h"
|
||||
#include "common.h"
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include <stb_vorbis.c>
|
||||
|
||||
constexpr float PITCH_VARIANCE = 0.06f;
|
||||
constexpr Uint64 SOUND_GAP = 40 * SDL_NS_PER_MS;
|
||||
constexpr const char* SOUND_NAMES[SOUND_COUNT] = {
|
||||
"beam",
|
||||
"blast",
|
||||
"boomerang",
|
||||
"boomerang_heavy",
|
||||
"bounce",
|
||||
"bow",
|
||||
"bow_heavy",
|
||||
"break",
|
||||
"cast",
|
||||
"charge",
|
||||
"chat",
|
||||
"crawl",
|
||||
"dash",
|
||||
"death",
|
||||
"detonate",
|
||||
"detonate_empty",
|
||||
"duck",
|
||||
"echo",
|
||||
"equip",
|
||||
"explosion",
|
||||
"fall",
|
||||
"finish",
|
||||
"fireball",
|
||||
"flail",
|
||||
"flail_heavy",
|
||||
"flail_land",
|
||||
"flame",
|
||||
"grapple",
|
||||
"grapple_heavy",
|
||||
"hit_blunt",
|
||||
"hit_blunt_heavy",
|
||||
"hit_bullet",
|
||||
"hit_bullet_heavy",
|
||||
"hit_energy",
|
||||
"hit_energy_heavy",
|
||||
"hit_explosive",
|
||||
"hit_explosive_heavy",
|
||||
"hit_fire",
|
||||
"hit_fire_heavy",
|
||||
"hit_lash",
|
||||
"hit_lash_heavy",
|
||||
"hit_magic",
|
||||
"hit_magic_heavy",
|
||||
"hit_pierce",
|
||||
"hit_pierce_heavy",
|
||||
"hit_slash",
|
||||
"hit_slash_heavy",
|
||||
"impact_arrow",
|
||||
"impact_blaster",
|
||||
"impact_boomerang",
|
||||
"impact_bullet",
|
||||
"impact_mine",
|
||||
"jump",
|
||||
"land",
|
||||
"latch",
|
||||
"level_down",
|
||||
"level_up",
|
||||
"mine",
|
||||
"poke",
|
||||
"poke_heavy",
|
||||
"pound",
|
||||
"punch",
|
||||
"ready",
|
||||
"ricochet",
|
||||
"rocket",
|
||||
"rocket_heavy",
|
||||
"roll",
|
||||
"select",
|
||||
"shotgun",
|
||||
"shotgun_heavy",
|
||||
"slam",
|
||||
"slash",
|
||||
"slash_heavy",
|
||||
"step",
|
||||
"swap",
|
||||
"swing",
|
||||
"swing_heavy",
|
||||
"teleport",
|
||||
"teleport_warp",
|
||||
"unduck",
|
||||
"unequip",
|
||||
"uppercut",
|
||||
"uzi",
|
||||
"uzi_heavy",
|
||||
"whip",
|
||||
"whip_heavy",
|
||||
"wisp",
|
||||
"zap",
|
||||
};
|
||||
|
||||
void Audio::init()
|
||||
{
|
||||
if (SDL_InitSubSystem(SDL_INIT_AUDIO))
|
||||
device = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, nullptr);
|
||||
if (!device)
|
||||
{
|
||||
SDL_Log("Failed to open audio: %s", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < SOUND_COUNT; i++)
|
||||
{
|
||||
std::string path = path_get("sfx/") + SOUND_NAMES[i] + ".ogg";
|
||||
Sound& sound = sounds[i];
|
||||
sound.frames = stb_vorbis_decode_filename(path.c_str(), &sound.channels, &sound.rate, &sound.samples);
|
||||
if (sound.frames <= 0)
|
||||
SDL_Log("Failed to load %s", path.c_str());
|
||||
}
|
||||
|
||||
SDL_AudioSpec deviceSpec = {};
|
||||
SDL_GetAudioDeviceFormat(device, &deviceSpec, nullptr);
|
||||
for (SDL_AudioStream*& voice : voices)
|
||||
{
|
||||
voice = SDL_CreateAudioStream(&deviceSpec, &deviceSpec);
|
||||
SDL_BindAudioStream(device, voice);
|
||||
}
|
||||
}
|
||||
|
||||
// Plays a sound with a slight random pitch and returns the voice used, or -1 if it was skipped.
|
||||
int Audio::play(SoundId id)
|
||||
{
|
||||
if (id == SOUND_NONE)
|
||||
return -1;
|
||||
Sound& sound = sounds[id];
|
||||
Uint64 now = SDL_GetTicksNS();
|
||||
if (!device || sound.frames <= 0 || isMuted || now - sound.played < SOUND_GAP)
|
||||
return -1;
|
||||
sound.played = now;
|
||||
|
||||
int voice = voiceNext;
|
||||
for (int i = 0; i < VOICE_COUNT; i++)
|
||||
{
|
||||
if (SDL_GetAudioStreamQueued(voices[i]) == 0)
|
||||
{
|
||||
voice = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
voiceNext = (voice + 1) % VOICE_COUNT;
|
||||
|
||||
SDL_AudioStream* stream = voices[voice];
|
||||
SDL_AudioSpec spec = {SDL_AUDIO_S16, sound.channels, sound.rate};
|
||||
SDL_ClearAudioStream(stream);
|
||||
SDL_SetAudioStreamFormat(stream, &spec, nullptr);
|
||||
SDL_SetAudioStreamFrequencyRatio(stream, random_get(1 - PITCH_VARIANCE, 1 + PITCH_VARIANCE));
|
||||
SDL_PutAudioStreamData(stream, sound.samples, sound.frames * sound.channels * sizeof(short));
|
||||
return voice;
|
||||
}
|
||||
|
||||
// Sets the volume of everything played, from silent at 0 to full at 1.
|
||||
void Audio::gain_set(float gain)
|
||||
{
|
||||
if (device)
|
||||
SDL_SetAudioDeviceGain(device, gain);
|
||||
}
|
||||
|
||||
void Audio::stop(int voice)
|
||||
{
|
||||
if (voice >= 0)
|
||||
SDL_ClearAudioStream(voices[voice]);
|
||||
}
|
||||
Reference in new issue
Block a user