93 lines
2 KiB
C++
93 lines
2 KiB
C++
#include <psemek/audio/recorder.hpp>
|
|
#include <psemek/util/exception.hpp>
|
|
|
|
#include <vector>
|
|
|
|
namespace psemek::audio
|
|
{
|
|
|
|
namespace
|
|
{
|
|
|
|
struct recorder_impl
|
|
: recorder
|
|
{
|
|
recorder_impl()
|
|
: channel_(std::make_shared<audio::channel>())
|
|
{}
|
|
|
|
channel_ptr channel() override
|
|
{
|
|
return channel_;
|
|
}
|
|
|
|
std::size_t request(std::size_t sample_count) override
|
|
{
|
|
std::size_t count = 0;
|
|
|
|
if (storage_.size() < samples_.size() + sample_count)
|
|
{
|
|
storage_.resize(std::max<std::size_t>(samples_.size() + sample_count, storage_.size() * 2));
|
|
samples_ = {storage_.data(), storage_.data() + samples_.size()};
|
|
}
|
|
|
|
if (auto stream = channel_->stream())
|
|
{
|
|
count = stream->read({storage_.data() + samples_.size(), sample_count});
|
|
if (count < sample_count)
|
|
channel_->stop();
|
|
}
|
|
|
|
std::fill(storage_.data() + samples_.size() + count, storage_.data() + samples_.size() + sample_count, 0.f);
|
|
samples_ = {storage_.data(), storage_.data() + samples_.size() + sample_count};
|
|
|
|
return sample_count;
|
|
}
|
|
|
|
util::span<float const> buffer() const override
|
|
{
|
|
return samples_;
|
|
}
|
|
|
|
std::vector<float> grab_buffer() override
|
|
{
|
|
storage_.resize(samples_.size());
|
|
samples_ = {};
|
|
return std::move(storage_);
|
|
}
|
|
|
|
private:
|
|
channel_ptr channel_;
|
|
std::vector<float> storage_;
|
|
util::span<float const> samples_;
|
|
};
|
|
|
|
}
|
|
|
|
std::shared_ptr<recorder> make_recorder()
|
|
{
|
|
return std::make_shared<recorder_impl>();
|
|
}
|
|
|
|
std::shared_ptr<recorder> make_recorder(stream_ptr stream)
|
|
{
|
|
auto recorder = make_recorder();
|
|
recorder->channel()->stream(std::move(stream));
|
|
return recorder;
|
|
}
|
|
|
|
std::shared_ptr<track> record(stream_ptr stream)
|
|
{
|
|
if (!stream->length())
|
|
throw util::exception("Cannot record an infinite stream");
|
|
return record(stream, *stream->length());
|
|
}
|
|
|
|
std::shared_ptr<track> record(stream_ptr stream, duration duration)
|
|
{
|
|
auto recorder = make_recorder(std::move(stream));
|
|
recorder->request(duration.samples());
|
|
return load_raw(recorder->grab_buffer());
|
|
}
|
|
|
|
}
|