Support loading WAV audio
This commit is contained in:
parent
e7c999c3dd
commit
2c59879630
2 changed files with 56 additions and 7 deletions
|
|
@ -21,8 +21,8 @@ namespace psemek::audio
|
||||||
engine();
|
engine();
|
||||||
~engine();
|
~engine();
|
||||||
|
|
||||||
track_ptr load_raw(float const * data, std::size_t sample_count, bool copy = true);
|
|
||||||
track_ptr load_raw(util::span<float const> data, bool copy = true);
|
track_ptr load_raw(util::span<float const> data, bool copy = true);
|
||||||
|
track_ptr load_wav(util::span<char const> data);
|
||||||
|
|
||||||
channel_ptr output();
|
channel_ptr output();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
#include <psemek/sdl2/init.hpp>
|
#include <psemek/sdl2/init.hpp>
|
||||||
#include <psemek/log/log.hpp>
|
#include <psemek/log/log.hpp>
|
||||||
#include <psemek/prof/profiler.hpp>
|
#include <psemek/prof/profiler.hpp>
|
||||||
|
#include <psemek/util/at_scope_exit.hpp>
|
||||||
|
#include <psemek/util/to_string.hpp>
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
|
|
@ -77,6 +79,41 @@ namespace psemek::audio
|
||||||
std::shared_ptr<track_data> data_;
|
std::shared_ptr<track_data> data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::vector<float> convert_audio(SDL_AudioSpec const & spec, std::uint8_t * samples, std::size_t length)
|
||||||
|
{
|
||||||
|
if (spec.channels > 2)
|
||||||
|
throw std::runtime_error(util::to_string("Can't convert audio with ", static_cast<int>(spec.channels), " channels"));
|
||||||
|
|
||||||
|
if (spec.freq != 44100)
|
||||||
|
throw std::runtime_error(util::to_string("Can't convert audio with frequency ", spec.freq));
|
||||||
|
|
||||||
|
if (spec.format != AUDIO_S16SYS)
|
||||||
|
throw std::runtime_error(util::to_string("Can't convert audio with format ", spec.format));
|
||||||
|
|
||||||
|
auto p = reinterpret_cast<std::int16_t *>(samples);
|
||||||
|
|
||||||
|
std::vector<float> result;
|
||||||
|
|
||||||
|
if (spec.channels == 1)
|
||||||
|
{
|
||||||
|
result.resize(length);
|
||||||
|
for (std::size_t i = 0; i < length / 2; ++i)
|
||||||
|
{
|
||||||
|
float v = (p[i] * 2.f + 1.f) / 65536.f;
|
||||||
|
result[2 * i + 0] = v;
|
||||||
|
result[2 * i + 1] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.resize(length / 2);
|
||||||
|
for (std::size_t i = 0; i < length / 2; ++i)
|
||||||
|
result[i] = (p[i] * 2.f + 1.f) / 65536.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct engine::impl
|
struct engine::impl
|
||||||
|
|
@ -154,26 +191,38 @@ namespace psemek::audio
|
||||||
|
|
||||||
engine::~engine() = default;
|
engine::~engine() = default;
|
||||||
|
|
||||||
track_ptr engine::load_raw(float const * data, std::size_t sample_count, bool copy)
|
track_ptr engine::load_raw(util::span<float const> data, bool copy)
|
||||||
{
|
{
|
||||||
if ((sample_count % 2) != 0)
|
if ((data.size() % 2) != 0)
|
||||||
throw std::runtime_error("bad sample count");
|
throw std::runtime_error("bad sample count");
|
||||||
|
|
||||||
auto tdata = std::make_shared<track_data>();
|
auto tdata = std::make_shared<track_data>();
|
||||||
if (copy)
|
if (copy)
|
||||||
{
|
{
|
||||||
tdata->storage.assign(data, data + sample_count);
|
tdata->storage.assign(data.begin(), data.end());
|
||||||
tdata->samples = tdata->storage;
|
tdata->samples = tdata->storage;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tdata->samples = {data, data + sample_count};
|
tdata->samples = data;
|
||||||
|
|
||||||
return std::make_shared<track_impl>(std::move(tdata));
|
return std::make_shared<track_impl>(std::move(tdata));
|
||||||
}
|
}
|
||||||
|
|
||||||
track_ptr engine::load_raw(util::span<float const> data, bool copy)
|
track_ptr engine::load_wav(util::span<char const> data)
|
||||||
{
|
{
|
||||||
return load_raw(data.data(), data.size(), copy);
|
SDL_AudioSpec spec;
|
||||||
|
std::uint8_t * samples;
|
||||||
|
std::uint32_t length;
|
||||||
|
if (!SDL_LoadWAV_RW(SDL_RWFromConstMem(data.data(), data.size()), 1, &spec, &samples, &length))
|
||||||
|
sdl2::fail("SDL_LoadWAV_RW failed:");
|
||||||
|
|
||||||
|
util::at_scope_exit release_samples([samples]{ SDL_FreeWAV(samples); });
|
||||||
|
|
||||||
|
auto tdata = std::make_shared<track_data>();
|
||||||
|
tdata->storage = convert_audio(spec, samples, length);
|
||||||
|
tdata->samples = tdata->storage;
|
||||||
|
|
||||||
|
return std::make_shared<track_impl>(std::move(tdata));
|
||||||
}
|
}
|
||||||
|
|
||||||
channel_ptr engine::output()
|
channel_ptr engine::output()
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue