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#include <wx/thread.h>
27
28#include "PluginProvider.h" // for PluginID
29#include "Observer.h"
30#include "SampleCount.h"
31#include "SampleFormat.h"
32
33class wxArrayString;
34class AudioIOBase;
35class AudioIO;
36class RingBuffer;
37class Mixer;
40class Resample;
41
42class AudacityProject;
43
44struct PaStreamCallbackTimeInfo;
45typedef unsigned long PaStreamCallbackFlags;
46typedef int PaError;
47
48namespace RealtimeEffects {
49 class ProcessingScope;
50}
51
53
54enum class Acknowledge { eNone = 0, eStart, eStop };
55
62 enum Type {
68 bool on;
69};
70
71struct AUDIO_IO_API TransportSequences final {
74 std::vector<std::shared_ptr<const OtherPlayableSequence>>
76
77 // This is a subset of playbackSequences
79};
80
104 const void *inputBuffer, void *outputBuffer,
105 unsigned long framesPerBuffer,
106 const PaStreamCallbackTimeInfo *timeInfo,
107 PaStreamCallbackFlags statusFlags, void *userData );
108
109class AudioIOExt;
110
111class AUDIO_IO_API AudioIoCallback /* not final */
112 : public AudioIOBase
113{
114public:
117
118public:
119 // This function executes in a thread spawned by the PortAudio library
120 int AudioCallback(
121 constSamplePtr inputBuffer, float *outputBuffer,
122 unsigned long framesPerBuffer,
123 const PaStreamCallbackTimeInfo *timeInfo,
124 const PaStreamCallbackFlags statusFlags, void *userData);
125
128 class AUDIO_IO_API AudioIOExtIterator {
129 public:
130 using difference_type = ptrdiff_t;
134 using iterator_category = std::forward_iterator_tag;
135
136 explicit AudioIOExtIterator( AudioIoCallback &audioIO, bool end )
137 : mIterator{ end
138 ? audioIO.mAudioIOExt.end()
139 : audioIO.mAudioIOExt.begin() }
140 {}
141 AudioIOExtIterator &operator ++ () { ++mIterator; return *this; }
142 auto operator *() const -> AudioIOExt &;
143 friend inline bool operator == (
144 const AudioIOExtIterator &xx, const AudioIOExtIterator &yy)
145 {
146 return xx.mIterator == yy.mIterator;
147 }
148 friend inline bool operator != (
149 const AudioIOExtIterator &xx, const AudioIOExtIterator &yy)
150 {
151 return !(xx == yy);
152 }
153 private:
154 std::vector<std::unique_ptr<AudioIOExtBase>>::const_iterator mIterator;
155 };
159 AudioIOExtIterator begin() const { return first; }
160 AudioIOExtIterator end() const { return second; }
161 };
162
164 return {
165 AudioIOExtIterator{ *this, false },
166 AudioIOExtIterator{ *this, true }
167 };
168 }
170
171 std::shared_ptr< AudioIOListener > GetListener() const
172 { return mListener.lock(); }
173 void SetListener( const std::shared_ptr< AudioIOListener > &listener);
174
175 // Part of the callback
176 int CallbackDoSeek();
177
178 // Part of the callback
179 void CallbackCheckCompletion(
180 int &callbackReturn, unsigned long len);
181
184 // Helpers to determine if sequences have already been faded out.
185 unsigned CountSoloingSequences();
186
187 bool SequenceShouldBeSilent(const PlayableSequence &ps);
188
189 void CheckSoundActivatedRecordingLevel(
190 float *inputSamples,
191 unsigned long framesPerBuffer
192 );
193
194 bool FillOutputBuffers(
195 float *outputFloats,
196 unsigned long framesPerBuffer,
197 float *outputMeterFloats
198 );
199 void DrainInputBuffers(
200 constSamplePtr inputBuffer,
201 unsigned long framesPerBuffer,
202 const PaStreamCallbackFlags statusFlags,
203 float * tempFloats
204 );
205 void UpdateTimePosition(
206 unsigned long framesPerBuffer
207 );
208 void DoPlaythrough(
209 constSamplePtr inputBuffer,
210 float *outputBuffer,
211 unsigned long framesPerBuffer,
212 float *outputMeterFloats
213 );
214 void SendVuInputMeterData(
215 const float *inputSamples,
216 unsigned long framesPerBuffer
217 );
218 void SendVuOutputMeterData(
219 const float *outputMeterFloats,
220 unsigned long framesPerBuffer
221 );
222
228 size_t GetCommonlyReadyPlayback();
229
230 size_t GetCommonlyWrittenForPlayback();
231
234
235#ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
236 bool mAILAActive;
237 bool mAILAClipped;
238 int mAILATotalAnalysis;
239 int mAILAAnalysisCounter;
240 double mAILAMax;
241 double mAILAGoalPoint;
242 double mAILAGoalDelta;
243 double mAILAAnalysisTime;
244 double mAILALastStartTime;
245 double mAILAChangeFactor;
246 double mAILATopLevel;
247 double mAILAAnalysisEndTime;
248 double mAILAAbsolutStartTime;
249 unsigned short mAILALastChangeType; //0 - no change, 1 - increase change, 2 - decrease change
250#endif
251
252 std::thread mAudioThread;
253 std::atomic<bool> mFinishAudioThread{ false };
254
255 std::vector<std::unique_ptr<Resample>> mResample;
256
257 using RingBuffers = std::vector<std::unique_ptr<RingBuffer>>;
262 std::vector<std::vector<float>> mProcessingBuffers;
265 std::vector<std::vector<float>> mMasterBuffers;
269 // Old volume is used in playback in linearly interpolating
270 // the volume.
272 // Temporary buffers, each as large as the playback buffers
273 std::vector<SampleBuffer> mScratchBuffers;
274 std::vector<float *> mScratchPointers;
275
276 std::vector<std::unique_ptr<Mixer>> mPlaybackMixers;
277
278 std::atomic<float> mMixerOutputVol{ 1.0 };
280 double mFactor;
281 unsigned long mMaxFramesOutput; // The actual number of frames output.
284
285 double mSeek;
288
292 size_t mHardwarePlaybackLatencyFrames {};
295
300
308 double mCaptureRate{};
309 unsigned long long mLostSamples{ 0 };
313
314 std::atomic<Acknowledge> mAudioThreadAcknowledge;
315
316 // Async start/stop + wait of AudioThread processing.
317 // Provided to allow more flexibility, however use with caution:
318 // never call Stop between Start and the wait for Started (and the converse)
319 void StartAudioThread();
320 void WaitForAudioThreadStarted();
321 void StopAudioThread();
322 void WaitForAudioThreadStopped();
323
324 void ProcessOnceAndWait( std::chrono::milliseconds sleepTime = std::chrono::milliseconds(50) );
325
326
327
328 std::atomic<bool> mForceFadeOut{ false };
329
331
335
336protected:
337 static size_t MinValue(
338 const RingBuffers &buffers, size_t (RingBuffer::*pmf)() const);
339
341 return mMixerOutputVol.load(std::memory_order_relaxed); }
342 void SetMixerOutputVol(float value) {
343 mMixerOutputVol.store(value, std::memory_order_relaxed); }
344
348 std::weak_ptr< AudioIOListener > mListener;
349
350 bool mUsingAlsa { false };
351 bool mUsingJack { false };
352
353 // For cacheing supported sample rates
354 static double mCachedBestRateOut;
357
358 // Serialize main thread and PortAudio thread's attempts to pause and change
359 // the state used by the third, Audio thread.
361
362public:
363 // Whether an exception (as for exhaustion of resource space) was detected
364 // in recording, and not yet cleared at the end of the procedure to stop
365 // recording.
367 { return mRecordingException; }
368
369protected:
370 // A flag tested and set in one thread, cleared in another. Perhaps
371 // this guarantee of atomicity is more cautious than necessary.
372 wxAtomicInt mRecordingException {};
374 { wxAtomicInc( mRecordingException ); }
376 { if (mRecordingException) wxAtomicDec( mRecordingException ); }
377
378 std::vector< std::pair<double, double> > mLostCaptureIntervals;
380 bool mDetectDropouts{ true };
381
382public:
383 // Pairs of starting time and duration
384 const std::vector< std::pair<double, double> > &LostCaptureIntervals()
385 { return mLostCaptureIntervals; }
386
387 // Used only for testing purposes in alpha builds
388 bool mSimulateRecordingErrors{ false };
389
390 // Whether to check the error code passed to audacityAudioCallback to
391 // detect more dropouts
392 std::atomic<bool> mDetectUpstreamDropouts{ true };
393
394protected:
395 RecordingSchedule mRecordingSchedule{};
397
398 struct TransportState;
400 std::unique_ptr<TransportState> mpTransportState;
401
402private:
409};
410
411struct PaStreamInfo;
412
413class AUDIO_IO_API AudioIO final
414 : public AudioIoCallback
415 , public Observer::Publisher<AudioIOEvent>
416{
417
418 AudioIO();
419 ~AudioIO();
420 void StartThread();
421
422public:
423 // This might return null during application startup or shutdown
424 static AudioIO *Get();
425
427
430 std::shared_ptr<RealtimeEffectState>
431 AddState(AudacityProject &project,
432 ChannelGroup *pGroup, const PluginID & id);
433
435
438 std::shared_ptr<RealtimeEffectState>
439 ReplaceState(AudacityProject &project,
440 ChannelGroup *pGroup, size_t index, const PluginID & id);
441
443 void RemoveState(AudacityProject &project,
444 ChannelGroup *pGroup,
445 std::shared_ptr<RealtimeEffectState> pState);
446
454 void StartMonitoring( const AudioIOStartStreamOptions &options );
455
469 int StartStream(const TransportSequences &sequences,
470 double t0, double t1,
471 double mixerLimit,
472 const AudioIOStartStreamOptions &options);
473
479 void StopStream() override;
482 void SeekStream(double seconds) { mSeek = seconds; }
483
484 using PostRecordingAction = std::function<void()>;
485
487
488 void CallAfterRecording(PostRecordingAction action);
489
490public:
491 wxString LastPaErrorString();
492
493 wxLongLong GetLastPlaybackTime() const { return mLastPlaybackTimeMillis; }
494 std::shared_ptr<AudacityProject> GetOwningProject() const
495 { return mOwningProject.lock(); }
496
498 void SetPaused(bool state, bool publish = false);
499
500 /* Mixer services are always available. If no stream is running, these
501 * methods use whatever device is specified by the preferences. If a
502 * stream *is* running, naturally they manipulate the mixer associated
503 * with that stream. If no mixer is available, output is emulated and
504 * input is stuck at 1.0f (a volume gain is applied to output samples).
505 */
506 void SetMixer(int inputSource, float inputVolume,
507 float playbackVolume);
508 void GetMixer(int *inputSource, float *inputVolume,
509 float *playbackVolume);
516 bool InputMixerWorks();
517
522 wxArrayString GetInputSourceNames();
523
524 sampleFormat GetCaptureFormat() { return mCaptureFormat; }
525 size_t GetNumPlaybackChannels() const { return mNumPlaybackChannels; }
526 size_t GetNumCaptureChannels() const { return mNumCaptureChannels; }
527
528 // Meaning really capturing, not just pre-rolling
529 bool IsCapturing() const;
530
534 static bool ValidateDeviceNames(const wxString &play, const wxString &rec);
535
539 #ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
540 void AILAInitialize();
541 void AILADisable();
542 bool AILAIsActive();
543 void AILAProcess(double maxPeak);
544 void AILASetStartTime();
545 double AILAGetLastDecisionTime();
546 #endif
547
548 bool IsAvailable(AudacityProject &project) const;
549
560 double GetBestRate(bool capturing, bool playing, double sampleRate);
561
568 double GetStreamTime();
569
570 static void AudioThread(std::atomic<bool> &finish);
571
572 static void Init();
573 static void Deinit();
574
577 void DelayActions(bool recording);
578
579private:
580
581 bool DelayingActions() const;
582
585 void SetMeters();
586
597 bool StartPortAudioStream(const AudioIOStartStreamOptions &options,
598 unsigned int numPlaybackChannels, unsigned int numCaptureChannels);
599
600 void SetOwningProject( const std::shared_ptr<AudacityProject> &pProject );
601 void ResetOwningProject();
602
609 void SequenceBufferExchange();
610
612 void FillPlayBuffers();
613
614 bool ProcessPlaybackSlices(
615 std::optional<RealtimeEffects::ProcessingScope> &pScope,
616 size_t available);
617
619 void DrainRecordBuffers();
620
626 size_t GetCommonlyFreePlayback();
627
634 size_t GetCommonlyAvailCapture();
635
641 bool AllocateBuffers(
642 const AudioIOStartStreamOptions &options,
643 const TransportSequences &sequences,
644 double t0, double t1, double sampleRate);
645
649 void StartStreamCleanup(bool bOnlyBuffers = false);
650
653
654 bool mDelayingActions{ false };
655};
656
657AUDIO_IO_API extern BoolSetting SoundActivatedRecord;
658
659#endif
int audacityAudioCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
Definition: AudioIO.cpp:2617
AUDIO_IO_API BoolSetting SoundActivatedRecord
Definition: AudioIO.cpp:3370
int PaError
Definition: AudioIO.h:46
bool ValidateDeviceNames()
unsigned long PaStreamCallbackFlags
Definition: AudioIO.h:44
Acknowledge
Definition: AudioIO.h:54
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:104
std::vector< std::unique_ptr< AudioIOExtBase > > mAudioIOExt
Definition: AudioIOBase.h:381
AudioIO uses the PortAudio library to play and record sound.
Definition: AudioIO.h:416
std::shared_ptr< AudacityProject > GetOwningProject() const
Definition: AudioIO.h:494
std::mutex mPostRecordingActionMutex
Definition: AudioIO.h:651
PostRecordingAction mPostRecordingAction
Definition: AudioIO.h:652
size_t GetNumPlaybackChannels() const
Definition: AudioIO.h:525
void SeekStream(double seconds)
Move the playback / recording position of the current stream by the specified amount from where it is...
Definition: AudioIO.h:482
sampleFormat GetCaptureFormat()
Definition: AudioIO.h:524
wxLongLong GetLastPlaybackTime() const
Definition: AudioIO.h:493
std::function< void()> PostRecordingAction
Definition: AudioIO.h:484
size_t GetNumCaptureChannels() const
Definition: AudioIO.h:526
std::vector< std::unique_ptr< AudioIOExtBase > >::const_iterator mIterator
Definition: AudioIO.h:154
AudioIOExtIterator(AudioIoCallback &audioIO, bool end)
Definition: AudioIO.h:136
std::forward_iterator_tag iterator_category
Definition: AudioIO.h:134
AudioIoCallback is a class that implements the callback required by PortAudio. The callback needs to ...
Definition: AudioIO.h:113
std::atomic< bool > mAudioThreadSequenceBufferExchangeLoopRunning
Definition: AudioIO.h:311
static int mNextStreamToken
Definition: AudioIO.h:279
std::shared_ptr< AudioIOListener > GetListener() const
Definition: AudioIO.h:171
size_t mNumPlaybackChannels
Definition: AudioIO.h:306
bool mbMicroFades
Definition: AudioIO.h:283
double mSeek
Definition: AudioIO.h:285
std::unique_ptr< TransportState > mpTransportState
Holds some state for duration of playback or recording.
Definition: AudioIO.h:398
const std::vector< std::pair< double, double > > & LostCaptureIntervals()
Definition: AudioIO.h:384
wxMutex mSuspendAudioThread
Definition: AudioIO.h:360
AudioIOExtRange Extensions()
Definition: AudioIO.h:163
std::atomic< bool > mAudioThreadShouldCallSequenceBufferExchangeOnce
Definition: AudioIO.h:310
std::vector< std::unique_ptr< Resample > > mResample
Definition: AudioIO.h:255
float GetMixerOutputVol()
Definition: AudioIO.h:340
PlaybackSchedule mPlaybackSchedule
Definition: AudioIO.h:396
std::vector< float * > mScratchPointers
pointing into mScratchBuffers
Definition: AudioIO.h:274
std::atomic< Acknowledge > mAudioThreadAcknowledge
Definition: AudioIO.h:314
int mbHasSoloSequences
Definition: AudioIO.h:182
size_t mPlaybackSamplesToCopy
Preferred batch size for replenishing the playback RingBuffer.
Definition: AudioIO.h:290
static double mCachedBestRateOut
Definition: AudioIO.h:354
std::vector< std::unique_ptr< Mixer > > mPlaybackMixers
Definition: AudioIO.h:276
PlaybackPolicy::Duration mPlaybackRingBufferSecs
Definition: AudioIO.h:286
std::vector< std::vector< float > > mProcessingBuffers
Definition: AudioIO.h:262
std::thread mAudioThread
Definition: AudioIO.h:252
int mCallbackReturn
Definition: AudioIO.h:183
std::atomic< bool > mAudioThreadSequenceBufferExchangeLoopActive
Definition: AudioIO.h:312
void ClearRecordingException()
Definition: AudioIO.h:375
long mNumPauseFrames
How many frames of zeros were output due to pauses?
Definition: AudioIO.h:233
void SetRecordingException()
Definition: AudioIO.h:373
wxLongLong mLastPlaybackTimeMillis
Definition: AudioIO.h:330
bool HasRecordingException() const
Definition: AudioIO.h:366
RingBuffers mCaptureBuffers
Definition: AudioIO.h:258
PaError mLastPaError
Definition: AudioIO.h:334
static bool mCachedBestRatePlaying
Definition: AudioIO.h:355
bool mSoftwarePlaythrough
Definition: AudioIO.h:298
RecordableSequences mCaptureSequences
Definition: AudioIO.h:259
RingBuffers mPlaybackBuffers
Definition: AudioIO.h:267
float mOldPlaybackVolume
Definition: AudioIO.h:271
std::vector< std::unique_ptr< RingBuffer > > RingBuffers
Definition: AudioIO.h:257
unsigned long mMaxFramesOutput
Definition: AudioIO.h:281
ConstPlayableSequences mPlaybackSequences
Definition: AudioIO.h:268
double mLastRecordingOffset
Not (yet) used; should perhaps be atomic when it is.
Definition: AudioIO.h:333
size_t mPlaybackQueueMinimum
Occupancy of the queue we try to maintain, with bigger batches if needed.
Definition: AudioIO.h:294
std::weak_ptr< AudioIOListener > mListener
Definition: AudioIO.h:348
double mCaptureRingBufferSecs
Definition: AudioIO.h:287
float mSilenceLevel
Definition: AudioIO.h:302
size_t mNumCaptureChannels
Definition: AudioIO.h:304
void SetMixerOutputVol(float value)
Definition: AudioIO.h:342
std::vector< std::vector< float > > mMasterBuffers
Definition: AudioIO.h:265
std::vector< std::pair< double, double > > mLostCaptureIntervals
Definition: AudioIO.h:378
bool mPauseRec
True if Sound Activated Recording is enabled.
Definition: AudioIO.h:301
double mFactor
Definition: AudioIO.h:280
double mMinCaptureSecsToCopy
Definition: AudioIO.h:296
std::vector< SampleBuffer > mScratchBuffers
Definition: AudioIO.h:273
static bool mCachedBestRateCapturing
Definition: AudioIO.h:356
sampleFormat mCaptureFormat
Definition: AudioIO.h:307
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:31
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:202
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:68
enum AudioIOEvent::Type type
AudacityProject * pProject
Definition: AudioIO.h:61
struct holding stream options, including a pointer to the time warp info and AudioIOListener and whet...
Definition: AudioIOBase.h:46
AudioIOExtIterator begin() const
Definition: AudioIO.h:159
AudioIOExtIterator end() const
Definition: AudioIO.h:160
AudioIOExtIterator first
Definition: AudioIO.h:157
AudioIOExtIterator second
Definition: AudioIO.h:158
RecordableSequences captureSequences
Definition: AudioIO.h:73
ConstPlayableSequences prerollSequences
Definition: AudioIO.h:78
std::vector< std::shared_ptr< const OtherPlayableSequence > > otherPlayableSequences
Definition: AudioIO.h:75
ConstPlayableSequences playbackSequences
Definition: AudioIO.h:72