OpenShot Library | libopenshot  1.0.0
AudioRecorder.h
Go to the documentation of this file.
1 
9 // Copyright (c) 2008-2026 OpenShot Studios, LLC
10 //
11 // SPDX-License-Identifier: LGPL-3.0-or-later
12 
13 #ifndef OPENSHOT_AUDIORECORDER_H
14 #define OPENSHOT_AUDIORECORDER_H
15 
16 #include <atomic>
17 #include <condition_variable>
18 #include <cstdint>
19 #include <deque>
20 #include <functional>
21 #include <map>
22 #include <memory>
23 #include <mutex>
24 #include <string>
25 #include <thread>
26 #include <vector>
27 
28 #include <AppConfig.h>
29 #include <juce_audio_basics/juce_audio_basics.h>
30 #include <juce_audio_devices/juce_audio_devices.h>
31 
32 #include "AudioWaveformer.h"
33 #include "ChannelLayouts.h"
34 
35 namespace openshot
36 {
37  class FFmpegWriter;
38  class Frame;
39 
41  {
42  std::string path;
43  std::string device_name;
44  std::string device_type;
45  std::string codec = "pcm_s16le";
46  int sample_rate = 48000;
47  int channels = 1;
49  int bit_rate = 192000;
50  int buffer_size = 512;
53  std::map<std::string, std::string> options;
54  };
55 
57  {
58  double timestamp = 0.0;
59  std::vector<float> peak;
60  std::vector<float> rms;
61  bool clipped = false;
62 
63  std::vector<std::vector<float>> vectors() const
64  {
65  std::vector<std::vector<float>> output;
66  output.push_back(peak);
67  output.push_back(rms);
68  return output;
69  }
70  };
71 
73  {
74  double start_time = 0.0;
75  double duration = 0.0;
77  std::vector<float> max_samples;
78  std::vector<float> rms_samples;
79 
80  std::vector<std::vector<float>> vectors() const
81  {
82  std::vector<std::vector<float>> output;
83  output.push_back(max_samples);
84  output.push_back(rms_samples);
85  return output;
86  }
87  };
88 
90  {
91  bool is_open = false;
92  bool is_recording = false;
93  int sample_rate = 0;
94  int channels = 0;
95  int64_t samples_recorded = 0;
96  int64_t dropped_blocks = 0;
97  int64_t queued_blocks = 0;
98  double duration = 0.0;
99  };
100 
102  {
103  int sample_rate = 0;
104  int64_t first_sample = 0;
105  std::vector<std::vector<float>> channels;
106 
107  int Samples() const
108  {
109  return channels.empty() ? 0 : static_cast<int>(channels.front().size());
110  }
111  };
112 
114  {
115  public:
116  AudioLevelData ProcessBlock(const AudioRecorderBlock& block) const;
117  };
118 
120  {
121  public:
122  AudioRecorderWaveformAccumulator(int sample_rate, int samples_per_second);
123 
124  std::vector<AudioWaveformChunk> ProcessBlock(const AudioRecorderBlock& block);
126  void Reset();
127 
128  private:
129  int sample_rate;
130  int samples_per_second;
131  int sample_divisor;
132  int pending_samples;
133  float pending_max;
134  double pending_squared_sum;
135  int64_t emitted_visual_samples;
136  std::vector<float> max_samples;
137  std::vector<float> rms_samples;
138  };
139 
141  {
142  public:
143  static std::shared_ptr<openshot::Frame> CreateFrame(
144  const AudioRecorderBlock& block,
145  openshot::ChannelLayout channel_layout,
146  int64_t frame_number);
147  };
148 
150 #ifndef SWIG
151  : private juce::AudioIODeviceCallback
152 #endif
153  {
154  public:
155  explicit AudioRecorder(const AudioRecorderSettings& settings);
157 #ifndef SWIG
158  override
159 #endif
160  ;
161 
162  void Open();
163  void PrepareRecording();
164  void Start();
165  void Stop();
166  void StartMonitoring();
167  void StopMonitoring();
168  void Close();
169 
170  bool IsOpen() const;
171  bool IsRecording() const;
172  bool IsMonitoring() const;
176 
177 #ifndef SWIG
178  void SetLevelCallback(std::function<void(const AudioLevelData&)> callback);
179  void SetWaveformCallback(std::function<void(const AudioWaveformChunk&)> callback);
181  const float* const* inputChannelData,
182  int numInputChannels,
183  float* const* outputChannelData,
184  int numOutputChannels,
185  int numSamples,
186  const juce::AudioIODeviceCallbackContext& context) override;
187  void audioDeviceAboutToStart(juce::AudioIODevice* device) override;
188  void audioDeviceStopped() override;
189 #endif
190 
191  private:
192  void ValidateSettings() const;
193  void OpenWriter();
194  void WriterLoop();
195  bool PopBlock(AudioRecorderBlock& block);
196 
197  AudioRecorderSettings settings;
198  juce::AudioDeviceManager device_manager;
199  std::unique_ptr<openshot::FFmpegWriter> writer;
200  std::unique_ptr<AudioRecorderWaveformAccumulator> waveform_accumulator;
201  AudioRecorderLevelMeter level_meter;
202 
203  mutable std::mutex state_mutex;
204  mutable std::mutex queue_mutex;
205  std::condition_variable queue_condition;
206  std::deque<AudioRecorderBlock> queue;
207  std::thread writer_thread;
208 
209  std::function<void(const AudioLevelData&)> level_callback;
210  std::function<void(const AudioWaveformChunk&)> waveform_callback;
211  AudioLevelData last_level;
212 
213  std::atomic<bool> is_open;
214  std::atomic<bool> is_recording;
215  std::atomic<bool> is_monitoring;
216  std::atomic<bool> writer_should_stop;
217  std::atomic<int64_t> samples_recorded;
218  std::atomic<int64_t> dropped_blocks;
219  int64_t next_frame_number;
220  };
221 }
222 
223 #endif
Header file for AudioWaveformer class.
Header file for ChannelLayout class.
AudioLevelData ProcessBlock(const AudioRecorderBlock &block) const
AudioRecorderWaveformAccumulator(int sample_rate, int samples_per_second)
std::vector< AudioWaveformChunk > ProcessBlock(const AudioRecorderBlock &block)
openshot::AudioWaveformData Snapshot() const
AudioRecorder(const AudioRecorderSettings &settings)
void SetWaveformCallback(std::function< void(const AudioWaveformChunk &)> callback)
void SetLevelCallback(std::function< void(const AudioLevelData &)> callback)
AudioRecorderStats GetStats() const
void audioDeviceAboutToStart(juce::AudioIODevice *device) override
openshot::AudioWaveformData GetWaveformSnapshot() const
void audioDeviceStopped() override
AudioLevelData GetLevelSnapshot() const
void audioDeviceIOCallbackWithContext(const float *const *inputChannelData, int numInputChannels, float *const *outputChannelData, int numOutputChannels, int numSamples, const juce::AudioIODeviceCallbackContext &context) override
static std::shared_ptr< openshot::Frame > CreateFrame(const AudioRecorderBlock &block, openshot::ChannelLayout channel_layout, int64_t frame_number)
This namespace is the default namespace for all code in the openshot library.
Definition: AnimatedCurve.h:24
ChannelLayout
This enumeration determines the audio channel layout (such as stereo, mono, 5 point surround,...
std::vector< float > rms
Definition: AudioRecorder.h:60
std::vector< std::vector< float > > vectors() const
Definition: AudioRecorder.h:63
std::vector< float > peak
Definition: AudioRecorder.h:59
std::vector< std::vector< float > > channels
std::map< std::string, std::string > options
Definition: AudioRecorder.h:53
openshot::ChannelLayout channel_layout
Definition: AudioRecorder.h:48
std::vector< float > max_samples
Definition: AudioRecorder.h:77
std::vector< float > rms_samples
Definition: AudioRecorder.h:78
std::vector< std::vector< float > > vectors() const
Definition: AudioRecorder.h:80
This struct holds the extracted waveform data (both the RMS root-mean-squared average,...