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, double rate=0.0)
 Get a list of sample rates the output (playback) device supports. More...
 
static std::vector< long > GetSupportedCaptureRates (int devIndex=-1, double rate=0.0)
 Get a list of sample rates the input (recording) device supports. More...
 
static std::vector< long > GetSupportedSampleRates (int playDevice=-1, int recDevice=-1, double rate=0.0)
 Get a list of sample rates the current input/output device combination supports. More...
 
static int GetOptimalSupportedSampleRate ()
 Get a supported sample rate which can be used a an optimal default. 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 int mCachedPlaybackIndex = -1
 
static std::vector< long > mCachedPlaybackRates
 
static int mCachedCaptureIndex = -1
 
static std::vector< long > mCachedCaptureRates
 
static std::vector< long > mCachedSampleRates
 
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 100 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 927 of file AudioIOBase.cpp.

928{
929 std::vector<AudioIODiagnostics> result;
930 result.push_back({
931 wxT("audiodev.txt"), GetDeviceInfo(), wxT("Audio Device Info") });
932 for( auto &pExt : mAudioIOExt )
933 if ( pExt )
934 result.emplace_back(pExt->Dump());
935 return result;
936}
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:322

References wxT().

Here is the call graph for this function:

◆ GetDeviceInfo()

wxString AudioIOBase::GetDeviceInfo ( ) const

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

Definition at line 698 of file AudioIOBase.cpp.

699{
700 wxStringOutputStream o;
701 wxTextOutputStream s(o, wxEOL_UNIX);
702
703 if (IsStreamActive()) {
704 return XO("Stream is active ... unable to gather information.\n")
705 .Translation();
706 }
707
708
709 // FIXME: TRAP_ERR PaErrorCode not handled. 3 instances in GetDeviceInfo().
710 int recDeviceNum = Pa_GetDefaultInputDevice();
711 int playDeviceNum = Pa_GetDefaultOutputDevice();
712 int cnt = Pa_GetDeviceCount();
713
714 // PRL: why only into the log?
715 wxLogDebug(wxT("Portaudio reports %d audio devices"),cnt);
716
717 s << wxT("==============================\n");
718 s << XO("Default recording device number: %d\n").Format( recDeviceNum );
719 s << XO("Default playback device number: %d\n").Format( playDeviceNum);
720
721 auto recDevice = AudioIORecordingDevice.Read();
722 auto playDevice = AudioIOPlaybackDevice.Read();
723 int j;
724
725 // This gets info on all available audio devices (input and output)
726 if (cnt <= 0) {
727 s << XO("No devices found\n");
728 return o.GetString();
729 }
730
731 const PaDeviceInfo* info;
732
733 for (j = 0; j < cnt; j++) {
734 s << wxT("==============================\n");
735
736 info = Pa_GetDeviceInfo(j);
737 if (!info) {
738 s << XO("Device info unavailable for: %d\n").Format( j );
739 continue;
740 }
741
742 wxString name = DeviceName(info);
743 s << XO("Device ID: %d\n").Format( j );
744 s << XO("Device name: %s\n").Format( name );
745 s << XO("Host name: %s\n").Format( HostName(info) );
746 s << XO("Recording channels: %d\n").Format( info->maxInputChannels );
747 s << XO("Playback channels: %d\n").Format( info->maxOutputChannels );
748 s << XO("Low Recording Latency: %g\n").Format( info->defaultLowInputLatency );
749 s << XO("Low Playback Latency: %g\n").Format( info->defaultLowOutputLatency );
750 s << XO("High Recording Latency: %g\n").Format( info->defaultHighInputLatency );
751 s << XO("High Playback Latency: %g\n").Format( info->defaultHighOutputLatency );
752
753 auto rates = GetSupportedPlaybackRates(j, 0.0);
754
755 /* i18n-hint: Supported, meaning made available by the system */
756 s << XO("Supported Rates:\n");
757 for (int k = 0; k < (int) rates.size(); k++) {
758 s << wxT(" ") << (int)rates[k] << wxT("\n");
759 }
760
761 if (name == playDevice && info->maxOutputChannels > 0)
762 playDeviceNum = j;
763
764 if (name == recDevice && info->maxInputChannels > 0)
765 recDeviceNum = j;
766
767 // Sometimes PortAudio returns -1 if it cannot find a suitable default
768 // device, so we just use the first one available
769 if (recDeviceNum < 0 && info->maxInputChannels > 0){
770 recDeviceNum = j;
771 }
772 if (playDeviceNum < 0 && info->maxOutputChannels > 0){
773 playDeviceNum = j;
774 }
775 }
776
777 bool haveRecDevice = (recDeviceNum >= 0);
778 bool havePlayDevice = (playDeviceNum >= 0);
779
780 s << wxT("==============================\n");
781 if (haveRecDevice)
782 s << XO("Selected recording device: %d - %s\n").Format( recDeviceNum, recDevice );
783 else
784 s << XO("No recording device found for '%s'.\n").Format( recDevice );
785
786 if (havePlayDevice)
787 s << XO("Selected playback device: %d - %s\n").Format( playDeviceNum, playDevice );
788 else
789 s << XO("No playback device found for '%s'.\n").Format( playDevice );
790
791 std::vector<long> supportedSampleRates;
792
793 if (havePlayDevice && haveRecDevice) {
794 supportedSampleRates = GetSupportedSampleRates(playDeviceNum, recDeviceNum);
795
796 s << XO("Supported Rates:\n");
797 for (int k = 0; k < (int) supportedSampleRates.size(); k++) {
798 s << wxT(" ") << (int)supportedSampleRates[k] << wxT("\n");
799 }
800 }
801 else {
802 s << XO("Cannot check mutual sample rates without both devices.\n");
803 return o.GetString();
804 }
805
806#if defined(USE_PORTMIXER)
807 if (supportedSampleRates.size() > 0)
808 {
809 int highestSampleRate = supportedSampleRates.back();
810 bool EmulateMixerInputVol = true;
811 float MixerInputVol = 1.0;
812 float MixerOutputVol = 1.0;
813
814 int error;
815
816 PaStream *stream;
817
818 PaStreamParameters playbackParameters;
819
820 playbackParameters.device = playDeviceNum;
821 playbackParameters.sampleFormat = paFloat32;
822 playbackParameters.hostApiSpecificStreamInfo = NULL;
823 playbackParameters.channelCount = 1;
824 if (Pa_GetDeviceInfo(playDeviceNum)){
825 playbackParameters.suggestedLatency =
826 Pa_GetDeviceInfo(playDeviceNum)->defaultLowOutputLatency;
827 }
828 else
829 playbackParameters.suggestedLatency =
831
832 PaStreamParameters captureParameters;
833
834 captureParameters.device = recDeviceNum;
835 captureParameters.sampleFormat = paFloat32;;
836 captureParameters.hostApiSpecificStreamInfo = NULL;
837 captureParameters.channelCount = 1;
838 if (Pa_GetDeviceInfo(recDeviceNum)){
839 captureParameters.suggestedLatency =
840 Pa_GetDeviceInfo(recDeviceNum)->defaultLowInputLatency;
841 }
842 else
843 captureParameters.suggestedLatency =
845
846 // Not really doing I/O so pass nullptr for the callback function
847 error = Pa_OpenStream(&stream,
848 &captureParameters, &playbackParameters,
849 highestSampleRate, paFramesPerBufferUnspecified,
850 paClipOff | paDitherOff,
851 nullptr, NULL);
852
853 if (error) {
854 error = Pa_OpenStream(&stream,
855 &captureParameters, NULL,
856 highestSampleRate, paFramesPerBufferUnspecified,
857 paClipOff | paDitherOff,
858 nullptr, NULL);
859 }
860
861 if (error) {
862 s << XO("Received %d while opening devices\n").Format( error );
863 return o.GetString();
864 }
865
866 PxMixer *PortMixer = Px_OpenMixer(stream, recDeviceNum, playDeviceNum, 0);
867
868 if (!PortMixer) {
869 s << XO("Unable to open Portmixer\n");
870 Pa_CloseStream(stream);
871 return o.GetString();
872 }
873
874 s << wxT("==============================\n");
875 s << XO("Available mixers:\n");
876
877 // FIXME: ? PortMixer errors on query not reported in GetDeviceInfo
878 cnt = Px_GetNumMixers(stream);
879 for (int i = 0; i < cnt; i++) {
880 wxString name = wxSafeConvertMB2WX(Px_GetMixerName(stream, i));
881 s << XO("%d - %s\n").Format( i, name );
882 }
883
884 s << wxT("==============================\n");
885 s << XO("Available recording sources:\n");
886 cnt = Px_GetNumInputSources(PortMixer);
887 for (int i = 0; i < cnt; i++) {
888 wxString name = wxSafeConvertMB2WX(Px_GetInputSourceName(PortMixer, i));
889 s << XO("%d - %s\n").Format( i, name );
890 }
891
892 s << wxT("==============================\n");
893 s << XO("Available playback volumes:\n");
894 cnt = Px_GetNumOutputVolumes(PortMixer);
895 for (int i = 0; i < cnt; i++) {
896 wxString name = wxSafeConvertMB2WX(Px_GetOutputVolumeName(PortMixer, i));
897 s << XO("%d - %s\n").Format( i, name );
898 }
899
900 // Check, if PortMixer supports adjusting input levels on the interface
901
902 MixerInputVol = Px_GetInputVolume(PortMixer);
903 EmulateMixerInputVol = false;
904 Px_SetInputVolume(PortMixer, 0.0);
905 if (Px_GetInputVolume(PortMixer) > 0.1)
906 EmulateMixerInputVol = true;
907 Px_SetInputVolume(PortMixer, 0.2f);
908 if (Px_GetInputVolume(PortMixer) < 0.1 ||
909 Px_GetInputVolume(PortMixer) > 0.3)
910 EmulateMixerInputVol = true;
911 Px_SetInputVolume(PortMixer, MixerInputVol);
912
913 Pa_CloseStream(stream);
914
915 s << wxT("==============================\n");
916 s << ( EmulateMixerInputVol
917 ? XO("Recording volume is emulated\n")
918 : XO("Recording volume is native\n") );
919
920 Px_CloseMixer(PortMixer);
921
922 } //end of massive if statement if a valid sample rate has been found
923#endif
924 return o.GetString();
925}
DoubleSetting AudioIOLatencyCorrection
StringSetting AudioIOPlaybackDevice
StringSetting AudioIORecordingDevice
void PaStream
Definition: AudioIOBase.h:23
const TranslatableString name
Definition: Distortion.cpp:76
XO("Cut/Copy/Paste")
static wxString HostName(const PaDeviceInfo *info)
Definition: AudioIOBase.cpp:83
static std::vector< long > GetSupportedPlaybackRates(int DevIndex=-1, double rate=0.0)
Get a list of sample rates the output (playback) device supports.
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, double rate=0.0)
Get a list of sample rates the current input/output device combination 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(), 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 552 of file AudioIOBase.cpp.

553{
554 auto rates = GetSupportedSampleRates();
555
556 if (make_iterator_range(rates).contains(44100))
557 return 44100;
558
559 if (make_iterator_range(rates).contains(48000))
560 return 48000;
561
562 // if there are no supported rates, the next bit crashes. So check first,
563 // and give them a "sensible" value if there are no valid values. They
564 // will still get an error later, but with any luck may have changed
565 // something by then. It's no worse than having an invalid default rate
566 // stored in the preferences, which we don't check for
567 if (rates.empty()) return 44100;
568
569 return rates.back();
570}
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
Definition: IteratorX.h:210

References GetSupportedSampleRates(), and make_iterator_range().

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 586 of file AudioIOBase.cpp.

587{
588 wxString devName(devNameArg);
589 // if we don't get given a device, look up the preferences
590 if (devName.empty())
591 devName = AudioIOPlaybackDevice.Read();
592
593 auto hostName = AudioIOHost.Read();
594 PaHostApiIndex hostCnt = Pa_GetHostApiCount();
595 PaHostApiIndex hostNum;
596 for (hostNum = 0; hostNum < hostCnt; hostNum++)
597 {
598 const PaHostApiInfo *hinfo = Pa_GetHostApiInfo(hostNum);
599 if (hinfo && wxString(wxSafeConvertMB2WX(hinfo->name)) == hostName)
600 {
601 for (PaDeviceIndex hostDevice = 0; hostDevice < hinfo->deviceCount; hostDevice++)
602 {
603 PaDeviceIndex deviceNum = Pa_HostApiDeviceIndexToDeviceIndex(hostNum, hostDevice);
604
605 const PaDeviceInfo *dinfo = Pa_GetDeviceInfo(deviceNum);
606 if (dinfo && DeviceName(dinfo) == devName && dinfo->maxOutputChannels > 0 )
607 {
608 // this device name matches the stored one, and works.
609 // So we say this is the answer and return it
610 return deviceNum;
611 }
612 }
613
614 // The device wasn't found so use the default for this host.
615 // LL: At this point, preferences and active no longer match.
616 return hinfo->defaultOutputDevice;
617 }
618 }
619
620 // The host wasn't found, so use the default output device.
621 // FIXME: TRAP_ERR PaErrorCode not handled well (this code is similar to input code
622 // and the input side has more comments.)
623
624 PaDeviceIndex deviceNum = Pa_GetDefaultOutputDevice();
625
626 // Sometimes PortAudio returns -1 if it cannot find a suitable default
627 // device, so we just use the first one available
628 //
629 // LL: At this point, preferences and active no longer match
630 //
631 // And I can't imagine how far we'll get specifying an "invalid" index later
632 // on...are we certain "0" even exists?
633 if (deviceNum < 0) {
634 assert(false);
635 deviceNum = 0;
636 }
637
638 return deviceNum;
639}
StringSetting AudioIOHost

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

