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
438 std::shared_ptr<RealtimeEffectState>
439 AddState(AudacityProject &project,
440 ChannelGroup *pGroup, const PluginID & id);
441
443
446 std::shared_ptr<RealtimeEffectState>
447 ReplaceState(AudacityProject &project,
448 ChannelGroup *pGroup, size_t index, const PluginID & id);
449
451 void RemoveState(AudacityProject &project,
452 ChannelGroup *pGroup,
453 std::shared_ptr<RealtimeEffectState> pState);
454
462 void StartMonitoring( const AudioIOStartStreamOptions &options );
463
477 int StartStream(const TransportSequences &sequences,
478 double t0, double t1,
479 double mixerLimit,
480 const AudioIOStartStreamOptions &options);
481
487 void StopStream() override;
490 void SeekStream(double seconds) { mSeek = seconds; }
491
492 using PostRecordingAction = std::function<void()>;
493
495
496 void CallAfterRecording(PostRecordingAction action);
497
498public:
499 wxString LastPaErrorString();
500
501 wxLongLong GetLastPlaybackTime() const { return mLastPlaybackTimeMillis; }
502 std::shared_ptr<AudacityProject> GetOwningProject() const
503 { return mOwningProject.lock(); }
504
506 void SetPaused(bool state);
507
508 /* Mixer services are always available. If no stream is running, these
509 * methods use whatever device is specified by the preferences. If a
510 * stream *is* running, naturally they manipulate the mixer associated
511 * with that stream. If no mixer is available, output is emulated and
512 * input is stuck at 1.0f (a gain is applied to output samples).
513 */
514 void SetMixer(int inputSource, float inputVolume,
515 float playbackVolume);
516 void GetMixer(int *inputSource, float *inputVolume,
517 float *playbackVolume);
524 bool InputMixerWorks();
525
530 wxArrayString GetInputSourceNames();
531
532 sampleFormat GetCaptureFormat() { return mCaptureFormat; }
533 size_t GetNumPlaybackChannels() const { return mNumPlaybackChannels; }
534 size_t GetNumCaptureChannels() const { return mNumCaptureChannels; }
535
536 // Meaning really capturing, not just pre-rolling
537 bool IsCapturing() const;
538
542 static bool ValidateDeviceNames(const wxString &play, const wxString &rec);
543
547 #ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
548 void AILAInitialize();
549 void AILADisable();
550 bool AILAIsActive();
551 void AILAProcess(double maxPeak);
552 void AILASetStartTime();
553 double AILAGetLastDecisionTime();
554 #endif
555
556 bool IsAvailable(AudacityProject &project) const;
557
568 double GetBestRate(bool capturing, bool playing, double sampleRate);
569
576 double GetStreamTime();
577
578 static void AudioThread(std::atomic<bool> &finish);
579
580 static void Init();
581 static void Deinit();
582
585 void DelayActions(bool recording);
586
587private:
588
589 bool DelayingActions() const;
590
593 void SetMeters();
594
605 bool StartPortAudioStream(const AudioIOStartStreamOptions &options,
606 unsigned int numPlaybackChannels, unsigned int numCaptureChannels);
607
608 void SetOwningProject( const std::shared_ptr<AudacityProject> &pProject );
609 void ResetOwningProject();
610
617 void SequenceBufferExchange();
618
620 void FillPlayBuffers();
621 void TransformPlayBuffers(
622 std::optional<RealtimeEffects::ProcessingScope> &scope);
623 bool ProcessPlaybackSlices(
624 std::optional<RealtimeEffects::ProcessingScope> &pScope,
625 size_t available);
626
628 void DrainRecordBuffers();
629
635 size_t GetCommonlyFreePlayback();
636
643 size_t GetCommonlyAvailCapture();
644
650 bool AllocateBuffers(
651 const AudioIOStartStreamOptions &options,
652 const TransportSequences &sequences,
653 double t0, double t1, double sampleRate);
654
658 void StartStreamCleanup(bool bOnlyBuffers = false);
659
662
663 bool mDelayingActions{ false };
664};
665
666AUDIO_IO_API extern BoolSetting SoundActivatedRecord;
667
668#endif
int audacityAudioCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
Definition: AudioIO.cpp:2522
AUDIO_IO_API BoolSetting SoundActivatedRecord
Definition: AudioIO.cpp:3354
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:502
std::mutex mPostRecordingActionMutex
Definition: AudioIO.h:660
PostRecordingAction mPostRecordingAction
Definition: AudioIO.h:661
size_t GetNumPlaybackChannels() const
Definition: AudioIO.h:533
void SeekStream(double seconds)
Move the playback / recording position of the current stream by the specified amount from where it is...
Definition: AudioIO.h:490
sampleFormat GetCaptureFormat()
Definition: AudioIO.h:532
wxLongLong GetLastPlaybackTime() const
Definition: AudioIO.h:501
std::function< void()> PostRecordingAction
Definition: AudioIO.h:492
size_t GetNumCaptureChannels() const
Definition: AudioIO.h:534
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:201
static CommandContext::TargetFactory::SubstituteInUnique< InteractiveOutputTargets > scope
const char * end(const char *str) noexcept
Definition: StringUtils.h:106
const char * begin(const char *str) noexcept
Definition: StringUtils.h:101
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