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

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

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

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

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

References AudioIOLatencyCorrection, AudioIOPlaybackDevice, AudioIORecordingDevice, DeviceName(), Setting< T >::GetDefault(), GetSupportedPlaybackRates(), GetSupportedSampleRates(), HostName(), IsStreamActive(), name, Setting< T >::Read(), 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 551 of file AudioIOBase.cpp.

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

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

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

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

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

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

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

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

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

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

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

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

363{
364 return ( token > 0 && token == mStreamToken );
365}
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 336 of file AudioIOBase.cpp.

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

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

368{
369 return ( mPortStreamV19 && mStreamToken==0 );
370}
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 331 of file AudioIOBase.cpp.

332{
333 return mPaused.load(std::memory_order_relaxed);
334}
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(), AudioIO::SetPaused(), and AudioIoCallback::TrackShouldBeSilent().

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

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

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

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

299{
300 if (auto pOwningProject = mOwningProject.lock();
301 ( pOwningProject ) && ( pOwningProject != project))
302 return;
303
304 auto meter = wMeter.lock();
305 if (meter)
306 {
307 mInputMeter = meter;
308 meter->Reset(mRate, true);
309 }
310 else
311 mInputMeter.reset();
312}
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, and mRate.

Referenced by AudioIO::StartPortAudioStream().

Here is the caller graph for this function:

◆ SetMixer()

void AudioIOBase::SetMixer ( int  inputSource)

Definition at line 102 of file AudioIOBase.cpp.

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

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

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

References mOutputMeter, mOwningProject, and mRate.

◆ 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: