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