From 82607781cf7590d28f1d0f0ae750dbc62a7f89de Mon Sep 17 00:00:00 2001 From: lisyarus Date: Sun, 16 Oct 2022 00:22:18 +0300 Subject: [PATCH] Audio example tweaks --- examples/audio.cpp | 98 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 82 insertions(+), 16 deletions(-) diff --git a/examples/audio.cpp b/examples/audio.cpp index 9703f06f..884b0895 100644 --- a/examples/audio.cpp +++ b/examples/audio.cpp @@ -67,6 +67,16 @@ static std::map const key_to_midi {SDLK_RIGHTBRACKET, 91}, }; +static geom::interval const key_rows[3] = { + {59, 68}, + {69, 79}, + {80, 91}, +}; + +static std::string_view const midi_name[12] = { + "A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", +}; + struct audio_app : app::app { @@ -86,12 +96,15 @@ struct audio_app { app::app::on_key_down(key); - if (key_to_midi.contains(key) && !channels_.contains(key)) + if (key_to_midi.contains(key)) { int midi = key_to_midi.at(key); - auto tone = audio::karplus_strong(440.f * std::pow(2.f, (midi - 69) / 12.f)); - tone = audio::distortion(std::move(tone)); - channels_[key] = mixer_->add(audio::fade_in(tone, 0.002f)); + if (!channels_.contains(midi)) + { + auto tone = audio::karplus_strong(440.f * std::pow(2.f, (midi - 69) / 12.f)); + tone = audio::distortion(std::move(tone), 4.f); + channels_[midi] = mixer_->add(audio::fade_in(tone, 0.005f)); + } } if (key == SDLK_SPACE) @@ -110,12 +123,13 @@ struct audio_app { app::app::on_key_up(key); - if (channels_.contains(key)) + if (key_to_midi.contains(key)) { - auto & ch = channels_[key]; + int midi = key_to_midi.at(key); + auto & ch = channels_[midi]; if (auto s = ch->stream()) - ch->stream(audio::fade_out(s, 0.01f)); - channels_.erase(key); + ch->stream(audio::fade_out(s, 0.1f)); + channels_.erase(midi); } if (key == SDLK_KP_PLUS) @@ -127,9 +141,12 @@ struct audio_app void update() override { - float const time = clock_.count(); + float const dt = clock_.restart().count(); + time_ += dt; - float volume = std::sin(time); + smooth_pitch_ += (12.f * std::log2(pitch_control_->pitch()) - smooth_pitch_) * (1.f - std::exp(- 20.f * dt)); + + float volume = std::sin(time_); volume_control_->gain_left(0.5f + 0.5f * volume); volume_control_->gain_right(0.5f - 0.5f * volume); } @@ -139,12 +156,58 @@ struct audio_app gl::ClearColor(0.8f, 0.8f, 1.f, 1.f); gl::Clear(gl::COLOR_BUFFER_BIT); + float size = 64.f; + float margin = 4.f; + float border = 8.f; + + float center = width() / 2.f; + float y = height() / 2.f + size * std::size(key_rows) / 2.f; + + gfx::painter::text_options opts; + opts.scale = 2.f; + opts.c = {0, 0, 0, 255}; + opts.x = gfx::painter::x_align::center; + opts.y = gfx::painter::y_align::center; + + for (auto const & row : key_rows) { - gfx::painter::text_options opts; - opts.x = gfx::painter::x_align::left; - opts.y = gfx::painter::y_align::top; - opts.scale = 2.f; - opts.c = {0, 0, 0, 255}; + y -= size; + + float x = center - (row.max - row.min + 1) * size / 2.f; + + for (int i = 0; i <= row.max - row.min; ++i) + { + gfx::color_rgba color{0, 0, 0, 255}; + if (channels_.contains(row.min + i)) + color = {255, 127, 0, 255}; + painter_.rect({{{x + margin, x + size - margin}, {y + margin, y + size - margin}}}, color); + + color = {255, 255, 255, 255}; + painter_.rect({{{x + border, x + size - border}, {y + border, y + size - border}}}, color); + + painter_.text({x + size / 2.f, y + size / 2.f}, midi_name[(row.min + i + 3) % 12], opts); + + x += size; + } + } + + opts.scale = 4.f; + opts.c = pause_control_->paused() ? gfx::color_rgba{255, 0, 0, 255} : gfx::color_rgba{0, 127, 0, 255}; + painter_.text({width() / 2.f, height() - 200.f}, pause_control_->paused() ? "PAUSED" : "PLAYING", opts); + + { + float x = width() - 200.f; + float y = height() / 2.f; + + float w = 4.f; + float h = 64.f; + + float s = 16.f; + float r = y - h * smooth_pitch_; + + painter_.rect({{{x - w, x + w}, {y - h, y + h}}}, {0, 0, 0, 255}); + + painter_.rect({{{x - s, x + s}, {r - w, r + w}}}, {0, 0, 255, 255}); } painter_.render(geom::window_camera{width(), height()}.transform()); @@ -161,9 +224,12 @@ private: std::shared_ptr volume_control_; std::shared_ptr pitch_control_; std::shared_ptr pause_control_; - std::map channels_; + std::map channels_; + + float smooth_pitch_ = 0.f; util::clock<> clock_; + float time_ = 0.f; gfx::painter painter_; };