Move loading raw & wav tracks from engine to free functions
This commit is contained in:
parent
5b0834f097
commit
3255aaf15d
5 changed files with 95 additions and 136 deletions
|
|
@ -21,9 +21,6 @@ namespace psemek::audio
|
|||
engine();
|
||||
~engine();
|
||||
|
||||
track_ptr load_raw(util::span<float const> data, bool copy = true);
|
||||
track_ptr load_wav(util::span<char const> data);
|
||||
|
||||
channel_ptr output();
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <psemek/audio/stream.hpp>
|
||||
#include <psemek/util/span.hpp>
|
||||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace psemek::audio
|
||||
{
|
||||
|
|
@ -17,4 +19,10 @@ namespace psemek::audio
|
|||
|
||||
using track_ptr = std::shared_ptr<track>;
|
||||
|
||||
track_ptr load_raw(util::span<float const> data);
|
||||
track_ptr load_raw(std::vector<float> data);
|
||||
|
||||
track_ptr load_wav(util::span<char const> data);
|
||||
track_ptr load_wav(std::vector<char> const & data);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,105 +17,6 @@
|
|||
namespace psemek::audio
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct track_data
|
||||
{
|
||||
util::span<float const> samples;
|
||||
std::vector<float> storage;
|
||||
};
|
||||
|
||||
struct track_stream_impl
|
||||
: stream
|
||||
{
|
||||
track_stream_impl(std::shared_ptr<track_data> data)
|
||||
: data_(std::move(data))
|
||||
{}
|
||||
|
||||
std::optional<std::size_t> length() const override
|
||||
{
|
||||
return data_->samples.size();
|
||||
}
|
||||
|
||||
std::size_t read(float * data, std::size_t sample_count) override
|
||||
{
|
||||
auto played = played_.load();
|
||||
|
||||
std::size_t result = std::min(sample_count, data_->samples.size() - played);
|
||||
std::copy(data_->samples.data() + played, data_->samples.data() + played + result, data);
|
||||
played_.fetch_add(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::size_t played() const override
|
||||
{
|
||||
return played_.load();
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<track_data> data_;
|
||||
std::atomic<std::size_t> played_{0};
|
||||
};
|
||||
|
||||
struct track_impl
|
||||
: track
|
||||
{
|
||||
track_impl(std::shared_ptr<track_data> data)
|
||||
: data_(std::move(data))
|
||||
{}
|
||||
|
||||
stream_ptr stream() const override
|
||||
{
|
||||
return std::make_shared<track_stream_impl>(data_);
|
||||
}
|
||||
|
||||
std::optional<std::size_t> length() const override
|
||||
{
|
||||
return data_->samples.size();
|
||||
}
|
||||
|
||||
private:
|
||||
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
|
||||
{
|
||||
std::shared_ptr<void> sdl_init;
|
||||
|
|
@ -191,40 +92,6 @@ namespace psemek::audio
|
|||
|
||||
engine::~engine() = default;
|
||||
|
||||
track_ptr engine::load_raw(util::span<float const> data, bool copy)
|
||||
{
|
||||
if ((data.size() % 2) != 0)
|
||||
throw std::runtime_error("bad sample count");
|
||||
|
||||
auto tdata = std::make_shared<track_data>();
|
||||
if (copy)
|
||||
{
|
||||
tdata->storage.assign(data.begin(), data.end());
|
||||
tdata->samples = tdata->storage;
|
||||
}
|
||||
else
|
||||
tdata->samples = data;
|
||||
|
||||
return std::make_shared<track_impl>(std::move(tdata));
|
||||
}
|
||||
|
||||
track_ptr engine::load_wav(util::span<char const> data)
|
||||
{
|
||||
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()
|
||||
{
|
||||
return impl().output;
|
||||
|
|
|
|||
17
libs/audio/source/track_raw.cpp
Normal file
17
libs/audio/source/track_raw.cpp
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#include <psemek/audio/track.hpp>
|
||||
#include <psemek/audio/duplicate.hpp>
|
||||
|
||||
namespace psemek::audio
|
||||
{
|
||||
|
||||
track_ptr load_raw(util::span<float const> data)
|
||||
{
|
||||
return make_duplicator(make_recorder(data));
|
||||
}
|
||||
|
||||
track_ptr load_raw(std::vector<float> data)
|
||||
{
|
||||
return make_duplicator(make_recorder(std::move(data)));
|
||||
}
|
||||
|
||||
}
|
||||
70
libs/audio/source/track_wav.cpp
Normal file
70
libs/audio/source/track_wav.cpp
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#include <psemek/audio/track.hpp>
|
||||
#include <psemek/audio/duplicate.hpp>
|
||||
#include <psemek/audio/constants.hpp>
|
||||
#include <psemek/util/to_string.hpp>
|
||||
#include <psemek/util/at_scope_exit.hpp>
|
||||
#include <psemek/sdl2/init.hpp>
|
||||
|
||||
#include <SDL2/SDL_audio.h>
|
||||
|
||||
namespace psemek::audio
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
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 != audio::frequency)
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
track_ptr load_wav(util::span<char const> data)
|
||||
{
|
||||
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); });
|
||||
return make_duplicator(make_recorder(convert_audio(spec, samples, length)));
|
||||
}
|
||||
|
||||
track_ptr load_wav(std::vector<char> const & data)
|
||||
{
|
||||
return load_wav(util::span<char const>(data));
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue