Audacity 3.2.0
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 "AudioIOBase.h" // to inherit
17#include "AudioIOSequences.h"
18#include "PlaybackSchedule.h" // member variable
19
20#include <functional>
21#include <memory>
22#include <mutex>
23#include <thread>
24#include <utility>
25#include <wx/atomic.h> // member variable
26
27#include "PluginProvider.h" // for PluginID
28#include "Observer.h"
29#include "SampleCount.h"
30#include "SampleFormat.h"
31
32class wxArrayString;
33class AudioIOBase;
34class AudioIO;
35class RingBuffer;
36class Mixer;
39class Resample;
40
41class AudacityProject;
42
43struct PaStreamCallbackTimeInfo;
44typedef unsigned long PaStreamCallbackFlags;
45typedef int PaError;
46
47namespace RealtimeEffects {
48 class ProcessingScope;
49}
50
52
53enum class Acknowledge { eNone = 0, eStart, eStop };
54
61 enum Type {
66 bool on;
67};
68
69struct AUDIO_IO_API TransportSequences final {
72 std::vector<std::shared_ptr<const OtherPlayableSequence>>
74
75 // This is a subset of playbackSequences
77};
78
102 const void *inputBuffer, void *outputBuffer,
103 unsigned long framesPerBuffer,
104 const PaStreamCallbackTimeInfo *timeInfo,
105 PaStreamCallbackFlags statusFlags, void *userData );
106
107class AudioIOExt;
108
109class AUDIO_IO_API AudioIoCallback /* not final */
110 : public AudioIOBase
111{
112public:
115
116public:
117 // This function executes in a thread spawned by the PortAudio library
118 int AudioCallback(
119 constSamplePtr inputBuffer, float *outputBuffer,
120 unsigned long framesPerBuffer,
121 const PaStreamCallbackTimeInfo *timeInfo,
122 const PaStreamCallbackFlags statusFlags, void *userData);
123
126 class AUDIO_IO_API AudioIOExtIterator {
127 public:
128 using difference_type = ptrdiff_t;
132 using iterator_category = std::forward_iterator_tag;
133
134 explicit AudioIOExtIterator( AudioIoCallback &audioIO, bool end )
135 : mIterator{ end
136 ? audioIO.mAudioIOExt.end()
137 : audioIO.mAudioIOExt.begin() }
138 {}
139 AudioIOExtIterator &operator ++ () { ++mIterator; return *this; }
140 auto operator *() const -> AudioIOExt &;
141 friend inline bool operator == (
142 const AudioIOExtIterator &xx, const AudioIOExtIterator &yy)
143 {
144 return xx.mIterator == yy.mIterator;
145 }
146 friend inline bool operator != (
147 const AudioIOExtIterator &xx, const AudioIOExtIterator &yy)
148 {
149 return !(xx == yy);
150 }
151 private:
152 std::vector<std::unique_ptr<AudioIOExtBase>>::const_iterator mIterator;
153 };
157 AudioIOExtIterator begin() const { return first; }
158 AudioIOExtIterator end() const { return second; }
159 };
160
162 return {
163 AudioIOExtIterator{ *this, false },
164 AudioIOExtIterator{ *this, true }
165 };
166 }
168
169 std::shared_ptr< AudioIOListener > GetListener() const
170 { return mListener.lock(); }
171 void SetListener( const std::shared_ptr< AudioIOListener > &listener);
172
173 // Part of the callback
174 int CallbackDoSeek();
175
176 // Part of the callback
177 void CallbackCheckCompletion(
178 int &callbackReturn, unsigned long len);
179
182 // Helpers to determine if sequences have already been faded out.
183 unsigned CountSoloingSequences();
184
185 using OldChannelGains = std::array<float, 2>;
186 bool SequenceShouldBeSilent(const PlayableSequence &ps);
188 bool SequenceHasBeenFadedOut(const OldChannelGains &gains);
189 bool AllSequencesAlreadySilent();
190
191 void CheckSoundActivatedRecordingLevel(
192 float *inputSamples,
193 unsigned long framesPerBuffer
194 );
195
199 void AddToOutputChannel( unsigned int chan, // index into gains
200 float * outputMeterFloats,
201 float * outputFloats,
202 const float * tempBuf,
203 bool drop,
204 unsigned long len,
205 const PlayableSequence &ps,
206 float &channelGain
207 );
208 bool FillOutputBuffers(
209 float *outputBuffer,
210 unsigned long framesPerBuffer,
211 float *outputMeterFloats
212 );
213 void DrainInputBuffers(
214 constSamplePtr inputBuffer,
215 unsigned long framesPerBuffer,
216 const PaStreamCallbackFlags statusFlags,
217 float * tempFloats
218 );
219 void UpdateTimePosition(
220 unsigned long framesPerBuffer
221 );
222 void DoPlaythrough(
223 constSamplePtr inputBuffer,
224 float *outputBuffer,
225 unsigned long framesPerBuffer,
226 float *outputMeterFloats
227 );
228 void SendVuInputMeterData(
229 const float *inputSamples,
230 unsigned long framesPerBuffer
231 );
232 void SendVuOutputMeterData(
233 const float *outputMeterFloats,
234 unsigned long framesPerBuffer
235 );
236
242 size_t GetCommonlyReadyPlayback();
243
244 size_t GetCommonlyWrittenForPlayback();
245
248
249#ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
250 bool mAILAActive;
251 bool mAILAClipped;
252 int mAILATotalAnalysis;
253 int mAILAAnalysisCounter;
254 double mAILAMax;
255 double mAILAGoalPoint;
256 double mAILAGoalDelta;
257 double mAILAAnalysisTime;
258 double mAILALastStartTime;
259 double mAILAChangeFactor;
260 double mAILATopLevel;
261 double mAILAAnalysisEndTime;
262 double mAILAAbsolutStartTime;
263 unsigned short mAILALastChangeType; //0 - no change, 1 - increase change, 2 - decrease change
264#endif
265
266 std::thread mAudioThread;
267 std::atomic<bool> mFinishAudioThread{ false };
268
269 std::vector<std::unique_ptr<Resample>> mResample;
270
271 using RingBuffers = std::vector<std::unique_ptr<RingBuffer>>;
277 // Old gain is used in playback in linearly interpolating
278 // the gain.
279 std::vector<OldChannelGains> mOldChannelGains;
280 // Temporary buffers, each as large as the playback buffers
281 std::vector<SampleBuffer> mScratchBuffers;
282 std::vector<float *> mScratchPointers;
283
284 std::vector<std::unique_ptr<Mixer>> mPlaybackMixers;
285
286 std::atomic<float> mMixerOutputVol{ 1.0 };
288 double mFactor;
289 unsigned long mMaxFramesOutput; // The actual number of frames output.
292
293 double mSeek;
296
300 size_t mHardwarePlaybackLatencyFrames {};
303
308
316 double mCaptureRate{};
317 unsigned long long mLostSamples{ 0 };
321
322 std::atomic<Acknowledge> mAudioThreadAcknowledge;
323
324 // Async start/stop + wait of AudioThread processing.
325 // Provided to allow more flexibility, however use with caution:
326 // never call Stop between Start and the wait for Started (and the converse)
327 void StartAudioThread();
328 void WaitForAudioThreadStarted();
329 void StopAudioThread();
330 void WaitForAudioThreadStopped();
331
332 void ProcessOnceAndWait( std::chrono::milliseconds sleepTime = std::chrono::milliseconds(50) );
333
334
335
336 std::atomic<bool> mForceFadeOut{ false };
337
339
343
344protected:
345 static size_t MinValue(
346 const RingBuffers &buffers, size_t (RingBuffer::*pmf)() const);
347
349 return mMixerOutputVol.load(std::memory_order_relaxed); }
350 void SetMixerOutputVol(float value) {
351 mMixerOutputVol.store(value, std::memory_order_relaxed); }
352
356 std::weak_ptr< AudioIOListener > mListener;
357
358 bool mUsingAlsa { false };
359 bool mUsingJack { false };
360
361 // For cacheing supported sample rates
362 static double mCachedBestRateOut;
365
366 // Serialize main thread and PortAudio thread's attempts to pause and change
367 // the state used by the third, Audio thread.
369
370public:
371 // Whether an exception (as for exhaustion of resource space) was detected
372 // in recording, and not yet cleared at the end of the procedure to stop
373 // recording.
375 { return mRecordingException; }
376
377protected:
378 // A flag tested and set in one thread, cleared in another. Perhaps
379 // this guarantee of atomicity is more cautious than necessary.
380 wxAtomicInt mRecordingException {};
382 { wxAtomicInc( mRecordingException ); }
384 { if (mRecordingException) wxAtomicDec( mRecordingException ); }
385
386 std::vector< std::pair<double, double> > mLostCaptureIntervals;
388 bool mDetectDropouts{ true };
389
390public:
391 // Pairs of starting time and duration
392 const std::vector< std::pair<double, double> > &LostCaptureIntervals()
393 { return mLostCaptureIntervals; }
394
395 // Used only for testing purposes in alpha builds
396 bool mSimulateRecordingErrors{ false };
397
398 // Whether to check the error code passed to audacityAudioCallback to
399 // detect more dropouts
400 std::atomic<bool> mDetectUpstreamDropouts{ true };
401
402protected:
403 RecordingSchedule mRecordingSchedule{};
405
406 struct TransportState;
408 std::unique_ptr<TransportState> mpTransportState;
409
410private:
417};
418
419struct PaStreamInfo;
420
421class AUDIO_IO_API AudioIO final
422 : public AudioIoCallback
423 , public Observer::Publisher<AudioIOEvent>
424{
425
426 AudioIO();
427 ~AudioIO();
428 void StartThread();
429
430public:
431 // This might return null during application startup or shutdown
432 static AudioIO *Get();
433
435
439 std::shared_ptr<RealtimeEffectState>
440 AddState(AudacityProject &project,
441 ChannelGroup *pGroup, const PluginID & id);
442
444
448 std::shared_ptr<RealtimeEffectState>
449 ReplaceState(AudacityProject &project,
450 ChannelGroup *pGroup, size_t index, const PluginID & id);
451
453 void RemoveState(AudacityProject &project,
454 ChannelGroup *pGroup,
455 std::shared_ptr<RealtimeEffectState> pState);
456
464 void StartMonitoring( const AudioIOStartStreamOptions &options );
465
480 int StartStream(const TransportSequences &sequences,
481 double t0, double t1,
482 double mixerLimit,
483 const AudioIOStartStreamOptions &options);
484
490 void StopStream() override;
493 void SeekStream(double seconds) { mSeek = seconds; }
494
495 using PostRecordingAction = std::function<void()>;
496
498
499 void CallAfterRecording(PostRecordingAction action);
500
501public:
502 wxString LastPaErrorString();
503
504 wxLongLong GetLastPlaybackTime() const { return mLastPlaybackTimeMillis; }
505 std::shared_ptr<AudacityProject> GetOwningProject() const
506 { return mOwningProject.lock(); }
507
509 void SetPaused(bool state);
510
511 /* Mixer services are always available. If no stream is running, these
512 * methods use whatever device is specified by the preferences. If a
513 * stream *is* running, naturally they manipulate the mixer associated
514 * with that stream. If no mixer is available, output is emulated and
515 * input is stuck at 1.0f (a gain is applied to output samples).
516 */
517 void SetMixer(int inputSource, float inputVolume,
518 float playbackVolume);
519 void GetMixer(int *inputSource, float *inputVolume,
520 float *playbackVolume);
527 bool InputMixerWorks();
528
533 wxArrayString GetInputSourceNames();
534
535 sampleFormat GetCaptureFormat() { return mCaptureFormat; }
536 size_t GetNumPlaybackChannels() const { return mNumPlaybackChannels; }
537 size_t GetNumCaptureChannels() const { return mNumCaptureChannels; }
538
539 // Meaning really capturing, not just pre-rolling
540 bool IsCapturing() const;
541
545 static bool ValidateDeviceNames(const wxString &play, const wxString &rec);
546
550 #ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
551 void AILAInitialize();
552 void AILADisable();
553 bool AILAIsActive();
554 void AILAProcess(double maxPeak);
555 void AILASetStartTime();
556 double AILAGetLastDecisionTime();
557 #endif
558
559 bool IsAvailable(AudacityProject &project) const;
560
571 double GetBestRate(bool capturing, bool playing, double sampleRate);
572
579 double GetStreamTime();
580
581 static void AudioThread(std::atomic<bool> &finish);
582
583 static void Init();
584 static void Deinit();
585
588 void DelayActions(bool recording);
589
590private:
591
592 bool DelayingActions() const;
593
596 void SetMeters();
597
608 bool StartPortAudioStream(const AudioIOStartStreamOptions &options,
609 unsigned int numPlaybackChannels, unsigned int numCaptureChannels);
610
611 void SetOwningProject( const std::shared_ptr<AudacityProject> &pProject );
612 void ResetOwningProject();
613
620 void SequenceBufferExchange();
621
623 void FillPlayBuffers();
624 void TransformPlayBuffers(
625 std::optional<RealtimeEffects::ProcessingScope> &scope);
626 bool ProcessPlaybackSlices(
627 std::optional<RealtimeEffects::ProcessingScope> &pScope,
628 size_t available);
629
631 void DrainRecordBuffers();
632
638 size_t GetCommonlyFreePlayback();
639
646 size_t GetCommonlyAvailCapture();
647
653 bool AllocateBuffers(
654 const AudioIOStartStreamOptions &options,
655 const TransportSequences &sequences,
656 double t0, double t1, double sampleRate);
657
661 void StartStreamCleanup(bool bOnlyBuffers = false);
662
665
666 bool mDelayingActions{ false };
667};
668
669AUDIO_IO_API extern BoolSetting SoundActivatedRecord;
670
671#endif
int audacityAudioCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
Definition: AudioIO.cpp:2525
AUDIO_IO_API BoolSetting SoundActivatedRecord
Definition: AudioIO.cpp:3357
int PaError
Definition: AudioIO.h:45
bool ValidateDeviceNames()
unsigned long PaStreamCallbackFlags
Definition: AudioIO.h:43
Acknowledge
Definition: AudioIO.h:53
std::vector< std::shared_ptr< RecordableSequence > > RecordableSequences
std::vector< std::shared_ptr< const PlayableSequence > > ConstPlayableSequences
wxString PluginID
Generalized interface for discovery of plug-ins for one protocol.
auto operator*(PffftAlignedCount x, Integral y) -> std::enable_if_t< std::is_unsigned_v< Integral > &&sizeof(Integral)<=sizeof(size_t), PffftAlignedCount >
sampleFormat
The ordering of these values with operator < agrees with the order of increasing bit width.
Definition: SampleFormat.h:30
const char * constSamplePtr
Definition: SampleFormat.h:58
const auto project
bool operator!=(const WaveTrackLocation &a, const WaveTrackLocation &b)
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
A singleton object supporting queries of the state of any active audio streams, and audio device capa...
Definition: AudioIOBase.h:102
std::vector< std::unique_ptr< AudioIOExtBase > > mAudioIOExt
Definition: AudioIOBase.h:322
AudioIO uses the PortAudio library to play and record sound.
Definition: AudioIO.h:424
std::shared_ptr< AudacityProject > GetOwningProject() const
Definition: AudioIO.h:505
std::mutex mPostRecordingActionMutex
Definition: AudioIO.h:663
PostRecordingAction mPostRecordingAction
Definition: AudioIO.h:664
size_t GetNumPlaybackChannels() const
Definition: AudioIO.h:536
void SeekStream(double seconds)
Move the playback / recording position of the current stream by the specified amount from where it is...
Definition: AudioIO.h:493
sampleFormat GetCaptureFormat()
Definition: AudioIO.h:535
wxLongLong GetLastPlaybackTime() const
Definition: AudioIO.h:504
std::function< void()> PostRecordingAction
Definition: AudioIO.h:495
size_t GetNumCaptureChannels() const
Definition: AudioIO.h:537
std::vector< std::unique_ptr< AudioIOExtBase > >::const_iterator mIterator
Definition: AudioIO.h:152
AudioIOExtIterator(AudioIoCallback &audioIO, bool end)
Definition: AudioIO.h:134
std::forward_iterator_tag iterator_category
Definition: AudioIO.h:132
AudioIoCallback is a class that implements the callback required by PortAudio. The callback needs to ...
Definition: AudioIO.h:111
std::atomic< bool > mAudioThreadSequenceBufferExchangeLoopRunning
Definition: AudioIO.h:319
static int mNextStreamToken
Definition: AudioIO.h:287
std::shared_ptr< AudioIOListener > GetListener() const
Definition: AudioIO.h:169
size_t mNumPlaybackChannels
Definition: AudioIO.h:314
bool mbMicroFades
Definition: AudioIO.h:291
double mSeek
Definition: AudioIO.h:293
std::unique_ptr< TransportState > mpTransportState
Holds some state for duration of playback or recording.
Definition: AudioIO.h:406
const std::vector< std::pair< double, double > > & LostCaptureIntervals()
Definition: AudioIO.h:392
wxMutex mSuspendAudioThread
Definition: AudioIO.h:368
AudioIOExtRange Extensions()
Definition: AudioIO.h:161
std::atomic< bool > mAudioThreadShouldCallSequenceBufferExchangeOnce
Definition: AudioIO.h:318
std::vector< std::unique_ptr< Resample > > mResample
Definition: AudioIO.h:269
float GetMixerOutputVol()
Definition: AudioIO.h:348
std::array< float, 2 > OldChannelGains
Definition: AudioIO.h:185
PlaybackSchedule mPlaybackSchedule
Definition: AudioIO.h:404
std::vector< float * > mScratchPointers
pointing into mScratchBuffers
Definition: AudioIO.h:282
std::atomic< Acknowledge > mAudioThreadAcknowledge
Definition: AudioIO.h:322
int mbHasSoloSequences
Definition: AudioIO.h:180
size_t mPlaybackSamplesToCopy
Preferred batch size for replenishing the playback RingBuffer.
Definition: AudioIO.h:298
static double mCachedBestRateOut
Definition: AudioIO.h:362
std::vector< std::unique_ptr< Mixer > > mPlaybackMixers
Definition: AudioIO.h:284
PlaybackPolicy::Duration mPlaybackRingBufferSecs
Definition: AudioIO.h:294
std::thread mAudioThread
Definition: AudioIO.h:266
int mCallbackReturn
Definition: AudioIO.h:181
std::atomic< bool > mAudioThreadSequenceBufferExchangeLoopActive
Definition: AudioIO.h:320
void ClearRecordingException()
Definition: AudioIO.h:383
long mNumPauseFrames
How many frames of zeros were output due to pauses?
Definition: AudioIO.h:247
void SetRecordingException()
Definition: AudioIO.h:381
wxLongLong mLastPlaybackTimeMillis
Definition: AudioIO.h:338
bool HasRecordingException() const
Definition: AudioIO.h:374
RingBuffers mCaptureBuffers
Definition: AudioIO.h:272
std::vector< OldChannelGains > mOldChannelGains
Definition: AudioIO.h:279
PaError mLastPaError
Definition: AudioIO.h:342
static bool mCachedBestRatePlaying
Definition: AudioIO.h:363
bool mSoftwarePlaythrough
Definition: AudioIO.h:306
RecordableSequences mCaptureSequences
Definition: AudioIO.h:273
RingBuffers mPlaybackBuffers
Definition: AudioIO.h:275
std::vector< std::unique_ptr< RingBuffer > > RingBuffers
Definition: AudioIO.h:271
unsigned long mMaxFramesOutput
Definition: AudioIO.h:289
ConstPlayableSequences mPlaybackSequences
Definition: AudioIO.h:276
double mLastRecordingOffset
Not (yet) used; should perhaps be atomic when it is.
Definition: AudioIO.h:341
size_t mPlaybackQueueMinimum
Occupancy of the queue we try to maintain, with bigger batches if needed.
Definition: AudioIO.h:302
std::weak_ptr< AudioIOListener > mListener
Definition: AudioIO.h:356
double mCaptureRingBufferSecs
Definition: AudioIO.h:295
float mSilenceLevel
Definition: AudioIO.h:310
size_t mNumCaptureChannels
Definition: AudioIO.h:312
void SetMixerOutputVol(float value)
Definition: AudioIO.h:350
std::vector< std::pair< double, double > > mLostCaptureIntervals
Definition: AudioIO.h:386
bool mPauseRec
True if Sound Activated Recording is enabled.
Definition: AudioIO.h:309
double mFactor
Definition: AudioIO.h:288
double mMinCaptureSecsToCopy
Definition: AudioIO.h:304
std::vector< SampleBuffer > mScratchBuffers
Definition: AudioIO.h:281
static bool mCachedBestRateCapturing
Definition: AudioIO.h:364
sampleFormat mCaptureFormat
Definition: AudioIO.h:315
This specialization of Setting for bool adds a Toggle method to negate the saved value.
Definition: Prefs.h:346
Functions for doing the mixdown of the tracks.
Definition: Mix.h:27
An object that sends messages to an open-ended list of subscribed callbacks.
Definition: Observer.h:108
This is defined just to enable dynamic_cast on it.
std::chrono::duration< double > Duration
Brackets one block of processing in one thread.
Interface to libsoxr.
Definition: Resample.h:27
Holds streamed audio samples.
Definition: RingBuffer.h:17
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:196
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:150
static CommandContext::TargetFactory::SubstituteInUnique< InteractiveOutputTargets > scope
bool on
Definition: AudioIO.h:66
enum AudioIOEvent::Type type
AudacityProject * pProject
Definition: AudioIO.h:60
struct holding stream options, including a pointer to the time warp info and AudioIOListener and whet...
Definition: AudioIOBase.h:44
AudioIOExtIterator begin() const
Definition: AudioIO.h:157
AudioIOExtIterator end() const
Definition: AudioIO.h:158
AudioIOExtIterator first
Definition: AudioIO.h:155
AudioIOExtIterator second
Definition: AudioIO.h:156
RecordableSequences captureSequences
Definition: AudioIO.h:71
ConstPlayableSequences prerollSequences
Definition: AudioIO.h:76
std::vector< std::shared_ptr< const OtherPlayableSequence > > otherPlayableSequences
Definition: AudioIO.h:73
ConstPlayableSequences playbackSequences
Definition: AudioIO.h:70