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