Audacity 3.2.0
Public Member Functions | Static Public Member Functions | Static Public Attributes | Static Protected Member Functions | Protected Attributes | Static Protected Attributes | List of all members
AudioIOBase Class Referenceabstract

A singleton object supporting queries of the state of any active audio streams, and audio device capabilities. More...

#include <AudioIOBase.h>

Inheritance diagram for AudioIOBase:
[legend]
Collaboration diagram for AudioIOBase:
[legend]

Public Member Functions

 AudioIOBase ()
 
virtual ~AudioIOBase ()
 
 AudioIOBase (const AudioIOBase &)=delete
 
AudioIOBaseoperator= (const AudioIOBase &)=delete
 
void SetCaptureMeter (const std::shared_ptr< AudacityProject > &project, const std::weak_ptr< Meter > &meter)
 
void SetPlaybackMeter (const std::shared_ptr< AudacityProject > &project, const std::weak_ptr< Meter > &meter)
 
void HandleDeviceChange ()
 update state after changing what audio devices are selected More...
 
wxString GetDeviceInfo () const
 Get diagnostic information on all the available audio I/O devices. More...
 
std::vector< AudioIODiagnosticsGetAllDeviceInfo ()
 Get diagnostic information for audio devices and also for extensions. More...
 
bool IsPaused () const
 Find out if playback / recording is currently paused. More...
 
virtual void StopStream ()=0
 
bool IsBusy () const
 Returns true if audio i/o is busy starting, stopping, playing, or recording. More...
 
bool IsStreamActive () const
 Returns true if the audio i/o is running at all, but not during cleanup. More...
 
bool IsStreamActive (int token) const
 
bool IsAudioTokenActive (int token) const
 Returns true if the stream is active, or even if audio I/O is busy cleaning up its data or writing to disk. More...
 
bool IsMonitoring () const
 Returns true if we're monitoring input (but not recording or playing actual audio) More...
 
void SetMixer (int inputSource)
 

Static Public Member Functions

static AudioIOBaseGet ()
 
static std::vector< long > GetSupportedPlaybackRates (int DevIndex=-1)
 Get a list of sample rates the output (playback) device supports. More...
 
static long GetClosestSupportedPlaybackRate (int devIndex, long rate)
 Find the closest supported sample rate for given playback device. More...
 
static std::vector< long > GetSupportedCaptureRates (int devIndex=-1)
 Get a list of sample rates the input (recording) device supports. More...
 
static long GetClosestSupportedCaptureRate (int devIndex, long rate)
 Find the closest supported sample rate for given recording device. More...
 
static std::vector< long > GetSupportedSampleRates (int playDevice=-1, int recDevice=-1)
 Get a list of sample rates the current input/output device combination supports. More...
 
static long GetClosestSupportedSampleRate (int playDevice, int recDevice, long rate)
 Find the closest supported sample rate for given playback and recording devices. More...
 
static int GetOptimalSupportedSampleRate ()
 Get a supported sample rate which can be used a an optimal default. More...
 
static bool IsPlaybackRateSupported (int devIndex, long rate)
 Check if the specified playback rate is supported by a device. More...
 
static bool IsCaptureRateSupported (int devIndex, long rate)
 Check if the specified sample rate is supported by a device. More...
 

Static Public Attributes

static const int StandardRates []
 Array of common audio sample rates. More...
 
static const int NumStandardRates = WXSIZEOF(AudioIOBase::StandardRates)
 How many standard sample rates there are. More...
 

Static Protected Member Functions

static wxString DeviceName (const PaDeviceInfo *info)
 
static wxString HostName (const PaDeviceInfo *info)
 
static int getRecordDevIndex (const wxString &devName={})
 get the index of the supplied (named) recording device, or the device selected in the preferences if none given. More...
 
static int getPlayDevIndex (const wxString &devName={})
 get the index of the device selected in the preferences. More...
 

Protected Attributes

std::weak_ptr< AudacityProjectmOwningProject
 
std::atomic< bool > mPaused { false }
 True if audio playback is paused. More...
 
int mStreamToken { 0 }
 
double mRate
 Audio playback rate in samples per second. More...
 
PaStreammPortStreamV19
 
std::weak_ptr< MetermInputMeter {}
 
std::weak_ptr< MetermOutputMeter {}
 
bool mInputMixerWorks
 Can we control the hardware input level? More...
 
std::vector< std::unique_ptr< AudioIOExtBase > > mAudioIOExt
 

Static Protected Attributes

static std::unique_ptr< AudioIOBaseugAudioIO
 
static std::map< int, std::vector< long > > mCachedPlaybackRates
 
static std::map< int, std::vector< long > > mCachedCaptureRates
 
static std::map< std::pair< int, int >, std::vector< long > > mCachedSampleRates
 
static int mCurrentPlaybackIndex { -1 }
 
static int mCurrentCaptureIndex { -1 }
 
static double mCachedBestRateIn { 0.0 }
 
static const int RatesToTry []
 Array of audio sample rates to try to use. More...
 
static const int NumRatesToTry = WXSIZEOF(AudioIOBase::RatesToTry)
 How many sample rates to try. More...
 

Detailed Description

A singleton object supporting queries of the state of any active audio streams, and audio device capabilities.

Definition at line 102 of file AudioIOBase.h.

Constructor & Destructor Documentation

◆ AudioIOBase() [1/2]

AudioIOBase::AudioIOBase ( )
default

◆ ~AudioIOBase()

AudioIOBase::~AudioIOBase ( )
virtualdefault

◆ AudioIOBase() [2/2]

AudioIOBase::AudioIOBase ( const AudioIOBase )
delete

Member Function Documentation

◆ DeviceName()

wxString AudioIOBase::DeviceName ( const PaDeviceInfo *  info)
staticprotected

Definition at line 76 of file AudioIOBase.cpp.

77{
78 wxString infoName = wxSafeConvertMB2WX(info->name);
79
80 return infoName;
81}

Referenced by GetDeviceInfo(), getPlayDevIndex(), getRecordDevIndex(), and AudioIO::Init().

Here is the caller graph for this function:

◆ Get()

AudioIOBase * AudioIOBase::Get ( )
static

◆ GetAllDeviceInfo()

auto AudioIOBase::GetAllDeviceInfo ( )

Get diagnostic information for audio devices and also for extensions.

Definition at line 1055 of file AudioIOBase.cpp.

1056{
1057 std::vector<AudioIODiagnostics> result;
1058 result.push_back({
1059 wxT("audiodev.txt"), GetDeviceInfo(), wxT("Audio Device Info") });
1060 for( auto &pExt : mAudioIOExt )
1061 if ( pExt )
1062 result.emplace_back(pExt->Dump());
1063 return result;
1064}
wxT("CloseDown"))
wxString GetDeviceInfo() const
Get diagnostic information on all the available audio I/O devices.
std::vector< std::unique_ptr< AudioIOExtBase > > mAudioIOExt
Definition: AudioIOBase.h:381

References wxT().

Here is the call graph for this function:

◆ GetClosestSupportedCaptureRate()

long AudioIOBase::GetClosestSupportedCaptureRate ( int  devIndex,
long  rate 
)
static

Find the closest supported sample rate for given recording device.

Attempts to find the sample rate that is closest to the requested rate, and is supported by the recording device.

If device is not specified the currently selected device will be used.

Sample rate check order:

  • the exact requested rate
  • higher available rates
  • lower available rates

returns 0 if none is found or the input rate is invalid.

Definition at line 542 of file AudioIOBase.cpp.

