mirror of
https://github.com/cookiengineer/audacity
synced 2025-07-31 07:59:27 +02:00
Remove PortMixer code
Removes PortMixer code since PortMixer isn't supported by PortAudio Signed-off-by: akleja <storspov@gmail.com>
This commit is contained in:
parent
056de91cf7
commit
12c0cba3c4
@ -628,17 +628,6 @@ else()
|
||||
message(STATUS "FLAC codec support disabled. Requires libflac and libflac++ C++ bindings.")
|
||||
endif()
|
||||
|
||||
# FIXME: requires vendored fork of PortMixer which requires vendored fork of PortAudio
|
||||
# https://github.com/audacity/audacity/issues/840#issuecomment-837795388
|
||||
#find_package(PortMixer)
|
||||
#cmake_dependent_option(PORTMIXER "PortMixer support" ON "PortMixer_FOUND" OFF)
|
||||
#if(PORTMIXER)
|
||||
#set(USE_PORTMIXER ON)
|
||||
#message(STATUS "PortMixer support enabled.")
|
||||
#else()
|
||||
#message(STATUS "PortMixer support disabled.")
|
||||
#endif()
|
||||
|
||||
find_package(sbsms)
|
||||
cmake_dependent_option(SBSMS "SBSMS timestretching" ON "sbsms_FOUND" OFF)
|
||||
if(SBSMS)
|
||||
|
@ -246,9 +246,6 @@ void AboutDialog::CreateInformationTab(ShuttleGui& AboutDialogGUI) {
|
||||
#ifndef USE_LV2
|
||||
#define USE_LV2 0
|
||||
#endif
|
||||
#ifndef USE_PORTMIXER
|
||||
#define USE_PORTMIXER 0
|
||||
#endif
|
||||
#ifndef USE_SOUNDTOUCH
|
||||
#define USE_SOUNDTOUCH 0
|
||||
#endif
|
||||
@ -318,9 +315,6 @@ void AboutDialog::CreateInformationTab(ShuttleGui& AboutDialogGUI) {
|
||||
#ifdef USE_LV2
|
||||
AddBuildInfoRow(&informationStr, wxT("LV2"), buildInfo_pluginSupport, USE_LV2 ? enabled : disabled);
|
||||
#endif
|
||||
#ifdef USE_PORTMIXER
|
||||
AddBuildInfoRow(&informationStr, wxT("PortMixer"), buildInfo_soundCardMixerSupport, USE_PORTMIXER ? enabled : disabled);
|
||||
#endif
|
||||
#ifdef USE_SOUNDTOUCH
|
||||
AddBuildInfoRow(&informationStr, wxT("SoundTouch"), buildInfo_pitchTempoSupport, USE_SOUNDTOUCH ? enabled : disabled);
|
||||
#endif
|
||||
|
174
src/AudioIO.cpp
174
src/AudioIO.cpp
@ -438,10 +438,6 @@ time warp info and AudioIOListener and whether the playback is looped.
|
||||
|
||||
#include "portaudio.h"
|
||||
|
||||
#if USE_PORTMIXER
|
||||
#include "portmixer.h"
|
||||
#endif
|
||||
|
||||
#include <wx/app.h>
|
||||
#include <wx/frame.h>
|
||||
#include <wx/wxcrtvararg.h>
|
||||
@ -1057,16 +1053,6 @@ AudioIO::AudioIO()
|
||||
mThread = std::make_unique<AudioThread>();
|
||||
mThread->Create();
|
||||
|
||||
#if defined(USE_PORTMIXER)
|
||||
mPortMixer = NULL;
|
||||
mPreviousHWPlaythrough = -1.0;
|
||||
HandleDeviceChange();
|
||||
#else
|
||||
mEmulateMixerOutputVol = true;
|
||||
mMixerOutputVol = 1.0;
|
||||
mInputMixerWorks = false;
|
||||
#endif
|
||||
|
||||
mLastPlaybackTimeMillis = 0;
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SUPPORT
|
||||
@ -1078,17 +1064,6 @@ AudioIO::AudioIO()
|
||||
|
||||
AudioIO::~AudioIO()
|
||||
{
|
||||
#if defined(USE_PORTMIXER)
|
||||
if (mPortMixer) {
|
||||
#if __WXMAC__
|
||||
if (Px_SupportsPlaythrough(mPortMixer) && mPreviousHWPlaythrough >= 0.0)
|
||||
Px_SetPlaythrough(mPortMixer, mPreviousHWPlaythrough);
|
||||
mPreviousHWPlaythrough = -1.0;
|
||||
#endif
|
||||
Px_CloseMixer(mPortMixer);
|
||||
mPortMixer = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
// FIXME: ? TRAP_ERR. Pa_Terminate probably OK if err without reporting.
|
||||
Pa_Terminate();
|
||||
@ -1116,96 +1091,6 @@ AudioIO::~AudioIO()
|
||||
mThread.reset();
|
||||
}
|
||||
|
||||
void AudioIO::SetMixer(int inputSource, float recordVolume,
|
||||
float playbackVolume)
|
||||
{
|
||||
mMixerOutputVol = playbackVolume;
|
||||
#if defined(USE_PORTMIXER)
|
||||
PxMixer *mixer = mPortMixer;
|
||||
if( !mixer )
|
||||
return;
|
||||
|
||||
float oldRecordVolume = Px_GetInputVolume(mixer);
|
||||
float oldPlaybackVolume = Px_GetPCMOutputVolume(mixer);
|
||||
|
||||
AudioIoCallback::SetMixer(inputSource);
|
||||
if( oldRecordVolume != recordVolume )
|
||||
Px_SetInputVolume(mixer, recordVolume);
|
||||
if( oldPlaybackVolume != playbackVolume )
|
||||
Px_SetPCMOutputVolume(mixer, playbackVolume);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void AudioIO::GetMixer(int *recordDevice, float *recordVolume,
|
||||
float *playbackVolume)
|
||||
{
|
||||
#if defined(USE_PORTMIXER)
|
||||
|
||||
PxMixer *mixer = mPortMixer;
|
||||
|
||||
if( mixer )
|
||||
{
|
||||
*recordDevice = Px_GetCurrentInputSource(mixer);
|
||||
|
||||
if (mInputMixerWorks)
|
||||
*recordVolume = Px_GetInputVolume(mixer);
|
||||
else
|
||||
*recordVolume = 1.0f;
|
||||
|
||||
if (mEmulateMixerOutputVol)
|
||||
*playbackVolume = mMixerOutputVol;
|
||||
else
|
||||
*playbackVolume = Px_GetPCMOutputVolume(mixer);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
*recordDevice = 0;
|
||||
*recordVolume = 1.0f;
|
||||
*playbackVolume = mMixerOutputVol;
|
||||
}
|
||||
|
||||
bool AudioIO::InputMixerWorks()
|
||||
{
|
||||
return mInputMixerWorks;
|
||||
}
|
||||
|
||||
bool AudioIO::OutputMixerEmulated()
|
||||
{
|
||||
return mEmulateMixerOutputVol;
|
||||
}
|
||||
|
||||
wxArrayString AudioIO::GetInputSourceNames()
|
||||
{
|
||||
#if defined(USE_PORTMIXER)
|
||||
|
||||
wxArrayString deviceNames;
|
||||
|
||||
if( mPortMixer )
|
||||
{
|
||||
int numSources = Px_GetNumInputSources(mPortMixer);
|
||||
for( int source = 0; source < numSources; source++ )
|
||||
deviceNames.push_back(wxString(wxSafeConvertMB2WX(Px_GetInputSourceName(mPortMixer, source))));
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogDebug(wxT("AudioIO::GetInputSourceNames(): PortMixer not initialised!"));
|
||||
}
|
||||
|
||||
return deviceNames;
|
||||
|
||||
#else
|
||||
|
||||
wxArrayString blank;
|
||||
|
||||
return blank;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static PaSampleFormat AudacityToPortAudioSampleFormat(sampleFormat format)
|
||||
{
|
||||
switch(format) {
|
||||
@ -1351,15 +1236,6 @@ bool AudioIO::StartPortAudioStream(const AudioIOStartStreamOptions &options,
|
||||
|
||||
SetMeters();
|
||||
|
||||
#ifdef USE_PORTMIXER
|
||||
#ifdef __WXMSW__
|
||||
//mchinen nov 30 2010. For some reason Pa_OpenStream resets the input volume on windows.
|
||||
//so cache and restore after it.
|
||||
//The actual problem is likely in portaudio's pa_win_wmme.c OpenStream().
|
||||
float oldRecordVolume = Px_GetInputVolume(mPortMixer);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// July 2016 (Carsten and Uwe)
|
||||
// BUG 193: Possibly tell portAudio to use 24 bit with DirectSound.
|
||||
int userData = 24;
|
||||
@ -1388,32 +1264,6 @@ bool AudioIO::StartPortAudioStream(const AudioIOStartStreamOptions &options,
|
||||
wxMilliSleep(1000);
|
||||
}
|
||||
|
||||
|
||||
#if USE_PORTMIXER
|
||||
#ifdef __WXMSW__
|
||||
Px_SetInputVolume(mPortMixer, oldRecordVolume);
|
||||
#endif
|
||||
if (mPortStreamV19 != NULL && mLastPaError == paNoError) {
|
||||
|
||||
#ifdef __WXMAC__
|
||||
if (mPortMixer) {
|
||||
if (Px_SupportsPlaythrough(mPortMixer)) {
|
||||
bool playthrough = false;
|
||||
|
||||
mPreviousHWPlaythrough = Px_GetPlaythrough(mPortMixer);
|
||||
|
||||
// Bug 388. Feature not supported.
|
||||
//gPrefs->Read(wxT("/AudioIO/Playthrough"), &playthrough, false);
|
||||
if (playthrough)
|
||||
Px_SetPlaythrough(mPortMixer, 1.0);
|
||||
else
|
||||
Px_SetPlaythrough(mPortMixer, 0.0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
// We use audio latency to estimate how far ahead of DACS we are writing
|
||||
if (mPortStreamV19 != NULL && mLastPaError == paNoError) {
|
||||
@ -2243,18 +2093,6 @@ void AudioIO::StopStream()
|
||||
wxMilliSleep( 50 );
|
||||
}
|
||||
|
||||
// Turn off HW playthrough if PortMixer is being used
|
||||
|
||||
#if defined(USE_PORTMIXER)
|
||||
if( mPortMixer ) {
|
||||
#if __WXMAC__
|
||||
if (Px_SupportsPlaythrough(mPortMixer) && mPreviousHWPlaythrough >= 0.0)
|
||||
Px_SetPlaythrough(mPortMixer, mPreviousHWPlaythrough);
|
||||
mPreviousHWPlaythrough = -1.0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mPortStreamV19) {
|
||||
Pa_AbortStream( mPortStreamV19 );
|
||||
Pa_CloseStream( mPortStreamV19 );
|
||||
@ -3783,9 +3621,6 @@ void AudioIoCallback::AddToOutputChannel( unsigned int chan,
|
||||
outputMeterFloats[numPlaybackChannels*i+chan] +=
|
||||
gain*tempBuf[i];
|
||||
|
||||
if (mEmulateMixerOutputVol)
|
||||
gain *= mMixerOutputVol;
|
||||
|
||||
float oldGain = vt->GetOldChannelGain(chan);
|
||||
if( gain != oldGain )
|
||||
vt->SetOldChannelGain(chan, gain);
|
||||
@ -4383,14 +4218,7 @@ int AudioIoCallback::AudioCallback(const void *inputBuffer, void *outputBuffer,
|
||||
float *tempFloats = (float *)alloca(framesPerBuffer*sizeof(float)*
|
||||
MAX(numCaptureChannels,numPlaybackChannels));
|
||||
|
||||
bool bVolEmulationActive =
|
||||
(outputBuffer && mEmulateMixerOutputVol && mMixerOutputVol != 1.0);
|
||||
// outputMeterFloats is the scratch pad for the output meter.
|
||||
// we can often reuse the existing outputBuffer and save on allocating
|
||||
// something new.
|
||||
float *outputMeterFloats = bVolEmulationActive ?
|
||||
(float *)alloca(framesPerBuffer*numPlaybackChannels * sizeof(float)) :
|
||||
(float *)outputBuffer;
|
||||
float *outputMeterFloats = (float *)outputBuffer;
|
||||
// ----- END of MEMORY ALLOCATIONS ------------------------------------------
|
||||
|
||||
if (inputBuffer && numCaptureChannels) {
|
||||
|
@ -646,38 +646,6 @@ public:
|
||||
/** \brief Pause and un-pause playback and recording */
|
||||
void SetPaused(bool state);
|
||||
|
||||
/* Mixer services are always available. If no stream is running, these
|
||||
* methods use whatever device is specified by the preferences. If a
|
||||
* stream *is* running, naturally they manipulate the mixer associated
|
||||
* with that stream. If no mixer is available, output is emulated and
|
||||
* input is stuck at 1.0f (a gain is applied to output samples).
|
||||
*/
|
||||
void SetMixer(int inputSource, float inputVolume,
|
||||
float playbackVolume);
|
||||
void GetMixer(int *inputSource, float *inputVolume,
|
||||
float *playbackVolume);
|
||||
/** @brief Find out if the input hardware level control is available
|
||||
*
|
||||
* Checks the mInputMixerWorks variable, which is set up in
|
||||
* AudioIOBase::HandleDeviceChange(). External people care, because we want to
|
||||
* disable the UI if it doesn't work.
|
||||
*/
|
||||
bool InputMixerWorks();
|
||||
|
||||
/** @brief Find out if the output level control is being emulated via software attenuation
|
||||
*
|
||||
* Checks the mEmulateMixerOutputVol variable, which is set up in
|
||||
* AudioIOBase::HandleDeviceChange(). External classes care, because we want to
|
||||
* modify the UI if it doesn't work.
|
||||
*/
|
||||
bool OutputMixerEmulated();
|
||||
|
||||
/** \brief Get the list of inputs to the current mixer device
|
||||
*
|
||||
* Returns an array of strings giving the names of the inputs to the
|
||||
* soundcard mixer (driven by PortMixer) */
|
||||
wxArrayString GetInputSourceNames();
|
||||
|
||||
sampleFormat GetCaptureFormat() { return mCaptureFormat; }
|
||||
unsigned GetNumPlaybackChannels() const { return mNumPlaybackChannels; }
|
||||
unsigned GetNumCaptureChannels() const { return mNumCaptureChannels; }
|
||||
|
@ -23,10 +23,6 @@ Paul Licameli split from AudioIO.cpp
|
||||
|
||||
#include <portaudio.h>
|
||||
|
||||
#if USE_PORTMIXER
|
||||
#include "portmixer.h"
|
||||
#endif
|
||||
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
#include "../lib-src/portmidi/pm_common/portmidi.h"
|
||||
#endif
|
||||
@ -100,15 +96,6 @@ AudioIOBase *AudioIOBase::Get()
|
||||
|
||||
AudioIOBase::~AudioIOBase() = default;
|
||||
|
||||
void AudioIOBase::SetMixer(int inputSource)
|
||||
{
|
||||
#if defined(USE_PORTMIXER)
|
||||
int oldRecordSource = Px_GetCurrentInputSource(mPortMixer);
|
||||
if ( inputSource != oldRecordSource )
|
||||
Px_SetCurrentInputSource(mPortMixer, inputSource);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AudioIOBase::HandleDeviceChange()
|
||||
{
|
||||
// This should not happen, but it would screw things up if it did.
|
||||
@ -135,180 +122,6 @@ void AudioIOBase::HandleDeviceChange()
|
||||
mCachedCaptureIndex = recDeviceNum;
|
||||
mCachedBestRateIn = 0.0;
|
||||
|
||||
#if defined(USE_PORTMIXER)
|
||||
|
||||
// if we have a PortMixer object, close it down
|
||||
if (mPortMixer) {
|
||||
#if __WXMAC__
|
||||
// on the Mac we must make sure that we restore the hardware playthrough
|
||||
// state of the sound device to what it was before, because there isn't
|
||||
// a UI for this (!)
|
||||
if (Px_SupportsPlaythrough(mPortMixer) && mPreviousHWPlaythrough >= 0.0)
|
||||
Px_SetPlaythrough(mPortMixer, mPreviousHWPlaythrough);
|
||||
mPreviousHWPlaythrough = -1.0;
|
||||
#endif
|
||||
Px_CloseMixer(mPortMixer);
|
||||
mPortMixer = NULL;
|
||||
}
|
||||
|
||||
// that might have given us no rates whatsoever, so we have to guess an
|
||||
// answer to do the next bit
|
||||
int numrates = mCachedSampleRates.size();
|
||||
int highestSampleRate;
|
||||
if (numrates > 0)
|
||||
{
|
||||
highestSampleRate = mCachedSampleRates[numrates - 1];
|
||||
}
|
||||
else
|
||||
{ // we don't actually have any rates that work for Rec and Play. Guess one
|
||||
// to use for messing with the mixer, which doesn't actually do either
|
||||
highestSampleRate = 44100;
|
||||
// mCachedSampleRates is still empty, but it's not used again, so
|
||||
// can ignore
|
||||
}
|
||||
mInputMixerWorks = false;
|
||||
mEmulateMixerOutputVol = true;
|
||||
mMixerOutputVol = 1.0;
|
||||
|
||||
int error;
|
||||
// This tries to open the device with the samplerate worked out above, which
|
||||
// will be the highest available for play and record on the device, or
|
||||
// 44.1kHz if the info cannot be fetched.
|
||||
|
||||
PaStream *stream;
|
||||
|
||||
PaStreamParameters playbackParameters;
|
||||
|
||||
playbackParameters.device = playDeviceNum;
|
||||
playbackParameters.sampleFormat = paFloat32;
|
||||
playbackParameters.hostApiSpecificStreamInfo = NULL;
|
||||
playbackParameters.channelCount = 1;
|
||||
if (Pa_GetDeviceInfo(playDeviceNum))
|
||||
playbackParameters.suggestedLatency =
|
||||
Pa_GetDeviceInfo(playDeviceNum)->defaultLowOutputLatency;
|
||||
else
|
||||
playbackParameters.suggestedLatency =
|
||||
AudioIOLatencyCorrection.GetDefault()/1000.0;
|
||||
|
||||
PaStreamParameters captureParameters;
|
||||
|
||||
captureParameters.device = recDeviceNum;
|
||||
captureParameters.sampleFormat = paFloat32;;
|
||||
captureParameters.hostApiSpecificStreamInfo = NULL;
|
||||
captureParameters.channelCount = 1;
|
||||
if (Pa_GetDeviceInfo(recDeviceNum))
|
||||
captureParameters.suggestedLatency =
|
||||
Pa_GetDeviceInfo(recDeviceNum)->defaultLowInputLatency;
|
||||
else
|
||||
captureParameters.suggestedLatency =
|
||||
AudioIOLatencyCorrection.GetDefault()/1000.0;
|
||||
|
||||
// try opening for record and playback
|
||||
// Not really doing I/O so pass nullptr for the callback function
|
||||
error = Pa_OpenStream(&stream,
|
||||
&captureParameters, &playbackParameters,
|
||||
highestSampleRate, paFramesPerBufferUnspecified,
|
||||
paClipOff | paDitherOff,
|
||||
nullptr, NULL);
|
||||
|
||||
if (!error) {
|
||||
// Try portmixer for this stream
|
||||
mPortMixer = Px_OpenMixer(stream, 0);
|
||||
if (!mPortMixer) {
|
||||
Pa_CloseStream(stream);
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
||||
// if that failed, try just for record
|
||||
if( error ) {
|
||||
error = Pa_OpenStream(&stream,
|
||||
&captureParameters, NULL,
|
||||
highestSampleRate, paFramesPerBufferUnspecified,
|
||||
paClipOff | paDitherOff,
|
||||
nullptr, NULL);
|
||||
|
||||
if (!error) {
|
||||
mPortMixer = Px_OpenMixer(stream, 0);
|
||||
if (!mPortMixer) {
|
||||
Pa_CloseStream(stream);
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// finally, try just for playback
|
||||
if ( error ) {
|
||||
error = Pa_OpenStream(&stream,
|
||||
NULL, &playbackParameters,
|
||||
highestSampleRate, paFramesPerBufferUnspecified,
|
||||
paClipOff | paDitherOff,
|
||||
nullptr, NULL);
|
||||
|
||||
if (!error) {
|
||||
mPortMixer = Px_OpenMixer(stream, 0);
|
||||
if (!mPortMixer) {
|
||||
Pa_CloseStream(stream);
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: TRAP_ERR errors in HandleDeviceChange not reported.
|
||||
// if it's still not working, give up
|
||||
if( error )
|
||||
return;
|
||||
|
||||
// Set input source
|
||||
#if USE_PORTMIXER
|
||||
auto sourceIndex = AudioIORecordingSourceIndex.Read(); // defaults to -1
|
||||
if (sourceIndex >= 0) {
|
||||
//the current index of our source may be different because the stream
|
||||
//is a combination of two devices, so update it.
|
||||
sourceIndex = getRecordSourceIndex(mPortMixer);
|
||||
if (sourceIndex >= 0)
|
||||
SetMixer(sourceIndex);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Determine mixer capabilities - if it doesn't support control of output
|
||||
// signal level, we emulate it (by multiplying this value by all outgoing
|
||||
// samples)
|
||||
|
||||
mMixerOutputVol = Px_GetPCMOutputVolume(mPortMixer);
|
||||
mEmulateMixerOutputVol = false;
|
||||
Px_SetPCMOutputVolume(mPortMixer, 0.0);
|
||||
if (Px_GetPCMOutputVolume(mPortMixer) > 0.1)
|
||||
mEmulateMixerOutputVol = true;
|
||||
Px_SetPCMOutputVolume(mPortMixer, 0.2f);
|
||||
if (Px_GetPCMOutputVolume(mPortMixer) < 0.1 ||
|
||||
Px_GetPCMOutputVolume(mPortMixer) > 0.3)
|
||||
mEmulateMixerOutputVol = true;
|
||||
Px_SetPCMOutputVolume(mPortMixer, mMixerOutputVol);
|
||||
|
||||
float inputVol = Px_GetInputVolume(mPortMixer);
|
||||
mInputMixerWorks = true; // assume it works unless proved wrong
|
||||
Px_SetInputVolume(mPortMixer, 0.0);
|
||||
if (Px_GetInputVolume(mPortMixer) > 0.1)
|
||||
mInputMixerWorks = false; // can't set to zero
|
||||
Px_SetInputVolume(mPortMixer, 0.2f);
|
||||
if (Px_GetInputVolume(mPortMixer) < 0.1 ||
|
||||
Px_GetInputVolume(mPortMixer) > 0.3)
|
||||
mInputMixerWorks = false; // can't set level accurately
|
||||
Px_SetInputVolume(mPortMixer, inputVol);
|
||||
|
||||
Pa_CloseStream(stream);
|
||||
|
||||
|
||||
#if 0
|
||||
wxPrintf("PortMixer: Playback: %s Recording: %s\n",
|
||||
mEmulateMixerOutputVol? "emulated": "native",
|
||||
mInputMixerWorks? "hardware": "no control");
|
||||
#endif
|
||||
|
||||
mMixerOutputVol = 1.0;
|
||||
|
||||
#endif // USE_PORTMIXER
|
||||
}
|
||||
|
||||
void AudioIOBase::SetCaptureMeter(AudacityProject *project, MeterPanelBase *meter)
|
||||
@ -580,20 +393,6 @@ int AudioIOBase::GetOptimalSupportedSampleRate()
|
||||
return rates.back();
|
||||
}
|
||||
|
||||
#if USE_PORTMIXER
|
||||
int AudioIOBase::getRecordSourceIndex(PxMixer *portMixer)
|
||||
{
|
||||
int i;
|
||||
auto sourceName = AudioIORecordingSource.Read();
|
||||
int numSources = Px_GetNumInputSources(portMixer);
|
||||
for (i = 0; i < numSources; i++) {
|
||||
if (sourceName == wxString(wxSafeConvertMB2WX(Px_GetInputSourceName(portMixer, i))))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int AudioIOBase::getPlayDevIndex(const wxString &devNameArg)
|
||||
{
|
||||
wxString devName(devNameArg);
|
||||
@ -814,141 +613,6 @@ wxString AudioIOBase::GetDeviceInfo()
|
||||
return o.GetString();
|
||||
}
|
||||
|
||||
#if defined(USE_PORTMIXER)
|
||||
if (supportedSampleRates.size() > 0)
|
||||
{
|
||||
int highestSampleRate = supportedSampleRates.back();
|
||||
bool EmulateMixerInputVol = true;
|
||||
bool EmulateMixerOutputVol = true;
|
||||
float MixerInputVol = 1.0;
|
||||
float MixerOutputVol = 1.0;
|
||||
|
||||
int error;
|
||||
|
||||
PaStream *stream;
|
||||
|
||||
PaStreamParameters playbackParameters;
|
||||
|
||||
playbackParameters.device = playDeviceNum;
|
||||
playbackParameters.sampleFormat = paFloat32;
|
||||
playbackParameters.hostApiSpecificStreamInfo = NULL;
|
||||
playbackParameters.channelCount = 1;
|
||||
if (Pa_GetDeviceInfo(playDeviceNum)){
|
||||
playbackParameters.suggestedLatency =
|
||||
Pa_GetDeviceInfo(playDeviceNum)->defaultLowOutputLatency;
|
||||
}
|
||||
else
|
||||
playbackParameters.suggestedLatency =
|
||||
AudioIOLatencyCorrection.GetDefault()/1000.0;
|
||||
|
||||
PaStreamParameters captureParameters;
|
||||
|
||||
captureParameters.device = recDeviceNum;
|
||||
captureParameters.sampleFormat = paFloat32;;
|
||||
captureParameters.hostApiSpecificStreamInfo = NULL;
|
||||
captureParameters.channelCount = 1;
|
||||
if (Pa_GetDeviceInfo(recDeviceNum)){
|
||||
captureParameters.suggestedLatency =
|
||||
Pa_GetDeviceInfo(recDeviceNum)->defaultLowInputLatency;
|
||||
}
|
||||
else
|
||||
captureParameters.suggestedLatency =
|
||||
AudioIOLatencyCorrection.GetDefault()/1000.0;
|
||||
|
||||
// Not really doing I/O so pass nullptr for the callback function
|
||||
error = Pa_OpenStream(&stream,
|
||||
&captureParameters, &playbackParameters,
|
||||
highestSampleRate, paFramesPerBufferUnspecified,
|
||||
paClipOff | paDitherOff,
|
||||
nullptr, NULL);
|
||||
|
||||
if (error) {
|
||||
error = Pa_OpenStream(&stream,
|
||||
&captureParameters, NULL,
|
||||
highestSampleRate, paFramesPerBufferUnspecified,
|
||||
paClipOff | paDitherOff,
|
||||
nullptr, NULL);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
s << XO("Received %d while opening devices\n").Format( error );
|
||||
return o.GetString();
|
||||
}
|
||||
|
||||
PxMixer *PortMixer = Px_OpenMixer(stream, 0);
|
||||
|
||||
if (!PortMixer) {
|
||||
s << XO("Unable to open Portmixer\n");
|
||||
Pa_CloseStream(stream);
|
||||
return o.GetString();
|
||||
}
|
||||
|
||||
s << wxT("==============================\n");
|
||||
s << XO("Available mixers:\n");
|
||||
|
||||
// FIXME: ? PortMixer errors on query not reported in GetDeviceInfo
|
||||
cnt = Px_GetNumMixers(stream);
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
wxString name = wxSafeConvertMB2WX(Px_GetMixerName(stream, i));
|
||||
s << XO("%d - %s\n").Format( i, name );
|
||||
}
|
||||
|
||||
s << wxT("==============================\n");
|
||||
s << XO("Available recording sources:\n");
|
||||
cnt = Px_GetNumInputSources(PortMixer);
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
wxString name = wxSafeConvertMB2WX(Px_GetInputSourceName(PortMixer, i));
|
||||
s << XO("%d - %s\n").Format( i, name );
|
||||
}
|
||||
|
||||
s << wxT("==============================\n");
|
||||
s << XO("Available playback volumes:\n");
|
||||
cnt = Px_GetNumOutputVolumes(PortMixer);
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
wxString name = wxSafeConvertMB2WX(Px_GetOutputVolumeName(PortMixer, i));
|
||||
s << XO("%d - %s\n").Format( i, name );
|
||||
}
|
||||
|
||||
// Determine mixer capabilities - if it doesn't support either
|
||||
// input or output, we emulate them (by multiplying this value
|
||||
// by all incoming/outgoing samples)
|
||||
|
||||
MixerOutputVol = Px_GetPCMOutputVolume(PortMixer);
|
||||
EmulateMixerOutputVol = false;
|
||||
Px_SetPCMOutputVolume(PortMixer, 0.0);
|
||||
if (Px_GetPCMOutputVolume(PortMixer) > 0.1)
|
||||
EmulateMixerOutputVol = true;
|
||||
Px_SetPCMOutputVolume(PortMixer, 0.2f);
|
||||
if (Px_GetPCMOutputVolume(PortMixer) < 0.1 ||
|
||||
Px_GetPCMOutputVolume(PortMixer) > 0.3)
|
||||
EmulateMixerOutputVol = true;
|
||||
Px_SetPCMOutputVolume(PortMixer, MixerOutputVol);
|
||||
|
||||
MixerInputVol = Px_GetInputVolume(PortMixer);
|
||||
EmulateMixerInputVol = false;
|
||||
Px_SetInputVolume(PortMixer, 0.0);
|
||||
if (Px_GetInputVolume(PortMixer) > 0.1)
|
||||
EmulateMixerInputVol = true;
|
||||
Px_SetInputVolume(PortMixer, 0.2f);
|
||||
if (Px_GetInputVolume(PortMixer) < 0.1 ||
|
||||
Px_GetInputVolume(PortMixer) > 0.3)
|
||||
EmulateMixerInputVol = true;
|
||||
Px_SetInputVolume(PortMixer, MixerInputVol);
|
||||
|
||||
Pa_CloseStream(stream);
|
||||
|
||||
s << wxT("==============================\n");
|
||||
s << ( EmulateMixerInputVol
|
||||
? XO("Recording volume is emulated\n")
|
||||
: XO("Recording volume is native\n") );
|
||||
s << ( EmulateMixerOutputVol
|
||||
? XO("Playback volume is emulated\n")
|
||||
: XO("Playback volume is native\n") );
|
||||
|
||||
Px_CloseMixer(PortMixer);
|
||||
|
||||
} //end of massive if statement if a valid sample rate has been found
|
||||
#endif
|
||||
return o.GetString();
|
||||
}
|
||||
|
||||
|
@ -26,10 +26,6 @@ Paul Licameli split from AudioIO.h
|
||||
struct PaDeviceInfo;
|
||||
typedef void PaStream;
|
||||
|
||||
#if USE_PORTMIXER
|
||||
typedef void PxMixer;
|
||||
#endif
|
||||
|
||||
class AudioIOBase;
|
||||
|
||||
class AudacityProject;
|
||||
@ -246,14 +242,6 @@ public:
|
||||
* playing actual audio) */
|
||||
bool IsMonitoring() const;
|
||||
|
||||
/* Mixer services are always available. If no stream is running, these
|
||||
* methods use whatever device is specified by the preferences. If a
|
||||
* stream *is* running, naturally they manipulate the mixer associated
|
||||
* with that stream. If no mixer is available, output is emulated and
|
||||
* input is stuck at 1.0f (a gain is applied to output samples).
|
||||
*/
|
||||
void SetMixer(int inputSource);
|
||||
|
||||
protected:
|
||||
static std::unique_ptr<AudioIOBase> ugAudioIO;
|
||||
static wxString DeviceName(const PaDeviceInfo* info);
|
||||
@ -280,22 +268,6 @@ protected:
|
||||
wxWeakRef<MeterPanelBase> mInputMeter{};
|
||||
wxWeakRef<MeterPanelBase> mOutputMeter{};
|
||||
|
||||
#if USE_PORTMIXER
|
||||
PxMixer *mPortMixer;
|
||||
float mPreviousHWPlaythrough;
|
||||
#endif /* USE_PORTMIXER */
|
||||
|
||||
bool mEmulateMixerOutputVol;
|
||||
/** @brief 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 */
|
||||
bool mInputMixerWorks;
|
||||
float mMixerOutputVol;
|
||||
|
||||
// For cacheing supported sample rates
|
||||
static int mCachedPlaybackIndex;
|
||||
static std::vector<long> mCachedPlaybackRates;
|
||||
@ -314,14 +286,6 @@ protected:
|
||||
*/
|
||||
static int getRecordDevIndex(const wxString &devName = {});
|
||||
|
||||
/** \brief get the index of the device selected in the preferences.
|
||||
*
|
||||
* If the device isn't found, returns -1
|
||||
*/
|
||||
#if USE_PORTMIXER
|
||||
static int getRecordSourceIndex(PxMixer *portMixer);
|
||||
#endif
|
||||
|
||||
/** \brief get the index of the supplied (named) playback device, or the
|
||||
* device selected in the preferences if none given.
|
||||
*
|
||||
|
@ -1089,7 +1089,6 @@ list( APPEND LIBRARIES
|
||||
$<$<BOOL:${USE_MIDI}>:PortMidi::PortMidi>
|
||||
$<$<BOOL:${USE_MIDI}>:PortSMF::PortSMF>
|
||||
libnyquist
|
||||
$<$<BOOL:${USE_PORTMIXER}>:portmixer>
|
||||
$<$<BOOL:${USE_SBSMS}>:sbsms::sbsms>
|
||||
$<$<BOOL:${USE_SOUNDTOUCH}>:SoundTouch::SoundTouch>
|
||||
$<$<BOOL:${USE_VAMP}>:VampHostSDK::VampHostSDK>
|
||||
|
@ -19,10 +19,6 @@
|
||||
#include "pa_win_wasapi.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_PORTMIXER
|
||||
#include "portmixer.h"
|
||||
#endif
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include <wx/choice.h>
|
||||
#include <wx/event.h>
|
||||
@ -130,9 +126,6 @@ static void FillHostDeviceInfo(DeviceSourceMap *map, const PaDeviceInfo *info, i
|
||||
|
||||
static void AddSourcesFromStream(int deviceIndex, const PaDeviceInfo *info, std::vector<DeviceSourceMap> *maps, PaStream *stream)
|
||||
{
|
||||
#ifdef USE_PORTMIXER
|
||||
int i;
|
||||
#endif
|
||||
DeviceSourceMap map;
|
||||
|
||||
map.sourceIndex = -1;
|
||||
@ -140,36 +133,10 @@ static void AddSourcesFromStream(int deviceIndex, const PaDeviceInfo *info, std:
|
||||
// Only inputs have sources, so we call FillHostDeviceInfo with a 1 to indicate this
|
||||
FillHostDeviceInfo(&map, info, deviceIndex, 1);
|
||||
|
||||
#ifdef USE_PORTMIXER
|
||||
PxMixer *portMixer = Px_OpenMixer(stream, 0);
|
||||
if (!portMixer) {
|
||||
maps->push_back(map);
|
||||
return;
|
||||
}
|
||||
|
||||
//if there is only one source, we don't need to concatenate the source
|
||||
//or enumerate, because it is something meaningless like 'master'
|
||||
//(as opposed to 'mic in' or 'line in'), and the user doesn't have any choice.
|
||||
//note that some devices have no input sources at all but are still valid.
|
||||
//the behavior we do is the same for 0 and 1 source cases.
|
||||
map.totalSources = Px_GetNumInputSources(portMixer);
|
||||
#endif
|
||||
|
||||
if (map.totalSources <= 1) {
|
||||
map.sourceIndex = 0;
|
||||
maps->push_back(map);
|
||||
}
|
||||
#ifdef USE_PORTMIXER
|
||||
else {
|
||||
//open up a stream with the device so portmixer can get the info out of it.
|
||||
for (i = 0; i < map.totalSources; i++) {
|
||||
map.sourceIndex = i;
|
||||
map.sourceString = wxString(wxSafeConvertMB2WX(Px_GetInputSourceName(portMixer, i)));
|
||||
maps->push_back(map);
|
||||
}
|
||||
}
|
||||
Px_CloseMixer(portMixer);
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool IsInputDeviceAMapperDevice(const PaDeviceInfo *info)
|
||||
|
@ -75,9 +75,6 @@
|
||||
/* Define if Nyquist support should be enabled */
|
||||
#cmakedefine USE_NYQUIST 1
|
||||
|
||||
/* Define if PortMixer support should be enabled */
|
||||
#cmakedefine USE_PORTMIXER 1
|
||||
|
||||
/* Define if QuickTime importing is enabled (Mac OS X only) */
|
||||
#cmakedefine USE_QUICKTIME 1
|
||||
|
||||
|
@ -733,32 +733,6 @@ void PrefsDialog::OnOK(wxCommandEvent & WXUNUSED(event))
|
||||
|
||||
SavePreferredPage();
|
||||
|
||||
#if USE_PORTMIXER
|
||||
auto gAudioIO = AudioIOBase::Get();
|
||||
if (gAudioIO) {
|
||||
// We cannot have opened this dialog if gAudioIO->IsAudioTokenActive(),
|
||||
// per the setting of AudioIONotBusyFlag and AudioIOBusyFlag in
|
||||
// AudacityProject::GetUpdateFlags().
|
||||
// However, we can have an invalid audio token (so IsAudioTokenActive()
|
||||
// is false), but be monitoring.
|
||||
// If monitoring, have to stop the stream, so HandleDeviceChange() can work.
|
||||
// We could disable the Preferences command while monitoring, i.e.,
|
||||
// set AudioIONotBusyFlag/AudioIOBusyFlag according to monitoring, as well.
|
||||
// Instead allow it because unlike recording, for example, monitoring
|
||||
// is not clearly something that should prohibit opening prefs.
|
||||
// TODO: We *could* be smarter in this method and call HandleDeviceChange()
|
||||
// only when the device choices actually changed. True of lots of prefs!
|
||||
// As is, we always stop monitoring before handling the device change.
|
||||
if (gAudioIO->IsMonitoring())
|
||||
{
|
||||
gAudioIO->StopStream();
|
||||
while (gAudioIO->IsBusy())
|
||||
wxMilliSleep(100);
|
||||
}
|
||||
gAudioIO->HandleDeviceChange();
|
||||
}
|
||||
#endif
|
||||
|
||||
// PRL: Is the following concern still valid, now that prefs update is
|
||||
// handled instead by delayed event processing?
|
||||
|
||||
|
@ -708,40 +708,6 @@ void DeviceToolBar::ShowComboDialog(wxChoice *combo, const TranslatableString &t
|
||||
return;
|
||||
}
|
||||
|
||||
#if USE_PORTMIXER
|
||||
wxArrayStringEx inputSources = combo->GetStrings();
|
||||
|
||||
wxDialogWrapper dlg(nullptr, wxID_ANY, title);
|
||||
dlg.SetName();
|
||||
ShuttleGui S(&dlg, eIsCreating);
|
||||
wxChoice *c;
|
||||
|
||||
S.StartVerticalLay(true);
|
||||
{
|
||||
S.StartHorizontalLay(wxCENTER, false);
|
||||
{
|
||||
c = S.AddChoice( Verbatim( combo->GetName() ),
|
||||
transform_container<TranslatableStrings>( inputSources, Verbatim ),
|
||||
combo->GetSelection());
|
||||
c->SetMinSize(c->GetBestSize());
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
}
|
||||
S.EndVerticalLay();
|
||||
S.AddStandardButtons();
|
||||
|
||||
dlg.GetSizer()->SetSizeHints(&dlg);
|
||||
dlg.Center();
|
||||
|
||||
if (dlg.ShowModal() == wxID_OK)
|
||||
{
|
||||
wxCommandEvent dummyEvent;
|
||||
dummyEvent.SetEventObject(combo);
|
||||
// SetSelection() doesn't send an event, so we call OnChoice explicitly
|
||||
combo->SetSelection(c->GetSelection());
|
||||
OnChoice(dummyEvent);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static RegisteredToolbarFactory factory{ DeviceBarID,
|
||||
|
Loading…
x
Reference in New Issue
Block a user