Referenced by GetSupportedPlaybackRates(), GetSupportedSampleRates(), HandleDeviceChange(), AudioIO::Init(), 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 641 of file AudioIOBase.cpp.

642{
643 wxString devName(devNameArg);
644 // if we don't get given a device, look up the preferences
645 if (devName.empty())
646 devName = AudioIORecordingDevice.Read();
647
648 auto hostName = AudioIOHost.Read();
649 PaHostApiIndex hostCnt = Pa_GetHostApiCount();
650 PaHostApiIndex hostNum;
651 for (hostNum = 0; hostNum < hostCnt; hostNum++)
652 {
653 const PaHostApiInfo *hinfo = Pa_GetHostApiInfo(hostNum);
654 if (hinfo && wxString(wxSafeConvertMB2WX(hinfo->name)) == hostName)
655 {
656 for (PaDeviceIndex hostDevice = 0; hostDevice < hinfo->deviceCount; hostDevice++)
657 {
658 PaDeviceIndex deviceNum = Pa_HostApiDeviceIndexToDeviceIndex(hostNum, hostDevice);
659
660 const PaDeviceInfo *dinfo = Pa_GetDeviceInfo(deviceNum);
661 if (dinfo && DeviceName(dinfo) == devName && dinfo->maxInputChannels > 0 )
662 {
663 // this device name matches the stored one, and works.
664 // So we say this is the answer and return it
665 return deviceNum;
666 }
667 }
668
669 // The device wasn't found so use the default for this host.
670 // LL: At this point, preferences and active no longer match.
671 return hinfo->defaultInputDevice;
672 }
673 }
674
675 // The host wasn't found, so use the default input device.
676 // FIXME: TRAP_ERR PaErrorCode not handled well in getRecordDevIndex()
677 PaDeviceIndex deviceNum = Pa_GetDefaultInputDevice();
678
679 // Sometimes PortAudio returns -1 if it cannot find a suitable default
680 // device, so we just use the first one available
681 // PortAudio has an error reporting function. We should log/report the error?
682 //
683 // LL: At this point, preferences and active no longer match
684 //
685 // And I can't imagine how far we'll get specifying an "invalid" index later
686 // on...are we certain "0" even exists?
687 if (deviceNum < 0) {
688 // JKC: This ASSERT will happen if you run with no config file
689 // This happens once. Config file will exist on the next run.
690 // TODO: Look into this a bit more. Could be relevant to blank Device Toolbar.
691 assert(false);
692 deviceNum = 0;
693 }
694
695 return deviceNum;
696}

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

Referenced by GetSupportedCaptureRates(), GetSupportedSampleRates(), HandleDeviceChange(), AudioIO::Init(), 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,
double  rate = 0.0 
)
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.

You may also specify a rate for which to check in addition to the standard rates.

Definition at line 438 of file AudioIOBase.cpp.

439{
440 if (devIndex == -1)
441 { // not given a device, look up in prefs / default
442 devIndex = getRecordDevIndex();
443 }
444
445 // Check if we can use the cached rates
446 if (mCachedCaptureIndex != -1 && devIndex == mCachedCaptureIndex
447 && (rate == 0.0 || make_iterator_range(mCachedCaptureRates).contains(rate)))
448 {
449 return mCachedCaptureRates;
450 }
451
452 std::vector<long> supported;
453 int irate = (int)rate;
454 const PaDeviceInfo* devInfo = NULL;
455 int i;
456
457 devInfo = Pa_GetDeviceInfo(devIndex);
458
459 if (!devInfo)
460 {
461 wxLogDebug(wxT("GetSupportedCaptureRates() Could not get device info!"));
462 return supported;
463 }
464
465 auto latencyDuration = AudioIOLatencyDuration.Read();
466 // Why not defaulting to 2 as elsewhere?
467 auto recordChannels = AudioIORecordChannels.ReadWithDefault(1);
468
469 // LLL: Remove when a proper method of determining actual supported
470 // DirectSound rate is devised.
471 const PaHostApiInfo* hostInfo = Pa_GetHostApiInfo(devInfo->hostApi);
472 bool isDirectSound = (hostInfo && hostInfo->type == paDirectSound);
473
474 PaStreamParameters pars;
475
476 pars.device = devIndex;
477 pars.channelCount = recordChannels;
478 pars.sampleFormat = paFloat32;
479 pars.suggestedLatency = latencyDuration / 1000.0;
480 pars.hostApiSpecificStreamInfo = NULL;
481
482 for (i = 0; i < NumRatesToTry; i++)
483 {
484 // LLL: Remove when a proper method of determining actual supported
485 // DirectSound rate is devised.
486 if (!(isDirectSound && RatesToTry[i] > 200000))
487 {
488 if (Pa_IsFormatSupported(&pars, NULL, RatesToTry[i]) == 0)
489 supported.push_back(RatesToTry[i]);
490 Pa_Sleep( 10 );// There are ALSA drivers that don't like being probed
491 // too quickly.
492 }
493 }
494
495 if (irate != 0 && !make_iterator_range(supported).contains(irate))
496 {
497 // LLL: Remove when a proper method of determining actual supported
498 // DirectSound rate is devised.
499 if (!(isDirectSound && irate > 200000))
500 if (Pa_IsFormatSupported(&pars, NULL, irate) == 0)
501 supported.push_back(irate);
502 }
503
504 return supported;
505}
DoubleSetting AudioIOLatencyDuration
IntSetting AudioIORecordChannels
static int mCachedCaptureIndex
Definition: AudioIOBase.h:279
static std::vector< long > mCachedCaptureRates
Definition: AudioIOBase.h:280
static const int NumRatesToTry
How many sample rates to try.
Definition: AudioIOBase.h:317
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:315
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(), mCachedCaptureIndex, mCachedCaptureRates, NumRatesToTry, RatesToTry, Setting< T >::Read(), Setting< T >::ReadWithDefault(), and wxT().

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

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,
double  rate = 0.0 
)
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.

You may also specify a rate for which to check in addition to the standard rates.

Definition at line 373 of file AudioIOBase.cpp.

374{
375 if (devIndex == -1)
376 { // weren't given a device index, get the prefs / default one
377 devIndex = getPlayDevIndex();
378 }
379
380 // Check if we can use the cached rates
381 if (mCachedPlaybackIndex != -1 && devIndex == mCachedPlaybackIndex
382 && (rate == 0.0 || make_iterator_range(mCachedPlaybackRates).contains(rate)))
383 {
385 }
386
387 std::vector<long> supported;
388 int irate = (int)rate;
389 const PaDeviceInfo* devInfo = NULL;
390 int i;
391
392 devInfo = Pa_GetDeviceInfo(devIndex);
393
394 if (!devInfo)
395 {
396 wxLogDebug(wxT("GetSupportedPlaybackRates() Could not get device info!"));
397 return supported;
398 }
399
400 // LLL: Remove when a proper method of determining actual supported
401 // DirectSound rate is devised.
402 const PaHostApiInfo* hostInfo = Pa_GetHostApiInfo(devInfo->hostApi);
403 bool isDirectSound = (hostInfo && hostInfo->type == paDirectSound);
404
405 PaStreamParameters pars;
406
407 pars.device = devIndex;
408 pars.channelCount = 1;
409 pars.sampleFormat = paFloat32;
410 pars.suggestedLatency = devInfo->defaultHighOutputLatency;
411 pars.hostApiSpecificStreamInfo = NULL;
412
413 // JKC: PortAudio Errors handled OK here. No need to report them
414 for (i = 0; i < NumRatesToTry; i++)
415 {
416 // LLL: Remove when a proper method of determining actual supported
417 // DirectSound rate is devised.
418 if (!(isDirectSound && RatesToTry[i] > 200000)){
419 if (Pa_IsFormatSupported(NULL, &pars, RatesToTry[i]) == 0)
420 supported.push_back(RatesToTry[i]);
421 Pa_Sleep( 10 );// There are ALSA drivers that don't like being probed
422 // too quickly.
423 }
424 }
425
426 if (irate != 0 && !make_iterator_range(supported).contains(irate))
427 {
428 // LLL: Remove when a proper method of determining actual supported
429 // DirectSound rate is devised.
430 if (!(isDirectSound && irate > 200000))
431 if (Pa_IsFormatSupported(NULL, &pars, irate) == 0)
432 supported.push_back(irate);
433 }
434
435 return supported;
436}
static int getPlayDevIndex(const wxString &devName={})
get the index of the device selected in the preferences.
static std::vector< long > mCachedPlaybackRates
Definition: AudioIOBase.h:278
static int mCachedPlaybackIndex
Definition: AudioIOBase.h:277

References getPlayDevIndex(), make_iterator_range(), mCachedPlaybackIndex, mCachedPlaybackRates, NumRatesToTry, RatesToTry, and wxT().

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

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,
double  rate = 0.0 
)
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. You may also specify a rate for which to check in addition to the standard rates.

Definition at line 507 of file AudioIOBase.cpp.

509{
510 // Not given device indices, look up prefs
511 if (playDevice == -1) {
512 playDevice = getPlayDevIndex();
513 }
514 if (recDevice == -1) {
515 recDevice = getRecordDevIndex();
516 }
517
518 // Check if we can use the cached rates
519 if (mCachedPlaybackIndex != -1 && mCachedCaptureIndex != -1 &&
520 playDevice == mCachedPlaybackIndex &&
521 recDevice == mCachedCaptureIndex &&
522 (rate == 0.0 || make_iterator_range(mCachedSampleRates).contains(rate)))
523 {
524 return mCachedSampleRates;
525 }
526
527 auto playback = GetSupportedPlaybackRates(playDevice, rate);
528 auto capture = GetSupportedCaptureRates(recDevice, rate);
529 int i;
530
531 // Return only sample rates which are in both arrays
532 std::vector<long> result;
533
534 for (i = 0; i < (int)playback.size(); i++)
535 if (make_iterator_range(capture).contains(playback[i]))
536 result.push_back(playback[i]);
537
538 // If this yields no results, use the default sample rates nevertheless
539/* if (result.empty())
540 {
541 for (i = 0; i < NumStandardRates; i++)
542 result.push_back(StandardRates[i]);
543 }*/
544
545 return result;
546}
static std::vector< long > mCachedSampleRates
Definition: AudioIOBase.h:281
static std::vector< long > GetSupportedCaptureRates(int devIndex=-1, double rate=0.0)
Get a list of sample rates the input (recording) device supports.

