OpenShot Library | libopenshot  0.2.0
AudioPlaybackThread.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  * @brief Source file for AudioPlaybackThread class
4  * @author Duzy Chan <code@duzy.info>
5  * @author Jonathan Thomas <jonathan@openshot.org> *
6  *
7  * @section LICENSE
8  *
9  * Copyright (c) 2008-2014 OpenShot Studios, LLC
10  * <http://www.openshotstudios.com/>. This file is part of
11  * OpenShot Library (libopenshot), an open-source project dedicated to
12  * delivering high quality video editing and animation solutions to the
13  * world. For more information visit <http://www.openshot.org/>.
14  *
15  * OpenShot Library (libopenshot) is free software: you can redistribute it
16  * and/or modify it under the terms of the GNU Lesser General Public License
17  * as published by the Free Software Foundation, either version 3 of the
18  * License, or (at your option) any later version.
19  *
20  * OpenShot Library (libopenshot) is distributed in the hope that it will be
21  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23  * GNU Lesser General Public License for more details.
24  *
25  * You should have received a copy of the GNU Lesser General Public License
26  * along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
27  */
28 
29 #include "../../include/Qt/AudioPlaybackThread.h"
30 
31 namespace openshot
32 {
33 
34  // Global reference to device manager
35  AudioDeviceManagerSingleton *AudioDeviceManagerSingleton::m_pInstance = NULL;
36 
37  // Create or Get an instance of the device manager singleton
39  {
40  if (!m_pInstance) {
41  // Create the actual instance of device manager only once
42  m_pInstance = new AudioDeviceManagerSingleton;
43 
44  // Initialize audio device only 1 time
45  m_pInstance->audioDeviceManager.initialise (
46  0, /* number of input channels */
47  numChannels, /* number of output channels */
48  0, /* no XML settings.. */
49  true /* select default device on failure */);
50  }
51 
52  return m_pInstance;
53  }
54 
55  // Close audio device
57  {
58  // Close Audio Device
59  audioDeviceManager.closeAudioDevice();
60  audioDeviceManager.removeAllChangeListeners();
61  audioDeviceManager.dispatchPendingMessages();
62  }
63 
64  // Constructor
65  AudioPlaybackThread::AudioPlaybackThread()
66  : Thread("audio-playback")
67  , player()
68  , transport()
69  , mixer()
70  , source(NULL)
71  , sampleRate(0.0)
72  , numChannels(0)
73  , buffer_size(12000)
74  , is_playing(false)
75  , time_thread("audio-buffer")
76  {
77  }
78 
79  // Destructor
80  AudioPlaybackThread::~AudioPlaybackThread()
81  {
82  }
83 
84  // Set the reader object
85  void AudioPlaybackThread::Reader(ReaderBase *reader) {
86  if (source)
87  source->Reader(reader);
88  else {
89  // Create new audio source reader
90  source = new AudioReaderSource(reader, 1, buffer_size);
91  source->setLooping(true); // prevent this source from terminating when it reaches the end
92  }
93 
94  // Set local vars
95  sampleRate = reader->info.sample_rate;
96  numChannels = reader->info.channels;
97 
98  // TODO: Update transport or audio source's sample rate, incase the sample rate
99  // is different than the original Reader
100 
101  // Mark as 'playing'
102  Play();
103  }
104 
105  // Get the current frame object (which is filling the buffer)
106  std::shared_ptr<Frame> AudioPlaybackThread::getFrame()
107  {
108  if (source) return source->getFrame();
109  return std::shared_ptr<Frame>();
110  }
111 
112  // Get the currently playing frame number
113  int64_t AudioPlaybackThread::getCurrentFramePosition()
114  {
115  return source ? source->getEstimatedFrame() : 0;
116  }
117 
118  // Seek the audio thread
119  void AudioPlaybackThread::Seek(int64_t new_position)
120  {
121  source->Seek(new_position);
122  }
123 
124  // Play the audio
125  void AudioPlaybackThread::Play() {
126  // Start playing
127  is_playing = true;
128  }
129 
130  // Stop the audio
131  void AudioPlaybackThread::Stop() {
132  // Stop playing
133  is_playing = false;
134  }
135 
136  // Start audio thread
137  void AudioPlaybackThread::run()
138  {
139  while (!threadShouldExit())
140  {
141  if (source && !transport.isPlaying() && is_playing) {
142 
143  // Start new audio device (or get existing one)
144  // Add callback
145  AudioDeviceManagerSingleton::Instance(numChannels)->audioDeviceManager.addAudioCallback(&player);
146 
147  // Create TimeSliceThread for audio buffering
148  time_thread.startThread();
149 
150  // Connect source to transport
151  transport.setSource(
152  source,
153  buffer_size, // tells it to buffer this many samples ahead
154  &time_thread,
155  sampleRate,
156  numChannels);
157  transport.setPosition(0);
158  transport.setGain(1.0);
159 
160  // Connect transport to mixer and player
161  mixer.addInputSource(&transport, false);
162  player.setSource(&mixer);
163 
164  // Start the transport
165  transport.start();
166 
167  while (!threadShouldExit() && transport.isPlaying() && is_playing)
168  usleep(2500);
169 
170  // Stop audio and shutdown transport
171  Stop();
172  transport.stop();
173 
174  // Kill previous audio
175  transport.setSource(NULL);
176 
177  player.setSource(NULL);
178  AudioDeviceManagerSingleton::Instance(0)->audioDeviceManager.removeAudioCallback(&player);
179 
180  // Remove source
181  delete source;
182  source = NULL;
183 
184  // Stop time slice thread
185  time_thread.stopThread(-1);
186  }
187  }
188 
189  }
190 }
void CloseAudioDevice()
Close audio device.
std::shared_ptr< Frame > getFrame() const
Return the current frame object.
AudioDeviceManager audioDeviceManager
Public device manager property.
void setLooping(bool shouldLoop)
Set if this audio source should repeat when it reaches the end.
void Seek(int64_t new_position)
Seek to a specific frame.
void Reader(ReaderBase *audio_reader)
Set Reader.
This namespace is the default namespace for all code in the openshot library.
Singleton wrapper for AudioDeviceManager (to prevent multiple instances).
static AudioDeviceManagerSingleton * Instance(int numChannels)
Create or get an instance of this singleton (invoke the class with this method)
int64_t getEstimatedFrame() const
Get the estimate frame that is playing at this moment.