543{
544 long supportedRate = 0;
545 if (devIndex == -1)
546 { // not given a device, look up in prefs / default
547 devIndex = getRecordDevIndex();
548 }
549
550 if (rate == 0)
551 { // not given a correct rate
552 return supportedRate;
553 }
554
555 // Check if we can use the cached rate
556 if (mCachedCaptureRates.count(devIndex)
557 && (make_iterator_range(mCachedCaptureRates[devIndex]).contains(rate)))
558 {
559 supportedRate = rate;
560 return supportedRate;
561 }
562
563
564 // First we will probe the requested state
565 std::vector<long> rates = { rate };
566
567 // Next default rates higher than requested
568 auto higherRatesIt = std::upper_bound(RatesToTry, RatesToTry + NumRatesToTry, rate);
569 std::copy(higherRatesIt, RatesToTry + NumRatesToTry, std::back_inserter(rates));
570
571 // Last default rates lower than requested in reverse order
572 auto lowerRatesIt = std::lower_bound(RatesToTry, RatesToTry + NumRatesToTry, rate);
573 std::copy(std::make_reverse_iterator(lowerRatesIt), std::make_reverse_iterator(RatesToTry),
574 std::back_inserter(rates));
575
576 for (const long rateToTry : rates)
577 {
578 if (IsCaptureRateSupported(devIndex, rateToTry))
579 {
580 supportedRate = rateToTry;
581 break;
582 }
583 Pa_Sleep( 10 ); // There are ALSA drivers that don't like being probed
584 // too quickly.
585 }
586
587 return supportedRate;
588}
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
Definition: IteratorX.h:210
static bool IsCaptureRateSupported(int devIndex, long rate)
Check if the specified sample rate is supported by a device.
static std::map< int, std::vector< long > > mCachedCaptureRates
Definition: AudioIOBase.h:337
static const int NumRatesToTry
How many sample rates to try.
Definition: AudioIOBase.h:376
static int getRecordDevIndex(const wxString &devName={})
get the index of the supplied (named) recording device, or the device selected in the preferences if ...
static const int RatesToTry[]
Array of audio sample rates to try to use.
Definition: AudioIOBase.h:374
void copy(const T *src, T *dst, int32_t n)
Definition: VectorOps.h:40

References staffpad::vo::copy(), getRecordDevIndex(), IsCaptureRateSupported(), make_iterator_range(), mCachedCaptureRates, NumRatesToTry, and RatesToTry.

Referenced by AudioIO::GetBestRate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetClosestSupportedPlaybackRate()

long AudioIOBase::GetClosestSupportedPlaybackRate ( int  devIndex,
long  rate 
)
static

Find the closest supported sample rate for given playback device.

Attempts to find the sample rate that is closest to the requested rate, and is supported by the playback device.

If device is not specified the currently selected device will be used.

Sample rate check order:

  • the exact requested rate
  • higher available rates
  • lower available rates

returns 0 if none is found or the input rate is invalid.

Definition at line 505 of file AudioIOBase.cpp.

506{
507 long supportedRate = 0;
508 if (devIndex == -1)
509 { // weren't given a device index, get the prefs / default one
510 devIndex = getPlayDevIndex();
511 }
512
513 if (rate == 0.0)
514 { // not given a correct rate
515 return 0;
516 }
517
518 // First we will probe the requested state
519 std::vector<long> rates = { rate };
520 // Next default rates higher than requested
521 auto higherRatesIt = std::upper_bound(RatesToTry, RatesToTry + NumRatesToTry, rate);
522 std::copy(higherRatesIt, RatesToTry + NumRatesToTry, std::back_inserter(rates));
523 // Last default rates lower than requested in reverse order
524 auto lowerRatesIt = std::lower_bound(RatesToTry, RatesToTry + NumRatesToTry, rate);
525 std::copy(std::make_reverse_iterator(lowerRatesIt), std::make_reverse_iterator(RatesToTry),
526 std::back_inserter(rates));
527
528 for (const long rateToTry : rates)
529 {
530 if (IsPlaybackRateSupported(devIndex, rateToTry))
531 {
532 supportedRate = rateToTry;
533 break;
534 }
535 Pa_Sleep( 10 ); // There are ALSA drivers that don't like being probed
536 // too quickly.
537 }
538
539 return supportedRate;
540}
static bool IsPlaybackRateSupported(int devIndex, long rate)
Check if the specified playback rate is supported by a device.
static int getPlayDevIndex(const wxString &devName={})
get the index of the device selected in the preferences.

References staffpad::vo::copy(), getPlayDevIndex(), IsPlaybackRateSupported(), NumRatesToTry, and RatesToTry.

Referenced by AudioIO::GetBestRate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetClosestSupportedSampleRate()

long AudioIOBase::GetClosestSupportedSampleRate ( int  playDevice,
int  recDevice,
long  rate 
)
static

Find the closest supported sample rate for given playback and recording devices.

Attempts to find the sample rate that is closest to the requested rate, and is supported by both playback and recording devices.

If devices are not specified the currently selected devices will be used.

Sample rate check order:

  • the exact requested rate
  • higher available rates
  • lower available rates

returns 0 if none is found or the input rate is invalid.

Definition at line 590 of file AudioIOBase.cpp.

592{
593 long supportedRate = 0;
594
595 // Not given device indices, look up prefs
596 if (playDevice == -1) {
597 playDevice = getPlayDevIndex();
598 }
599 if (recDevice == -1) {
600 recDevice = getRecordDevIndex();
601 }
602
603 // Check if we can use the cached rates
604 std::pair<int, int> devicePair { playDevice, recDevice };
605 if (mCachedSampleRates.count(devicePair) &&
606 make_iterator_range(mCachedSampleRates.at(devicePair)).contains(rate))
607 {
608 return rate;
609 }
610
611 // First we will probe the requested state
612 std::vector<long> rates { rate };
613
614 // Next default rates higher than requested
615 auto higherRatesIt = std::upper_bound(RatesToTry, RatesToTry + NumRatesToTry, rate);
616 std::copy(higherRatesIt, RatesToTry + NumRatesToTry, std::back_inserter(rates));
617
618 // Last default rates lower than requested in reverse order
619 auto lowerRatesIt = std::lower_bound(RatesToTry, RatesToTry + NumRatesToTry, rate);
620 std::copy(std::make_reverse_iterator(lowerRatesIt), std::make_reverse_iterator(RatesToTry),
621 std::back_inserter(rates));
622
623 for (const long rateToTry : rates)
624 {
625 if (IsPlaybackRateSupported(playDevice, rateToTry) &&
626 IsCaptureRateSupported(recDevice, rateToTry))
627 {
628 supportedRate = rateToTry;
629 break;
630 }
631 Pa_Sleep( 10 ); // There are ALSA drivers that don't like being probed
632 // too quickly.
633 }
634
635 mCachedSampleRates[devicePair].push_back(supportedRate);
636
637 return supportedRate;
638}
static std::map< std::pair< int, int >, std::vector< long > > mCachedSampleRates
Definition: AudioIOBase.h:338

References staffpad::vo::copy(), getPlayDevIndex(), getRecordDevIndex(), IsCaptureRateSupported(), IsPlaybackRateSupported(), make_iterator_range(), mCachedSampleRates, NumRatesToTry, and RatesToTry.

Referenced by AudioIO::GetBestRate(), GetOptimalSupportedSampleRate(), and HandleDeviceChange().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetDeviceInfo()

wxString AudioIOBase::GetDeviceInfo ( ) const

Get diagnostic information on all the available audio I/O devices.

Definition at line 812 of file AudioIOBase.cpp.

