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