1 /**
2  * @file
3  * @brief Source file for AudioResampler class
4  * @author Jonathan Thomas <jonathan@openshot.org>
5  *
6  * @ref License
7  */
8 
9 /* LICENSE
10  *
11  * Copyright (c) 2008-2019 OpenShot Studios, LLC
12  * <http://www.openshotstudios.com/>. This file is part of
13  * OpenShot Library (libopenshot), an open-source project dedicated to
14  * delivering high quality video editing and animation solutions to the
15  * world. For more information visit <http://www.openshot.org/>.
16  *
17  * OpenShot Library (libopenshot) is free software: you can redistribute it
18  * and/or modify it under the terms of the GNU Lesser General Public License
19  * as published by the Free Software Foundation, either version 3 of the
20  * License, or (at your option) any later version.
21  *
22  * OpenShot Library (libopenshot) is distributed in the hope that it will be
23  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25  * GNU Lesser General Public License for more details.
26  *
27  * You should have received a copy of the GNU Lesser General Public License
28  * along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
29  */
30 
31 #include "AudioResampler.h"
32 
33 using namespace std;
34 using namespace openshot;
35 
36 // Default constructor, max frames to cache is 20 // resample_source(NULL), buffer_source(NULL), num_of_samples(0), new_num_of_samples(0), dest_ratio(0), source_ratio(0), resampled_buffer(NULL), isPrepared(false)
AudioResampler()37 AudioResampler::AudioResampler()
38 {
39 	resample_source = NULL;
40 	buffer_source = NULL;
41 	num_of_samples = 0;
42 	new_num_of_samples = 0;
43 	dest_ratio = 0;
44 	source_ratio = 0;
45 	resampled_buffer = NULL;
46 	isPrepared = false;
47 
48 	// Init buffer source
49 	buffer_source = new AudioBufferSource(buffer);
50 
51 	// Init resampling source
52 	resample_source = new juce::ResamplingAudioSource(buffer_source, false, 2);
53 
54 	// Init resampled buffer
55 	resampled_buffer = new juce::AudioSampleBuffer(2, 1);
56 	resampled_buffer->clear();
57 
58 	// Init callback buffer
59 	resample_callback_buffer.buffer = resampled_buffer;
60 	resample_callback_buffer.numSamples = 1;
61 	resample_callback_buffer.startSample = 0;
62 }
63 
64 // Descructor
~AudioResampler()65 AudioResampler::~AudioResampler()
66 {
67 	// Clean up
68 	if (buffer_source)
69 		delete buffer_source;
70 	if (resample_source)
71 		delete resample_source;
72 	if (resampled_buffer)
73 		delete resampled_buffer;
74 }
75 
76 // Sets the audio buffer and updates the key settings
SetBuffer(juce::AudioSampleBuffer * new_buffer,double sample_rate,double new_sample_rate)77 void AudioResampler::SetBuffer(juce::AudioSampleBuffer *new_buffer, double sample_rate, double new_sample_rate)
78 {
79 	if (sample_rate <= 0)
80 		sample_rate = 44100;
81 	if (new_sample_rate <= 0)
82 		new_sample_rate = 44100;
83 
84 	// Set the sample ratio (the ratio of sample rate change)
85 	source_ratio = sample_rate / new_sample_rate;
86 
87 	// Call SetBuffer with ratio
88 	SetBuffer(new_buffer, source_ratio);
89 }
90 
91 // Sets the audio buffer and key settings
SetBuffer(juce::AudioSampleBuffer * new_buffer,double ratio)92 void AudioResampler::SetBuffer(juce::AudioSampleBuffer *new_buffer, double ratio)
93 {
94 	// Update buffer & buffer source
95 	buffer = new_buffer;
96 	buffer_source->setBuffer(buffer);
97 
98 	// Set the sample ratio (the ratio of sample rate change)
99 	source_ratio = ratio;
100 	dest_ratio = 1.0 / ratio;
101 	num_of_samples = buffer->getNumSamples();
102 	new_num_of_samples = round(num_of_samples * dest_ratio) - 1;
103 
104 	// Set resample ratio
105 	resample_source->setResamplingRatio(source_ratio);
106 
107 	// Prepare to play resample source
108 	if (!isPrepared)
109 	{
110 		// Prepare to play the audio sources (and set the # of samples per chunk to a little more than expected)
111 		resample_source->prepareToPlay(num_of_samples + 10, 0);
112 		isPrepared = true;
113 	}
114 
115 	// Resize buffer for the newly resampled data
116 	resampled_buffer->setSize(buffer->getNumChannels(), new_num_of_samples, true, true, true);
117 	resample_callback_buffer.numSamples = new_num_of_samples;
118 	resample_callback_buffer.startSample = 0;
119 	resample_callback_buffer.clearActiveBufferRegion();
120 }
121 
122 // Get the resampled audio buffer
GetResampledBuffer()123 juce::AudioSampleBuffer* AudioResampler::GetResampledBuffer()
124 {
125 	// Resample the current frame's audio buffer (into the temp callback buffer)
126 	resample_source->getNextAudioBlock(resample_callback_buffer);
127 
128 	// Return buffer pointer to this newly resampled buffer
129 	return resampled_buffer;
130 }
131