References getPlayDevIndex(), getRecordDevIndex(), GetSupportedCaptureRates(), GetSupportedPlaybackRates(), make_iterator_range(), mCachedCaptureIndex, mCachedPlaybackIndex, and mCachedSampleRates.

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

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 (mCachedPlaybackIndex == playDeviceNum &&
127 mCachedCaptureIndex == recDeviceNum)
128 return;
129
130 // cache playback/capture rates
133 mCachedSampleRates = GetSupportedSampleRates(playDeviceNum, recDeviceNum);
134 mCachedPlaybackIndex = playDeviceNum;
135 mCachedCaptureIndex = recDeviceNum;
136 mCachedBestRateIn = 0.0;
137
138#if defined(USE_PORTMIXER)
139
140 // if we have a PortMixer object, close it down
141 if (mPortMixer) {
142 #if __WXMAC__
143 // on the Mac we must make sure that we restore the hardware playthrough
144 // state of the sound device to what it was before, because there isn't
145 // a UI for this (!)
146 if (Px_SupportsPlaythrough(mPortMixer) && mPreviousHWPlaythrough >= 0.0)
147 Px_SetPlaythrough(mPortMixer, mPreviousHWPlaythrough);
148 mPreviousHWPlaythrough = -1.0;
149 #endif
150 Px_CloseMixer(mPortMixer);
151 mPortMixer = NULL;
152 }
153
154 // that might have given us no rates whatsoever, so we have to guess an
155 // answer to do the next bit
156 int numrates = mCachedSampleRates.size();
157 int highestSampleRate;
158 if (numrates > 0)
159 {
160 highestSampleRate = mCachedSampleRates[numrates - 1];
161 }
162 else
163 { // we don't actually have any rates that work for Rec and Play. Guess one
164 // to use for messing with the mixer, which doesn't actually do either
165 highestSampleRate = 44100;
166 // mCachedSampleRates is still empty, but it's not used again, so
167 // can ignore
168 }
169
170 mInputMixerWorks = false;
171
172 int error;
173 // This tries to open the device with the samplerate worked out above, which
174 // will be the highest available for play and record on the device, or
175 // 44.1kHz if the info cannot be fetched.
176
177 PaStream *stream;
178
179 PaStreamParameters playbackParameters;
180
181 playbackParameters.device = playDeviceNum;
182 playbackParameters.sampleFormat = paFloat32;
183 playbackParameters.hostApiSpecificStreamInfo = NULL;
184 playbackParameters.channelCount = 1;
185 if (Pa_GetDeviceInfo(playDeviceNum))
186 playbackParameters.suggestedLatency =
187 Pa_GetDeviceInfo(playDeviceNum)->defaultLowOutputLatency;
188 else
189 playbackParameters.suggestedLatency =
191
192 PaStreamParameters captureParameters;
193
194 captureParameters.device = recDeviceNum;
195 captureParameters.sampleFormat = paFloat32;;
196 captureParameters.hostApiSpecificStreamInfo = NULL;
197 captureParameters.channelCount = 1;
198 if (Pa_GetDeviceInfo(recDeviceNum))
199 captureParameters.suggestedLatency =
200 Pa_GetDeviceInfo(recDeviceNum)->defaultLowInputLatency;
201 else
202 captureParameters.suggestedLatency =
204
205 // try opening for record and playback
206 // Not really doing I/O so pass nullptr for the callback function
207 error = Pa_OpenStream(&stream,
208 &captureParameters, &playbackParameters,
209 highestSampleRate, paFramesPerBufferUnspecified,
210 paClipOff | paDitherOff,
211 nullptr, NULL);
212
213 if (!error) {
214 // Try portmixer for this stream
215 mPortMixer = Px_OpenMixer(stream, recDeviceNum, playDeviceNum, 0);
216 if (!mPortMixer) {
217 Pa_CloseStream(stream);
218 error = true;
219 }
220 }
221
222 // if that failed, try just for record
223 if( error ) {
224 error = Pa_OpenStream(&stream,
225 &captureParameters, NULL,
226 highestSampleRate, paFramesPerBufferUnspecified,
227 paClipOff | paDitherOff,
228 nullptr, NULL);
229
230 if (!error) {
231 mPortMixer = Px_OpenMixer(stream, recDeviceNum, playDeviceNum, 0);
232 if (!mPortMixer) {
233 Pa_CloseStream(stream);
234 error = true;
235 }
236 }
237 }
238
239 // finally, try just for playback
240 if ( error ) {
241 error = Pa_OpenStream(&stream,
242 NULL, &playbackParameters,
243 highestSampleRate, paFramesPerBufferUnspecified,
244 paClipOff | paDitherOff,
245 nullptr, NULL);
246
247 if (!error) {
248 mPortMixer = Px_OpenMixer(stream, recDeviceNum, playDeviceNum, 0);
249 if (!mPortMixer) {
250 Pa_CloseStream(stream);
251 error = true;
252 }
253 }
254 }
255
256 // FIXME: TRAP_ERR errors in HandleDeviceChange not reported.
257 // if it's still not working, give up
258 if( error )
259 return;
260
261 // Set input source
262#if USE_PORTMIXER
263 auto sourceIndex = AudioIORecordingSourceIndex.Read(); // defaults to -1
264 if (sourceIndex >= 0) {
265 //the current index of our source may be different because the stream
266 //is a combination of two devices, so update it.
267 sourceIndex = getRecordSourceIndex(mPortMixer);
268 if (sourceIndex >= 0)
269 SetMixer(sourceIndex);
270 }
271#endif
272
273 // Determine mixer capabilities - if it doesn't support control of output
274 // signal level, we emulate it (by multiplying this value by all outgoing
275 // samples)
276
277 float inputVol = Px_GetInputVolume(mPortMixer);
278 mInputMixerWorks = true; // assume it works unless proved wrong
279 Px_SetInputVolume(mPortMixer, 0.0);
280 if (Px_GetInputVolume(mPortMixer) > 0.1)
281 mInputMixerWorks = false; // can't set to zero
282 Px_SetInputVolume(mPortMixer, 0.2f);
283 if (Px_GetInputVolume(mPortMixer) < 0.1 ||
284 Px_GetInputVolume(mPortMixer) > 0.3)
285 mInputMixerWorks = false; // can't set level accurately
286 Px_SetInputVolume(mPortMixer, inputVol);
287
288 Pa_CloseStream(stream);
289
290
291 #if 0
292 wxPrintf("PortMixer: Recording: %s\n"
293 mInputMixerWorks? "hardware": "no control");
294 #endif
295#endif // USE_PORTMIXER
296}
IntSetting AudioIORecordingSourceIndex
static double mCachedBestRateIn
Definition: AudioIOBase.h:282
void SetMixer(int inputSource)
bool mInputMixerWorks
Can we control the hardware input level?
Definition: AudioIOBase.h:274

