138 lines
3 KiB
C++
138 lines
3 KiB
C++
#include <psemek/audio/engine.hpp>
|
|
#include <psemek/audio/wave/silence.hpp>
|
|
#include <psemek/audio/wave/sine.hpp>
|
|
#include <psemek/audio/wave/sawtooth.hpp>
|
|
#include <psemek/audio/wave/square.hpp>
|
|
#include <psemek/audio/wave/triangle.hpp>
|
|
#include <psemek/audio/effect/volume.hpp>
|
|
#include <psemek/audio/effect/fade_in.hpp>
|
|
#include <psemek/audio/effect/fade_out.hpp>
|
|
#include <psemek/audio/effect/compressor.hpp>
|
|
#include <psemek/audio/duplicate.hpp>
|
|
#include <psemek/audio/stereo.hpp>
|
|
#include <psemek/audio/mixer.hpp>
|
|
#include <psemek/app/app.hpp>
|
|
#include <psemek/app/main.hpp>
|
|
#include <psemek/gfx/painter.hpp>
|
|
#include <psemek/util/clock.hpp>
|
|
#include <psemek/util/to_string.hpp>
|
|
#include <psemek/geom/constants.hpp>
|
|
#include <psemek/geom/camera.hpp>
|
|
|
|
#include <map>
|
|
|
|
using namespace psemek;
|
|
|
|
static std::map<SDL_Keycode, int> 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());
|
|
}
|
|
|
|
private:
|
|
audio::engine engine_;
|
|
audio::mixer_ptr mixer_;
|
|
std::shared_ptr<audio::volume_control_stereo> volume_control_;
|
|
std::map<SDL_Keycode, audio::channel_ptr> channels_;
|
|
|
|
util::clock<> clock_;
|
|
|
|
gfx::painter painter_;
|
|
};
|
|
|
|
int main()
|
|
{
|
|
return app::main<audio_app>();
|
|
}
|