813{
814 wxStringOutputStream o;
815 wxTextOutputStream s(o, wxEOL_UNIX);
816
817 if (IsStreamActive()) {
818 return XO("Stream is active ... unable to gather information.\n")
819 .Translation();
820 }
821
822
823 // FIXME: TRAP_ERR PaErrorCode not handled. 3 instances in GetDeviceInfo().
824 int recDeviceNum = Pa_GetDefaultInputDevice();
825 int playDeviceNum = Pa_GetDefaultOutputDevice();
826 int cnt = Pa_GetDeviceCount();
827
828 // PRL: why only into the log?
829 wxLogDebug(wxT("Portaudio reports %d audio devices"),cnt);
830
831 s << wxT("==============================\n");
832 s << XO("Default recording device number: %d\n").Format( recDeviceNum );
833 s << XO("Default playback device number: %d\n").Format( playDeviceNum);
834
835 auto recDevice = AudioIORecordingDevice.Read();
836 auto playDevice = AudioIOPlaybackDevice.Read();
837 int j;
838
839 // This gets info on all available audio devices (input and output)
840 if (cnt <= 0) {
841 s << XO("No devices found\n");
842 return o.GetString();
843 }
844
845 const PaDeviceInfo* info;
846
847 for (j = 0; j < cnt; j++) {
848 s << wxT("==============================\n");
849
850 info = Pa_GetDeviceInfo(j);
851 if (!info) {
852 s << XO("Device info unavailable for: %d\n").Format( j );
853 continue;
854 }
855
856 wxString name = DeviceName(info);
857 s << XO("Device ID: %d\n").Format( j );
858 s << XO("Device name: %s\n").Format( name );
859 s << XO("Host name: %s\n").Format( HostName(info) );
860 s << XO("Recording channels: %d\n").Format( info->maxInputChannels );
861 s << XO("Playback channels: %d\n").Format( info->maxOutputChannels );
862 s << XO("Low Recording Latency: %g\n").Format( info->defaultLowInputLatency );
863 s << XO("Low Playback Latency: %g\n").Format( info->defaultLowOutputLatency );
864 s << XO("High Recording Latency: %g\n").Format( info->defaultHighInputLatency );
865 s << XO("High Playback Latency: %g\n").Format( info->defaultHighOutputLatency );
866
867 if (info->maxOutputChannels)
868 {
869 auto rates = GetSupportedPlaybackRates(j);
870
871 /* i18n-hint: Supported, meaning made available by the system */
872 s << XO("Supported Playback Rates:\n");
873 for (int k = 0; k < (int) rates.size(); k++) {
874 s << wxT(" ") << (int) rates[k] << wxT("\n");
875 }
876 }
877
878 if (info->maxInputChannels)
879 {
880 auto rates = GetSupportedCaptureRates(j);
881
882 /* i18n-hint: Supported, meaning made available by the system */
883 s << XO("Supported Capture Rates:\n");
884 for (int k = 0; k < (int) rates.size(); k++) {
885 s << wxT(" ") << (int) rates[k] << wxT("\n");
886 }
887 }
888
889 if (name == playDevice && info->maxOutputChannels > 0)
890 playDeviceNum = j;
891
892 if (name == recDevice && info->maxInputChannels > 0)
893 recDeviceNum = j;
894
895 // Sometimes PortAudio returns -1 if it cannot find a suitable default
896 // device, so we just use the first one available
897 if (recDeviceNum < 0 && info->maxInputChannels > 0){
898 recDeviceNum = j;
899 }
900 if (playDeviceNum < 0 && info->maxOutputChannels > 0){
901 playDeviceNum = j;
902 }
903 }
904
905 bool haveRecDevice = (recDeviceNum >= 0);
906 bool havePlayDevice = (playDeviceNum >= 0);
907
908 s << wxT("==============================\n");
909 if (haveRecDevice)
910 s << XO("Selected recording device: %d - %s\n").Format( recDeviceNum, recDevice );
911 else
912 s << XO("No recording device found for '%s'.\n").Format( recDevice );
913
914 if (havePlayDevice)
915 s << XO("Selected playback device: %d - %s\n").Format( playDeviceNum, playDevice );
916 else
917 s << XO("No playback device found for '%s'.\n").Format( playDevice );
918
919 std::vector<long> supportedSampleRates;
920
921 if (havePlayDevice && haveRecDevice) {
922 supportedSampleRates = GetSupportedSampleRates(playDeviceNum, recDeviceNum);
923
924 s << XO("Supported Rates:\n");
925 for (int k = 0; k < (int) supportedSampleRates.size(); k++) {
926 s << wxT(" ") << (int)supportedSampleRates[k] << wxT("\n");
927 }
928 }
929 else {
930 s << XO("Cannot check mutual sample rates without both devices.\n");
931 return o.GetString();
932 }
933
934#if defined(USE_PORTMIXER)
935 if (supportedSampleRates.size() > 0)
936 {
937 int highestSampleRate = supportedSampleRates.back();
938 bool EmulateMixerInputVol = true;
939 float MixerInputVol = 1.0;
940 float MixerOutputVol = 1.0;
941
942 int error;
943
944 PaStream *stream;
945
946 PaStreamParameters playbackParameters;
947
948 playbackParameters.device = playDeviceNum;
949 playbackParameters.sampleFormat = paFloat32;
950 playbackParameters.hostApiSpecificStreamInfo = NULL;
951 playbackParameters.channelCount = 1;
952 if (Pa_GetDeviceInfo(playDeviceNum)){
953 playbackParameters.suggestedLatency =
954 Pa_GetDeviceInfo(playDeviceNum)->defaultLowOutputLatency;
955 }
956 else
957 playbackParameters.suggestedLatency =
959
960 PaStreamParameters captureParameters;
961
962 captureParameters.device = recDeviceNum;
963 captureParameters.sampleFormat = paFloat32;;
964 captureParameters.hostApiSpecificStreamInfo = NULL;
965 captureParameters.channelCount = 1;
966 if (Pa_GetDeviceInfo(recDeviceNum)){
967 captureParameters.suggestedLatency =
968 Pa_GetDeviceInfo(recDeviceNum)->defaultLowInputLatency;
969 }
970 else
971 captureParameters.suggestedLatency =
973
974 // Not really doing I/O so pass nullptr for the callback function
975 error = Pa_OpenStream(&stream,
976 &captureParameters, &playbackParameters,
977 highestSampleRate, paFramesPerBufferUnspecified,
978 paClipOff | paDitherOff,
979 nullptr, NULL);
980
981 if (error) {
982 error = Pa_OpenStream(&stream,
983 &captureParameters, NULL,
984 highestSampleRate, paFramesPerBufferUnspecified,
985 paClipOff | paDitherOff,
986 nullptr, NULL);
987 }
988
989 if (error) {
990 s << XO("Received %d while opening devices\n").Format( error );
991 return o.GetString();
992 }
993
994 PxMixer *PortMixer = Px_OpenMixer(stream, recDeviceNum, playDeviceNum, 0);
995
996 if (!PortMixer) {
997 s << XO("Unable to open Portmixer\n");
998 Pa_CloseStream(stream);
999 return o.GetString();
1000 }
1001
1002 s << wxT("==============================\n");
1003 s << XO("Available mixers:\n");
1004
1005 // FIXME: ? PortMixer errors on query not reported in GetDeviceInfo
1006 cnt = Px_GetNumMixers(stream);
1007 for (int i = 0; i < cnt; i++) {
1008 wxString name = wxSafeConvertMB2WX(Px_GetMixerName(stream, i));
1009 s << XO("%d - %s\n").Format( i, name );
1010 }
1011
1012 s << wxT("==============================\n");
1013 s << XO("Available recording sources:\n");
1014 cnt = Px_GetNumInputSources(PortMixer);
1015 for (int i = 0; i < cnt; i++) {
1016 wxString name = wxSafeConvertMB2WX(Px_GetInputSourceName(PortMixer, i));
1017 s << XO("%d - %s\n").Format( i, name );
1018 }
1019
1020 s << wxT("==============================\n");
1021 s << XO("Available playback volumes:\n");
1022 cnt = Px_GetNumOutputVolumes(PortMixer);
1023 for (int i = 0; i < cnt; i++) {
1024 wxString name = wxSafeConvertMB2WX(Px_GetOutputVolumeName(PortMixer, i));
1025 s << XO("%d - %s\n").Format( i, name );
1026 }
1027
1028 // Check, if PortMixer supports adjusting input levels on the interface
1029
1030 MixerInputVol = Px_GetInputVolume(PortMixer);
1031 EmulateMixerInputVol = false;
1032 Px_SetInputVolume(PortMixer, 0.0);
1033 if (Px_GetInputVolume(PortMixer) > 0.1)
1034 EmulateMixerInputVol = true;
1035 Px_SetInputVolume(PortMixer, 0.2f);
1036 if (Px_GetInputVolume(PortMixer) < 0.1 ||
1037 Px_GetInputVolume(PortMixer) > 0.3)
1038 EmulateMixerInputVol = true;
1039 Px_SetInputVolume(PortMixer, MixerInputVol);
1040
1041 Pa_CloseStream(stream);
1042
1043 s << wxT("==============================\n");
1044 s << ( EmulateMixerInputVol
1045 ? XO("Recording volume is emulated\n")
1046 : XO("Recording volume is native\n") );
1047
1048 Px_CloseMixer(PortMixer);
1049
1050 } //end of massive if statement if a valid sample rate has been found
1051#endif
1052 return o.GetString();
1053}
DoubleSetting AudioIOLatencyCorrection
StringSetting AudioIOPlaybackDevice
StringSetting AudioIORecordingDevice
void PaStream
Definition: AudioIOBase.h:25
XO("Cut/Copy/Paste")
wxString name
Definition: TagsEditor.cpp:166
static wxString HostName(const PaDeviceInfo *info)
Definition: AudioIOBase.cpp:83
bool IsStreamActive() const
Returns true if the audio i/o is running at all, but not during cleanup.
static wxString DeviceName(const PaDeviceInfo *info)
Definition: AudioIOBase.cpp:76
static std::vector< long > GetSupportedSampleRates(int playDevice=-1, int recDevice=-1)
Get a list of sample rates the current input/output device combination supports.
static std::vector< long > GetSupportedPlaybackRates(int DevIndex=-1)
Get a list of sample rates the output (playback) device supports.
static std::vector< long > GetSupportedCaptureRates(int devIndex=-1)
Get a list of sample rates the input (recording) device supports.
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:207
const T & GetDefault() const
Definition: Prefs.h:199

