#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace psemek; static std::map const key_to_midi { {SDLK_z, 59}, {SDLK_x, 60}, {SDLK_c, 61}, {SDLK_v, 62}, {SDLK_b, 63}, {SDLK_n, 64}, {SDLK_m, 65}, {SDLK_COMMA, 66}, {SDLK_PERIOD, 67}, {SDLK_SLASH, 68}, {SDLK_a, 69}, {SDLK_s, 70}, {SDLK_d, 71}, {SDLK_f, 72}, {SDLK_g, 73}, {SDLK_h, 74}, {SDLK_j, 75}, {SDLK_k, 76}, {SDLK_l, 77}, {SDLK_SEMICOLON, 78}, {SDLK_QUOTE, 79}, {SDLK_q, 80}, {SDLK_w, 81}, {SDLK_e, 82}, {SDLK_r, 83}, {SDLK_t, 84}, {SDLK_y, 85}, {SDLK_u, 86}, {SDLK_i, 87}, {SDLK_o, 88}, {SDLK_p, 89}, {SDLK_LEFTBRACKET, 90}, {SDLK_RIGHTBRACKET, 91}, }; struct audio_app : app::app { audio_app() : app::app("Audio example") { mixer_ = audio::make_mixer(); volume_control_ = audio::volume_stereo(mixer_, 0.5f, 0.5f, 0.1f); engine_.output()->stream(audio::compressor(volume_control_, audio::from_db(-2.f), 0.95f, 0.002f, 1.f, audio::from_db(1.f))); } void on_key_down(SDL_Keycode key) override { app::app::on_key_down(key); if (key_to_midi.contains(key) && !channels_.contains(key)) { int midi = key_to_midi.at(key); auto tone = audio::sine_wave(440.f * std::pow(2.f, (midi - 69) / 12.f)); channels_[key] = mixer_->add(audio::fade_in(tone, 0.01f)); } } void on_key_up(SDL_Keycode key) override { app::app::on_key_up(key); if (channels_.contains(key)) { auto & ch = channels_[key]; if (auto s = ch->stream()) ch->stream(audio::fade_out(s, 0.01f)); channels_.erase(key); } } void update() override { float const time = clock_.count(); float volume = std::sin(time); volume_control_->gain_left(0.5f + 0.5f * volume); volume_control_->gain_right(0.5f - 0.5f * volume); } void present() override { gl::ClearColor(0.8f, 0.8f, 1.f, 1.f); gl::Clear(gl::COLOR_BUFFER_BIT); { 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}; } painter_.render(geom::window_camera{width(), height()}.transform()); } void on_scene_exit() override { prof::dump(); } private: audio::engine engine_; audio::mixer_ptr mixer_; std::shared_ptr volume_control_; std::map channels_; util::clock<> clock_; gfx::painter painter_; }; int main() { return app::main(); }