2 Copyright (C) 2013 Valeriy Kamyshniy
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 using namespace ARDOUR;
27 extern "C" __declspec(dllexport) ARDOUR::AudioBackendInfo* descriptor ()
29 extern "C" ARDOURBACKEND_API ARDOUR::AudioBackendInfo* descriptor ()
32 // COMMENTED DBG LOGS */ std::cout << "waves_backend.dll : ARDOUR::AudioBackendInfo* descriptor (): " << std::endl;
33 return &WavesAudioBackend::backend_info ();
36 void WavesAudioBackend::AudioDeviceManagerNotification (NotificationReason reason, void* parameter)
39 case WCMRAudioDeviceManagerClient::DeviceDebugInfo:
40 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::DeviceDebugInfo -- " << (char*)parameter << std::endl;
42 case WCMRAudioDeviceManagerClient::BufferSizeChanged:
43 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::BufferSizeChanged: " << *(uint32_t*)parameter << std::endl;
44 _buffer_size_change(*(uint32_t*)parameter);
46 case WCMRAudioDeviceManagerClient::RequestReset:
47 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::RequestReset" << std::endl;
49 case WCMRAudioDeviceManagerClient::RequestResync:
50 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::RequestResync" << std::endl;
52 case WCMRAudioDeviceManagerClient::SamplingRateChanged:
53 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::SamplingRateChanged: " << *(float*)parameter << std::endl;
54 set_sample_rate(*(float*)parameter);
56 case WCMRAudioDeviceManagerClient::DeviceDroppedSamples:
57 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::DeviceDroppedSamples" << std::endl;
59 case WCMRAudioDeviceManagerClient::DeviceStoppedStreaming:
60 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::DeviceStoppedStreaming" << std::endl;
62 case WCMRAudioDeviceManagerClient::DeviceStartsStreaming:
63 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::DeviceStartsStreaming" << std::endl;
64 _call_thread_init_callback = true; // streaming will be started from device side, just set thread init flag
66 case WCMRAudioDeviceManagerClient::DeviceConnectionLost:
67 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::DeviceConnectionLost" << std::endl;
69 case WCMRAudioDeviceManagerClient::DeviceListChanged:
70 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::DeviceListChanged" << std::endl;
71 _device_list_change();
73 case WCMRAudioDeviceManagerClient::IODeviceDisconnected:
74 std::cout << "------------------------------- WCMRAudioDeviceManagerClient::DeviceListChanged" << std::endl;
75 _device_list_change();
77 case WCMRAudioDeviceManagerClient::AudioCallback:
79 AudioCallbackData* audio_callback_data = (AudioCallbackData*)parameter;
80 _audio_device_callback (
81 audio_callback_data->acdInputBuffer,
82 audio_callback_data->acdOutputBuffer,
83 audio_callback_data->acdFrames,
84 audio_callback_data->acdSampleTime,
85 audio_callback_data->acdCycleStartTimeNanos
96 WavesAudioBackend::WavesAudioBackend (AudioEngine& e, AudioBackendInfo& info)
97 : AudioBackend (e, info)
98 , _audio_device_manager (this)
99 , _midi_device_manager (*this)
101 , _sample_format (FormatFloat)
102 , _interleaved (true)
103 , _input_channels (0)
104 , _max_input_channels (0)
105 , _output_channels (0)
106 , _max_output_channels (0)
109 , _systemic_input_latency (0)
110 , _systemic_output_latency (0)
111 , _call_thread_init_callback (false)
113 , _sample_time_at_cycle_start (0)
114 , _freewheeling (false)
115 , _freewheel_thread_active (false)
116 , _audio_cycle_period_nanos (0)
117 , _dsp_load_accumulator (0)
118 , _dsp_load_history_length(0)
123 WavesAudioBackend::~WavesAudioBackend ()
129 WavesAudioBackend::name () const
132 return std::string ("CoreAudio");
133 #elif PLATFORM_WINDOWS
134 return std::string ("ASIO");
140 WavesAudioBackend::is_realtime () const
147 WavesAudioBackend::requires_driver_selection () const
153 std::vector<std::string>
154 WavesAudioBackend::enumerate_drivers () const
156 // this backend does not suppose driver selection
159 return std::vector<std::string> ();
164 WavesAudioBackend::set_driver (const std::string& /*drivername*/)
166 //Waves audio backend does not suppose driver selection
173 std::vector<AudioBackend::DeviceStatus>
174 WavesAudioBackend::enumerate_devices () const
176 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::enumerate_devices (): " << std::endl;
178 std::vector<DeviceStatus> devicesStatus;
179 const DeviceInfoVec& deviceInfoList = _audio_device_manager.DeviceInfoList();
181 for (DeviceInfoVecConstIter deviceInfoIter = deviceInfoList.begin (); deviceInfoIter != deviceInfoList.end (); ++deviceInfoIter) {
182 // COMMENTED DBG LOGS */ std::cout << "\t Device found: " << (*deviceInfoIter)->m_DeviceName << std::endl;
183 devicesStatus.push_back (DeviceStatus ((*deviceInfoIter)->m_DeviceName, true));
186 return devicesStatus;
191 WavesAudioBackend::available_sample_rates (const std::string& device_name) const
193 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::available_sample_rates (): [" << device_name << "]" << std::endl;
196 WTErr err = _audio_device_manager.GetDeviceInfoByName(device_name, devInfo);
199 std::cerr << "WavesAudioBackend::available_sample_rates (): Failed to find device [" << device_name << "]" << std::endl;
200 return std::vector<float> ();
203 // COMMENTED DBG LOGS */ std::cout << "\tFound " << devInfo.m_AvailableSampleRates.size () << " sample rates for " << device_name << ":";
205 std::vector<float> sample_rates (devInfo.m_AvailableSampleRates.begin (), devInfo.m_AvailableSampleRates.end ());
207 // COMMENTED DBG LOGS */ for (std::vector<float>::iterator i = sample_rates.begin (); i != sample_rates.end (); ++i) std::cout << " " << *i; std::cout << std::endl;
213 float WavesAudioBackend::default_sample_rate () const
215 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::default_sample_rate (): " << AudioBackend::default_sample_rate () << std::endl;
216 return AudioBackend::default_sample_rate ();
220 std::vector<uint32_t>
221 WavesAudioBackend::available_buffer_sizes (const std::string& device_name) const
223 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::available_buffer_sizes (): [" << device_name << "]" << std::endl;
228 retVal = _audio_device_manager.GetDeviceBufferSizes(device_name, bs);
230 if (retVal != eNoErr) {
231 std::cerr << "WavesAudioBackend::available_buffer_sizes (): Failed to get buffer size for device [" << device_name << "]" << std::endl;
232 return std::vector<uint32_t> ();
235 std::vector<uint32_t> buffer_sizes (bs.begin (), bs.end ());
237 // COMMENTED DBG LOGS */ std::cout << "\tFound " << buffer_sizes.size () << " buffer sizes for " << device_name << ":";
238 // 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;
245 WavesAudioBackend::available_input_channel_count (const std::string& device_name) const
248 WTErr err = _audio_device_manager.GetDeviceInfoByName(device_name, devInfo);
251 std::cerr << "WavesAudioBackend::available_input_channel_count (): Failed to find device [" << device_name << "]" << std::endl;
255 uint32_t num_of_input_channels = devInfo.m_MaxInputChannels;
257 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::available_input_channel_count (): " << num_of_input_channels << std::endl;
258 return num_of_input_channels;
263 WavesAudioBackend::available_output_channel_count (const std::string& device_name) const
266 WTErr err = _audio_device_manager.GetDeviceInfoByName(device_name, devInfo);
269 std::cerr << "WavesAudioBackend::available_output_channel_count (): Failed to find device [" << device_name << "]" << std::endl;
273 uint32_t num_of_output_channels = devInfo.m_MaxOutputChannels;
275 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::available_output_channel_count (): " << num_of_output_channels << std::endl;
277 return num_of_output_channels;
282 WavesAudioBackend::can_change_sample_rate_when_running () const
284 // VERIFY IT CAREFULLY
290 WavesAudioBackend::can_change_buffer_size_when_running () const
292 // VERIFY IT CAREFULLY
298 WavesAudioBackend::set_device_name (const std::string& device_name)
300 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_device_name (): " << device_name << std::endl;
302 if (_ports.size ()) {
303 std::cerr << "WavesAudioBackend::set_device_name (): There are unregistered ports left after [" << (_device ? _device->DeviceName () : std::string ("<NULL>")) << "]!" << std::endl;
304 for (size_t i = 0; i < _ports.size (); ++i) {
305 std::cerr << "\t[" << _ports[i]->name () << "]!" << std::endl;
310 if (_device && _device->Streaming () ) {
311 std::cerr << "WavesAudioBackend::set_device_name (): [" << _device->DeviceName () << "] is streaming! Current device must be stopped before setting another device as current" << std::endl;
314 // we must have only one device initialized at a time
315 // stop current device first
318 retVal = _device->SetActive (false);
319 if (retVal != eNoErr) {
320 std::cerr << "WavesAudioBackend::set_device_name (): [" << _device->DeviceName () << "]->SetActive (false) failed!" << std::endl;
326 _audio_device_manager.DestroyCurrentDevice();
329 WCMRAudioDevice * device = _audio_device_manager.InitNewCurrentDevice(device_name);
332 std::cerr << "WavesAudioBackend::set_device_name (): Failed to initialize device [" << device_name << "]!" << std::endl;
337 retVal = device->SetActive (true);
338 if (retVal != eNoErr) {
339 std::cerr << "WavesAudioBackend::set_device_name (): [" << device->DeviceName () << "]->SetActive () failed!" << std::endl;
349 WavesAudioBackend::drop_device()
355 wtErr = _device->SetActive (false);
356 if (wtErr != eNoErr) {
357 std::cerr << "WavesAudioBackend::drop_device (): [" << _device->DeviceName () << "]->SetActive () failed!" << std::endl;
362 _audio_device_manager.DestroyCurrentDevice();
370 WavesAudioBackend::set_sample_rate (float sample_rate)
372 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_sample_rate (): " << sample_rate << std::endl;
374 WTErr retVal = eNoErr;
377 std::cerr << "WavesAudioBackend::set_sample_rate (): No device is set!" << std::endl;
382 bool device_needs_restart = _device->Streaming ();
384 if (device_needs_restart) {
385 retVal = _device->SetStreaming (false);
386 // COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->_device->SetStreaming (false);"<< std::endl;
387 if (retVal != eNoErr) {
388 std::cerr << "WavesAudioBackend::set_sample_rate (): [" << _device->DeviceName () << "]->SetStreaming (false) failed (" << retVal << ") !" << std::endl;
393 retVal = _device->SetCurrentSamplingRate ((int)sample_rate);
395 if (retVal != eNoErr) {
396 std::cerr << "WavesAudioBackend::set_sample_rate (): [" << _device->DeviceName() << "]->SetCurrentSamplingRate ((int)" << sample_rate << ") failed (" << retVal << ") !" << std::endl;
400 _sample_rate_change(sample_rate);
402 if (device_needs_restart) {
403 // COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetStreaming (true);"<< std::endl;
404 _call_thread_init_callback = true;
405 retVal = _device->SetStreaming (true);
406 if (retVal != eNoErr) {
407 std::cerr << "WavesAudioBackend::set_sample_rate (): [" << _device->DeviceName () << "]->SetStreaming (true) failed (" << retVal << ") !" << std::endl;
416 WavesAudioBackend::set_buffer_size (uint32_t buffer_size)
418 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_buffer_size (" << buffer_size << "):"<< std::endl;
420 WTErr retVal = eNoErr;
423 std::cerr << "WavesAudioBackend::set_buffer_size (): No device is set!" << std::endl;
427 bool device_needs_restart = _device->Streaming ();
429 if (device_needs_restart) {
430 retVal = _device->SetStreaming (false);
431 // COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetStreaming (false);"<< std::endl;
432 if (retVal != eNoErr) {
433 std::cerr << "WavesAudioBackend::set_buffer_size (): [" << _device->DeviceName () << "]->SetStreaming (false) failed (" << retVal << ") !" << std::endl;
438 retVal = _device->SetCurrentBufferSize (buffer_size);
440 if (retVal != eNoErr) {
441 std::cerr << "WavesAudioBackend::set_buffer_size (): [" << _device->DeviceName() << "]->SetCurrentBufferSize (" << buffer_size << ") failed (" << retVal << ") !" << std::endl;
445 _buffer_size_change(buffer_size);
447 if (device_needs_restart) {
448 // COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetStreaming (true);"<< std::endl;
449 _call_thread_init_callback = true;
450 retVal = _device->SetStreaming (true);
451 if (retVal != eNoErr) {
452 std::cerr << "WavesAudioBackend::set_buffer_size (): [" << _device->DeviceName () << "]->SetStreaming (true) failed (" << retVal << ") !" << std::endl;
462 WavesAudioBackend::set_sample_format (SampleFormat sample_format)
464 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_sample_format (): " << sample_format << std::endl;
466 _sample_format = sample_format;
471 WavesAudioBackend::_reset_device (uint32_t buffer_size, float sample_rate)
473 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_reset_device (" << buffer_size <<", " << sample_rate << "):" << std::endl;
475 WTErr retVal = eNoErr;
478 std::cerr << "WavesAudioBackend::set_buffer_size (): No device is set!" << std::endl;
482 bool device_needs_restart = _device->Streaming ();
484 if (device_needs_restart) {
485 retVal = _device->SetStreaming (false);
486 // COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetStreaming (false);"<< std::endl;
487 if (retVal != eNoErr) {
488 std::cerr << "WavesAudioBackend::_reset_device (): [" << _device->DeviceName () << "]->SetStreaming (false) failed (" << retVal << ") !" << std::endl;
491 retVal = _device->SetActive (false);
492 // COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetActive (false);"<< std::endl;
493 if (retVal != eNoErr) {
494 std::cerr << "WavesAudioBackend::_reset_device (): [" << _device->DeviceName () << "]->SetActive (false) failed (" << retVal << ") !" << std::endl;
499 retVal = _device->UpdateDeviceInfo ();
500 if (retVal != eNoErr) {
501 std::cerr << "WavesAudioBackend::_reset_device (): [" << _device->DeviceName() << "]->UpdateDeviceInfo () failed (" << retVal << ") !" << std::endl;
505 if (buffer_size != 0)
507 retVal = _device->SetCurrentBufferSize (buffer_size);
509 if (retVal != eNoErr) {
510 std::cerr << "WavesAudioBackend::_reset_device (): [" << _device->DeviceName() << "]->SetCurrentBufferSize (" << buffer_size << ") failed (" << retVal << ") !" << std::endl;
514 _buffer_size = buffer_size;
518 uint32_t current_buffer_size = _device->CurrentBufferSize();
519 // COMMENTED DBG LOGS */ std::cout << "\t\tcurrent_buffer_size: " << current_buffer_size << std::endl;
520 // COMMENTED DBG LOGS */ std::cout << "\t\t _buffer_size: " << _buffer_size << std::endl;
521 if(_buffer_size != current_buffer_size)
523 _buffer_size = current_buffer_size;
524 engine.buffer_size_change (_buffer_size);
525 // COMMENTED DBG LOGS */ std::cout << "\t\tengine.buffer_size_change (" << buffer_size <<")" << std::endl;
529 if(sample_rate > 0.0)
531 retVal = _device->SetCurrentSamplingRate ((int)sample_rate);
533 if (retVal != eNoErr) {
534 std::cerr << "WavesAudioBackend::set_sample_rate (): [" << _device->DeviceName() << "]->SetCurrentSamplingRate ((int)" << sample_rate << ") failed (" << retVal << ") !" << std::endl;
537 _sample_rate = sample_rate;
541 float current_sample_rate = _device->CurrentSamplingRate();
542 // COMMENTED DBG LOGS */ std::cout << "\t\tcurrent_sample_rate: " << current_sample_rate << std::endl;
543 // COMMENTED DBG LOGS */ std::cout << "\t\t _sample_rate: " << _sample_rate << std::endl;
544 if(_sample_rate != current_sample_rate)
546 _sample_rate = current_sample_rate;
547 engine.sample_rate_change (_sample_rate);
548 // COMMENTED DBG LOGS */ std::cout << "\t\tengine.sample_rate_change (" << _sample_rate <<")" << std::endl;
552 _init_dsp_load_history();
554 if (device_needs_restart) {
555 // COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetActive (true);"<< std::endl;
556 retVal = _device->SetActive (true);
557 if (retVal != eNoErr) {
558 std::cerr << "WavesAudioBackend::_reset_device (): [" << _device->DeviceName () << "]->SetActive (true) failed (" << retVal << ") !" << std::endl;
561 // COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetStreaming (true);"<< std::endl;
562 _call_thread_init_callback = true;
563 retVal = _device->SetStreaming (true);
564 if (retVal != eNoErr) {
565 std::cerr << "WavesAudioBackend::_reset_device (): [" << _device->DeviceName () << "]->SetStreaming (true) failed (" << retVal << ") !" << std::endl;
575 WavesAudioBackend::_buffer_size_change (uint32_t new_buffer_size)
577 _buffer_size = new_buffer_size;
578 _init_dsp_load_history();
579 return engine.buffer_size_change (new_buffer_size);
584 WavesAudioBackend::_sample_rate_change (float new_sample_rate)
586 _sample_rate = new_sample_rate;
587 _init_dsp_load_history();
588 return engine.sample_rate_change (new_sample_rate);
593 WavesAudioBackend::_device_list_change ()
595 // requires GZ changes for device list update
596 // return engine.device_list_change ();
602 WavesAudioBackend::set_interleaved (bool yn)
604 /*you can ignore them totally*/
611 WavesAudioBackend::set_input_channels (uint32_t input_channels)
613 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_input_channels (): " << input_channels << std::endl;
615 _input_channels = input_channels;
621 WavesAudioBackend::set_output_channels (uint32_t output_channels)
623 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_output_channels (): " << output_channels << std::endl;
625 _output_channels = output_channels;
631 WavesAudioBackend::device_name () const
636 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::device_name (): " << _device->DeviceName () << std::endl;
638 return _device->DeviceName ();
643 WavesAudioBackend::sample_rate () const
645 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::sample_rate (): " << std::endl;
648 std::cerr << "WavesAudioBackend::sample_rate (): No device is set!" << std::endl;
652 int sample_rate = _device->CurrentSamplingRate ();
654 // COMMENTED DBG LOGS */ std::cout << "\t[" << _device->DeviceName () << "]->CurrentSamplingRate () returned " << sample_rate << std::endl;
656 return (float)sample_rate;
661 WavesAudioBackend::buffer_size () const
664 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::buffer_size (): " << std::endl;
667 std::cerr << "WavesAudioBackend::buffer_size (): No device is set!" << std::endl;
671 int size = _device->CurrentBufferSize ();
673 // COMMENTED DBG LOGS */ std::cout << "\t[" << _device->DeviceName () << "]->CurrentBufferSize () returned " << size << std::endl;
675 return (uint32_t)size;
680 WavesAudioBackend::sample_format () const
682 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::sample_format ()" << std::endl;
683 return _sample_format;
688 WavesAudioBackend::interleaved () const
690 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::interleaved ()" << std::endl;
697 WavesAudioBackend::input_channels () const
699 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::input_channels ()" << std::endl;
701 return _input_channels;
706 WavesAudioBackend::output_channels () const
708 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::output_channels ()" << std::endl;
710 return _output_channels;
715 WavesAudioBackend::control_app_name () const
717 std::string app_name = "";
719 if (_device && !dynamic_cast<WCMRNativeAudioNoneDevice*> (_device)) {
720 app_name = "PortAudioMayKnowIt";
728 WavesAudioBackend::launch_control_app ()
730 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::launch_control_app ()" << std::endl;
732 std::cerr << "WavesAudioBackend::launch_control_app (): No device is set!" << std::endl;
736 WTErr err = _device->ShowConfigPanel (NULL);
739 std::cerr << "WavesAudioBackend::launch_control_app (): [" << _device->DeviceName () << "]->ShowConfigPanel () failed (" << err << ")!" << std::endl;
742 // COMMENTED DBG LOGS */ else std::cout << "WavesAudioBackend::launch_control_app (): [" << _device->DeviceName () << "]->ShowConfigPanel () successfully launched!" << std::endl;
747 WavesAudioBackend::_start (bool for_latency_measurement)
749 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_start ()" << std::endl;
752 std::cerr << "WavesAudioBackend::_start (): No device is set!" << std::endl;
756 if (_register_system_audio_ports () != 0) {
757 std::cerr << "WavesAudioBackend::_start (): _register_system_audio_ports () failed!" << std::endl;
762 if (_midi_device_manager.start () != 0) {
763 std::cerr << "WavesAudioBackend::_start (): _midi_device_manager.start () failed!" << std::endl;
766 if (_register_system_midi_ports () != 0) {
767 std::cerr << "WavesAudioBackend::_start (): _register_system_midi_ports () failed!" << std::endl;
772 if (engine.reestablish_ports () != 0) {
773 std::cerr << "WavesAudioBackend::_start (): engine.reestablish_ports () failed!" << std::endl;
776 manager.registration_callback ();
778 _call_thread_init_callback = true;
779 WTErr retVal = _device->SetStreaming (true);
780 if (retVal != eNoErr) {
781 std::cerr << "WavesAudioBackend::_start (): [" << _device->DeviceName () << "]->SetStreaming () failed!" << std::endl;
786 if (_midi_device_manager.stream (true)) {
787 std::cerr << "WavesAudioBackend::_start (): _midi_device_manager.stream (true) failed!" << std::endl;
797 WavesAudioBackend::_audio_device_callback (const float* input_buffer,
798 float* output_buffer,
799 unsigned long nframes,
800 pframes_t sample_time,
801 uint64_t cycle_start_time_nanos)
803 uint64_t dsp_start_time_nanos = __get_time_nanos();
804 // COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::_audio_device_callback ():" << _device->DeviceName () << std::endl;
805 _sample_time_at_cycle_start = sample_time;
806 _cycle_start_time_nanos = cycle_start_time_nanos;
808 if (_buffer_size != nframes) {
809 // COMMENTED DBG LOGS */ std::cout << "\tAudioEngine::thread_init_callback() buffer size and nframes are not equal: " << _buffer_size << "!=" << nframes << std::endl;
813 _read_audio_data_from_device (input_buffer, nframes);
814 _read_midi_data_from_devices ();
816 if (_call_thread_init_callback) {
817 _call_thread_init_callback = false;
818 // COMMENTED DBG LOGS */ std::cout << "\tAudioEngine::thread_init_callback() invoked for " << std::hex << pthread_self() << std::dec << " !" << std::endl;
819 AudioEngine::thread_init_callback (this);
822 engine.process_callback (nframes);
824 _write_audio_data_to_device (output_buffer, nframes);
825 _write_midi_data_to_devices (nframes);
827 uint64_t dsp_end_time_nanos = __get_time_nanos();
829 _dsp_load_accumulator -= *_dsp_load_history.begin();
830 _dsp_load_history.pop_front();
831 uint64_t dsp_load_nanos = dsp_end_time_nanos - dsp_start_time_nanos;
832 _dsp_load_accumulator += dsp_load_nanos;
833 _dsp_load_history.push_back(dsp_load_nanos);
840 WavesAudioBackend::stop ()
842 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::stop ()" << std::endl;
844 WTErr wtErr = eNoErr;
847 // COMMENTED DBG LOGS */ std::cout << "\t[" << _device->DeviceName () << "]" << std::endl;
850 wtErr = _device->SetStreaming (false);
851 if (wtErr != eNoErr) {
852 std::cerr << "WavesAudioBackend::stop (): [" << _device->DeviceName () << "]->SetStreaming () failed!" << std::endl;
857 _midi_device_manager.stop ();
859 _unregister_system_audio_ports ();
860 _unregister_system_midi_ports ();
867 WavesAudioBackend::freewheel (bool start_stop)
869 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::freewheel (" << start_stop << "):" << std::endl;
871 if (start_stop != _freewheeling) {
872 if (start_stop == true) {
873 WTErr retval = _device->SetStreaming (false);
874 if (retval != eNoErr) {
875 std::cerr << "WavesAudioBackend::freewheel (): [" << _device->DeviceName () << "]->SetStreaming () failed!" << std::endl;
878 _call_thread_init_callback = true;
879 _freewheel_thread ();
880 engine.freewheel_callback (start_stop);
883 _freewheel_thread_active = false; // stop _freewheel_thread ()
884 engine.freewheel_callback (start_stop);
885 _call_thread_init_callback = true;
886 WTErr retval = _device->SetStreaming (true);
887 if (retval != eNoErr) {
888 std::cerr << "WavesAudioBackend::freewheel (): [" << _device->DeviceName () << "]->SetStreaming () failed!" << std::endl;
892 _freewheeling = start_stop;
894 // already doing what has been asked for
900 WavesAudioBackend::_freewheel_thread ()
902 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_freewheel_thread ():" << std::endl;
903 if (!_freewheel_thread_active) { // Lets create it
905 // COMMENTED DBG LOGS */ std::cout << "\tCreating the thread _freewheel_thread () . . ." << std::endl;
906 pthread_attr_t attributes;
909 ThreadData* thread_data = new ThreadData (this, boost::bind (&WavesAudioBackend::_freewheel_thread, this), __thread_stack_size ());
911 if (pthread_attr_init (&attributes)) {
912 std::cerr << "WavesAudioBackend::freewheel_thread (): pthread_attr_init () failed!" << std::endl;
916 if (pthread_attr_setstacksize (&attributes, __thread_stack_size ())) {
917 std::cerr << "WavesAudioBackend::freewheel_thread (): pthread_attr_setstacksize () failed!" << std::endl;
921 _freewheel_thread_active = false;
922 if ((pthread_create (&thread_id, &attributes, __start_process_thread, thread_data))) {
923 _freewheel_thread_active = true;
924 std::cerr << "WavesAudioBackend::freewheel_thread (): pthread_create () failed!" << std::endl;
928 // COMMENTED DBG LOGS */ std::cout << "\t. . . _freewheel_thread () complete." << std::endl;
932 if (_call_thread_init_callback) {
933 _call_thread_init_callback = false;
934 AudioEngine::thread_init_callback (this);
937 while (_freewheel_thread_active) {
938 engine.process_callback (_buffer_size);
940 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_freewheel_thread (): FINISHED" << std::endl;
946 WavesAudioBackend::dsp_load () const
948 // COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::dsp_load (): " << std::endl;
951 std::cerr << "WavesAudioBackend::cpu_load (): No device is set!" << std::endl;
955 float average_dsp_load = (float)_dsp_load_accumulator/_dsp_load_history_length;
957 return ( average_dsp_load / _audio_cycle_period_nanos)*100.0;
962 WavesAudioBackend::_init_dsp_load_history()
964 if((_sample_rate <= 0.0) || (_buffer_size <= 0.0)) {
968 _audio_cycle_period_nanos = ((uint64_t)1000000000L * _buffer_size) / _sample_rate;
970 _dsp_load_accumulator = 0;
972 _dsp_load_history_length = (_sample_rate + _buffer_size - 1) / _buffer_size;
973 // COMMENTED DBG LOGS */ std::cout << "\t\t_dsp_load_history_length = " << _dsp_load_history_length << std::endl;
974 _dsp_load_history = std::list<uint64_t>(_dsp_load_history_length, 0);
979 WavesAudioBackend::transport_start ()
981 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::transport_start (): " << std::endl;
986 WavesAudioBackend::transport_stop ()
988 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::transport_stop (): " << std::endl;
993 WavesAudioBackend::transport_state () const
995 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::transport_state (): " << std::endl;
996 return TransportStopped;
1001 WavesAudioBackend::transport_locate (framepos_t pos)
1003 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::transport_locate (" << pos << "): " << std::endl;
1008 WavesAudioBackend::transport_frame () const
1010 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::transport_frame (): " << std::endl;
1016 WavesAudioBackend::set_time_master (bool yn)
1018 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_time_master (): " << yn << std::endl;
1024 WavesAudioBackend::usecs_per_cycle () const
1026 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::usecs_per_cycle (): " << std::endl;
1027 return (1000000 * _sample_rate) / _buffer_size;
1032 WavesAudioBackend::raw_buffer_size (DataType data_type)
1034 // COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::raw_buffer_size (" << data_type.to_string () << "): " << std::endl;
1035 switch (data_type) {
1036 case DataType::AUDIO:
1037 return WavesAudioPort::MAX_BUFFER_SIZE_BYTES;
1040 case DataType::MIDI:
1041 return WavesMidiPort::MAX_BUFFER_SIZE_BYTES;
1045 std::cerr << "WavesAudioBackend::raw_buffer_size (): unexpected data type (" << (uint32_t)data_type <<")!" << std::endl;
1053 WavesAudioBackend::sample_time ()
1055 // WARNING: This is approximate calculation. Implementation of accurate calculation is pending.
1056 // http://kokkinizita.linuxaudio.org/papers/usingdll.pdf
1058 return _sample_time_at_cycle_start + ((__get_time_nanos () - _cycle_start_time_nanos)*_sample_rate)/1000000000L;
1063 WavesAudioBackend::__get_time_nanos ()
1066 // here we exploit the time counting API which is used by the WCMRCoreAudioDeviceManager. However,
1067 // the API should be a part of WCMRCoreAudioDeviceManager to give a chance of being tied to the
1068 // audio device transport timeß.
1069 return AudioConvertHostTimeToNanos (AudioGetCurrentHostTime ());
1071 #elif PLATFORM_WINDOWS
1072 LARGE_INTEGER Count;
1073 QueryPerformanceCounter (&Count);
1074 return uint64_t ((Count.QuadPart * 1000000000L / __performance_counter_frequency));
1080 WavesAudioBackend::sample_time_at_cycle_start ()
1082 // COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::sample_time_at_cycle_start (): " << _sample_time_at_cycle_start << std::endl;
1083 return _sample_time_at_cycle_start;
1088 WavesAudioBackend::samples_since_cycle_start ()
1090 pframes_t diff_sample_time;
1091 diff_sample_time = sample_time () - _sample_time_at_cycle_start;
1092 // COMMENTED DBG LOGS */ std::cout << "samples_since_cycle_start: " << diff_sample_time << std::endl;
1094 return diff_sample_time;
1099 WavesAudioBackend::get_sync_offset (pframes_t& /*offset*/) const
1101 // COMMENTED DBG LOGS */ std::cout << "get_sync_offset: false" << std::endl;
1108 WavesAudioBackend::create_process_thread (boost::function<void ()> func)
1110 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::create_process_thread ():" << std::endl;
1112 pthread_attr_t attributes;
1113 size_t stacksize_aligned;
1114 pthread_t thread_id;
1116 // Align stacksize to PTHREAD_STACK_MIN.
1117 stacksize_aligned = __thread_stack_size ();
1119 ThreadData* td = new ThreadData (this, func, stacksize_aligned);
1121 if ((retVal = pthread_attr_init (&attributes))) {
1122 std::cerr << "Cannot set thread attr init res = " << retVal << endmsg;
1126 if ((retVal = pthread_attr_setstacksize (&attributes, stacksize_aligned))) {
1127 std::cerr << "Cannot set thread stack size (" << stacksize_aligned << ") res = " << retVal << endmsg;
1131 if ((retVal = pthread_create (&thread_id, &attributes, __start_process_thread, td))) {
1132 std::cerr << "Cannot create thread res = " << retVal << endmsg;
1136 _backend_threads.push_back (thread_id);
1137 // COMMENTED DBG LOGS */ std::cout << "\t\t\t. . . thread " << std::hex << thread_id << std::dec << " has been created" << std::endl;
1144 WavesAudioBackend::__start_process_thread (void* arg)
1146 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__start_process_thread ():" << std::endl;
1147 ThreadData* td = reinterpret_cast<ThreadData*> (arg);
1148 boost::function<void ()> f = td->f;
1156 WavesAudioBackend::join_process_threads ()
1158 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::join_process_thread ()" << std::endl;
1161 for (std::vector<pthread_t>::const_iterator i = _backend_threads.begin ();
1162 i != _backend_threads.end ();
1164 // COMMENTED DBG LOGS */ std::cout << "\t\t\tstopping thread " << std::hex << *i << std::dec << "...\n";
1167 if (pthread_join (*i, &status) != 0) {
1168 std::cerr << "AudioEngine: cannot stop process thread !" << std::endl;
1171 // COMMENTED DBG LOGS */ std::cout << "\t\t\t\t...done" << std::endl;
1173 // COMMENTED DBG LOGS */ std::cout << "\t\t\tall threads finished..." << std::endl;
1174 _backend_threads.clear ();
1175 // COMMENTED DBG LOGS */ std::cout << "\t\t\tthread list cleared..." << std::endl;
1182 WavesAudioBackend::in_process_thread ()
1184 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::in_process_thread ()" << std::endl;
1185 for (std::vector<pthread_t>::const_iterator i = _backend_threads.begin ();
1186 i != _backend_threads.end (); i++) {
1187 if (pthread_equal (*i, pthread_self ()) != 0) {
1196 WavesAudioBackend::__thread_stack_size ()
1198 // Align stacksize to PTHREAD_STACK_MIN.
1199 #if defined (__APPLE__)
1200 return (((thread_stack_size () - 1) / PTHREAD_STACK_MIN) + 1) * PTHREAD_STACK_MIN;
1201 #elif defined (PLATFORM_WINDOWS)
1202 return thread_stack_size ();
1208 WavesAudioBackend::process_thread_count ()
1210 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::process_thread_count (): returns " << _backend_threads.size () << std::endl;
1211 return _backend_threads.size ();
1216 WavesAudioBackend::_read_audio_data_from_device (const float* input_buffer, pframes_t nframes)
1218 #if defined(PLATFORM_WINDOWS)
1219 const float **buffer = (const float**)input_buffer;
1220 size_t copied_bytes = nframes*sizeof(float*);
1222 for(std::vector<WavesAudioPort*>::iterator it = _physical_audio_inputs.begin ();
1223 it != _physical_audio_inputs.end();
1226 memcpy((*it)->buffer(), *buffer, copied_bytes);
1230 std::vector<WavesAudioPort*>::iterator it = _physical_audio_inputs.begin ();
1232 // Well, let's de-interleave here:
1233 const Sample* source = input_buffer;
1235 for (uint32_t chann_cnt = 0; (chann_cnt < _max_input_channels) && (it != _physical_audio_inputs.end ()); ++chann_cnt, ++source, ++it) {
1236 const Sample* src = source;
1237 Sample* tgt = (*it)->buffer ();
1239 for (uint32_t frame = 0; frame < nframes; ++frame, src += _max_input_channels, ++tgt) {
1247 WavesAudioBackend::_write_audio_data_to_device (float* output_buffer, pframes_t nframes)
1249 #if defined(_WnonononoINDOWS)
1250 float **buffer = (float**)output_buffer;
1251 size_t copied_bytes = nframes*sizeof(float);
1253 for(std::vector<WavesAudioPort*>::iterator it = _physical_audio_outputs.begin ();
1254 it != _physical_audio_outputs.end();
1257 memcpy(*buffer, (*it)->buffer(), copied_bytes);
1258 //*buffer = (*it)->buffer();
1262 // Well, let's interleave here:
1263 std::vector<WavesAudioPort*>::iterator it = _physical_audio_outputs.begin ();
1264 Sample* target = output_buffer;
1266 for (uint32_t chann_cnt = 0;
1267 (chann_cnt < _max_output_channels) && (it != _physical_audio_outputs.end ());
1268 ++chann_cnt, ++target, ++it) {
1269 const Sample* src = (Sample*) ((*it)->get_buffer (nframes));
1270 Sample* tgt = target;
1271 for (uint32_t frame = 0; frame < nframes; ++frame, tgt += _max_output_channels, ++src) {
1279 static boost::shared_ptr<WavesAudioBackend> __instance;
1282 boost::shared_ptr<AudioBackend>
1283 WavesAudioBackend::__waves_backend_factory (AudioEngine& e)
1285 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__waves_backend_factory ():" << std::endl;
1287 __instance.reset (new WavesAudioBackend (e, __backend_info));
1293 #if defined(PLATFORM_WINDOWS)
1295 uint64_t WavesAudioBackend::__performance_counter_frequency;
1300 WavesAudioBackend::__instantiate (const std::string& arg1, const std::string& arg2)
1302 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__instantiate ():" << "[" << arg1 << "], [" << arg2 << "]" << std::endl;
1303 __instantiated_name = arg1;
1304 #if defined(PLATFORM_WINDOWS)
1306 LARGE_INTEGER Frequency;
1307 QueryPerformanceFrequency(&Frequency);
1308 __performance_counter_frequency = Frequency.QuadPart;
1309 std::cout << "__performance_counter_frequency:" << __performance_counter_frequency << std::endl;
1317 WavesAudioBackend::__deinstantiate ()
1319 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__deinstantiate ():" << std::endl;
1320 __instance.reset ();
1326 WavesAudioBackend::__already_configured ()
1328 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__already_configured ():" << std::endl;
1334 WavesAudioBackend::private_handle () const
1336 // COMMENTED DBG LOGS */ std::cout << "WHY DO CALL IT: WavesAudioBackend::private_handle: " << std::endl;
1342 WavesAudioBackend::available () const
1344 // COMMENTED SECONDARY DBG LOGS */// std::cout << "WavesAudioBackend::available: " << std::endl;
1350 WavesAudioBackend::my_name () const
1352 // COMMENTED SECONDARY DBG LOGS */// std::cout << "WavesAudioBackend::my_name: " << _port_prefix_name << std::endl;
1353 return __instantiated_name;
1358 WavesAudioBackend::can_monitor_input () const
1360 // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::can_monitor_input: " << std::endl;
1364 std::string WavesAudioBackend::__instantiated_name;
1366 AudioBackendInfo WavesAudioBackend::__backend_info = {
1369 #elif PLATFORM_WINDOWS
1373 WavesAudioBackend::__deinstantiate,
1374 WavesAudioBackend::__waves_backend_factory,
1375 WavesAudioBackend::__already_configured,