Audacity  2.2.2
AudioIO.h
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  AudioIO.h
6 
7  Dominic Mazzoni
8 
9  Use the PortAudio library to play and record sound
10 
11 **********************************************************************/
12 
13 #ifndef __AUDACITY_AUDIO_IO__
14 #define __AUDACITY_AUDIO_IO__
15 
16 #include "portaudio.h"
17 #include "Audacity.h"
18 #include "Experimental.h"
19 
20 #include "MemoryX.h"
21 #include <atomic>
22 #include <utility>
23 #include <vector>
24 #include <wx/atomic.h>
25 #include <wx/weakref.h>
26 
27 #ifdef USE_MIDI
28 
29 // TODO: Put the relative paths into automake.
30 
31 #ifdef EXPERIMENTAL_MIDI_OUT
32 #include "../lib-src/portmidi/pm_common/portmidi.h"
33 #include "../lib-src/portmidi/porttime/porttime.h"
34 #include <cstring> // Allegro include fails if this header isn't included do to no memcpy
35 #include "../lib-src/header-substitutes/allegro.h"
36 
37 class NoteTrack;
38 using NoteTrackArray = std::vector < std::shared_ptr< NoteTrack > >;
39 using NoteTrackConstArray = std::vector < std::shared_ptr< const NoteTrack > >;
40 
41 #endif // EXPERIMENTAL_MIDI_OUT
42 
43 #endif // USE_MIDI
44 
45 #if USE_PORTMIXER
46 #include "../lib-src/portmixer/include/portmixer.h"
47 #endif
48 
49 #include <wx/event.h>
50 #include <wx/string.h>
51 #include <wx/thread.h>
52 
53 #include "SampleFormat.h"
54 
55 class AudioIO;
56 class RingBuffer;
57 class Mixer;
58 class Resample;
59 class TimeTrack;
60 class AudioThread;
61 class MeterPanel;
62 class SelectedRegion;
63 
64 class AudacityProject;
65 
66 class WaveTrack;
67 using WaveTrackArray = std::vector < std::shared_ptr < WaveTrack > >;
68 using WaveTrackConstArray = std::vector < std::shared_ptr < const WaveTrack > >;
69 
70 extern AUDACITY_DLL_API AudioIO *gAudioIO;
71 
72 void InitAudioIO();
73 void DeinitAudioIO();
74 wxString DeviceName(const PaDeviceInfo* info);
75 wxString HostName(const PaDeviceInfo* info);
76 bool ValidateDeviceNames();
77 
78 class AudioIOListener;
79 
80 // #include <cfloat> if you need this constant
81 #define BAD_STREAM_TIME (-DBL_MAX)
82 
83 #define MAX_MIDI_BUFFER_SIZE 5000
84 #define DEFAULT_SYNTH_LATENCY 5
85 
86 #define DEFAULT_LATENCY_DURATION 100.0
87 #define DEFAULT_LATENCY_CORRECTION -130.0
88 
89 #define AUDIO_PRE_ROLL_KEY (wxT("/AudioIO/PreRoll"))
90 #define DEFAULT_PRE_ROLL_SECONDS 5.0
91 
92 #define AUDIO_ROLL_CROSSFADE_KEY (wxT("/AudioIO/Crossfade"))
93 #define DEFAULT_ROLL_CROSSFADE_MS 10.0
94 
95 #ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
96  #define AILA_DEF_TARGET_PEAK 92
97  #define AILA_DEF_DELTA_PEAK 2
98  #define AILA_DEF_ANALYSIS_TIME 1000
99  #define AILA_DEF_NUMBER_ANALYSIS 5
100 #endif
101 
102 wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
103  EVT_AUDIOIO_PLAYBACK, wxCommandEvent);
104 wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
105  EVT_AUDIOIO_CAPTURE, wxCommandEvent);
106 wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
107  EVT_AUDIOIO_MONITOR, wxCommandEvent);
108 
109 // PRL:
110 // If we always run a portaudio output stream (even just to produce silence)
111 // whenever we play Midi, then we might use just one thread for both.
112 // I thought this would improve MIDI synch problems on Linux/ALSA, but RBD
113 // convinced me it was neither a necessary nor sufficient fix. Perhaps too the
114 // MIDI thread might block in some error situations but we should then not
115 // also block the audio thread.
116 // So leave the separate thread ENABLED.
117 #define USE_MIDI_THREAD
118 
119 struct ScrubbingOptions;
120 
121 using PRCrossfadeData = std::vector< std::vector < float > >;
122 
123 // To avoid growing the argument list of StartStream, add fields here
125 {
126  explicit
128  : timeTrack(NULL)
129  , listener(NULL)
130  , rate(rate_)
131  , playLooped(false)
132  , cutPreviewGapStart(0.0)
133  , cutPreviewGapLen(0.0)
134  , pStartTime(NULL)
135  , preRoll(0.0)
136  {}
137 
140  double rate;
144  double * pStartTime;
145  double preRoll;
146 
147 #ifdef EXPERIMENTAL_SCRUBBING_SUPPORT
148  // Non-null value indicates that scrubbing will happen
149  // (do not specify a time track, looping, or recording, which
150  // are all incompatible with scrubbing):
152 #endif
153 
154  // contents may get swapped with empty vector
156 };
157 
161 #ifdef EXPERIMENTAL_MIDI_OUT
162  NoteTrackConstArray midiTracks;
163 #endif
164 
165  // This is a subset of playbackTracks
167 };
168 
169 // This workaround makes pause and stop work when output is to GarageBand,
170 // which seems not to implement the notes-off message correctly.
171 #define AUDIO_IO_GB_MIDI_WORKAROUND
172 
196  const void *inputBuffer, void *outputBuffer,
197  unsigned long framesPerBuffer,
198  const PaStreamCallbackTimeInfo *timeInfo,
199  PaStreamCallbackFlags statusFlags, void *userData );
200 
201 // Communicate data from one writer to one reader.
202 // This is not a queue: it is not necessary for each write to be read.
203 // Rather loss of a message is allowed: writer may overwrite.
204 // Data must be default-constructible and either copyable or movable.
205 template<typename Data>
207  struct alignas( 64
209  //std::hardware_destructive_interference_size // C++17
212  std::atomic<bool> mBusy{ false };
213  Data mData;
214  } mSlots[2];
215 
216  std::atomic<unsigned char> mLastWrittenSlot{ 0 };
217 
218 public:
219  void Initialize();
220 
221  // Move data out (if available), or else copy it out
222  Data Read();
223 
224  // Copy data in
225  void Write( const Data &data );
226  // Move data in
227  void Write( Data &&data );
228 };
230 template<typename Data>
232 {
233  for (auto &slot : mSlots)
234  // Lock both slots first, maybe spinning a little
235  while ( slot.mBusy.exchange( true, std::memory_order_acquire ) )
236  {}
237 
238  mSlots[0].mData = {};
239  mSlots[1].mData = {};
240  mLastWrittenSlot.store( 0, std::memory_order_relaxed );
241 
242  for (auto &slot : mSlots)
243  slot.mBusy.exchange( false, std::memory_order_release );
244 }
246 template<typename Data>
248 {
249  // Whichever slot was last written, prefer to read that.
250  auto idx = mLastWrittenSlot.load( std::memory_order_relaxed );
251  idx = 1 - idx;
252  bool wasBusy = false;
253  do {
254  // This loop is unlikely to execute twice, but it might because the
255  // producer thread is writing a slot.
256  idx = 1 - idx;
257  wasBusy = mSlots[idx].mBusy.exchange( true, std::memory_order_acquire );
258  } while ( wasBusy );
259 
260  // Copy the slot
261  auto result = std::move( mSlots[idx].mData );
262 
263  mSlots[idx].mBusy.store( false, std::memory_order_release );
264 
265  return result;
266 }
268 template<typename Data>
269 void MessageBuffer<Data>::Write( const Data &data )
270 {
271  // Whichever slot was last written, prefer to write the other.
272  auto idx = mLastWrittenSlot.load( std::memory_order_relaxed );
273  bool wasBusy = false;
274  do {
275  // This loop is unlikely to execute twice, but it might because the
276  // consumer thread is reading a slot.
277  idx = 1 - idx;
278  wasBusy = mSlots[idx].mBusy.exchange( true, std::memory_order_acquire );
279  } while ( wasBusy );
280 
281  mSlots[idx].mData = data;
282  mLastWrittenSlot.store( idx, std::memory_order_relaxed );
283 
284  mSlots[idx].mBusy.store( false, std::memory_order_release );
285 }
287 template<typename Data>
288 void MessageBuffer<Data>::Write( Data &&data )
289 {
290  // Whichever slot was last written, prefer to write the other.
291  auto idx = mLastWrittenSlot.load( std::memory_order_relaxed );
292  bool wasBusy = false;
293  do {
294  // This loop is unlikely to execute twice, but it might because the
295  // consumer thread is reading a slot.
296  idx = 1 - idx;
297  wasBusy = mSlots[idx].mBusy.exchange( true, std::memory_order_acquire );
298  } while ( wasBusy );
299 
300  mSlots[idx].mData = std::move( data );
301  mLastWrittenSlot.store( idx, std::memory_order_relaxed );
302 
303  mSlots[idx].mBusy.store( false, std::memory_order_release );
304 }
305 
306 class AUDACITY_DLL_API AudioIO final {
307 
308  public:
309  AudioIO();
310  ~AudioIO();
311 
312  // This function executes in a thread spawned by the PortAudio library
313  int AudioCallback(
314  const void *inputBuffer, void *outputBuffer,
315  unsigned long framesPerBuffer,
316  const PaStreamCallbackTimeInfo *timeInfo,
317  const PaStreamCallbackFlags statusFlags, void *userData);
318 
319  // Part of the callback
320  PaStreamCallbackResult CallbackDoSeek();
321 
322  // Part of the callback
323  void CallbackCheckCompletion(
324  int &callbackReturn, unsigned long len);
325 
326  AudioIOListener* GetListener() { return mListener; }
327  void SetListener(AudioIOListener* listener);
328 
336  void StartMonitoring(double sampleRate);
337 
345  int StartStream(const TransportTracks &tracks,
346  double t0, double t1,
347  const AudioIOStartStreamOptions &options);
348 
354  void StopStream();
357  void SeekStream(double seconds) { mSeek = seconds; }
359 #ifdef EXPERIMENTAL_SCRUBBING_SUPPORT
360  bool IsScrubbing() const { return IsBusy() && mScrubState != 0; }
361 
367  void UpdateScrub(double endTimeOrSpeed, const ScrubbingOptions &options);
368 
369  void StopScrub();
370 
373  double GetLastScrubTime() const;
374 #endif
375 
380  bool IsBusy() const;
381 
388  bool IsStreamActive() const;
389  bool IsStreamActive(int token) const;
391  wxLongLong GetLastPlaybackTime() const { return mLastPlaybackTimeMillis; }
392  AudacityProject *GetOwningProject() const { return mOwningProject; }
393 
394 #ifdef EXPERIMENTAL_MIDI_OUT
395 
399  PmTimestamp MidiTime();
400 
401  // Note: audio code solves the problem of soloing/muting tracks by scanning
402  // all playback tracks on every call to the audio buffer fill routine.
403  // We do the same for Midi, but it seems wasteful for at least two
404  // threads to be frequently polling to update status. This could be
405  // eliminated (also with a reduction in code I think) by updating mHasSolo
406  // each time a solo button is activated or deactivated. For now, I'm
407  // going to do this polling in the FillMidiBuffer routine to localize
408  // changes for midi to the midi code, but I'm declaring the variable
409  // here so possibly in the future, Audio code can use it too. -RBD
410  private:
411  bool mHasSolo; // is any playback solo button pressed?
412  public:
413  bool SetHasSolo(bool hasSolo);
414  bool GetHasSolo() { return mHasSolo; }
415 #endif
416 
422  bool IsAudioTokenActive(int token) const;
423 
426  bool IsMonitoring() const;
427 
429  void SetPaused(bool state);
431  bool IsPaused() const;
432 
433  /* Mixer services are always available. If no stream is running, these
434  * methods use whatever device is specified by the preferences. If a
435  * stream *is* running, naturally they manipulate the mixer associated
436  * with that stream. If no mixer is available, output is emulated and
437  * input is stuck at 1.0f (a gain is applied to output samples).
438  */
439  void SetMixer(int inputSource);
440  void SetMixer(int inputSource, float inputVolume,
441  float playbackVolume);
442  void GetMixer(int *inputSource, float *inputVolume,
443  float *playbackVolume);
450  bool InputMixerWorks();
451 
458  bool OutputMixerEmulated();
459 
464  wxArrayString GetInputSourceNames();
465 
474  void HandleDeviceChange();
475 
488  static std::vector<long> GetSupportedPlaybackRates(int DevIndex = -1,
489  double rate = 0.0);
490 
503  static std::vector<long> GetSupportedCaptureRates(int devIndex = -1,
504  double rate = 0.0);
505 
520  static std::vector<long> GetSupportedSampleRates(int playDevice = -1,
521  int recDevice = -1,
522  double rate = 0.0);
523 
532  static int GetOptimalSupportedSampleRate();
533 
540  double GetStreamTime();
542  sampleFormat GetCaptureFormat() { return mCaptureFormat; }
543  unsigned GetNumPlaybackChannels() const { return mNumPlaybackChannels; }
544  unsigned GetNumCaptureChannels() const { return mNumCaptureChannels; }
545 
546  // Meaning really capturing, not just pre-rolling
547  bool IsCapturing() const;
548 
553  static const int StandardRates[];
555  static const int NumStandardRates;
556 
560  wxString GetDeviceInfo();
561 
562 #ifdef EXPERIMENTAL_MIDI_OUT
563 
564  wxString GetMidiDeviceInfo();
565 #endif
566 
570  static bool ValidateDeviceNames(const wxString &play, const wxString &rec);
571 
575  #ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
576  void AILAInitialize();
577  void AILADisable();
578  bool AILAIsActive();
579  void AILAProcess(double maxPeak);
580  void AILASetStartTime();
581  double AILAGetLastDecisionTime();
582  #endif
583 
584  bool IsAvailable(AudacityProject *projecT) const;
585  void SetCaptureMeter(AudacityProject *project, MeterPanel *meter);
586  void SetPlaybackMeter(AudacityProject *project, MeterPanel *meter);
587 
598  double GetBestRate(bool capturing, bool playing, double sampleRate);
599 
600 private:
603  void SetMeters();
604 
605 
616  bool StartPortAudioStream(double sampleRate,
617  unsigned int numPlaybackChannels,
618  unsigned int numCaptureChannels,
619  sampleFormat captureFormat);
620  void FillBuffers();
621 
622 #ifdef EXPERIMENTAL_MIDI_OUT
623  void PrepareMidiIterator(bool send = true, double offset = 0);
624  bool StartPortMidiStream();
625 
626  // Compute nondecreasing real time stamps, accounting for pauses, but not the
627  // synth latency.
628  double UncorrectedMidiEventTime();
629 
630  void OutputEvent();
631  void FillMidiBuffers();
632  void GetNextEvent();
633  double AudioTime() { return mPlaybackSchedule.mT0 + mNumFrames / mRate; }
634  double PauseTime();
635  void AllNotesOff(bool looping = false);
636 #endif
637 
643  size_t GetCommonlyFreePlayback();
644 
650  size_t GetCommonlyReadyPlayback();
651 
658  size_t GetCommonlyAvailCapture();
659 
667  static int getRecordDevIndex(const wxString &devName = wxEmptyString);
672 #if USE_PORTMIXER
673  static int getRecordSourceIndex(PxMixer *portMixer);
674 #endif
675 
683  static int getPlayDevIndex(const wxString &devName = wxEmptyString);
684 
689  static const int RatesToTry[];
691  static const int NumRatesToTry;
692 
698  bool AllocateBuffers(
699  const AudioIOStartStreamOptions &options,
700  const TransportTracks &tracks, double t0, double t1, double sampleRate,
701  bool scrubbing );
702 
706  void StartStreamCleanup(bool bOnlyBuffers = false);
707 
708 #ifdef EXPERIMENTAL_MIDI_OUT
709  // MIDI_PLAYBACK:
710  PmStream *mMidiStream;
711  PmError mLastPmError;
712 
714  long mSynthLatency; // ms
715 
716  // These fields are used to synchronize MIDI with audio:
717 
719  volatile double mAudioCallbackClockTime;
720 
722  volatile long mNumFrames;
724  volatile long mNumPauseFrames;
726  volatile int mMidiLoopPasses;
727  inline double MidiLoopOffset() {
728  return mMidiLoopPasses * (mPlaybackSchedule.mT1 - mPlaybackSchedule.mT0);
729  }
730 
731  volatile long mAudioFramesPerBuffer;
734  volatile bool mMidiPaused;
737  PmTimestamp mMaxMidiTimestamp;
738 
742  double mSystemMinusAudioTime;
745  double mAudioOutLatency;
746 
747  // Next two are used to adjust the previous two, if
748  // PortAudio does not provide the info (using ALSA):
749 
752  double mStartTime;
754  long mCallbackCount;
755 
758  volatile double mSystemMinusAudioTimePlusLatency;
759 
760  Alg_seq_ptr mSeq;
761  std::unique_ptr<Alg_iterator> mIterator;
763  Alg_event_ptr mNextEvent;
764 
765 #ifdef AUDIO_IO_GB_MIDI_WORKAROUND
766  std::vector< std::pair< int, int > > mPendingNotesOff;
767 #endif
768 
771  double mNextEventTime;
773  NoteTrack *mNextEventTrack;
775  bool mMidiOutputComplete{ true };
777  bool mNextIsNoteOn;
779  bool mMidiStreamActive;
782  bool mSendMidiState;
783  NoteTrackConstArray mMidiPlaybackTracks;
784 #endif
785 
786 #ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
787  bool mAILAActive;
788  bool mAILAClipped;
789  int mAILATotalAnalysis;
790  int mAILAAnalysisCounter;
791  double mAILAMax;
792  double mAILAGoalPoint;
793  double mAILAGoalDelta;
794  double mAILAAnalysisTime;
795  double mAILALastStartTime;
796  double mAILAChangeFactor;
797  double mAILATopLevel;
798  double mAILAAnalysisEndTime;
799  double mAILAAbsolutStartTime;
800  unsigned short mAILALastChangeType; //0 - no change, 1 - increase change, 2 - decrease change
801 #endif
802 
803  std::unique_ptr<AudioThread> mThread;
804 #ifdef EXPERIMENTAL_MIDI_OUT
805 #ifdef USE_MIDI_THREAD
806  std::unique_ptr<AudioThread> mMidiThread;
807 #endif
808 #endif
811  WaveTrackArray mCaptureTracks;
812  ArrayOf<std::unique_ptr<RingBuffer>> mPlaybackBuffers;
813  WaveTrackArray mPlaybackTracks;
816  volatile int mStreamToken;
817  static int mNextStreamToken;
818  double mFactor;
820  double mRate;
822  double mSeek;
823  double mPlaybackRingBufferSecs;
824  double mCaptureRingBufferSecs;
827  size_t mPlaybackSamplesToCopy;
829  size_t mPlaybackQueueMinimum;
830 
831  double mMinCaptureSecsToCopy;
833  bool mPaused;
834  PaStream *mPortStreamV19;
835  bool mSoftwarePlaythrough;
837  bool mPauseRec;
838  float mSilenceLevel;
839  unsigned int mNumCaptureChannels;
840  unsigned int mNumPlaybackChannels;
841  sampleFormat mCaptureFormat;
842  unsigned long long mLostSamples{ 0 };
843  volatile bool mAudioThreadShouldCallFillBuffersOnce;
844  volatile bool mAudioThreadFillBuffersLoopRunning;
845  volatile bool mAudioThreadFillBuffersLoopActive;
846 
847  wxLongLong mLastPlaybackTimeMillis;
848 
849 #ifdef EXPERIMENTAL_MIDI_OUT
850  volatile bool mMidiThreadFillBuffersLoopRunning;
851  volatile bool mMidiThreadFillBuffersLoopActive;
852 #endif
854  volatile double mLastRecordingOffset;
855  PaError mLastPaError;
856 
857 public:
858  wxString LastPaErrorString();
859 private:
861  AudacityProject *mOwningProject;
862  wxWeakRef<MeterPanel> mInputMeter{};
863  MeterPanel *mOutputMeter;
864  bool mUpdateMeters;
865  volatile bool mUpdatingMeters;
866 
867  #if USE_PORTMIXER
868  PxMixer *mPortMixer;
869  float mPreviousHWPlaythrough;
870  #endif /* USE_PORTMIXER */
871 
872  bool mEmulateMixerOutputVol;
880  bool mInputMixerWorks;
881  float mMixerOutputVol;
882 
883  AudioIOListener* mListener;
884 
885  friend class AudioThread;
886 #ifdef EXPERIMENTAL_MIDI_OUT
887  friend class MidiThread;
888 #endif
889 
890  friend void InitAudioIO();
891 
892  bool mUsingAlsa { false };
894  // For cacheing supported sample rates
895  static int mCachedPlaybackIndex;
896  static std::vector<long> mCachedPlaybackRates;
897  static int mCachedCaptureIndex;
898  static std::vector<long> mCachedCaptureRates;
899  static std::vector<long> mCachedSampleRates;
900  static double mCachedBestRateIn;
901  static double mCachedBestRateOut;
902 
903  // Serialize main thread and PortAudio thread's attempts to pause and change
904  // the state used by the third, Audio thread.
905  wxMutex mSuspendAudioThread;
907 #ifdef EXPERIMENTAL_SCRUBBING_SUPPORT
908  struct ScrubState;
909  std::unique_ptr<ScrubState> mScrubState;
911  bool mSilentScrub;
912  double mScrubSpeed;
913  sampleCount mScrubDuration;
914 #endif
915 
916  // A flag tested and set in one thread, cleared in another. Perhaps
917  // this guarantee of atomicity is more cautious than necessary.
918  wxAtomicInt mRecordingException {};
919  void SetRecordingException()
920  { wxAtomicInc( mRecordingException ); }
921  void ClearRecordingException()
922  { if (mRecordingException) wxAtomicDec( mRecordingException ); }
924  std::vector< std::pair<double, double> > mLostCaptureIntervals;
925  bool mDetectDropouts{ true };
926 
927 public:
928  // Pairs of starting time and duration
929  const std::vector< std::pair<double, double> > &LostCaptureIntervals()
930  { return mLostCaptureIntervals; }
932  // Used only for testing purposes in alpha builds
933  bool mSimulateRecordingErrors{ false };
934 
935  // Whether to check the error code passed to audacityAudioCallback to
936  // detect more dropouts
937  bool mDetectUpstreamDropouts{ true };
939 private:
941  double mPreRoll{};
942  double mLatencyCorrection{}; // negative value usually
943  double mDuration{};
944  PRCrossfadeData mCrossfadeData;
945 
946  // These are initialized by the main thread, then updated
947  // only by the thread calling FillBuffers:
948  double mPosition{};
949  bool mLatencyCorrected{};
950 
951  double TotalCorrection() const { return mLatencyCorrection - mPreRoll; }
952  double ToConsume() const;
953  double Consumed() const;
954  double ToDiscard() const;
955  } mRecordingSchedule{};
956 
959  double mT0;
961  double mT1;
966  std::atomic<double> mTime;
967 
971  double mWarpedTime;
972 
976  double mWarpedLength;
977 
978  // mWarpedTime and mWarpedLength are irrelevant when scrubbing,
979  // else they are used in updating mTime,
980  // and when not scrubbing or playing looped, mTime is also used
981  // in the test for termination of playback.
982 
983  // with ComputeWarpedLength, it is now possible the calculate the warped length with 100% accuracy
984  // (ignoring accumulated rounding errors during playback) which fixes the 'missing sound at the end' bug
985 
986  const TimeTrack *mTimeTrack;
987 
988  volatile enum {
989  PLAY_STRAIGHT,
990  PLAY_LOOPED,
991 #ifdef EXPERIMENTAL_SCRUBBING_SUPPORT
992  PLAY_SCRUB,
993  PLAY_AT_SPEED, // a version of PLAY_SCRUB.
994 #endif
995  } mPlayMode { PLAY_STRAIGHT };
996  double mCutPreviewGapStart;
997  double mCutPreviewGapLen;
998 
999  void Init(
1000  double t0, double t1,
1001  const AudioIOStartStreamOptions &options,
1002  const RecordingSchedule *pRecordingSchedule );
1005  bool ReversedTime() const
1006  {
1007  return mT1 < mT0;
1008  }
1009 
1014  double GetTrackTime() const
1015  { return mTime.load(std::memory_order_relaxed); }
1016 
1019  void SetTrackTime( double time )
1020  { mTime.store(time, std::memory_order_relaxed); }
1021 
1027  double ClampTrackTime( double trackTime ) const;
1028 
1034  double LimitTrackTime() const;
1035 
1041  double NormalizeTrackTime() const;
1042 
1043  void ResetMode() { mPlayMode = PLAY_STRAIGHT; }
1045  bool PlayingStraight() const { return mPlayMode == PLAY_STRAIGHT; }
1046  bool Looping() const { return mPlayMode == PLAY_LOOPED; }
1047  bool Scrubbing() const { return mPlayMode == PLAY_SCRUB; }
1048  bool PlayingAtSpeed() const { return mPlayMode == PLAY_AT_SPEED; }
1049  bool Interactive() const { return Scrubbing() || PlayingAtSpeed(); }
1050 
1051  // Returns true if a loop pass, or the sole pass of straight play,
1052  // is completed at the current value of mTime
1053  bool PassIsComplete() const;
1054 
1055  // Returns true if time equals t1 or is on opposite side of t1, to t0
1056  bool Overruns( double trackTime ) const;
1057 
1058  // Compute the NEW track time for the given one and a real duration,
1059  // taking into account whether the schedule is for looping
1060  double AdvancedTrackTime(
1061  double trackTime, double realElapsed, double speed) const;
1062 
1063  // Use the function above in the callback after consuming samples from the
1064  // playback ring buffers, during usual straight or looping play
1065  void TrackTimeUpdate(double realElapsed);
1066 
1067  // Convert a nonnegative real duration to an increment of track time
1068  // relative to mT0.
1069  double TrackDuration(double realElapsed) const;
1070 
1071  // Convert time between mT0 and argument to real duration, according to
1072  // time track if one is given; result is always nonnegative
1073  double RealDuration(double trackTime1) const;
1074 
1075  // How much real time left?
1076  double RealTimeRemaining() const;
1077 
1078  // Advance the real time position
1079  void RealTimeAdvance( double increment );
1080 
1081  // Determine starting duration within the first pass -- sometimes not
1082  // zero
1083  void RealTimeInit( double trackTime );
1084 
1085  void RealTimeRestart();
1086 
1087  } mPlaybackSchedule;
1088 
1089  // Another circular buffer
1090  // Holds track time values corresponding to every nth sample in the playback
1091  // buffers, for some large n
1092  struct TimeQueue {
1093  Doubles mData;
1094  size_t mSize{ 0 };
1095  double mLastTime {};
1096  // These need not be updated atomically, because we rely on the atomics
1097  // in the playback ring buffers to supply the synchronization. Still,
1098  // align them to avoid false sharing.
1099  alignas(64) struct Cursor {
1100  size_t mIndex {};
1101  size_t mRemainder {};
1102  } mHead, mTail;
1103 
1104  void Producer(
1105  const PlaybackSchedule &schedule, double rate, double scrubSpeed,
1106  size_t nSamples );
1107  double Consumer( size_t nSamples, double rate );
1108  } mTimeQueue;
1109 };
#endif
AudioIO::TimeQueue
Definition: AudioIO.h:1090
AudioIO
AudioIO uses the PortAudio library to play and record sound.
Definition: AudioIO.h:304
wxDECLARE_EXPORTED_EVENT
wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API, EVT_AUDIOIO_PLAYBACK, wxCommandEvent)
AudioIO::RecordingSchedule
Definition: AudioIO.h:938
AudioIOStartStreamOptions::timeTrack
TimeTrack * timeTrack
Definition: AudioIO.h:138
AudioIOStartStreamOptions::rate
double rate
Definition: AudioIO.h:140
AudioIOStartStreamOptions::cutPreviewGapStart
double cutPreviewGapStart
Definition: AudioIO.h:142
TransportTracks::prerollTracks
WaveTrackConstArray prerollTracks
Definition: AudioIO.h:166
MessageBuffer::Read
Data Read()
Definition: AudioIO.h:245
MessageBuffer::mSlots
struct MessageBuffer::UpdateSlot mSlots[2]
TransportTracks::playbackTracks
WaveTrackArray playbackTracks
Definition: AudioIO.h:159
DeinitAudioIO
void DeinitAudioIO()
Definition: AudioIO.cpp:956
AudioIOStartStreamOptions::AudioIOStartStreamOptions
AudioIOStartStreamOptions(double rate_)
Definition: AudioIO.h:127
AudioIO::ScrubState
Definition: AudioIO.cpp:525
AudioIOStartStreamOptions::pScrubbingOptions
ScrubbingOptions * pScrubbingOptions
Definition: AudioIO.h:151
MessageBuffer::UpdateSlot::mData
Data mData
Definition: AudioIO.h:211
MeterPanel
MeterPanel is a panel that paints the meter used for monitoring or playback.
Definition: Meter.h:97
ValidateDeviceNames
bool ValidateDeviceNames()
MessageBuffer::Initialize
void Initialize()
Definition: AudioIO.h:229
gAudioIO
AUDACITY_DLL_API AudioIO * gAudioIO
Definition: AudioIO.cpp:483
MessageBuffer::mLastWrittenSlot
std::atomic< unsigned char > mLastWrittenSlot
Definition: AudioIO.h:214
MessageBuffer
Definition: AudioIO.h:206
AudacityProject
AudacityProject provides the main window, with tools and tracks contained within it.
Definition: Project.h:176
AudioIOStartStreamOptions::playLooped
bool playLooped
Definition: AudioIO.h:141
AudioIOStartStreamOptions::pCrossfadeData
PRCrossfadeData * pCrossfadeData
Definition: AudioIO.h:155
TimeTrack
A kind of Track used to 'warp time'.
Definition: TimeTrack.h:29
MessageBuffer::UpdateSlot::mBusy
std::atomic< bool > mBusy
Definition: AudioIO.h:210
SelectedRegion
Defines a selected portion of a project.
Definition: SelectedRegion.h:37
audacityAudioCallback
int audacityAudioCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
Definition: AudioIO.cpp:4687
WaveTrackArray
std::vector< std::shared_ptr< WaveTrack > > WaveTrackArray
Definition: AudioIO.h:67
AudioIOStartStreamOptions
struct holding stream options, including a pointer to the TimeTrack and AudioIOListener and whether t...
Definition: AudioIO.h:124
WaveTrackConstArray
std::vector< std::shared_ptr< const WaveTrack > > WaveTrackConstArray
Definition: AudioIO.h:68
Audacity.h
sampleFormat
sampleFormat
Definition: Types.h:188
MessageBuffer::UpdateSlot
Definition: AudioIO.h:207
WaveTrack
A Track that contains audio waveform data.
Definition: WaveTrack.h:60
AudioIO::PlaybackSchedule
Definition: AudioIO.h:955
DeviceName
wxString DeviceName(const PaDeviceInfo *info)
Definition: AudioIO.cpp:961
Experimental.h
sampleCount
Definition: Types.h:60
SampleFormat.h
HostName
wxString HostName(const PaDeviceInfo *info)
Definition: AudioIO.cpp:968
MemoryX.h
TransportTracks
Definition: AudioIO.h:158
PRCrossfadeData
std::vector< std::vector< float > > PRCrossfadeData
Definition: AudioIO.h:121
NoteTrackConstArray
std::vector< std::shared_ptr< const NoteTrack > > NoteTrackConstArray
Definition: Track.h:54
AudioIO::TimeQueue::Cursor
Definition: AudioIO.h:1097
AudioIOListener
Monitors record play start/stop and new blockfiles. Has callbacks for these events.
Definition: AudioIOListener.h:20
RingBuffer
Holds streamed audio samples.
Definition: RingBuffer.h:17
Resample
Interface to libsoxr.
Definition: Resample.h:32
ScrubbingOptions
Definition: Scrubbing.h:38
ArrayOf
Memory.h template class for making an array of float, bool, etc.
Definition: MemoryX.h:82
MessageBuffer::Write
void Write(const Data &data)
Definition: AudioIO.h:267
InitAudioIO
void InitAudioIO()
Definition: AudioIO.cpp:923
AudioIOStartStreamOptions::listener
AudioIOListener * listener
Definition: AudioIO.h:139
Mixer
Functions for doing the mixdown of the tracks.
Definition: Mix.h:80
AudioIOStartStreamOptions::cutPreviewGapLen
double cutPreviewGapLen
Definition: AudioIO.h:143
AudioIOStartStreamOptions::pStartTime
double * pStartTime
Definition: AudioIO.h:144
TransportTracks::captureTracks
WaveTrackArray captureTracks
Definition: AudioIO.h:160
AudioIOStartStreamOptions::preRoll
double preRoll
Definition: AudioIO.h:145
NoteTrack
A Track that is used for Midi notes. (Somewhat old code).
AudioThread
Defined different on Mac and other platforms (on Mac it does not use wxWidgets wxThread), this class sits in a thread loop reading and writing audio.
Definition: AudioIO.cpp:901