OpenShot Library | libopenshot  0.3.1
AudioPlaybackThread.cpp
Go to the documentation of this file.
1 
10 // Copyright (c) 2008-2019 OpenShot Studios, LLC
11 //
12 // SPDX-License-Identifier: LGPL-3.0-or-later
13 
14 #include "AudioPlaybackThread.h"
15 #include "Settings.h"
16 
17 #include "../ReaderBase.h"
18 #include "../RendererBase.h"
19 #include "../AudioReaderSource.h"
20 #include "../AudioDevices.h"
21 #include "../Settings.h"
22 
23 #include <mutex>
24 #include <thread> // for std::this_thread::sleep_for
25 #include <chrono> // for std::chrono::milliseconds
26 
27 using namespace juce;
28 
29 namespace openshot
30 {
31  // Global reference to device manager
32  AudioDeviceManagerSingleton *AudioDeviceManagerSingleton::m_pInstance = NULL;
33 
34  // Create or Get audio device singleton with default settings (44100, 2)
35  AudioDeviceManagerSingleton *AudioDeviceManagerSingleton::Instance()
36  {
37  return AudioDeviceManagerSingleton::Instance(44100, 2);
38  }
39 
40  // Create or Get an instance of the device manager singleton (with custom sample rate & channels)
41  AudioDeviceManagerSingleton *AudioDeviceManagerSingleton::Instance(int rate, int channels)
42  {
43  static std::mutex mutex;
44  std::lock_guard<std::mutex> lock(mutex);
45 
46  if (!m_pInstance) {
47  // Create the actual instance of device manager only once
48  m_pInstance = new AudioDeviceManagerSingleton;
49  auto* mgr = &m_pInstance->audioDeviceManager;
50  AudioIODevice *foundAudioIODevice = NULL;
51  m_pInstance->initialise_error = "";
52  m_pInstance->currentAudioDevice.name = "";
53  m_pInstance->currentAudioDevice.type = "";
54  m_pInstance->defaultSampleRate = 0.0;
55 
56  // Get preferred audio device type and name (if any - these can be blank)
57  openshot::AudioDeviceInfo requested_device = {Settings::Instance()->PLAYBACK_AUDIO_DEVICE_TYPE,
58  Settings::Instance()->PLAYBACK_AUDIO_DEVICE_NAME};
59 
60  // Find missing device type (if needed)
61  if (requested_device.type.isEmpty() && !requested_device.name.isEmpty()) {
62  for (const auto t : mgr->getAvailableDeviceTypes()) {
63  t->scanForDevices();
64  for (const auto n : t->getDeviceNames()) {
65  if (requested_device.name.trim().equalsIgnoreCase(n.trim())) {
66  requested_device.type = t->getTypeName();
67  break;
68  }
69  }
70  }
71  }
72 
73  // Populate all possible device types and device names (starting with the user's requested settings)
74  std::vector<openshot::AudioDeviceInfo> devices{ { requested_device } };
75  for (const auto t : mgr->getAvailableDeviceTypes()) {
76  t->scanForDevices();
77  for (const auto n : t->getDeviceNames()) {
78  AudioDeviceInfo device = { t->getTypeName(), n.trim() };
79  devices.push_back(device);
80  }
81  }
82 
83  // Loop through all device combinations (starting with the requested one)
84  for (auto attempt_device : devices) {
85  m_pInstance->currentAudioDevice = attempt_device;
86 
87  // Resets everything to a default device setup
88  m_pInstance->audioDeviceManager.initialiseWithDefaultDevices(0, channels);
89 
90  // Set device type (if any)
91  if (!attempt_device.type.isEmpty()) {
92  m_pInstance->audioDeviceManager.setCurrentAudioDeviceType(attempt_device.type, true);
93  }
94 
95  // Settings for audio device playback
96  AudioDeviceManager::AudioDeviceSetup deviceSetup = AudioDeviceManager::AudioDeviceSetup();
97  deviceSetup.inputChannels = 0;
98  deviceSetup.outputChannels = channels;
99 
100  // Loop through common sample rates, starting with the user's requested rate
101  // Not all sample rates are supported by audio devices, for example, many VMs
102  // do not support 48000 causing no audio device to be found.
103  int possible_rates[] { rate, 48000, 44100, 22050 };
104  for(int attempt_rate : possible_rates) {
105  // Update the audio device setup for the current sample rate
106  m_pInstance->defaultSampleRate = attempt_rate;
107  deviceSetup.sampleRate = attempt_rate;
108  m_pInstance->audioDeviceManager.setAudioDeviceSetup(deviceSetup, true);
109 
110  // Open the audio device with specific sample rate (if possible)
111  // Not all sample rates are supported by audio devices
112  juce::String audio_error = m_pInstance->audioDeviceManager.initialise(
113  0, // number of input channels
114  channels, // number of output channels
115  nullptr, // no XML settings..
116  true, // select default device on failure
117  attempt_device.name, // preferredDefaultDeviceName
118  &deviceSetup // sample_rate & channels
119  );
120 
121  // Persist any errors detected
122  m_pInstance->initialise_error = audio_error.toStdString();
123 
124  // Determine if audio device was opened successfully, and matches the attempted sample rate
125  // If all rates fail to match, a default audio device and sample rate will be opened if possible
126  foundAudioIODevice = m_pInstance->audioDeviceManager.getCurrentAudioDevice();
127  if (foundAudioIODevice && foundAudioIODevice->getCurrentSampleRate() == attempt_rate) {
128  // Successfully tested a sample rate
129  break;
130  }
131  }
132 
133  if (foundAudioIODevice) {
134  // Successfully opened an audio device
135  break;
136  }
137  }
138 
139  }
140  return m_pInstance;
141  }
142 
143  // Close audio device
144  void AudioDeviceManagerSingleton::CloseAudioDevice()
145  {
146  // Close Audio Device
147  audioDeviceManager.closeAudioDevice();
148  audioDeviceManager.removeAllChangeListeners();
149  audioDeviceManager.dispatchPendingMessages();
150 
151  delete m_pInstance;
152  m_pInstance = NULL;
153  }
154 
155  // Constructor
156  AudioPlaybackThread::AudioPlaybackThread(openshot::VideoCacheThread* cache)
157  : juce::Thread("audio-playback")
158  , player()
159  , transport()
160  , mixer()
161  , source(NULL)
162  , sampleRate(0.0)
163  , numChannels(0)
164  , is_playing(false)
165  , time_thread("audio-buffer")
166  , videoCache(cache)
167  {
168  }
169 
170  // Destructor
171  AudioPlaybackThread::~AudioPlaybackThread()
172  {
173  }
174 
175  // Set the reader object
176  void AudioPlaybackThread::Reader(openshot::ReaderBase *reader) {
177  if (source)
178  source->Reader(reader);
179  else {
180  // Create new audio source reader
181  auto starting_frame = 1;
182  source = new AudioReaderSource(reader, starting_frame);
183  }
184 
185  // Set local vars
186  sampleRate = reader->info.sample_rate;
187  numChannels = reader->info.channels;
188 
189  // Set video cache thread
190  source->setVideoCache(videoCache);
191 
192  // Mark as 'playing'
193  Play();
194  }
195 
196  // Get the current frame object (which is filling the buffer)
197  std::shared_ptr<openshot::Frame> AudioPlaybackThread::getFrame()
198  {
199  if (source) return source->getFrame();
200  return std::shared_ptr<openshot::Frame>();
201  }
202 
203  // Seek the audio thread
204  void AudioPlaybackThread::Seek(int64_t new_position)
205  {
206  if (source) {
207  source->Seek(new_position);
208  }
209  }
210 
211  // Play the audio
212  void AudioPlaybackThread::Play() {
213  // Start playing
214  is_playing = true;
215  }
216 
217  // Stop the audio
218  void AudioPlaybackThread::Stop() {
219  // Stop playing
220  is_playing = false;
221  }
222 
223  // Start audio thread
224  void AudioPlaybackThread::run()
225  {
226  while (!threadShouldExit())
227  {
228  if (source && !transport.isPlaying() && is_playing) {
229  // Start new audio device (or get existing one)
230  AudioDeviceManagerSingleton *audioInstance =
231  AudioDeviceManagerSingleton::Instance(sampleRate, numChannels);
232 
233  // Add callback
234  audioInstance->audioDeviceManager.addAudioCallback(&player);
235 
236  // Create TimeSliceThread for audio buffering
237  time_thread.startThread();
238 
239  // Connect source to transport
240  transport.setSource(
241  source,
242  0, // No read ahead buffer
243  &time_thread,
244  0, // Sample rate correction (none)
245  numChannels); // max channels
246  transport.setPosition(0);
247  transport.setGain(1.0);
248 
249  // Connect transport to mixer and player
250  mixer.addInputSource(&transport, false);
251  player.setSource(&mixer);
252 
253  // Start the transport
254  transport.start();
255 
256  while (!threadShouldExit() && transport.isPlaying() && is_playing)
257  std::this_thread::sleep_for(std::chrono::milliseconds(2));
258 
259  // Stop audio and shutdown transport
260  Stop();
261  transport.stop();
262 
263  // Kill previous audio
264  transport.setSource(NULL);
265 
266  player.setSource(NULL);
267  audioInstance->audioDeviceManager.removeAudioCallback(&player);
268 
269  // Remove source
270  delete source;
271  source = NULL;
272 
273  // Stop time slice thread
274  time_thread.stopThread(-1);
275  }
276  }
277 
278  }
279 }
juce::AudioDeviceManager audioDeviceManager
Public device manager property.
The video cache class.
This abstract class is the base class, used by all readers in libopenshot.
Definition: ReaderBase.h:75
Source file for AudioPlaybackThread class.
Header file for global Settings class.
openshot::ReaderInfo info
Information about the current media file.
Definition: ReaderBase.h:88
This class is used to expose any ReaderBase derived class as an AudioSource in JUCE.
This namespace is the default namespace for all code in the openshot library.
Definition: Compressor.h:28
Singleton wrapper for AudioDeviceManager (to prevent multiple instances).
int channels
The number of audio channels used in the audio stream.
Definition: ReaderBase.h:61
This struct hold information about Audio Devices.
Definition: AudioDevices.h:26
int sample_rate
The number of audio samples per second (44100 is a common sample rate)
Definition: ReaderBase.h:60