Audacity 3.2.0
AudioIO.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 AudioIO.cpp
6
7 Copyright 2000-2004:
8 Dominic Mazzoni
9 Joshua Haberman
10 Markus Meyer
11 Matt Brubeck
12
13 This program is free software; you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by the Free
15 Software Foundation; either version 2 of the License, or (at your option)
16 any later version.
17
18********************************************************************//*****************************************************************//****************************************************************//****************************************************************//*******************************************************************/
61#include "AudioIO.h"
62
63#include "AudioIOExt.h"
64#include "AudioIOListener.h"
65
66#include "float_cast.h"
67#include "DeviceManager.h"
68
69#include <cfloat>
70#include <math.h>
71#include <stdlib.h>
72#include <algorithm>
73#include <numeric>
74#include <optional>
75
76#ifdef __WXMSW__
77#include <malloc.h>
78#endif
79
80#ifdef HAVE_ALLOCA_H
81#include <alloca.h>
82#endif
83
84#include "portaudio.h"
85#ifdef __WXMSW__
86#include "pa_win_wasapi.h"
87#endif
88
89#if USE_PORTMIXER
90#include "portmixer.h"
91#endif
92
93#include <wx/wxcrtvararg.h>
94#include <wx/log.h>
95#include <wx/time.h>
96#include <wx/debug.h>
97
98#if defined(__WXMAC__) || defined(__WXMSW__)
99#include <wx/power.h>
100#endif
101
102#include "Channel.h"
103#include "Meter.h"
104#include "Mix.h"
105#include "Resample.h"
106#include "RingBuffer.h"
107#include "Decibels.h"
108#include "Prefs.h"
109#include "Project.h"
110#include "TransactionScope.h"
111
113#include "QualitySettings.h"
114#include "BasicUI.h"
115
116#include "Gain.h"
117
118#ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
119 #define LOWER_BOUND 0.0
120 #define UPPER_BOUND 1.0
121#endif
122
123using std::max;
124using std::min;
125
127{
128 return static_cast< AudioIO* >( AudioIOBase::Get() );
129}
130
132 TransportState(std::weak_ptr<AudacityProject> wOwningProject,
133 const ConstPlayableSequences &playbackSequences,
134 unsigned numPlaybackChannels, double sampleRate)
135 {
136 if (auto pOwningProject = wOwningProject.lock();
137 pOwningProject && numPlaybackChannels > 0) {
138 // Setup for realtime playback at the rate of the realtime
139 // stream, not the rate of the sample sequence.
141 move(wOwningProject), sampleRate, numPlaybackChannels);
142 // The following adds a new effect processor for each logical sequence.
143 for (size_t i = 0, cnt = playbackSequences.size(); i < cnt; ++i) {
144 // An array only of non-null pointers should be given to us
145 const auto vt = playbackSequences[i].get();
146 const auto pGroup = vt ? vt->FindChannelGroup() : nullptr;
147 if (!pGroup) {
148 assert(false);
149 continue;
150 }
152 ->AddGroup(*pGroup, numPlaybackChannels, sampleRate);
153 }
154 }
155 }
156
157 std::optional<RealtimeEffects::InitializationScope> mpRealtimeInitialization;
158};
159
160// static
165
166#ifdef __WXGTK__
167 // Might #define this for a useful thing on Linux
168 #undef REALTIME_ALSA_THREAD
169#else
170 // never on the other operating systems
171 #undef REALTIME_ALSA_THREAD
172#endif
173
174#ifdef REALTIME_ALSA_THREAD
175#include "pa_linux_alsa.h"
176#endif
177
178int audacityAudioCallback(const void *inputBuffer, void *outputBuffer,
179 unsigned long framesPerBuffer,
180 const PaStreamCallbackTimeInfo *timeInfo,
181 PaStreamCallbackFlags statusFlags, void *userData );
182
183
185//
186// UI Thread Context
187//
189
191{
192 auto pAudioIO = safenew AudioIO();
193 ugAudioIO.reset(pAudioIO);
194 pAudioIO->StartThread();
195
196 // Make sure device prefs are initialized
197 if (gPrefs->Read(wxT("AudioIO/RecordingDevice"), wxT("")).empty()) {
198 int i = getRecordDevIndex();
199 const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
200 if (info) {
203 }
204 }
205
206 if (gPrefs->Read(wxT("AudioIO/PlaybackDevice"), wxT("")).empty()) {
207 int i = getPlayDevIndex();
208 const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
209 if (info) {
212 }
213 }
214
215 gPrefs->Flush();
216}
217
219{
220 ugAudioIO.reset();
221}
222
223bool AudioIO::ValidateDeviceNames(const wxString &play, const wxString &rec)
224{
225 const PaDeviceInfo *pInfo = Pa_GetDeviceInfo(getPlayDevIndex(play));
226 const PaDeviceInfo *rInfo = Pa_GetDeviceInfo(getRecordDevIndex(rec));
227
228 // Valid iff both defined and the same api.
229 return pInfo != nullptr && rInfo != nullptr && pInfo->hostApi == rInfo->hostApi;
230}
231
233{
234 if (!std::atomic<double>{}.is_lock_free()) {
235 // If this check fails, then the atomic<double> members in AudioIO.h
236 // might be changed to atomic<float> to be more efficient with some
237 // loss of precision. That could be conditionally compiled depending
238 // on the platform.
239 wxASSERT(false);
240 }
241
242 // This ASSERT because of casting in the callback
243 // functions where we cast a tempFloats buffer to a (short*) buffer.
244 // We have to ASSERT in the GUI thread, if we are to see it properly.
245 wxASSERT( sizeof( short ) <= sizeof( float ));
246
248 .store(false, std::memory_order_relaxed);
250 .store(false, std::memory_order_relaxed);
252 .store(false, std::memory_order_relaxed);
253
254 mAudioThreadAcknowledge.store(Acknowledge::eNone, std::memory_order_relaxed);
255
256 mPortStreamV19 = NULL;
257
258 mNumPauseFrames = 0;
259
260#ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
261 mAILAActive = false;
262#endif
263
264 mLastPaError = paNoError;
265
268 mSilenceLevel = 0.0;
269
270 mOutputMeter.reset();
271
272 PaError err = Pa_Initialize();
273
274 if (err != paNoError) {
275 auto errStr = XO("Could not find any audio devices.\n");
276 errStr += XO("You will not be able to play or record audio.\n\n");
277 wxString paErrStr = LAT1CTOWX(Pa_GetErrorText(err));
278 if (!paErrStr.empty())
279 errStr += XO("Error: %s").Format( paErrStr );
280 // XXX: we are in libaudacity, popping up dialogs not allowed! A
281 // long-term solution will probably involve exceptions
282 using namespace BasicUI;
284 errStr,
286 .Caption(XO("Error Initializing Audio"))
287 .IconStyle(Icon::Error)
288 .ButtonStyle(Button::Ok));
289
290 // Since PortAudio is not initialized, all calls to PortAudio
291 // functions will fail. This will give reasonable behavior, since
292 // the user will be able to do things not relating to audio i/o,
293 // but any attempt to play or record will simply fail.
294 }
295
296#if defined(USE_PORTMIXER)
297 mPortMixer = NULL;
298 mPreviousHWPlaythrough = -1.0;
300#else
301 mInputMixerWorks = false;
302#endif
303
305
307}
308
310{
311 mAudioThread = std::thread(AudioThread, ref(mFinishAudioThread));
312}
313
315{
316 if ( !mOwningProject.expired() )
317 // Unlikely that this will be destroyed earlier than any projects, but
318 // be prepared anyway
320
321#if defined(USE_PORTMIXER)
322 if (mPortMixer) {
323 #if __WXMAC__
324 if (Px_SupportsPlaythrough(mPortMixer) && mPreviousHWPlaythrough >= 0.0)
325 Px_SetPlaythrough(mPortMixer, mPreviousHWPlaythrough);
326 mPreviousHWPlaythrough = -1.0;
327 #endif
328 Px_CloseMixer(mPortMixer);
329 mPortMixer = NULL;
330 }
331#endif
332
333 // FIXME: ? TRAP_ERR. Pa_Terminate probably OK if err without reporting.
334 Pa_Terminate();
335
336 /* Delete is a "graceful" way to stop the thread.
337 (Kill is the not-graceful way.) */
338
339 // This causes reentrancy issues during application shutdown
340 // wxTheApp->Yield();
341
342 mFinishAudioThread.store(true, std::memory_order_release);
343 mAudioThread.join();
344}
345
346std::shared_ptr<RealtimeEffectState>
348 ChannelGroup *pGroup, const PluginID & id)
349{
351 if (mpTransportState && mpTransportState->mpRealtimeInitialization)
352 if (auto pProject = GetOwningProject(); pProject.get() == &project)
353 pInit = &*mpTransportState->mpRealtimeInitialization;
354 return RealtimeEffectManager::Get(project).AddState(pInit, pGroup, id);
355}
356
357std::shared_ptr<RealtimeEffectState>
359 ChannelGroup *pGroup, size_t index, const PluginID & id)
360{
362 if (mpTransportState && mpTransportState->mpRealtimeInitialization)
363 if (auto pProject = GetOwningProject(); pProject.get() == &project)
364 pInit = &*mpTransportState->mpRealtimeInitialization;
366 .ReplaceState(pInit, pGroup, index, id);
367}
368
370 ChannelGroup *pGroup,
371 const std::shared_ptr<RealtimeEffectState> pState)
372{
374 if (mpTransportState && mpTransportState->mpRealtimeInitialization)
375 if (auto pProject = GetOwningProject(); pProject.get() == &project)
376 pInit = &*mpTransportState->mpRealtimeInitialization;
377 RealtimeEffectManager::Get(project).RemoveState(pInit, pGroup, pState);
378}
379
380void AudioIO::SetMixer(int inputSource, float recordVolume,
381 float playbackVolume)
382{
383 SetMixerOutputVol(playbackVolume);
384 AudioIOPlaybackVolume.Write(playbackVolume);
385
386#if defined(USE_PORTMIXER)
387 PxMixer *mixer = mPortMixer;
388 if( !mixer )
389 return;
390
391 float oldRecordVolume = Px_GetInputVolume(mixer);
392
393 AudioIoCallback::SetMixer(inputSource);
394 if( oldRecordVolume != recordVolume )
395 Px_SetInputVolume(mixer, recordVolume);
396
397#endif
398}
399
400void AudioIO::GetMixer(int *recordDevice, float *recordVolume,
401 float *playbackVolume)
402{
403 *playbackVolume = GetMixerOutputVol();
404
405#if defined(USE_PORTMIXER)
406
407 PxMixer *mixer = mPortMixer;
408
409 if( mixer )
410 {
411 *recordDevice = Px_GetCurrentInputSource(mixer);
412
414 *recordVolume = Px_GetInputVolume(mixer);
415 else
416 *recordVolume = 1.0f;
417
418 return;
419 }
420
421#endif
422
423 *recordDevice = 0;
424 *recordVolume = 1.0f;
425}
426
428{
429 return mInputMixerWorks;
430}
431
433{
434#if defined(USE_PORTMIXER)
435
436 wxArrayString deviceNames;
437
438 if( mPortMixer )
439 {
440 int numSources = Px_GetNumInputSources(mPortMixer);
441 for( int source = 0; source < numSources; source++ )
442 deviceNames.push_back(wxString(wxSafeConvertMB2WX(Px_GetInputSourceName(mPortMixer, source))));
443 }
444 else
445 {
446 wxLogDebug(wxT("AudioIO::GetInputSourceNames(): PortMixer not initialised!"));
447 }
448
449 return deviceNames;
450
451#else
452
453 wxArrayString blank;
454
455 return blank;
456
457#endif
458}
459
461{
462 switch(format) {
463 case int16Sample:
464 return paInt16;
465 case int24Sample:
466 return paInt24;
467 case floatSample:
468 default:
469 return paFloat32;
470 }
471}
472
474 unsigned int numPlaybackChannels, unsigned int numCaptureChannels)
475{
476 auto sampleRate = options.rate;
477 mNumPauseFrames = 0;
478 SetOwningProject( options.pProject );
479 bool success = false;
480 auto cleanup = finally([&]{
481 if (!success)
483 });
484
485 // PRL: Protection from crash reported by David Bailes, involving starting
486 // and stopping with frequent changes of active window, hard to reproduce
487 if (mOwningProject.expired())
488 return false;
489
490 mInputMeter.reset();
491 mOutputMeter.reset();
492
493 mLastPaError = paNoError;
494 // pick a rate to do the audio I/O at, from those available. The project
495 // rate is suggested, but we may get something else if it isn't supported
496 mRate = GetBestRate(numCaptureChannels > 0, numPlaybackChannels > 0, sampleRate);
497
498 // GetBestRate() will return 0.0 for bidirectional streams when there is no
499 // common sample rate supported by both the input and output devices.
500 // Bidirectional streams are used when recording while overdub or
501 // software playthrough options are enabled.
502
503 // Pa_OpenStream() will return paInvalidSampleRate when trying to create the
504 // bidirectional stream with a sampleRate of 0.0
505 bool isStreamBidirectional = (numCaptureChannels > 0) && (numPlaybackChannels > 0);
506 bool isUnsupportedSampleRate = isStreamBidirectional && (mRate == 0.0);
507
508 // July 2016 (Carsten and Uwe)
509 // BUG 193: Tell PortAudio sound card will handle 24 bit (under DirectSound) using
510 // userData.
511 auto captureFormat = mCaptureFormat;
512 auto captureFormat_saved = captureFormat;
513 // Special case: Our 24-bit sample format is different from PortAudio's
514 // 3-byte packed format. So just make PortAudio return float samples,
515 // since we need float values anyway to apply the gain.
516 // ANSWER-ME: So we *never* actually handle 24-bit?! This causes mCapture to
517 // be set to floatSample below.
518 // JKC: YES that's right. Internally Audacity uses float, and float has space for
519 // 24 bits as well as exponent. Actual 24 bit would require packing and
520 // unpacking unaligned bytes and would be inefficient.
521 // ANSWER ME: is floatSample 64 bit on 64 bit machines?
522 if (captureFormat == int24Sample)
523 {
524 captureFormat = floatSample;
525 // mCaptureFormat is overwritten before the call to
526 // StartPortAudioStream. So the hack with captureFormat_saved is
527 // still working (assuming it worked before).
528 mCaptureFormat = captureFormat;
529 }
530
531 mNumPlaybackChannels = numPlaybackChannels;
532 mNumCaptureChannels = numCaptureChannels;
533
534 bool usePlayback = false, useCapture = false;
535 PaStreamParameters playbackParameters{};
536 PaStreamParameters captureParameters{};
537
538 #ifdef __WXMSW__
539 PaWasapiStreamInfo wasapiStreamInfo{};
540 #endif
541
542 auto latencyDuration = AudioIOLatencyDuration.Read();
543
544 if( numPlaybackChannels > 0)
545 {
546 usePlayback = true;
547
548 // this sets the device index to whatever is "right" based on preferences,
549 // then defaults
550 playbackParameters.device = getPlayDevIndex();
551
552 const PaDeviceInfo *playbackDeviceInfo;
553 playbackDeviceInfo = Pa_GetDeviceInfo( playbackParameters.device );
554
555 if( playbackDeviceInfo == NULL )
556 return false;
557
558 // regardless of source formats, we always mix to float
559 playbackParameters.sampleFormat = paFloat32;
560 playbackParameters.hostApiSpecificStreamInfo = NULL;
561 playbackParameters.channelCount = mNumPlaybackChannels;
562
563 const PaHostApiInfo* hostInfo = Pa_GetHostApiInfo(playbackDeviceInfo->hostApi);
564 bool isWASAPI = (hostInfo && hostInfo->type == paWASAPI);
565
566 #ifdef __WXMSW__
567 // If the host API is WASAPI, the stream is bidirectional and there is no
568 // supported sample rate enable the WASAPI Sample Rate Conversion
569 // for the playback device.
570 if (isWASAPI && isUnsupportedSampleRate)
571 {
572 wasapiStreamInfo.size = sizeof(PaWasapiStreamInfo);
573 wasapiStreamInfo.hostApiType = paWASAPI;
574 wasapiStreamInfo.version = 1;
575 wasapiStreamInfo.flags = paWinWasapiAutoConvert;
576
577 playbackParameters.hostApiSpecificStreamInfo = &wasapiStreamInfo;
578 }
579 #endif
580
582 playbackParameters.suggestedLatency =
583 playbackDeviceInfo->defaultLowOutputLatency;
584 else {
585 // When using WASAPI, the suggested latency does not affect
586 // the latency of the playback, but the position of playback is given as if
587 // there was the suggested latency. This results in the last "suggested latency"
588 // of a selection not being played. So for WASAPI use 0.0 for the suggested
589 // latency regardless of user setting. See bug 1949.
590 playbackParameters.suggestedLatency = isWASAPI ? 0.0 : latencyDuration/1000.0;
591 }
592
593 mOutputMeter = options.playbackMeter;
594 }
595
596 if( numCaptureChannels > 0)
597 {
598 useCapture = true;
599
600 const PaDeviceInfo *captureDeviceInfo;
601 // retrieve the index of the device set in the prefs, or a sensible
602 // default if it isn't set/valid
603 captureParameters.device = getRecordDevIndex();
604
605 captureDeviceInfo = Pa_GetDeviceInfo( captureParameters.device );
606
607 if( captureDeviceInfo == NULL )
608 return false;
609
610 const PaHostApiInfo* hostInfo = Pa_GetHostApiInfo(captureDeviceInfo->hostApi);
611 bool isWASAPI = (hostInfo && hostInfo->type == paWASAPI);
612
613 // If the stream is bidirectional and there is no supported sample rate
614 // set mRate to the value supported by the capture device.
615 if (isWASAPI && isUnsupportedSampleRate)
616 mRate = captureDeviceInfo->defaultSampleRate;
617
618 captureParameters.sampleFormat =
620
621 captureParameters.hostApiSpecificStreamInfo = NULL;
622 captureParameters.channelCount = mNumCaptureChannels;
623
625 captureParameters.suggestedLatency =
626 captureDeviceInfo->defaultHighInputLatency;
627 else
628 captureParameters.suggestedLatency = latencyDuration/1000.0;
629
631 }
632
633 const auto deviceInfo = usePlayback ?
634 Pa_GetDeviceInfo(playbackParameters.device) :
635 Pa_GetDeviceInfo(captureParameters.device);
636
637 if (deviceInfo != nullptr)
638 {
639 const auto hostApiInfo = Pa_GetHostApiInfo(deviceInfo->hostApi);
640
641 if (hostApiInfo)
642 {
643 mUsingAlsa = hostApiInfo->type == paALSA;
644 mUsingJack = hostApiInfo->type == paJACK;
645 }
646 }
647
648 SetMeters();
649
650#ifdef USE_PORTMIXER
651#ifdef __WXMSW__
652 //mchinen nov 30 2010. For some reason Pa_OpenStream resets the input volume on windows.
653 //so cache and restore after it.
654 //The actual problem is likely in portaudio's pa_win_wmme.c OpenStream().
655 float oldRecordVolume = Px_GetInputVolume(mPortMixer);
656#endif
657#endif
658
659 // July 2016 (Carsten and Uwe)
660 // BUG 193: Possibly tell portAudio to use 24 bit with DirectSound.
661 int userData = 24;
662 int* lpUserData = (captureFormat_saved == int24Sample) ? &userData : NULL;
663
664 // (Linux, bug 1885) After scanning devices it takes a little time for the
665 // ALSA device to be available, so allow retries.
666 // On my test machine, no more than 3 attempts are required.
667 unsigned int maxTries = 1;
668#ifdef __WXGTK__
669 {
670 using namespace std::chrono;
672 maxTries = 5;
673 }
674#endif
675
676 for (unsigned int tries = 0; tries < maxTries; tries++) {
677 mLastPaError = Pa_OpenStream( &mPortStreamV19,
678 useCapture ? &captureParameters : NULL,
679 usePlayback ? &playbackParameters : NULL,
680 mRate, paFramesPerBufferUnspecified,
681 paNoFlag,
682 audacityAudioCallback, lpUserData );
683 if (mLastPaError == paNoError) {
684 const auto stream = Pa_GetStreamInfo(mPortStreamV19);
685 // Use the reported latency as a hint about the hardware buffer size
686 // required for uninterrupted playback.
687 const auto outputLatency =
688 mUsingJack ?
689 // When using Jack as a host, PA calculates the wrong latency
690 // if a non system port is used. Assume, that Jack provides a very
691 // low latency, lower than user requested
692 // (https://github.com/audacity/audacity/issues/4646)
693 (latencyDuration / 1000.0) :
694 // Otherwise, use the (likely incorrect) latency reported by PA
695 stream->outputLatency;
696
697 mHardwarePlaybackLatencyFrames = lrint(outputLatency * mRate);
698#ifdef __WXGTK__
699 // DV: When using ALSA PortAudio does not report the buffer size.
700 // Instead, it reports periodSize * (periodsCount - 1). It is impossible
701 // to retrieve periodSize or periodsCount either. By default PA sets
702 // periodsCount to 4. However it was observed, that PA reports back ~100msec
703 // latency and expects a buffer of ~200msecs on Audacity default settings
704 // which suggests that ALSA changes the periodsCount to suit its needs.
705 //
706 // Why 3? 2 doesn't work for me, 3 does :-) So similar to PA - this
707 // is the value that works for author setup.
708 if (mUsingAlsa)
710#endif
711 break;
712 }
713 wxLogDebug("Attempt %u to open capture stream failed with: %d", 1 + tries, mLastPaError);
714 using namespace std::chrono;
715 std::this_thread::sleep_for(1s);
716 }
717
718
719#if USE_PORTMIXER
720#ifdef __WXMSW__
721 Px_SetInputVolume(mPortMixer, oldRecordVolume);
722#endif
723 if (mPortStreamV19 != NULL && mLastPaError == paNoError) {
724
725 #ifdef __WXMAC__
726 if (mPortMixer) {
727 if (Px_SupportsPlaythrough(mPortMixer)) {
728 bool playthrough = false;
729
730 mPreviousHWPlaythrough = Px_GetPlaythrough(mPortMixer);
731
732 // Bug 388. Feature not supported.
733 //gPrefs->Read(wxT("/AudioIO/Playthrough"), &playthrough, false);
734 if (playthrough)
735 Px_SetPlaythrough(mPortMixer, 1.0);
736 else
737 Px_SetPlaythrough(mPortMixer, 0.0);
738 }
739 }
740 #endif
741 }
742#endif
743
744#if (defined(__WXMAC__) || defined(__WXMSW__)) && wxCHECK_VERSION(3,1,0)
745 // Don't want the system to sleep while audio I/O is active
746 if (mPortStreamV19 != NULL && mLastPaError == paNoError) {
747 wxPowerResource::Acquire(wxPOWER_RESOURCE_SCREEN, _("Audacity Audio"));
748 }
749#endif
750
751 return (success = (mLastPaError == paNoError));
752}
753
755{
756 return wxString::Format(wxT("%d %s."), (int) mLastPaError, Pa_GetErrorText(mLastPaError));
757}
758
760 const std::shared_ptr<AudacityProject> &pProject )
761{
762 if ( !mOwningProject.expired() ) {
763 wxASSERT(false);
765 }
766
767 mOwningProject = pProject;
768}
769
771{
772 mOwningProject.reset();
773}
774
776{
778 return;
779
780 bool success;
781 auto captureFormat = QualitySettings::SampleFormatChoice();
782 auto captureChannels = AudioIORecordChannels.Read();
783 gPrefs->Read(wxT("/AudioIO/SWPlaythrough"), &mSoftwarePlaythrough, false);
784 int playbackChannels = 0;
785
787 playbackChannels = 2;
788
789 // FIXME: TRAP_ERR StartPortAudioStream (a PaError may be present)
790 // but StartPortAudioStream function only returns true or false.
791 mUsingAlsa = false;
792 mCaptureFormat = captureFormat;
793 mCaptureRate = 44100.0; // Shouldn't matter
794 success = StartPortAudioStream(options,
795 static_cast<unsigned int>(playbackChannels),
796 static_cast<unsigned int>(captureChannels));
797
798 auto pOwningProject = mOwningProject.lock();
799 if (!success) {
800 using namespace BasicUI;
801 auto msg = XO("Error opening recording device.\nError code: %s")
802 .Format( Get()->LastPaErrorString() );
803 ShowErrorDialog( *ProjectFramePlacement( pOwningProject.get() ),
804 XO("Error"), msg, wxT("Error_opening_sound_device"),
805 ErrorDialogOptions{ ErrorDialogType::ModalErrorReport } );
806 return;
807 }
808
809 Publish({ pOwningProject.get(), AudioIOEvent::MONITOR, true });
810
811 // FIXME: TRAP_ERR PaErrorCode 'noted' but not reported in StartMonitoring.
812 // Now start the PortAudio stream!
813 // TODO: ? Factor out and reuse error reporting code from end of
814 // AudioIO::StartStream?
815 mLastPaError = Pa_StartStream( mPortStreamV19 );
816
817 // Update UI display only now, after all possibilities for error are past.
818 auto pListener = GetListener();
819 if ((mLastPaError == paNoError) && pListener) {
820 // advertise the chosen I/O sample rate to the UI
821 pListener->OnAudioIORate((int)mRate);
822 }
823}
824
826 double t0, double t1, double mixerLimit,
827 const AudioIOStartStreamOptions &options)
828{
829 // precondition
830 assert(std::all_of(
831 sequences.playbackSequences.begin(), sequences.playbackSequences.end(),
832 [](const auto &pSequence){
833 const auto pGroup =
834 pSequence ? pSequence->FindChannelGroup() : nullptr;
835 return pGroup; }
836 ));
837
838 const auto &pStartTime = options.pStartTime;
839 t1 = std::min(t1, mixerLimit);
840
841 mLostSamples = 0;
842 mLostCaptureIntervals.clear();
844 gPrefs->Read( WarningDialogKey(wxT("DropoutDetected")), true ) != 0;
845 auto cleanup = finally ( [this] { ClearRecordingException(); } );
846
847 if( IsBusy() )
848 return 0;
849
850 // We just want to set mStreamToken to -1 - this way avoids
851 // an extremely rare but possible race condition, if two functions
852 // somehow called StartStream at the same time...
853 mStreamToken--;
854 if (mStreamToken != -1)
855 return 0;
856
857 // TODO: we don't really need to close and reopen stream if the
858 // format matches; however it's kind of tricky to keep it open...
859 //
860 // if (sampleRate == mRate &&
861 // playbackChannels == mNumPlaybackChannels &&
862 // captureChannels == mNumCaptureChannels &&
863 // captureFormat == mCaptureFormat) {
864
865 if (mPortStreamV19) {
866 StopStream();
867 while(mPortStreamV19) {
868 using namespace std::chrono;
869 std::this_thread::sleep_for(50ms);
870 }
871 }
872
873 gPrefs->Read(wxT("/AudioIO/SWPlaythrough"), &mSoftwarePlaythrough, false);
875 gPrefs->Read(wxT("/AudioIO/Microfades"), &mbMicroFades, false);
876 int silenceLevelDB;
877 gPrefs->Read(wxT("/AudioIO/SilenceLevel"), &silenceLevelDB, -50);
878 int dBRange = DecibelScaleCutoff.Read();
879 if(silenceLevelDB < -dBRange)
880 {
881 silenceLevelDB = -dBRange + 3;
882 // meter range was made smaller than SilenceLevel
883 // so set SilenceLevel reasonable
884
885 // PRL: update prefs, or correct it only in-session?
886 // The behavior (as of 2.3.1) was the latter, the code suggested that
887 // the intent was the former; I preserve the behavior, but uncomment
888 // this if you disagree.
889 // gPrefs->Write(wxT("/AudioIO/SilenceLevel"), silenceLevelDB);
890 // gPrefs->Flush();
891 }
892 mSilenceLevel = DB_TO_LINEAR(silenceLevelDB); // meter goes -dBRange dB -> 0dB
893
894 // Clamp pre-roll so we don't play before time 0
895 const auto preRoll = std::max(0.0, std::min(t0, options.preRoll));
901 if (options.pCrossfadeData)
903
904 mListener = options.listener;
905 mRate = options.rate;
906
907 mSeek = 0;
911
912 bool commit = false;
913 auto cleanupSequences = finally([&]{
914 if (!commit) {
915 // Don't keep unnecessary shared pointers to sequences
916 mPlaybackSequences.clear();
917 mCaptureSequences.clear();
918 for(auto &ext : Extensions())
919 ext.AbortOtherStream();
920
921 // Don't cause a busy wait in the audio thread after stopping scrubbing
923 }
924 });
925
926 mPlaybackBuffers.clear();
927 mScratchBuffers.clear();
928 mScratchPointers.clear();
929 mPlaybackMixers.clear();
930 mCaptureBuffers.clear();
931 mResample.clear();
933
935 t0, t1, options, mCaptureSequences.empty() ? nullptr : &mRecordingSchedule );
936
937 unsigned int playbackChannels = 0;
938 size_t numCaptureChannels = 0;
939 sampleFormat captureFormat = floatSample;
940 double captureRate = 44100.0;
941
942 auto pListener = GetListener();
943
944 if (sequences.playbackSequences.size() > 0
945 || sequences.otherPlayableSequences.size() > 0)
946 playbackChannels = 2;
947
949 playbackChannels = 2;
950
951 if (mCaptureSequences.size() > 0) {
952 numCaptureChannels = accumulate(
953 mCaptureSequences.begin(), mCaptureSequences.end(), size_t{},
954 [](auto acc, const auto &pSequence) {
955 return acc + pSequence->NChannels();
956 });
957 // I don't deal with the possibility of the capture sequences
958 // having different sample formats, since it will never happen
959 // with the current code. This code wouldn't *break* if this
960 // assumption was false, but it would be sub-optimal. For example,
961 // if the first sequence was 16-bit and the second sequence was 24-bit,
962 // we would set the sound card to capture in 16 bits and the second
963 // sequence wouldn't get the benefit of all 24 bits the card is capable
964 // of.
965 const auto &sequence0 = mCaptureSequences[0];
966 captureFormat = sequence0->GetSampleFormat();
967 captureRate = sequence0->GetRate();
968
969 // Tell project that we are about to start recording
970 if (pListener)
971 pListener->OnAudioIOStartRecording();
972 }
973
974 bool successAudio;
975
976 mCaptureFormat = captureFormat;
977 mCaptureRate = captureRate;
978 successAudio =
979 StartPortAudioStream(options, playbackChannels, numCaptureChannels);
980
981 // Call this only after reassignment of mRate that might happen in the
982 // previous call.
984
985 auto range = Extensions();
986 successAudio = successAudio &&
987 std::all_of(range.begin(), range.end(),
988 [this, &sequences, t0](auto &ext){
989 return ext.StartOtherStream(sequences,
990 (mPortStreamV19 != NULL && mLastPaError == paNoError)
991 ? Pa_GetStreamInfo(mPortStreamV19) : nullptr,
992 t0, mRate ); });
993
994 if (!successAudio) {
995 if (pListener && numCaptureChannels > 0)
996 pListener->OnAudioIOStopRecording();
997 mStreamToken = 0;
998
999 return 0;
1000 }
1001
1002 {
1003 double mixerStart = t0;
1004 if (pStartTime)
1005 mixerStart = std::min( mixerStart, *pStartTime );
1006 if (!AllocateBuffers(options, sequences,
1007 mixerStart, mixerLimit, options.rate))
1008 return 0;
1009 }
1010
1011 mpTransportState = std::make_unique<TransportState>(mOwningProject,
1013
1014#ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
1015 AILASetStartTime();
1016#endif
1017
1018 if (pStartTime)
1019 {
1020 // Calculate the NEW time position
1021 const auto time = *pStartTime;
1022
1023 // Main thread's initialization of mTime
1026
1027 // Reset mixer positions for all playback sequences
1028 for (auto &mixer : mPlaybackMixers)
1029 mixer->Reposition( time );
1030 }
1031
1032 // Now that we are done with AllocateBuffers() and SetSequenceTime():
1034 // else recording only without overdub
1035
1036 // We signal the audio thread to call SequenceBufferExchange, to prime the RingBuffers
1037 // so that they will have data in them when the stream starts. Having the
1038 // audio thread call SequenceBufferExchange here makes the code more predictable, since
1039 // SequenceBufferExchange will ALWAYS get called from the Audio thread.
1041 .store(true, std::memory_order_release);
1042
1044 .load(std::memory_order_acquire)) {
1045 using namespace std::chrono;
1046 auto interval = 50ms;
1047 if (options.playbackStreamPrimer) {
1048 interval = options.playbackStreamPrimer();
1049 }
1050 std::this_thread::sleep_for(interval);
1051 }
1052
1054
1055#ifdef REALTIME_ALSA_THREAD
1056 // PRL: Do this in hope of less thread scheduling jitter in calls to
1057 // audacityAudioCallback.
1058 // Not needed to make audio playback work smoothly.
1059 // But needed in case we also play MIDI, so that the variable "offset"
1060 // in AudioIO::MidiTime() is a better approximation of the duration
1061 // between the call of audacityAudioCallback and the actual output of
1062 // the first audio sample.
1063 // (Which we should be able to determine from fields of
1064 // PaStreamCallbackTimeInfo, but that seems not to work as documented with
1065 // ALSA.)
1066 if (mUsingAlsa)
1067 // Perhaps we should do this only if also playing MIDI ?
1068 PaAlsa_EnableRealtimeScheduling( mPortStreamV19, 1 );
1069#endif
1070
1071 //
1072 // Generate a unique value each time, to be returned to
1073 // clients accessing the AudioIO API, so they can query if they
1074 // are the ones who have reserved AudioIO or not.
1075 //
1076 // It is important to set this before setting the portaudio stream in
1077 // motion -- otherwise it may play an unspecified number of leading
1078 // zeroes.
1080
1081 // This affects AudioThread (not the portaudio callback).
1082 // Probably not needed so urgently before portaudio thread start for usual
1083 // playback, since our ring buffers have been primed already with 4 sec
1084 // of audio, but then we might be scrubbing, so do it.
1086
1087 mForceFadeOut.store(false, std::memory_order_relaxed);
1088
1089 // Now start the PortAudio stream!
1090 PaError err;
1091 err = Pa_StartStream( mPortStreamV19 );
1092
1093 if( err != paNoError )
1094 {
1095 mStreamToken = 0;
1096
1098
1099 if (pListener && mNumCaptureChannels > 0)
1100 pListener->OnAudioIOStopRecording();
1102 // PRL: PortAudio error messages are sadly not internationalized
1104 Verbatim( LAT1CTOWX(Pa_GetErrorText(err)) ) );
1105 return 0;
1106 }
1107 }
1108
1109 // Update UI display only now, after all possibilities for error are past.
1110 if (pListener) {
1111 // advertise the chosen I/O sample rate to the UI
1112 pListener->OnAudioIORate((int)mRate);
1113 }
1114
1115 auto pOwningProject = mOwningProject.lock();
1116 if (mNumPlaybackChannels > 0)
1117 Publish({ pOwningProject.get(), AudioIOEvent::PLAYBACK, true });
1118 if (mNumCaptureChannels > 0)
1119 Publish({ pOwningProject.get(), AudioIOEvent::CAPTURE, true });
1120
1121 commit = true;
1122
1124
1125 return mStreamToken;
1126}
1127
1128void AudioIO::DelayActions(bool recording)
1129{
1130 mDelayingActions = recording;
1131}
1132
1134{
1136}
1137
1139{
1140 if (!action)
1141 return;
1142
1143 {
1144 std::lock_guard<std::mutex> guard{ mPostRecordingActionMutex };
1146 // Enqueue it, even if perhaps not still recording,
1147 // but it wasn't cleared yet
1149 prevAction = std::move(mPostRecordingAction),
1150 nextAction = std::move(action)
1151 ]{ prevAction(); nextAction(); };
1152 return;
1153 }
1154 else if (DelayingActions()) {
1155 mPostRecordingAction = std::move(action);
1156 return;
1157 }
1158 }
1159
1160 // Don't delay it except until idle time.
1161 // (Recording might start between now and then, but won't go far before
1162 // the action is done. So the system isn't bulletproof yet.)
1163 BasicUI::CallAfter(move(action));
1164}
1165
1167 const AudioIOStartStreamOptions &options,
1168 const TransportSequences &sequences, double t0, double t1, double sampleRate)
1169{
1170 bool success = false;
1171 auto cleanup = finally([&]{
1172 if (!success) StartStreamCleanup( false );
1173 });
1174
1175 auto &policy = mPlaybackSchedule.GetPolicy();
1176 auto times = policy.SuggestedBufferTimes(mPlaybackSchedule);
1177
1178 //
1179 // The (audio) stream has been opened successfully (assuming we tried
1180 // to open it). We now proceed to
1181 // allocate the memory structures the stream will need.
1182 //
1183
1184 //
1185 // The RingBuffer sizes, and the max amount of the buffer to
1186 // fill at a time, both grow linearly with the number of
1187 // sequences. This allows us to scale up to many sequences without
1188 // killing performance.
1189 //
1190
1191 // real playback time to produce with each filling of the buffers
1192 // by the Audio thread (except at the end of playback):
1193 // usually, make fillings fewer and longer for less CPU usage.
1194 // What Audio thread produces for playback is then consumed by the PortAudio
1195 // thread, in many smaller pieces.
1196 double playbackTime = lrint(times.batchSize.count() * mRate) / mRate;
1197
1198 wxASSERT( playbackTime >= 0 );
1199 mPlaybackSamplesToCopy = playbackTime * mRate;
1200
1201 // Capacity of the playback buffer.
1202 mPlaybackRingBufferSecs = times.ringBufferDelay;
1203
1205 4.5 + 0.5 * std::min(size_t(16), mNumCaptureChannels);
1207 0.2 + 0.2 * std::min(size_t(16), mNumCaptureChannels);
1208
1209 bool bDone;
1210 do
1211 {
1212 bDone = true; // assume success
1213 try
1214 {
1215 if( mNumPlaybackChannels > 0 ) {
1216 // Allocate output buffers.
1217 // Allow at least 2x of the buffer latency.
1218 auto playbackBufferSize =
1219 std::max((size_t)lrint(mRate * mPlaybackRingBufferSecs.count()), mHardwarePlaybackLatencyFrames * 2);
1220
1221 // Make playbackBufferSize a multiple of mPlaybackSamplesToCopy
1222 playbackBufferSize = mPlaybackSamplesToCopy *
1223 ((playbackBufferSize + mPlaybackSamplesToCopy - 1) / mPlaybackSamplesToCopy);
1224
1225 // Adjust mPlaybackRingBufferSecs correspondingly
1226 mPlaybackRingBufferSecs = PlaybackPolicy::Duration { playbackBufferSize / mRate };
1227
1228 mPlaybackBuffers.resize(0);
1229 mProcessingBuffers.resize(0);
1230 mMasterBuffers.resize(0);
1231
1232 // Always make at least one playback buffer, in case of
1233 // MIDI playback without any audio
1234 if(mPlaybackSequences.empty())
1235 mPlaybackBuffers.resize(1);
1236 else
1237 {
1239 mProcessingBuffers.resize(std::accumulate(
1240 mPlaybackSequences.begin(),
1241 mPlaybackSequences.end(),
1242 0, [](int n, auto& seq) { return n + seq->NChannels(); }
1243 ));
1244 for(auto& buffer : mProcessingBuffers)
1245 buffer.reserve(playbackBufferSize);
1246
1248 for(auto& buffer : mMasterBuffers)
1249 buffer.reserve(playbackBufferSize);
1250
1251 // Number of scratch buffers depends on device playback channels
1252 if (mNumPlaybackChannels > 0) {
1253 mScratchBuffers.resize(mNumPlaybackChannels * 2 + 1);
1254 mScratchPointers.clear();
1255 for (auto &buffer : mScratchBuffers) {
1256 buffer.Allocate(playbackBufferSize, floatSample);
1257 mScratchPointers.push_back(
1258 reinterpret_cast<float*>(buffer.ptr()));
1259 }
1260 }
1261 }
1262
1263 std::generate(
1264 mPlaybackBuffers.begin(),
1265 mPlaybackBuffers.end(),
1266 [=]{ return std::make_unique<RingBuffer>(floatSample, playbackBufferSize); }
1267 );
1268
1269 mPlaybackMixers.clear();
1270
1271 const auto &warpOptions =
1272 policy.MixerWarpOptions(mPlaybackSchedule);
1273
1274 mPlaybackQueueMinimum = lrint( mRate * times.latency.count() );
1276 std::min( mPlaybackQueueMinimum, playbackBufferSize );
1277
1278 // Limit the mPlaybackQueueMinimum to the hardware latency
1281
1282 // Make mPlaybackQueueMinimum a multiple of mPlaybackSamplesToCopy
1285
1286 // Bug 1763 - We must fade in from zero to avoid a click on starting.
1287 mOldPlaybackGain = 0.0f;
1288 for (unsigned int i = 0; i < mPlaybackSequences.size(); i++) {
1289 const auto &pSequence = mPlaybackSequences[i];
1290
1291 // By the precondition of StartStream which is sole caller of
1292 // this function:
1293 assert(pSequence->FindChannelGroup());
1294 // use sequence time for the end time, not real time!
1295 double startTime, endTime;
1296 if (!sequences.prerollSequences.empty())
1297 startTime = mPlaybackSchedule.mT0;
1298 else
1299 startTime = t0;
1300
1302 .contains(pSequence))
1303 // Stop playing this sequence after pre-roll
1304 endTime = t0;
1305 else
1306 // Pass t1 -- not mT1 as may have been adjusted for latency
1307 // -- so that overdub recording stops playing back samples
1308 // at the right time, though transport may continue to
1309 // record
1310 endTime = t1;
1311
1312 Mixer::Inputs mixSequences;
1313 mixSequences.push_back(Mixer::Input{ pSequence });
1314 mPlaybackMixers.emplace_back(std::make_unique<Mixer>(
1315 std::move(mixSequences), std::nullopt,
1316 // Don't throw for read errors, just play silence:
1317 false, warpOptions, startTime, endTime,
1318 pSequence->NChannels(),
1320 false, // not interleaved
1322 false, // low quality dithering and resampling
1323 nullptr, // no custom mix-down
1324 Mixer::ApplyGain::Discard // don't apply gains
1325 ));
1326 }
1327
1328 const auto timeQueueSize = 1 +
1329 (playbackBufferSize + TimeQueueGrainSize - 1)
1331 mPlaybackSchedule.mTimeQueue.Init( timeQueueSize );
1332 }
1333
1334 if( mNumCaptureChannels > 0 )
1335 {
1336 // Allocate input buffers. For every input sequence we allocate
1337 // a ring buffer of five seconds
1338 auto captureBufferSize =
1339 (size_t)(mRate * mCaptureRingBufferSecs + 0.5);
1340
1341 // In the extraordinarily rare case that we can't even afford
1342 // 100 samples, just give up.
1343 if(captureBufferSize < 100)
1344 {
1345 BasicUI::ShowMessageBox( XO("Out of memory!") );
1346 return false;
1347 }
1348
1349 mCaptureBuffers.resize(0);
1351 mResample.resize(0);
1354
1355 for (unsigned int i = 0; i < mNumCaptureChannels; ++i) {
1356 mCaptureBuffers[i] = std::make_unique<RingBuffer>(
1357 mCaptureFormat, captureBufferSize);
1358 mResample[i] =
1359 std::make_unique<Resample>(true, mFactor, mFactor);
1360 // constant rate resampling
1361 }
1362 }
1363 }
1364 catch(std::bad_alloc&)
1365 {
1366 // Oops! Ran out of memory. This is pretty rare, so we'll just
1367 // try deleting everything, halving our buffer size, and try again.
1368 StartStreamCleanup(true);
1372 mMinCaptureSecsToCopy *= 0.5;
1373 bDone = false;
1374
1375 // In the extraordinarily rare case that we can't even afford 100
1376 // samples, just give up.
1377 auto playbackBufferSize =
1378 (size_t)lrint(mRate * mPlaybackRingBufferSecs.count());
1379 if(playbackBufferSize < 100 || mPlaybackSamplesToCopy < 100)
1380 {
1381 BasicUI::ShowMessageBox( XO("Out of memory!") );
1382 return false;
1383 }
1384 }
1385 } while(!bDone);
1386
1387 success = true;
1388 return true;
1389}
1390
1391void AudioIO::StartStreamCleanup(bool bOnlyBuffers)
1392{
1393 mpTransportState.reset();
1394
1395 mPlaybackBuffers.clear();
1396 mScratchBuffers.clear();
1397 mScratchPointers.clear();
1398 mPlaybackMixers.clear();
1399 mCaptureBuffers.clear();
1400 mResample.clear();
1402
1403 if(!bOnlyBuffers)
1404 {
1405 Pa_AbortStream( mPortStreamV19 );
1406 Pa_CloseStream( mPortStreamV19 );
1407 mPortStreamV19 = NULL;
1408 mStreamToken = 0;
1409 }
1410
1412}
1413
1415{
1416 auto pOwningProject = mOwningProject.lock();
1417 return !pOwningProject || pOwningProject.get() == &project;
1418}
1419
1421{
1422 if (auto pInputMeter = mInputMeter.lock())
1423 pInputMeter->Reset(mRate, true);
1424 if (auto pOutputMeter = mOutputMeter.lock())
1425 pOutputMeter->Reset(mRate, true);
1426}
1427
1429{
1430 auto cleanup = finally ( [this] {
1432 mRecordingSchedule.mCrossfadeData.clear(); // free arrays
1433 } );
1434
1435 if( mPortStreamV19 == NULL )
1436 return;
1437
1438 // DV: This code seems to be unnecessary.
1439 // We do not leave mPortStreamV19 open in stopped
1440 // state. (Do we?)
1441 // This breaks WASAPI backend, as it sets the `running`
1442 // flag to `false` asynchronously.
1443 // Previously we have patched PortAudio and the patch
1444 // was breaking IsStreamStopped() == !IsStreamActive()
1445 // invariant.
1446 /*
1447 if ( Pa_IsStreamStopped(mPortStreamV19) )
1448 return;
1449 */
1450
1451#if (defined(__WXMAC__) || defined(__WXMSW__)) && wxCHECK_VERSION(3,1,0)
1452 // Re-enable system sleep
1453 wxPowerResource::Release(wxPOWER_RESOURCE_SCREEN);
1454#endif
1455
1457 .load(std::memory_order_relaxed) )
1458 {
1459 // PortAudio callback can use the information that we are stopping to fade
1460 // out the audio. Give PortAudio callback a chance to do so.
1461 mForceFadeOut.store(true, std::memory_order_relaxed);
1462 auto latency = static_cast<long>(AudioIOLatencyDuration.Read());
1463 // If we can gracefully fade out in 200ms, with the faded-out play buffers making it through
1464 // the sound card, then do so. If we can't, don't wait around. Just stop quickly and accept
1465 // there will be a click.
1466 if( mbMicroFades && (latency < 150 )) {
1467 using namespace std::chrono;
1468 std::this_thread::sleep_for(milliseconds{latency + 50});
1469 }
1470 }
1471
1472 wxMutexLocker locker(mSuspendAudioThread);
1473
1474 //
1475 // We got here in one of two ways:
1476 //
1477 // 1. The user clicked the stop button and we therefore want to stop
1478 // as quickly as possible. So we use AbortStream(). If this is
1479 // the case the portaudio stream is still in the Running state
1480 // (see PortAudio state machine docs).
1481 //
1482 // 2. The callback told PortAudio to stop the stream since it had
1483 // reached the end of the selection. The UI thread discovered
1484 // this by noticing that AudioIO::IsActive() returned false.
1485 // IsActive() (which calls Pa_GetStreamActive()) will not return
1486 // false until all buffers have finished playing, so we can call
1487 // AbortStream without losing any samples. If this is the case
1488 // we are in the "callback finished state" (see PortAudio state
1489 // machine docs).
1490 //
1491 // The moral of the story: We can call AbortStream safely, without
1492 // losing samples.
1493 //
1494 // DMM: This doesn't seem to be true; it seems to be necessary to
1495 // call StopStream if the callback brought us here, and AbortStream
1496 // if the user brought us here.
1497 //
1498 // DV: Seems that Pa_CloseStream calls Pa_AbortStream internally,
1499 // at least for PortAudio 19.7.0+
1500
1502
1503 // Turn off HW playthrough if PortMixer is being used
1504
1505 #if defined(USE_PORTMIXER)
1506 if( mPortMixer ) {
1507 #if __WXMAC__
1508 if (Px_SupportsPlaythrough(mPortMixer) && mPreviousHWPlaythrough >= 0.0)
1509 Px_SetPlaythrough(mPortMixer, mPreviousHWPlaythrough);
1510 mPreviousHWPlaythrough = -1.0;
1511 #endif
1512 }
1513 #endif
1514
1515 if (mPortStreamV19) {
1516 // DV: Pa_CloseStream will close Pa_AbortStream internally,
1517 // but it doesn't hurt to do it ourselves.
1518 // PA_AbortStream will silently fail if stream is stopped.
1519 if (!Pa_IsStreamStopped( mPortStreamV19 ))
1520 Pa_AbortStream( mPortStreamV19 );
1521
1522 Pa_CloseStream( mPortStreamV19 );
1523
1524 mPortStreamV19 = NULL;
1525 }
1526
1527
1528
1529 // We previously told AudioThread to stop processing, now let's
1530 // be sure it has really stopped before resetting mpTransportState
1532
1533
1534 for( auto &ext : Extensions() )
1535 ext.StopOtherStream();
1536
1537 auto pListener = GetListener();
1538
1539 // If there's no token, we were just monitoring, so we can
1540 // skip this next part...
1541 if (mStreamToken > 0) {
1542 // In either of the above cases, we want to make sure that any
1543 // capture data that made it into the PortAudio callback makes it
1544 // to the target RecordableSequence. To do this, we ask the audio thread
1545 // to call SequenceBufferExchange one last time (it normally would not do
1546 // so since Pa_GetStreamActive() would now return false
1548 }
1549
1550 // No longer need effects processing. This must be done after the stream is stopped
1551 // to prevent the callback from being invoked after the effects are finalized.
1552 mpTransportState.reset();
1553
1554 //
1555 // Everything is taken care of. Now, just free all the resources
1556 // we allocated in StartStream()
1557 //
1558 mPlaybackBuffers.clear();
1559 mScratchBuffers.clear();
1560 mScratchPointers.clear();
1561 mPlaybackMixers.clear();
1563
1564 if (mStreamToken > 0)
1565 {
1566 //
1567 // Offset all recorded sequences to account for latency
1568 //
1569 if (mCaptureSequences.size() > 0) {
1570 mCaptureBuffers.clear();
1571 mResample.clear();
1572
1573 //
1574 // We only apply latency correction when we actually played back
1575 // sequences during the recording. If we did not play back sequences,
1576 // there's nothing we could be out of sync with. This also covers the
1577 // case that we do not apply latency correction when recording the
1578 // first sequence in a project.
1579 //
1580
1581 for (auto &sequence : mCaptureSequences) {
1582 // The calls to Flush
1583 // may cause exceptions because of exhaustion of disk space.
1584 // Stop those exceptions here, or else they propagate through too
1585 // many parts of Audacity that are not effects or editing
1586 // operations. GuardedCall ensures that the user sees a warning.
1587
1588 // Also be sure to Flush each sequence, at the top of the
1589 // guarded call, relying on the guarantee that the sequence will be
1590 // left in a flushed state, though the append buffer may be lost.
1591
1592 GuardedCall( [&] {
1593 // use No-fail-guarantee that sequence is flushed,
1594 // Partial-guarantee that some initial length of the recording
1595 // is saved.
1596 // See comments in SequenceBufferExchange().
1597 sequence->Flush();
1598 } );
1599 }
1600
1601
1602 if (!mLostCaptureIntervals.empty()) {
1603 // This scope may combine many insertions of silence
1604 // into one transaction, lessening the number of checkpoints
1605 std::optional<TransactionScope> pScope;
1606 if (auto pOwningProject = mOwningProject.lock())
1607 pScope.emplace(*pOwningProject, "Dropouts");
1608 for (auto &interval : mLostCaptureIntervals) {
1609 auto &start = interval.first;
1610 auto duration = interval.second;
1611 for (auto &sequence : mCaptureSequences)
1612 GuardedCall([&] {
1613 sequence->InsertSilence(start, duration);
1614 });
1615 }
1616 if (pScope)
1617 pScope->Commit();
1618 }
1619
1620 if (pListener)
1621 pListener->OnCommitRecording();
1622 }
1623 }
1624
1625
1626
1627 if (auto pInputMeter = mInputMeter.lock())
1628 pInputMeter->Reset(mRate, false);
1629
1630 if (auto pOutputMeter = mOutputMeter.lock())
1631 pOutputMeter->Reset(mRate, false);
1632
1633 mInputMeter.reset();
1634 mOutputMeter.reset();
1635
1636 if (pListener && mNumCaptureChannels > 0)
1637 pListener->OnAudioIOStopRecording();
1638
1639 BasicUI::CallAfter([this]{
1641 // Recording was restarted between StopStream and idle time
1642 // So the actions can keep waiting
1643 return;
1644 // In case some other thread was waiting on the mutex too:
1645 std::this_thread::yield();
1646 std::lock_guard<std::mutex> guard{ mPostRecordingActionMutex };
1650 }
1651 DelayActions(false);
1652 });
1653
1654 //
1655 // Only set token to 0 after we're totally finished with everything
1656 //
1657 bool wasMonitoring = mStreamToken == 0;
1658 mStreamToken = 0;
1659
1660 {
1661 auto pOwningProject = mOwningProject.lock();
1662 if (mNumPlaybackChannels > 0)
1663 Publish({ pOwningProject.get(), AudioIOEvent::PLAYBACK, false });
1664 if (mNumCaptureChannels > 0)
1665 Publish({ pOwningProject.get(),
1666 wasMonitoring
1669 false });
1670 }
1671
1673
1676
1677 mPlaybackSequences.clear();
1678 mCaptureSequences.clear();
1679
1681
1682 if (pListener) {
1683 // Tell UI to hide sample rate
1684 pListener->OnAudioIORate(0);
1685 }
1686
1687 // Don't cause a busy wait in the audio thread after stopping scrubbing
1689}
1690
1691void AudioIO::SetPaused(bool state, bool publish)
1692{
1693 if (state != IsPaused())
1694 {
1695 if (auto pOwningProject = mOwningProject.lock()) {
1696 // The realtime effects manager may remain "active" but becomes
1697 // "suspended" or "resumed".
1698 auto &em = RealtimeEffectManager::Get(*pOwningProject);
1699 em.SetSuspended(state);
1700 }
1701 }
1702
1703 mPaused.store(state, std::memory_order_relaxed);
1704
1705 if (publish)
1706 Publish({ mOwningProject.lock().get(), AudioIOEvent::PAUSE, state });
1707}
1708
1709double AudioIO::GetBestRate(bool capturing, bool playing, double sampleRate)
1710{
1711 // Check if we can use the cached value
1713 && mCachedBestRatePlaying == playing && mCachedBestRateCapturing == capturing) {
1714 return mCachedBestRateOut;
1715 }
1716
1717 // In order to cache the value, all early returns should instead set retval
1718 // and jump to finished
1719 double retval;
1720
1721 std::vector<long> rates;
1722 if (capturing) wxLogDebug(wxT("AudioIO::GetBestRate() for capture"));
1723 if (playing) wxLogDebug(wxT("AudioIO::GetBestRate() for playback"));
1724 wxLogDebug(wxT("GetBestRate() suggested rate %.0lf Hz"), sampleRate);
1725
1726 if (capturing && !playing) {
1728 }
1729 else if (playing && !capturing) {
1731 }
1732 else { // we assume capturing and playing - the alternative would be a
1733 // bit odd
1734 rates = GetSupportedSampleRates(-1, -1, sampleRate);
1735 }
1736 /* rem rates is the array of hardware-supported sample rates (in the current
1737 * configuration), sampleRate is the Project Rate (desired sample rate) */
1738 long rate = (long)sampleRate;
1739
1740 if (make_iterator_range(rates).contains(rate)) {
1741 wxLogDebug(wxT("GetBestRate() Returning %.0ld Hz"), rate);
1742 retval = rate;
1743 goto finished;
1744 /* the easy case - the suggested rate (project rate) is in the list, and
1745 * we can just accept that and send back to the caller. This should be
1746 * the case for most users most of the time (all of the time on
1747 * Win MME as the OS does resampling) */
1748 }
1749
1750 /* if we get here, there is a problem - the project rate isn't supported
1751 * on our hardware, so we can't us it. Need to come up with an alternative
1752 * rate to use. The process goes like this:
1753 * * If there are no rates to pick from, we're stuck and return 0 (error)
1754 * * If there are some rates, we pick the next one higher than the requested
1755 * rate to use.
1756 * * If there aren't any higher, we use the highest available rate */
1757
1758 if (rates.empty()) {
1759 /* we're stuck - there are no supported rates with this hardware. Error */
1760 wxLogDebug(wxT("GetBestRate() Error - no supported sample rates"));
1761 retval = 0.0;
1762 goto finished;
1763 }
1764 int i;
1765 for (i = 0; i < (int)rates.size(); i++) // for each supported rate
1766 {
1767 if (rates[i] > rate) {
1768 // supported rate is greater than requested rate
1769 wxLogDebug(wxT("GetBestRate() Returning next higher rate - %.0ld Hz"), rates[i]);
1770 retval = rates[i];
1771 goto finished;
1772 }
1773 }
1774
1775 wxLogDebug(wxT("GetBestRate() Returning highest rate - %.0ld Hz"), rates.back());
1776 retval = rates.back(); // the highest available rate
1777 goto finished;
1778
1779finished:
1781 mCachedBestRateOut = retval;
1782 mCachedBestRatePlaying = playing;
1783 mCachedBestRateCapturing = capturing;
1784 return retval;
1785}
1786
1788{
1789 // Sequence time readout for the main thread
1790
1791 if( !IsStreamActive() )
1792 return BAD_STREAM_TIME;
1793
1795}
1796
1797
1799//
1800// Audio Thread Context
1801//
1803
1805void AudioIO::AudioThread(std::atomic<bool> &finish)
1806{
1807 enum class State { eUndefined, eOnce, eLoopRunning, eDoNothing, eMonitoring } lastState = State::eUndefined;
1808 AudioIO *const gAudioIO = AudioIO::Get();
1809 while (!finish.load(std::memory_order_acquire)) {
1810 using Clock = std::chrono::steady_clock;
1811 auto loopPassStart = Clock::now();
1812 auto &schedule = gAudioIO->mPlaybackSchedule;
1813 const auto interval = schedule.GetPolicy().SleepInterval(schedule);
1814
1815 // Set LoopActive outside the tests to avoid race condition
1817 .store(true, std::memory_order_relaxed);
1819 .load(std::memory_order_acquire) )
1820 {
1821 gAudioIO->SequenceBufferExchange();
1823 .store(false, std::memory_order_release);
1824
1825 lastState = State::eOnce;
1826 }
1828 .load(std::memory_order_relaxed))
1829 {
1830 if (lastState != State::eLoopRunning)
1831 {
1832 // Main thread has told us to start - acknowledge that we do
1834 std::memory_order::memory_order_release);
1835 }
1836 lastState = State::eLoopRunning;
1837
1838 // We call the processing after raising the acknowledge flag, because the main thread
1839 // only needs to know that the message was seen.
1840 //
1841 // This is unlike the case with mAudioThreadShouldCallSequenceBufferExchangeOnce where the
1842 // store really means that the one-time exchange was done.
1843
1844 gAudioIO->SequenceBufferExchange();
1845 }
1846 else
1847 {
1848 if ( (lastState == State::eLoopRunning)
1849 || (lastState == State::eMonitoring ) )
1850 {
1851 // Main thread has told us to stop; (actually: to neither process "once" nor "loop running")
1852 // acknowledge that we received the order and that no more processing will be done.
1854 std::memory_order::memory_order_release);
1855 }
1856 lastState = State::eDoNothing;
1857
1858 if (gAudioIO->IsMonitoring())
1859 {
1860 lastState = State::eMonitoring;
1861 }
1862 }
1863
1865 .store(false, std::memory_order_relaxed);
1866
1867 std::this_thread::sleep_until( loopPassStart + interval );
1868 }
1869}
1870
1872 const RingBuffers &buffers, size_t (RingBuffer::*pmf)() const)
1873{
1874 return std::accumulate(buffers.begin(), buffers.end(),
1875 std::numeric_limits<size_t>::max(),
1876 [pmf](auto value, auto &pBuffer){
1877 return std::min(value, (pBuffer.get()->*pmf)()); });
1878}
1879
1881{
1882 auto commonlyAvail = MinValue(mPlaybackBuffers, &RingBuffer::AvailForPut);
1883 // MB: subtract a few samples because the code in SequenceBufferExchange has rounding
1884 // errors
1885 return commonlyAvail - std::min(size_t(10), commonlyAvail);
1886}
1887
1889{
1891}
1892
1894{
1896}
1897
1899{
1901}
1902
1903// This method is the data gateway between the audio thread (which
1904// communicates with the disk) and the PortAudio callback thread
1905// (which communicates with the audio device).
1907{
1910}
1911
1913{
1914 std::optional<RealtimeEffects::ProcessingScope> pScope;
1915 if (mpTransportState && mpTransportState->mpRealtimeInitialization)
1916 pScope.emplace(
1917 *mpTransportState->mpRealtimeInitialization, mOwningProject);
1918
1919 if (mNumPlaybackChannels == 0)
1920 return;
1921
1922 // It is possible that some buffers will have more samples available than
1923 // others. This could happen if we hit this code during the PortAudio
1924 // callback. Also, if in a previous pass, unequal numbers of samples were
1925 // discarded from ring buffers for differing latencies.
1926
1927 // To keep things simple, we write no more data than is vacant in
1928 // ALL buffers, and advance the global time by that much.
1929 auto nAvailable = GetCommonlyFreePlayback();
1930
1931 // Don't fill the buffers at all unless we can do
1932 // at least mPlaybackSamplesToCopy. This improves performance
1933 // by not always trying to process tiny chunks, eating the
1934 // CPU unnecessarily.
1935 if (nAvailable < mPlaybackSamplesToCopy)
1936 return;
1937
1938 // More than mPlaybackSamplesToCopy might be copied:
1939 // May produce a larger amount when initially priming the buffer, or
1940 // perhaps again later in play to avoid underfilling the queue and
1941 // falling behind the real-time demand on the consumer side in the
1942 // callback.
1943 auto GetNeeded = [&]() -> size_t {
1944 // Note that reader might concurrently consume between loop passes below
1945 // So this might not be nondecreasing
1946 auto nReady = GetCommonlyWrittenForPlayback();
1948 };
1949 auto nNeeded = GetNeeded();
1950
1951 // wxASSERT( nNeeded <= nAvailable );
1952
1953 auto Flush = [&]{
1954 /* The flushing of all the Puts to the RingBuffers is lifted out of the
1955 do-loop in ProcessPlaybackSlices, and also after transformation of the
1956 stream for realtime effects.
1957
1958 It's only here that a release is done on the atomic variable that
1959 indicates the readiness of sample data to the consumer. That atomic
1960 also synchronizes the use of the TimeQueue.
1961 */
1962 for (const auto &pBuffer : mPlaybackBuffers)
1963 pBuffer->Flush();
1964 };
1965
1966 while (true) {
1967 // Limit maximum buffer size (increases performance)
1968 auto available = std::min( nAvailable,
1969 std::max( nNeeded, mPlaybackSamplesToCopy ) );
1970
1971 // After each loop pass or after break
1972 Finally Do{ Flush };
1973
1974 if (!ProcessPlaybackSlices(pScope, available))
1975 // We are not making progress. May fail to satisfy the minimum but
1976 // won't loop forever
1977 break;
1978
1979 // Loop again to satisfy the minimum queue requirement in case there
1980 // was discarding of processed data for effect latencies
1981 nNeeded = GetNeeded();
1982 if (nNeeded == 0)
1983 break;
1984
1985 // Might increase because the reader consumed some
1986 nAvailable = GetCommonlyFreePlayback();
1987 }
1988}
1989
1990#define stackAllocate(T, count) static_cast<T*>(alloca(count * sizeof(T)))
1991
1993 std::optional<RealtimeEffects::ProcessingScope> &pScope, size_t available)
1994{
1995 auto &policy = mPlaybackSchedule.GetPolicy();
1996
1997 // msmeyer: When playing a very short selection in looped
1998 // mode, the selection must be copied to the buffer multiple
1999 // times, to ensure, that the buffer has a reasonable size
2000 // This is the purpose of this loop.
2001 // PRL: or, when scrubbing, we may get work repeatedly from the
2002 // user interface.
2003 bool done = false;
2004 bool progress = false;
2005
2006 // remember initial processing buffer offsets
2007 // they may be different depending on latencies
2008 const auto processingBufferOffsets = stackAllocate(size_t, mProcessingBuffers.size());
2009 for(unsigned n = 0; n < mProcessingBuffers.size(); ++n)
2010 processingBufferOffsets[n] = mProcessingBuffers[n].size();
2011
2012 do {
2013 const auto slice =
2014 policy.GetPlaybackSlice(mPlaybackSchedule, available);
2015 const auto &[frames, toProduce] = slice;
2016 progress = progress || toProduce > 0;
2017
2018 // Update the time queue. This must be done before writing to the
2019 // ring buffers of samples, for proper synchronization with the
2020 // consumer side in the PortAudio thread, which reads the time
2021 // queue after reading the sample queues. The sample queues use
2022 // atomic variables, the time queue doesn't.
2024
2025 // mPlaybackMixers correspond one-to-one with mPlaybackSequences
2026 size_t iSequence = 0;
2027 // mPlaybackBuffers correspond many-to-one with mPlaybackSequences
2028 size_t iBuffer = 0;
2029 for (auto &mixer : mPlaybackMixers) {
2030 // The mixer here isn't actually mixing: it's just doing
2031 // resampling, format conversion, and possibly time track
2032 // warping
2033 if (frames > 0) {
2034 size_t produced = 0;
2035
2036 if (toProduce)
2037 produced = mixer->Process(toProduce);
2038
2039 //wxASSERT(produced <= toProduce);
2040 // Copy (non-interleaved) mixer outputs to one or more ring buffers
2041 const auto nChannels = mPlaybackSequences[iSequence]->NChannels();
2042
2043 const auto appendPos = mProcessingBuffers[iBuffer].size();
2044 for (size_t j = 0; j < nChannels; ++j)
2045 {
2046 // mPlaybackBuffers correspond many-to-one with mPlaybackSequences
2047 auto& buffer = mProcessingBuffers[iBuffer + j];
2048 //Sufficient size should have been reserved in AllocateBuffers
2049 //But for some latency values (> aprox. 100ms) pre-allocated
2050 //buffer could be not large enough.
2051 //Preserve what was written to the buffer during previous pass, don't discard
2052 buffer.resize(buffer.size() + frames, 0);
2053
2054 const auto warpedSamples = mixer->GetBuffer(j);
2055 std::copy_n(
2056 reinterpret_cast<const float*>(warpedSamples),
2057 produced,
2058 buffer.data() + appendPos);
2059 std::fill_n(
2060 buffer.data() + appendPos + produced,
2061 frames - produced,
2062 .0f);
2063 }
2064
2065 iBuffer += nChannels;
2066 ++iSequence;
2067 }
2068 }
2069
2070 available -= frames;
2071 // wxASSERT(available >= 0); // don't assert on this thread
2072 if(mPlaybackSequences.empty())
2073 // Produce silence in the single ring buffer
2074 mPlaybackBuffers[0]->Put(nullptr, floatSample, 0, frames);
2075
2076 done = policy.RepositionPlayback( mPlaybackSchedule, mPlaybackMixers,
2077 frames, available );
2078 } while (available && !done);
2079
2080 //stop here if there are no sample sources to process...
2081 if(mPlaybackSequences.empty())
2082 return progress;
2083
2084 // Do any realtime effect processing for each individual sample source,
2085 // after all the little slices have been written.
2086 if (pScope)
2087 {
2088 const auto pointers = stackAllocate(float*, mNumPlaybackChannels);
2089
2090 int bufferIndex = 0;
2091 for(const auto& seq : mPlaybackSequences)
2092 {
2093 if(!seq)
2094 continue;//no similar check in convert-to-float part
2095 const auto channelGroup = seq->FindChannelGroup();
2096 if(!channelGroup)
2097 continue;
2098
2099 // Are there more output device channels than channels of vt?
2100 // Such as when a mono sequence is processed for stereo play?
2101 // Then supply some non-null fake input buffers, because the
2102 // various ProcessBlock overrides of effects may crash without it.
2103 // But it would be good to find the fixes to make this unnecessary.
2104 auto scratch = &mScratchPointers[mNumPlaybackChannels + 1];
2105
2106 //skip samples that are already processed
2107 const auto offset = processingBufferOffsets[bufferIndex];
2108 //number of newly written samples
2109 const auto len = mProcessingBuffers[bufferIndex].size() - offset;
2110
2111 if(len > 0)
2112 {
2113 for(unsigned i = 0; i < seq->NChannels(); ++i)
2114 pointers[i] = mProcessingBuffers[bufferIndex + i].data() + offset;
2115
2116 for(unsigned i = seq->NChannels(); i < mNumPlaybackChannels; ++i)
2117 {
2118
2119 pointers[i] = *scratch++;
2120 std::fill_n(pointers[i], len, .0f);
2121 }
2122
2123 const auto discardable = pScope->Process(channelGroup, &pointers[0],
2124 mScratchPointers.data(),
2125 // The single dummy output buffer:
2128 // Check for asynchronous user changes in mute, solo status
2129 const auto silenced = SequenceShouldBeSilent(*seq);
2130 for(int i = 0; i < seq->NChannels(); ++i)
2131 {
2132 auto& buffer = mProcessingBuffers[bufferIndex + i];
2133 buffer.erase(buffer.begin() + offset, buffer.begin() + offset + discardable);
2134 if(silenced)
2135 {
2136 //TODO: fade out smoothly
2137 std::fill_n(buffer.data() + offset, len - discardable, 0);
2138 }
2139 }
2140 }
2141
2142 bufferIndex += seq->NChannels();
2143 }
2144 }
2145
2146 //samples at the beginning could have been discarded
2147 //in the previous step, proceed with the number of samples
2148 //equal to the shortest buffer size available
2149 auto samplesAvailable = std::min_element(
2150 mProcessingBuffers.begin(),
2151 mProcessingBuffers.end(),
2152 [](auto& first, auto& second) { return first.size() < second.size(); }
2153 )->size();
2154
2155 //introduced latency may be too high...
2156 //but we don't discard what already was written
2157 if(samplesAvailable == 0)
2158 return progress;
2159
2160 //Prepare master buffers.
2161 auto cleanup = finally([=] {
2162 for(auto& buffer : mMasterBuffers)
2163 buffer.clear();
2164 });
2165
2166 for(auto& buffer : mMasterBuffers)
2167 {
2168 //assert(buffer.size() == 0);
2169 //assert(buffer.capacity() >= samplesAvailable);
2170 buffer.resize(samplesAvailable, 0);
2171 }
2172
2173 {
2174 unsigned bufferIndex = 0;
2175 for(const auto& seq : mPlaybackSequences)
2176 {
2177 //TODO: apply micro-fades
2178 const auto numChannels = seq->NChannels();
2179 if(numChannels > 1)
2180 {
2181 for(unsigned n = 0; n < seq->NChannels(); ++n)
2182 {
2183 const auto gain = seq->GetChannelGain(n);
2184 for(unsigned i = 0; i < samplesAvailable; ++i)
2185 mMasterBuffers[n][i] += mProcessingBuffers[bufferIndex + n][i] * gain;
2186 }
2187 }
2188 else if(numChannels == 1)
2189 {
2190 //mono source is duplicated into every output channel
2191 for(unsigned n = 0; n < mNumPlaybackChannels; ++n)
2192 {
2193 const auto gain = seq->GetChannelGain(n);
2194 for(unsigned i = 0; i < samplesAvailable; ++i)
2195 mMasterBuffers[n][i] += mProcessingBuffers[bufferIndex][i] * gain;
2196 }
2197 }
2198 bufferIndex += seq->NChannels();
2199 }
2200 }
2201
2202 //remove only samples that were processed in previous step
2203 for(auto& buffer : mProcessingBuffers)
2204 buffer.erase(buffer.begin(), buffer.begin() + samplesAvailable);
2205
2206 // Do any realtime effect processing, after all the little
2207 // slices have been written. This time we use mixed source created in
2208 // previous step
2209 size_t masterBufferOffset = 0;//The amount of samples to be discarded
2210 if(pScope)
2211 {
2212 const auto pointers = stackAllocate(float*, mNumPlaybackChannels);
2213 for(unsigned i = 0; i < mNumPlaybackChannels; ++i)
2214 pointers[i] = mMasterBuffers[i].data();
2215
2216 masterBufferOffset = pScope->Process(
2218 &pointers[0],
2219 mScratchPointers.data(),
2220 // The single dummy output buffer:
2222 mNumPlaybackChannels, samplesAvailable);
2223
2224 // wxASSERT(samplesAvailable >= masterBufferOffset); // don't assert on this thread
2225 samplesAvailable -= masterBufferOffset;
2226 }
2227
2228 if(samplesAvailable == 0)
2229 return progress;
2230
2231 {
2232 unsigned bufferIndex = 0;
2233 for(auto& buffer : mMasterBuffers)
2234 {
2235 mPlaybackBuffers[bufferIndex++]->Put(
2236 reinterpret_cast<constSamplePtr>(buffer.data()) + masterBufferOffset * sizeof(float),
2238 samplesAvailable,
2239 0
2240 );
2241 }
2242 }
2243
2244 for(auto& buffer : mMasterBuffers)
2245 buffer.clear();
2246
2247 return progress;
2248}
2249
2251{
2253 return;
2254
2255 auto delayedHandler = [this] ( AudacityException * pException ) {
2256 // In the main thread, stop recording
2257 // This is one place where the application handles disk
2258 // exhaustion exceptions from RecordableSequence operations, without
2259 // rolling back to the last pushed undo state. Instead, partial recording
2260 // results are pushed as a NEW undo state. For this reason, as
2261 // commented elsewhere, we want an exception safety guarantee for
2262 // the output RecordableSequences, after the failed append operation, that
2263 // the sequences remain as they were after the previous successful
2264 // (block-level) appends.
2265
2266 // Note that the Flush in StopStream() may throw another exception,
2267 // but StopStream() contains that exception, and the logic in
2268 // AudacityException::DelayedHandlerAction prevents redundant message
2269 // boxes.
2270 StopStream();
2271 DefaultDelayedHandlerAction( pException );
2272 for (auto &pSequence: mCaptureSequences)
2273 pSequence->RepairChannels();
2274 };
2275
2276 GuardedCall( [&] {
2277 // start record buffering
2278 const auto avail = GetCommonlyAvailCapture(); // samples
2279 const auto remainingTime =
2280 std::max(0.0, mRecordingSchedule.ToConsume());
2281 // This may be a very big double number:
2282 const auto remainingSamples = remainingTime * mRate;
2283 bool latencyCorrected = true;
2284
2285 double deltat = avail / mRate;
2286
2288 .load(std::memory_order_relaxed) ||
2289 deltat >= mMinCaptureSecsToCopy)
2290 {
2291 bool newBlocks = false;
2292
2293 // Append captured samples to the end of the RecordableSequences.
2294 // (WaveTracks have their own buffering for efficiency.)
2295 auto iter = mCaptureSequences.begin();
2296 auto width = (*iter)->NChannels();
2297 size_t iChannel = 0;
2298 for (size_t i = 0; i < mNumCaptureChannels; ++i) {
2299 Finally Do {[&]{
2300 if (++iChannel == width) {
2301 ++iter;
2302 iChannel = 0;
2303 if (iter != mCaptureSequences.end())
2304 width = (*iter)->NChannels();
2305 }
2306 }};
2307 size_t discarded = 0;
2308
2310 const auto correction = mRecordingSchedule.TotalCorrection();
2311 if (correction >= 0) {
2312 // Rightward shift
2313 // Once only (per sequence per recording), insert some initial
2314 // silence.
2315 size_t size = floor( correction * mRate * mFactor);
2317 ClearSamples(temp.ptr(), mCaptureFormat, 0, size);
2318 (*iter)->Append(iChannel, temp.ptr(), mCaptureFormat, size, 1,
2319 // Do not dither recordings
2321 }
2322 else {
2323 // Leftward shift
2324 // discard some samples from the ring buffers.
2325 size_t size = floor(
2327
2328 // The ring buffer might have grown concurrently -- don't discard more
2329 // than the "avail" value noted above.
2330 discarded = mCaptureBuffers[i]->Discard(std::min(avail, size));
2331
2332 if (discarded < size)
2333 // We need to visit this again to complete the
2334 // discarding.
2335 latencyCorrected = false;
2336 }
2337 }
2338
2339 const float *pCrossfadeSrc = nullptr;
2340 size_t crossfadeStart = 0, totalCrossfadeLength = 0;
2341 if (i < mRecordingSchedule.mCrossfadeData.size())
2342 {
2343 // Do crossfading
2344 // The supplied crossfade samples are at the same rate as the
2345 // sequence
2346 const auto &data = mRecordingSchedule.mCrossfadeData[i];
2347 totalCrossfadeLength = data.size();
2348 if (totalCrossfadeLength) {
2349 crossfadeStart =
2351 if (crossfadeStart < totalCrossfadeLength)
2352 pCrossfadeSrc = data.data() + crossfadeStart;
2353 }
2354 }
2355
2356 wxASSERT(discarded <= avail);
2357 size_t toGet = avail - discarded;
2358 SampleBuffer temp;
2359 size_t size;
2361 if( mFactor == 1.0 )
2362 {
2363 // Take captured samples directly
2364 size = toGet;
2365 if (pCrossfadeSrc)
2366 // Change to float for crossfade calculation
2368 else
2370 temp.Allocate(size, format);
2371 const auto got =
2372 mCaptureBuffers[i]->Get(temp.ptr(), format, toGet);
2373 // wxASSERT(got == toGet);
2374 // but we can't assert in this thread
2375 wxUnusedVar(got);
2376 if (double(size) > remainingSamples)
2377 size = floor(remainingSamples);
2378 }
2379 else
2380 {
2381 size = lrint(toGet * mFactor);
2383 SampleBuffer temp1(toGet, floatSample);
2384 temp.Allocate(size, format);
2385 const auto got =
2386 mCaptureBuffers[i]->Get(temp1.ptr(), floatSample, toGet);
2387 // wxASSERT(got == toGet);
2388 // but we can't assert in this thread
2389 wxUnusedVar(got);
2390 /* we are re-sampling on the fly. The last resampling call
2391 * must flush any samples left in the rate conversion buffer
2392 * so that they get recorded
2393 */
2394 if (toGet > 0 ) {
2395 if (double(toGet) > remainingSamples)
2396 toGet = floor(remainingSamples);
2397 const auto results =
2398 mResample[i]->Process(mFactor, (float *)temp1.ptr(), toGet,
2399 !IsStreamActive(), (float *)temp.ptr(), size);
2400 size = results.second;
2401 }
2402 }
2403
2404 if (pCrossfadeSrc) {
2405 wxASSERT(format == floatSample);
2406 size_t crossfadeLength = std::min(size, totalCrossfadeLength - crossfadeStart);
2407 if (crossfadeLength) {
2408 auto ratio = double(crossfadeStart) / totalCrossfadeLength;
2409 auto ratioStep = 1.0 / totalCrossfadeLength;
2410 auto pCrossfadeDst = (float*)temp.ptr();
2411
2412 // Crossfade loop here
2413 for (size_t ii = 0; ii < crossfadeLength; ++ii) {
2414 *pCrossfadeDst = ratio * *pCrossfadeDst + (1.0 - ratio) * *pCrossfadeSrc;
2415 ++pCrossfadeSrc, ++pCrossfadeDst;
2416 ratio += ratioStep;
2417 }
2418 }
2419 }
2420
2421 // Now append
2422 // see comment in second handler about guarantee
2423 newBlocks = (*iter)->Append(iChannel,
2424 temp.ptr(), format, size, 1,
2425 // Do not dither recordings
2427 ) || newBlocks;
2428 } // end loop over capture channels
2429
2430 // Now update the recording schedule position
2432 mRecordingSchedule.mLatencyCorrected = latencyCorrected;
2433
2434 auto pListener = GetListener();
2435 if (pListener && newBlocks)
2436 pListener->OnAudioIONewBlocks();
2437
2438 }
2439 // end of record buffering
2440 },
2441 // handler
2442 [this] ( AudacityException *pException ) {
2443 if ( pException ) {
2444 // So that we don't attempt to fill the recording buffer again
2445 // before the main thread stops recording
2447 return ;
2448 }
2449 else
2450 // Don't want to intercept other exceptions (?)
2451 throw;
2452 },
2453 delayedHandler );
2454}
2455
2457 const std::shared_ptr< AudioIOListener > &listener)
2458{
2459 if (IsBusy())
2460 return;
2461
2462 mListener = listener;
2463}
2464
2465// Automated Input Level Adjustment - Automatically tries to find an acceptable input volume
2466#ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
2467
2468#include "ProjectStatus.h"
2469
2470void AudioIO::AILAInitialize() {
2471 gPrefs->Read(wxT("/AudioIO/AutomatedInputLevelAdjustment"), &mAILAActive, false);
2472 gPrefs->Read(wxT("/AudioIO/TargetPeak"), &mAILAGoalPoint, AILA_DEF_TARGET_PEAK);
2473 gPrefs->Read(wxT("/AudioIO/DeltaPeakVolume"), &mAILAGoalDelta, AILA_DEF_DELTA_PEAK);
2474 gPrefs->Read(wxT("/AudioIO/AnalysisTime"), &mAILAAnalysisTime, AILA_DEF_ANALYSIS_TIME);
2475 gPrefs->Read(wxT("/AudioIO/NumberAnalysis"), &mAILATotalAnalysis, AILA_DEF_NUMBER_ANALYSIS);
2476 mAILAGoalDelta /= 100.0;
2477 mAILAGoalPoint /= 100.0;
2478 mAILAAnalysisTime /= 1000.0;
2479 mAILAMax = 0.0;
2480 mAILALastStartTime = max(0.0, mPlaybackSchedule.mT0);
2481 mAILAClipped = false;
2482 mAILAAnalysisCounter = 0;
2483 mAILAChangeFactor = 1.0;
2484 mAILALastChangeType = 0;
2485 mAILATopLevel = 1.0;
2486 mAILAAnalysisEndTime = -1.0;
2487}
2488
2489void AudioIO::AILADisable() {
2490 mAILAActive = false;
2491}
2492
2493bool AudioIO::AILAIsActive() {
2494 return mAILAActive;
2495}
2496
2497void AudioIO::AILASetStartTime() {
2498 mAILAAbsolutStartTime = Pa_GetStreamTime(mPortStreamV19);
2499 wxPrintf("START TIME %f\n\n", mAILAAbsolutStartTime);
2500}
2501
2502double AudioIO::AILAGetLastDecisionTime() {
2503 return mAILAAnalysisEndTime;
2504}
2505
2506void AudioIO::AILAProcess(double maxPeak) {
2507 const auto proj = mOwningProject.lock();
2508 if (proj && mAILAActive) {
2509 if (mInputMeter && mInputMeter->IsClipping()) {
2510 mAILAClipped = true;
2511 wxPrintf("clipped");
2512 }
2513
2514 mAILAMax = max(mAILAMax, maxPeak);
2515
2516 if ((mAILATotalAnalysis == 0 || mAILAAnalysisCounter < mAILATotalAnalysis) && mPlaybackSchedule.GetSequenceTime() - mAILALastStartTime >= mAILAAnalysisTime) {
2517 auto ToLinearIfDB = [](double value, int dbRange) {
2518 if (dbRange >= 0)
2519 value = pow(10.0, (-(1.0-value) * dbRange)/20.0);
2520 return value;
2521 };
2522
2523 putchar('\n');
2524 mAILAMax = mInputMeter ? ToLinearIfDB(mAILAMax, mInputMeter->GetDBRange()) : 0.0;
2525 double iv = (double) Px_GetInputVolume(mPortMixer);
2526 unsigned short changetype = 0; //0 - no change, 1 - increase change, 2 - decrease change
2527 wxPrintf("mAILAAnalysisCounter:%d\n", mAILAAnalysisCounter);
2528 wxPrintf("\tmAILAClipped:%d\n", mAILAClipped);
2529 wxPrintf("\tmAILAMax (linear):%f\n", mAILAMax);
2530 wxPrintf("\tmAILAGoalPoint:%f\n", mAILAGoalPoint);
2531 wxPrintf("\tmAILAGoalDelta:%f\n", mAILAGoalDelta);
2532 wxPrintf("\tiv:%f\n", iv);
2533 wxPrintf("\tmAILAChangeFactor:%f\n", mAILAChangeFactor);
2534 if (mAILAClipped || mAILAMax > mAILAGoalPoint + mAILAGoalDelta) {
2535 wxPrintf("too high:\n");
2536 mAILATopLevel = min(mAILATopLevel, iv);
2537 wxPrintf("\tmAILATopLevel:%f\n", mAILATopLevel);
2538 //if clipped or too high
2539 if (iv <= LOWER_BOUND) {
2540 //we can't improve it more now
2541 if (mAILATotalAnalysis != 0) {
2542 mAILAActive = false;
2543 ProjectStatus::Get( *proj ).Set(
2544 XO(
2545"Automated Recording Level Adjustment stopped. It was not possible to optimize it more. Still too high.") );
2546 }
2547 wxPrintf("\talready min vol:%f\n", iv);
2548 }
2549 else {
2550 float vol = (float) max(LOWER_BOUND, iv+(mAILAGoalPoint-mAILAMax)*mAILAChangeFactor);
2551 Px_SetInputVolume(mPortMixer, vol);
2552 auto msg = XO(
2553"Automated Recording Level Adjustment decreased the volume to %f.").Format( vol );
2554 ProjectStatus::Get( *proj ).Set(msg);
2555 changetype = 1;
2556 wxPrintf("\tnew vol:%f\n", vol);
2557 float check = Px_GetInputVolume(mPortMixer);
2558 wxPrintf("\tverified %f\n", check);
2559 }
2560 }
2561 else if ( mAILAMax < mAILAGoalPoint - mAILAGoalDelta ) {
2562 //if too low
2563 wxPrintf("too low:\n");
2564 if (iv >= UPPER_BOUND || iv + 0.005 > mAILATopLevel) { //condition for too low volumes and/or variable volumes that cause mAILATopLevel to decrease too much
2565 //we can't improve it more
2566 if (mAILATotalAnalysis != 0) {
2567 mAILAActive = false;
2568 ProjectStatus::Get( *proj ).Set(
2569 XO(
2570"Automated Recording Level Adjustment stopped. It was not possible to optimize it more. Still too low.") );
2571 }
2572 wxPrintf("\talready max vol:%f\n", iv);
2573 }
2574 else {
2575 float vol = (float) min(UPPER_BOUND, iv+(mAILAGoalPoint-mAILAMax)*mAILAChangeFactor);
2576 if (vol > mAILATopLevel) {
2577 vol = (iv + mAILATopLevel)/2.0;
2578 wxPrintf("\tTruncated vol:%f\n", vol);
2579 }
2580 Px_SetInputVolume(mPortMixer, vol);
2581 auto msg = XO(
2582"Automated Recording Level Adjustment increased the volume to %.2f.")
2583 .Format( vol );
2584 ProjectStatus::Get( *proj ).Set(msg);
2585 changetype = 2;
2586 wxPrintf("\tnew vol:%f\n", vol);
2587 float check = Px_GetInputVolume(mPortMixer);
2588 wxPrintf("\tverified %f\n", check);
2589 }
2590 }
2591
2592 mAILAAnalysisCounter++;
2593 //const PaStreamInfo* info = Pa_GetStreamInfo(mPortStreamV19);
2594 //double latency = 0.0;
2595 //if (info)
2596 // latency = info->inputLatency;
2597 //mAILAAnalysisEndTime = mTime+latency;
2598 mAILAAnalysisEndTime = Pa_GetStreamTime(mPortStreamV19) - mAILAAbsolutStartTime;
2599 mAILAMax = 0;
2600 wxPrintf("\tA decision was made @ %f\n", mAILAAnalysisEndTime);
2601 mAILAClipped = false;
2602 mAILALastStartTime = mPlaybackSchedule.GetSequenceTime();
2603
2604 if (changetype == 0)
2605 mAILAChangeFactor *= 0.8; //time factor
2606 else if (mAILALastChangeType == changetype)
2607 mAILAChangeFactor *= 1.1; //concordance factor
2608 else
2609 mAILAChangeFactor *= 0.7; //discordance factor
2610 mAILALastChangeType = changetype;
2611 putchar('\n');
2612 }
2613
2614 if (mAILAActive && mAILATotalAnalysis != 0 && mAILAAnalysisCounter >= mAILATotalAnalysis) {
2615 mAILAActive = false;
2616 if (mAILAMax > mAILAGoalPoint + mAILAGoalDelta)
2617 ProjectStatus::Get( *proj ).Set(
2618 XO(
2619"Automated Recording Level Adjustment stopped. The total number of analyses has been exceeded without finding an acceptable volume. Still too high.") );
2620 else if (mAILAMax < mAILAGoalPoint - mAILAGoalDelta)
2621 ProjectStatus::Get( *proj ).Set(
2622 XO(
2623"Automated Recording Level Adjustment stopped. The total number of analyses has been exceeded without finding an acceptable volume. Still too low.") );
2624 else {
2625 auto msg = XO(
2626"Automated Recording Level Adjustment stopped. %.2f seems an acceptable volume.")
2627 .Format( Px_GetInputVolume(mPortMixer) );
2628 ProjectStatus::Get( *proj ).Set(msg);
2629 }
2630 }
2631 }
2632}
2633#endif
2634
2636 sampleFormat inputFormat,
2637 unsigned inputChannels,
2638 float *outputBuffer,
2639 unsigned long len)
2640{
2641 for (unsigned int i=0; i < inputChannels; i++) {
2642 auto inputPtr = inputBuffer + (i * SAMPLE_SIZE(inputFormat));
2643
2644 SamplesToFloats(inputPtr, inputFormat,
2645 outputBuffer + i, len, inputChannels, 2);
2646 }
2647
2648 // One mono input channel goes to both output channels...
2649 if (inputChannels == 1)
2650 for (int i=0; i < len; i++)
2651 outputBuffer[2*i + 1] = outputBuffer[2*i];
2652}
2653
2654int audacityAudioCallback(const void *inputBuffer, void *outputBuffer,
2655 unsigned long framesPerBuffer,
2656 const PaStreamCallbackTimeInfo *timeInfo,
2657 const PaStreamCallbackFlags statusFlags, void *userData )
2658{
2659 auto gAudioIO = AudioIO::Get();
2660 return gAudioIO->AudioCallback(
2661 static_cast<constSamplePtr>(inputBuffer),
2662 static_cast<float*>(outputBuffer), framesPerBuffer,
2663 timeInfo, statusFlags, userData);
2664}
2665
2666// Stop recording if 'silence' is detected
2667// Start recording if sound detected.
2668//
2669// By using CallAfter(), we can schedule the call to the toolbar
2670// to run in the main GUI thread after the next event loop iteration.
2671// That's important, because Pause() updates GUI, such as status bar,
2672// and that should NOT happen in this audio non-gui thread.
2674 float *inputSamples,
2675 unsigned long framesPerBuffer
2676 )
2677{
2678 // Quick returns if next to nothing to do.
2679 if( !mPauseRec )
2680 return;
2681
2682 float maxPeak = 0.;
2683 for( unsigned long i = 0, cnt = framesPerBuffer * mNumCaptureChannels; i < cnt; ++i ) {
2684 float sample = fabs(*(inputSamples++));
2685 if (sample > maxPeak) {
2686 maxPeak = sample;
2687 }
2688 }
2689
2690 bool bShouldBePaused = maxPeak < mSilenceLevel;
2691 if( bShouldBePaused != IsPaused() )
2692 {
2693 auto pListener = GetListener();
2694 if ( pListener )
2695 pListener->OnSoundActivationThreshold();
2696 }
2697}
2698
2699// Limit values to -1.0..+1.0
2700void ClampBuffer(float * pBuffer, unsigned long len){
2701 for(unsigned i = 0; i < len; i++)
2702 pBuffer[i] = std::clamp(pBuffer[i], -1.0f, 1.0f);
2703};
2704
2705
2706// return true, IFF we have fully handled the callback.
2707//
2708// Mix and copy to PortAudio's output buffer
2709// from our intermediate playback buffers
2710//
2712 float *outputFloats,
2713 unsigned long framesPerBuffer,
2714 float *outputMeterFloats
2715)
2716{
2717 const auto numPlaybackSequences = mPlaybackSequences.size();
2718 const auto numPlaybackChannels = mNumPlaybackChannels;
2719
2720 mMaxFramesOutput = 0;
2721
2722 // Quick returns if next to nothing to do.
2723 if (mStreamToken <= 0 ||
2724 !outputFloats ||
2725 numPlaybackChannels <= 0) {
2726 // So that UpdateTimePosition() will be correct, in case of MIDI play with
2727 // no audio output channels
2728 mMaxFramesOutput = framesPerBuffer;
2729 return false;
2730 }
2731
2733 mSeek = 0.0;
2734
2735 if (mSeek){
2737 return true;
2738 }
2739
2740 // Choose a common size to take from all ring buffers
2741 const auto toGet =
2742 std::min<size_t>(framesPerBuffer, GetCommonlyReadyPlayback());
2743
2744 // Poke: If there are no playback sequences, then check playback
2745 // completion condition and do early return
2746 // PRL: Also consume frbom the single playback ring buffer
2747 if (numPlaybackSequences == 0) {
2748 mMaxFramesOutput = mPlaybackBuffers[0]->Discard(toGet);
2750 mLastPlaybackTimeMillis = ::wxGetUTCTimeMillis();
2751 return false;
2752 }
2753
2754 // JKC: The original code attempted to be faster by doing nothing on silenced audio.
2755 // This, IMHO, is 'premature optimisation'. Instead clearer and cleaner code would
2756 // simply use a gain of 0.0 for silent audio and go on through to the stage of
2757 // applying that 0.0 gain to the data mixed into the buffer.
2758 // Then (and only then) we would have if needed fast paths for:
2759 // - Applying a uniform gain of 0.0.
2760 // - Applying a uniform gain of 1.0.
2761 // - Applying some other uniform gain.
2762 // - Applying a linearly interpolated gain.
2763 // I would expect us not to need the fast paths, since linearly interpolated gain
2764 // is very cheap to process.
2765
2766 // ------ MEMORY ALLOCATION ----------------------
2767 // These are small structures.
2768 const auto tempBufs = stackAllocate(float *, numPlaybackChannels);
2769
2770 // And these are larger structures....
2771 for (unsigned int c = 0; c < numPlaybackChannels; c++)
2772 tempBufs[c] = stackAllocate(float, framesPerBuffer);
2773 // ------ End of MEMORY ALLOCATION ---------------
2774
2775 auto gain = ExpGain(GetMixerOutputVol());
2776 if (mForceFadeOut.load(std::memory_order_relaxed) || IsPaused())
2777 gain = 0.0;
2778
2779 for(unsigned n = 0; n < numPlaybackChannels; ++n)
2780 {
2781 decltype(framesPerBuffer) len = mPlaybackBuffers[n]->Get(
2782 reinterpret_cast<samplePtr>(tempBufs[n]),
2784 toGet
2785 );
2786 if(len < framesPerBuffer)
2787 {
2788 // This used to happen normally at the end of non-looping
2789 // plays, but it can also be an anomalous case where the
2790 // supply from SequenceBufferExchange fails to keep up with the
2791 // real-time demand in this thread (see bug 1932). We
2792 // must supply something to the sound card, so pad it with
2793 // zeroes and not random garbage.
2794 memset((void*)&tempBufs[n][len], 0,
2795 (framesPerBuffer - len) * sizeof(float));
2796 }
2797
2798 // PRL: More recent rewrites of SequenceBufferExchange should guarantee a
2799 // padding out of the ring buffers so that equal lengths are
2800 // available, so maxLen ought to increase from 0 only once
2801 mMaxFramesOutput = std::max(mMaxFramesOutput, len);
2802
2803 len = mMaxFramesOutput;
2804
2805 // Realtime effect transformation of the sound used to happen here
2806 // but it is now done already on the producer side of the RingBuffer
2807
2808 // Mix the results with the existing output (software playthrough) and
2809 // apply panning. If post panning effects are desired, the panning would
2810 // need to be be split out from the mixing and applied in a separate step.
2811
2812 // Our channels aren't silent. We need to pass their data on.
2813 //
2814 // Each channel in the sequences can output to more than one channel on
2815 // the device. For example mono channels output to both left and right
2816 // output channels.
2817 if (len > 0)
2818 {
2819 // Output volume emulation: possibly copy meter samples, then
2820 // apply volume, then copy to the output buffer
2821 if(outputMeterFloats != outputFloats)
2822 {
2823 for ( unsigned i = 0; i < len; ++i)
2824 outputMeterFloats[numPlaybackChannels*i+n] +=
2825 gain*tempBufs[n][i];
2826 }
2827
2828 auto oldGain = mOldPlaybackGain;
2829 // if no microfades, jump in volume.
2830 if (!mbMicroFades)
2831 oldGain = gain;
2832
2833 // Linear interpolate.
2834 // PRL todo: choose denominator differently, so it doesn't depend on
2835 // framesPerBuffer, which is influenced by the portAudio implementation in
2836 // opaque ways
2837 const float deltaGain = (gain - oldGain) / len;
2838 for (unsigned i = 0; i < len; i++)
2839 {
2840 outputFloats[numPlaybackChannels * i + n] +=
2841 (oldGain + deltaGain * i) * tempBufs[n][i];
2842 }
2843 }
2845 }
2846
2847 mOldPlaybackGain = gain;
2848
2849 // wxASSERT( maxLen == toGet );
2850
2851 mLastPlaybackTimeMillis = ::wxGetUTCTimeMillis();
2852
2853 ClampBuffer( outputFloats, framesPerBuffer*numPlaybackChannels );
2854 if (outputMeterFloats != outputFloats)
2855 ClampBuffer( outputMeterFloats, framesPerBuffer*numPlaybackChannels );
2856
2857 return false;
2858}
2859
2860void AudioIoCallback::UpdateTimePosition(unsigned long framesPerBuffer)
2861{
2862 // Quick returns if next to nothing to do.
2863 if (mStreamToken <= 0)
2864 return;
2865
2866 // Update the position seen by drawing code
2869}
2870
2871// return true, IFF we have fully handled the callback.
2872//
2873// Copy from PortAudio input buffers to our intermediate recording buffers.
2874//
2876 constSamplePtr inputBuffer,
2877 unsigned long framesPerBuffer,
2878 const PaStreamCallbackFlags statusFlags,
2879 float * tempFloats
2880)
2881{
2882 const auto numPlaybackChannels = mNumPlaybackChannels;
2883 const auto numCaptureChannels = mNumCaptureChannels;
2884
2885 // Quick returns if next to nothing to do.
2886 if (mStreamToken <= 0)
2887 return;
2888 if( !inputBuffer )
2889 return;
2890 if( numCaptureChannels <= 0 )
2891 return;
2892
2893 // If there are no playback sequences, and we are recording, then the
2894 // earlier checks for being past the end won't happen, so do it here.
2896 mCallbackReturn = paComplete;
2897 }
2898
2899 // The error likely from a too-busy CPU falling behind real-time data
2900 // is paInputOverflow
2901 bool inputError =
2902 (statusFlags & (paInputOverflow))
2903 && !(statusFlags & paPrimingOutput);
2904
2905 // But it seems it's easy to get false positives, at least on Mac
2906 // So we have not decided to enable this extra detection yet in
2907 // production
2908
2909 size_t len = framesPerBuffer;
2910 for(unsigned t = 0; t < numCaptureChannels; t++)
2911 len = std::min( len, mCaptureBuffers[t]->AvailForPut() );
2912
2913 if (mSimulateRecordingErrors && 100LL * rand() < RAND_MAX)
2914 // Make spurious errors for purposes of testing the error
2915 // reporting
2916 len = 0;
2917
2918 // A different symptom is that len < framesPerBuffer because
2919 // the other thread, executing SequenceBufferExchange, isn't consuming fast
2920 // enough from mCaptureBuffers; maybe it's CPU-bound, or maybe the
2921 // storage device it writes is too slow
2922 if (mDetectDropouts &&
2923 ((mDetectUpstreamDropouts.load(std::memory_order_relaxed)
2924 && inputError) ||
2925 len < framesPerBuffer) ) {
2926 // Assume that any good partial buffer should be written leftmost
2927 // and zeroes will be padded after; label the zeroes.
2928 auto start = mPlaybackSchedule.GetSequenceTime() +
2930 auto duration = (framesPerBuffer - len) / mRate;
2931 auto pLast = mLostCaptureIntervals.empty()
2932 ? nullptr : &mLostCaptureIntervals.back();
2933 if (pLast &&
2934 fabs(pLast->first + pLast->second - start) < 0.5/mRate)
2935 // Make one bigger interval, not two butting intervals
2936 pLast->second = start + duration - pLast->first;
2937 else
2938 mLostCaptureIntervals.emplace_back( start, duration );
2939 }
2940
2941 if (len < framesPerBuffer)
2942 {
2943 mLostSamples += (framesPerBuffer - len);
2944 wxPrintf(wxT("lost %d samples\n"), (int)(framesPerBuffer - len));
2945 }
2946
2947 if (len <= 0)
2948 return;
2949
2950 // We have an ASSERT in the AudioIO constructor to alert us to
2951 // possible issues with the (short*) cast. We'd have a problem if
2952 // sizeof(short) > sizeof(float) since our buffers are sized for floats.
2953 for(unsigned t = 0; t < numCaptureChannels; t++) {
2954
2955 // dmazzoni:
2956 // Un-interleave. Ugly special-case code required because the
2957 // capture channels could be in three different sample formats;
2958 // it'd be nice to be able to call CopySamples, but it can't
2959 // handle multiplying by the gain and then clipping. Bummer.
2960
2961 switch(mCaptureFormat) {
2962 case floatSample: {
2963 auto inputFloats = (const float *)inputBuffer;
2964 for(unsigned i = 0; i < len; i++)
2965 tempFloats[i] =
2966 inputFloats[numCaptureChannels*i+t];
2967 } break;
2968 case int24Sample:
2969 // We should never get here. Audacity's int24Sample format
2970 // is different from PortAudio's sample format and so we
2971 // make PortAudio return float samples when recording in
2972 // 24-bit samples.
2973 wxASSERT(false);
2974 break;
2975 case int16Sample: {
2976 auto inputShorts = (const short *)inputBuffer;
2977 short *tempShorts = (short *)tempFloats;
2978 for( unsigned i = 0; i < len; i++) {
2979 float tmp = inputShorts[numCaptureChannels*i+t];
2980 tmp = std::clamp(tmp, -32768.0f, 32767.0f);
2981 tempShorts[i] = (short)(tmp);
2982 }
2983 } break;
2984 } // switch
2985
2986 // JKC: mCaptureFormat must be for samples with sizeof(float) or
2987 // fewer bytes (because tempFloats is sized for floats). All
2988 // formats are 2 or 4 bytes, so we are OK.
2989 const auto put =
2990 mCaptureBuffers[t]->Put(
2991 (samplePtr)tempFloats, mCaptureFormat, len);
2992 // wxASSERT(put == len);
2993 // but we can't assert in this thread
2994 wxUnusedVar(put);
2995 mCaptureBuffers[t]->Flush();
2996 }
2997}
2998
2999
3000#if 0
3001// Record the reported latency from PortAudio.
3002// TODO: Don't recalculate this with every callback?
3003// 01/21/2009: Disabled until a better solution presents itself.
3004void OldCodeToCalculateLatency()
3005{
3006 // As of 06/17/2006, portaudio v19 returns inputBufferAdcTime set to
3007 // zero. It is being worked on, but for now we just can't do much
3008 // but follow the leader.
3009 //
3010 // 08/27/2006: too inconsistent for now...just leave it a zero.
3011 //
3012 // 04/16/2008: Looks like si->inputLatency comes back with something useful though.
3013 // This rearranged logic uses si->inputLatency, but if PortAudio fixes inputBufferAdcTime,
3014 // this code won't have to be modified to use it.
3015 // Also avoids setting mLastRecordingOffset except when simultaneously playing and recording.
3016 //
3017 if (numCaptureChannels > 0 && numPlaybackChannels > 0) // simultaneously playing and recording
3018 {
3019 if (timeInfo->inputBufferAdcTime > 0)
3020 mLastRecordingOffset = timeInfo->inputBufferAdcTime - timeInfo->outputBufferDacTime;
3021 else if (mLastRecordingOffset == 0.0)
3022 {
3023 const PaStreamInfo* si = Pa_GetStreamInfo( mPortStreamV19 );
3024 mLastRecordingOffset = -si->inputLatency;
3025 }
3026 }
3027}
3028#endif
3029
3030
3031// return true, IFF we have fully handled the callback.
3032// Prime the output buffer with 0's, optionally adding in the playthrough.
3034 constSamplePtr inputBuffer,
3035 float *outputBuffer,
3036 unsigned long framesPerBuffer,
3037 float *outputMeterFloats
3038 )
3039{
3040 const auto numCaptureChannels = mNumCaptureChannels;
3041 const auto numPlaybackChannels = mNumPlaybackChannels;
3042
3043 // Quick returns if next to nothing to do.
3044 if( !outputBuffer )
3045 return;
3046 if( numPlaybackChannels <= 0 )
3047 return;
3048
3049 float *outputFloats = outputBuffer;
3050 for(unsigned i = 0; i < framesPerBuffer*numPlaybackChannels; i++)
3051 outputFloats[i] = 0.0;
3052
3053 if (inputBuffer && mSoftwarePlaythrough) {
3055 numCaptureChannels,
3056 outputBuffer, framesPerBuffer);
3057 }
3058
3059 // Copy the results to outputMeterFloats if necessary
3060 if (outputMeterFloats != outputFloats) {
3061 for (unsigned i = 0; i < framesPerBuffer*numPlaybackChannels; ++i) {
3062 outputMeterFloats[i] = outputFloats[i];
3063 }
3064 }
3065}
3066
3067/* Send data to recording VU meter if applicable */
3068// Also computes rms
3070 const float *inputSamples,
3071 unsigned long framesPerBuffer
3072 )
3073{
3074 const auto numCaptureChannels = mNumCaptureChannels;
3075 auto pInputMeter = mInputMeter.lock();
3076 if ( !pInputMeter )
3077 return;
3078 if( pInputMeter->IsMeterDisabled())
3079 return;
3080 pInputMeter->UpdateDisplay(
3081 numCaptureChannels, framesPerBuffer, inputSamples);
3082}
3083
3084/* Send data to playback VU meter if applicable */
3086 const float *outputMeterFloats,
3087 unsigned long framesPerBuffer)
3088{
3089 const auto numPlaybackChannels = mNumPlaybackChannels;
3090
3091 auto pOutputMeter = mOutputMeter.lock();
3092 if (!pOutputMeter)
3093 return;
3094 if( pOutputMeter->IsMeterDisabled() )
3095 return;
3096 if( !outputMeterFloats)
3097 return;
3098 pOutputMeter->UpdateDisplay(
3099 numPlaybackChannels, framesPerBuffer, outputMeterFloats);
3100
3101 //v Vaughan, 2011-02-25: Moved this update back to TrackPanel::OnTimer()
3102 // as it helps with playback issues reported by Bill and noted on Bug 258.
3103 // The problem there occurs if Software Playthrough is on.
3104 // Could conditionally do the update here if Software Playthrough is off,
3105 // and in TrackPanel::OnTimer() if Software Playthrough is on, but not now.
3106 // PRL 12 Jul 2015: and what was in TrackPanel::OnTimer is now handled by means of track panel timer events
3107 //MixerBoard* pMixerBoard = mOwningProject->GetMixerBoard();
3108 //if (pMixerBoard)
3109 // pMixerBoard->UpdateMeters(GetStreamTime(),
3110 // (pProj->GetControlToolBar()->GetLastPlayMode() == loopedPlay));
3111}
3112
3114 const auto numPlaybackSequences = mPlaybackSequences.size();
3115
3116 // MOVE_TO: CountSoloingSequences() function
3117 unsigned numSolo = 0;
3118 for (unsigned t = 0; t < numPlaybackSequences; t++ )
3119 if (mPlaybackSequences[t]->GetSolo())
3120 numSolo++;
3121 auto range = Extensions();
3122 numSolo += std::accumulate(range.begin(), range.end(), 0,
3123 [](unsigned sum, auto &ext){
3124 return sum + ext.CountOtherSolo(); });
3125 return numSolo;
3126}
3127
3128// TODO: Consider making the two sequence status functions into member
3129// functions of sequence objects
3130
3131// true IFF the sequence should be silent.
3132// The sequence may not yet be silent, since it may still be
3133// fading out.
3135{
3136 return !ps.GetSolo() && (
3137 // Cut if somebody else is soloing
3139 // Cut if we're muted (and not soloing)
3140 ps.GetMute()
3141 );
3142}
3143
3145{
3146 auto &factories = AudioIOExt::GetFactories();
3147 for (auto &factory: factories)
3148 if (auto pExt = factory(mPlaybackSchedule))
3149 mAudioIOExt.push_back( move(pExt) );
3150}
3151
3152
3154{
3155}
3156
3157
3159 constSamplePtr inputBuffer, float *outputBuffer,
3160 unsigned long framesPerBuffer,
3161 const PaStreamCallbackTimeInfo *timeInfo,
3162 const PaStreamCallbackFlags statusFlags, void * WXUNUSED(userData) )
3163{
3164 // Poll sequences for change of state.
3165 // (User might click mute and solo buttons.)
3167 mCallbackReturn = paContinue;
3168
3169 if (IsPaused()
3170 // PRL: Why was this added? Was it only because of the mysterious
3171 // initial leading zeroes, now solved by setting mStreamToken early?
3172 // JKC: I think it's used for the MIDI time cursor. See comments
3173 // at head of file about AudioTime().
3174 || mStreamToken <= 0
3175 )
3176 mNumPauseFrames += framesPerBuffer;
3177
3178 for( auto &ext : Extensions() ) {
3179 ext.ComputeOtherTimings(mRate, IsPaused(),
3180 timeInfo,
3181 framesPerBuffer);
3182 ext.FillOtherBuffers(
3184 }
3185
3186 // ------ MEMORY ALLOCATIONS -----------------------------------------------
3187 // tempFloats will be a reusable scratch pad for (possibly format converted)
3188 // audio data. One temporary use is for the InputMeter data.
3189 const auto numPlaybackChannels = mNumPlaybackChannels;
3190 const auto numCaptureChannels = mNumCaptureChannels;
3191 const auto tempFloats = stackAllocate(float,
3192 framesPerBuffer * std::max(numCaptureChannels, numPlaybackChannels));
3193
3194 bool bVolEmulationActive =
3195 (outputBuffer && GetMixerOutputVol() != 1.0);
3196 // outputMeterFloats is the scratch pad for the output meter.
3197 // we can often reuse the existing outputBuffer and save on allocating
3198 // something new.
3199 const auto outputMeterFloats = bVolEmulationActive
3200 ? stackAllocate(float, framesPerBuffer * numPlaybackChannels)
3201 : outputBuffer;
3202 // ----- END of MEMORY ALLOCATIONS ------------------------------------------
3203
3204 if (inputBuffer && numCaptureChannels) {
3205 float *inputSamples;
3206
3207 if (mCaptureFormat == floatSample) {
3208 inputSamples = (float *) inputBuffer;
3209 }
3210 else {
3211 SamplesToFloats(reinterpret_cast<constSamplePtr>(inputBuffer),
3212 mCaptureFormat, tempFloats, framesPerBuffer * numCaptureChannels);
3213 inputSamples = tempFloats;
3214 }
3215
3217 inputSamples,
3218 framesPerBuffer);
3219
3220 // This function may queue up a pause or resume.
3221 // TODO this is a bit dodgy as it toggles the Pause, and
3222 // relies on an idle event to have handled that, so could
3223 // queue up multiple toggle requests and so do nothing.
3224 // Eventually it will sort itself out by random luck, but
3225 // the net effect is a delay in starting/stopping sound activated
3226 // recording.
3228 inputSamples,
3229 framesPerBuffer);
3230 }
3231
3232 // Even when paused, we do playthrough.
3233 // Initialise output buffer to zero or to playthrough data.
3234 // Initialise output meter values.
3236 inputBuffer,
3237 outputBuffer,
3238 framesPerBuffer,
3239 outputMeterFloats);
3240
3241 // Test for no sequence audio to play (because we are paused and have faded
3242 // out)
3243 if( IsPaused() && (( !mbMicroFades ) || mOldPlaybackGain == 0.0f ))
3244 return mCallbackReturn;
3245
3246 // To add sequence output to output (to play sound on speaker)
3247 // possible exit, if we were seeking.
3249 outputBuffer,
3250 framesPerBuffer,
3251 outputMeterFloats))
3252 return mCallbackReturn;
3253
3254 // To move the cursor onwards. (uses mMaxFramesOutput)
3255 UpdateTimePosition(framesPerBuffer);
3256
3257 // To capture input into sequence (sound from microphone)
3259 inputBuffer,
3260 framesPerBuffer,
3261 statusFlags,
3262 tempFloats);
3263
3264 SendVuOutputMeterData( outputMeterFloats, framesPerBuffer);
3265
3266 return mCallbackReturn;
3267}
3268
3270{
3271 const int token = mStreamToken;
3272 wxMutexLocker locker(mSuspendAudioThread);
3273 if (token != mStreamToken)
3274 // This stream got destroyed while we waited for it
3275 return paAbort;
3276
3277 // Pause audio thread and wait for it to finish
3278 //
3279 // [PM] the following 8 lines of code could be probably replaced by
3280 // a single call to StopAudioThreadAndWait()
3281 //
3282 // CAUTION: when trying the above, you must also replace the setting of the
3283 // atomic before the return, with a call to StartAudioThread()
3284 //
3285 // If that works, then we can remove mAudioThreadSequenceBufferExchangeLoopActive,
3286 // as it will become unused; consequently, the AudioThread loop would get simpler too.
3287 //
3289 .store(false, std::memory_order_relaxed);
3290
3292 .load(std::memory_order_relaxed ) )
3293 {
3294 using namespace std::chrono;
3295 std::this_thread::sleep_for(50ms);
3296 }
3297
3298 // Calculate the NEW time position, in the PortAudio callback
3299 const auto time =
3301
3303 mSeek = 0.0;
3304
3305
3306 // Reset mixer positions and flush buffers for all sequences
3307 for (auto &mixer : mPlaybackMixers)
3308 mixer->Reposition( time, true );
3309 for (auto &buffer : mPlaybackBuffers) {
3310 const auto toDiscard = buffer->AvailForGet();
3311 const auto discarded = buffer->Discard( toDiscard );
3312 // wxASSERT( discarded == toDiscard );
3313 // but we can't assert in this thread
3314 wxUnusedVar(discarded);
3315 }
3316
3318
3319 // Reload the ring buffers
3321
3322 // Reenable the audio thread
3324 .store(true, std::memory_order_relaxed);
3325
3326 return paContinue;
3327}
3328
3330 int &callbackReturn, unsigned long len)
3331{
3332 if (IsPaused())
3333 return;
3334
3335 bool done =
3337 if (!done)
3338 return;
3339
3340 for( auto &ext : Extensions() )
3341 ext.SignalOtherCompletion();
3342 callbackReturn = paComplete;
3343}
3344
3346{
3347 // Down-cast and dereference are safe because only AudioIOCallback
3348 // populates the array
3349 return *static_cast<AudioIOExt*>(mIterator->get());
3350}
3351
3352
3354{
3355 mAudioThreadSequenceBufferExchangeLoopRunning.store(true, std::memory_order_release);
3356}
3357
3359{
3360 while (mAudioThreadAcknowledge.load(std::memory_order_acquire) != Acknowledge::eStart)
3361 {
3362 using namespace std::chrono;
3363 std::this_thread::sleep_for(50ms);
3364 }
3365 mAudioThreadAcknowledge.store(Acknowledge::eNone, std::memory_order_release);
3366}
3367
3369{
3370 mAudioThreadSequenceBufferExchangeLoopRunning.store(false, std::memory_order_release);
3371}
3372
3374{
3375 while (mAudioThreadAcknowledge.load(std::memory_order_acquire) != Acknowledge::eStop)
3376 {
3377 using namespace std::chrono;
3378 std::this_thread::sleep_for(50ms);
3379 }
3380 mAudioThreadAcknowledge.store(Acknowledge::eNone, std::memory_order_release);
3381}
3382
3383void AudioIoCallback::ProcessOnceAndWait(std::chrono::milliseconds sleepTime)
3384{
3386 .store(true, std::memory_order_release);
3387
3389 .load(std::memory_order_acquire))
3390 {
3391 using namespace std::chrono;
3392 std::this_thread::sleep_for(sleepTime);
3393 }
3394}
3395
3396
3397
3399{
3400 // Includes a test of mTime, used in the main thread
3401 return IsStreamActive() &&
3402 GetNumCaptureChannels() > 0 &&
3405}
3406
3407BoolSetting SoundActivatedRecord{ "/AudioIO/SoundActivatedRecord", false };
wxT("CloseDown"))
void DefaultDelayedHandlerAction(AudacityException *pException)
A default template parameter for GuardedCall.
R GuardedCall(const F1 &body, const F2 &handler=F2::Default(), F3 delayedHandler=DefaultDelayedHandlerAction) noexcept(noexcept(handler(std::declval< AudacityException * >())) &&noexcept(handler(nullptr)) &&noexcept(std::function< void(AudacityException *)>{std::move(delayedHandler)}))
Execute some code on any thread; catch any AudacityException; enqueue error report on the main thread...
int audacityAudioCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
Definition: AudioIO.cpp:2654
static PaSampleFormat AudacityToPortAudioSampleFormat(sampleFormat format)
Definition: AudioIO.cpp:460
BoolSetting SoundActivatedRecord
Definition: AudioIO.cpp:3407
static void DoSoftwarePlaythrough(constSamplePtr inputBuffer, sampleFormat inputFormat, unsigned inputChannels, float *outputBuffer, unsigned long len)
Definition: AudioIO.cpp:2635
void ClampBuffer(float *pBuffer, unsigned long len)
Definition: AudioIO.cpp:2700
#define stackAllocate(T, count)
Definition: AudioIO.cpp:1990
int PaError
Definition: AudioIO.h:45
unsigned long PaStreamCallbackFlags
Definition: AudioIO.h:43
DoubleSetting AudioIOLatencyCorrection
DoubleSetting AudioIOPlaybackVolume
StringSetting AudioIOPlaybackDevice
DoubleSetting AudioIOLatencyDuration
StringSetting AudioIORecordingDevice
StringSetting AudioIOHost
IntSetting AudioIORecordChannels
#define BAD_STREAM_TIME
Definition: AudioIOBase.h:38
Abstract base class for hooks into audio playback procedures.
std::vector< std::shared_ptr< const PlayableSequence > > ConstPlayableSequences
static RegisteredToolbarFactory factory
Toolkit-neutral facade for basic user interface services.
Abstract class ChannelGroup with two discrete iterable dimensions, channels and intervals; subclasses...
wxString PluginID
int min(int a, int b)
IntSetting DecibelScaleCutoff
Negation of this value is the lowest dB level that should be shown in dB scales.
Definition: Decibels.cpp:12
XO("Cut/Copy/Paste")
Type ExpGain(Type gain) noexcept
Definition: Gain.h:19
#define LAT1CTOWX(X)
Definition: Internat.h:158
#define _(s)
Definition: Internat.h:73
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
Definition: IteratorX.h:210
#define safenew
Definition: MemoryX.h:10
#define DB_TO_LINEAR(x)
Definition: MemoryX.h:338
constexpr size_t TimeQueueGrainSize
audacity::BasicSettings * gPrefs
Definition: Prefs.cpp:68
wxString WarningDialogKey(const wxString &internalDialogName)
Definition: Prefs.cpp:510
std::unique_ptr< const BasicUI::WindowPlacement > ProjectFramePlacement(AudacityProject *project)
Make a WindowPlacement object suitable for project (which may be null)
Definition: Project.cpp:129
void ClearSamples(samplePtr dst, sampleFormat format, size_t start, size_t len)
void SamplesToFloats(constSamplePtr src, sampleFormat srcFormat, float *dst, size_t len, size_t srcStride, size_t dstStride)
Copy samples from any format into the widest format, which is 32 bit float, with no dithering.
constexpr sampleFormat int16Sample
Definition: SampleFormat.h:43
constexpr sampleFormat floatSample
Definition: SampleFormat.h:45
constexpr sampleFormat int24Sample
Definition: SampleFormat.h:44
sampleFormat
The ordering of these values with operator < agrees with the order of increasing bit width.
Definition: SampleFormat.h:30
@ narrowestSampleFormat
Two synonyms for previous values that might change if more values were added.
char * samplePtr
Definition: SampleFormat.h:57
#define SAMPLE_SIZE(SampleFormat)
Definition: SampleFormat.h:52
const char * constSamplePtr
Definition: SampleFormat.h:58
const auto project
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
std::chrono::system_clock Clock
Base class for exceptions specially processed by the application.
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
std::weak_ptr< Meter > mOutputMeter
Definition: AudioIOBase.h:260
PaStream * mPortStreamV19
Definition: AudioIOBase.h:257
static wxString HostName(const PaDeviceInfo *info)
Definition: AudioIOBase.cpp:83
std::atomic< bool > mPaused
True if audio playback is paused.
Definition: AudioIOBase.h:248
double mRate
Audio playback rate in samples per second.
Definition: AudioIOBase.h:255
static std::vector< long > GetSupportedCaptureRates(int devIndex=-1, double rate=0.0)
Get a list of sample rates the input (recording) device supports.
bool IsMonitoring() const
Returns true if we're monitoring input (but not recording or playing actual audio)
static std::vector< long > GetSupportedPlaybackRates(int DevIndex=-1, double rate=0.0)
Get a list of sample rates the output (playback) device supports.
static std::unique_ptr< AudioIOBase > ugAudioIO
Definition: AudioIOBase.h:241
static double mCachedBestRateIn
Definition: AudioIOBase.h:282
void SetCaptureMeter(const std::shared_ptr< AudacityProject > &project, const std::weak_ptr< Meter > &meter)
static int getPlayDevIndex(const wxString &devName={})
get the index of the device selected in the preferences.
static AudioIOBase * Get()
Definition: AudioIOBase.cpp:94
bool IsStreamActive() const
Returns true if the audio i/o is running at all, but not during cleanup.
bool IsBusy() const
Returns true if audio i/o is busy starting, stopping, playing, or recording.
void HandleDeviceChange()
update state after changing what audio devices are selected
void SetMixer(int inputSource)
static wxString DeviceName(const PaDeviceInfo *info)
Definition: AudioIOBase.cpp:76
int mStreamToken
Definition: AudioIOBase.h:251
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.
std::weak_ptr< AudacityProject > mOwningProject
Definition: AudioIOBase.h:245
bool mInputMixerWorks
Can we control the hardware input level?
Definition: AudioIOBase.h:274
bool IsPaused() const
Find out if playback / recording is currently paused.
std::weak_ptr< Meter > mInputMeter
Definition: AudioIOBase.h:259
static int getRecordDevIndex(const wxString &devName={})
get the index of the supplied (named) recording device, or the device selected in the preferences if ...
static Factories & GetFactories()
Definition: AudioIOExt.cpp:15
AudioIO uses the PortAudio library to play and record sound.
Definition: AudioIO.h:415
std::shared_ptr< AudacityProject > GetOwningProject() const
Definition: AudioIO.h:493
bool mDelayingActions
Definition: AudioIO.h:653
void StopStream() override
Stop recording, playback or input monitoring.
Definition: AudioIO.cpp:1428
void SetOwningProject(const std::shared_ptr< AudacityProject > &pProject)
Definition: AudioIO.cpp:759
bool IsCapturing() const
Definition: AudioIO.cpp:3398
bool InputMixerWorks()
Find out if the input hardware level control is available.
Definition: AudioIO.cpp:427
std::mutex mPostRecordingActionMutex
Definition: AudioIO.h:650
PostRecordingAction mPostRecordingAction
Definition: AudioIO.h:651
bool AllocateBuffers(const AudioIOStartStreamOptions &options, const TransportSequences &sequences, double t0, double t1, double sampleRate)
Allocate RingBuffer structures, and others, needed for playback and recording.
Definition: AudioIO.cpp:1166
void GetMixer(int *inputSource, float *inputVolume, float *playbackVolume)
Definition: AudioIO.cpp:400
static void Init()
Definition: AudioIO.cpp:190
int StartStream(const TransportSequences &sequences, double t0, double t1, double mixerLimit, const AudioIOStartStreamOptions &options)
Start recording or playing back audio.
Definition: AudioIO.cpp:825
void DrainRecordBuffers()
Second part of SequenceBufferExchange.
Definition: AudioIO.cpp:2250
static void Deinit()
Definition: AudioIO.cpp:218
static AudioIO * Get()
Definition: AudioIO.cpp:126
bool StartPortAudioStream(const AudioIOStartStreamOptions &options, unsigned int numPlaybackChannels, unsigned int numCaptureChannels)
Opens the portaudio stream(s) used to do playback or recording (or both) through.
Definition: AudioIO.cpp:473
double GetBestRate(bool capturing, bool playing, double sampleRate)
Return a valid sample rate that is supported by the current I/O device(s).
Definition: AudioIO.cpp:1709
void FillPlayBuffers()
First part of SequenceBufferExchange.
Definition: AudioIO.cpp:1912
AudioIO()
Definition: AudioIO.cpp:232
void DelayActions(bool recording)
Definition: AudioIO.cpp:1128
void SetMixer(int inputSource, float inputVolume, float playbackVolume)
Definition: AudioIO.cpp:380
bool ProcessPlaybackSlices(std::optional< RealtimeEffects::ProcessingScope > &pScope, size_t available)
Definition: AudioIO.cpp:1992
void RemoveState(AudacityProject &project, ChannelGroup *pGroup, std::shared_ptr< RealtimeEffectState > pState)
Forwards to RealtimeEffectManager::RemoveState with proper init scope.
Definition: AudioIO.cpp:369
~AudioIO()
Definition: AudioIO.cpp:314
void SetMeters()
Set the current VU meters - this should be done once after each call to StartStream currently.
Definition: AudioIO.cpp:1420
void CallAfterRecording(PostRecordingAction action)
Enqueue action for main thread idle time, not before the end of any recording in progress.
Definition: AudioIO.cpp:1138
bool DelayingActions() const
Definition: AudioIO.cpp:1133
bool IsAvailable(AudacityProject &project) const
Function to automatically set an acceptable volume.
Definition: AudioIO.cpp:1414
std::shared_ptr< RealtimeEffectState > AddState(AudacityProject &project, ChannelGroup *pGroup, const PluginID &id)
Forwards to RealtimeEffectManager::AddState with proper init scope.
Definition: AudioIO.cpp:347
void StartStreamCleanup(bool bOnlyBuffers=false)
Clean up after StartStream if it fails.
Definition: AudioIO.cpp:1391
wxArrayString GetInputSourceNames()
Get the list of inputs to the current mixer device.
Definition: AudioIO.cpp:432
static void AudioThread(std::atomic< bool > &finish)
Sits in a thread loop reading and writing audio.
Definition: AudioIO.cpp:1805
void StartMonitoring(const AudioIOStartStreamOptions &options)
Start up Portaudio for capture and recording as needed for input monitoring and software playthrough ...
Definition: AudioIO.cpp:775
size_t GetCommonlyFreePlayback()
Get the number of audio samples free in all of the playback buffers.
Definition: AudioIO.cpp:1880
void ResetOwningProject()
Definition: AudioIO.cpp:770
std::function< void()> PostRecordingAction
Definition: AudioIO.h:483
std::shared_ptr< RealtimeEffectState > ReplaceState(AudacityProject &project, ChannelGroup *pGroup, size_t index, const PluginID &id)
Forwards to RealtimeEffectManager::ReplaceState with proper init scope.
Definition: AudioIO.cpp:358
void SetPaused(bool state, bool publish=false)
Pause and un-pause playback and recording.
Definition: AudioIO.cpp:1691
void SequenceBufferExchange()
Definition: AudioIO.cpp:1906
static bool ValidateDeviceNames(const wxString &play, const wxString &rec)
Ensure selected device names are valid.
Definition: AudioIO.cpp:223
size_t GetCommonlyAvailCapture()
Get the number of audio samples ready in all of the recording buffers.
Definition: AudioIO.cpp:1898
double GetStreamTime()
During playback, the sequence time most recently played.
Definition: AudioIO.cpp:1787
wxString LastPaErrorString()
Definition: AudioIO.cpp:754
void StartThread()
Definition: AudioIO.cpp:309
std::vector< std::unique_ptr< AudioIOExtBase > >::const_iterator mIterator
Definition: AudioIO.h:153
auto operator*() const -> AudioIOExt &
Definition: AudioIO.cpp:3345
unsigned CountSoloingSequences()
Definition: AudioIO.cpp:3113
std::atomic< bool > mAudioThreadSequenceBufferExchangeLoopRunning
Definition: AudioIO.h:310
static int mNextStreamToken
Definition: AudioIO.h:278
std::shared_ptr< AudioIOListener > GetListener() const
Definition: AudioIO.h:170
size_t GetCommonlyWrittenForPlayback()
Definition: AudioIO.cpp:1893
size_t mNumPlaybackChannels
Definition: AudioIO.h:305
void CallbackCheckCompletion(int &callbackReturn, unsigned long len)
Definition: AudioIO.cpp:3329
bool mbMicroFades
Definition: AudioIO.h:282
double mSeek
Definition: AudioIO.h:284
std::unique_ptr< TransportState > mpTransportState
Holds some state for duration of playback or recording.
Definition: AudioIO.h:397
wxMutex mSuspendAudioThread
Definition: AudioIO.h:359
AudioIOExtRange Extensions()
Definition: AudioIO.h:162
std::atomic< bool > mAudioThreadShouldCallSequenceBufferExchangeOnce
Definition: AudioIO.h:309
std::vector< std::unique_ptr< Resample > > mResample
Definition: AudioIO.h:254
float GetMixerOutputVol()
Definition: AudioIO.h:339
int AudioCallback(constSamplePtr inputBuffer, float *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, const PaStreamCallbackFlags statusFlags, void *userData)
Definition: AudioIO.cpp:3158
void CheckSoundActivatedRecordingLevel(float *inputSamples, unsigned long framesPerBuffer)
Definition: AudioIO.cpp:2673
PlaybackSchedule mPlaybackSchedule
Definition: AudioIO.h:395
RecordingSchedule mRecordingSchedule
Definition: AudioIO.h:394
std::vector< float * > mScratchPointers
pointing into mScratchBuffers
Definition: AudioIO.h:273
std::atomic< Acknowledge > mAudioThreadAcknowledge
Definition: AudioIO.h:313
std::atomic< bool > mFinishAudioThread
Definition: AudioIO.h:252
void UpdateTimePosition(unsigned long framesPerBuffer)
Definition: AudioIO.cpp:2860
int mbHasSoloSequences
Definition: AudioIO.h:181
size_t mPlaybackSamplesToCopy
Preferred batch size for replenishing the playback RingBuffer.
Definition: AudioIO.h:289
static double mCachedBestRateOut
Definition: AudioIO.h:353
std::vector< std::unique_ptr< Mixer > > mPlaybackMixers
Definition: AudioIO.h:275
PlaybackPolicy::Duration mPlaybackRingBufferSecs
Definition: AudioIO.h:285
std::vector< std::vector< float > > mProcessingBuffers
Definition: AudioIO.h:261
std::thread mAudioThread
Definition: AudioIO.h:251
int mCallbackReturn
Definition: AudioIO.h:182
std::atomic< bool > mAudioThreadSequenceBufferExchangeLoopActive
Definition: AudioIO.h:311
static size_t MinValue(const RingBuffers &buffers, size_t(RingBuffer::*pmf)() const)
Definition: AudioIO.cpp:1871
void ClearRecordingException()
Definition: AudioIO.h:374
long mNumPauseFrames
How many frames of zeros were output due to pauses?
Definition: AudioIO.h:232
bool SequenceShouldBeSilent(const PlayableSequence &ps)
Definition: AudioIO.cpp:3134
void SetRecordingException()
Definition: AudioIO.h:372
std::atomic< bool > mForceFadeOut
Definition: AudioIO.h:327
void DrainInputBuffers(constSamplePtr inputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackFlags statusFlags, float *tempFloats)
Definition: AudioIO.cpp:2875
wxLongLong mLastPlaybackTimeMillis
Definition: AudioIO.h:329
void SendVuInputMeterData(const float *inputSamples, unsigned long framesPerBuffer)
Definition: AudioIO.cpp:3069
std::vector< std::unique_ptr< AudioIOExtBase > > mAudioIOExt
Definition: AudioIOBase.h:322
size_t mHardwarePlaybackLatencyFrames
Hardware output latency in frames.
Definition: AudioIO.h:291
void SendVuOutputMeterData(const float *outputMeterFloats, unsigned long framesPerBuffer)
Definition: AudioIO.cpp:3085
RingBuffers mCaptureBuffers
Definition: AudioIO.h:257
bool mDetectDropouts
Definition: AudioIO.h:379
void DoPlaythrough(constSamplePtr inputBuffer, float *outputBuffer, unsigned long framesPerBuffer, float *outputMeterFloats)
Definition: AudioIO.cpp:3033
void StopAudioThread()
Definition: AudioIO.cpp:3368
void WaitForAudioThreadStarted()
Definition: AudioIO.cpp:3358
bool mSimulateRecordingErrors
Definition: AudioIO.h:387
PaError mLastPaError
Definition: AudioIO.h:333
static bool mCachedBestRatePlaying
Definition: AudioIO.h:354
bool mSoftwarePlaythrough
Definition: AudioIO.h:297
RecordableSequences mCaptureSequences
Definition: AudioIO.h:258
void SetListener(const std::shared_ptr< AudioIOListener > &listener)
Definition: AudioIO.cpp:2456
RingBuffers mPlaybackBuffers
Definition: AudioIO.h:266
double mCaptureRate
Definition: AudioIO.h:307
float mOldPlaybackGain
Definition: AudioIO.h:270
std::vector< std::unique_ptr< RingBuffer > > RingBuffers
Definition: AudioIO.h:256
int CallbackDoSeek()
Definition: AudioIO.cpp:3269
unsigned long mMaxFramesOutput
Definition: AudioIO.h:280
ConstPlayableSequences mPlaybackSequences
Definition: AudioIO.h:267
double mLastRecordingOffset
Not (yet) used; should perhaps be atomic when it is.
Definition: AudioIO.h:332
void StartAudioThread()
Definition: AudioIO.cpp:3353
size_t GetCommonlyReadyPlayback()
Get the number of audio samples ready in all of the playback buffers.
Definition: AudioIO.cpp:1888
bool mUsingJack
Definition: AudioIO.h:350
std::atomic< bool > mDetectUpstreamDropouts
Definition: AudioIO.h:391
void ProcessOnceAndWait(std::chrono::milliseconds sleepTime=std::chrono::milliseconds(50))
Definition: AudioIO.cpp:3383
size_t mPlaybackQueueMinimum
Occupancy of the queue we try to maintain, with bigger batches if needed.
Definition: AudioIO.h:293
std::weak_ptr< AudioIOListener > mListener
Definition: AudioIO.h:347
wxAtomicInt mRecordingException
Definition: AudioIO.h:371
double mCaptureRingBufferSecs
Definition: AudioIO.h:286
float mSilenceLevel
Definition: AudioIO.h:301
size_t mNumCaptureChannels
Definition: AudioIO.h:303
void SetMixerOutputVol(float value)
Definition: AudioIO.h:341
std::vector< std::vector< float > > mMasterBuffers
Definition: AudioIO.h:264
bool FillOutputBuffers(float *outputFloats, unsigned long framesPerBuffer, float *outputMeterFloats)
Definition: AudioIO.cpp:2711
std::vector< std::pair< double, double > > mLostCaptureIntervals
Definition: AudioIO.h:377
void WaitForAudioThreadStopped()
Definition: AudioIO.cpp:3373
bool mPauseRec
True if Sound Activated Recording is enabled.
Definition: AudioIO.h:300
bool mUsingAlsa
Definition: AudioIO.h:349
double mFactor
Definition: AudioIO.h:279
double mMinCaptureSecsToCopy
Definition: AudioIO.h:295
unsigned long long mLostSamples
Definition: AudioIO.h:308
std::vector< SampleBuffer > mScratchBuffers
Definition: AudioIO.h:272
static bool mCachedBestRateCapturing
Definition: AudioIO.h:355
sampleFormat mCaptureFormat
Definition: AudioIO.h:306
This specialization of Setting for bool adds a Toggle method to negate the saved value.
Definition: Prefs.h:346
static DeviceManager * Instance()
Gets the singleton instance.
std::chrono::duration< float > GetTimeSinceRescan()
std::vector< Input > Inputs
Definition: Mix.h:47
CallbackReturn Publish(const AudioIOEvent &message)
Send a message to connected callbacks.
Definition: Observer.h:207
virtual BufferTimes SuggestedBufferTimes(PlaybackSchedule &schedule)
Provide hints for construction of playback RingBuffer objects.
virtual double OffsetSequenceTime(PlaybackSchedule &schedule, double offset)
Called when the play head needs to jump a certain distance.
virtual bool AllowSeek(PlaybackSchedule &schedule)
Whether repositioning commands are allowed during playback.
virtual void Finalize(PlaybackSchedule &schedule)
Called after stopping of an audio stream or an unsuccessful start.
virtual void Initialize(PlaybackSchedule &schedule, double rate)
Called before starting an audio stream.
virtual bool Done(PlaybackSchedule &schedule, unsigned long outputFrames)
Returns true if schedule.GetSequenceTime() has reached the end of playback.
std::chrono::duration< double > Duration
virtual std::chrono::milliseconds SleepInterval(PlaybackSchedule &schedule)
How long to wait between calls to AudioIO::SequenceBufferExchange.
void Producer(PlaybackSchedule &schedule, PlaybackSlice slice)
Enqueue track time value advanced by the slice according to schedule's PlaybackPolicy.
double Consumer(size_t nSamples, double rate)
Find the track time value nSamples after the last consumed sample.
void Prime(double time)
Empty the queue and reassign the last produced time.
static ProjectStatus & Get(AudacityProject &project)
void Set(const TranslatableString &msg, StatusBarField field=MainStatusBarField())
static RealtimeEffectManager & Get(AudacityProject &project)
static constexpr ChannelGroup * MasterGroup
void RemoveState(RealtimeEffects::InitializationScope *pScope, ChannelGroup *pGroup, std::shared_ptr< RealtimeEffectState > pState)
Main thread removes a global or per-group effect.
std::shared_ptr< RealtimeEffectState > ReplaceState(RealtimeEffects::InitializationScope *pScope, ChannelGroup *pGroup, size_t index, const PluginID &id)
Main thread replaces a global or per-group effect.
std::shared_ptr< RealtimeEffectState > AddState(RealtimeEffects::InitializationScope *pScope, ChannelGroup *pGroup, const PluginID &id)
Main thread appends a global or per-group effect.
Brackets processing setup and cleanup in the main thread.
Holds streamed audio samples.
Definition: RingBuffer.h:17
size_t WrittenForGet() const
Reader may concurrently cause a decrease of what this returns.
Definition: RingBuffer.cpp:73
size_t AvailForPut() const
Definition: RingBuffer.cpp:64
size_t AvailForGet() const
Definition: RingBuffer.cpp:226
SampleBuffer & Allocate(size_t count, sampleFormat format)
Definition: SampleFormat.h:151
samplePtr ptr() const
Definition: SampleFormat.h:165
bool Write(const T &value)
Write value to config and return true if successful.
Definition: Prefs.h:259
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:207
virtual bool Flush() noexcept=0
virtual bool Read(const wxString &key, bool *value) const =0
#define lrint(dbl)
Definition: float_cast.h:169
void CallAfter(Action action)
Schedule an action to be done later, and in the main thread.
Definition: BasicUI.cpp:214
void ShowErrorDialog(const WindowPlacement &placement, const TranslatableString &dlogTitle, const TranslatableString &message, const ManualPageID &helpPage, const ErrorDialogOptions &options={})
Show an error dialog with a link to the manual for further help.
Definition: BasicUI.h:272
MessageBoxResult ShowMessageBox(const TranslatableString &message, MessageBoxOptions options={})
Show a modal message box with either Ok or Yes and No, and optionally Cancel.
Definition: BasicUI.h:287
void Release(wxWindow *handler)
PROJECT_RATE_API sampleFormat SampleFormatChoice()
struct holding stream options, including a pointer to the time warp info and AudioIOListener and whet...
Definition: AudioIOBase.h:44
std::function< std::chrono::milliseconds() > playbackStreamPrimer
Definition: AudioIOBase.h:69
std::shared_ptr< AudacityProject > pProject
Definition: AudioIOBase.h:53
std::weak_ptr< Meter > captureMeter
Definition: AudioIOBase.h:54
std::weak_ptr< Meter > playbackMeter
Definition: AudioIOBase.h:54
PRCrossfadeData * pCrossfadeData
Definition: AudioIOBase.h:64
std::optional< double > pStartTime
Definition: AudioIOBase.h:58
std::shared_ptr< AudioIOListener > listener
Definition: AudioIOBase.h:56
TransportState(std::weak_ptr< AudacityProject > wOwningProject, const ConstPlayableSequences &playbackSequences, unsigned numPlaybackChannels, double sampleRate)
Definition: AudioIO.cpp:132
std::optional< RealtimeEffects::InitializationScope > mpRealtimeInitialization
Definition: AudioIO.cpp:157
Options for variations of error dialogs; the default is for modal dialogs.
Definition: BasicUI.h:52
MessageBoxOptions && Caption(TranslatableString caption_) &&
Definition: BasicUI.h:101
"finally" as in The C++ Programming Language, 4th ed., p. 358 Useful for defining ad-hoc RAII actions...
Definition: MemoryX.h:175
virtual bool GetSolo() const =0
May vary asynchronously.
virtual bool GetMute() const =0
May vary asynchronously.
double mT0
Playback starts at offset of mT0, which is measured in seconds.
void Init(double t0, double t1, const AudioIOStartStreamOptions &options, const RecordingSchedule *pRecordingSchedule)
void SetSequenceTime(double time)
Set current track time value, unadjusted.
class AUDIO_IO_API PlaybackSchedule::TimeQueue mTimeQueue
double GetSequenceTime() const
Get current track time value, unadjusted.
PlaybackPolicy & GetPolicy()
double TotalCorrection() const
double ToDiscard() const
double ToConsume() const
double Consumed() const
PRCrossfadeData mCrossfadeData
Definition: Dither.cpp:67
RecordableSequences captureSequences
Definition: AudioIO.h:72
ConstPlayableSequences prerollSequences
Definition: AudioIO.h:77
std::vector< std::shared_ptr< const OtherPlayableSequence > > otherPlayableSequences
Definition: AudioIO.h:74
ConstPlayableSequences playbackSequences
Definition: AudioIO.h:71