References AudioIOLatencyCorrection, AudioIOPlaybackDevice, AudioIORecordingDevice, DeviceName(), Setting< T >::GetDefault(), GetSupportedCaptureRates(), GetSupportedPlaybackRates(), GetSupportedSampleRates(), HostName(), IsStreamActive(), name, Setting< T >::Read(), anonymous_namespace{ExportOpus.cpp}::supportedSampleRates, wxT(), and XO().

Here is the call graph for this function:

◆ GetOptimalSupportedSampleRate()

int AudioIOBase::GetOptimalSupportedSampleRate ( )
static

Get a supported sample rate which can be used a an optimal default.

Currently, this uses the first supported rate in the list [44100, 48000, highest sample rate]. Used in Project as a default value for project rates if one cannot be retrieved from the preferences. So all in all not that useful or important really

Todo:
: should this take into account PortAudio's value for PaDeviceInfo::defaultSampleRate? In principal this should let us work out which rates are "real" and which resampled in the drivers, and so prefer the real rates.

Definition at line 669 of file AudioIOBase.cpp.

670{
671 auto rate = GetClosestSupportedSampleRate(-1, -1, 44100);
672
673 // if there are no supported rates, the next bit crashes. So check first,
674 // and give them a "sensible" value if there are no valid values. They
675 // will still get an error later, but with any luck may have changed
676 // something by then. It's no worse than having an invalid default rate
677 // stored in the preferences, which we don't check for
678 if (rate == 0)
679 {
680 return 44100;
681 }
682
683 return rate;
684}
static long GetClosestSupportedSampleRate(int playDevice, int recDevice, long rate)
Find the closest supported sample rate for given playback and recording devices.

References GetClosestSupportedSampleRate().

Here is the call graph for this function:

◆ getPlayDevIndex()

int AudioIOBase::getPlayDevIndex ( const wxString &  devName = {})
staticprotected

get the index of the device selected in the preferences.

If the device isn't found, returns -1

get the index of the supplied (named) playback device, or the device selected in the preferences if none given.

Pure utility function, but it comes round a number of times in the code and would be neater done once. If the device isn't found, return the default device index.

Definition at line 700 of file AudioIOBase.cpp.

701{
702 wxString devName(devNameArg);
703 // if we don't get given a device, look up the preferences
704 if (devName.empty())
705 devName = AudioIOPlaybackDevice.Read();
706
707 auto hostName = AudioIOHost.Read();
708 PaHostApiIndex hostCnt = Pa_GetHostApiCount();
709 PaHostApiIndex hostNum;
710 for (hostNum = 0; hostNum < hostCnt; hostNum++)
711 {
712 const PaHostApiInfo *hinfo = Pa_GetHostApiInfo(hostNum);
713 if (hinfo && wxString(wxSafeConvertMB2WX(hinfo->name)) == hostName)
714 {
715 for (PaDeviceIndex hostDevice = 0; hostDevice < hinfo->deviceCount; hostDevice++)
716 {
717 PaDeviceIndex deviceNum = Pa_HostApiDeviceIndexToDeviceIndex(hostNum, hostDevice);
718
719 const PaDeviceInfo *dinfo = Pa_GetDeviceInfo(deviceNum);
720 if (dinfo && DeviceName(dinfo) == devName && dinfo->maxOutputChannels > 0 )
721 {
722 // this device name matches the stored one, and works.
723 // So we say this is the answer and return it
724 return deviceNum;
725 }
726 }
727
728 // The device wasn't found so use the default for this host.
729 // LL: At this point, preferences and active no longer match.
730 return hinfo->defaultOutputDevice;
731 }
732 }
733
734 // The host wasn't found, so use the default output device.
735 // FIXME: TRAP_ERR PaErrorCode not handled well (this code is similar to input code
736 // and the input side has more comments.)
737
738 PaDeviceIndex deviceNum = Pa_GetDefaultOutputDevice();
739
740 // Sometimes PortAudio returns -1 if it cannot find a suitable default
741 // device, so we just use the first one available
742 //
743 // LL: At this point, preferences and active no longer match
744 //
745 // And I can't imagine how far we'll get specifying an "invalid" index later
746 // on...are we certain "0" even exists?
747 if (deviceNum < 0) {
748 assert(false);
749 deviceNum = 0;
750 }
751
752 return deviceNum;
753}
StringSetting AudioIOHost

References AudioIOHost, AudioIOPlaybackDevice, DeviceName(), and Setting< T >::Read().

Referenced by GetClosestSupportedPlaybackRate(), GetClosestSupportedSampleRate(), GetSupportedPlaybackRates(), GetSupportedSampleRates(), HandleDeviceChange(), AudioIO::Init(), IsPlaybackRateSupported(), AudioIO::StartPortAudioStream(), and AudioIO::ValidateDeviceNames().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getRecordDevIndex()

int AudioIOBase::getRecordDevIndex ( const wxString &  devName = {})
staticprotected

get the index of the supplied (named) recording device, or the device selected in the preferences if none given.

Pure utility function, but it comes round a number of times in the code and would be neater done once. If the device isn't found, return the default device index.

Definition at line 755 of file AudioIOBase.cpp.

