2 Copyright (C) 2014 Waves Audio Ltd.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "waves_audiobackend.h"
21 #include "waves_audioport.h"
22 #include "waves_midiport.h"
24 #include "ardour/runtime_functions.h"
28 #define sleep(X) Sleep((X) * 1000)
29 // JE - Perhaps we should be using Glib::usleep() here, rather than sleep()?? But
30 // that would make the Waves backend dependent on Glib (which is isn't, currently).
33 using namespace ARDOUR;
35 #if defined __MINGW64__ || defined __MINGW32__
36 extern "C" __declspec(dllexport) ARDOUR::AudioBackendInfo* descriptor ()
38 extern "C" ARDOURBACKEND_API ARDOUR::AudioBackendInfo* descriptor ()
41 // COMMENTED DBG LOGS */ std::cout << "waves_backend.dll : ARDOUR::AudioBackendInfo* descriptor (): " << std::endl;
42 return &WavesAudioBackend::backend_info ();
45 void WavesAudioBackend::AudioDeviceManagerNotification (NotificationReason reason, void* parameter)
48 case WCMRAudioDeviceManagerClient::DeviceDebugInfo:
49 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::DeviceDebugInfo -- " << (char*)parameter << std::endl;
51 case WCMRAudioDeviceManagerClient::BufferSizeChanged:
52 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::BufferSizeChanged: " << *(int*)parameter << std::endl;
53 _buffer_size_change(*(int*)parameter);
55 case WCMRAudioDeviceManagerClient::RequestReset:
56 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::RequestReset" << std::endl;
57 engine.request_backend_reset();
59 case WCMRAudioDeviceManagerClient::RequestResync:
60 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::RequestResync" << std::endl;
62 case WCMRAudioDeviceManagerClient::SamplingRateChanged:
63 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::SamplingRateChanged: " << *(float*)parameter << std::endl;
64 _sample_rate_change(*(float*)parameter);
66 case WCMRAudioDeviceManagerClient::Dropout:
67 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::Dropout: " << std::endl;
69 case WCMRAudioDeviceManagerClient::DeviceDroppedSamples:
70 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::DeviceDroppedSamples" << std::endl;
72 case WCMRAudioDeviceManagerClient::DeviceStoppedStreaming:
73 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::DeviceStoppedStreaming" << std::endl;
75 case WCMRAudioDeviceManagerClient::DeviceStartsStreaming:
76 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::DeviceStartsStreaming" << std::endl;
77 _call_thread_init_callback = true; // streaming will be started from device side, just set thread init flag
79 case WCMRAudioDeviceManagerClient::DeviceConnectionLost:
80 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::DeviceConnectionLost" << std::endl;
82 case WCMRAudioDeviceManagerClient::DeviceListChanged:
83 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::DeviceListChanged" << std::endl;
84 engine.request_device_list_update();
86 case WCMRAudioDeviceManagerClient::IODeviceDisconnected:
87 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::IODeviceDisconnected" << std::endl;
88 engine.request_device_list_update();
90 case WCMRAudioDeviceManagerClient::AudioCallback:
92 const AudioCallbackData* audio_callback_data = (AudioCallbackData*)parameter;
93 _audio_device_callback (
94 audio_callback_data->acdInputBuffer,
95 audio_callback_data->acdOutputBuffer,
96 audio_callback_data->acdFrames,
97 audio_callback_data->acdSampleTime,
98 audio_callback_data->acdCycleStartTimeNanos
109 WavesAudioBackend::WavesAudioBackend (AudioEngine& e)
110 : AudioBackend (e, __backend_info)
111 , _audio_device_manager (this)
112 , _midi_device_manager (*this)
114 , _sample_format (FormatFloat)
115 , _interleaved (true)
116 , _input_channels (0)
117 , _max_input_channels (0)
118 , _output_channels (0)
119 , _max_output_channels (0)
122 , _systemic_input_latency (0)
123 , _systemic_output_latency (0)
124 , _call_thread_init_callback (false)
126 , _sample_time_at_cycle_start (0)
127 , _freewheeling (false)
128 , _freewheel_thread_active (false)
129 , _dsp_load_accumulator (0)
130 , _audio_cycle_period_nanos (0)
131 , _dsp_load_history_length(0)
136 WavesAudioBackend::~WavesAudioBackend ()
142 WavesAudioBackend::name () const
145 return std::string ("CoreAudio");
146 #elif PLATFORM_WINDOWS
147 return std::string ("ASIO");
153 WavesAudioBackend::is_realtime () const
160 WavesAudioBackend::requires_driver_selection () const
166 std::vector<std::string>
167 WavesAudioBackend::enumerate_drivers () const
169 // this backend does not suppose driver selection
172 return std::vector<std::string> ();
177 WavesAudioBackend::set_driver (const std::string& /*drivername*/)
179 //Waves audio backend does not suppose driver selection
186 std::vector<AudioBackend::DeviceStatus>
187 WavesAudioBackend::enumerate_devices () const
189 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::enumerate_devices (): " << std::endl;
191 std::vector<DeviceStatus> devicesStatus;
192 const DeviceInfoVec& deviceInfoList = _audio_device_manager.DeviceInfoList();
194 for (DeviceInfoVecConstIter deviceInfoIter = deviceInfoList.begin (); deviceInfoIter != deviceInfoList.end (); ++deviceInfoIter) {
195 // COMMENTED DBG LOGS */ std::cout << "\t Device found: " << (*deviceInfoIter)->m_DeviceName << std::endl;
196 devicesStatus.push_back (DeviceStatus ((*deviceInfoIter)->m_DeviceName, true));
199 return devicesStatus;
204 WavesAudioBackend::available_sample_rates (const std::string& device_name) const
206 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::available_sample_rates (): [" << device_name << "]" << std::endl;
210 WTErr retVal = _audio_device_manager.GetDeviceSampleRates(device_name, sr);
212 if (eNoErr != retVal) {
213 std::cerr << "WavesAudioBackend::available_sample_rates (): Failed to find device [" << device_name << "]" << std::endl;
214 return std::vector<float> ();
217 // COMMENTED DBG LOGS */ std::cout << "\tFound " << devInfo.m_AvailableSampleRates.size () << " sample rates for " << device_name << ":";
219 std::vector<float> sample_rates (sr.begin (), sr.end ());
221 // COMMENTED DBG LOGS */ for (std::vector<float>::iterator i = sample_rates.begin (); i != sample_rates.end (); ++i) std::cout << " " << *i; std::cout << std::endl;
227 float WavesAudioBackend::default_sample_rate () const
229 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::default_sample_rate (): " << AudioBackend::default_sample_rate () << std::endl;
230 return AudioBackend::default_sample_rate ();
234 std::vector<uint32_t>
235 WavesAudioBackend::available_buffer_sizes (const std::string& device_name) const
237 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::available_buffer_sizes (): [" << device_name << "]" << std::endl;
241 WTErr retVal = _audio_device_manager.GetDeviceBufferSizes(device_name, bs);
243 if (retVal != eNoErr) {
244 std::cerr << "WavesAudioBackend::available_buffer_sizes (): Failed to get buffer size for device [" << device_name << "]" << std::endl;
245 return std::vector<uint32_t> ();
248 std::vector<uint32_t> buffer_sizes (bs.begin (), bs.end ());
250 // COMMENTED DBG LOGS */ std::cout << "\tFound " << buffer_sizes.size () << " buffer sizes for " << device_name << ":";
251 // COMMENTED DBG LOGS */ for (std::vector<uint32_t>::const_iterator i = buffer_sizes.begin (); i != buffer_sizes.end (); ++i) std::cout << " " << *i; std::cout << std::endl;
258 WavesAudioBackend::available_input_channel_count (const std::string& device_name) const
261 WTErr err = _audio_device_manager.GetDeviceInfoByName(device_name, devInfo);
264 std::cerr << "WavesAudioBackend::available_input_channel_count (): Failed to find device [" << device_name << "]" << std::endl;
268 uint32_t num_of_input_channels = devInfo.m_MaxInputChannels;
270 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::available_input_channel_count (): " << num_of_input_channels << std::endl;
271 return num_of_input_channels;
276 WavesAudioBackend::available_output_channel_count (const std::string& device_name) const
279 WTErr err = _audio_device_manager.GetDeviceInfoByName(device_name, devInfo);
282 std::cerr << "WavesAudioBackend::available_output_channel_count (): Failed to find device [" << device_name << "]" << std::endl;
286 uint32_t num_of_output_channels = devInfo.m_MaxOutputChannels;
288 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::available_output_channel_count (): " << num_of_output_channels << std::endl;
290 return num_of_output_channels;
295 WavesAudioBackend::can_change_sample_rate_when_running () const
297 // VERIFY IT CAREFULLY
303 WavesAudioBackend::can_change_buffer_size_when_running () const
305 // VERIFY IT CAREFULLY
311 WavesAudioBackend::set_device_name (const std::string& device_name)
313 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_device_name (): " << device_name << std::endl;
315 if (_ports.size ()) {
316 std::cerr << "WavesAudioBackend::set_device_name (): There are unregistered ports left after [" << (_device ? _device->DeviceName () : std::string ("<NULL>")) << "]!" << std::endl;
317 for (size_t i = 0; i < _ports.size (); ++i) {
318 std::cerr << "\t[" << _ports[i]->name () << "]!" << std::endl;
323 if (_device && _device->Streaming () ) {
324 std::cerr << "WavesAudioBackend::set_device_name (): [" << _device->DeviceName () << "] is streaming! Current device must be stopped before setting another device as current" << std::endl;
327 // we must have only one device initialized at a time
328 // stop current device first
331 retVal = _device->SetActive (false);
332 if (retVal != eNoErr) {
333 std::cerr << "WavesAudioBackend::set_device_name (): [" << _device->DeviceName () << "]->SetActive (false) failed!" << std::endl;
339 _audio_device_manager.DestroyCurrentDevice();
342 WCMRAudioDevice * device = _audio_device_manager.InitNewCurrentDevice(device_name);
345 std::cerr << "WavesAudioBackend::set_device_name (): Failed to initialize device [" << device_name << "]!" << std::endl;
350 retVal = device->SetActive (true);
351 if (retVal != eNoErr) {
352 std::cerr << "WavesAudioBackend::set_device_name (): [" << device->DeviceName () << "]->SetActive () failed!" << std::endl;
362 WavesAudioBackend::drop_device()
368 wtErr = _device->SetActive (false);
369 if (wtErr != eNoErr) {
370 std::cerr << "WavesAudioBackend::drop_device (): [" << _device->DeviceName () << "]->SetActive () failed!" << std::endl;
375 _audio_device_manager.DestroyCurrentDevice();
383 WavesAudioBackend::set_sample_rate (float sample_rate)
385 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_sample_rate (): " << sample_rate << std::endl;
387 WTErr retVal = eNoErr;
390 std::cerr << "WavesAudioBackend::set_sample_rate (): No device is set!" << std::endl;
395 bool device_needs_restart = _device->Streaming ();
397 if (device_needs_restart) {
398 retVal = _device->SetStreaming (false);
399 // COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->_device->SetStreaming (false);"<< std::endl;
400 if (retVal != eNoErr) {
401 std::cerr << "WavesAudioBackend::set_sample_rate (): [" << _device->DeviceName () << "]->SetStreaming (false) failed (" << retVal << ") !" << std::endl;
406 retVal = _device->SetCurrentSamplingRate ((int)sample_rate);
408 if (retVal != eNoErr) {
409 std::cerr << "WavesAudioBackend::set_sample_rate (): [" << _device->DeviceName() << "]->SetCurrentSamplingRate ((int)" << sample_rate << ") failed (" << retVal << ") !" << std::endl;
413 // if call to set sample rate is successful
414 // but device sample rate differs from the value we tried to set
415 // this means we are driven by device for buffer size
416 sample_rate = _device->CurrentSamplingRate ();
417 _sample_rate_change(sample_rate);
419 if (device_needs_restart) {
420 // COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetStreaming (true);"<< std::endl;
421 retVal = _device->SetStreaming (true);
422 if (retVal != eNoErr) {
423 std::cerr << "WavesAudioBackend::set_sample_rate (): [" << _device->DeviceName () << "]->SetStreaming (true) failed (" << retVal << ") !" << std::endl;
432 WavesAudioBackend::set_buffer_size (uint32_t buffer_size)
434 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_buffer_size (" << buffer_size << "):"<< std::endl;
436 WTErr retVal = eNoErr;
439 std::cerr << "WavesAudioBackend::set_buffer_size (): No device is set!" << std::endl;
443 bool device_needs_restart = _device->Streaming ();
445 if (device_needs_restart) {
446 retVal = _device->SetStreaming (false);
447 // COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetStreaming (false);"<< std::endl;
448 if (retVal != eNoErr) {
449 std::cerr << "WavesAudioBackend::set_buffer_size (): [" << _device->DeviceName () << "]->SetStreaming (false) failed (" << retVal << ") !" << std::endl;
454 retVal = _device->SetCurrentBufferSize (buffer_size);
456 if (retVal != eNoErr) {
457 std::cerr << "WavesAudioBackend::set_buffer_size (): [" << _device->DeviceName() << "]->SetCurrentBufferSize (" << buffer_size << ") failed (" << retVal << ") !" << std::endl;
461 // if call to set buffer is successful but device buffer size differs from the value we tried to set
462 // this means we are driven by device for buffer size
463 buffer_size = _device->CurrentBufferSize ();
465 _buffer_size_change(buffer_size);
467 if (device_needs_restart) {
468 // COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetStreaming (true);"<< std::endl;
469 retVal = _device->SetStreaming (true);
470 if (retVal != eNoErr) {
471 std::cerr << "WavesAudioBackend::set_buffer_size (): [" << _device->DeviceName () << "]->SetStreaming (true) failed (" << retVal << ") !" << std::endl;
481 WavesAudioBackend::set_sample_format (SampleFormat sample_format)
483 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_sample_format (): " << sample_format << std::endl;
485 _sample_format = sample_format;
490 WavesAudioBackend::reset_device ()
492 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_reset_device ():" << std::endl;
495 std::cerr << "WavesAudioBackend::set_buffer_size (): No device is set!" << std::endl;
499 return _device->ResetDevice();
504 WavesAudioBackend::_buffer_size_change (uint32_t new_buffer_size)
506 _buffer_size = new_buffer_size;
507 _init_dsp_load_history();
508 return engine.buffer_size_change (new_buffer_size);
513 WavesAudioBackend::_sample_rate_change (float new_sample_rate)
515 _sample_rate = new_sample_rate;
516 _init_dsp_load_history();
517 return engine.sample_rate_change (new_sample_rate);
522 WavesAudioBackend::set_interleaved (bool yn)
524 /*you can ignore them totally*/
531 WavesAudioBackend::set_input_channels (uint32_t input_channels)
533 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_input_channels (): " << input_channels << std::endl;
535 _input_channels = input_channels;
541 WavesAudioBackend::set_output_channels (uint32_t output_channels)
543 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_output_channels (): " << output_channels << std::endl;
545 _output_channels = output_channels;
551 WavesAudioBackend::device_name () const
556 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::device_name (): " << _device->DeviceName () << std::endl;
558 return _device->DeviceName ();
563 WavesAudioBackend::sample_rate () const
565 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::sample_rate (): " << std::endl;
568 std::cerr << "WavesAudioBackend::sample_rate (): No device is set!" << std::endl;
572 int sample_rate = _device->CurrentSamplingRate ();
574 // COMMENTED DBG LOGS */ std::cout << "\t[" << _device->DeviceName () << "]->CurrentSamplingRate () returned " << sample_rate << std::endl;
576 return (float)sample_rate;
581 WavesAudioBackend::buffer_size () const
584 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::buffer_size (): " << std::endl;
587 std::cerr << "WavesAudioBackend::buffer_size (): No device is set!" << std::endl;
591 int size = _device->CurrentBufferSize ();
593 // COMMENTED DBG LOGS */ std::cout << "\t[" << _device->DeviceName () << "]->CurrentBufferSize () returned " << size << std::endl;
595 return (uint32_t)size;
600 WavesAudioBackend::sample_format () const
602 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::sample_format ()" << std::endl;
603 return _sample_format;
608 WavesAudioBackend::interleaved () const
610 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::interleaved ()" << std::endl;
617 WavesAudioBackend::input_channels () const
619 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::input_channels ()" << std::endl;
621 return _input_channels;
626 WavesAudioBackend::output_channels () const
628 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::output_channels ()" << std::endl;
630 return _output_channels;
635 WavesAudioBackend::control_app_name () const
637 std::string app_name = "";
639 if (_device && !dynamic_cast<WCMRNativeAudioNoneDevice*> (_device)) {
640 app_name = "PortAudioMayKnowIt";
648 WavesAudioBackend::launch_control_app ()
650 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::launch_control_app ()" << std::endl;
652 std::cerr << "WavesAudioBackend::launch_control_app (): No device is set!" << std::endl;
656 WTErr err = _device->ShowConfigPanel (NULL);
659 std::cerr << "WavesAudioBackend::launch_control_app (): [" << _device->DeviceName () << "]->ShowConfigPanel () failed (" << err << ")!" << std::endl;
662 // COMMENTED DBG LOGS */ else std::cout << "WavesAudioBackend::launch_control_app (): [" << _device->DeviceName () << "]->ShowConfigPanel () successfully launched!" << std::endl;
667 WavesAudioBackend::_start (bool for_latency_measurement)
669 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_start ()" << std::endl;
672 std::cerr << "WavesAudioBackend::_start (): No device is set!" << std::endl;
677 if (_register_system_audio_ports () != 0) {
678 std::cerr << "WavesAudioBackend::_start (): _register_system_audio_ports () failed!" << std::endl;
684 if (_midi_device_manager.start () != 0) {
685 std::cerr << "WavesAudioBackend::_start (): _midi_device_manager.start () failed!" << std::endl;
689 if (_register_system_midi_ports () != 0) {
690 std::cerr << "WavesAudioBackend::_start (): _register_system_midi_ports () failed!" << std::endl;
696 if (engine.reestablish_ports () != 0) {
697 std::cerr << "WavesAudioBackend::_start (): engine.reestablish_ports () failed!" << std::endl;
700 manager.registration_callback ();
702 WTErr retVal = _device->SetStreaming (true);
703 if (retVal != eNoErr) {
704 std::cerr << "WavesAudioBackend::_start (): [" << _device->DeviceName () << "]->SetStreaming () failed!" << std::endl;
710 if (_midi_device_manager.stream (true)) {
711 std::cerr << "WavesAudioBackend::_start (): _midi_device_manager.stream (true) failed!" << std::endl;
722 WavesAudioBackend::_audio_device_callback (const float* input_buffer,
723 float* output_buffer,
724 unsigned long nframes,
725 framepos_t sample_time,
726 uint64_t cycle_start_time_nanos)
728 uint64_t dsp_start_time_nanos = __get_time_nanos();
729 // COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::_audio_device_callback ():" << _device->DeviceName () << std::endl;
730 _sample_time_at_cycle_start = sample_time;
731 _cycle_start_time_nanos = cycle_start_time_nanos;
733 if (_buffer_size != nframes) {
734 // COMMENTED DBG LOGS */ std::cout << "\tAudioEngine::thread_init_callback() buffer size and nframes are not equal: " << _buffer_size << "!=" << nframes << std::endl;
738 _read_audio_data_from_device (input_buffer, nframes);
739 _read_midi_data_from_devices ();
741 if (_call_thread_init_callback) {
742 _call_thread_init_callback = false;
743 // COMMENTED DBG LOGS */ std::cout << "\tAudioEngine::thread_init_callback() invoked for " << std::hex << pthread_self() << std::dec << " !" << std::endl;
745 /* There is the possibility that the thread this runs in may change from
746 * callback to callback, so do it every time.
748 _main_thread = pthread_self ();
750 AudioEngine::thread_init_callback (this);
753 if ( !engine.thread_initialised_for_audio_processing () ) {
754 std::cerr << "\tWavesAudioBackend::_audio_device_callback (): It's an attempt to call process callback from the thread which didn't initialize it " << std::endl;
756 AudioEngine::thread_init_callback (this);
759 if (pthread_equal (_main_thread, pthread_self()) == 0) {
761 std::cerr << "Process thread ID has changed. Expected thread: " << _main_thread.p << " current thread: " << pthread_self().p << std::dec << " !" << std::endl;
763 std::cerr << "Process thread ID has changed. Expected thread: " << _main_thread << " current thread: " << pthread_self() << std::dec << " !" << std::endl;
765 _main_thread = pthread_self();
768 engine.process_callback (nframes);
770 _write_audio_data_to_device (output_buffer, nframes);
771 _write_midi_data_to_devices (nframes);
773 uint64_t dsp_end_time_nanos = __get_time_nanos();
775 _dsp_load_accumulator -= *_dsp_load_history.begin();
776 _dsp_load_history.pop_front();
777 uint64_t dsp_load_nanos = dsp_end_time_nanos - dsp_start_time_nanos;
778 _dsp_load_accumulator += dsp_load_nanos;
779 _dsp_load_history.push_back(dsp_load_nanos);
786 WavesAudioBackend::stop ()
788 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::stop ()" << std::endl;
790 WTErr wtErr = eNoErr;
793 // COMMENTED DBG LOGS */ std::cout << "\t[" << _device->DeviceName () << "]" << std::endl;
796 wtErr = _device->SetStreaming (false);
797 if (wtErr != eNoErr) {
798 std::cerr << "WavesAudioBackend::stop (): [" << _device->DeviceName () << "]->SetStreaming () failed!" << std::endl;
803 _midi_device_manager.stop ();
804 _unregister_system_audio_ports ();
805 _unregister_system_midi_ports ();
812 WavesAudioBackend::freewheel (bool start_stop)
814 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::freewheel (" << start_stop << "):" << std::endl;
816 if (start_stop != _freewheeling) {
817 if (start_stop == true) {
818 WTErr retval = _device->SetStreaming (false);
819 if (retval != eNoErr) {
820 std::cerr << "WavesAudioBackend::freewheel (): [" << _device->DeviceName () << "]->SetStreaming () failed!" << std::endl;
823 _call_thread_init_callback = true;
824 _freewheel_thread ();
826 while (!engine.freewheeling()) {
830 // freewheel thread was not activated successfully
831 if (_freewheel_thread_active == false) {
832 engine.freewheel_callback(false);
836 _freewheel_thread_active = false; // stop _freewheel_thread ()
838 while (engine.freewheeling()) {
842 _call_thread_init_callback = true;
843 WTErr retval = _device->SetStreaming (true);
844 if (retval != eNoErr) {
845 std::cerr << "WavesAudioBackend::freewheel (): [" << _device->DeviceName () << "]->SetStreaming () failed!" << std::endl;
849 _freewheeling = start_stop;
851 // already doing what has been asked for
857 WavesAudioBackend::_freewheel_thread ()
859 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_freewheel_thread ():" << std::endl;
860 if (!_freewheel_thread_active) { // Lets create it
862 // COMMENTED DBG LOGS */ std::cout << "\tCreating the thread _freewheel_thread () . . ." << std::endl;
863 pthread_attr_t attributes;
866 ThreadData* thread_data = new ThreadData (this, boost::bind (&WavesAudioBackend::_freewheel_thread, this), __thread_stack_size ());
868 if (pthread_attr_init (&attributes)) {
869 std::cerr << "WavesAudioBackend::freewheel_thread (): pthread_attr_init () failed!" << std::endl;
873 if (pthread_attr_setstacksize (&attributes, __thread_stack_size ())) {
874 std::cerr << "WavesAudioBackend::freewheel_thread (): pthread_attr_setstacksize () failed!" << std::endl;
878 _freewheel_thread_active = true;
879 if ((pthread_create (&thread_id, &attributes, __start_process_thread, thread_data))) {
880 _freewheel_thread_active = false;
882 // release invoking thread
883 engine.freewheel_callback(true);
885 std::cerr << "WavesAudioBackend::freewheel_thread (): pthread_create () failed!" << std::endl;
889 // COMMENTED DBG LOGS */ std::cout << "\t. . . _freewheel_thread () complete." << std::endl;
893 // notify angine that freewheeling is started
894 engine.freewheel_callback(true);
896 if (_call_thread_init_callback) {
897 _call_thread_init_callback = false;
898 AudioEngine::thread_init_callback (this);
901 while (_freewheel_thread_active) {
902 engine.process_callback (_buffer_size);
905 // notify angine that freewheeling is stopped
906 engine.freewheel_callback(false);
908 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_freewheel_thread (): FINISHED" << std::endl;
914 WavesAudioBackend::dsp_load () const
916 // COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::dsp_load (): " << std::endl;
919 std::cerr << "WavesAudioBackend::cpu_load (): No device is set!" << std::endl;
923 float average_dsp_load = (float)_dsp_load_accumulator/_dsp_load_history_length;
925 return ( average_dsp_load / _audio_cycle_period_nanos)*100.0;
930 WavesAudioBackend::_init_dsp_load_history()
932 if((_sample_rate <= 0.0) || (_buffer_size <= 0.0)) {
936 _audio_cycle_period_nanos = ((uint64_t)1000000000L * _buffer_size) / _sample_rate;
938 _dsp_load_accumulator = 0;
940 _dsp_load_history_length = (_sample_rate + _buffer_size - 1) / _buffer_size;
941 // COMMENTED DBG LOGS */ std::cout << "\t\t_dsp_load_history_length = " << _dsp_load_history_length << std::endl;
942 _dsp_load_history = std::list<uint64_t>(_dsp_load_history_length, 0);
947 WavesAudioBackend::transport_start ()
949 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::transport_start (): " << std::endl;
954 WavesAudioBackend::transport_stop ()
956 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::transport_stop (): " << std::endl;
961 WavesAudioBackend::transport_state () const
963 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::transport_state (): " << std::endl;
964 return TransportStopped;
969 WavesAudioBackend::transport_locate (framepos_t pos)
971 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::transport_locate (" << pos << "): " << std::endl;
976 WavesAudioBackend::transport_frame () const
978 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::transport_frame (): " << std::endl;
984 WavesAudioBackend::set_time_master (bool yn)
986 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_time_master (): " << yn << std::endl;
992 WavesAudioBackend::usecs_per_cycle () const
994 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::usecs_per_cycle (): " << std::endl;
995 return (1000000 * _sample_rate) / _buffer_size;
1000 WavesAudioBackend::raw_buffer_size (DataType data_type)
1002 // COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::raw_buffer_size (" << data_type.to_string () << "): " << std::endl;
1003 switch (data_type) {
1004 case DataType::AUDIO:
1005 return WavesAudioPort::MAX_BUFFER_SIZE_BYTES;
1008 case DataType::MIDI:
1009 return WavesMidiPort::MAX_BUFFER_SIZE_BYTES;
1013 std::cerr << "WavesAudioBackend::raw_buffer_size (): unexpected data type (" << (uint32_t)data_type <<")!" << std::endl;
1021 WavesAudioBackend::sample_time ()
1023 // WARNING: This is approximate calculation. Implementation of accurate calculation is pending.
1024 // http://kokkinizita.linuxaudio.org/papers/usingdll.pdf
1026 return _sample_time_at_cycle_start + ((__get_time_nanos () - _cycle_start_time_nanos)*_sample_rate)/1000000000L;
1031 WavesAudioBackend::__get_time_nanos ()
1034 // here we exploit the time counting API which is used by the WCMRCoreAudioDeviceManager. However,
1035 // the API should be a part of WCMRCoreAudioDeviceManager to give a chance of being tied to the
1036 // audio device transport timeß.
1037 return AudioConvertHostTimeToNanos (AudioGetCurrentHostTime ());
1039 #elif PLATFORM_WINDOWS
1040 LARGE_INTEGER Count;
1041 QueryPerformanceCounter (&Count);
1042 return uint64_t ((Count.QuadPart * 1000000000L / __performance_counter_frequency));
1048 WavesAudioBackend::sample_time_at_cycle_start ()
1050 // COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::sample_time_at_cycle_start (): " << _sample_time_at_cycle_start << std::endl;
1051 return _sample_time_at_cycle_start;
1056 WavesAudioBackend::samples_since_cycle_start ()
1058 pframes_t diff_sample_time;
1059 diff_sample_time = sample_time () - _sample_time_at_cycle_start;
1060 // COMMENTED DBG LOGS */ std::cout << "samples_since_cycle_start: " << diff_sample_time << std::endl;
1062 return diff_sample_time;
1067 WavesAudioBackend::get_sync_offset (pframes_t& /*offset*/) const
1069 // COMMENTED DBG LOGS */ std::cout << "get_sync_offset: false" << std::endl;
1076 WavesAudioBackend::create_process_thread (boost::function<void ()> func)
1078 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::create_process_thread ():" << std::endl;
1080 pthread_attr_t attributes;
1081 size_t stacksize_aligned;
1082 pthread_t thread_id;
1084 // Align stacksize to PTHREAD_STACK_MIN.
1085 stacksize_aligned = __thread_stack_size ();
1087 ThreadData* td = new ThreadData (this, func, stacksize_aligned);
1089 if ((retVal = pthread_attr_init (&attributes))) {
1090 std::cerr << "Cannot set thread attr init res = " << retVal << endmsg;
1094 if ((retVal = pthread_attr_setstacksize (&attributes, stacksize_aligned))) {
1095 std::cerr << "Cannot set thread stack size (" << stacksize_aligned << ") res = " << retVal << endmsg;
1099 if ((retVal = pthread_create (&thread_id, &attributes, __start_process_thread, td))) {
1100 std::cerr << "Cannot create thread res = " << retVal << endmsg;
1104 _backend_threads.push_back (thread_id);
1105 // COMMENTED DBG LOGS */ std::cout << "\t\t\t. . . thread " << std::hex << thread_id << std::dec << " has been created" << std::endl;
1112 WavesAudioBackend::__start_process_thread (void* arg)
1114 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__start_process_thread ():" << std::endl;
1115 ThreadData* td = reinterpret_cast<ThreadData*> (arg);
1116 boost::function<void ()> f = td->f;
1124 WavesAudioBackend::join_process_threads ()
1126 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::join_process_thread ()" << std::endl;
1129 for (std::vector<pthread_t>::const_iterator i = _backend_threads.begin ();
1130 i != _backend_threads.end ();
1132 // COMMENTED DBG LOGS */ std::cout << "\t\t\tstopping thread " << std::hex << *i << std::dec << "...\n";
1135 if (pthread_join (*i, &status) != 0) {
1136 std::cerr << "AudioEngine: cannot stop process thread !" << std::endl;
1139 // COMMENTED DBG LOGS */ std::cout << "\t\t\t\t...done" << std::endl;
1141 // COMMENTED DBG LOGS */ std::cout << "\t\t\tall threads finished..." << std::endl;
1142 _backend_threads.clear ();
1143 // COMMENTED DBG LOGS */ std::cout << "\t\t\tthread list cleared..." << std::endl;
1150 WavesAudioBackend::in_process_thread ()
1152 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::in_process_thread ()" << std::endl;
1153 if (pthread_equal (_main_thread, pthread_self()) != 0) {
1156 for (std::vector<pthread_t>::const_iterator i = _backend_threads.begin ();
1157 i != _backend_threads.end (); i++) {
1158 if (pthread_equal (*i, pthread_self ()) != 0) {
1167 WavesAudioBackend::__thread_stack_size ()
1169 // Align stacksize to PTHREAD_STACK_MIN.
1170 #if defined (__APPLE__)
1171 return (((thread_stack_size () - 1) / PTHREAD_STACK_MIN) + 1) * PTHREAD_STACK_MIN;
1172 #elif defined (PLATFORM_WINDOWS)
1173 return thread_stack_size ();
1179 WavesAudioBackend::process_thread_count ()
1181 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::process_thread_count (): returns " << _backend_threads.size () << std::endl;
1182 return _backend_threads.size ();
1187 WavesAudioBackend::_read_audio_data_from_device (const float* input_buffer, pframes_t nframes)
1189 #if defined(PLATFORM_WINDOWS)
1190 const float **buffer = (const float**)input_buffer;
1192 for(std::vector<WavesAudioPort*>::iterator it = _physical_audio_inputs.begin ();
1193 it != _physical_audio_inputs.end();
1196 ARDOUR::copy_vector ((*it)->buffer(), *buffer, nframes);
1200 std::vector<WavesAudioPort*>::iterator it = _physical_audio_inputs.begin ();
1202 // Well, let's de-interleave here:
1203 const Sample* source = input_buffer;
1205 for (uint32_t chann_cnt = 0; (chann_cnt < _max_input_channels) && (it != _physical_audio_inputs.end ()); ++chann_cnt, ++source, ++it) {
1206 const Sample* src = source;
1207 Sample* tgt = (*it)->buffer ();
1209 for (uint32_t frame = 0; frame < nframes; ++frame, src += _max_input_channels, ++tgt) {
1217 WavesAudioBackend::_write_audio_data_to_device (float* output_buffer, pframes_t nframes)
1219 #if defined(_WnonononoINDOWS)
1220 float **buffer = (float**)output_buffer;
1221 size_t copied_bytes = nframes*sizeof(float);
1223 for(std::vector<WavesAudioPort*>::iterator it = _physical_audio_outputs.begin ();
1224 it != _physical_audio_outputs.end();
1227 memcpy(*buffer, (*it)->buffer(), copied_bytes);
1228 //*buffer = (*it)->buffer();
1232 // Well, let's interleave here:
1233 std::vector<WavesAudioPort*>::iterator it = _physical_audio_outputs.begin ();
1234 Sample* target = output_buffer;
1236 for (uint32_t chann_cnt = 0;
1237 (chann_cnt < _max_output_channels) && (it != _physical_audio_outputs.end ());
1238 ++chann_cnt, ++target, ++it) {
1239 const Sample* src = (Sample*) ((*it)->get_buffer (nframes));
1240 Sample* tgt = target;
1241 for (uint32_t frame = 0; frame < nframes; ++frame, tgt += _max_output_channels, ++src) {
1249 static boost::shared_ptr<WavesAudioBackend> __instance;
1252 boost::shared_ptr<AudioBackend>
1253 WavesAudioBackend::__waves_backend_factory (AudioEngine& e)
1255 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__waves_backend_factory ():" << std::endl;
1257 __instance.reset (new WavesAudioBackend (e));
1263 #if defined(PLATFORM_WINDOWS)
1265 uint64_t WavesAudioBackend::__performance_counter_frequency;
1270 WavesAudioBackend::__instantiate (const std::string& arg1, const std::string& arg2)
1272 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__instantiate ():" << "[" << arg1 << "], [" << arg2 << "]" << std::endl;
1273 __instantiated_name = arg1;
1274 #if defined(PLATFORM_WINDOWS)
1276 LARGE_INTEGER Frequency;
1277 QueryPerformanceFrequency(&Frequency);
1278 __performance_counter_frequency = Frequency.QuadPart;
1286 WavesAudioBackend::__deinstantiate ()
1288 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__deinstantiate ():" << std::endl;
1289 __instance.reset ();
1295 WavesAudioBackend::__already_configured ()
1297 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__already_configured ():" << std::endl;
1302 WavesAudioBackend::__available ()
1304 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__available ():" << std::endl;
1310 WavesAudioBackend::private_handle () const
1312 // COMMENTED DBG LOGS */ std::cout << "WHY DO CALL IT: WavesAudioBackend::private_handle: " << std::endl;
1318 WavesAudioBackend::available () const
1320 // COMMENTED SECONDARY DBG LOGS */// std::cout << "WavesAudioBackend::available: " << std::endl;
1326 WavesAudioBackend::my_name () const
1328 // COMMENTED SECONDARY DBG LOGS */// std::cout << "WavesAudioBackend::my_name: " << _port_prefix_name << std::endl;
1329 return __instantiated_name;
1334 WavesAudioBackend::can_monitor_input () const
1336 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::can_monitor_input: " << std::endl;
1340 std::string WavesAudioBackend::__instantiated_name;
1342 AudioBackendInfo WavesAudioBackend::__backend_info = {
1345 #elif PLATFORM_WINDOWS
1349 WavesAudioBackend::__deinstantiate,
1350 WavesAudioBackend::__waves_backend_factory,
1351 WavesAudioBackend::__already_configured,
1352 WavesAudioBackend::__available,