References AudioIOLatencyCorrection, AudioIORecordingSourceIndex, Setting< T >::GetDefault(), getPlayDevIndex(), getRecordDevIndex(), GetSupportedCaptureRates(), GetSupportedPlaybackRates(), GetSupportedSampleRates(), IsStreamActive(), mCachedBestRateIn, mCachedCaptureIndex, mCachedCaptureRates, mCachedPlaybackIndex, mCachedPlaybackRates, mCachedSampleRates, 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 363 of file AudioIOBase.cpp.

364{
365 return ( token > 0 && token == mStreamToken );
366}
int mStreamToken
Definition: AudioIOBase.h:251

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 337 of file AudioIOBase.cpp.

338{
339 if (mStreamToken != 0)
340 return true;
341
342 return false;
343}

References mStreamToken.

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

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 368 of file AudioIOBase.cpp.

369{
370 return ( mPortStreamV19 && mStreamToken==0 );
371}
PaStream * mPortStreamV19
Definition: AudioIOBase.h:257

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 332 of file AudioIOBase.cpp.

333{
334 return mPaused.load(std::memory_order_relaxed);
335}
std::atomic< bool > mPaused
True if audio playback is paused.
Definition: AudioIOBase.h:248

References mPaused.

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

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 345 of file AudioIOBase.cpp.

346{
347 bool isActive = false;
348 // JKC: Not reporting any Pa error, but that looks OK.
349 if( mPortStreamV19 )
350 isActive = (Pa_IsStreamActive( mPortStreamV19 ) > 0);
351
352 isActive = isActive ||
353 std::any_of(mAudioIOExt.begin(), mAudioIOExt.end(),
354 [](auto &pExt){ return pExt && pExt->IsOtherStreamActive(); });
355 return isActive;
356}

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 358 of file AudioIOBase.cpp.

359{
360 return (this->IsStreamActive() && this->IsAudioTokenActive(token));
361}
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 298 of file AudioIOBase.cpp.

300{
301 if (auto pOwningProject = mOwningProject.lock();
302 ( pOwningProject ) && ( pOwningProject != project))
303 return;
304
305 auto meter = wMeter.lock();
306 if (meter)
307 {
308 mInputMeter = meter;
309 meter->Reset(mRate, true);
310 }
311 else
312 mInputMeter.reset();
313}
const auto project
double mRate
Audio playback rate in samples per second.
Definition: AudioIOBase.h:255
std::weak_ptr< AudacityProject > mOwningProject
Definition: AudioIOBase.h:245
std::weak_ptr< Meter > mInputMeter
Definition: AudioIOBase.h:259

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 315 of file AudioIOBase.cpp.

317{
318 if (auto pOwningProject = mOwningProject.lock();
319 ( pOwningProject ) && ( pOwningProject != project))
320 return;
321
322 auto meter = wMeter.lock();
323 if (meter)
324 {
325 mOutputMeter = meter;
326 meter->Reset(mRate, true);
327 }
328 else
329 mOutputMeter.reset();
330}
std::weak_ptr< Meter > mOutputMeter
Definition: AudioIOBase.h:260

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 322 of file AudioIOBase.h.

Referenced by IsStreamActive().

◆ mCachedBestRateIn

double AudioIOBase::mCachedBestRateIn = 0.0
staticprotected

Definition at line 282 of file AudioIOBase.h.

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

◆ mCachedCaptureIndex

int AudioIOBase::mCachedCaptureIndex = -1
staticprotected

◆ mCachedCaptureRates

std::vector< long > AudioIOBase::mCachedCaptureRates
staticprotected

Definition at line 280 of file AudioIOBase.h.

Referenced by GetSupportedCaptureRates(), and HandleDeviceChange().

◆ mCachedPlaybackIndex

int AudioIOBase::mCachedPlaybackIndex = -1
staticprotected

◆ mCachedPlaybackRates

std::vector< long > AudioIOBase::mCachedPlaybackRates
staticprotected

Definition at line 278 of file AudioIOBase.h.

Referenced by GetSupportedPlaybackRates(), and HandleDeviceChange().

◆ mCachedSampleRates

std::vector< long > AudioIOBase::mCachedSampleRates
staticprotected

Definition at line 281 of file AudioIOBase.h.

Referenced by GetSupportedSampleRates(), and 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 274 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 248 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 317 of file AudioIOBase.h.

Referenced by GetSupportedCaptureRates(), and GetSupportedPlaybackRates().

◆ NumStandardRates

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

How many standard sample rates there are.

Definition at line 191 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 315 of file AudioIOBase.h.

Referenced by 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 189 of file AudioIOBase.h.

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

◆ ugAudioIO

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

Definition at line 241 of file AudioIOBase.h.

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


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