OpenShot Library | libopenshot  0.1.1
AudioReaderSource.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  * @brief Source file for AudioReaderSource class
4  * @author Jonathan Thomas <jonathan@openshot.org>
5  *
6  * @section LICENSE
7  *
8  * Copyright (c) 2008-2014 OpenShot Studios, LLC
9  * <http://www.openshotstudios.com/>. This file is part of
10  * OpenShot Library (libopenshot), an open-source project dedicated to
11  * delivering high quality video editing and animation solutions to the
12  * world. For more information visit <http://www.openshot.org/>.
13  *
14  * OpenShot Library (libopenshot) is free software: you can redistribute it
15  * and/or modify it under the terms of the GNU Lesser General Public License
16  * as published by the Free Software Foundation, either version 3 of the
17  * License, or (at your option) any later version.
18  *
19  * OpenShot Library (libopenshot) is distributed in the hope that it will be
20  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public License
25  * along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
26  */
27 
28 #include "../include/AudioReaderSource.h"
29 
30 using namespace std;
31 using namespace openshot;
32 
33 // Constructor that reads samples from a reader
34 AudioReaderSource::AudioReaderSource(ReaderBase *audio_reader, int64 starting_frame_number, int buffer_size)
35  : reader(audio_reader), frame_number(starting_frame_number), original_frame_number(starting_frame_number),
36  size(buffer_size), position(0), frame_position(0), estimated_frame(0), speed(1) {
37 
38  // Initialize an audio buffer (based on reader)
39  buffer = new juce::AudioSampleBuffer(reader->info.channels, size);
40 
41  // initialize the audio samples to zero (silence)
42  buffer->clear();
43 }
44 
45 // Destructor
47 {
48  // Clear and delete the buffer
49  delete buffer;
50  buffer = NULL;
51 };
52 
53 // Get more samples from the reader
54 void AudioReaderSource::GetMoreSamplesFromReader()
55 {
56  // Determine the amount of samples needed to fill up this buffer
57  int amount_needed = position; // replace these used samples
58  int amount_remaining = size - amount_needed; // these are unused samples, and need to be carried forward
59  if (!frame) {
60  // If no frame, load entire buffer
61  amount_needed = size;
62  amount_remaining = 0;
63  }
64 
65  // Init estimated buffer equal to the current frame position (before getting more samples)
66  estimated_frame = frame_number;
67 
68  // Init new buffer
69  juce::AudioSampleBuffer *new_buffer = new juce::AudioSampleBuffer(reader->info.channels, size);
70  new_buffer->clear();
71 
72  // Move the remaining samples into new buffer (if any)
73  if (amount_remaining > 0) {
74  for (int channel = 0; channel < buffer->getNumChannels(); channel++)
75  new_buffer->addFrom(channel, 0, *buffer, channel, position, amount_remaining);
76 
77  position = amount_remaining;
78  } else
79  // reset position to 0
80  position = 0;
81 
82  // Loop through frames until buffer filled
83  while (amount_needed > 0 && speed == 1 && frame_number >= 1 && frame_number <= reader->info.video_length) {
84 
85  // Get the next frame (if position is zero)
86  if (frame_position == 0) {
87  try {
88  // Get frame object
89  frame = reader->GetFrame(frame_number);
90  frame_number = frame_number + speed;
91 
92  } catch (const ReaderClosed & e) {
93  break;
94  } catch (const TooManySeeks & e) {
95  break;
96  } catch (const OutOfBoundsFrame & e) {
97  break;
98  }
99  }
100 
101  bool frame_completed = false;
102  int amount_to_copy = 0;
103  if (frame)
104  amount_to_copy = frame->GetAudioSamplesCount() - frame_position;
105  if (amount_to_copy > amount_needed) {
106  // Don't copy too many samples (we don't want to overflow the buffer)
107  amount_to_copy = amount_needed;
108  amount_needed = 0;
109  } else {
110  // Not enough to fill the buffer (so use the entire frame)
111  amount_needed -= amount_to_copy;
112  frame_completed = true;
113  }
114 
115  // Load all of its samples into the buffer
116  if (frame)
117  for (int channel = 0; channel < new_buffer->getNumChannels(); channel++)
118  new_buffer->addFrom(channel, position, *frame->GetAudioSampleBuffer(), channel, frame_position, amount_to_copy);
119 
120  // Adjust remaining samples
121  position += amount_to_copy;
122  if (frame_completed)
123  // Reset frame buffer position (which will load a new frame on the next loop)
124  frame_position = 0;
125  else
126  // Continue tracking the current frame's position
127  frame_position += amount_to_copy;
128  }
129 
130  // Delete old buffer
131  buffer->clear();
132  delete buffer;
133 
134  // Replace buffer and reset position
135  buffer = new_buffer;
136  position = 0;
137 }
138 
139 // Reverse an audio buffer
140 juce::AudioSampleBuffer* AudioReaderSource::reverse_buffer(juce::AudioSampleBuffer* buffer)
141 {
142  int number_of_samples = buffer->getNumSamples();
143  int channels = buffer->getNumChannels();
144 
145  // Reverse array (create new buffer to hold the reversed version)
146  AudioSampleBuffer *reversed = new juce::AudioSampleBuffer(channels, number_of_samples);
147  reversed->clear();
148 
149  for (int channel = 0; channel < channels; channel++)
150  {
151  int n=0;
152  for (int s = number_of_samples - 1; s >= 0; s--, n++)
153  reversed->getWritePointer(channel)[n] = buffer->getWritePointer(channel)[s];
154  }
155 
156  // Copy the samples back to the original array
157  buffer->clear();
158  // Loop through channels, and get audio samples
159  for (int channel = 0; channel < channels; channel++)
160  // Get the audio samples for this channel
161  buffer->addFrom(channel, 0, reversed->getReadPointer(channel), number_of_samples, 1.0f);
162 
163  delete reversed;
164  reversed = NULL;
165 
166  // return pointer or passed in object (so this method can be chained together)
167  return buffer;
168 }
169 
170 // Get the next block of audio samples
171 void AudioReaderSource::getNextAudioBlock (const AudioSourceChannelInfo& info)
172 {
173  int buffer_samples = buffer->getNumSamples();
174  int buffer_channels = buffer->getNumChannels();
175 
176  if (info.numSamples > 0) {
177  int number_to_copy = 0;
178 
179  // Do we need more samples?
180  if (speed == 1) {
181  // Only refill buffers if speed is normal
182  if ((reader && reader->IsOpen() && !frame) or
183  (reader && reader->IsOpen() && buffer_samples - position < info.numSamples))
184  // Refill buffer from reader
185  GetMoreSamplesFromReader();
186  } else {
187  // Fill buffer with silence and clear current frame
188  info.buffer->clear();
189  return;
190  }
191 
192  // Determine how many samples to copy
193  if (position + info.numSamples <= buffer_samples)
194  {
195  // copy the full amount requested
196  number_to_copy = info.numSamples;
197  }
198  else if (position > buffer_samples)
199  {
200  // copy nothing
201  number_to_copy = 0;
202  }
203  else if (buffer_samples - position > 0)
204  {
205  // only copy what is left in the buffer
206  number_to_copy = buffer_samples - position;
207  }
208  else
209  {
210  // copy nothing
211  number_to_copy = 0;
212  }
213 
214 
215  // Determine if any samples need to be copied
216  if (number_to_copy > 0)
217  {
218  // Loop through each channel and copy some samples
219  for (int channel = 0; channel < buffer_channels; channel++)
220  info.buffer->copyFrom(channel, info.startSample, *buffer, channel, position, number_to_copy);
221 
222  // Update the position of this audio source
223  position += number_to_copy;
224  }
225 
226  // Adjust estimate frame number (the estimated frame number that is being played)
227  estimated_samples_per_frame = Frame::GetSamplesPerFrame(estimated_frame, reader->info.fps, reader->info.sample_rate, buffer_channels);
228  estimated_frame += double(info.numSamples) / double(estimated_samples_per_frame);
229  }
230 }
231 
232 // Prepare to play this audio source
233 void AudioReaderSource::prepareToPlay(int, double) { }
234 
235 // Release all resources
237 
238 // Set the next read position of this source
239 void AudioReaderSource::setNextReadPosition (long long newPosition)
240 {
241  // set position (if the new position is in range)
242  if (newPosition >= 0 && newPosition < buffer->getNumSamples())
243  position = newPosition;
244 }
245 
246 // Get the next read position of this source
248 {
249  // return the next read position
250  return position;
251 }
252 
253 // Get the total length (in samples) of this audio source
255 {
256  // Get the length
257  if (reader)
258  return reader->info.sample_rate * reader->info.duration;
259  else
260  return 0;
261 }
262 
263 // Determines if this audio source should repeat when it reaches the end
265 {
266  // return if this source is looping
267  return repeat;
268 }
269 
270 // Set if this audio source should repeat when it reaches the end
271 void AudioReaderSource::setLooping (bool shouldLoop)
272 {
273  // Set the repeat flag
274  repeat = shouldLoop;
275 }
276 
277 // Update the internal buffer used by this source
278 void AudioReaderSource::setBuffer (AudioSampleBuffer *audio_buffer)
279 {
280  buffer = audio_buffer;
282 }
void setBuffer(AudioSampleBuffer *audio_buffer)
Update the internal buffer used by this source.
float duration
Length of time (in seconds)
Definition: ReaderBase.h:64
void getNextAudioBlock(const AudioSourceChannelInfo &info)
Get the next block of audio samples.
void setLooping(bool shouldLoop)
Set if this audio source should repeat when it reaches the end.
This abstract class is the base class, used by all readers in libopenshot.
Definition: ReaderBase.h:95
void releaseResources()
Release all resources.
Exception when a reader is closed, and a frame is requested.
Definition: Exceptions.h:234
bool isLooping() const
Determines if this audio source should repeat when it reaches the end.
long long getNextReadPosition() const
Get the next read position of this source.
void setNextReadPosition(long long newPosition)
Set the next read position of this source.
ReaderInfo info
Information about the current media file.
Definition: ReaderBase.h:120
Fraction fps
Frames per second, as a fraction (i.e. 24/1 = 24 fps)
Definition: ReaderBase.h:69
Exception for frames that are out of bounds.
Definition: Exceptions.h:202
virtual tr1::shared_ptr< Frame > GetFrame(long int number)=0
void prepareToPlay(int, double)
Prepare to play this audio source.
int channels
The number of audio channels used in the audio stream.
Definition: ReaderBase.h:82
long long getTotalLength() const
Get the total length (in samples) of this audio source.
int GetSamplesPerFrame(Fraction fps, int sample_rate, int channels)
Calculate the # of samples per video frame (for the current frame number)
Definition: Frame.cpp:482
int sample_rate
The number of audio samples per second (44100 is a common sample rate)
Definition: ReaderBase.h:81
Exception when too many seek attempts happen.
Definition: Exceptions.h:254
virtual bool IsOpen()=0
A thread safe version of GetFrame.