OpenShot Library | libopenshot 0.3.3
Loading...
Searching...
No Matches
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
16using namespace std;
17using namespace openshot;
18
19
20// Default constructor
21AudioWaveformer::AudioWaveformer(ReaderBase* new_reader) : reader(new_reader)
22{
23
24}
25
26// Destructor
31
32// Extract audio samples from any ReaderBase class
33AudioWaveformData AudioWaveformer::ExtractSamples(int channel, int num_per_second, bool normalize) {
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}
Header file for AudioWaveformer class.
AudioWaveformer(ReaderBase *reader)
Default constructor.
AudioWaveformData ExtractSamples(int channel, int num_per_second, bool normalize)
Extract audio samples from any ReaderBase class.
This abstract class is the base class, used by all readers in libopenshot.
Definition ReaderBase.h:76
virtual bool IsOpen()=0
Determine if reader is open or closed.
openshot::ReaderInfo info
Information about the current media file.
Definition ReaderBase.h:88
virtual void Open()=0
Open the reader (and start consuming resources, such as images or video files)
virtual std::shared_ptr< openshot::Frame > GetFrame(int64_t number)=0
This namespace is the default namespace for all code in the openshot library.
Definition Compressor.h:29
This struct holds the extracted waveform data (both the RMS root-mean-squared average,...
void resize(int total_samples)
Resize both datasets.
std::vector< float > rms_samples
std::vector< float > max_samples
void zero(int total_samples)
Zero out # of values in both datasets.
void scale(int total_samples, float factor)
Scale # of values by some factor.
float duration
Length of time (in seconds)
Definition ReaderBase.h:43
int channels
The number of audio channels used in the audio stream.
Definition ReaderBase.h:61
int64_t video_length
The number of frames in the video stream.
Definition ReaderBase.h:53
bool has_video
Determines if this file has a video stream.
Definition ReaderBase.h:40
bool has_audio
Determines if this file has an audio stream.
Definition ReaderBase.h:41
int sample_rate
The number of audio samples per second (44100 is a common sample rate)
Definition ReaderBase.h:60