756{
757 wxString devName(devNameArg);
758 // if we don't get given a device, look up the preferences
759 if (devName.empty())
760 devName = AudioIORecordingDevice.Read();
761
762 auto hostName = AudioIOHost.Read();
763 PaHostApiIndex hostCnt = Pa_GetHostApiCount();
764 PaHostApiIndex hostNum;
765 for (hostNum = 0; hostNum < hostCnt; hostNum++)
766 {
767 const PaHostApiInfo *hinfo = Pa_GetHostApiInfo(hostNum);
768 if (hinfo && wxString(wxSafeConvertMB2WX(hinfo->name)) == hostName)
769 {
770 for (PaDeviceIndex hostDevice = 0; hostDevice < hinfo->deviceCount; hostDevice++)
771 {
772 PaDeviceIndex deviceNum = Pa_HostApiDeviceIndexToDeviceIndex(hostNum, hostDevice);
773
774 const PaDeviceInfo *dinfo = Pa_GetDeviceInfo(deviceNum);
775 if (dinfo && DeviceName(dinfo) == devName && dinfo->maxInputChannels > 0 )
776 {
777 // this device name matches the stored one, and works.
778 // So we say this is the answer and return it
779 return deviceNum;
780 }
781 }
782
783 // The device wasn't found so use the default for this host.
784 // LL: At this point, preferences and active no longer match.
785 return hinfo->defaultInputDevice;
786 }
787 }
788
789 // The host wasn't found, so use the default input device.
790 // FIXME: TRAP_ERR PaErrorCode not handled well in getRecordDevIndex()
791 PaDeviceIndex deviceNum = Pa_GetDefaultInputDevice();
792
793 // Sometimes PortAudio returns -1 if it cannot find a suitable default
794 // device, so we just use the first one available
795 // PortAudio has an error reporting function. We should log/report the error?
796 //
797 // LL: At this point, preferences and active no longer match
798 //
799 // And I can't imagine how far we'll get specifying an "invalid" index later
800 // on...are we certain "0" even exists?
801 if (deviceNum < 0) {
802 // JKC: This will happen if you run with no config file
803 // This happens once. Config file will exist on the next run.
804 // TODO: Look into this a bit more. Could be relevant to blank Device Toolbar.
805 wxLogDebug("PortAudio returns -1, cannot find a suitable default device, so we just use the first one available");
806 deviceNum = 0;
807 }
808
809 return deviceNum;
810}

References AudioIOHost, AudioIORecordingDevice, DeviceName(), and Setting< T >::Read().

Referenced by GetClosestSupportedCaptureRate(), GetClosestSupportedSampleRate(), GetSupportedCaptureRates(), GetSupportedSampleRates(), HandleDeviceChange(), AudioIO::Init(), IsCaptureRateSupported(), AudioIO::StartPortAudioStream(), and AudioIO::ValidateDeviceNames().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetSupportedCaptureRates()

std::vector< long > AudioIOBase::GetSupportedCaptureRates ( int  devIndex = -1)
static

Get a list of sample rates the input (recording) device supports.

If no information about available sample rates can be fetched, an empty list is returned.

You can explicitly give the index of the device. If you don't give it, the currently selected device from the preferences will be used.

Definition at line 485 of file AudioIOBase.cpp.

486{
487 if (devIndex == -1)
488 { // weren't given a device index, get the prefs / default one
489 devIndex = getRecordDevIndex();
490 }
491
492 std::vector<long> supportedRates;
493
494 for(const long rate : RatesToTry) {
495 if (IsCaptureRateSupported(devIndex, rate)) {
496 supportedRates.push_back(rate);
497 }
498 Pa_Sleep( 10 ); // There are ALSA drivers that don't like being probed
499 // too quickly.
500 }
501
502 return supportedRates;
503}

References getRecordDevIndex(), IsCaptureRateSupported(), and RatesToTry.

Referenced by GetDeviceInfo(), and GetSupportedSampleRates().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetSupportedPlaybackRates()

std::vector< long > AudioIOBase::GetSupportedPlaybackRates ( int  DevIndex = -1)
static

Get a list of sample rates the output (playback) device supports.

If no information about available sample rates can be fetched, an empty list is returned.

You can explicitly give the index of the device. If you don't give it, the currently selected device from the preferences will be used.

Definition at line 465 of file AudioIOBase.cpp.

466{
467 if (devIndex == -1)
468 { // weren't given a device index, get the prefs / default one
469 devIndex = getPlayDevIndex();
470 }
471
472 std::vector<long> supportedRates;
473
474 for(const long rate : RatesToTry) {
475 if (IsPlaybackRateSupported(devIndex, rate)) {
476 supportedRates.push_back(rate);
477 }
478 Pa_Sleep( 10 ); // There are ALSA drivers that don't like being probed
479 // too quickly.
480 }
481
482 return supportedRates;
483}

References getPlayDevIndex(), IsPlaybackRateSupported(), and RatesToTry.

Referenced by GetDeviceInfo(), and GetSupportedSampleRates().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetSupportedSampleRates()

std::vector< long > AudioIOBase::GetSupportedSampleRates ( int  playDevice = -1,
int  recDevice = -1 
)
static

Get a list of sample rates the current input/output device combination supports.

Since there is no concept (yet) for different input/output sample rates, this currently returns only sample rates that are supported on both the output and input device. If no information about available sample rates can be fetched, it returns a default list. You can explicitly give the indexes of the playDevice/recDevice. If you don't give them, the selected devices from the preferences will be used.

Definition at line 640 of file AudioIOBase.cpp.

641{
642 // Not given device indices, look up prefs
643 if (playDevice == -1)
644 {
645 playDevice = getPlayDevIndex();
646 }
647 if (recDevice == -1)
648 {
649 recDevice = getRecordDevIndex();
650 }
651
652 auto playback = GetSupportedPlaybackRates(playDevice);
653 auto capture = GetSupportedCaptureRates(recDevice);
654
655 // Return only sample rates which are in both arrays
656 std::vector<long> result;
657
658 std::set_intersection(playback.begin(), playback.end(),
659 capture.begin(), capture.end(),
660 std::back_inserter(result));
661
662 return result;
663}

References getPlayDevIndex(), getRecordDevIndex(), GetSupportedCaptureRates(), and GetSupportedPlaybackRates().

Referenced by GetDeviceInfo().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ HandleDeviceChange()

void AudioIOBase::HandleDeviceChange ( )

update state after changing what audio devices are selected

Called when the devices stored in the preferences are changed to update the audio mixer capabilities

Todo:
: Make this do a sample rate query and store the result in the AudioIO object to avoid doing it later? Would simplify the GetSupported*Rate functions considerably

Definition at line 112 of file AudioIOBase.cpp.

