Audio: query actual frequency & channels, initialize effects based on that
This commit is contained in:
parent
3432b9b476
commit
ac8684faa3
4 changed files with 44 additions and 9 deletions
|
|
@ -11,6 +11,8 @@ namespace psemek::audio
|
||||||
{
|
{
|
||||||
virtual std::string_view name() const = 0;
|
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 void operator()(std::int16_t * data, std::size_t count) = 0;
|
||||||
|
|
||||||
virtual ~effect() {}
|
virtual ~effect() {}
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,12 @@ namespace psemek::audio
|
||||||
|
|
||||||
struct engine
|
struct engine
|
||||||
{
|
{
|
||||||
static const int frequency = 44100;
|
|
||||||
static const int channels = 2;
|
|
||||||
|
|
||||||
engine();
|
engine();
|
||||||
~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_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);
|
std::shared_ptr<track> load(char const * data, std::size_t size);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,13 @@ namespace psemek::audio
|
||||||
: audio::effect
|
: audio::effect
|
||||||
{
|
{
|
||||||
echo_impl(float delay, float volume)
|
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);
|
samples_.reserve(sample_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,6 +59,7 @@ namespace psemek::audio
|
||||||
private:
|
private:
|
||||||
std::vector<std::int16_t> samples_;
|
std::vector<std::int16_t> samples_;
|
||||||
std::size_t pos_ = 0;
|
std::size_t pos_ = 0;
|
||||||
|
float delay_;
|
||||||
float volume_;
|
float volume_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,12 @@ namespace psemek::audio
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct spec_t
|
||||||
|
{
|
||||||
|
int frequency = 44100;
|
||||||
|
int channels = 2;
|
||||||
|
};
|
||||||
|
|
||||||
struct track_impl
|
struct track_impl
|
||||||
: track
|
: track
|
||||||
{
|
{
|
||||||
|
|
@ -69,12 +75,15 @@ namespace psemek::audio
|
||||||
std::shared_ptr<track_impl> track;
|
std::shared_ptr<track_impl> track;
|
||||||
bool loop;
|
bool loop;
|
||||||
|
|
||||||
|
spec_t spec;
|
||||||
|
|
||||||
std::vector<std::shared_ptr<effect>> effects;
|
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)
|
: channel(channel)
|
||||||
, track(track)
|
, track(track)
|
||||||
, loop(loop)
|
, loop(loop)
|
||||||
|
, spec(spec)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void volume(float value)
|
void volume(float value)
|
||||||
|
|
@ -85,6 +94,7 @@ namespace psemek::audio
|
||||||
|
|
||||||
void push_effect(std::shared_ptr<effect> e) override
|
void push_effect(std::shared_ptr<effect> e) override
|
||||||
{
|
{
|
||||||
|
e->init(spec.frequency, spec.channels);
|
||||||
effects.push_back(e);
|
effects.push_back(e);
|
||||||
Mix_RegisterEffect(channel, &effect_func, nullptr, e.get());
|
Mix_RegisterEffect(channel, &effect_func, nullptr, e.get());
|
||||||
}
|
}
|
||||||
|
|
@ -143,6 +153,8 @@ namespace psemek::audio
|
||||||
std::shared_ptr<void> sdl_init;
|
std::shared_ptr<void> sdl_init;
|
||||||
sdl2_mixer_initializer mix_init;
|
sdl2_mixer_initializer mix_init;
|
||||||
|
|
||||||
|
spec_t spec;
|
||||||
|
|
||||||
struct channel
|
struct channel
|
||||||
{
|
{
|
||||||
std::shared_ptr<stream_impl> stream;
|
std::shared_ptr<stream_impl> stream;
|
||||||
|
|
@ -181,12 +193,18 @@ namespace psemek::audio
|
||||||
engine::impl::impl()
|
engine::impl::impl()
|
||||||
: sdl_init(sdl2::init(SDL_INIT_AUDIO))
|
: 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: ");
|
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);
|
Mix_ChannelFinished(&channel_finished);
|
||||||
|
|
||||||
log::info() << "Initialized audio";
|
log::info() << "Initialized audio: " << spec.channels << " channels, " << spec.frequency << " Hz";
|
||||||
}
|
}
|
||||||
|
|
||||||
engine::impl::~impl()
|
engine::impl::~impl()
|
||||||
|
|
@ -226,7 +244,7 @@ namespace psemek::audio
|
||||||
ch = c;
|
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;
|
channels[*ch].stream = str;
|
||||||
|
|
||||||
|
|
@ -253,6 +271,16 @@ namespace psemek::audio
|
||||||
engine::~engine()
|
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)
|
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));
|
return std::make_shared<track_impl>(Mix_LoadWAV_RW(SDL_RWFromConstMem(data, size), 1));
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue