32 const int channels =
static_cast<int>(block.
channels.size());
33 result.
peak.assign(channels, 0.0f);
34 result.
rms.assign(channels, 0.0f);
36 for (
int channel = 0; channel < channels; ++channel) {
37 const auto& samples = block.
channels[channel];
38 double squared_sum = 0.0;
41 for (
float sample : samples) {
42 const float abs_sample = std::abs(sample);
43 peak = std::max(peak, abs_sample);
44 squared_sum +=
static_cast<double>(sample) *
static_cast<double>(sample);
45 if (abs_sample >= 1.0f) {
50 result.
peak[channel] = peak;
51 if (!samples.empty()) {
52 result.
rms[channel] =
static_cast<float>(std::sqrt(squared_sum /
static_cast<double>(samples.size())));
60 : sample_rate(new_sample_rate)
61 , samples_per_second(new_samples_per_second)
65 , pending_squared_sum(0.0)
66 , emitted_visual_samples(0)
68 if (sample_rate <= 0 || samples_per_second <= 0) {
69 throw InvalidOptions(
"Audio waveform settings require a valid sample rate and samples-per-second value.");
72 sample_divisor = std::max(1, sample_rate / samples_per_second);
77 std::vector<AudioWaveformChunk> chunks;
84 chunk.
start_time =
static_cast<double>(emitted_visual_samples) /
static_cast<double>(samples_per_second);
86 const int channels =
static_cast<int>(block.
channels.size());
87 const int samples = block.
Samples();
88 for (
int sample_index = 0; sample_index < samples; ++sample_index) {
89 for (
int channel = 0; channel < channels; ++channel) {
90 if (sample_index >=
static_cast<int>(block.
channels[channel].size())) {
93 const float sample = block.
channels[channel][sample_index];
94 pending_max = std::max(pending_max, std::abs(sample));
95 pending_squared_sum +=
static_cast<double>(sample) *
static_cast<double>(sample);
99 if (pending_samples >= sample_divisor) {
100 const double denominator =
static_cast<double>(pending_samples * channels);
101 const float rms = denominator > 0.0
102 ?
static_cast<float>(std::sqrt(pending_squared_sum / denominator))
105 max_samples.push_back(pending_max);
106 rms_samples.push_back(rms);
109 emitted_visual_samples++;
113 pending_squared_sum = 0.0;
118 chunk.
duration =
static_cast<double>(chunk.
max_samples.size()) /
static_cast<double>(samples_per_second);
119 chunks.push_back(std::move(chunk));
137 pending_squared_sum = 0.0;
138 emitted_visual_samples = 0;
146 int64_t frame_number)
148 const int channels =
static_cast<int>(block.
channels.size());
149 const int samples = block.
Samples();
150 auto frame = std::make_shared<Frame>(frame_number, samples, channels);
152 frame->ChannelsLayout(channel_layout);
154 for (
int channel = 0; channel < channels; ++channel) {
155 frame->AddAudio(
true, channel, 0, block.
channels[channel].data(), samples, 1.0f);
162 : settings(new_settings)
164 , waveform_accumulator(nullptr)
166 , is_recording(false)
167 , is_monitoring(false)
168 , writer_should_stop(false)
169 , samples_recorded(0)
171 , next_frame_number(1)
181 void AudioRecorder::ValidateSettings()
const
183 if (settings.
path.empty()) {
186 if (settings.
codec.empty()) {
190 throw InvalidSampleRate(
"Audio recorder requires a sample rate of at least 8000 Hz.", settings.
path);
193 throw InvalidChannels(
"Audio recorder requires at least one input channel.", settings.
path);
196 throw InvalidOptions(
"Audio recorder requires a positive audio buffer size.", settings.
path);
199 throw InvalidOptions(
"Audio recorder requires a positive waveform sample rate.", settings.
path);
202 throw InvalidOptions(
"Audio recorder requires a positive maximum queue duration.", settings.
path);
213 device_manager.setCurrentAudioDeviceType(settings.
device_type,
true);
216 juce::AudioDeviceManager::AudioDeviceSetup setup;
217 setup.inputChannels.clear();
218 for (
int channel = 0; channel < settings.
channels; ++channel) {
219 setup.inputChannels.setBit(channel);
221 setup.outputChannels.clear();
226 const juce::String error = device_manager.initialise(
233 if (error.isNotEmpty()) {
237 if (
auto* device = device_manager.getCurrentAudioDevice()) {
238 const double actual_rate = device->getCurrentSampleRate();
239 if (actual_rate > 0.0) {
240 settings.
sample_rate =
static_cast<int>(std::llround(actual_rate));
244 waveform_accumulator = std::make_unique<AudioRecorderWaveformAccumulator>(
251 void AudioRecorder::OpenWriter()
257 writer = std::make_unique<FFmpegWriter>(settings.
path);
270 writer_should_stop =
false;
272 device_manager.addAudioCallback(
this);
273 writer_thread = std::thread(&AudioRecorder::WriterLoop,
this);
283 if (waveform_accumulator) {
284 waveform_accumulator->Reset();
286 samples_recorded = 0;
288 next_frame_number = 1;
293 if (!is_recording && !writer_thread.joinable()) {
301 is_recording =
false;
302 device_manager.removeAudioCallback(
this);
303 writer_should_stop =
true;
304 queue_condition.notify_all();
306 if (writer_thread.joinable()) {
307 writer_thread.join();
318 if (is_recording || is_monitoring) {
326 is_monitoring =
true;
327 device_manager.addAudioCallback(
this);
332 if (!is_monitoring) {
336 is_monitoring =
false;
337 device_manager.removeAudioCallback(
this);
346 device_manager.closeAudioDevice();
367 return is_monitoring;
383 std::lock_guard<std::mutex> lock(queue_mutex);
390 std::lock_guard<std::mutex> lock(state_mutex);
391 return waveform_accumulator ? waveform_accumulator->Snapshot() :
AudioWaveformData();
396 std::lock_guard<std::mutex> lock(state_mutex);
402 std::lock_guard<std::mutex> lock(state_mutex);
403 level_callback = std::move(callback);
408 std::lock_guard<std::mutex> lock(state_mutex);
409 waveform_callback = std::move(callback);
413 const float*
const* inputChannelData,
414 int numInputChannels,
415 float*
const* outputChannelData,
416 int numOutputChannels,
418 const juce::AudioIODeviceCallbackContext&)
420 for (
int channel = 0; channel < numOutputChannels; ++channel) {
421 if (outputChannelData[channel]) {
422 std::fill(outputChannelData[channel], outputChannelData[channel] + numSamples, 0.0f);
426 if ((!is_recording && !is_monitoring) || numSamples <= 0) {
435 for (
int channel = 0; channel < settings.
channels; ++channel) {
436 block.
channels[channel].assign(numSamples, 0.0f);
437 if (channel < numInputChannels && inputChannelData[channel]) {
438 std::copy(inputChannelData[channel], inputChannelData[channel] + numSamples, block.
channels[channel].begin());
445 std::lock_guard<std::mutex> lock(state_mutex);
447 level_cb = level_callback;
454 samples_recorded += numSamples;
458 const int64_t max_queue_blocks =
static_cast<int64_t
>(
461 std::lock_guard<std::mutex> lock(queue_mutex);
462 if (
static_cast<int64_t
>(queue.size()) >= max_queue_blocks) {
465 queue.push_back(std::move(block));
466 queue_condition.notify_one();
470 samples_recorded += numSamples;
484 std::unique_lock<std::mutex> lock(queue_mutex);
485 queue_condition.wait(lock, [
this]() {
486 return writer_should_stop || !queue.empty();
493 block = std::move(queue.front());
498 void AudioRecorder::WriterLoop()
500 int64_t expected_next_sample = -1;
503 if (!PopBlock(block)) {
504 if (writer_should_stop) {
510 std::vector<AudioWaveformChunk> waveform_chunks;
513 std::lock_guard<std::mutex> lock(state_mutex);
514 if (waveform_accumulator) {
515 waveform_chunks = waveform_accumulator->ProcessBlock(block);
517 waveform_cb = waveform_callback;
521 for (
const auto& chunk : waveform_chunks) {
527 while (expected_next_sample >= 0 && block.
first_sample > expected_next_sample) {
528 const int64_t missing_samples = block.
first_sample - expected_next_sample;
529 const int silence_samples =
static_cast<int>(std::min<int64_t>(
537 std::vector<float>(silence_samples, 0.0f));
541 next_frame_number++));
542 expected_next_sample += silence_samples;
548 next_frame_number++));