113{
114 // This should not happen, but it would screw things up if it did.
115 // Vaughan, 2010-10-08: But it *did* happen, due to a bug, and nobody
116 // caught it because this method just returned. Added wxASSERT().
117 wxASSERT(!IsStreamActive());
118 if (IsStreamActive())
119 return;
120
121 // get the selected record and playback devices
122 const int playDeviceNum = getPlayDevIndex();
123 const int recDeviceNum = getRecordDevIndex();
124
125 // If no change needed, return
126 if (mCurrentPlaybackIndex == playDeviceNum &&
127 mCurrentCaptureIndex == recDeviceNum)
128 return;
129
130 // Update playback/capture device indices
131 mCurrentPlaybackIndex = playDeviceNum;
132 mCurrentCaptureIndex = recDeviceNum;
133 mCachedBestRateIn = 0.0;
134
135#if defined(USE_PORTMIXER)
136
137 // if we have a PortMixer object, close it down
138 if (mPortMixer) {
139 #if __WXMAC__
140 // on the Mac we must make sure that we restore the hardware playthrough
141 // state of the sound device to what it was before, because there isn't
142 // a UI for this (!)
143 if (Px_SupportsPlaythrough(mPortMixer) && mPreviousHWPlaythrough >= 0.0)
144 Px_SetPlaythrough(mPortMixer, mPreviousHWPlaythrough);
145 mPreviousHWPlaythrough = -1.0;
146 #endif
147 Px_CloseMixer(mPortMixer);
148 mPortMixer = NULL;
149 }
150
151 // Looking for highest supported sample rate for a given
152 // play/rec device pair
153 long highestSampleRate = GetClosestSupportedSampleRate(playDeviceNum, recDeviceNum, INT_MAX);
154 if (highestSampleRate == 0)
155 {
156 // we don't actually have any rates that work for Rec and Play. Guess one
157 // to use for messing with the mixer, which doesn't actually do either
158 highestSampleRate = 44100;
159 }
160
161 mInputMixerWorks = false;
162
163 int error;
164 // This tries to open the device with the samplerate worked out above, which
165 // will be the highest available for play and record on the device, or
166 // 44.1kHz if the info cannot be fetched.
167
168 PaStream *stream;
169
170 PaStreamParameters playbackParameters;
171
172 playbackParameters.device = playDeviceNum;
173 playbackParameters.sampleFormat = paFloat32;
174 playbackParameters.hostApiSpecificStreamInfo = NULL;
175 playbackParameters.channelCount = 1;
176 if (Pa_GetDeviceInfo(playDeviceNum))
177 playbackParameters.suggestedLatency =
178 Pa_GetDeviceInfo(playDeviceNum)->defaultLowOutputLatency;
179 else
180 playbackParameters.suggestedLatency =
182
183 PaStreamParameters captureParameters;
184
185 captureParameters.device = recDeviceNum;
186 captureParameters.sampleFormat = paFloat32;;
187 captureParameters.hostApiSpecificStreamInfo = NULL;
188 captureParameters.channelCount = 1;
189 if (Pa_GetDeviceInfo(recDeviceNum))
190 captureParameters.suggestedLatency =
191 Pa_GetDeviceInfo(recDeviceNum)->defaultLowInputLatency;
192 else
193 captureParameters.suggestedLatency =
195
196 // try opening for record and playback
197 // Not really doing I/O so pass nullptr for the callback function
198 error = Pa_OpenStream(&stream,
199 &captureParameters, &playbackParameters,
200 highestSampleRate, paFramesPerBufferUnspecified,
201 paClipOff | paDitherOff,
202 nullptr, NULL);
203
204 if (!error) {
205 // Try portmixer for this stream
206 mPortMixer = Px_OpenMixer(stream, recDeviceNum, playDeviceNum, 0);
207 if (!mPortMixer) {
208 Pa_CloseStream(stream);
209 error = true;
210 }
211 }
212
213 // if that failed, try just for record
214 if( error ) {
215 error = Pa_OpenStream(&stream,
216 &captureParameters, NULL,
217 highestSampleRate, paFramesPerBufferUnspecified,
218 paClipOff | paDitherOff,
219 nullptr, NULL);
220
221 if (!error) {
222 mPortMixer = Px_OpenMixer(stream, recDeviceNum, playDeviceNum, 0);
223 if (!mPortMixer) {
224 Pa_CloseStream(stream);
225 error = true;
226 }
227 }
228 }
229
230 // finally, try just for playback
231 if ( error ) {
232 error = Pa_OpenStream(&stream,
233 NULL, &playbackParameters,
234 highestSampleRate, paFramesPerBufferUnspecified,
235 paClipOff | paDitherOff,
236 nullptr, NULL);
237
238 if (!error) {
239 mPortMixer = Px_OpenMixer(stream, recDeviceNum, playDeviceNum, 0);
240 if (!mPortMixer) {
241 Pa_CloseStream(stream);
242 error = true;
243 }
244 }
245 }
246
247 // FIXME: TRAP_ERR errors in HandleDeviceChange not reported.
248 // if it's still not working, give up
249 if( error )
250 return;
251
252 // Set input source
253#if USE_PORTMIXER
254 auto sourceIndex = AudioIORecordingSourceIndex.Read(); // defaults to -1
255 if (sourceIndex >= 0) {
256 //the current index of our source may be different because the stream
257 //is a combination of two devices, so update it.
258 sourceIndex = getRecordSourceIndex(mPortMixer);
259 if (sourceIndex >= 0)
260 SetMixer(sourceIndex);
261 }
262#endif
263
264 // Determine mixer capabilities - if it doesn't support control of output
265 // signal level, we emulate it (by multiplying this value by all outgoing
266 // samples)
267
268 float inputVol = Px_GetInputVolume(mPortMixer);
269 mInputMixerWorks = true; // assume it works unless proved wrong
270 Px_SetInputVolume(mPortMixer, 0.0);
271 if (Px_GetInputVolume(mPortMixer) > 0.1)
272 mInputMixerWorks = false; // can't set to zero
273 Px_SetInputVolume(mPortMixer, 0.2f);
274 if (Px_GetInputVolume(mPortMixer) < 0.1 ||
275 Px_GetInputVolume(mPortMixer) > 0.3)
276 mInputMixerWorks = false; // can't set level accurately
277 Px_SetInputVolume(mPortMixer, inputVol);
278
279 Pa_CloseStream(stream);
280
281
282 #if 0
283 wxPrintf("PortMixer: Recording: %s\n"
284 mInputMixerWorks? "hardware": "no control");
285 #endif
286#endif // USE_PORTMIXER
287}
IntSetting AudioIORecordingSourceIndex
static int mCurrentPlaybackIndex
Definition: AudioIOBase.h:339
static double mCachedBestRateIn
Definition: AudioIOBase.h:341
static int mCurrentCaptureIndex
Definition: AudioIOBase.h:340
void SetMixer(int inputSource)
bool mInputMixerWorks
Can we control the hardware input level?
Definition: AudioIOBase.h:333

References AudioIOLatencyCorrection, AudioIORecordingSourceIndex, GetClosestSupportedSampleRate(), Setting< T >::GetDefault(), getPlayDevIndex(), getRecordDevIndex(), IsStreamActive(), mCachedBestRateIn, mCurrentCaptureIndex, mCurrentPlaybackIndex, mInputMixerWorks, Setting< T >::Read(), and SetMixer().

Referenced by AudioIO::AudioIO().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ HostName()

wxString AudioIOBase::HostName ( const PaDeviceInfo *  info)
staticprotected

Definition at line 83 of file AudioIOBase.cpp.

84{
85 wxString hostapiName = wxSafeConvertMB2WX(Pa_GetHostApiInfo(info->hostApi)->name);
86
87 return hostapiName;
88}

Referenced by GetDeviceInfo(), and AudioIO::Init().

Here is the caller graph for this function:

◆ IsAudioTokenActive()

bool AudioIOBase::IsAudioTokenActive ( int  token) const

Returns true if the stream is active, or even if audio I/O is busy cleaning up its data or writing to disk.

This is used by TrackPanel to determine when a track has been completely recorded, and it's safe to flush to disk.

Definition at line 354 of file AudioIOBase.cpp.

355{
356 return ( token > 0 && token == mStreamToken );
357}
int mStreamToken
Definition: AudioIOBase.h:310

References mStreamToken.

Referenced by AudioIOBusyPred(), and IsStreamActive().

Here is the caller graph for this function:

◆ IsBusy()

bool AudioIOBase::IsBusy ( ) const

Returns true if audio i/o is busy starting, stopping, playing, or recording.

When this is false, it's safe to start playing or recording

Definition at line 328 of file AudioIOBase.cpp.

329{
330 if (mStreamToken != 0)
331 return true;
332
333 return false;
334}

References mStreamToken.

Referenced by AudioIoCallback::SetListener(), and AudioIO::StartStream().

Here is the caller graph for this function:

◆ IsCaptureRateSupported()

bool AudioIOBase::IsCaptureRateSupported ( int  devIndex,
long  rate 
)
static

Check if the specified sample rate is supported by a device.

Verifies if a recording device supports a given rate. If no device index is specified (devIndex == -1), the preferred device is used.

Definition at line 413 of file AudioIOBase.cpp.

414{
415 if (devIndex == -1)
416 { // not given a device, look up in prefs / default
417 devIndex = getRecordDevIndex();
418 }
419
420 // Check if we can use the cached rate
421 if (mCachedCaptureRates.count(devIndex) &&
422 (make_iterator_range(mCachedCaptureRates.at(devIndex)).contains(rate)))
423 {
424 return true;
425 }
426
427 auto devInfo = Pa_GetDeviceInfo(devIndex);
428
429 if (!devInfo)
430 {
431 wxLogDebug(wxT("IsCaptureRateSupported() Could not get device info!"));
432 return false;
433 }
434
435 auto latencyDuration = AudioIOLatencyDuration.Read();
436 // Why not defaulting to 2 as elsewhere?
437 auto recordChannels = AudioIORecordChannels.ReadWithDefault(1);
438
439 // LLL: Remove when a proper method of determining actual supported
440 // DirectSound rate is devised.
441 const PaHostApiInfo* hostInfo = Pa_GetHostApiInfo(devInfo->hostApi);
442 bool isDirectSound = (hostInfo && hostInfo->type == paDirectSound);
443
444 PaStreamParameters pars;
445
446 pars.device = devIndex;
447 pars.channelCount = recordChannels;
448 pars.sampleFormat = paFloat32;
449 pars.suggestedLatency = latencyDuration / 1000.0;
450 pars.hostApiSpecificStreamInfo = NULL;
451
452 // LLL: Remove when a proper method of determining actual supported
453 // DirectSound rate is devised.
454 if (!(isDirectSound && rate > 200000))
455 {
456 if (Pa_IsFormatSupported(&pars, NULL, rate) == 0)
457 {
458 mCachedCaptureRates[devIndex].push_back(rate);
459 return true;
460 }
461 }
462 return false;
463}
DoubleSetting AudioIOLatencyDuration
IntSetting AudioIORecordChannels
bool ReadWithDefault(T *pVar, const T &defaultValue) const
overload of ReadWithDefault returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:213

References AudioIOLatencyDuration, AudioIORecordChannels, getRecordDevIndex(), make_iterator_range(), mCachedCaptureRates, Setting< T >::Read(), Setting< T >::ReadWithDefault(), and wxT().

Referenced by GetClosestSupportedCaptureRate(), GetClosestSupportedSampleRate(), and GetSupportedCaptureRates().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ IsMonitoring()

bool AudioIOBase::IsMonitoring ( ) const

Returns true if we're monitoring input (but not recording or playing actual audio)

Definition at line 359 of file AudioIOBase.cpp.

360{
361 return ( mPortStreamV19 && mStreamToken==0 );
362}
PaStream * mPortStreamV19
Definition: AudioIOBase.h:316

References mPortStreamV19, and mStreamToken.

Referenced by AudioIO::AudioThread().

Here is the caller graph for this function:

◆ IsPaused()

bool AudioIOBase::IsPaused ( ) const

Find out if playback / recording is currently paused.

Definition at line 323 of file AudioIOBase.cpp.

324{
325 return mPaused.load(std::memory_order_relaxed);
326}
std::atomic< bool > mPaused
True if audio playback is paused.
Definition: AudioIOBase.h:307

References mPaused.

Referenced by AudioIoCallback::AudioCallback(), AudioIoCallback::CallbackCheckCompletion(), AudioIoCallback::CheckSoundActivatedRecordingLevel(), AudioIoCallback::FillOutputBuffers(), PausedFlag(), and AudioIO::SetPaused().

Here is the caller graph for this function:

◆ IsPlaybackRateSupported()

bool AudioIOBase::IsPlaybackRateSupported ( int  devIndex,
long  rate 
)
static

Check if the specified playback rate is supported by a device.

Verifies if a playback device supports a given rate. If no device index is specified (devIndex == -1), the preferred device is used.

Definition at line 364 of file AudioIOBase.cpp.

365{
366 if (devIndex == -1)
367 { // weren't given a device index, get the prefs / default one
368 devIndex = getPlayDevIndex();
369 }
370
371 // Check if we can use the cached rate
372 if (mCachedPlaybackRates.count(devIndex) &&
373 (make_iterator_range(mCachedPlaybackRates.at(devIndex)).contains(rate)))
374 {
375 return true;
376 }
377
378 auto devInfo = Pa_GetDeviceInfo(devIndex);
379
380 if (!devInfo)
381 {
382 wxLogDebug(wxT("IsPlaybackRateSupported() Could not get device info!"));
383 return false;
384 }
385
386 // LLL: Remove when a proper method of determining actual supported
387 // DirectSound rate is devised.
388 const PaHostApiInfo* hostInfo = Pa_GetHostApiInfo(devInfo->hostApi);
389 bool isDirectSound = (hostInfo && hostInfo->type == paDirectSound);
390
391 PaStreamParameters pars;
392
393 pars.device = devIndex;
394 pars.channelCount = 1;
395 pars.sampleFormat = paFloat32;
396 pars.suggestedLatency = devInfo->defaultHighOutputLatency;
397 pars.hostApiSpecificStreamInfo = NULL;
398
399 // JKC: PortAudio Errors handled OK here. No need to report them
400
401 // LLL: Remove when a proper method of determining actual supported
402 // DirectSound rate is devised.
403 if (!(isDirectSound && rate > 200000)){
404 if (Pa_IsFormatSupported(NULL, &pars, rate) == 0)
405 {
406 mCachedPlaybackRates[devIndex].push_back(rate);
407 return true;
408 }
409 }
410 return false;
411}
static std::map< int, std::vector< long > > mCachedPlaybackRates
Definition: AudioIOBase.h:336

References getPlayDevIndex(), make_iterator_range(), mCachedPlaybackRates, and wxT().

Referenced by GetClosestSupportedPlaybackRate(), GetClosestSupportedSampleRate(), and GetSupportedPlaybackRates().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ IsStreamActive() [1/2]

bool AudioIOBase::IsStreamActive ( ) const

Returns true if the audio i/o is running at all, but not during cleanup.

Doesn't return true if the device has been closed but some disk i/o or cleanup is still going on. If you want to know if it's safe to start a NEW stream, use IsBusy()

Definition at line 336 of file AudioIOBase.cpp.

337{
338 bool isActive = false;
339 // JKC: Not reporting any Pa error, but that looks OK.
340 if( mPortStreamV19 )
341 isActive = (Pa_IsStreamActive( mPortStreamV19 ) > 0);
342
343 isActive = isActive ||
344 std::any_of(mAudioIOExt.begin(), mAudioIOExt.end(),
345 [](auto &pExt){ return pExt && pExt->IsOtherStreamActive(); });
346 return isActive;
347}

References mAudioIOExt, and mPortStreamV19.

Referenced by AudioIO::DrainRecordBuffers(), GetDeviceInfo(), AudioIO::GetStreamTime(), HandleDeviceChange(), AudioIO::IsCapturing(), and IsStreamActive().

Here is the caller graph for this function:

◆ IsStreamActive() [2/2]

bool AudioIOBase::IsStreamActive ( int  token) const

Definition at line 349 of file AudioIOBase.cpp.

350{
351 return (this->IsStreamActive() && this->IsAudioTokenActive(token));
352}
bool IsAudioTokenActive(int token) const
Returns true if the stream is active, or even if audio I/O is busy cleaning up its data or writing to...

References IsAudioTokenActive(), and IsStreamActive().

Here is the call graph for this function:

◆ operator=()

