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