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 const size_t totalWidth = std::accumulate(
1229 mPlaybackSequences.begin(), mPlaybackSequences.end(), 0,
1230 [](size_t acc, const auto &pSequence){
1231 return acc + pSequence->NChannels(); });
1232
1233 // mPlaybackBuffers buffers correspond many-to-one with
1234 // mPlaybackSequences
1235 // Except, always make at least one playback buffer, in case of
1236 // MIDI playback without any audio
1237 mPlaybackBuffers.resize(0);
1238 mPlaybackBuffers.resize(
1239 std::max<size_t>(1, totalWidth));
1240 // Number of scratch buffers depends on device playback channels
1241 if (mNumPlaybackChannels > 0) {
1242 mScratchBuffers.resize(mNumPlaybackChannels * 2 + 1);
1243 mScratchPointers.clear();
1244 for (auto &buffer : mScratchBuffers) {
1245 buffer.Allocate(playbackBufferSize, floatSample);
1246 mScratchPointers.push_back(
1247 reinterpret_cast<float*>(buffer.ptr()));
1248 }
1249 }
1250 mPlaybackMixers.clear();
1251
1252 const auto &warpOptions =
1253 policy.MixerWarpOptions(mPlaybackSchedule);
1254
1255 mPlaybackQueueMinimum = lrint( mRate * times.latency.count() );
1257 std::min( mPlaybackQueueMinimum, playbackBufferSize );
1258
1259 // Limit the mPlaybackQueueMinimum to the hardware latency
1262
1263 // Make mPlaybackQueueMinimum a multiple of mPlaybackSamplesToCopy
1266
1267 if (mPlaybackSequences.empty())
1268 // Make at least one playback buffer
1269 mPlaybackBuffers[0] =
1270 std::make_unique<RingBuffer>(floatSample, playbackBufferSize);
1271
1272 mOldChannelGains.resize(mPlaybackSequences.size());
1273 size_t iBuffer = 0;
1274 for (unsigned int i = 0; i < mPlaybackSequences.size(); i++) {
1275 const auto &pSequence = mPlaybackSequences[i];
1276 // Bug 1763 - We must fade in from zero to avoid a click on starting.
1277 mOldChannelGains[i][0] = 0.0;
1278 mOldChannelGains[i][1] = 0.0;
1279
1280 for (size_t jj = 0, nChannels = pSequence->NChannels();
1281 jj < nChannels; ++jj
1282 )
1283 mPlaybackBuffers[iBuffer++] = std::make_unique<RingBuffer>(
1284 floatSample, playbackBufferSize);
1285
1286 // By the precondition of StartStream which is sole caller of
1287 // this function:
1288 assert(pSequence->FindChannelGroup());
1289 // use sequence time for the end time, not real time!
1290 double startTime, endTime;
1291 if (!sequences.prerollSequences.empty())
1292 startTime = mPlaybackSchedule.mT0;
1293 else
1294 startTime = t0;
1295
1297 .contains(pSequence))
1298 // Stop playing this sequence after pre-roll
1299 endTime = t0;
1300 else
1301 // Pass t1 -- not mT1 as may have been adjusted for latency
1302 // -- so that overdub recording stops playing back samples
1303 // at the right time, though transport may continue to
1304 // record
1305 endTime = t1;
1306
1307 Mixer::Inputs mixSequences;
1308 mixSequences.push_back(Mixer::Input{ pSequence });
1309 mPlaybackMixers.emplace_back(std::make_unique<Mixer>(
1310 move(mixSequences),
1311 // Don't throw for read errors, just play silence:
1312 false,
1313 warpOptions, startTime, endTime, pSequence->NChannels(),
1315 false, // not interleaved
1317 false, // low quality dithering and resampling
1318 nullptr, // no custom mix-down
1319 Mixer::ApplyGain::Discard // don't apply gains
1320 ));
1321 }
1322
1323 const auto timeQueueSize = 1 +
1324 (playbackBufferSize + TimeQueueGrainSize - 1)
1326 mPlaybackSchedule.mTimeQueue.Resize( timeQueueSize );
1327 }
1328
1329 if( mNumCaptureChannels > 0 )
1330 {
1331 // Allocate input buffers. For every input sequence we allocate
1332 // a ring buffer of five seconds
1333 auto captureBufferSize =
1334 (size_t)(mRate * mCaptureRingBufferSecs + 0.5);
1335
1336 // In the extraordinarily rare case that we can't even afford
1337 // 100 samples, just give up.
1338 if(captureBufferSize < 100)
1339 {
1340 BasicUI::ShowMessageBox( XO("Out of memory!") );
1341 return false;
1342 }
1343
1344 mCaptureBuffers.resize(0);
1346 mResample.resize(0);
1349
1350 for (unsigned int i = 0; i < mNumCaptureChannels; ++i) {
1351 mCaptureBuffers[i] = std::make_unique<RingBuffer>(
1352 mCaptureFormat, captureBufferSize);
1353 mResample[i] =
1354 std::make_unique<Resample>(true, mFactor, mFactor);
1355 // constant rate resampling
1356 }
1357 }
1358 }
1359 catch(std::bad_alloc&)
1360 {
1361 // Oops! Ran out of memory. This is pretty rare, so we'll just
1362 // try deleting everything, halving our buffer size, and try again.
1363 StartStreamCleanup(true);
1367 mMinCaptureSecsToCopy *= 0.5;
1368 bDone = false;
1369
1370 // In the extraordinarily rare case that we can't even afford 100
1371 // samples, just give up.
1372 auto playbackBufferSize =
1373 (size_t)lrint(mRate * mPlaybackRingBufferSecs.count());
1374 if(playbackBufferSize < 100 || mPlaybackSamplesToCopy < 100)
1375 {
1376 BasicUI::ShowMessageBox( XO("Out of memory!") );
1377 return false;
1378 }
1379 }
1380 } while(!bDone);
1381
1382 success = true;
1383 return true;
1384}
1385
1386void AudioIO::StartStreamCleanup(bool bOnlyBuffers)
1387{
1388 mpTransportState.reset();
1389
1390 mPlaybackBuffers.clear();
1391 mScratchBuffers.clear();
1392 mScratchPointers.clear();
1393 mPlaybackMixers.clear();
1394 mCaptureBuffers.clear();
1395 mResample.clear();
1397
1398 if(!bOnlyBuffers)
1399 {
1400 Pa_AbortStream( mPortStreamV19 );
1401 Pa_CloseStream( mPortStreamV19 );
1402 mPortStreamV19 = NULL;
1403 mStreamToken = 0;
1404 }
1405
1407}
1408
1410{
1411 auto pOwningProject = mOwningProject.lock();
1412 return !pOwningProject || pOwningProject.get() == &project;
1413}
1414
1416{
1417 if (auto pInputMeter = mInputMeter.lock())
1418 pInputMeter->Reset(mRate, true);
1419 if (auto pOutputMeter = mOutputMeter.lock())
1420 pOutputMeter->Reset(mRate, true);
1421}
1422
1424{
1425 auto cleanup = finally ( [this] {
1427 mRecordingSchedule.mCrossfadeData.clear(); // free arrays
1428 } );
1429
1430 if( mPortStreamV19 == NULL )
1431 return;
1432
1433 // DV: This code seems to be unnecessary.
1434 // We do not leave mPortStreamV19 open in stopped
1435 // state. (Do we?)
1436 // This breaks WASAPI backend, as it sets the `running`
1437 // flag to `false` asynchronously.
1438 // Previously we have patched PortAudio and the patch
1439 // was breaking IsStreamStopped() == !IsStreamActive()
1440 // invariant.
1441 /*
1442 if ( Pa_IsStreamStopped(mPortStreamV19) )
1443 return;
1444 */
1445
1446#if (defined(__WXMAC__) || defined(__WXMSW__)) && wxCHECK_VERSION(3,1,0)
1447 // Re-enable system sleep
1448 wxPowerResource::Release(wxPOWER_RESOURCE_SCREEN);
1449#endif
1450
1452 .load(std::memory_order_relaxed) )
1453 {
1454 // PortAudio callback can use the information that we are stopping to fade
1455 // out the audio. Give PortAudio callback a chance to do so.
1456 mForceFadeOut.store(true, std::memory_order_relaxed);
1457 auto latency = static_cast<long>(AudioIOLatencyDuration.Read());
1458 // If we can gracefully fade out in 200ms, with the faded-out play buffers making it through
1459 // the sound card, then do so. If we can't, don't wait around. Just stop quickly and accept
1460 // there will be a click.
1461 if( mbMicroFades && (latency < 150 )) {
1462 using namespace std::chrono;
1463 std::this_thread::sleep_for(milliseconds{latency + 50});
1464 }
1465 }
1466
1467 wxMutexLocker locker(mSuspendAudioThread);
1468
1469 //
1470 // We got here in one of two ways:
1471 //
1472 // 1. The user clicked the stop button and we therefore want to stop
1473 // as quickly as possible. So we use AbortStream(). If this is
1474 // the case the portaudio stream is still in the Running state
1475 // (see PortAudio state machine docs).
1476 //
1477 // 2. The callback told PortAudio to stop the stream since it had
1478 // reached the end of the selection. The UI thread discovered
1479 // this by noticing that AudioIO::IsActive() returned false.
1480 // IsActive() (which calls Pa_GetStreamActive()) will not return
1481 // false until all buffers have finished playing, so we can call
1482 // AbortStream without losing any samples. If this is the case
1483 // we are in the "callback finished state" (see PortAudio state
1484 // machine docs).
1485 //
1486 // The moral of the story: We can call AbortStream safely, without
1487 // losing samples.
1488 //
1489 // DMM: This doesn't seem to be true; it seems to be necessary to
1490 // call StopStream if the callback brought us here, and AbortStream
1491 // if the user brought us here.
1492 //
1493 // DV: Seems that Pa_CloseStream calls Pa_AbortStream internally,
1494 // at least for PortAudio 19.7.0+
1495
1497
1498 // Turn off HW playthrough if PortMixer is being used
1499
1500 #if defined(USE_PORTMIXER)
1501 if( mPortMixer ) {
1502 #if __WXMAC__
1503 if (Px_SupportsPlaythrough(mPortMixer) && mPreviousHWPlaythrough >= 0.0)
1504 Px_SetPlaythrough(mPortMixer, mPreviousHWPlaythrough);
1505 mPreviousHWPlaythrough = -1.0;
1506 #endif
1507 }
1508 #endif
1509
1510 if (mPortStreamV19) {
1511 // DV: Pa_CloseStream will close Pa_AbortStream internally,
1512 // but it doesn't hurt to do it ourselves.
1513 // PA_AbortStream will silently fail if stream is stopped.
1514 if (!Pa_IsStreamStopped( mPortStreamV19 ))
1515 Pa_AbortStream( mPortStreamV19 );
1516
1517 Pa_CloseStream( mPortStreamV19 );
1518
1519 mPortStreamV19 = NULL;
1520 }
1521
1522
1523
1524 // We previously told AudioThread to stop processing, now let's
1525 // be sure it has really stopped before resetting mpTransportState
1527
1528
1529 for( auto &ext : Extensions() )
1530 ext.StopOtherStream();
1531
1532 auto pListener = GetListener();
1533
1534 // If there's no token, we were just monitoring, so we can
1535 // skip this next part...
1536 if (mStreamToken > 0) {
1537 // In either of the above cases, we want to make sure that any
1538 // capture data that made it into the PortAudio callback makes it
1539 // to the target RecordableSequence. To do this, we ask the audio thread
1540 // to call SequenceBufferExchange one last time (it normally would not do
1541 // so since Pa_GetStreamActive() would now return false
1543 }
1544
1545 // No longer need effects processing. This must be done after the stream is stopped
1546 // to prevent the callback from being invoked after the effects are finalized.
1547 mpTransportState.reset();
1548
1549 //
1550 // Everything is taken care of. Now, just free all the resources
1551 // we allocated in StartStream()
1552 //
1553 mPlaybackBuffers.clear();
1554 mScratchBuffers.clear();
1555 mScratchPointers.clear();
1556 mPlaybackMixers.clear();
1558
1559 if (mStreamToken > 0)
1560 {
1561 //
1562 // Offset all recorded sequences to account for latency
1563 //
1564 if (mCaptureSequences.size() > 0) {
1565 mCaptureBuffers.clear();
1566 mResample.clear();
1567
1568 //
1569 // We only apply latency correction when we actually played back
1570 // sequences during the recording. If we did not play back sequences,
1571 // there's nothing we could be out of sync with. This also covers the
1572 // case that we do not apply latency correction when recording the
1573 // first sequence in a project.
1574 //
1575
1576 for (auto &sequence : mCaptureSequences) {
1577 // The calls to Flush
1578 // may cause exceptions because of exhaustion of disk space.
1579 // Stop those exceptions here, or else they propagate through too
1580 // many parts of Audacity that are not effects or editing
1581 // operations. GuardedCall ensures that the user sees a warning.
1582
1583 // Also be sure to Flush each sequence, at the top of the
1584 // guarded call, relying on the guarantee that the sequence will be
1585 // left in a flushed state, though the append buffer may be lost.
1586
1587 GuardedCall( [&] {
1588 // use No-fail-guarantee that sequence is flushed,
1589 // Partial-guarantee that some initial length of the recording
1590 // is saved.
1591 // See comments in SequenceBufferExchange().
1592 sequence->Flush();
1593 } );
1594 }
1595
1596
1597 if (!mLostCaptureIntervals.empty()) {
1598 // This scope may combine many insertions of silence
1599 // into one transaction, lessening the number of checkpoints
1600 std::optional<TransactionScope> pScope;
1601 if (auto pOwningProject = mOwningProject.lock())
1602 pScope.emplace(*pOwningProject, "Dropouts");
1603 for (auto &interval : mLostCaptureIntervals) {
1604 auto &start = interval.first;
1605 auto duration = interval.second;
1606 for (auto &sequence : mCaptureSequences)
1607 GuardedCall([&] {
1608 sequence->InsertSilence(start, duration);
1609 });
1610 }
1611 if (pScope)
1612 pScope->Commit();
1613 }
1614
1615 if (pListener)
1616 pListener->OnCommitRecording();
1617 }
1618 }
1619
1620
1621
1622 if (auto pInputMeter = mInputMeter.lock())
1623 pInputMeter->Reset(mRate, false);
1624
1625 if (auto pOutputMeter = mOutputMeter.lock())
1626 pOutputMeter->Reset(mRate, false);
1627
1628 mInputMeter.reset();
1629 mOutputMeter.reset();
1630
1631 if (pListener && mNumCaptureChannels > 0)
1632 pListener->OnAudioIOStopRecording();
1633
1634 BasicUI::CallAfter([this]{
1636 // Recording was restarted between StopStream and idle time
1637 // So the actions can keep waiting
1638 return;
1639 // In case some other thread was waiting on the mutex too:
1640 std::this_thread::yield();
1641 std::lock_guard<std::mutex> guard{ mPostRecordingActionMutex };
1645 }
1646 DelayActions(false);
1647 });
1648
1649 //
1650 // Only set token to 0 after we're totally finished with everything
1651 //
1652 bool wasMonitoring = mStreamToken == 0;
1653 mStreamToken = 0;
1654
1655 {
1656 auto pOwningProject = mOwningProject.lock();
1657 if (mNumPlaybackChannels > 0)
1658 Publish({ pOwningProject.get(), AudioIOEvent::PLAYBACK, false });
1659 if (mNumCaptureChannels > 0)
1660 Publish({ pOwningProject.get(),
1661 wasMonitoring
1664 false });
1665 }
1666
1668
1671
1672 mPlaybackSequences.clear();
1673 mCaptureSequences.clear();
1674
1676
1677 if (pListener) {
1678 // Tell UI to hide sample rate
1679 pListener->OnAudioIORate(0);
1680 }
1681
1682 // Don't cause a busy wait in the audio thread after stopping scrubbing
1684}
1685
1686void AudioIO::SetPaused(bool state)
1687{
1688 if (state != IsPaused())
1689 {
1690 if (auto pOwningProject = mOwningProject.lock()) {
1691 // The realtime effects manager may remain "active" but becomes
1692 // "suspended" or "resumed".
1693 auto &em = RealtimeEffectManager::Get(*pOwningProject);
1694 em.SetSuspended(state);
1695 }
1696 }
1697
1698 mPaused.store(state, std::memory_order_relaxed);
1699}
1700
1701double AudioIO::GetBestRate(bool capturing, bool playing, double sampleRate)
1702{
1703 // Check if we can use the cached value
1705 && mCachedBestRatePlaying == playing && mCachedBestRateCapturing == capturing) {
1706 return mCachedBestRateOut;
1707 }
1708
1709 // In order to cache the value, all early returns should instead set retval
1710 // and jump to finished
1711 double retval;
1712
1713 std::vector<long> rates;
1714 if (capturing) wxLogDebug(wxT("AudioIO::GetBestRate() for capture"));
1715 if (playing) wxLogDebug(wxT("AudioIO::GetBestRate() for playback"));
1716 wxLogDebug(wxT("GetBestRate() suggested rate %.0lf Hz"), sampleRate);
1717
1718 if (capturing && !playing) {
1720 }
1721 else if (playing && !capturing) {
1723 }
1724 else { // we assume capturing and playing - the alternative would be a
1725 // bit odd
1726 rates = GetSupportedSampleRates(-1, -1, sampleRate);
1727 }
1728 /* rem rates is the array of hardware-supported sample rates (in the current
1729 * configuration), sampleRate is the Project Rate (desired sample rate) */
1730 long rate = (long)sampleRate;
1731
1732 if (make_iterator_range(rates).contains(rate)) {
1733 wxLogDebug(wxT("GetBestRate() Returning %.0ld Hz"), rate);
1734 retval = rate;
1735 goto finished;
1736 /* the easy case - the suggested rate (project rate) is in the list, and
1737 * we can just accept that and send back to the caller. This should be
1738 * the case for most users most of the time (all of the time on
1739 * Win MME as the OS does resampling) */
1740 }
1741
1742 /* if we get here, there is a problem - the project rate isn't supported
1743 * on our hardware, so we can't us it. Need to come up with an alternative
1744 * rate to use. The process goes like this:
1745 * * If there are no rates to pick from, we're stuck and return 0 (error)
1746 * * If there are some rates, we pick the next one higher than the requested
1747 * rate to use.
1748 * * If there aren't any higher, we use the highest available rate */
1749
1750 if (rates.empty()) {
1751 /* we're stuck - there are no supported rates with this hardware. Error */
1752 wxLogDebug(wxT("GetBestRate() Error - no supported sample rates"));
1753 retval = 0.0;
1754 goto finished;
1755 }
1756 int i;
1757 for (i = 0; i < (int)rates.size(); i++) // for each supported rate
1758 {
1759 if (rates[i] > rate) {
1760 // supported rate is greater than requested rate
1761 wxLogDebug(wxT("GetBestRate() Returning next higher rate - %.0ld Hz"), rates[i]);
1762 retval = rates[i];
1763 goto finished;
1764 }
1765 }
1766
1767 wxLogDebug(wxT("GetBestRate() Returning highest rate - %.0ld Hz"), rates.back());
1768 retval = rates.back(); // the highest available rate
1769 goto finished;
1770
1771finished:
1773 mCachedBestRateOut = retval;
1774 mCachedBestRatePlaying = playing;
1775 mCachedBestRateCapturing = capturing;
1776 return retval;
1777}
1778
1780{
1781 // Sequence time readout for the main thread
1782
1783 if( !IsStreamActive() )
1784 return BAD_STREAM_TIME;
1785
1787}
1788
1789
1791//
1792// Audio Thread Context
1793//
1795
1797void AudioIO::AudioThread(std::atomic<bool> &finish)
1798{
1799 enum class State { eUndefined, eOnce, eLoopRunning, eDoNothing, eMonitoring } lastState = State::eUndefined;
1800 AudioIO *const gAudioIO = AudioIO::Get();
1801 while (!finish.load(std::memory_order_acquire)) {
1802 using Clock = std::chrono::steady_clock;
1803 auto loopPassStart = Clock::now();
1804 auto &schedule = gAudioIO->mPlaybackSchedule;
1805 const auto interval = schedule.GetPolicy().SleepInterval(schedule);
1806
1807 // Set LoopActive outside the tests to avoid race condition
1809 .store(true, std::memory_order_relaxed);
1811 .load(std::memory_order_acquire) )
1812 {
1813 gAudioIO->SequenceBufferExchange();
1815 .store(false, std::memory_order_release);
1816
1817 lastState = State::eOnce;
1818 }
1820 .load(std::memory_order_relaxed))
1821 {
1822 if (lastState != State::eLoopRunning)
1823 {
1824 // Main thread has told us to start - acknowledge that we do
1826 std::memory_order::memory_order_release);
1827 }
1828 lastState = State::eLoopRunning;
1829
1830 // We call the processing after raising the acknowledge flag, because the main thread
1831 // only needs to know that the message was seen.
1832 //
1833 // This is unlike the case with mAudioThreadShouldCallSequenceBufferExchangeOnce where the
1834 // store really means that the one-time exchange was done.
1835
1836 gAudioIO->SequenceBufferExchange();
1837 }
1838 else
1839 {
1840 if ( (lastState == State::eLoopRunning)
1841 || (lastState == State::eMonitoring ) )
1842 {
1843 // Main thread has told us to stop; (actually: to neither process "once" nor "loop running")
1844 // acknowledge that we received the order and that no more processing will be done.
1846 std::memory_order::memory_order_release);
1847 }
1848 lastState = State::eDoNothing;
1849
1850 if (gAudioIO->IsMonitoring())
1851 {
1852 lastState = State::eMonitoring;
1853 }
1854 }
1855
1857 .store(false, std::memory_order_relaxed);
1858
1859 std::this_thread::sleep_until( loopPassStart + interval );
1860 }
1861}
1862
1864 const RingBuffers &buffers, size_t (RingBuffer::*pmf)() const)
1865{
1866 return std::accumulate(buffers.begin(), buffers.end(),
1867 std::numeric_limits<size_t>::max(),
1868 [pmf](auto value, auto &pBuffer){
1869 return std::min(value, (pBuffer.get()->*pmf)()); });
1870}
1871
1873{
1874 auto commonlyAvail = MinValue(mPlaybackBuffers, &RingBuffer::AvailForPut);
1875 // MB: subtract a few samples because the code in SequenceBufferExchange has rounding
1876 // errors
1877 return commonlyAvail - std::min(size_t(10), commonlyAvail);
1878}
1879
1881{
1883}
1884
1886{
1888}
1889
1891{
1893}
1894
1895// This method is the data gateway between the audio thread (which
1896// communicates with the disk) and the PortAudio callback thread
1897// (which communicates with the audio device).
1899{
1902}
1903
1905{
1906 std::optional<RealtimeEffects::ProcessingScope> pScope;
1907 if (mpTransportState && mpTransportState->mpRealtimeInitialization)
1908 pScope.emplace(
1909 *mpTransportState->mpRealtimeInitialization, mOwningProject);
1910
1911 if (mNumPlaybackChannels == 0)
1912 return;
1913
1914 // It is possible that some buffers will have more samples available than
1915 // others. This could happen if we hit this code during the PortAudio
1916 // callback. Also, if in a previous pass, unequal numbers of samples were
1917 // discarded from ring buffers for differing latencies.
1918
1919 // To keep things simple, we write no more data than is vacant in
1920 // ALL buffers, and advance the global time by that much.
1921 auto nAvailable = GetCommonlyFreePlayback();
1922
1923 // Don't fill the buffers at all unless we can do
1924 // at least mPlaybackSamplesToCopy. This improves performance
1925 // by not always trying to process tiny chunks, eating the
1926 // CPU unnecessarily.
1927 if (nAvailable < mPlaybackSamplesToCopy)
1928 return;
1929
1930 // More than mPlaybackSamplesToCopy might be copied:
1931 // May produce a larger amount when initially priming the buffer, or
1932 // perhaps again later in play to avoid underfilling the queue and
1933 // falling behind the real-time demand on the consumer side in the
1934 // callback.
1935 auto GetNeeded = [&]() -> size_t {
1936 // Note that reader might concurrently consume between loop passes below
1937 // So this might not be nondecreasing
1938 auto nReady = GetCommonlyWrittenForPlayback();
1940 };
1941 auto nNeeded = GetNeeded();
1942
1943 // wxASSERT( nNeeded <= nAvailable );
1944
1945 auto Flush = [&]{
1946 /* The flushing of all the Puts to the RingBuffers is lifted out of the
1947 do-loop in ProcessPlaybackSlices, and also after transformation of the
1948 stream for realtime effects.
1949
1950 It's only here that a release is done on the atomic variable that
1951 indicates the readiness of sample data to the consumer. That atomic
1952 also synchronizes the use of the TimeQueue.
1953 */
1954 for (const auto &pBuffer : mPlaybackBuffers)
1955 pBuffer->Flush();
1956 };
1957
1958 while (true) {
1959 // Limit maximum buffer size (increases performance)
1960 auto available = std::min( nAvailable,
1961 std::max( nNeeded, mPlaybackSamplesToCopy ) );
1962
1963 // After each loop pass or after break
1964 Finally Do{ Flush };
1965
1966 if (!ProcessPlaybackSlices(pScope, available))
1967 // We are not making progress. May fail to satisfy the minimum but
1968 // won't loop forever
1969 break;
1970
1971 // Loop again to satisfy the minimum queue requirement in case there
1972 // was discarding of processed data for effect latencies
1973 nNeeded = GetNeeded();
1974 if (nNeeded == 0)
1975 break;
1976
1977 // Might increase because the reader consumed some
1978 nAvailable = GetCommonlyFreePlayback();
1979 }
1980}
1981
1983 std::optional<RealtimeEffects::ProcessingScope> &pScope, size_t available)
1984{
1985 auto &policy = mPlaybackSchedule.GetPolicy();
1986
1987 // msmeyer: When playing a very short selection in looped
1988 // mode, the selection must be copied to the buffer multiple
1989 // times, to ensure, that the buffer has a reasonable size
1990 // This is the purpose of this loop.
1991 // PRL: or, when scrubbing, we may get work repeatedly from the
1992 // user interface.
1993 bool done = false;
1994 bool progress = false;
1995 do {
1996 const auto slice =
1997 policy.GetPlaybackSlice(mPlaybackSchedule, available);
1998 const auto &[frames, toProduce] = slice;
1999 progress = progress || toProduce > 0;
2000
2001 // Update the time queue. This must be done before writing to the
2002 // ring buffers of samples, for proper synchronization with the
2003 // consumer side in the PortAudio thread, which reads the time
2004 // queue after reading the sample queues. The sample queues use
2005 // atomic variables, the time queue doesn't.
2007
2008 // mPlaybackMixers correspond one-to-one with mPlaybackSequences
2009 size_t iSequence = 0;
2010 // mPlaybackBuffers correspond many-to-one with mPlaybackSequences
2011 size_t iBuffer = 0;
2012 for (auto &mixer : mPlaybackMixers) {
2013 // The mixer here isn't actually mixing: it's just doing
2014 // resampling, format conversion, and possibly time track
2015 // warping
2016 if (frames > 0) {
2017 size_t produced = 0;
2018 if (toProduce)
2019 produced = mixer->Process(toProduce);
2020 //wxASSERT(produced <= toProduce);
2021 // Copy (non-interleaved) mixer outputs to one or more ring buffers
2022 const auto nChannels = mPlaybackSequences[iSequence++]->NChannels();
2023 for (size_t j = 0; j < nChannels; ++j) {
2024 auto warpedSamples = mixer->GetBuffer(j);
2025 const auto put = mPlaybackBuffers[iBuffer++]->Put(
2026 warpedSamples, floatSample, produced, frames - produced);
2027 // wxASSERT(put == frames);
2028 // but we can't assert in this thread
2029 wxUnusedVar(put);
2030 }
2031 }
2032 }
2033
2034 if (mPlaybackSequences.empty())
2035 // Produce silence in the single ring buffer
2036 mPlaybackBuffers[0]->Put(nullptr, floatSample, 0, frames);
2037
2038 available -= frames;
2039 // wxASSERT(available >= 0); // don't assert on this thread
2040
2041 done = policy.RepositionPlayback( mPlaybackSchedule, mPlaybackMixers,
2042 frames, available );
2043 } while (available && !done);
2044
2045 // Do any realtime effect processing, more efficiently in at most
2046 // two buffers per sequence, after all the little slices have been written.
2047 TransformPlayBuffers(pScope);
2048 return progress;
2049}
2050
2051#define stackAllocate(T, count) static_cast<T*>(alloca(count * sizeof(T)))
2052
2054 std::optional<RealtimeEffects::ProcessingScope> &pScope)
2055{
2056 // Transform written but un-flushed samples in the RingBuffers in-place.
2057
2058 // Avoiding std::vector
2059 const auto pointers = stackAllocate(float*, mNumPlaybackChannels);
2060
2061 const auto numPlaybackSequences = mPlaybackSequences.size();
2062 // mPlaybackBuffers correspond many-to-one with mPlaybackSequences
2063 size_t iBuffer = 0;
2064 for (const auto vt : mPlaybackSequences) {
2065 if (!vt)
2066 continue;
2067 const auto pGroup = vt->FindChannelGroup();
2068 if (!pGroup)
2069 continue;
2070 // vt is mono, or is the first of its group of channels
2071 const auto nChannels = std::min<size_t>(
2072 mNumPlaybackChannels, vt->NChannels());
2073
2074 // Loop over the blocks of unflushed data, at most two
2075 for (unsigned iBlock : {0, 1}) {
2076 size_t len = 0;
2077 size_t iChannel = 0;
2078 for (; iChannel < nChannels; ++iChannel) {
2079 auto &ringBuffer = *mPlaybackBuffers[iBuffer + iChannel];
2080 const auto pair = ringBuffer.GetUnflushed(iBlock);
2081 // Playback RingBuffers have float format: see AllocateBuffers
2082 pointers[iChannel] = reinterpret_cast<float*>(pair.first);
2083 // The lengths of corresponding unflushed blocks should be
2084 // the same for all channels
2085 if (len == 0)
2086 len = pair.second;
2087 else
2088 assert(len == pair.second);
2089 }
2090
2091 // Are there more output device channels than channels of vt?
2092 // Such as when a mono sequence is processed for stereo play?
2093 // Then supply some non-null fake input buffers, because the
2094 // various ProcessBlock overrides of effects may crash without it.
2095 // But it would be good to find the fixes to make this unnecessary.
2096 float **scratch = &mScratchPointers[mNumPlaybackChannels + 1];
2098 memset((pointers[iChannel++] = *scratch++), 0, len * sizeof(float));
2099
2100 if (len && pScope) {
2101 auto discardable = pScope->Process(*pGroup, &pointers[0],
2102 mScratchPointers.data(),
2103 // The single dummy output buffer:
2106 iChannel = 0;
2107 for (; iChannel < nChannels; ++iChannel) {
2108 auto &ringBuffer = *mPlaybackBuffers[iBuffer + iChannel];
2109 auto discarded = ringBuffer.Unput(discardable);
2110 // assert(discarded == discardable);
2111 }
2112 }
2113 }
2114 iBuffer += vt->NChannels();
2115 }
2116}
2117
2119{
2121 return;
2122
2123 auto delayedHandler = [this] ( AudacityException * pException ) {
2124 // In the main thread, stop recording
2125 // This is one place where the application handles disk
2126 // exhaustion exceptions from RecordableSequence operations, without
2127 // rolling back to the last pushed undo state. Instead, partial recording
2128 // results are pushed as a NEW undo state. For this reason, as
2129 // commented elsewhere, we want an exception safety guarantee for
2130 // the output RecordableSequences, after the failed append operation, that
2131 // the sequences remain as they were after the previous successful
2132 // (block-level) appends.
2133
2134 // Note that the Flush in StopStream() may throw another exception,
2135 // but StopStream() contains that exception, and the logic in
2136 // AudacityException::DelayedHandlerAction prevents redundant message
2137 // boxes.
2138 StopStream();
2139 DefaultDelayedHandlerAction( pException );
2140 for (auto &pSequence: mCaptureSequences)
2141 pSequence->RepairChannels();
2142 };
2143
2144 GuardedCall( [&] {
2145 // start record buffering
2146 const auto avail = GetCommonlyAvailCapture(); // samples
2147 const auto remainingTime =
2148 std::max(0.0, mRecordingSchedule.ToConsume());
2149 // This may be a very big double number:
2150 const auto remainingSamples = remainingTime * mRate;
2151 bool latencyCorrected = true;
2152
2153 double deltat = avail / mRate;
2154
2156 .load(std::memory_order_relaxed) ||
2157 deltat >= mMinCaptureSecsToCopy)
2158 {
2159 bool newBlocks = false;
2160
2161 // Append captured samples to the end of the RecordableSequences.
2162 // (WaveTracks have their own buffering for efficiency.)
2163 auto iter = mCaptureSequences.begin();
2164 auto width = (*iter)->NChannels();
2165 size_t iChannel = 0;
2166 for (size_t i = 0; i < mNumCaptureChannels; ++i) {
2167 Finally Do {[&]{
2168 if (++iChannel == width) {
2169 ++iter;
2170 iChannel = 0;
2171 if (iter != mCaptureSequences.end())
2172 width = (*iter)->NChannels();
2173 }
2174 }};
2175 size_t discarded = 0;
2176
2178 const auto correction = mRecordingSchedule.TotalCorrection();
2179 if (correction >= 0) {
2180 // Rightward shift
2181 // Once only (per sequence per recording), insert some initial
2182 // silence.
2183 size_t size = floor( correction * mRate * mFactor);
2185 ClearSamples(temp.ptr(), mCaptureFormat, 0, size);
2186 (*iter)->Append(iChannel, temp.ptr(), mCaptureFormat, size, 1,
2187 // Do not dither recordings
2189 }
2190 else {
2191 // Leftward shift
2192 // discard some samples from the ring buffers.
2193 size_t size = floor(
2195
2196 // The ring buffer might have grown concurrently -- don't discard more
2197 // than the "avail" value noted above.
2198 discarded = mCaptureBuffers[i]->Discard(std::min(avail, size));
2199
2200 if (discarded < size)
2201 // We need to visit this again to complete the
2202 // discarding.
2203 latencyCorrected = false;
2204 }
2205 }
2206
2207 const float *pCrossfadeSrc = nullptr;
2208 size_t crossfadeStart = 0, totalCrossfadeLength = 0;
2209 if (i < mRecordingSchedule.mCrossfadeData.size())
2210 {
2211 // Do crossfading
2212 // The supplied crossfade samples are at the same rate as the
2213 // sequence
2214 const auto &data = mRecordingSchedule.mCrossfadeData[i];
2215 totalCrossfadeLength = data.size();
2216 if (totalCrossfadeLength) {
2217 crossfadeStart =
2219 if (crossfadeStart < totalCrossfadeLength)
2220 pCrossfadeSrc = data.data() + crossfadeStart;
2221 }
2222 }
2223
2224 wxASSERT(discarded <= avail);
2225 size_t toGet = avail - discarded;
2226 SampleBuffer temp;
2227 size_t size;
2229 if( mFactor == 1.0 )
2230 {
2231 // Take captured samples directly
2232 size = toGet;
2233 if (pCrossfadeSrc)
2234 // Change to float for crossfade calculation
2236 else
2238 temp.Allocate(size, format);
2239 const auto got =
2240 mCaptureBuffers[i]->Get(temp.ptr(), format, toGet);
2241 // wxASSERT(got == toGet);
2242 // but we can't assert in this thread
2243 wxUnusedVar(got);
2244 if (double(size) > remainingSamples)
2245 size = floor(remainingSamples);
2246 }
2247 else
2248 {
2249 size = lrint(toGet * mFactor);
2251 SampleBuffer temp1(toGet, floatSample);
2252 temp.Allocate(size, format);
2253 const auto got =
2254 mCaptureBuffers[i]->Get(temp1.ptr(), floatSample, toGet);
2255 // wxASSERT(got == toGet);
2256 // but we can't assert in this thread
2257 wxUnusedVar(got);
2258 /* we are re-sampling on the fly. The last resampling call
2259 * must flush any samples left in the rate conversion buffer
2260 * so that they get recorded
2261 */
2262 if (toGet > 0 ) {
2263 if (double(toGet) > remainingSamples)
2264 toGet = floor(remainingSamples);
2265 const auto results =
2266 mResample[i]->Process(mFactor, (float *)temp1.ptr(), toGet,
2267 !IsStreamActive(), (float *)temp.ptr(), size);
2268 size = results.second;
2269 }
2270 }
2271
2272 if (pCrossfadeSrc) {
2273 wxASSERT(format == floatSample);
2274 size_t crossfadeLength = std::min(size, totalCrossfadeLength - crossfadeStart);
2275 if (crossfadeLength) {
2276 auto ratio = double(crossfadeStart) / totalCrossfadeLength;
2277 auto ratioStep = 1.0 / totalCrossfadeLength;
2278 auto pCrossfadeDst = (float*)temp.ptr();
2279
2280 // Crossfade loop here
2281 for (size_t ii = 0; ii < crossfadeLength; ++ii) {
2282 *pCrossfadeDst = ratio * *pCrossfadeDst + (1.0 - ratio) * *pCrossfadeSrc;
2283 ++pCrossfadeSrc, ++pCrossfadeDst;
2284 ratio += ratioStep;
2285 }
2286 }
2287 }
2288
2289 // Now append
2290 // see comment in second handler about guarantee
2291 newBlocks = (*iter)->Append(iChannel,
2292 temp.ptr(), format, size, 1,
2293 // Do not dither recordings
2295 ) || newBlocks;
2296 } // end loop over capture channels
2297
2298 // Now update the recording schedule position
2300 mRecordingSchedule.mLatencyCorrected = latencyCorrected;
2301
2302 auto pListener = GetListener();
2303 if (pListener && newBlocks)
2304 pListener->OnAudioIONewBlocks();
2305
2306 }
2307 // end of record buffering
2308 },
2309 // handler
2310 [this] ( AudacityException *pException ) {
2311 if ( pException ) {
2312 // So that we don't attempt to fill the recording buffer again
2313 // before the main thread stops recording
2315 return ;
2316 }
2317 else
2318 // Don't want to intercept other exceptions (?)
2319 throw;
2320 },
2321 delayedHandler );
2322}
2323
2325 const std::shared_ptr< AudioIOListener > &listener)
2326{
2327 if (IsBusy())
2328 return;
2329
2330 mListener = listener;
2331}
2332
2333// Automated Input Level Adjustment - Automatically tries to find an acceptable input volume
2334#ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
2335
2336#include "ProjectStatus.h"
2337
2338void AudioIO::AILAInitialize() {
2339 gPrefs->Read(wxT("/AudioIO/AutomatedInputLevelAdjustment"), &mAILAActive, false);
2340 gPrefs->Read(wxT("/AudioIO/TargetPeak"), &mAILAGoalPoint, AILA_DEF_TARGET_PEAK);
2341 gPrefs->Read(wxT("/AudioIO/DeltaPeakVolume"), &mAILAGoalDelta, AILA_DEF_DELTA_PEAK);
2342 gPrefs->Read(wxT("/AudioIO/AnalysisTime"), &mAILAAnalysisTime, AILA_DEF_ANALYSIS_TIME);
2343 gPrefs->Read(wxT("/AudioIO/NumberAnalysis"), &mAILATotalAnalysis, AILA_DEF_NUMBER_ANALYSIS);
2344 mAILAGoalDelta /= 100.0;
2345 mAILAGoalPoint /= 100.0;
2346 mAILAAnalysisTime /= 1000.0;
2347 mAILAMax = 0.0;
2348 mAILALastStartTime = max(0.0, mPlaybackSchedule.mT0);
2349 mAILAClipped = false;
2350 mAILAAnalysisCounter = 0;
2351 mAILAChangeFactor = 1.0;
2352 mAILALastChangeType = 0;
2353 mAILATopLevel = 1.0;
2354 mAILAAnalysisEndTime = -1.0;
2355}
2356
2357void AudioIO::AILADisable() {
2358 mAILAActive = false;
2359}
2360
2361bool AudioIO::AILAIsActive() {
2362 return mAILAActive;
2363}
2364
2365void AudioIO::AILASetStartTime() {
2366 mAILAAbsolutStartTime = Pa_GetStreamTime(mPortStreamV19);
2367 wxPrintf("START TIME %f\n\n", mAILAAbsolutStartTime);
2368}
2369
2370double AudioIO::AILAGetLastDecisionTime() {
2371 return mAILAAnalysisEndTime;
2372}
2373
2374void AudioIO::AILAProcess(double maxPeak) {
2375 const auto proj = mOwningProject.lock();
2376 if (proj && mAILAActive) {
2377 if (mInputMeter && mInputMeter->IsClipping()) {
2378 mAILAClipped = true;
2379 wxPrintf("clipped");
2380 }
2381
2382 mAILAMax = max(mAILAMax, maxPeak);
2383
2384 if ((mAILATotalAnalysis == 0 || mAILAAnalysisCounter < mAILATotalAnalysis) && mPlaybackSchedule.GetSequenceTime() - mAILALastStartTime >= mAILAAnalysisTime) {
2385 auto ToLinearIfDB = [](double value, int dbRange) {
2386 if (dbRange >= 0)
2387 value = pow(10.0, (-(1.0-value) * dbRange)/20.0);
2388 return value;
2389 };
2390
2391 putchar('\n');
2392 mAILAMax = mInputMeter ? ToLinearIfDB(mAILAMax, mInputMeter->GetDBRange()) : 0.0;
2393 double iv = (double) Px_GetInputVolume(mPortMixer);
2394 unsigned short changetype = 0; //0 - no change, 1 - increase change, 2 - decrease change
2395 wxPrintf("mAILAAnalysisCounter:%d\n", mAILAAnalysisCounter);
2396 wxPrintf("\tmAILAClipped:%d\n", mAILAClipped);
2397 wxPrintf("\tmAILAMax (linear):%f\n", mAILAMax);
2398 wxPrintf("\tmAILAGoalPoint:%f\n", mAILAGoalPoint);
2399 wxPrintf("\tmAILAGoalDelta:%f\n", mAILAGoalDelta);
2400 wxPrintf("\tiv:%f\n", iv);
2401 wxPrintf("\tmAILAChangeFactor:%f\n", mAILAChangeFactor);
2402 if (mAILAClipped || mAILAMax > mAILAGoalPoint + mAILAGoalDelta) {
2403 wxPrintf("too high:\n");
2404 mAILATopLevel = min(mAILATopLevel, iv);
2405 wxPrintf("\tmAILATopLevel:%f\n", mAILATopLevel);
2406 //if clipped or too high
2407 if (iv <= LOWER_BOUND) {
2408 //we can't improve it more now
2409 if (mAILATotalAnalysis != 0) {
2410 mAILAActive = false;
2411 ProjectStatus::Get( *proj ).Set(
2412 XO(
2413"Automated Recording Level Adjustment stopped. It was not possible to optimize it more. Still too high.") );
2414 }
2415 wxPrintf("\talready min vol:%f\n", iv);
2416 }
2417 else {
2418 float vol = (float) max(LOWER_BOUND, iv+(mAILAGoalPoint-mAILAMax)*mAILAChangeFactor);
2419 Px_SetInputVolume(mPortMixer, vol);
2420 auto msg = XO(
2421"Automated Recording Level Adjustment decreased the volume to %f.").Format( vol );
2422 ProjectStatus::Get( *proj ).Set(msg);
2423 changetype = 1;
2424 wxPrintf("\tnew vol:%f\n", vol);
2425 float check = Px_GetInputVolume(mPortMixer);
2426 wxPrintf("\tverified %f\n", check);
2427 }
2428 }
2429 else if ( mAILAMax < mAILAGoalPoint - mAILAGoalDelta ) {
2430 //if too low
2431 wxPrintf("too low:\n");
2432 if (iv >= UPPER_BOUND || iv + 0.005 > mAILATopLevel) { //condition for too low volumes and/or variable volumes that cause mAILATopLevel to decrease too much
2433 //we can't improve it more
2434 if (mAILATotalAnalysis != 0) {
2435 mAILAActive = false;
2436 ProjectStatus::Get( *proj ).Set(
2437 XO(
2438"Automated Recording Level Adjustment stopped. It was not possible to optimize it more. Still too low.") );
2439 }
2440 wxPrintf("\talready max vol:%f\n", iv);
2441 }
2442 else {
2443 float vol = (float) min(UPPER_BOUND, iv+(mAILAGoalPoint-mAILAMax)*mAILAChangeFactor);
2444 if (vol > mAILATopLevel) {
2445 vol = (iv + mAILATopLevel)/2.0;
2446 wxPrintf("\tTruncated vol:%f\n", vol);
2447 }
2448 Px_SetInputVolume(mPortMixer, vol);
2449 auto msg = XO(
2450"Automated Recording Level Adjustment increased the volume to %.2f.")
2451 .Format( vol );
2452 ProjectStatus::Get( *proj ).Set(msg);
2453 changetype = 2;
2454 wxPrintf("\tnew vol:%f\n", vol);
2455 float check = Px_GetInputVolume(mPortMixer);
2456 wxPrintf("\tverified %f\n", check);
2457 }
2458 }
2459
2460 mAILAAnalysisCounter++;
2461 //const PaStreamInfo* info = Pa_GetStreamInfo(mPortStreamV19);
2462 //double latency = 0.0;
2463 //if (info)
2464 // latency = info->inputLatency;
2465 //mAILAAnalysisEndTime = mTime+latency;
2466 mAILAAnalysisEndTime = Pa_GetStreamTime(mPortStreamV19) - mAILAAbsolutStartTime;
2467 mAILAMax = 0;
2468 wxPrintf("\tA decision was made @ %f\n", mAILAAnalysisEndTime);
2469 mAILAClipped = false;
2470 mAILALastStartTime = mPlaybackSchedule.GetSequenceTime();
2471
2472 if (changetype == 0)
2473 mAILAChangeFactor *= 0.8; //time factor
2474 else if (mAILALastChangeType == changetype)
2475 mAILAChangeFactor *= 1.1; //concordance factor
2476 else
2477 mAILAChangeFactor *= 0.7; //discordance factor
2478 mAILALastChangeType = changetype;
2479 putchar('\n');
2480 }
2481
2482 if (mAILAActive && mAILATotalAnalysis != 0 && mAILAAnalysisCounter >= mAILATotalAnalysis) {
2483 mAILAActive = false;
2484 if (mAILAMax > mAILAGoalPoint + mAILAGoalDelta)
2485 ProjectStatus::Get( *proj ).Set(
2486 XO(
2487"Automated Recording Level Adjustment stopped. The total number of analyses has been exceeded without finding an acceptable volume. Still too high.") );
2488 else if (mAILAMax < mAILAGoalPoint - mAILAGoalDelta)
2489 ProjectStatus::Get( *proj ).Set(
2490 XO(
2491"Automated Recording Level Adjustment stopped. The total number of analyses has been exceeded without finding an acceptable volume. Still too low.") );
2492 else {
2493 auto msg = XO(
2494"Automated Recording Level Adjustment stopped. %.2f seems an acceptable volume.")
2495 .Format( Px_GetInputVolume(mPortMixer) );
2496 ProjectStatus::Get( *proj ).Set(msg);
2497 }
2498 }
2499 }
2500}
2501#endif
2502
2504 sampleFormat inputFormat,
2505 unsigned inputChannels,
2506 float *outputBuffer,
2507 unsigned long len)
2508{
2509 for (unsigned int i=0; i < inputChannels; i++) {
2510 auto inputPtr = inputBuffer + (i * SAMPLE_SIZE(inputFormat));
2511
2512 SamplesToFloats(inputPtr, inputFormat,
2513 outputBuffer + i, len, inputChannels, 2);
2514 }
2515
2516 // One mono input channel goes to both output channels...
2517 if (inputChannels == 1)
2518 for (int i=0; i < len; i++)
2519 outputBuffer[2*i + 1] = outputBuffer[2*i];
2520}
2521
2522int audacityAudioCallback(const void *inputBuffer, void *outputBuffer,
2523 unsigned long framesPerBuffer,
2524 const PaStreamCallbackTimeInfo *timeInfo,
2525 const PaStreamCallbackFlags statusFlags, void *userData )
2526{
2527 auto gAudioIO = AudioIO::Get();
2528 return gAudioIO->AudioCallback(
2529 static_cast<constSamplePtr>(inputBuffer),
2530 static_cast<float*>(outputBuffer), framesPerBuffer,
2531 timeInfo, statusFlags, userData);
2532}
2533
2534// Stop recording if 'silence' is detected
2535// Start recording if sound detected.
2536//
2537// By using CallAfter(), we can schedule the call to the toolbar
2538// to run in the main GUI thread after the next event loop iteration.
2539// That's important, because Pause() updates GUI, such as status bar,
2540// and that should NOT happen in this audio non-gui thread.
2542 float *inputSamples,
2543 unsigned long framesPerBuffer
2544 )
2545{
2546 // Quick returns if next to nothing to do.
2547 if( !mPauseRec )
2548 return;
2549
2550 float maxPeak = 0.;
2551 for( unsigned long i = 0, cnt = framesPerBuffer * mNumCaptureChannels; i < cnt; ++i ) {
2552 float sample = fabs(*(inputSamples++));
2553 if (sample > maxPeak) {
2554 maxPeak = sample;
2555 }
2556 }
2557
2558 bool bShouldBePaused = maxPeak < mSilenceLevel;
2559 if( bShouldBePaused != IsPaused() )
2560 {
2561 auto pListener = GetListener();
2562 if ( pListener )
2563 pListener->OnSoundActivationThreshold();
2564 }
2565}
2566
2567// A function to apply the requested gain, fading up or down from the
2568// most recently applied gain.
2570 float * outputMeterFloats,
2571 float * outputFloats,
2572 const float * tempBuf,
2573 bool drop,
2574 const unsigned long len,
2575 const PlayableSequence &ps,
2576 float &channelGain)
2577{
2578 const auto numPlaybackChannels = mNumPlaybackChannels;
2579
2580 float gain = ps.GetChannelGain(chan);
2581 if (drop || mForceFadeOut.load(std::memory_order_relaxed) || IsPaused())
2582 gain = 0.0;
2583
2584 // Output volume emulation: possibly copy meter samples, then
2585 // apply volume, then copy to the output buffer
2586 if (outputMeterFloats != outputFloats)
2587 for ( unsigned i = 0; i < len; ++i)
2588 outputMeterFloats[numPlaybackChannels*i+chan] +=
2589 gain*tempBuf[i];
2590
2591 // DV: We use gain to emulate panning.
2592 // Let's keep the old behavior for panning.
2593 gain *= ExpGain(GetMixerOutputVol());
2594
2595 float oldGain = channelGain;
2596 channelGain = gain;
2597 // if no microfades, jump in volume.
2598 if (!mbMicroFades)
2599 oldGain = gain;
2600 wxASSERT(len > 0);
2601
2602 // Linear interpolate.
2603 // PRL todo: choose denominator differently, so it doesn't depend on
2604 // framesPerBuffer, which is influenced by the portAudio implementation in
2605 // opaque ways
2606 float deltaGain = (gain - oldGain) / len;
2607 for (unsigned i = 0; i < len; i++)
2608 outputFloats[numPlaybackChannels*i+chan] += (oldGain + deltaGain * i) *tempBuf[i];
2609};
2610
2611// Limit values to -1.0..+1.0
2612void ClampBuffer(float * pBuffer, unsigned long len){
2613 for(unsigned i = 0; i < len; i++)
2614 pBuffer[i] = std::clamp(pBuffer[i], -1.0f, 1.0f);
2615};
2616
2617
2618// return true, IFF we have fully handled the callback.
2619//
2620// Mix and copy to PortAudio's output buffer
2621// from our intermediate playback buffers
2622//
2624 float *outputBuffer,
2625 unsigned long framesPerBuffer,
2626 float *outputMeterFloats
2627)
2628{
2629 const auto numPlaybackSequences = mPlaybackSequences.size();
2630 const auto numPlaybackChannels = mNumPlaybackChannels;
2631 const auto numCaptureChannels = mNumCaptureChannels;
2632
2633 mMaxFramesOutput = 0;
2634
2635 // Quick returns if next to nothing to do.
2636 if (mStreamToken <= 0 ||
2637 !outputBuffer ||
2638 numPlaybackChannels <= 0) {
2639 // So that UpdateTimePosition() will be correct, in case of MIDI play with
2640 // no audio output channels
2641 mMaxFramesOutput = framesPerBuffer;
2642 return false;
2643 }
2644
2645 float *outputFloats = outputBuffer;
2646
2648 mSeek = 0.0;
2649
2650 if (mSeek){
2652 return true;
2653 }
2654
2655 // ------ MEMORY ALLOCATION ----------------------
2656 // These are small structures.
2657 const auto tempBufs = stackAllocate(float *, numPlaybackChannels);
2658
2659 // And these are larger structures....
2660 for (unsigned int c = 0; c < numPlaybackChannels; c++)
2661 tempBufs[c] = stackAllocate(float, framesPerBuffer);
2662 // ------ End of MEMORY ALLOCATION ---------------
2663
2664 // Choose a common size to take from all ring buffers
2665 const auto toGet =
2666 std::min<size_t>(framesPerBuffer, GetCommonlyReadyPlayback());
2667
2668 // The drop and dropQuickly booleans are so named for historical reasons.
2669 // JKC: The original code attempted to be faster by doing nothing on silenced audio.
2670 // This, IMHO, is 'premature optimisation'. Instead clearer and cleaner code would
2671 // simply use a gain of 0.0 for silent audio and go on through to the stage of
2672 // applying that 0.0 gain to the data mixed into the buffer.
2673 // Then (and only then) we would have if needed fast paths for:
2674 // - Applying a uniform gain of 0.0.
2675 // - Applying a uniform gain of 1.0.
2676 // - Applying some other uniform gain.
2677 // - Applying a linearly interpolated gain.
2678 // I would expect us not to need the fast paths, since linearly interpolated gain
2679 // is very cheap to process.
2680
2681 bool drop = false; // Sequence should become silent.
2682 bool discardable = false; // Sequence has already been faded to silence.
2683 // mPlaybackBuffers buffers correspond many-to-one with mPlaybackSequences
2684 size_t iBuffer = 0;
2685 for (unsigned tt = 0; tt < numPlaybackSequences; ++tt) {
2686 auto vt = mPlaybackSequences[tt].get();
2687 const auto width = vt->NChannels();
2688
2689 // IF mono THEN clear 'the other' channel.
2690 if (width < numPlaybackChannels)
2691 // TODO: more-than-two-channels
2692 memset(tempBufs[1], 0, framesPerBuffer * sizeof(float));
2693
2694 // Check for asynchronous user changes in mute, solo, pause status
2695 discardable = drop = SequenceShouldBeSilent(*vt);
2696
2697 if (mbMicroFades)
2698 // If micro fading, don't silence tracks instantaneously
2699 discardable = discardable &&
2701
2702 decltype(framesPerBuffer) len = 0;
2703
2704 for (size_t c = 0; c < width; ++c) {
2705 if (discardable) {
2706 len = mPlaybackBuffers[iBuffer]->Discard(toGet);
2707 // keep going here.
2708 // we may still need to issue a paComplete.
2709
2710 // Keep tempBufs initialized to avoid NaNs and Infs
2711 memset(tempBufs[c], 0, framesPerBuffer * sizeof(float));
2712 }
2713 else {
2714 len = mPlaybackBuffers[iBuffer]
2715 ->Get((samplePtr)tempBufs[c], floatSample, toGet);
2716 // wxASSERT( len == toGet );
2717 if (len < framesPerBuffer)
2718 // This used to happen normally at the end of non-looping
2719 // plays, but it can also be an anomalous case where the
2720 // supply from SequenceBufferExchange fails to keep up with the
2721 // real-time demand in this thread (see bug 1932). We
2722 // must supply something to the sound card, so pad it with
2723 // zeroes and not random garbage.
2724 memset((void*)&tempBufs[c][len], 0,
2725 (framesPerBuffer - len) * sizeof(float));
2726 }
2727 ++iBuffer;
2728 }
2729
2730 // PRL: More recent rewrites of SequenceBufferExchange should guarantee a
2731 // padding out of the ring buffers so that equal lengths are
2732 // available, so maxLen ought to increase from 0 only once
2733 mMaxFramesOutput = std::max(mMaxFramesOutput, len);
2734
2735 len = mMaxFramesOutput;
2736
2737 // Realtime effect transformation of the sound used to happen here
2738 // but it is now done already on the producer side of the RingBuffer
2739
2740 // Mix the results with the existing output (software playthrough) and
2741 // apply panning. If post panning effects are desired, the panning would
2742 // need to be be split out from the mixing and applied in a separate step.
2743
2744 // Our channels aren't silent. We need to pass their data on.
2745 //
2746 // Each channel in the sequences can output to more than one channel on
2747 // the device. For example mono channels output to both left and right
2748 // output channels.
2749 if (len > 0) {
2750 auto &gains = mOldChannelGains[tt];
2751 AddToOutputChannel(0, outputMeterFloats, outputFloats,
2752 tempBufs[0], drop, len, *vt, gains[0]);
2753
2754 // If one of mPlaybackSequences is mono, this replicates it in both
2755 // device channels
2756 const auto iBuffer = std::min<size_t>(1, width - 1);
2757 AddToOutputChannel(1, outputMeterFloats, outputFloats,
2758 tempBufs[iBuffer], drop, len, *vt, gains[1]);
2759 }
2760
2762 if (discardable) // no samples to process, they've been discarded
2763 continue;
2764 }
2765
2766 // Poke: If there are no playback sequences, then the earlier check
2767 // about the time indicator being past the end won't happen;
2768 // do it here instead (but not if looping or scrubbing)
2769 // PRL: Also consume from the single playback ring buffer
2770 if (numPlaybackSequences == 0) {
2771 mMaxFramesOutput = mPlaybackBuffers[0]->Discard(toGet);
2773 }
2774
2775 // wxASSERT( maxLen == toGet );
2776
2777 mLastPlaybackTimeMillis = ::wxGetUTCTimeMillis();
2778
2779 ClampBuffer( outputFloats, framesPerBuffer*numPlaybackChannels );
2780 if (outputMeterFloats != outputFloats)
2781 ClampBuffer( outputMeterFloats, framesPerBuffer*numPlaybackChannels );
2782
2783 return false;
2784}
2785
2786void AudioIoCallback::UpdateTimePosition(unsigned long framesPerBuffer)
2787{
2788 // Quick returns if next to nothing to do.
2789 if (mStreamToken <= 0)
2790 return;
2791
2792 // Update the position seen by drawing code
2795}
2796
2797// return true, IFF we have fully handled the callback.
2798//
2799// Copy from PortAudio input buffers to our intermediate recording buffers.
2800//
2802 constSamplePtr inputBuffer,
2803 unsigned long framesPerBuffer,
2804 const PaStreamCallbackFlags statusFlags,
2805 float * tempFloats
2806)
2807{
2808 const auto numPlaybackChannels = mNumPlaybackChannels;
2809 const auto numCaptureChannels = mNumCaptureChannels;
2810
2811 // Quick returns if next to nothing to do.
2812 if (mStreamToken <= 0)
2813 return;
2814 if( !inputBuffer )
2815 return;
2816 if( numCaptureChannels <= 0 )
2817 return;
2818
2819 // If there are no playback sequences, and we are recording, then the
2820 // earlier checks for being past the end won't happen, so do it here.
2822 mCallbackReturn = paComplete;
2823 }
2824
2825 // The error likely from a too-busy CPU falling behind real-time data
2826 // is paInputOverflow
2827 bool inputError =
2828 (statusFlags & (paInputOverflow))
2829 && !(statusFlags & paPrimingOutput);
2830
2831 // But it seems it's easy to get false positives, at least on Mac
2832 // So we have not decided to enable this extra detection yet in
2833 // production
2834
2835 size_t len = framesPerBuffer;
2836 for(unsigned t = 0; t < numCaptureChannels; t++)
2837 len = std::min( len, mCaptureBuffers[t]->AvailForPut() );
2838
2839 if (mSimulateRecordingErrors && 100LL * rand() < RAND_MAX)
2840 // Make spurious errors for purposes of testing the error
2841 // reporting
2842 len = 0;
2843
2844 // A different symptom is that len < framesPerBuffer because
2845 // the other thread, executing SequenceBufferExchange, isn't consuming fast
2846 // enough from mCaptureBuffers; maybe it's CPU-bound, or maybe the
2847 // storage device it writes is too slow
2848 if (mDetectDropouts &&
2849 ((mDetectUpstreamDropouts.load(std::memory_order_relaxed)
2850 && inputError) ||
2851 len < framesPerBuffer) ) {
2852 // Assume that any good partial buffer should be written leftmost
2853 // and zeroes will be padded after; label the zeroes.
2854 auto start = mPlaybackSchedule.GetSequenceTime() +
2856 auto duration = (framesPerBuffer - len) / mRate;
2857 auto pLast = mLostCaptureIntervals.empty()
2858 ? nullptr : &mLostCaptureIntervals.back();
2859 if (pLast &&
2860 fabs(pLast->first + pLast->second - start) < 0.5/mRate)
2861 // Make one bigger interval, not two butting intervals
2862 pLast->second = start + duration - pLast->first;
2863 else
2864 mLostCaptureIntervals.emplace_back( start, duration );
2865 }
2866
2867 if (len < framesPerBuffer)
2868 {
2869 mLostSamples += (framesPerBuffer - len);
2870 wxPrintf(wxT("lost %d samples\n"), (int)(framesPerBuffer - len));
2871 }
2872
2873 if (len <= 0)
2874 return;
2875
2876 // We have an ASSERT in the AudioIO constructor to alert us to
2877 // possible issues with the (short*) cast. We'd have a problem if
2878 // sizeof(short) > sizeof(float) since our buffers are sized for floats.
2879 for(unsigned t = 0; t < numCaptureChannels; t++) {
2880
2881 // dmazzoni:
2882 // Un-interleave. Ugly special-case code required because the
2883 // capture channels could be in three different sample formats;
2884 // it'd be nice to be able to call CopySamples, but it can't
2885 // handle multiplying by the gain and then clipping. Bummer.
2886
2887 switch(mCaptureFormat) {
2888 case floatSample: {
2889 auto inputFloats = (const float *)inputBuffer;
2890 for(unsigned i = 0; i < len; i++)
2891 tempFloats[i] =
2892 inputFloats[numCaptureChannels*i+t];
2893 } break;
2894 case int24Sample:
2895 // We should never get here. Audacity's int24Sample format
2896 // is different from PortAudio's sample format and so we
2897 // make PortAudio return float samples when recording in
2898 // 24-bit samples.
2899 wxASSERT(false);
2900 break;
2901 case int16Sample: {
2902 auto inputShorts = (const short *)inputBuffer;
2903 short *tempShorts = (short *)tempFloats;
2904 for( unsigned i = 0; i < len; i++) {
2905 float tmp = inputShorts[numCaptureChannels*i+t];
2906 tmp = std::clamp(tmp, -32768.0f, 32767.0f);
2907 tempShorts[i] = (short)(tmp);
2908 }
2909 } break;
2910 } // switch
2911
2912 // JKC: mCaptureFormat must be for samples with sizeof(float) or
2913 // fewer bytes (because tempFloats is sized for floats). All
2914 // formats are 2 or 4 bytes, so we are OK.
2915 const auto put =
2916 mCaptureBuffers[t]->Put(
2917 (samplePtr)tempFloats, mCaptureFormat, len);
2918 // wxASSERT(put == len);
2919 // but we can't assert in this thread
2920 wxUnusedVar(put);
2921 mCaptureBuffers[t]->Flush();
2922 }
2923}
2924
2925
2926#if 0
2927// Record the reported latency from PortAudio.
2928// TODO: Don't recalculate this with every callback?
2929// 01/21/2009: Disabled until a better solution presents itself.
2930void OldCodeToCalculateLatency()
2931{
2932 // As of 06/17/2006, portaudio v19 returns inputBufferAdcTime set to
2933 // zero. It is being worked on, but for now we just can't do much
2934 // but follow the leader.
2935 //
2936 // 08/27/2006: too inconsistent for now...just leave it a zero.
2937 //
2938 // 04/16/2008: Looks like si->inputLatency comes back with something useful though.
2939 // This rearranged logic uses si->inputLatency, but if PortAudio fixes inputBufferAdcTime,
2940 // this code won't have to be modified to use it.
2941 // Also avoids setting mLastRecordingOffset except when simultaneously playing and recording.
2942 //
2943 if (numCaptureChannels > 0 && numPlaybackChannels > 0) // simultaneously playing and recording
2944 {
2945 if (timeInfo->inputBufferAdcTime > 0)
2946 mLastRecordingOffset = timeInfo->inputBufferAdcTime - timeInfo->outputBufferDacTime;
2947 else if (mLastRecordingOffset == 0.0)
2948 {
2949 const PaStreamInfo* si = Pa_GetStreamInfo( mPortStreamV19 );
2950 mLastRecordingOffset = -si->inputLatency;
2951 }
2952 }
2953}
2954#endif
2955
2956
2957// return true, IFF we have fully handled the callback.
2958// Prime the output buffer with 0's, optionally adding in the playthrough.
2960 constSamplePtr inputBuffer,
2961 float *outputBuffer,
2962 unsigned long framesPerBuffer,
2963 float *outputMeterFloats
2964 )
2965{
2966 const auto numCaptureChannels = mNumCaptureChannels;
2967 const auto numPlaybackChannels = mNumPlaybackChannels;
2968
2969 // Quick returns if next to nothing to do.
2970 if( !outputBuffer )
2971 return;
2972 if( numPlaybackChannels <= 0 )
2973 return;
2974
2975 float *outputFloats = outputBuffer;
2976 for(unsigned i = 0; i < framesPerBuffer*numPlaybackChannels; i++)
2977 outputFloats[i] = 0.0;
2978
2979 if (inputBuffer && mSoftwarePlaythrough) {
2981 numCaptureChannels,
2982 outputBuffer, framesPerBuffer);
2983 }
2984
2985 // Copy the results to outputMeterFloats if necessary
2986 if (outputMeterFloats != outputFloats) {
2987 for (unsigned i = 0; i < framesPerBuffer*numPlaybackChannels; ++i) {
2988 outputMeterFloats[i] = outputFloats[i];
2989 }
2990 }
2991}
2992
2993/* Send data to recording VU meter if applicable */
2994// Also computes rms
2996 const float *inputSamples,
2997 unsigned long framesPerBuffer
2998 )
2999{
3000 const auto numCaptureChannels = mNumCaptureChannels;
3001 auto pInputMeter = mInputMeter.lock();
3002 if ( !pInputMeter )
3003 return;
3004 if( pInputMeter->IsMeterDisabled())
3005 return;
3006 pInputMeter->UpdateDisplay(
3007 numCaptureChannels, framesPerBuffer, inputSamples);
3008}
3009
3010/* Send data to playback VU meter if applicable */
3012 const float *outputMeterFloats,
3013 unsigned long framesPerBuffer)
3014{
3015 const auto numPlaybackChannels = mNumPlaybackChannels;
3016
3017 auto pOutputMeter = mOutputMeter.lock();
3018 if (!pOutputMeter)
3019 return;
3020 if( pOutputMeter->IsMeterDisabled() )
3021 return;
3022 if( !outputMeterFloats)
3023 return;
3024 pOutputMeter->UpdateDisplay(
3025 numPlaybackChannels, framesPerBuffer, outputMeterFloats);
3026
3027 //v Vaughan, 2011-02-25: Moved this update back to TrackPanel::OnTimer()
3028 // as it helps with playback issues reported by Bill and noted on Bug 258.
3029 // The problem there occurs if Software Playthrough is on.
3030 // Could conditionally do the update here if Software Playthrough is off,
3031 // and in TrackPanel::OnTimer() if Software Playthrough is on, but not now.
3032 // PRL 12 Jul 2015: and what was in TrackPanel::OnTimer is now handled by means of track panel timer events
3033 //MixerBoard* pMixerBoard = mOwningProject->GetMixerBoard();
3034 //if (pMixerBoard)
3035 // pMixerBoard->UpdateMeters(GetStreamTime(),
3036 // (pProj->GetControlToolBar()->GetLastPlayMode() == loopedPlay));
3037}
3038
3040 const auto numPlaybackSequences = mPlaybackSequences.size();
3041
3042 // MOVE_TO: CountSoloingSequences() function
3043 unsigned numSolo = 0;
3044 for (unsigned t = 0; t < numPlaybackSequences; t++ )
3045 if (mPlaybackSequences[t]->GetSolo())
3046 numSolo++;
3047 auto range = Extensions();
3048 numSolo += std::accumulate(range.begin(), range.end(), 0,
3049 [](unsigned sum, auto &ext){
3050 return sum + ext.CountOtherSolo(); });
3051 return numSolo;
3052}
3053
3054// TODO: Consider making the two sequence status functions into member
3055// functions of sequence objects
3056
3057// true IFF the sequence should be silent.
3058// The sequence may not yet be silent, since it may still be
3059// fading out.
3061{
3062 return IsPaused() || (!ps.GetSolo() && (
3063 // Cut if somebody else is soloing
3065 // Cut if we're muted (and not soloing)
3066 ps.GetMute()
3067 ));
3068}
3069
3070// This is about micro-fades.
3072{
3073 return gains[0] == 0.0 && gains[1] == 0.0;
3074}
3075
3077{
3078 for (size_t ii = 0, nn = mPlaybackSequences.size(); ii < nn; ++ii) {
3079 auto vt = mPlaybackSequences[ii];
3080 const auto &oldGains = mOldChannelGains[ii];
3081 if (!(SequenceShouldBeSilent(*vt) && SequenceHasBeenFadedOut(oldGains)))
3082 return false;
3083 }
3084 return true;
3085}
3086
3088{
3089 auto &factories = AudioIOExt::GetFactories();
3090 for (auto &factory: factories)
3091 if (auto pExt = factory(mPlaybackSchedule))
3092 mAudioIOExt.push_back( move(pExt) );
3093}
3094
3095
3097{
3098}
3099
3100
3102 constSamplePtr inputBuffer, float *outputBuffer,
3103 unsigned long framesPerBuffer,
3104 const PaStreamCallbackTimeInfo *timeInfo,
3105 const PaStreamCallbackFlags statusFlags, void * WXUNUSED(userData) )
3106{
3107 // Poll sequences for change of state.
3108 // (User might click mute and solo buttons.)
3110 mCallbackReturn = paContinue;
3111
3112 if (IsPaused()
3113 // PRL: Why was this added? Was it only because of the mysterious
3114 // initial leading zeroes, now solved by setting mStreamToken early?
3115 // JKC: I think it's used for the MIDI time cursor. See comments
3116 // at head of file about AudioTime().
3117 || mStreamToken <= 0
3118 )
3119 mNumPauseFrames += framesPerBuffer;
3120
3121 for( auto &ext : Extensions() ) {
3122 ext.ComputeOtherTimings(mRate, IsPaused(),
3123 timeInfo,
3124 framesPerBuffer);
3125 ext.FillOtherBuffers(
3127 }
3128
3129 // ------ MEMORY ALLOCATIONS -----------------------------------------------
3130 // tempFloats will be a reusable scratch pad for (possibly format converted)
3131 // audio data. One temporary use is for the InputMeter data.
3132 const auto numPlaybackChannels = mNumPlaybackChannels;
3133 const auto numCaptureChannels = mNumCaptureChannels;
3134 const auto tempFloats = stackAllocate(float,
3135 framesPerBuffer * std::max(numCaptureChannels, numPlaybackChannels));
3136
3137 bool bVolEmulationActive =
3138 (outputBuffer && GetMixerOutputVol() != 1.0);
3139 // outputMeterFloats is the scratch pad for the output meter.
3140 // we can often reuse the existing outputBuffer and save on allocating
3141 // something new.
3142 const auto outputMeterFloats = bVolEmulationActive
3143 ? stackAllocate(float, framesPerBuffer * numPlaybackChannels)
3144 : outputBuffer;
3145 // ----- END of MEMORY ALLOCATIONS ------------------------------------------
3146
3147 if (inputBuffer && numCaptureChannels) {
3148 float *inputSamples;
3149
3150 if (mCaptureFormat == floatSample) {
3151 inputSamples = (float *) inputBuffer;
3152 }
3153 else {
3154 SamplesToFloats(reinterpret_cast<constSamplePtr>(inputBuffer),
3155 mCaptureFormat, tempFloats, framesPerBuffer * numCaptureChannels);
3156 inputSamples = tempFloats;
3157 }
3158
3160 inputSamples,
3161 framesPerBuffer);
3162
3163 // This function may queue up a pause or resume.
3164 // TODO this is a bit dodgy as it toggles the Pause, and
3165 // relies on an idle event to have handled that, so could
3166 // queue up multiple toggle requests and so do nothing.
3167 // Eventually it will sort itself out by random luck, but
3168 // the net effect is a delay in starting/stopping sound activated
3169 // recording.
3171 inputSamples,
3172 framesPerBuffer);
3173 }
3174
3175 // Even when paused, we do playthrough.
3176 // Initialise output buffer to zero or to playthrough data.
3177 // Initialise output meter values.
3179 inputBuffer,
3180 outputBuffer,
3181 framesPerBuffer,
3182 outputMeterFloats);
3183
3184 // Test for no sequence audio to play (because we are paused and have faded
3185 // out)
3186 if( IsPaused() && (( !mbMicroFades ) || AllSequencesAlreadySilent() ))
3187 return mCallbackReturn;
3188
3189 // To add sequence output to output (to play sound on speaker)
3190 // possible exit, if we were seeking.
3192 outputBuffer,
3193 framesPerBuffer,
3194 outputMeterFloats))
3195 return mCallbackReturn;
3196
3197 // To move the cursor onwards. (uses mMaxFramesOutput)
3198 UpdateTimePosition(framesPerBuffer);
3199
3200 // To capture input into sequence (sound from microphone)
3202 inputBuffer,
3203 framesPerBuffer,
3204 statusFlags,
3205 tempFloats);
3206
3207 SendVuOutputMeterData( outputMeterFloats, framesPerBuffer);
3208
3209 return mCallbackReturn;
3210}
3211
3212
3213
3214
3215
3217{
3218 const int token = mStreamToken;
3219 wxMutexLocker locker(mSuspendAudioThread);
3220 if (token != mStreamToken)
3221 // This stream got destroyed while we waited for it
3222 return paAbort;
3223
3224 // Pause audio thread and wait for it to finish
3225 //
3226 // [PM] the following 8 lines of code could be probably replaced by
3227 // a single call to StopAudioThreadAndWait()
3228 //
3229 // CAUTION: when trying the above, you must also replace the setting of the
3230 // atomic before the return, with a call to StartAudioThread()
3231 //
3232 // If that works, then we can remove mAudioThreadSequenceBufferExchangeLoopActive,
3233 // as it will become unused; consequently, the AudioThread loop would get simpler too.
3234 //
3236 .store(false, std::memory_order_relaxed);
3237
3239 .load(std::memory_order_relaxed ) )
3240 {
3241 using namespace std::chrono;
3242 std::this_thread::sleep_for(50ms);
3243 }
3244
3245 // Calculate the NEW time position, in the PortAudio callback
3246 const auto time =
3248
3250 mSeek = 0.0;
3251
3252
3253 // Reset mixer positions and flush buffers for all sequences
3254 for (auto &mixer : mPlaybackMixers)
3255 mixer->Reposition( time, true );
3256 for (auto &buffer : mPlaybackBuffers) {
3257 const auto toDiscard = buffer->AvailForGet();
3258 const auto discarded = buffer->Discard( toDiscard );
3259 // wxASSERT( discarded == toDiscard );
3260 // but we can't assert in this thread
3261 wxUnusedVar(discarded);
3262 }
3263
3265
3266 // Reload the ring buffers
3268
3269 // Reenable the audio thread
3271 .store(true, std::memory_order_relaxed);
3272
3273 return paContinue;
3274}
3275
3277 int &callbackReturn, unsigned long len)
3278{
3279 if (IsPaused())
3280 return;
3281
3282 bool done =
3284 if (!done)
3285 return;
3286
3287 for( auto &ext : Extensions() )
3288 ext.SignalOtherCompletion();
3289 callbackReturn = paComplete;
3290}
3291
3293{
3294 // Down-cast and dereference are safe because only AudioIOCallback
3295 // populates the array
3296 return *static_cast<AudioIOExt*>(mIterator->get());
3297}
3298
3299
3301{
3302 mAudioThreadSequenceBufferExchangeLoopRunning.store(true, std::memory_order_release);
3303}
3304
3306{
3307 while (mAudioThreadAcknowledge.load(std::memory_order_acquire) != Acknowledge::eStart)
3308 {
3309 using namespace std::chrono;
3310 std::this_thread::sleep_for(50ms);
3311 }
3312 mAudioThreadAcknowledge.store(Acknowledge::eNone, std::memory_order_release);
3313}
3314
3316{
3317 mAudioThreadSequenceBufferExchangeLoopRunning.store(false, std::memory_order_release);
3318}
3319
3321{
3322 while (mAudioThreadAcknowledge.load(std::memory_order_acquire) != Acknowledge::eStop)
3323 {
3324 using namespace std::chrono;
3325 std::this_thread::sleep_for(50ms);
3326 }
3327 mAudioThreadAcknowledge.store(Acknowledge::eNone, std::memory_order_release);
3328}
3329
3330void AudioIoCallback::ProcessOnceAndWait(std::chrono::milliseconds sleepTime)
3331{
3333 .store(true, std::memory_order_release);
3334
3336 .load(std::memory_order_acquire))
3337 {
3338 using namespace std::chrono;
3339 std::this_thread::sleep_for(sleepTime);
3340 }
3341}
3342
3343
3344
3346{
3347 // Includes a test of mTime, used in the main thread
3348 return IsStreamActive() &&
3349 GetNumCaptureChannels() > 0 &&
3352}
3353
3354BoolSetting 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:2522
static PaSampleFormat AudacityToPortAudioSampleFormat(sampleFormat format)
Definition: AudioIO.cpp:460
BoolSetting SoundActivatedRecord
Definition: AudioIO.cpp:3354
static void DoSoftwarePlaythrough(constSamplePtr inputBuffer, sampleFormat inputFormat, unsigned inputChannels, float *outputBuffer, unsigned long len)
Definition: AudioIO.cpp:2503
void ClampBuffer(float *pBuffer, unsigned long len)
Definition: AudioIO.cpp:2612
#define stackAllocate(T, count)
Definition: AudioIO.cpp:2051
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:9
#define DB_TO_LINEAR(x)
Definition: MemoryX.h:337
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:424
std::shared_ptr< AudacityProject > GetOwningProject() const
Definition: AudioIO.h:502
bool mDelayingActions
Definition: AudioIO.h:663
void StopStream() override
Stop recording, playback or input monitoring.
Definition: AudioIO.cpp:1423
void SetOwningProject(const std::shared_ptr< AudacityProject > &pProject)
Definition: AudioIO.cpp:759
bool IsCapturing() const
Definition: AudioIO.cpp:3345
bool InputMixerWorks()
Find out if the input hardware level control is available.
Definition: AudioIO.cpp:427
std::mutex mPostRecordingActionMutex
Definition: AudioIO.h:660
PostRecordingAction mPostRecordingAction
Definition: AudioIO.h:661
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:2118
static void Deinit()
Definition: AudioIO.cpp:218
static AudioIO * Get()
Definition: AudioIO.cpp:126
void SetPaused(bool state)
Pause and un-pause playback and recording.
Definition: AudioIO.cpp:1686
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:1701
void FillPlayBuffers()
First part of SequenceBufferExchange.
Definition: AudioIO.cpp:1904
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:1982
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:1415
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:1409
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:1386
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:1797
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:1872
void ResetOwningProject()
Definition: AudioIO.cpp:770
std::function< void()> PostRecordingAction
Definition: AudioIO.h:492
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 SequenceBufferExchange()
Definition: AudioIO.cpp:1898
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:1890
double GetStreamTime()
During playback, the sequence time most recently played.
Definition: AudioIO.cpp:1779
wxString LastPaErrorString()
Definition: AudioIO.cpp:754
void TransformPlayBuffers(std::optional< RealtimeEffects::ProcessingScope > &scope)
Definition: AudioIO.cpp:2053
void StartThread()
Definition: AudioIO.cpp:309
std::vector< std::unique_ptr< AudioIOExtBase > >::const_iterator mIterator
Definition: AudioIO.h:152
auto operator*() const -> AudioIOExt &
Definition: AudioIO.cpp:3292
unsigned CountSoloingSequences()
Definition: AudioIO.cpp:3039
std::atomic< bool > mAudioThreadSequenceBufferExchangeLoopRunning
Definition: AudioIO.h:319
static int mNextStreamToken
Definition: AudioIO.h:287
std::shared_ptr< AudioIOListener > GetListener() const
Definition: AudioIO.h:169
size_t GetCommonlyWrittenForPlayback()
Definition: AudioIO.cpp:1885
size_t mNumPlaybackChannels
Definition: AudioIO.h:314
void CallbackCheckCompletion(int &callbackReturn, unsigned long len)
Definition: AudioIO.cpp:3276
bool mbMicroFades
Definition: AudioIO.h:291
bool AllSequencesAlreadySilent()
Definition: AudioIO.cpp:3076
double mSeek
Definition: AudioIO.h:293
std::unique_ptr< TransportState > mpTransportState
Holds some state for duration of playback or recording.
Definition: AudioIO.h:406
wxMutex mSuspendAudioThread
Definition: AudioIO.h:368
AudioIOExtRange Extensions()
Definition: AudioIO.h:161
std::atomic< bool > mAudioThreadShouldCallSequenceBufferExchangeOnce
Definition: AudioIO.h:318
std::vector< std::unique_ptr< Resample > > mResample
Definition: AudioIO.h:269
float GetMixerOutputVol()
Definition: AudioIO.h:348
int AudioCallback(constSamplePtr inputBuffer, float *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, const PaStreamCallbackFlags statusFlags, void *userData)
Definition: AudioIO.cpp:3101
std::array< float, 2 > OldChannelGains
Definition: AudioIO.h:185
void CheckSoundActivatedRecordingLevel(float *inputSamples, unsigned long framesPerBuffer)
Definition: AudioIO.cpp:2541
PlaybackSchedule mPlaybackSchedule
Definition: AudioIO.h:404
RecordingSchedule mRecordingSchedule
Definition: AudioIO.h:403
std::vector< float * > mScratchPointers
pointing into mScratchBuffers
Definition: AudioIO.h:282
std::atomic< Acknowledge > mAudioThreadAcknowledge
Definition: AudioIO.h:322
std::atomic< bool > mFinishAudioThread
Definition: AudioIO.h:267
void UpdateTimePosition(unsigned long framesPerBuffer)
Definition: AudioIO.cpp:2786
int mbHasSoloSequences
Definition: AudioIO.h:180
size_t mPlaybackSamplesToCopy
Preferred batch size for replenishing the playback RingBuffer.
Definition: AudioIO.h:298
static double mCachedBestRateOut
Definition: AudioIO.h:362
std::vector< std::unique_ptr< Mixer > > mPlaybackMixers
Definition: AudioIO.h:284
PlaybackPolicy::Duration mPlaybackRingBufferSecs
Definition: AudioIO.h:294
std::thread mAudioThread
Definition: AudioIO.h:266
int mCallbackReturn
Definition: AudioIO.h:181
void AddToOutputChannel(unsigned int chan, float *outputMeterFloats, float *outputFloats, const float *tempBuf, bool drop, unsigned long len, const PlayableSequence &ps, float &channelGain)
Definition: AudioIO.cpp:2569
std::atomic< bool > mAudioThreadSequenceBufferExchangeLoopActive
Definition: AudioIO.h:320
static size_t MinValue(const RingBuffers &buffers, size_t(RingBuffer::*pmf)() const)
Definition: AudioIO.cpp:1863
void ClearRecordingException()
Definition: AudioIO.h:383
long mNumPauseFrames
How many frames of zeros were output due to pauses?
Definition: AudioIO.h:247
bool SequenceShouldBeSilent(const PlayableSequence &ps)
Definition: AudioIO.cpp:3060
void SetRecordingException()
Definition: AudioIO.h:381
std::atomic< bool > mForceFadeOut
Definition: AudioIO.h:336
void DrainInputBuffers(constSamplePtr inputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackFlags statusFlags, float *tempFloats)
Definition: AudioIO.cpp:2801
wxLongLong mLastPlaybackTimeMillis
Definition: AudioIO.h:338
void SendVuInputMeterData(const float *inputSamples, unsigned long framesPerBuffer)
Definition: AudioIO.cpp:2995
std::vector< std::unique_ptr< AudioIOExtBase > > mAudioIOExt
Definition: AudioIOBase.h:322
size_t mHardwarePlaybackLatencyFrames
Hardware output latency in frames.
Definition: AudioIO.h:300
void SendVuOutputMeterData(const float *outputMeterFloats, unsigned long framesPerBuffer)
Definition: AudioIO.cpp:3011
RingBuffers mCaptureBuffers
Definition: AudioIO.h:272
bool mDetectDropouts
Definition: AudioIO.h:388
void DoPlaythrough(constSamplePtr inputBuffer, float *outputBuffer, unsigned long framesPerBuffer, float *outputMeterFloats)
Definition: AudioIO.cpp:2959
void StopAudioThread()
Definition: AudioIO.cpp:3315
void WaitForAudioThreadStarted()
Definition: AudioIO.cpp:3305
bool SequenceHasBeenFadedOut(const OldChannelGains &gains)
Returns true when playback buffer data from both channels is discardable.
Definition: AudioIO.cpp:3071
bool mSimulateRecordingErrors
Definition: AudioIO.h:396
std::vector< OldChannelGains > mOldChannelGains
Definition: AudioIO.h:279
PaError mLastPaError
Definition: AudioIO.h:342
bool FillOutputBuffers(float *outputBuffer, unsigned long framesPerBuffer, float *outputMeterFloats)
Definition: AudioIO.cpp:2623
static bool mCachedBestRatePlaying
Definition: AudioIO.h:363
bool mSoftwarePlaythrough
Definition: AudioIO.h:306
RecordableSequences mCaptureSequences
Definition: AudioIO.h:273
void SetListener(const std::shared_ptr< AudioIOListener > &listener)
Definition: AudioIO.cpp:2324
RingBuffers mPlaybackBuffers
Definition: AudioIO.h:275
double mCaptureRate
Definition: AudioIO.h:316
std::vector< std::unique_ptr< RingBuffer > > RingBuffers
Definition: AudioIO.h:271
int CallbackDoSeek()
Definition: AudioIO.cpp:3216
unsigned long mMaxFramesOutput
Definition: AudioIO.h:289
ConstPlayableSequences mPlaybackSequences
Definition: AudioIO.h:276
double mLastRecordingOffset
Not (yet) used; should perhaps be atomic when it is.
Definition: AudioIO.h:341
void StartAudioThread()
Definition: AudioIO.cpp:3300
size_t GetCommonlyReadyPlayback()
Get the number of audio samples ready in all of the playback buffers.
Definition: AudioIO.cpp:1880
bool mUsingJack
Definition: AudioIO.h:359
std::atomic< bool > mDetectUpstreamDropouts
Definition: AudioIO.h:400
void ProcessOnceAndWait(std::chrono::milliseconds sleepTime=std::chrono::milliseconds(50))
Definition: AudioIO.cpp:3330
size_t mPlaybackQueueMinimum
Occupancy of the queue we try to maintain, with bigger batches if needed.
Definition: AudioIO.h:302
std::weak_ptr< AudioIOListener > mListener
Definition: AudioIO.h:356
wxAtomicInt mRecordingException
Definition: AudioIO.h:380
double mCaptureRingBufferSecs
Definition: AudioIO.h:295
float mSilenceLevel
Definition: AudioIO.h:310
size_t mNumCaptureChannels
Definition: AudioIO.h:312
void SetMixerOutputVol(float value)
Definition: AudioIO.h:350
std::vector< std::pair< double, double > > mLostCaptureIntervals
Definition: AudioIO.h:386
void WaitForAudioThreadStopped()
Definition: AudioIO.cpp:3320
bool mPauseRec
True if Sound Activated Recording is enabled.
Definition: AudioIO.h:309
bool mUsingAlsa
Definition: AudioIO.h:358
double mFactor
Definition: AudioIO.h:288
double mMinCaptureSecsToCopy
Definition: AudioIO.h:304
unsigned long long mLostSamples
Definition: AudioIO.h:317
std::vector< SampleBuffer > mScratchBuffers
Definition: AudioIO.h:281
static bool mCachedBestRateCapturing
Definition: AudioIO.h:364
sampleFormat mCaptureFormat
Definition: AudioIO.h:315
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:45
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 PlaybackSlice GetPlaybackSlice(PlaybackSchedule &schedule, size_t available)
Choose length of one fetch of samples from tracks in a call to AudioIO::FillPlayBuffers.
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)
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 float GetChannelGain(int channel) const =0
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:208
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:264
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:279
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:174
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:71
ConstPlayableSequences prerollSequences
Definition: AudioIO.h:76
std::vector< std::shared_ptr< const OtherPlayableSequence > > otherPlayableSequences
Definition: AudioIO.h:73
ConstPlayableSequences playbackSequences
Definition: AudioIO.h:70