examples

Toy examples in single C files.
git clone git://henryandlizzy.uk/examples
Log | Files | Refs

commit 01a25f14bc50f21e384029650521babdce387a09
parent 14d3d89dd20b1ce52b9eb7b84584243e63f5e9a8
Author: Henry Wilson <henry@henryandlizzy.uk>
Date:   Sat, 23 Apr 2022 11:07:23 +0100

gl-asteroids: Add more sound types

Diffstat:
Msrc/gl-asteroids.cpp | 64++++++++++++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 52 insertions(+), 12 deletions(-)

diff --git a/src/gl-asteroids.cpp b/src/gl-asteroids.cpp @@ -11,9 +11,17 @@ #include <chrono> #include <optional> #include <functional> -#include <atomic> -std::atomic_flag beep; +using sample = std::span<short>; + +std::mutex queued_sounds_mutex; +std::vector<sample> queued_sounds; + +void play_sample(sample s) +{ + std::lock_guard lock(queued_sounds_mutex); + queued_sounds.push_back(s); +} void sound_routine(std::stop_token token) { @@ -22,18 +30,28 @@ void sound_routine(std::stop_token token) snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0); snd_pcm_set_params(handle, SND_PCM_FORMAT_S16, SND_PCM_ACCESS_RW_INTERLEAVED, 1, 48000, 1, 10000); + std::vector<sample> playing_sounds; + while (not token.stop_requested()) { + { + std::lock_guard lock(queued_sounds_mutex); + std::ranges::move(queued_sounds, back_inserter(playing_sounds)); + queued_sounds.clear(); + } + std::array<short, 2048> buf; - if (beep.test()) + for (auto& b : buf) { - beep.clear(); - for (unsigned i = 0; i < buf.size(); ++i) - buf[i] = (i % 256 - 128) * 50; + b = 0; + std::erase_if(playing_sounds, [](auto s){ return s.empty(); }); + for (auto& s : playing_sounds) + { + b += s[0]; + s = sample{s.data()+1, s.size()-1}; + } } - else - for (auto& s : buf) - s = 0; + snd_pcm_sframes_t frames = snd_pcm_writei(handle, buf.data(), buf.size()); } snd_pcm_drain(handle); @@ -344,6 +362,26 @@ int main(int argc, char* argv[]) std::uniform_int_distribution<int> dis_d(0,7); std::uniform_real_distribution<float> dis_a(-3,3); + std::array<short, 2 * 512> tone; + for (unsigned i = 0; i < tone.size(); ++i) + tone[i] = sin(i * 6.283 * 440 / 48000) * 50 * 128; + + std::array<short, 2 * 512> square; + for (unsigned i = 0; i < square.size(); ++i) + square[i] = (i & 0x80 - 0x40) * 50; + + std::array<short, 3 * 512> saw; + for (unsigned i = 0; i < saw.size(); ++i) + saw[i] = (i % 0x80 - 0x40) * 30; + + std::array<short, 8 * 512> blip; + for (unsigned i = 0; i < blip.size(); ++i) + blip[i] = sin(i * (i + 440) * 6.283 / 10 / 48000) * 50 * 128; + + std::array<short, 16 * 1024> bang; + for (unsigned i = 0; i < bang.size(); ++i) + bang[i] = 2048 * dis_p(gen) / exp(i * .00005) * (2 + cos(i * 6.283 * 15 / 48000)); + glfwInit(); w = glfwCreateWindow(926, 926, argv[0], NULL, NULL); @@ -432,7 +470,7 @@ int main(int argc, char* argv[]) if (is_pressed(GLFW_KEY_SPACE) && bullet_time < t && ammo) { - beep.test_and_set(); + play_sample(tone); --ammo; bullet_time = t + 1/firerate; @@ -486,7 +524,7 @@ int main(int argc, char* argv[]) { if (is_colliding(r->p, b->p)) { - beep.test_and_set(); + play_sample(square); for (unsigned j = 0; j < 7; ++j) { entity debris = *r; @@ -539,7 +577,7 @@ int main(int argc, char* argv[]) if (not is_colliding(b->p, powerups->p)) continue; - beep.test_and_set(); + play_sample(saw); for (unsigned j = 0; j < 4; ++j) { @@ -556,6 +594,7 @@ int main(int argc, char* argv[]) } if (is_colliding(s, powerups->p)) { + play_sample(blip); powerup_cb(); powerups.reset(); score += 10; @@ -564,6 +603,7 @@ int main(int argc, char* argv[]) if(any_of(rocks.begin(), rocks.end(), [](auto& r) { return is_colliding(s, r.p); })) { + play_sample(bang); using namespace std::chrono_literals; auto timeout = std::chrono::steady_clock::now() + 1s; score += t;