Audio: query actual frequency & channels, initialize effects based on that

This commit is contained in:
Nikita Lisitsa 2020-09-22 20:20:48 +03:00
parent 3432b9b476
commit ac8684faa3
4 changed files with 44 additions and 9 deletions

View file

@ -11,6 +11,8 @@ namespace psemek::audio
{
virtual std::string_view name() const = 0;
virtual void init(int frequency, int channels) = 0;
virtual void operator()(std::int16_t * data, std::size_t count) = 0;
virtual ~effect() {}

View file

@ -12,12 +12,12 @@ namespace psemek::audio
struct engine
{
static const int frequency = 44100;
static const int channels = 2;
engine();
~engine();
int frequency() const;
int channels() const;
std::shared_ptr<track> load_raw(std::int16_t const * data, std::size_t sample_count, bool copy = true);
std::shared_ptr<track> load(char const * data, std::size_t size);

View file

@ -15,9 +15,13 @@ namespace psemek::audio
: audio::effect
{
echo_impl(float delay, float volume)
: volume_(volume)
: delay_(delay)
, volume_(volume)
{}
void init(int frequency, int channels) override
{
int sample_count = std::round(delay * audio::engine::frequency * audio::engine::channels);
int sample_count = std::round(delay_ * frequency) * channels;
samples_.reserve(sample_count);
}
@ -55,6 +59,7 @@ namespace psemek::audio
private:
std::vector<std::int16_t> samples_;
std::size_t pos_ = 0;
float delay_;
float volume_;
};

View file

@ -35,6 +35,12 @@ namespace psemek::audio
}
};
struct spec_t
{
int frequency = 44100;
int channels = 2;
};
struct track_impl
: track
{
@ -69,12 +75,15 @@ namespace psemek::audio
std::shared_ptr<track_impl> track;
bool loop;
spec_t spec;
std::vector<std::shared_ptr<effect>> effects;
stream_impl(int channel, std::shared_ptr<track_impl> track, bool loop)
stream_impl(int channel, std::shared_ptr<track_impl> track, bool loop, spec_t spec)
: channel(channel)
, track(track)
, loop(loop)
, spec(spec)
{}
void volume(float value)
@ -85,6 +94,7 @@ namespace psemek::audio
void push_effect(std::shared_ptr<effect> e) override
{
e->init(spec.frequency, spec.channels);
effects.push_back(e);
Mix_RegisterEffect(channel, &effect_func, nullptr, e.get());
}
@ -143,6 +153,8 @@ namespace psemek::audio
std::shared_ptr<void> sdl_init;
sdl2_mixer_initializer mix_init;
spec_t spec;
struct channel
{
std::shared_ptr<stream_impl> stream;
@ -181,12 +193,18 @@ namespace psemek::audio
engine::impl::impl()
: sdl_init(sdl2::init(SDL_INIT_AUDIO))
{
if (Mix_OpenAudio(engine::frequency, AUDIO_S16SYS, engine::channels, 4096) != 0)
if (Mix_OpenAudio(spec.frequency, AUDIO_S16SYS, spec.channels, 4096) != 0)
mix_fail("Mix_OpenAudio: ");
Uint16 format;
Mix_QuerySpec(&spec.frequency, &format, &spec.channels);
if (format != AUDIO_S16SYS)
throw std::runtime_error("Failed to initialize audio with int16 samples");
Mix_ChannelFinished(&channel_finished);
log::info() << "Initialized audio";
log::info() << "Initialized audio: " << spec.channels << " channels, " << spec.frequency << " Hz";
}
engine::impl::~impl()
@ -226,7 +244,7 @@ namespace psemek::audio
ch = c;
}
auto str = std::make_shared<stream_impl>(*ch, std::move(ss), loop);
auto str = std::make_shared<stream_impl>(*ch, std::move(ss), loop, spec);
channels[*ch].stream = str;
@ -253,6 +271,16 @@ namespace psemek::audio
engine::~engine()
{}
int engine::frequency() const
{
return impl::instance()->spec.frequency;
}
int engine::channels() const
{
return impl::instance()->spec.channels;
}
std::shared_ptr<track> engine::load(char const * data, std::size_t size)
{
return std::make_shared<track_impl>(Mix_LoadWAV_RW(SDL_RWFromConstMem(data, size), 1));