1 /**
2  * @file
3  * @brief Source file for AudioReaderSource 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 "AudioReaderSource.h"
32 #include "Exceptions.h"
33 
34 using namespace std;
35 using namespace openshot;
36 
37 // Constructor that reads samples from a reader
AudioReaderSource(ReaderBase * audio_reader,int64_t starting_frame_number,int buffer_size)38 AudioReaderSource::AudioReaderSource(ReaderBase *audio_reader, int64_t starting_frame_number, int buffer_size)
39 	: reader(audio_reader), frame_number(starting_frame_number),
40 	  size(buffer_size), position(0), frame_position(0), estimated_frame(0), speed(1) {
41 
42 	// Initialize an audio buffer (based on reader)
43 	buffer = new juce::AudioSampleBuffer(reader->info.channels, size);
44 
45 	// initialize the audio samples to zero (silence)
46 	buffer->clear();
47 }
48 
49 // Destructor
~AudioReaderSource()50 AudioReaderSource::~AudioReaderSource()
51 {
52 	// Clear and delete the buffer
53 	delete buffer;
54 	buffer = NULL;
55 }
56 
57 // Get more samples from the reader
GetMoreSamplesFromReader()58 void AudioReaderSource::GetMoreSamplesFromReader()
59 {
60 	// Determine the amount of samples needed to fill up this buffer
61 	int amount_needed = position; // replace these used samples
62 	int amount_remaining = size - amount_needed; // these are unused samples, and need to be carried forward
63 	if (!frame) {
64 		// If no frame, load entire buffer
65 		amount_needed = size;
66 		amount_remaining = 0;
67 	}
68 
69 	// Debug
70 	ZmqLogger::Instance()->AppendDebugMethod("AudioReaderSource::GetMoreSamplesFromReader", "amount_needed", amount_needed, "amount_remaining", amount_remaining);
71 
72 	// Init estimated buffer equal to the current frame position (before getting more samples)
73 	estimated_frame = frame_number;
74 
75 	// Init new buffer
76 	juce::AudioSampleBuffer *new_buffer = new juce::AudioSampleBuffer(reader->info.channels, size);
77 	new_buffer->clear();
78 
79 	// Move the remaining samples into new buffer (if any)
80 	if (amount_remaining > 0) {
81 		for (int channel = 0; channel < buffer->getNumChannels(); channel++)
82 		    new_buffer->addFrom(channel, 0, *buffer, channel, position, amount_remaining);
83 
84 		position = amount_remaining;
85 	} else
86 		// reset position to 0
87 		position = 0;
88 
89 	// Loop through frames until buffer filled
90 	while (amount_needed > 0 && speed == 1  && frame_number >= 1 && frame_number <= reader->info.video_length) {
91 
92 		// Get the next frame (if position is zero)
93 		if (frame_position == 0) {
94 			try {
95 				// Get frame object
96 				frame = reader->GetFrame(frame_number);
97 				frame_number = frame_number + speed;
98 
99 			} catch (const ReaderClosed & e) {
100 			break;
101 			} catch (const OutOfBoundsFrame & e) {
102 			break;
103 			}
104 		}
105 
106 		bool frame_completed = false;
107 		int amount_to_copy = 0;
108 		if (frame)
109 			amount_to_copy = frame->GetAudioSamplesCount() - frame_position;
110 		if (amount_to_copy > amount_needed) {
111 			// Don't copy too many samples (we don't want to overflow the buffer)
112 			amount_to_copy = amount_needed;
113 			amount_needed = 0;
114 		} else {
115 			// Not enough to fill the buffer (so use the entire frame)
116 			amount_needed -= amount_to_copy;
117 			frame_completed = true;
118 		}
119 
120 		// Load all of its samples into the buffer
121 		if (frame)
122 			for (int channel = 0; channel < new_buffer->getNumChannels(); channel++)
123 				new_buffer->addFrom(channel, position, *frame->GetAudioSampleBuffer(), channel, frame_position, amount_to_copy);
124 
125 		// Adjust remaining samples
126 		position += amount_to_copy;
127 		if (frame_completed)
128 			// Reset frame buffer position (which will load a new frame on the next loop)
129 			frame_position = 0;
130 		else
131 			// Continue tracking the current frame's position
132 			frame_position += amount_to_copy;
133 	}
134 
135 	// Delete old buffer
136 	buffer->clear();
137 	delete buffer;
138 
139 	// Replace buffer and reset position
140 	buffer = new_buffer;
141 	position = 0;
142 }
143 
144 // Reverse an audio buffer
reverse_buffer(juce::AudioSampleBuffer * buffer)145 juce::AudioSampleBuffer* AudioReaderSource::reverse_buffer(juce::AudioSampleBuffer* buffer)
146 {
147 	int number_of_samples = buffer->getNumSamples();
148 	int channels = buffer->getNumChannels();
149 
150 	// Debug
151 	ZmqLogger::Instance()->AppendDebugMethod("AudioReaderSource::reverse_buffer", "number_of_samples", number_of_samples, "channels", channels);
152 
153 	// Reverse array (create new buffer to hold the reversed version)
154 	juce::AudioSampleBuffer *reversed = new juce::AudioSampleBuffer(channels, number_of_samples);
155 	reversed->clear();
156 
157 	for (int channel = 0; channel < channels; channel++)
158 	{
159 		int n=0;
160 		for (int s = number_of_samples - 1; s >= 0; s--, n++)
161 			reversed->getWritePointer(channel)[n] = buffer->getWritePointer(channel)[s];
162 	}
163 
164 	// Copy the samples back to the original array
165 	buffer->clear();
166 	// Loop through channels, and get audio samples
167 	for (int channel = 0; channel < channels; channel++)
168 		// Get the audio samples for this channel
169 		buffer->addFrom(channel, 0, reversed->getReadPointer(channel), number_of_samples, 1.0f);
170 
171 	delete reversed;
172 	reversed = NULL;
173 
174 	// return pointer or passed in object (so this method can be chained together)
175 	return buffer;
176 }
177 
178 // Get the next block of audio samples
getNextAudioBlock(const juce::AudioSourceChannelInfo & info)179 void AudioReaderSource::getNextAudioBlock(const juce::AudioSourceChannelInfo& info)
180 {
181 	int buffer_samples = buffer->getNumSamples();
182 	int buffer_channels = buffer->getNumChannels();
183 
184 	if (info.numSamples > 0) {
185 		int number_to_copy = 0;
186 
187 		// Do we need more samples?
188 		if (speed == 1) {
189 			// Only refill buffers if speed is normal
190 			if ((reader && reader->IsOpen() && !frame) or
191 				(reader && reader->IsOpen() && buffer_samples - position < info.numSamples))
192 				// Refill buffer from reader
193 				GetMoreSamplesFromReader();
194 		} else {
195 			// Fill buffer with silence and clear current frame
196 			info.buffer->clear();
197 			return;
198 		}
199 
200 		// Determine how many samples to copy
201 		if (position + info.numSamples <= buffer_samples)
202 		{
203 			// copy the full amount requested
204 			number_to_copy = info.numSamples;
205 		}
206 		else if (position > buffer_samples)
207 		{
208 			// copy nothing
209 			number_to_copy = 0;
210 		}
211 		else if (buffer_samples - position > 0)
212 		{
213 			// only copy what is left in the buffer
214 			number_to_copy = buffer_samples - position;
215 		}
216 		else
217 		{
218 			// copy nothing
219 			number_to_copy = 0;
220 		}
221 
222 
223 		// Determine if any samples need to be copied
224 		if (number_to_copy > 0)
225 		{
226 			// Debug
227 			ZmqLogger::Instance()->AppendDebugMethod("AudioReaderSource::getNextAudioBlock", "number_to_copy", number_to_copy, "buffer_samples", buffer_samples, "buffer_channels", buffer_channels, "info.numSamples", info.numSamples, "speed", speed, "position", position);
228 
229 			// Loop through each channel and copy some samples
230 			for (int channel = 0; channel < buffer_channels; channel++)
231 				info.buffer->copyFrom(channel, info.startSample, *buffer, channel, position, number_to_copy);
232 
233 			// Update the position of this audio source
234 			position += number_to_copy;
235 		}
236 
237 		// Adjust estimate frame number (the estimated frame number that is being played)
238 		estimated_samples_per_frame = Frame::GetSamplesPerFrame(estimated_frame, reader->info.fps, reader->info.sample_rate, buffer_channels);
239 		estimated_frame += double(info.numSamples) / double(estimated_samples_per_frame);
240 	}
241 }
242 
243 // Prepare to play this audio source
prepareToPlay(int,double)244 void AudioReaderSource::prepareToPlay(int, double) { }
245 
246 // Release all resources
releaseResources()247 void AudioReaderSource::releaseResources() { }
248 
249 // Set the next read position of this source
setNextReadPosition(juce::int64 newPosition)250 void AudioReaderSource::setNextReadPosition (juce::int64 newPosition)
251 {
252 	// set position (if the new position is in range)
253 	if (newPosition >= 0 && newPosition < buffer->getNumSamples())
254 		position = newPosition;
255 }
256 
257 // Get the next read position of this source
getNextReadPosition() const258 juce::int64 AudioReaderSource::getNextReadPosition() const
259 {
260 	// return the next read position
261 	return position;
262 }
263 
264 // Get the total length (in samples) of this audio source
getTotalLength() const265 juce::int64 AudioReaderSource::getTotalLength() const
266 {
267 	// Get the length
268 	if (reader)
269 		return reader->info.sample_rate * reader->info.duration;
270 	else
271 		return 0;
272 }
273 
274 // Determines if this audio source should repeat when it reaches the end
isLooping() const275 bool AudioReaderSource::isLooping() const
276 {
277 	// return if this source is looping
278 	return repeat;
279 }
280 
281 // Set if this audio source should repeat when it reaches the end
setLooping(bool shouldLoop)282 void AudioReaderSource::setLooping (bool shouldLoop)
283 {
284 	// Set the repeat flag
285 	repeat = shouldLoop;
286 }
287 
288 // Update the internal buffer used by this source
setBuffer(juce::AudioSampleBuffer * audio_buffer)289 void AudioReaderSource::setBuffer (juce::AudioSampleBuffer *audio_buffer)
290 {
291 	buffer = audio_buffer;
292 	setNextReadPosition(0);
293 }
294