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:
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;