OpenShot Library | libopenshot  0.4.0
AudioWaveformer.cpp
Go to the documentation of this file.
1 
9 // Copyright (c) 2008-2022 OpenShot Studios, LLC
10 //
11 // SPDX-License-Identifier: LGPL-3.0-or-later
12 
13 #include "AudioWaveformer.h"
14 
15 
16 using namespace std;
17 using namespace openshot;
18 
19 
20 // Default constructor
21 AudioWaveformer::AudioWaveformer(ReaderBase* new_reader) : reader(new_reader)
22 {
23 
24 }
25 
26 // Destructor
28 {
29 
30 }
31 
32 // Extract audio samples from any ReaderBase class
33 AudioWaveformData AudioWaveformer::ExtractSamples(int channel, int num_per_second, bool normalize) {
34  AudioWaveformData data;
35 
36  if (reader) {
37  // Open reader (if needed)
38  bool does_reader_have_video = reader->info.has_video;
39  if (!reader->IsOpen()) {
40  reader->Open();
41  }
42  // Disable video for faster processing
43  reader->info.has_video = false;
44 
45  int sample_rate = reader->info.sample_rate;
46  int sample_divisor = sample_rate / num_per_second;
47  int total_samples = num_per_second * (reader->info.duration + 1.0);
48  int extracted_index = 0;
49 
50  // Force output to zero elements for non-audio readers
51  if (!reader->info.has_audio) {
52  total_samples = 0;
53  }
54 
55  // Resize and clear audio buffers
56  data.resize(total_samples);
57  data.zero(total_samples);
58 
59  // Bail out, if no samples needed
60  if (total_samples == 0 || reader->info.channels == 0) {
61  return data;
62  }
63 
64  // Loop through all frames
65  int sample_index = 0;
66  float samples_max = 0.0;
67  float chunk_max = 0.0;
68  float chunk_squared_sum = 0.0;
69 
70  // How many channels are we using
71  int channel_count = 1;
72  if (channel == -1) {
73  channel_count = reader->info.channels;
74  }
75 
76  for (auto f = 1; f <= reader->info.video_length; f++) {
77  // Get next frame
78  shared_ptr<openshot::Frame> frame = reader->GetFrame(f);
79 
80  // Cache channels for this frame, to reduce # of calls to frame->GetAudioSamples
81  float* channels[channel_count];
82  for (auto channel_index = 0; channel_index < reader->info.channels; channel_index++) {
83  if (channel == channel_index || channel == -1) {
84  channels[channel_index] = frame->GetAudioSamples(channel_index);
85  }
86  }
87 
88  // Get sample value from a specific channel (or all channels)
89  for (auto s = 0; s < frame->GetAudioSamplesCount(); s++) {
90  for (auto channel_index = 0; channel_index < reader->info.channels; channel_index++) {
91  if (channel == channel_index || channel == -1) {
92  float *samples = channels[channel_index];
93  float rms_sample_value = std::sqrt(samples[s] * samples[s]);
94 
95  // Accumulate sample averages
96  chunk_squared_sum += rms_sample_value;
97  chunk_max = std::max(chunk_max, rms_sample_value);
98  }
99  }
100 
101  sample_index += 1;
102 
103  // Cut-off reached
104  if (sample_index % sample_divisor == 0) {
105  float avg_squared_sum = chunk_squared_sum / (sample_divisor * channel_count);
106  data.max_samples[extracted_index] = chunk_max;
107  data.rms_samples[extracted_index] = avg_squared_sum;
108  extracted_index++;
109 
110  // Track max/min values
111  samples_max = std::max(samples_max, chunk_max);
112 
113  // reset sample total and index
114  sample_index = 0;
115  chunk_max = 0.0;
116  chunk_squared_sum = 0.0;
117  }
118  }
119  }
120 
121  // Scale all values to the -1 to +1 range (regardless of how small or how large the
122  // original audio sample values are)
123  if (normalize && samples_max > 0.0) {
124  float scale = 1.0f / samples_max;
125  data.scale(total_samples, scale);
126  }
127 
128  // Resume previous has_video value
129  reader->info.has_video = does_reader_have_video;
130  }
131 
132 
133  return data;
134 }
openshot::ReaderInfo::sample_rate
int sample_rate
The number of audio samples per second (44100 is a common sample rate)
Definition: ReaderBase.h:60
openshot::AudioWaveformer::~AudioWaveformer
~AudioWaveformer()
Destructor.
Definition: AudioWaveformer.cpp:27
openshot::AudioWaveformData::rms_samples
std::vector< float > rms_samples
Definition: AudioWaveformer.h:32
openshot::ReaderBase::GetFrame
virtual std::shared_ptr< openshot::Frame > GetFrame(int64_t number)=0
openshot::AudioWaveformData::resize
void resize(int total_samples)
Resize both datasets.
Definition: AudioWaveformer.h:35
openshot
This namespace is the default namespace for all code in the openshot library.
Definition: Compressor.h:28
openshot::ReaderBase::info
openshot::ReaderInfo info
Information about the current media file.
Definition: ReaderBase.h:88
openshot::AudioWaveformData::zero
void zero(int total_samples)
Zero out # of values in both datasets.
Definition: AudioWaveformer.h:41
openshot::AudioWaveformData::scale
void scale(int total_samples, float factor)
Scale # of values by some factor.
Definition: AudioWaveformer.h:47
openshot::ReaderInfo::duration
float duration
Length of time (in seconds)
Definition: ReaderBase.h:43
openshot::ReaderInfo::has_video
bool has_video
Determines if this file has a video stream.
Definition: ReaderBase.h:40
openshot::ReaderInfo::video_length
int64_t video_length
The number of frames in the video stream.
Definition: ReaderBase.h:53
openshot::ReaderBase::Open
virtual void Open()=0
Open the reader (and start consuming resources, such as images or video files)
openshot::AudioWaveformer::ExtractSamples
AudioWaveformData ExtractSamples(int channel, int num_per_second, bool normalize)
Extract audio samples from any ReaderBase class.
Definition: AudioWaveformer.cpp:33
openshot::ReaderInfo::has_audio
bool has_audio
Determines if this file has an audio stream.
Definition: ReaderBase.h:41
openshot::ReaderBase::IsOpen
virtual bool IsOpen()=0
Determine if reader is open or closed.
openshot::AudioWaveformData
This struct holds the extracted waveform data (both the RMS root-mean-squared average,...
Definition: AudioWaveformer.h:29
AudioWaveformer.h
Header file for AudioWaveformer class.
openshot::AudioWaveformData::max_samples
std::vector< float > max_samples
Definition: AudioWaveformer.h:31
openshot::ReaderBase
This abstract class is the base class, used by all readers in libopenshot.
Definition: ReaderBase.h:75
openshot::ReaderInfo::channels
int channels
The number of audio channels used in the audio stream.
Definition: ReaderBase.h:61