2014-04-30 13:46:41 -04:00
/*
2014-09-30 20:35:31 -04:00
Copyright ( C ) 2014 Waves Audio Ltd .
2014-04-30 13:46:41 -04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
2014-10-07 16:09:29 -04:00
( at your option ) any later version .
2014-04-30 13:46:41 -04:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "waves_audiobackend.h"
# include "waves_audioport.h"
# include "waves_midiport.h"
2015-05-12 21:07:09 -04:00
# include "ardour/runtime_functions.h"
2015-07-02 03:16:44 -04:00
# ifdef COMPILER_MSVC
# include <windows.h>
# define sleep(X) Sleep((X) * 1000)
// JE - Perhaps we should be using Glib::usleep() here, rather than sleep()?? But
// that would make the Waves backend dependent on Glib (which is isn't, currently).
# endif
2014-04-30 13:46:41 -04:00
using namespace ARDOUR ;
2014-10-02 18:46:34 -04:00
# if defined __MINGW64__ || defined __MINGW32__
2014-05-01 09:14:25 -04:00
extern " C " __declspec ( dllexport ) ARDOUR : : AudioBackendInfo * descriptor ( )
# else
extern " C " ARDOURBACKEND_API ARDOUR : : AudioBackendInfo * descriptor ( )
# endif
{
// COMMENTED DBG LOGS */ std::cout << "waves_backend.dll : ARDOUR::AudioBackendInfo* descriptor (): " << std::endl;
return & WavesAudioBackend : : backend_info ( ) ;
}
2014-04-30 13:46:41 -04:00
void WavesAudioBackend : : AudioDeviceManagerNotification ( NotificationReason reason , void * parameter )
{
switch ( reason ) {
case WCMRAudioDeviceManagerClient : : DeviceDebugInfo :
std : : cout < < " ------------------------------- WCMRAudioDeviceManagerClient::DeviceDebugInfo -- " < < ( char * ) parameter < < std : : endl ;
2014-09-30 20:35:31 -04:00
break ;
2014-04-30 13:46:41 -04:00
case WCMRAudioDeviceManagerClient : : BufferSizeChanged :
2015-05-14 10:52:12 -04:00
std : : cout < < " ------------------------------- WCMRAudioDeviceManagerClient::BufferSizeChanged: " < < * ( int * ) parameter < < std : : endl ;
_buffer_size_change ( * ( int * ) parameter ) ;
2014-09-30 20:35:31 -04:00
break ;
2014-04-30 13:46:41 -04:00
case WCMRAudioDeviceManagerClient : : RequestReset :
std : : cout < < " ------------------------------- WCMRAudioDeviceManagerClient::RequestReset " < < std : : endl ;
2014-09-30 20:35:31 -04:00
engine . request_backend_reset ( ) ;
2014-04-30 13:46:41 -04:00
break ;
case WCMRAudioDeviceManagerClient : : RequestResync :
std : : cout < < " ------------------------------- WCMRAudioDeviceManagerClient::RequestResync " < < std : : endl ;
break ;
case WCMRAudioDeviceManagerClient : : SamplingRateChanged :
std : : cout < < " ------------------------------- WCMRAudioDeviceManagerClient::SamplingRateChanged: " < < * ( float * ) parameter < < std : : endl ;
2015-05-14 10:52:12 -04:00
_sample_rate_change ( * ( float * ) parameter ) ;
2014-04-30 13:46:41 -04:00
break ;
2014-09-30 20:35:31 -04:00
case WCMRAudioDeviceManagerClient : : Dropout :
std : : cout < < " ------------------------------- WCMRAudioDeviceManagerClient::Dropout: " < < std : : endl ;
break ;
2014-04-30 13:46:41 -04:00
case WCMRAudioDeviceManagerClient : : DeviceDroppedSamples :
std : : cout < < " ------------------------------- WCMRAudioDeviceManagerClient::DeviceDroppedSamples " < < std : : endl ;
break ;
case WCMRAudioDeviceManagerClient : : DeviceStoppedStreaming :
std : : cout < < " ------------------------------- WCMRAudioDeviceManagerClient::DeviceStoppedStreaming " < < std : : endl ;
break ;
case WCMRAudioDeviceManagerClient : : DeviceStartsStreaming :
std : : cout < < " ------------------------------- WCMRAudioDeviceManagerClient::DeviceStartsStreaming " < < std : : endl ;
_call_thread_init_callback = true ; // streaming will be started from device side, just set thread init flag
break ;
case WCMRAudioDeviceManagerClient : : DeviceConnectionLost :
std : : cout < < " ------------------------------- WCMRAudioDeviceManagerClient::DeviceConnectionLost " < < std : : endl ;
break ;
case WCMRAudioDeviceManagerClient : : DeviceListChanged :
std : : cout < < " ------------------------------- WCMRAudioDeviceManagerClient::DeviceListChanged " < < std : : endl ;
2014-09-30 20:35:31 -04:00
engine . request_device_list_update ( ) ;
2014-04-30 13:46:41 -04:00
break ;
case WCMRAudioDeviceManagerClient : : IODeviceDisconnected :
2015-05-14 10:52:12 -04:00
std : : cout < < " ------------------------------- WCMRAudioDeviceManagerClient::IODeviceDisconnected " < < std : : endl ;
2014-09-30 20:35:31 -04:00
engine . request_device_list_update ( ) ;
2014-04-30 13:46:41 -04:00
break ;
case WCMRAudioDeviceManagerClient : : AudioCallback :
if ( parameter ) {
2015-02-20 05:52:47 -05:00
const AudioCallbackData * audio_callback_data = ( AudioCallbackData * ) parameter ;
2014-04-30 13:46:41 -04:00
_audio_device_callback (
audio_callback_data - > acdInputBuffer ,
audio_callback_data - > acdOutputBuffer ,
audio_callback_data - > acdFrames ,
audio_callback_data - > acdSampleTime ,
audio_callback_data - > acdCycleStartTimeNanos
) ;
}
break ;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
default :
break ;
} ;
}
2015-05-14 10:47:38 -04:00
WavesAudioBackend : : WavesAudioBackend ( AudioEngine & e )
: AudioBackend ( e , __backend_info )
2014-04-30 13:46:41 -04:00
, _audio_device_manager ( this )
, _midi_device_manager ( * this )
, _device ( NULL )
, _sample_format ( FormatFloat )
, _interleaved ( true )
, _input_channels ( 0 )
, _max_input_channels ( 0 )
, _output_channels ( 0 )
, _max_output_channels ( 0 )
, _sample_rate ( 0 )
, _buffer_size ( 0 )
, _systemic_input_latency ( 0 )
, _systemic_output_latency ( 0 )
, _call_thread_init_callback ( false )
, _use_midi ( true )
, _sample_time_at_cycle_start ( 0 )
, _freewheeling ( false )
, _freewheel_thread_active ( false )
, _dsp_load_accumulator ( 0 )
2014-10-22 21:32:14 -04:00
, _audio_cycle_period_nanos ( 0 )
2014-04-30 13:46:41 -04:00
, _dsp_load_history_length ( 0 )
{
}
WavesAudioBackend : : ~ WavesAudioBackend ( )
{
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
}
std : : string
WavesAudioBackend : : name ( ) const
{
2014-05-01 09:32:18 -04:00
# ifdef __APPLE__
2014-04-30 13:46:41 -04:00
return std : : string ( " CoreAudio " ) ;
2014-05-01 09:32:18 -04:00
# elif PLATFORM_WINDOWS
2014-04-30 13:46:41 -04:00
return std : : string ( " ASIO " ) ;
# endif
}
bool
WavesAudioBackend : : is_realtime ( ) const
{
return true ;
}
2015-10-04 14:51:05 -04:00
bool
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : requires_driver_selection ( ) const
2015-10-04 14:51:05 -04:00
{
return false ;
2014-04-30 13:46:41 -04:00
}
2015-10-04 14:51:05 -04:00
std : : vector < std : : string >
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : enumerate_drivers ( ) const
2015-10-04 14:51:05 -04:00
{
2014-04-30 13:46:41 -04:00
// this backend does not suppose driver selection
assert ( false ) ;
2015-10-04 14:51:05 -04:00
return std : : vector < std : : string > ( ) ;
2014-04-30 13:46:41 -04:00
}
2015-10-04 14:51:05 -04:00
int
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : set_driver ( const std : : string & /*drivername*/ )
{
//Waves audio backend does not suppose driver selection
assert ( false ) ;
2015-10-04 14:51:05 -04:00
return - 1 ;
2014-04-30 13:46:41 -04:00
}
2015-10-04 14:51:05 -04:00
std : : vector < AudioBackend : : DeviceStatus >
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : enumerate_devices ( ) const
2015-10-04 14:51:05 -04:00
{
2014-04-30 13:46:41 -04:00
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::enumerate_devices (): " << std::endl;
std : : vector < DeviceStatus > devicesStatus ;
2015-10-04 14:51:05 -04:00
const DeviceInfoVec & deviceInfoList = _audio_device_manager . DeviceInfoList ( ) ;
2014-04-30 13:46:41 -04:00
for ( DeviceInfoVecConstIter deviceInfoIter = deviceInfoList . begin ( ) ; deviceInfoIter ! = deviceInfoList . end ( ) ; + + deviceInfoIter ) {
// COMMENTED DBG LOGS */ std::cout << "\t Device found: " << (*deviceInfoIter)->m_DeviceName << std::endl;
devicesStatus . push_back ( DeviceStatus ( ( * deviceInfoIter ) - > m_DeviceName , true ) ) ;
}
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
return devicesStatus ;
2015-10-04 14:51:05 -04:00
}
2014-04-30 13:46:41 -04:00
2015-10-04 14:51:05 -04:00
std : : vector < float >
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : available_sample_rates ( const std : : string & device_name ) const
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::available_sample_rates (): [" << device_name << "]" << std::endl;
2014-09-30 20:35:31 -04:00
std : : vector < int > sr ;
2015-10-04 14:51:05 -04:00
2014-09-30 20:35:31 -04:00
WTErr retVal = _audio_device_manager . GetDeviceSampleRates ( device_name , sr ) ;
2015-10-04 14:51:05 -04:00
2014-09-30 20:35:31 -04:00
if ( eNoErr ! = retVal ) {
2014-04-30 13:46:41 -04:00
std : : cerr < < " WavesAudioBackend::available_sample_rates (): Failed to find device [ " < < device_name < < " ] " < < std : : endl ;
return std : : vector < float > ( ) ;
}
// COMMENTED DBG LOGS */ std::cout << "\tFound " << devInfo.m_AvailableSampleRates.size () << " sample rates for " << device_name << ":";
2014-09-30 20:35:31 -04:00
std : : vector < float > sample_rates ( sr . begin ( ) , sr . end ( ) ) ;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
// COMMENTED DBG LOGS */ for (std::vector<float>::iterator i = sample_rates.begin (); i != sample_rates.end (); ++i) std::cout << " " << *i; std::cout << std::endl;
return sample_rates ;
}
2015-10-04 14:51:05 -04:00
float WavesAudioBackend : : default_sample_rate ( ) const
{
2014-04-30 13:46:41 -04:00
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::default_sample_rate (): " << AudioBackend::default_sample_rate () << std::endl;
2015-10-04 14:51:05 -04:00
return AudioBackend : : default_sample_rate ( ) ;
2014-04-30 13:46:41 -04:00
}
2015-10-04 14:51:05 -04:00
std : : vector < uint32_t >
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : available_buffer_sizes ( const std : : string & device_name ) const
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::available_buffer_sizes (): [" << device_name << "]" << std::endl;
std : : vector < int > bs ;
2014-09-30 20:35:31 -04:00
WTErr retVal = _audio_device_manager . GetDeviceBufferSizes ( device_name , bs ) ;
2014-04-30 13:46:41 -04:00
if ( retVal ! = eNoErr ) {
std : : cerr < < " WavesAudioBackend::available_buffer_sizes (): Failed to get buffer size for device [ " < < device_name < < " ] " < < std : : endl ;
return std : : vector < uint32_t > ( ) ;
}
std : : vector < uint32_t > buffer_sizes ( bs . begin ( ) , bs . end ( ) ) ;
// COMMENTED DBG LOGS */ std::cout << "\tFound " << buffer_sizes.size () << " buffer sizes for " << device_name << ":";
// 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;
return buffer_sizes ;
}
2015-10-04 14:51:05 -04:00
uint32_t
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : available_input_channel_count ( const std : : string & device_name ) const
{
DeviceInfo devInfo ;
WTErr err = _audio_device_manager . GetDeviceInfoByName ( device_name , devInfo ) ;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
if ( eNoErr ! = err ) {
std : : cerr < < " WavesAudioBackend::available_input_channel_count (): Failed to find device [ " < < device_name < < " ] " < < std : : endl ;
return 0 ;
}
uint32_t num_of_input_channels = devInfo . m_MaxInputChannels ;
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::available_input_channel_count (): " << num_of_input_channels << std::endl;
return num_of_input_channels ;
}
2015-10-04 14:51:05 -04:00
uint32_t
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : available_output_channel_count ( const std : : string & device_name ) const
{
DeviceInfo devInfo ;
WTErr err = _audio_device_manager . GetDeviceInfoByName ( device_name , devInfo ) ;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
if ( eNoErr ! = err ) {
std : : cerr < < " WavesAudioBackend::available_output_channel_count (): Failed to find device [ " < < device_name < < " ] " < < std : : endl ;
return 0 ;
}
uint32_t num_of_output_channels = devInfo . m_MaxOutputChannels ;
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::available_output_channel_count (): " << num_of_output_channels << std::endl;
return num_of_output_channels ;
}
bool
WavesAudioBackend : : can_change_sample_rate_when_running ( ) const
{
// VERIFY IT CAREFULLY
return true ;
}
bool
WavesAudioBackend : : can_change_buffer_size_when_running ( ) const
{
// VERIFY IT CAREFULLY
return true ;
}
int
WavesAudioBackend : : set_device_name ( const std : : string & device_name )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_device_name (): " << device_name << std::endl;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
if ( _ports . size ( ) ) {
std : : cerr < < " WavesAudioBackend::set_device_name (): There are unregistered ports left after [ " < < ( _device ? _device - > DeviceName ( ) : std : : string ( " <NULL> " ) ) < < " ]! " < < std : : endl ;
for ( size_t i = 0 ; i < _ports . size ( ) ; + + i ) {
std : : cerr < < " \t [ " < < _ports [ i ] - > name ( ) < < " ]! " < < std : : endl ;
}
return - 1 ;
}
if ( _device & & _device - > Streaming ( ) ) {
std : : cerr < < " WavesAudioBackend::set_device_name (): [ " < < _device - > DeviceName ( ) < < " ] is streaming! Current device must be stopped before setting another device as current " < < std : : endl ;
}
// we must have only one device initialized at a time
// stop current device first
WTErr retVal ;
if ( _device ) {
retVal = _device - > SetActive ( false ) ;
if ( retVal ! = eNoErr ) {
std : : cerr < < " WavesAudioBackend::set_device_name (): [ " < < _device - > DeviceName ( ) < < " ]->SetActive (false) failed! " < < std : : endl ;
return - 1 ;
}
}
// deinitialize it
_audio_device_manager . DestroyCurrentDevice ( ) ;
_device = 0 ;
WCMRAudioDevice * device = _audio_device_manager . InitNewCurrentDevice ( device_name ) ;
if ( ! device ) {
std : : cerr < < " WavesAudioBackend::set_device_name (): Failed to initialize device [ " < < device_name < < " ]! " < < std : : endl ;
return - 1 ;
}
retVal = device - > SetActive ( true ) ;
if ( retVal ! = eNoErr ) {
std : : cerr < < " WavesAudioBackend::set_device_name (): [ " < < device - > DeviceName ( ) < < " ]->SetActive () failed! " < < std : : endl ;
return - 1 ;
}
_device = device ;
return 0 ;
}
int
WavesAudioBackend : : drop_device ( )
{
WTErr wtErr = 0 ;
if ( _device )
{
wtErr = _device - > SetActive ( false ) ;
if ( wtErr ! = eNoErr ) {
std : : cerr < < " WavesAudioBackend::drop_device (): [ " < < _device - > DeviceName ( ) < < " ]->SetActive () failed! " < < std : : endl ;
return - 1 ;
}
}
_audio_device_manager . DestroyCurrentDevice ( ) ;
_device = 0 ;
return 0 ;
}
2015-10-04 14:51:05 -04:00
int
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : set_sample_rate ( float sample_rate )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_sample_rate (): " << sample_rate << std::endl;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
WTErr retVal = eNoErr ;
if ( ! _device ) {
std : : cerr < < " WavesAudioBackend::set_sample_rate (): No device is set! " < < std : : endl ;
return - 1 ;
}
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
bool device_needs_restart = _device - > Streaming ( ) ;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
if ( device_needs_restart ) {
retVal = _device - > SetStreaming ( false ) ;
// COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->_device->SetStreaming (false);"<< std::endl;
if ( retVal ! = eNoErr ) {
std : : cerr < < " WavesAudioBackend::set_sample_rate (): [ " < < _device - > DeviceName ( ) < < " ]->SetStreaming (false) failed ( " < < retVal < < " ) ! " < < std : : endl ;
return - 1 ;
}
}
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
retVal = _device - > SetCurrentSamplingRate ( ( int ) sample_rate ) ;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
if ( retVal ! = eNoErr ) {
std : : cerr < < " WavesAudioBackend::set_sample_rate (): [ " < < _device - > DeviceName ( ) < < " ]->SetCurrentSamplingRate ((int) " < < sample_rate < < " ) failed ( " < < retVal < < " ) ! " < < std : : endl ;
return - 1 ;
}
2015-05-13 19:11:27 -04:00
// if call to set sample rate is successful
// but device sample rate differs from the value we tried to set
// this means we are driven by device for buffer size
sample_rate = _device - > CurrentSamplingRate ( ) ;
_sample_rate_change ( sample_rate ) ;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
if ( device_needs_restart ) {
// COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetStreaming (true);"<< std::endl;
retVal = _device - > SetStreaming ( true ) ;
if ( retVal ! = eNoErr ) {
std : : cerr < < " WavesAudioBackend::set_sample_rate (): [ " < < _device - > DeviceName ( ) < < " ]->SetStreaming (true) failed ( " < < retVal < < " ) ! " < < std : : endl ;
return - 1 ;
}
}
return 0 ;
}
2015-10-04 14:51:05 -04:00
int
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : set_buffer_size ( uint32_t buffer_size )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_buffer_size (" << buffer_size << "):"<< std::endl;
WTErr retVal = eNoErr ;
if ( ! _device ) {
std : : cerr < < " WavesAudioBackend::set_buffer_size (): No device is set! " < < std : : endl ;
return - 1 ;
}
bool device_needs_restart = _device - > Streaming ( ) ;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
if ( device_needs_restart ) {
retVal = _device - > SetStreaming ( false ) ;
// COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetStreaming (false);"<< std::endl;
if ( retVal ! = eNoErr ) {
std : : cerr < < " WavesAudioBackend::set_buffer_size (): [ " < < _device - > DeviceName ( ) < < " ]->SetStreaming (false) failed ( " < < retVal < < " ) ! " < < std : : endl ;
return - 1 ;
}
}
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
retVal = _device - > SetCurrentBufferSize ( buffer_size ) ;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
if ( retVal ! = eNoErr ) {
std : : cerr < < " WavesAudioBackend::set_buffer_size (): [ " < < _device - > DeviceName ( ) < < " ]->SetCurrentBufferSize ( " < < buffer_size < < " ) failed ( " < < retVal < < " ) ! " < < std : : endl ;
return - 1 ;
}
2015-10-04 14:51:05 -04:00
2014-09-30 20:35:31 -04:00
// if call to set buffer is successful but device buffer size differs from the value we tried to set
// this means we are driven by device for buffer size
buffer_size = _device - > CurrentBufferSize ( ) ;
2014-04-30 13:46:41 -04:00
_buffer_size_change ( buffer_size ) ;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
if ( device_needs_restart ) {
// COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetStreaming (true);"<< std::endl;
retVal = _device - > SetStreaming ( true ) ;
if ( retVal ! = eNoErr ) {
std : : cerr < < " WavesAudioBackend::set_buffer_size (): [ " < < _device - > DeviceName ( ) < < " ]->SetStreaming (true) failed ( " < < retVal < < " ) ! " < < std : : endl ;
return - 1 ;
}
}
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
return 0 ;
}
2015-10-04 14:51:05 -04:00
int
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : set_sample_format ( SampleFormat sample_format )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_sample_format (): " << sample_format << std::endl;
_sample_format = sample_format ;
return 0 ;
}
2015-10-04 14:51:05 -04:00
int
2014-09-30 20:35:31 -04:00
WavesAudioBackend : : reset_device ( )
2014-04-30 13:46:41 -04:00
{
2014-09-30 20:35:31 -04:00
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_reset_device ():" << std::endl;
2014-04-30 13:46:41 -04:00
if ( ! _device ) {
std : : cerr < < " WavesAudioBackend::set_buffer_size (): No device is set! " < < std : : endl ;
return - 1 ;
}
2014-09-30 20:35:31 -04:00
return _device - > ResetDevice ( ) ;
2014-04-30 13:46:41 -04:00
}
2015-10-04 14:51:05 -04:00
int
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : _buffer_size_change ( uint32_t new_buffer_size )
{
_buffer_size = new_buffer_size ;
_init_dsp_load_history ( ) ;
return engine . buffer_size_change ( new_buffer_size ) ;
}
2015-10-04 14:51:05 -04:00
int
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : _sample_rate_change ( float new_sample_rate )
{
_sample_rate = new_sample_rate ;
_init_dsp_load_history ( ) ;
return engine . sample_rate_change ( new_sample_rate ) ;
}
2015-10-04 14:51:05 -04:00
int
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : set_interleaved ( bool yn )
{
/*you can ignore them totally*/
_interleaved = yn ;
return 0 ;
}
2015-10-04 14:51:05 -04:00
int
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : set_input_channels ( uint32_t input_channels )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_input_channels (): " << input_channels << std::endl;
_input_channels = input_channels ;
return 0 ;
}
2015-10-04 14:51:05 -04:00
int
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : set_output_channels ( uint32_t output_channels )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_output_channels (): " << output_channels << std::endl;
_output_channels = output_channels ;
return 0 ;
}
2015-10-04 14:51:05 -04:00
std : : string
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : device_name ( ) const
{
if ( ! _device ) {
return " " ;
}
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::device_name (): " << _device->DeviceName () << std::endl;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
return _device - > DeviceName ( ) ;
}
2015-10-04 14:51:05 -04:00
float
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : sample_rate ( ) const
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::sample_rate (): " << std::endl;
if ( ! _device ) {
std : : cerr < < " WavesAudioBackend::sample_rate (): No device is set! " < < std : : endl ;
return - 1 ;
}
int sample_rate = _device - > CurrentSamplingRate ( ) ;
// COMMENTED DBG LOGS */ std::cout << "\t[" << _device->DeviceName () << "]->CurrentSamplingRate () returned " << sample_rate << std::endl;
return ( float ) sample_rate ;
}
2015-10-04 14:51:05 -04:00
uint32_t
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : buffer_size ( ) const
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::buffer_size (): " << std::endl;
if ( ! _device ) {
std : : cerr < < " WavesAudioBackend::buffer_size (): No device is set! " < < std : : endl ;
return 0 ;
}
int size = _device - > CurrentBufferSize ( ) ;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
// COMMENTED DBG LOGS */ std::cout << "\t[" << _device->DeviceName () << "]->CurrentBufferSize () returned " << size << std::endl;
return ( uint32_t ) size ;
}
2015-10-04 14:51:05 -04:00
SampleFormat
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : sample_format ( ) const
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::sample_format ()" << std::endl;
return _sample_format ;
}
2015-10-04 14:51:05 -04:00
bool
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : interleaved ( ) const
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::interleaved ()" << std::endl;
return _interleaved ;
}
2015-10-04 14:51:05 -04:00
uint32_t
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : input_channels ( ) const
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::input_channels ()" << std::endl;
return _input_channels ;
}
2015-10-04 14:51:05 -04:00
uint32_t
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : output_channels ( ) const
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::output_channels ()" << std::endl;
return _output_channels ;
}
2015-10-04 14:51:05 -04:00
std : : string
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : control_app_name ( ) const
{
2015-10-04 14:51:05 -04:00
std : : string app_name = " " ;
2014-04-30 13:46:41 -04:00
if ( _device & & ! dynamic_cast < WCMRNativeAudioNoneDevice * > ( _device ) ) {
app_name = " PortAudioMayKnowIt " ;
}
2015-10-04 14:51:05 -04:00
return app_name ;
2014-04-30 13:46:41 -04:00
}
void
WavesAudioBackend : : launch_control_app ( )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::launch_control_app ()" << std::endl;
if ( ! _device ) {
std : : cerr < < " WavesAudioBackend::launch_control_app (): No device is set! " < < std : : endl ;
return ;
}
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
WTErr err = _device - > ShowConfigPanel ( NULL ) ;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
if ( eNoErr ! = err ) {
std : : cerr < < " WavesAudioBackend::launch_control_app (): [ " < < _device - > DeviceName ( ) < < " ]->ShowConfigPanel () failed ( " < < err < < " )! " < < std : : endl ;
}
// COMMENTED DBG LOGS */ else std::cout << "WavesAudioBackend::launch_control_app (): [" << _device->DeviceName () << "]->ShowConfigPanel () successfully launched!" << std::endl;
}
int
WavesAudioBackend : : _start ( bool for_latency_measurement )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_start ()" << std::endl;
if ( ! _device ) {
std : : cerr < < " WavesAudioBackend::_start (): No device is set! " < < std : : endl ;
2014-09-30 20:35:31 -04:00
stop ( ) ;
return - 1 ;
2014-04-30 13:46:41 -04:00
}
if ( _register_system_audio_ports ( ) ! = 0 ) {
std : : cerr < < " WavesAudioBackend::_start (): _register_system_audio_ports () failed! " < < std : : endl ;
2014-09-30 20:35:31 -04:00
stop ( ) ;
return - 1 ;
2014-04-30 13:46:41 -04:00
}
if ( _use_midi ) {
if ( _midi_device_manager . start ( ) ! = 0 ) {
std : : cerr < < " WavesAudioBackend::_start (): _midi_device_manager.start () failed! " < < std : : endl ;
2014-09-30 20:35:31 -04:00
stop ( ) ;
return - 1 ;
2014-04-30 13:46:41 -04:00
}
if ( _register_system_midi_ports ( ) ! = 0 ) {
std : : cerr < < " WavesAudioBackend::_start (): _register_system_midi_ports () failed! " < < std : : endl ;
2014-09-30 20:35:31 -04:00
stop ( ) ;
return - 1 ;
2014-04-30 13:46:41 -04:00
}
}
if ( engine . reestablish_ports ( ) ! = 0 ) {
std : : cerr < < " WavesAudioBackend::_start (): engine.reestablish_ports () failed! " < < std : : endl ;
}
manager . registration_callback ( ) ;
WTErr retVal = _device - > SetStreaming ( true ) ;
if ( retVal ! = eNoErr ) {
std : : cerr < < " WavesAudioBackend::_start (): [ " < < _device - > DeviceName ( ) < < " ]->SetStreaming () failed! " < < std : : endl ;
2014-09-30 20:35:31 -04:00
stop ( ) ;
2014-04-30 13:46:41 -04:00
return - 1 ;
}
if ( _use_midi ) {
if ( _midi_device_manager . stream ( true ) ) {
std : : cerr < < " WavesAudioBackend::_start (): _midi_device_manager.stream (true) failed! " < < std : : endl ;
2014-09-30 20:35:31 -04:00
stop ( ) ;
return - 1 ;
2014-04-30 13:46:41 -04:00
}
}
return 0 ;
}
void
2015-10-04 14:51:05 -04:00
WavesAudioBackend : : _audio_device_callback ( const float * input_buffer ,
float * output_buffer ,
2014-04-30 13:46:41 -04:00
unsigned long nframes ,
2015-02-19 17:43:16 -05:00
framepos_t sample_time ,
2014-04-30 13:46:41 -04:00
uint64_t cycle_start_time_nanos )
{
uint64_t dsp_start_time_nanos = __get_time_nanos ( ) ;
// COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::_audio_device_callback ():" << _device->DeviceName () << std::endl;
_sample_time_at_cycle_start = sample_time ;
_cycle_start_time_nanos = cycle_start_time_nanos ;
if ( _buffer_size ! = nframes ) {
// COMMENTED DBG LOGS */ std::cout << "\tAudioEngine::thread_init_callback() buffer size and nframes are not equal: " << _buffer_size << "!=" << nframes << std::endl;
return ;
}
_read_audio_data_from_device ( input_buffer , nframes ) ;
_read_midi_data_from_devices ( ) ;
if ( _call_thread_init_callback ) {
_call_thread_init_callback = false ;
// COMMENTED DBG LOGS */ std::cout << "\tAudioEngine::thread_init_callback() invoked for " << std::hex << pthread_self() << std::dec << " !" << std::endl;
2015-10-04 14:51:05 -04:00
2015-05-12 10:50:26 -04:00
/* There is the possibility that the thread this runs in may change from
* callback to callback , so do it every time .
*/
_main_thread = pthread_self ( ) ;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
AudioEngine : : thread_init_callback ( this ) ;
}
2015-02-24 07:27:36 -05:00
if ( ! engine . thread_initialised_for_audio_processing ( ) ) {
std : : cerr < < " \t WavesAudioBackend::_audio_device_callback (): It's an attempt to call process callback from the thread which didn't initialize it " < < std : : endl ;
2015-10-04 14:51:05 -04:00
2015-02-24 07:27:36 -05:00
AudioEngine : : thread_init_callback ( this ) ;
}
2015-10-04 14:51:05 -04:00
2015-06-30 03:17:43 -04:00
if ( pthread_equal ( _main_thread , pthread_self ( ) ) = = 0 ) {
2015-06-30 03:11:05 -04:00
# ifdef PTW32_VERSION
std : : cerr < < " Process thread ID has changed. Expected thread: " < < _main_thread . p < < " current thread: " < < pthread_self ( ) . p < < std : : dec < < " ! " < < std : : endl ;
# else
2015-05-13 20:29:27 -04:00
std : : cerr < < " Process thread ID has changed. Expected thread: " < < _main_thread < < " current thread: " < < pthread_self ( ) < < std : : dec < < " ! " < < std : : endl ;
2015-06-30 03:11:05 -04:00
# endif
2015-05-13 20:29:27 -04:00
_main_thread = pthread_self ( ) ;
2015-05-12 10:50:26 -04:00
}
2015-02-24 07:27:36 -05:00
2014-04-30 13:46:41 -04:00
engine . process_callback ( nframes ) ;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
_write_audio_data_to_device ( output_buffer , nframes ) ;
_write_midi_data_to_devices ( nframes ) ;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
uint64_t dsp_end_time_nanos = __get_time_nanos ( ) ;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
_dsp_load_accumulator - = * _dsp_load_history . begin ( ) ;
2014-09-30 20:35:31 -04:00
_dsp_load_history . pop_front ( ) ;
2014-04-30 13:46:41 -04:00
uint64_t dsp_load_nanos = dsp_end_time_nanos - dsp_start_time_nanos ;
_dsp_load_accumulator + = dsp_load_nanos ;
_dsp_load_history . push_back ( dsp_load_nanos ) ;
return ;
}
int
WavesAudioBackend : : stop ( )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::stop ()" << std::endl;
WTErr wtErr = eNoErr ;
int retVal = 0 ;
// COMMENTED DBG LOGS */ std::cout << "\t[" << _device->DeviceName () << "]" << std::endl;
if ( _device ) {
wtErr = _device - > SetStreaming ( false ) ;
if ( wtErr ! = eNoErr ) {
std : : cerr < < " WavesAudioBackend::stop (): [ " < < _device - > DeviceName ( ) < < " ]->SetStreaming () failed! " < < std : : endl ;
retVal = - 1 ;
}
}
2015-03-02 13:19:50 -05:00
_midi_device_manager . stop ( ) ;
2014-04-30 13:46:41 -04:00
_unregister_system_audio_ports ( ) ;
_unregister_system_midi_ports ( ) ;
2015-03-02 13:19:50 -05:00
2014-04-30 13:46:41 -04:00
return retVal ;
}
int
WavesAudioBackend : : freewheel ( bool start_stop )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::freewheel (" << start_stop << "):" << std::endl;
if ( start_stop ! = _freewheeling ) {
if ( start_stop = = true ) {
WTErr retval = _device - > SetStreaming ( false ) ;
if ( retval ! = eNoErr ) {
std : : cerr < < " WavesAudioBackend::freewheel (): [ " < < _device - > DeviceName ( ) < < " ]->SetStreaming () failed! " < < std : : endl ;
return - 1 ;
}
_call_thread_init_callback = true ;
_freewheel_thread ( ) ;
2015-10-04 14:51:05 -04:00
2015-05-13 19:11:27 -04:00
while ( ! engine . freewheeling ( ) ) {
sleep ( 0 ) ;
}
2015-10-04 14:51:05 -04:00
2015-05-13 19:11:27 -04:00
// freewheel thread was not activated successfully
if ( _freewheel_thread_active = = false ) {
engine . freewheel_callback ( false ) ;
}
2014-04-30 13:46:41 -04:00
}
else {
_freewheel_thread_active = false ; // stop _freewheel_thread ()
2015-10-04 14:51:05 -04:00
2015-05-13 19:11:27 -04:00
while ( engine . freewheeling ( ) ) {
sleep ( 0 ) ;
}
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
_call_thread_init_callback = true ;
WTErr retval = _device - > SetStreaming ( true ) ;
if ( retval ! = eNoErr ) {
std : : cerr < < " WavesAudioBackend::freewheel (): [ " < < _device - > DeviceName ( ) < < " ]->SetStreaming () failed! " < < std : : endl ;
return - 1 ;
}
}
_freewheeling = start_stop ;
}
// already doing what has been asked for
return 0 ;
}
2015-10-04 14:51:05 -04:00
void
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : _freewheel_thread ( )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_freewheel_thread ():" << std::endl;
if ( ! _freewheel_thread_active ) { // Lets create it
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
// COMMENTED DBG LOGS */ std::cout << "\tCreating the thread _freewheel_thread () . . ." << std::endl;
pthread_attr_t attributes ;
pthread_t thread_id ;
ThreadData * thread_data = new ThreadData ( this , boost : : bind ( & WavesAudioBackend : : _freewheel_thread , this ) , __thread_stack_size ( ) ) ;
if ( pthread_attr_init ( & attributes ) ) {
std : : cerr < < " WavesAudioBackend::freewheel_thread (): pthread_attr_init () failed! " < < std : : endl ;
return ;
}
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
if ( pthread_attr_setstacksize ( & attributes , __thread_stack_size ( ) ) ) {
std : : cerr < < " WavesAudioBackend::freewheel_thread (): pthread_attr_setstacksize () failed! " < < std : : endl ;
return ;
}
2014-12-18 14:16:24 -05:00
_freewheel_thread_active = true ;
2014-04-30 13:46:41 -04:00
if ( ( pthread_create ( & thread_id , & attributes , __start_process_thread , thread_data ) ) ) {
2014-12-18 14:16:24 -05:00
_freewheel_thread_active = false ;
2015-10-04 14:51:05 -04:00
2015-05-13 19:11:27 -04:00
// release invoking thread
engine . freewheel_callback ( true ) ;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
std : : cerr < < " WavesAudioBackend::freewheel_thread (): pthread_create () failed! " < < std : : endl ;
return ;
}
// COMMENTED DBG LOGS */ std::cout << "\t. . . _freewheel_thread () complete." << std::endl;
return ;
}
2015-10-04 14:51:05 -04:00
2015-05-13 19:11:27 -04:00
// notify angine that freewheeling is started
engine . freewheel_callback ( true ) ;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
if ( _call_thread_init_callback ) {
_call_thread_init_callback = false ;
AudioEngine : : thread_init_callback ( this ) ;
}
while ( _freewheel_thread_active ) {
engine . process_callback ( _buffer_size ) ;
}
2015-10-04 14:51:05 -04:00
2015-05-13 19:11:27 -04:00
// notify angine that freewheeling is stopped
engine . freewheel_callback ( false ) ;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_freewheel_thread (): FINISHED" << std::endl;
return ;
}
float
WavesAudioBackend : : dsp_load ( ) const
{
// COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::dsp_load (): " << std::endl;
if ( ! _device ) {
std : : cerr < < " WavesAudioBackend::cpu_load (): No device is set! " < < std : : endl ;
return 0 ;
}
float average_dsp_load = ( float ) _dsp_load_accumulator / _dsp_load_history_length ;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
return ( average_dsp_load / _audio_cycle_period_nanos ) * 100.0 ;
}
void
WavesAudioBackend : : _init_dsp_load_history ( )
{
if ( ( _sample_rate < = 0.0 ) | | ( _buffer_size < = 0.0 ) ) {
return ;
}
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
_audio_cycle_period_nanos = ( ( uint64_t ) 1000000000L * _buffer_size ) / _sample_rate ;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
_dsp_load_accumulator = 0 ;
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
_dsp_load_history_length = ( _sample_rate + _buffer_size - 1 ) / _buffer_size ;
// COMMENTED DBG LOGS */ std::cout << "\t\t_dsp_load_history_length = " << _dsp_load_history_length << std::endl;
_dsp_load_history = std : : list < uint64_t > ( _dsp_load_history_length , 0 ) ;
}
void
WavesAudioBackend : : transport_start ( )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::transport_start (): " << std::endl;
}
void
2015-10-04 14:51:05 -04:00
WavesAudioBackend : : transport_stop ( )
2014-04-30 13:46:41 -04:00
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::transport_stop (): " << std::endl;
}
TransportState
WavesAudioBackend : : transport_state ( ) const
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::transport_state (): " << std::endl;
2015-10-04 14:51:05 -04:00
return TransportStopped ;
2014-04-30 13:46:41 -04:00
}
void
WavesAudioBackend : : transport_locate ( framepos_t pos )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::transport_locate (" << pos << "): " << std::endl;
}
framepos_t
WavesAudioBackend : : transport_frame ( ) const
2015-10-04 14:51:05 -04:00
{
2014-04-30 13:46:41 -04:00
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::transport_frame (): " << std::endl;
2015-10-04 14:51:05 -04:00
return 0 ;
2014-04-30 13:46:41 -04:00
}
int
WavesAudioBackend : : set_time_master ( bool yn )
2015-10-04 14:51:05 -04:00
{
2014-04-30 13:46:41 -04:00
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::set_time_master (): " << yn << std::endl;
2015-10-04 14:51:05 -04:00
return 0 ;
2014-04-30 13:46:41 -04:00
}
int
WavesAudioBackend : : usecs_per_cycle ( ) const
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::usecs_per_cycle (): " << std::endl;
return ( 1000000 * _sample_rate ) / _buffer_size ;
}
size_t
WavesAudioBackend : : raw_buffer_size ( DataType data_type )
{
// COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::raw_buffer_size (" << data_type.to_string () << "): " << std::endl;
switch ( data_type ) {
case DataType : : AUDIO :
return WavesAudioPort : : MAX_BUFFER_SIZE_BYTES ;
break ;
case DataType : : MIDI :
return WavesMidiPort : : MAX_BUFFER_SIZE_BYTES ;
break ;
default :
std : : cerr < < " WavesAudioBackend::raw_buffer_size (): unexpected data type ( " < < ( uint32_t ) data_type < < " )! " < < std : : endl ;
break ;
}
return 0 ;
}
2015-02-19 17:43:16 -05:00
framepos_t
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : sample_time ( )
{
// WARNING: This is approximate calculation. Implementation of accurate calculation is pending.
// http://kokkinizita.linuxaudio.org/papers/usingdll.pdf
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
return _sample_time_at_cycle_start + ( ( __get_time_nanos ( ) - _cycle_start_time_nanos ) * _sample_rate ) / 1000000000L ;
}
uint64_t
WavesAudioBackend : : __get_time_nanos ( )
{
2014-05-01 09:32:18 -04:00
# ifdef __APPLE__
2014-04-30 13:46:41 -04:00
// here we exploit the time counting API which is used by the WCMRCoreAudioDeviceManager. However,
// the API should be a part of WCMRCoreAudioDeviceManager to give a chance of being tied to the
// audio device transport timeß.
return AudioConvertHostTimeToNanos ( AudioGetCurrentHostTime ( ) ) ;
2015-10-04 14:51:05 -04:00
2014-05-01 09:32:18 -04:00
# elif PLATFORM_WINDOWS
2014-04-30 13:46:41 -04:00
LARGE_INTEGER Count ;
QueryPerformanceCounter ( & Count ) ;
return uint64_t ( ( Count . QuadPart * 1000000000L / __performance_counter_frequency ) ) ;
# endif
}
2015-02-19 17:43:16 -05:00
framepos_t
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : sample_time_at_cycle_start ( )
{
// COMMENTED FREQUENT DBG LOGS */ std::cout << "WavesAudioBackend::sample_time_at_cycle_start (): " << _sample_time_at_cycle_start << std::endl;
return _sample_time_at_cycle_start ;
}
pframes_t
WavesAudioBackend : : samples_since_cycle_start ( )
{
2015-10-04 14:51:05 -04:00
pframes_t diff_sample_time ;
2014-04-30 13:46:41 -04:00
diff_sample_time = sample_time ( ) - _sample_time_at_cycle_start ;
// COMMENTED DBG LOGS */ std::cout << "samples_since_cycle_start: " << diff_sample_time << std::endl;
return diff_sample_time ;
}
bool
WavesAudioBackend : : get_sync_offset ( pframes_t & /*offset*/ ) const
2015-10-04 14:51:05 -04:00
{
2014-04-30 13:46:41 -04:00
// COMMENTED DBG LOGS */ std::cout << "get_sync_offset: false" << std::endl;
2015-10-04 14:51:05 -04:00
return false ;
2014-04-30 13:46:41 -04:00
}
int
WavesAudioBackend : : create_process_thread ( boost : : function < void ( ) > func )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::create_process_thread ():" << std::endl;
int retVal ;
pthread_attr_t attributes ;
size_t stacksize_aligned ;
pthread_t thread_id ;
// Align stacksize to PTHREAD_STACK_MIN.
stacksize_aligned = __thread_stack_size ( ) ;
ThreadData * td = new ThreadData ( this , func , stacksize_aligned ) ;
if ( ( retVal = pthread_attr_init ( & attributes ) ) ) {
std : : cerr < < " Cannot set thread attr init res = " < < retVal < < endmsg ;
return - 1 ;
}
2015-10-04 14:51:05 -04:00
2014-04-30 13:46:41 -04:00
if ( ( retVal = pthread_attr_setstacksize ( & attributes , stacksize_aligned ) ) ) {
std : : cerr < < " Cannot set thread stack size ( " < < stacksize_aligned < < " ) res = " < < retVal < < endmsg ;
return - 1 ;
}
if ( ( retVal = pthread_create ( & thread_id , & attributes , __start_process_thread , td ) ) ) {
std : : cerr < < " Cannot create thread res = " < < retVal < < endmsg ;
return - 1 ;
}
_backend_threads . push_back ( thread_id ) ;
// COMMENTED DBG LOGS */ std::cout << "\t\t\t. . . thread " << std::hex << thread_id << std::dec << " has been created" << std::endl;
return 0 ;
}
void *
WavesAudioBackend : : __start_process_thread ( void * arg )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__start_process_thread ():" << std::endl;
ThreadData * td = reinterpret_cast < ThreadData * > ( arg ) ;
boost : : function < void ( ) > f = td - > f ;
delete td ;
f ( ) ;
return 0 ;
}
int
WavesAudioBackend : : join_process_threads ( )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::join_process_thread ()" << std::endl;
int ret = 0 ;
for ( std : : vector < pthread_t > : : const_iterator i = _backend_threads . begin ( ) ;
i ! = _backend_threads . end ( ) ;
+ + i ) {
// COMMENTED DBG LOGS */ std::cout << "\t\t\tstopping thread " << std::hex << *i << std::dec << "...\n";
2015-10-04 14:51:05 -04:00
void * status ;
2014-04-30 13:46:41 -04:00
if ( pthread_join ( * i , & status ) ! = 0 ) {
std : : cerr < < " AudioEngine: cannot stop process thread ! " < < std : : endl ;
ret + = - 1 ;
}
// COMMENTED DBG LOGS */ std::cout << "\t\t\t\t...done" << std::endl;
}
// COMMENTED DBG LOGS */ std::cout << "\t\t\tall threads finished..." << std::endl;
_backend_threads . clear ( ) ;
// COMMENTED DBG LOGS */ std::cout << "\t\t\tthread list cleared..." << std::endl;
return ret ;
}
2015-10-04 14:51:05 -04:00
bool
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : in_process_thread ( )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::in_process_thread ()" << std::endl;
2014-10-22 17:02:15 -04:00
if ( pthread_equal ( _main_thread , pthread_self ( ) ) ! = 0 ) {
return true ;
}
for ( std : : vector < pthread_t > : : const_iterator i = _backend_threads . begin ( ) ;
i ! = _backend_threads . end ( ) ; i + + ) {
if ( pthread_equal ( * i , pthread_self ( ) ) ! = 0 ) {
return true ;
}
}
return false ;
2014-04-30 13:46:41 -04:00
}
size_t
WavesAudioBackend : : __thread_stack_size ( )
{
// Align stacksize to PTHREAD_STACK_MIN.
2014-05-01 09:32:18 -04:00
# if defined (__APPLE__)
2014-04-30 13:46:41 -04:00
return ( ( ( thread_stack_size ( ) - 1 ) / PTHREAD_STACK_MIN ) + 1 ) * PTHREAD_STACK_MIN ;
2014-05-01 09:32:18 -04:00
# elif defined (PLATFORM_WINDOWS)
2014-04-30 13:46:41 -04:00
return thread_stack_size ( ) ;
# endif
}
2015-10-04 14:51:05 -04:00
uint32_t
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : process_thread_count ( )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::process_thread_count (): returns " << _backend_threads.size () << std::endl;
return _backend_threads . size ( ) ;
}
void
WavesAudioBackend : : _read_audio_data_from_device ( const float * input_buffer , pframes_t nframes )
{
2014-05-01 09:32:18 -04:00
# if defined(PLATFORM_WINDOWS)
2014-04-30 13:46:41 -04:00
const float * * buffer = ( const float * * ) input_buffer ;
for ( std : : vector < WavesAudioPort * > : : iterator it = _physical_audio_inputs . begin ( ) ;
it ! = _physical_audio_inputs . end ( ) ;
+ + it )
{
2015-05-12 21:07:09 -04:00
ARDOUR : : copy_vector ( ( * it ) - > buffer ( ) , * buffer , nframes ) ;
2014-04-30 13:46:41 -04:00
+ + buffer ;
}
# else
std : : vector < WavesAudioPort * > : : iterator it = _physical_audio_inputs . begin ( ) ;
// Well, let's de-interleave here:
const Sample * source = input_buffer ;
for ( uint32_t chann_cnt = 0 ; ( chann_cnt < _max_input_channels ) & & ( it ! = _physical_audio_inputs . end ( ) ) ; + + chann_cnt , + + source , + + it ) {
const Sample * src = source ;
Sample * tgt = ( * it ) - > buffer ( ) ;
for ( uint32_t frame = 0 ; frame < nframes ; + + frame , src + = _max_input_channels , + + tgt ) {
* tgt = * src ;
}
}
# endif
}
void
WavesAudioBackend : : _write_audio_data_to_device ( float * output_buffer , pframes_t nframes )
{
# if defined(_WnonononoINDOWS)
float * * buffer = ( float * * ) output_buffer ;
size_t copied_bytes = nframes * sizeof ( float ) ;
int i = 0 ;
for ( std : : vector < WavesAudioPort * > : : iterator it = _physical_audio_outputs . begin ( ) ;
it ! = _physical_audio_outputs . end ( ) ;
+ + it )
{
memcpy ( * buffer , ( * it ) - > buffer ( ) , copied_bytes ) ;
//*buffer = (*it)->buffer();
buffer + + ;
}
# else
// Well, let's interleave here:
std : : vector < WavesAudioPort * > : : iterator it = _physical_audio_outputs . begin ( ) ;
Sample * target = output_buffer ;
for ( uint32_t chann_cnt = 0 ;
( chann_cnt < _max_output_channels ) & & ( it ! = _physical_audio_outputs . end ( ) ) ;
+ + chann_cnt , + + target , + + it ) {
const Sample * src = ( Sample * ) ( ( * it ) - > get_buffer ( nframes ) ) ;
Sample * tgt = target ;
for ( uint32_t frame = 0 ; frame < nframes ; + + frame , tgt + = _max_output_channels , + + src ) {
* tgt = * src ;
}
}
# endif
}
static boost : : shared_ptr < WavesAudioBackend > __instance ;
boost : : shared_ptr < AudioBackend >
WavesAudioBackend : : __waves_backend_factory ( AudioEngine & e )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__waves_backend_factory ():" << std::endl;
if ( ! __instance ) {
2015-05-20 10:42:35 -04:00
__instance . reset ( new WavesAudioBackend ( e ) ) ;
2014-04-30 13:46:41 -04:00
}
return __instance ;
}
2014-05-01 09:32:18 -04:00
# if defined(PLATFORM_WINDOWS)
2014-04-30 13:46:41 -04:00
uint64_t WavesAudioBackend : : __performance_counter_frequency ;
# endif
2015-10-04 14:51:05 -04:00
int
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : __instantiate ( const std : : string & arg1 , const std : : string & arg2 )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__instantiate ():" << "[" << arg1 << "], [" << arg2 << "]" << std::endl;
__instantiated_name = arg1 ;
2014-05-01 09:32:18 -04:00
# if defined(PLATFORM_WINDOWS)
2014-04-30 13:46:41 -04:00
LARGE_INTEGER Frequency ;
QueryPerformanceFrequency ( & Frequency ) ;
__performance_counter_frequency = Frequency . QuadPart ;
# endif
return 0 ;
}
2015-10-04 14:51:05 -04:00
int
2014-04-30 13:46:41 -04:00
WavesAudioBackend : : __deinstantiate ( )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__deinstantiate ():" << std::endl;
__instance . reset ( ) ;
return 0 ;
}
bool
WavesAudioBackend : : __already_configured ( )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__already_configured ():" << std::endl;
return false ;
}
2014-10-23 07:02:02 -04:00
bool
WavesAudioBackend : : __available ( )
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::__available ():" << std::endl;
return true ;
}
2014-04-30 13:46:41 -04:00
void *
WavesAudioBackend : : private_handle ( ) const
{
// COMMENTED DBG LOGS */ std::cout << "WHY DO CALL IT: WavesAudioBackend::private_handle: " << std::endl;
return NULL ;
}
bool
WavesAudioBackend : : available ( ) const
{
// COMMENTED SECONDARY DBG LOGS */// std::cout << "WavesAudioBackend::available: " << std::endl;
return true ;
}
const std : : string &
WavesAudioBackend : : my_name ( ) const
{
// COMMENTED SECONDARY DBG LOGS */// std::cout << "WavesAudioBackend::my_name: " << _port_prefix_name << std::endl;
return __instantiated_name ;
}
bool
WavesAudioBackend : : can_monitor_input ( ) const
{
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::can_monitor_input: " << std::endl;
return false ;
}
std : : string WavesAudioBackend : : __instantiated_name ;
AudioBackendInfo WavesAudioBackend : : __backend_info = {
2014-05-01 09:32:18 -04:00
# ifdef __APPLE__
2014-04-30 13:46:41 -04:00
" CoreAudio " ,
2014-05-01 09:32:18 -04:00
# elif PLATFORM_WINDOWS
2014-04-30 13:46:41 -04:00
" ASIO " ,
# endif
__instantiate ,
WavesAudioBackend : : __deinstantiate ,
WavesAudioBackend : : __waves_backend_factory ,
WavesAudioBackend : : __already_configured ,
2014-10-23 07:02:02 -04:00
WavesAudioBackend : : __available ,
2014-04-30 13:46:41 -04:00
} ;
2014-09-30 20:35:31 -04:00