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