5#ifndef OPENSHOT_CAPTURE_AUDIO_BUFFER_H
6#define OPENSHOT_CAPTURE_AUDIO_BUFFER_H
15#include <libavutil/mathematics.h>
23 void Reset(
int channels, int64_t capacity)
25 channel_count = channels;
26 max_samples = capacity;
29 timestamp_started =
false;
30 next_timestamp_sample = 0;
34 void Push(int64_t start, std::vector<std::vector<float>> samples)
36 if (samples.size() !=
static_cast<size_t>(channel_count) || samples.empty())
return;
37 const int64_t count = samples.front().size();
38 for (
const auto& channel : samples) {
39 if (channel.size() !=
static_cast<size_t>(count))
return;
41 if (!count || start + count <= position)
return;
44 const int64_t trim = std::max<int64_t>({0, position - start, count - max_samples});
45 for (
auto& channel : samples) channel.erase(channel.begin(), channel.begin() + trim);
47 queued_samples += count - trim;
48 const auto insertion = std::upper_bound(blocks.begin(), blocks.end(), start,
49 [](int64_t value,
const Block& block) { return value < block.start; });
50 blocks.insert(insertion, Block{start, std::move(samples)});
51 while (queued_samples > max_samples && !blocks.empty()) {
52 queued_samples -= blocks.front().samples.front().size();
57 void PushTimestamp(int64_t timestamp, int64_t epoch, AVRational time_base,
58 int sample_rate, std::vector<std::vector<float>> samples)
60 if (samples.empty() || samples.front().empty())
return;
61 int64_t start = av_rescale_q(timestamp - epoch, time_base, AVRational{1, sample_rate});
67 const int64_t tolerance = std::max(1, sample_rate / 1000);
68 if (timestamp_started && start >= next_timestamp_sample - tolerance
69 && start <= next_timestamp_sample + tolerance) {
70 start = next_timestamp_sample;
72 next_timestamp_sample = start +
static_cast<int64_t
>(samples.front().size());
73 timestamp_started =
true;
74 Push(start, std::move(samples));
79 return std::any_of(blocks.begin(), blocks.end(), [&](
const Block& block) {
80 return block.start + static_cast<int64_t>(block.samples.front().size()) >= position + count;
84 std::vector<std::vector<float>>
Read(
int count)
86 std::vector<std::vector<float>> result(channel_count, std::vector<float>(count, 0.0f));
87 const int64_t end = position + count;
88 for (
const auto& block : blocks) {
89 const int64_t first = std::max(position, block.start);
90 const int64_t last = std::min(end, block.start +
static_cast<int64_t
>(block.samples.front().size()));
91 if (last <= first)
continue;
92 for (
int channel = 0; channel < channel_count; ++channel) {
93 std::copy_n(block.samples[channel].begin() + (first - block.start), last - first,
94 result[channel].begin() + (first - position));
98 for (
auto it = blocks.begin(); it != blocks.end();) {
99 if (it->start +
static_cast<int64_t
>(it->samples.front().size()) <= position) {
100 queued_samples -= it->samples.front().size();
101 it = blocks.erase(it);
110 std::vector<std::vector<float>> samples;
112 std::deque<Block> blocks;
113 int channel_count = 0;
114 int64_t max_samples = 0;
115 int64_t position = 0;
116 int64_t queued_samples = 0;
117 bool timestamp_started =
false;
118 int64_t next_timestamp_sample = 0;
void Push(int64_t start, std::vector< std::vector< float > > samples)
bool Covers(int count) const
void Reset(int channels, int64_t capacity)
void PushTimestamp(int64_t timestamp, int64_t epoch, AVRational time_base, int sample_rate, std::vector< std::vector< float > > samples)
std::vector< std::vector< float > > Read(int count)
This namespace is the default namespace for all code in the openshot library.