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