AudioIOBase & AudioIOBase::operator= ( const AudioIOBase )
delete

◆ SetCaptureMeter()

void AudioIOBase::SetCaptureMeter ( const std::shared_ptr< AudacityProject > &  project,
const std::weak_ptr< Meter > &  meter 
)

Definition at line 289 of file AudioIOBase.cpp.

291{
292 if (auto pOwningProject = mOwningProject.lock();
293 ( pOwningProject ) && ( pOwningProject != project))
294 return;
295
296 auto meter = wMeter.lock();
297 if (meter)
298 {
299 mInputMeter = meter;
300 meter->Reset(mRate, true);
301 }
302 else
303 mInputMeter.reset();
304}
const auto project
double mRate
Audio playback rate in samples per second.
Definition: AudioIOBase.h:314
std::weak_ptr< AudacityProject > mOwningProject
Definition: AudioIOBase.h:304
std::weak_ptr< Meter > mInputMeter
Definition: AudioIOBase.h:318

References mInputMeter, mOwningProject, mRate, and project.

Referenced by AudioIO::StartPortAudioStream().

Here is the caller graph for this function:

◆ SetMixer()

void AudioIOBase::SetMixer ( int  inputSource)

Definition at line 103 of file AudioIOBase.cpp.

104{
105#if defined(USE_PORTMIXER)
106 int oldRecordSource = Px_GetCurrentInputSource(mPortMixer);
107 if ( inputSource != oldRecordSource )
108 Px_SetCurrentInputSource(mPortMixer, inputSource);
109#endif
110}

Referenced by HandleDeviceChange(), and AudioIO::SetMixer().

Here is the caller graph for this function:

◆ SetPlaybackMeter()

void AudioIOBase::SetPlaybackMeter ( const std::shared_ptr< AudacityProject > &  project,
const std::weak_ptr< Meter > &  meter 
)

Definition at line 306 of file AudioIOBase.cpp.

308{
309 if (auto pOwningProject = mOwningProject.lock();
310 ( pOwningProject ) && ( pOwningProject != project))
311 return;
312
313 auto meter = wMeter.lock();
314 if (meter)
315 {
316 mOutputMeter = meter;
317 meter->Reset(mRate, true);
318 }
319 else
320 mOutputMeter.reset();
321}
std::weak_ptr< Meter > mOutputMeter
Definition: AudioIOBase.h:319

References mOutputMeter, mOwningProject, mRate, and project.

◆ StopStream()

virtual void AudioIOBase::StopStream ( )
pure virtual

Implemented in AudioIO.

Member Data Documentation

◆ mAudioIOExt

std::vector<std::unique_ptr<AudioIOExtBase> > AudioIOBase::mAudioIOExt
protected

This class needs to iterate this array for one limited purpose but does not populate it and does not give access to it except to subclasses

Definition at line 381 of file AudioIOBase.h.

Referenced by IsStreamActive().

◆ mCachedBestRateIn

double AudioIOBase::mCachedBestRateIn { 0.0 }
staticprotected

Definition at line 341 of file AudioIOBase.h.

Referenced by AudioIO::GetBestRate(), and HandleDeviceChange().

◆ mCachedCaptureRates

std::map< int, std::vector< long > > AudioIOBase::mCachedCaptureRates
staticprotected

Definition at line 337 of file AudioIOBase.h.

Referenced by GetClosestSupportedCaptureRate(), and IsCaptureRateSupported().

◆ mCachedPlaybackRates

std::map< int, std::vector< long > > AudioIOBase::mCachedPlaybackRates
staticprotected

Definition at line 336 of file AudioIOBase.h.

Referenced by IsPlaybackRateSupported().

◆ mCachedSampleRates

std::map< std::pair< int, int >, std::vector< long > > AudioIOBase::mCachedSampleRates
staticprotected

Definition at line 338 of file AudioIOBase.h.

Referenced by GetClosestSupportedSampleRate().

◆ mCurrentCaptureIndex

int AudioIOBase::mCurrentCaptureIndex { -1 }
staticprotected

Definition at line 340 of file AudioIOBase.h.

Referenced by HandleDeviceChange().

◆ mCurrentPlaybackIndex

int AudioIOBase::mCurrentPlaybackIndex { -1 }
staticprotected

Definition at line 339 of file AudioIOBase.h.

Referenced by HandleDeviceChange().

◆ mInputMeter

std::weak_ptr<Meter> AudioIOBase::mInputMeter {}
protected

◆ mInputMixerWorks

bool AudioIOBase::mInputMixerWorks
protected

Can we control the hardware input level?

This flag is set to true if using portmixer to control the input volume seems to be working (and so we offer the user the control), and to false (locking the control out) otherwise. This avoids stupid scaled clipping problems when trying to do software emulated input volume control

Definition at line 333 of file AudioIOBase.h.

Referenced by AudioIO::AudioIO(), AudioIO::GetMixer(), HandleDeviceChange(), and AudioIO::InputMixerWorks().

◆ mOutputMeter

std::weak_ptr<Meter> AudioIOBase::mOutputMeter {}
protected

◆ mOwningProject

std::weak_ptr<AudacityProject> AudioIOBase::mOwningProject
protected

◆ mPaused

std::atomic<bool> AudioIOBase::mPaused { false }
protected

True if audio playback is paused.

Definition at line 307 of file AudioIOBase.h.

Referenced by IsPaused(), and AudioIO::SetPaused().

◆ mPortStreamV19

PaStream* AudioIOBase::mPortStreamV19
protected

◆ mRate

double AudioIOBase::mRate
protected

◆ mStreamToken

int AudioIOBase::mStreamToken { 0 }
protected

◆ NumRatesToTry

const int AudioIOBase::NumRatesToTry = WXSIZEOF(AudioIOBase::RatesToTry)
staticprotected

How many sample rates to try.

Definition at line 376 of file AudioIOBase.h.

Referenced by GetClosestSupportedCaptureRate(), GetClosestSupportedPlaybackRate(), and GetClosestSupportedSampleRate().

◆ NumStandardRates

const int AudioIOBase::NumStandardRates = WXSIZEOF(AudioIOBase::StandardRates)
static

How many standard sample rates there are.

Definition at line 250 of file AudioIOBase.h.

Referenced by DevicePrefs::GetNamesAndLabels(), and ImportRawDialog::ImportRawDialog().

◆ RatesToTry

const int AudioIOBase::RatesToTry
staticprotected
Initial value:
= {
8000,
9600,
11025,
12000,
15000,
16000,
22050,
24000,
32000,
44100,
48000,
88200,
96000,
176400,
192000,
352800,
384000
}

Array of audio sample rates to try to use.

These are the rates we will check if a device supports, and is as long as I can think of (to try and work out what the card can do)

Definition at line 374 of file AudioIOBase.h.

Referenced by GetClosestSupportedCaptureRate(), GetClosestSupportedPlaybackRate(), GetClosestSupportedSampleRate(), GetSupportedCaptureRates(), and GetSupportedPlaybackRates().

◆ StandardRates

const int AudioIOBase::StandardRates
static
Initial value:
= {
8000,
11025,
16000,
22050,
32000,
44100,
48000,
88200,
96000,
176400,
192000,
352800,
384000
}

Array of common audio sample rates.

These are the rates we will always support, regardless of hardware support for them (by resampling in audacity if needed)

Definition at line 248 of file AudioIOBase.h.

Referenced by DevicePrefs::GetNamesAndLabels(), and ImportRawDialog::ImportRawDialog().

◆ ugAudioIO

std::unique_ptr< AudioIOBase > AudioIOBase::ugAudioIO
staticprotected

Definition at line 300 of file AudioIOBase.h.

Referenced by AudioIO::Deinit(), Get(), and AudioIO::Init().


The documentation for this class was generated from the following files: