Audacity  2.2.2
Classes | Macros | Enumerations | Functions | Variables
AudioIO.cpp File Reference
#include "Audacity.h"
#include "Experimental.h"
#include "AudioIO.h"
#include "float_cast.h"
#include <cfloat>
#include <math.h>
#include <stdlib.h>
#include <algorithm>
#include <wx/log.h>
#include <wx/textctrl.h>
#include <wx/timer.h>
#include <wx/intl.h>
#include <wx/debug.h>
#include <wx/sstream.h>
#include <wx/txtstrm.h>
#include "AudacityApp.h"
#include "AudacityException.h"
#include "Mix.h"
#include "MixerBoard.h"
#include "Resample.h"
#include "RingBuffer.h"
#include "prefs/GUISettings.h"
#include "Prefs.h"
#include "Project.h"
#include "TimeTrack.h"
#include "WaveTrack.h"
#include "AutoRecovery.h"
#include "prefs/QualityPrefs.h"
#include "toolbars/ControlToolBar.h"
#include "widgets/Meter.h"
#include "widgets/ErrorDialog.h"
#include "widgets/Warning.h"
#include "tracks/ui/Scrubbing.h"

Go to the source code of this file.

Classes

struct  AudioIO::ScrubQueue
 
struct  AudioIO::ScrubQueue::Entry
 
struct  AudioIO::ScrubQueue::Duration
 
class  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. More...
 

Macros

#define MAX(a, b)   ((a) > (b) ? (a) : (b))
 
#define ORIGINAL_DO_NOT_PLAY_ALL_MUTED_TRACKS_TO_END
 

Enumerations

enum  { MIDI_MINIMAL_LATENCY_MS = 1 }
 

Functions

 wxDEFINE_EVENT (EVT_AUDIOIO_PLAYBACK, wxCommandEvent)
 
 wxDEFINE_EVENT (EVT_AUDIOIO_CAPTURE, wxCommandEvent)
 
 wxDEFINE_EVENT (EVT_AUDIOIO_MONITOR, wxCommandEvent)
 
int audacityAudioCallback (const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
 
void InitAudioIO ()
 
void DeinitAudioIO ()
 
wxString DeviceName (const PaDeviceInfo *info)
 
wxString HostName (const PaDeviceInfo *info)
 
static PaSampleFormat AudacityToPortAudioSampleFormat (sampleFormat format)
 
static void DoSoftwarePlaythrough (const void *inputBuffer, sampleFormat inputFormat, unsigned inputChannels, float *outputBuffer, int len)
 
int audacityAudioCallback (const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *WXUNUSED(timeInfo), const PaStreamCallbackFlags statusFlags, void *WXUNUSED(userData))
 

Variables

std::unique_ptr< AudioIOugAudioIO
 
AudioIOgAudioIO {}
 

Macro Definition Documentation

#define MAX (   a,
 
)    ((a) > (b) ? (a) : (b))

Definition at line 4700 of file AudioIO.cpp.

Referenced by audacityAudioCallback().

#define ORIGINAL_DO_NOT_PLAY_ALL_MUTED_TRACKS_TO_END

Enumeration Type Documentation

anonymous enum
Enumerator
MIDI_MINIMAL_LATENCY_MS 

Definition at line 498 of file AudioIO.cpp.

498  {
499  // This is the least positive latency we can
500  // specify to Pm_OpenOutput, 1 ms, which prevents immediate
501  // scheduling of events:
503 };

Function Documentation

int audacityAudioCallback ( const void *  inputBuffer,
void *  outputBuffer,
unsigned long  framesPerBuffer,
const PaStreamCallbackTimeInfo *  timeInfo,
PaStreamCallbackFlags  statusFlags,
void *  userData 
)

brief The function which is called from PortAudio's callback thread context to collect and deliver audio for / from the sound device.

This covers recording, playback, and doing both simultaneously. It is also invoked to do monitoring and software playthrough. Note that dealing with the two buffers needs some care to ensure that the right things happen for all possible cases.

Parameters
inputBufferBuffer of length framesPerBuffer containing samples from the sound card, or null if not capturing audio. Note that the data type will depend on the format of audio data that was chosen when the stream was created (so could be floats or various integers)
outputBufferUninitialised buffer of length framesPerBuffer which will be sent to the sound card after the callback, or null if not playing audio back.
framesPerBufferThe length of the playback and recording buffers
PaStreamCallbackTimeInfoPointer to PortAudio time information structure, which tells us how long we have been playing / recording
statusFlagsPortAudio stream status flags
userDatapointer to user-defined data structure. Provided for flexibility by PortAudio, but not used by Audacity - the data is stored in the AudioIO class instead.
int audacityAudioCallback ( const void *  inputBuffer,
void *  outputBuffer,
unsigned long  framesPerBuffer,
const PaStreamCallbackTimeInfo *  WXUNUSEDtimeInfo,
const PaStreamCallbackFlags  statusFlags,
void *  WXUNUSEDuserData 
)

Definition at line 4723 of file AudioIO.cpp.

References ClearSamples(), TimeTrack::ComputeWarpedLength(), CopySamples(), DoSoftwarePlaythrough(), floatSample, gAudioIO, EffectManager::Get(), GetActiveProject(), WaveTrack::GetChannel(), WaveTrack::GetChannelGain(), AudacityProject::GetControlToolBar(), Track::GetLinked(), PlayableTrack::GetMute(), Track::GetSelected(), PlayableTrack::GetSolo(), if(), int16Sample, int24Sample, MeterPanel::IsMeterDisabled(), AudioIO::IsPaused(), Track::LeftChannel, AudioIO::LimitStreamTime(), AudioIO::mAudioThreadFillBuffersLoopActive, AudioIO::mAudioThreadFillBuffersLoopRunning, AudioIO::mAudioThreadShouldCallFillBuffersOnce, MAX, AudioIO::mCaptureBuffers, AudioIO::mCaptureFormat, AudioIO::mDetectDropouts, AudioIO::mDetectUpstreamDropouts, AudioIO::mEmulateMixerOutputVol, min(), AudioIO::mInputMeter, AudioIO::mLastPlaybackTimeMillis, AudioIO::mLastRecordingOffset, AudioIO::RecordingSchedule::mLatencyCorrection, AudioIO::mLostCaptureIntervals, AudioIO::mLostSamples, AudioIO::mMixerOutputVol, AudioIO::mNumCaptureChannels, AudioIO::mNumPlaybackChannels, Track::MonoChannel, AudioIO::mOutputMeter, AudioIO::mPaused, AudioIO::mPauseRec, AudioIO::mPlaybackBuffers, AudioIO::mPlaybackMixers, AudioIO::mPlaybackTracks, AudioIO::mPlayMode, AudioIO::mPortStreamV19, AudioIO::mRate, AudioIO::mRecordingSchedule, AudioIO::mScrubQueue, AudioIO::mSeek, AudioIO::mSilenceLevel, AudioIO::mSimulateRecordingErrors, AudioIO::mSoftwarePlaythrough, AudioIO::mStreamToken, AudioIO::mSuspendAudioThread, AudioIO::mT0, AudioIO::mT1, AudioIO::mTime, AudioIO::mTimeTrack, AudioIO::mUpdateMeters, AudioIO::mUpdatingMeters, AudioIO::mUsingAlsa, AudioIO::mWarpedTime, ControlToolBar::Pause(), AudioIO::PLAY_LOOPED, AudioIO::PLAY_SCRUB, AudioIO::PLAY_STRAIGHT, EffectManager::RealtimeProcess(), EffectManager::RealtimeProcessEnd(), EffectManager::RealtimeProcessStart(), AudioIO::ReversedTime(), Track::RightChannel, TimeTrack::SolveWarpedLength(), MeterPanel::UpdateDisplay(), and USE_MIDI_THREAD.

4734 {
4735  auto numPlaybackChannels = gAudioIO->mNumPlaybackChannels;
4736  auto numPlaybackTracks = gAudioIO->mPlaybackTracks.size();
4737  auto numCaptureChannels = gAudioIO->mNumCaptureChannels;
4738  int callbackReturn = paContinue;
4739  void *tempBuffer = alloca(framesPerBuffer*sizeof(float)*
4740  MAX(numCaptureChannels,numPlaybackChannels));
4741  float *tempFloats = (float*)tempBuffer;
4742 
4743  // output meter may need samples untouched by volume emulation
4744  float *outputMeterFloats;
4745  outputMeterFloats =
4746  (outputBuffer && gAudioIO->mEmulateMixerOutputVol &&
4747  gAudioIO->mMixerOutputVol != 1.0) ?
4748  (float *)alloca(framesPerBuffer*numPlaybackChannels * sizeof(float)) :
4749  (float *)outputBuffer;
4750 
4751 #ifdef EXPERIMENTAL_MIDI_OUT
4752  if (gAudioIO->mCallbackCount++ == 0) {
4753  // This is effectively mSystemMinusAudioTime when the buffer is empty:
4754  gAudioIO->mStartTime = SystemTime(gAudioIO->mUsingAlsa) - gAudioIO->mT0;
4755  // later, mStartTime - mSystemMinusAudioTime will tell us latency
4756  }
4757 
4758  /* GSW: Save timeInfo in case MidiPlayback needs it */
4759  gAudioIO->mAudioCallbackClockTime = PaUtil_GetTime();
4760 
4761  /* for Linux, estimate a smooth audio time as a slowly-changing
4762  offset from system time */
4763  // rnow is system time as a double to simplify math
4764  double rnow = SystemTime(gAudioIO->mUsingAlsa);
4765  // anow is next-sample-to-be-computed audio time as a double
4766  double anow = gAudioIO->AudioTime();
4767 
4768  if (gAudioIO->mUsingAlsa) {
4769  // timeInfo's fields are not all reliable.
4770 
4771  // enow is audio time estimated from our clock synchronization protocol,
4772  // which produces mSystemMinusAudioTime. But we want the estimate
4773  // to drift low, so we steadily increase mSystemMinusAudioTime to
4774  // simulate a fast system clock or a slow audio clock. If anow > enow,
4775  // we'll update mSystemMinusAudioTime to keep in sync. (You might think
4776  // we could just use anow as the "truth", but it has a lot of jitter,
4777  // so we are using enow to smooth out this jitter, in fact to < 1ms.)
4778  // Add worst-case clock drift using previous framesPerBuffer:
4779  const auto increase =
4780  gAudioIO->mAudioFramesPerBuffer * 0.0002 / gAudioIO->mRate;
4781  gAudioIO->mSystemMinusAudioTime += increase;
4782  gAudioIO->mSystemMinusAudioTimePlusLatency += increase;
4783  double enow = rnow - gAudioIO->mSystemMinusAudioTime;
4784 
4785 
4786  // now, use anow instead if it is ahead of enow
4787  if (anow > enow) {
4788  gAudioIO->mSystemMinusAudioTime = rnow - anow;
4789  // Update our mAudioOutLatency estimate during the first 20 callbacks.
4790  // During this period, the buffer should fill. Once we have a good
4791  // estimate of mSystemMinusAudioTime (expected in fewer than 20 callbacks)
4792  // we want to stop the updating in case there is clock drift, which would
4793  // cause the mAudioOutLatency estimation to drift as well. The clock drift
4794  // in the first 20 callbacks should be negligible, however.
4795  if (gAudioIO->mCallbackCount < 20) {
4796  gAudioIO->mAudioOutLatency = gAudioIO->mStartTime -
4797  gAudioIO->mSystemMinusAudioTime;
4798  }
4799  gAudioIO->mSystemMinusAudioTimePlusLatency =
4800  gAudioIO->mSystemMinusAudioTime + gAudioIO->mAudioOutLatency;
4801  }
4802  }
4803  else {
4804  // If not using Alsa, rely on timeInfo to have meaningful values that are
4805  // more precise than the output latency value reported at stream start.
4806  gAudioIO->mSystemMinusAudioTime = rnow - anow;
4807  gAudioIO->mSystemMinusAudioTimePlusLatency =
4808  gAudioIO->mSystemMinusAudioTime +
4809  (timeInfo->outputBufferDacTime - timeInfo->currentTime);
4810  }
4811 
4812  gAudioIO->mAudioFramesPerBuffer = framesPerBuffer;
4813  if (gAudioIO->IsPaused()
4814  // PRL: Why was this added? Was it only because of the mysterious
4815  // initial leading zeroes, now solved by setting mStreamToken early?
4816  || gAudioIO->mStreamToken <= 0
4817  )
4818  gAudioIO->mNumPauseFrames += framesPerBuffer;
4819 
4820  // PRL: Note that when there is a separate MIDI thread, it is effectively
4821  // blocked until the first visit to this line during a playback, and will
4822  // not read gAudioIO->mSystemMinusAudioTimePlusLatency sooner:
4823  gAudioIO->mNumFrames += framesPerBuffer;
4824 
4825 #ifndef USE_MIDI_THREAD
4826  if (gAudioIO->mMidiStream)
4827  gAudioIO->FillMidiBuffers();
4828 #endif
4829 
4830 #endif
4831 
4832  unsigned int i;
4833 
4834  /* Send data to recording VU meter if applicable */
4835 
4836  if (gAudioIO->mInputMeter &&
4837  !gAudioIO->mInputMeter->IsMeterDisabled() &&
4838  inputBuffer) {
4839  // get here if meters are actually live , and being updated
4840  /* It's critical that we don't update the meters while StopStream is
4841  * trying to stop PortAudio, otherwise it can lead to a freeze. We use
4842  * two variables to synchronize:
4843  * mUpdatingMeters tells StopStream when the callback is about to enter
4844  * the code where it might update the meters, and
4845  * mUpdateMeters is how the rest of the code tells the callback when it
4846  * is allowed to actually do the updating.
4847  * Note that mUpdatingMeters must be set first to avoid a race condition.
4848  */
4849  gAudioIO->mUpdatingMeters = true;
4850  if (gAudioIO->mUpdateMeters) {
4852  gAudioIO->mInputMeter->UpdateDisplay(numCaptureChannels,
4853  framesPerBuffer,
4854  (float *)inputBuffer);
4855  else {
4857  (samplePtr)tempFloats, floatSample,
4858  framesPerBuffer * numCaptureChannels);
4859  gAudioIO->mInputMeter->UpdateDisplay(numCaptureChannels,
4860  framesPerBuffer,
4861  tempFloats);
4862  }
4863  }
4864  gAudioIO->mUpdatingMeters = false;
4865  } // end recording VU meter update
4866 
4867  // Stop recording if 'silence' is detected
4868  //
4869  // LL: We'd gotten a little "dangerous" with the control toolbar calls
4870  // here because we are not running in the main GUI thread. Eventually
4871  // the toolbar attempts to update the active project's status bar.
4872  // But, since we're not in the main thread, we can get all manner of
4873  // really weird failures. Or none at all which is even worse, since
4874  // we don't know a problem exists.
4875  //
4876  // By using CallAfter(), we can schedule the call to the toolbar
4877  // to run in the main GUI thread after the next event loop iteration.
4878  if(gAudioIO->mPauseRec && inputBuffer && gAudioIO->mInputMeter) {
4879  if(gAudioIO->mInputMeter->GetMaxPeak() < gAudioIO->mSilenceLevel ) {
4880  if(!gAudioIO->IsPaused()) {
4882  ControlToolBar *bar = p->GetControlToolBar();
4883  bar->CallAfter(&ControlToolBar::Pause);
4884  }
4885  }
4886  else {
4887  if(gAudioIO->IsPaused()) {
4889  ControlToolBar *bar = p->GetControlToolBar();
4890  bar->CallAfter(&ControlToolBar::Pause);
4891  }
4892  }
4893  }
4894  if( gAudioIO->mPaused )
4895  {
4896  if (outputBuffer && numPlaybackChannels > 0)
4897  {
4898  ClearSamples((samplePtr)outputBuffer, floatSample,
4899  0, framesPerBuffer * numPlaybackChannels);
4900 
4901  if (inputBuffer && gAudioIO->mSoftwarePlaythrough) {
4903  numCaptureChannels,
4904  (float *)outputBuffer, (int)framesPerBuffer);
4905  }
4906  }
4907 
4908  return paContinue;
4909  }
4910 
4911  if (gAudioIO->mStreamToken > 0)
4912  {
4913  //
4914  // Mix and copy to PortAudio's output buffer
4915  //
4916 
4917  if( outputBuffer && (numPlaybackChannels > 0) )
4918  {
4919  bool cut = false;
4920  bool linkFlag = false;
4921 
4922  float *outputFloats = (float *)outputBuffer;
4923  for( i = 0; i < framesPerBuffer*numPlaybackChannels; i++)
4924  outputFloats[i] = 0.0;
4925 
4926  if (inputBuffer && gAudioIO->mSoftwarePlaythrough) {
4928  numCaptureChannels,
4929  (float *)outputBuffer, (int)framesPerBuffer);
4930  }
4931 
4932  // Copy the results to outputMeterFloats if necessary
4933  if (outputMeterFloats != outputFloats) {
4934  for (i = 0; i < framesPerBuffer*numPlaybackChannels; ++i) {
4935  outputMeterFloats[i] = outputFloats[i];
4936  }
4937  }
4938 
4939 #ifdef EXPERIMENTAL_SCRUBBING_SUPPORT
4940  // While scrubbing, ignore seek requests
4942  gAudioIO->mSeek = 0.0;
4943  else
4944 #endif
4945  if (gAudioIO->mSeek)
4946  {
4947  int token = gAudioIO->mStreamToken;
4948  wxMutexLocker locker(gAudioIO->mSuspendAudioThread);
4949  if (token != gAudioIO->mStreamToken)
4950  // This stream got destroyed while we waited for it
4951  return paAbort;
4952 
4953  // Pause audio thread and wait for it to finish
4956  {
4957  wxMilliSleep( 50 );
4958  }
4959 
4960  // Calculate the NEW time position
4963  gAudioIO->mSeek = 0.0;
4964 
4965  // Reset mixer positions and flush buffers for all tracks
4966  if(gAudioIO->mTimeTrack)
4967  // Following gives negative when mT0 > mTime
4970  (gAudioIO->mT0, gAudioIO->mTime);
4971  else
4973  gAudioIO->mWarpedTime = std::abs(gAudioIO->mWarpedTime);
4974 
4975  // Reset mixer positions and flush buffers for all tracks
4976  for (i = 0; i < numPlaybackTracks; i++)
4977  {
4978  gAudioIO->mPlaybackMixers[i]->Reposition(gAudioIO->mTime);
4979  const auto toDiscard =
4980  gAudioIO->mPlaybackBuffers[i]->AvailForGet();
4981  const auto discarded =
4982  gAudioIO->mPlaybackBuffers[i]->Discard( toDiscard );
4983  // wxASSERT( discarded == toDiscard );
4984  // but we can't assert in this thread
4985  wxUnusedVar(discarded);
4986  }
4987 
4988  // Reload the ring buffers
4991  {
4992  wxMilliSleep( 50 );
4993  }
4994 
4995  // Reenable the audio thread
4997 
4998  return paContinue;
4999  }
5000 
5001  unsigned numSolo = 0;
5002  for(unsigned t = 0; t < numPlaybackTracks; t++ )
5003  if( gAudioIO->mPlaybackTracks[t]->GetSolo() )
5004  numSolo++;
5005 #ifdef EXPERIMENTAL_MIDI_OUT
5006  auto numMidiPlaybackTracks = gAudioIO->mMidiPlaybackTracks.size();
5007  for( unsigned t = 0; t < numMidiPlaybackTracks; t++ )
5008  if( gAudioIO->mMidiPlaybackTracks[t]->GetSolo() )
5009  numSolo++;
5010 #endif
5011 
5012  const WaveTrack **chans = (const WaveTrack **) alloca(numPlaybackChannels * sizeof(WaveTrack *));
5013  float **tempBufs = (float **) alloca(numPlaybackChannels * sizeof(float *));
5014  for (unsigned int c = 0; c < numPlaybackChannels; c++)
5015  {
5016  tempBufs[c] = (float *) alloca(framesPerBuffer * sizeof(float));
5017  }
5018 
5020  em.RealtimeProcessStart();
5021 
5022  bool selected = false;
5023  int group = 0;
5024  int chanCnt = 0;
5025  decltype(framesPerBuffer) maxLen = 0;
5026  for (unsigned t = 0; t < numPlaybackTracks; t++)
5027  {
5028  const WaveTrack *vt = gAudioIO->mPlaybackTracks[t].get();
5029 
5030  chans[chanCnt] = vt;
5031 
5032  if (linkFlag)
5033  linkFlag = false;
5034  else {
5035  cut = false;
5036 
5037  // Cut if somebody else is soloing
5038  if (numSolo>0 && !vt->GetSolo())
5039  cut = true;
5040 
5041  // Cut if we're muted (unless we're soloing)
5042  if (vt->GetMute() && !vt->GetSolo())
5043  cut = true;
5044 
5045  linkFlag = vt->GetLinked();
5046  selected = vt->GetSelected();
5047 
5048  // If we have a mono track, clear the right channel
5049  if (!linkFlag)
5050  {
5051  memset(tempBufs[1], 0, framesPerBuffer * sizeof(float));
5052  }
5053  }
5054 
5055 #define ORIGINAL_DO_NOT_PLAY_ALL_MUTED_TRACKS_TO_END
5056 #ifdef ORIGINAL_DO_NOT_PLAY_ALL_MUTED_TRACKS_TO_END
5057  decltype(framesPerBuffer) len = 0;
5058  // this is original code prior to r10680 -RBD
5059  if (cut)
5060  {
5061  len = gAudioIO->mPlaybackBuffers[t]->Discard(framesPerBuffer);
5062  // keep going here.
5063  // we may still need to issue a paComplete.
5064  }
5065  else
5066  {
5067  len = gAudioIO->mPlaybackBuffers[t]->Get((samplePtr)tempBufs[chanCnt],
5068  floatSample,
5069  framesPerBuffer);
5070  if (len < framesPerBuffer)
5071  // Pad with zeroes to the end, in case of a short channel
5072  memset((void*)&tempBufs[chanCnt][len], 0,
5073  (framesPerBuffer - len) * sizeof(float));
5074 
5075  chanCnt++;
5076  }
5077 
5078  // PRL: Bug1104:
5079  // There can be a difference of len in different loop passes if one channel
5080  // of a stereo track ends before the other! Take a max!
5081  maxLen = std::max(maxLen, len);
5082 
5083 
5084  if (linkFlag)
5085  {
5086  continue;
5087  }
5088 #else
5089  // This code was reorganized so that if all audio tracks
5090  // are muted, we still return paComplete when the end of
5091  // a selection is reached.
5092  // Vaughan, 2011-10-20: Further comments from Roger, by off-list email:
5093  // ...something to do with what it means to mute all audio tracks. E.g. if you
5094  // mute all and play, does the playback terminate immediately or play
5095  // silence? If it terminates immediately, does that terminate any MIDI
5096  // playback that might also be going on? ...Maybe muted audio tracks + MIDI,
5097  // the playback would NEVER terminate. ...I think the #else part is probably preferable...
5098  size_t len;
5099  if (cut)
5100  {
5101  len =
5102  gAudioIO->mPlaybackBuffers[t]->Discard(framesPerBuffer);
5103  } else
5104  {
5105  len =
5106  gAudioIO->mPlaybackBuffers[t]->Get((samplePtr)tempFloats,
5107  floatSample,
5108  framesPerBuffer);
5109  }
5110 #endif
5111 
5112  // Last channel seen now
5113  len = maxLen;
5114 
5115  if( !cut && selected )
5116  {
5117  len = em.RealtimeProcess(group, chanCnt, tempBufs, len);
5118  }
5119  group++;
5120 
5121  // If our buffer is empty and the time indicator is past
5122  // the end, then we've actually finished playing the entire
5123  // selection.
5124  // msmeyer: We never finish if we are playing looped
5125  // PRL: or scrubbing.
5126  if (len == 0 &&
5128  if ((gAudioIO->ReversedTime()
5129  ? gAudioIO->mTime <= gAudioIO->mT1
5130  : gAudioIO->mTime >= gAudioIO->mT1))
5131  // PRL: singalling MIDI output complete is necessary if
5132  // not USE_MIDI_THREAD, otherwise it's harmlessly redundant
5133 #ifdef EXPERIMENTAL_MIDI_OUT
5134  gAudioIO->mMidiOutputComplete = true,
5135 #endif
5136  callbackReturn = paComplete;
5137  }
5138 
5139  if (cut) // no samples to process, they've been discarded
5140  continue;
5141 
5142  for (int c = 0; c < chanCnt; c++)
5143  {
5144  vt = chans[c];
5145 
5146  if (vt->GetChannel() == Track::LeftChannel ||
5147  vt->GetChannel() == Track::MonoChannel)
5148  {
5149  float gain = vt->GetChannelGain(0);
5150 
5151  // Output volume emulation: possibly copy meter samples, then
5152  // apply volume, then copy to the output buffer
5153  if (outputMeterFloats != outputFloats)
5154  for (decltype(len) i = 0; i < len; ++i)
5155  outputMeterFloats[numPlaybackChannels*i] +=
5156  gain*tempFloats[i];
5157 
5159  gain *= gAudioIO->mMixerOutputVol;
5160 
5161  for(decltype(len) i = 0; i < len; i++)
5162  outputFloats[numPlaybackChannels*i] += gain*tempBufs[c][i];
5163  }
5164 
5165  if (vt->GetChannel() == Track::RightChannel ||
5166  vt->GetChannel() == Track::MonoChannel)
5167  {
5168  float gain = vt->GetChannelGain(1);
5169 
5170  // Output volume emulation (as above)
5171  if (outputMeterFloats != outputFloats)
5172  for (decltype(len) i = 0; i < len; ++i)
5173  outputMeterFloats[numPlaybackChannels*i+1] +=
5174  gain*tempFloats[i];
5175 
5177  gain *= gAudioIO->mMixerOutputVol;
5178 
5179  for(decltype(len) i = 0; i < len; i++)
5180  outputFloats[numPlaybackChannels*i+1] += gain*tempBufs[c][i];
5181  }
5182  }
5183 
5184  chanCnt = 0;
5185  }
5186  // Poke: If there are no playback tracks, then the earlier check
5187  // about the time indicator being passed the end won't happen;
5188  // do it here instead (but not if looping or scrubbing)
5189  if (numPlaybackTracks == 0 &&
5191  {
5192  if ((gAudioIO->ReversedTime()
5193  ? gAudioIO->mTime <= gAudioIO->mT1
5194  : gAudioIO->mTime >= gAudioIO->mT1)) {
5195 
5196  // PRL: singalling MIDI output complete is necessary if
5197  // not USE_MIDI_THREAD, otherwise it's harmlessly redundant
5198 #ifdef EXPERIMENTAL_MIDI_OUT
5199  gAudioIO->mMidiOutputComplete = true,
5200 #endif
5201  callbackReturn = paComplete;
5202  }
5203  }
5204 
5205 #ifdef EXPERIMENTAL_SCRUBBING_SUPPORT
5206  // Update the current time position, for scrubbing
5207  // "Consume" only as much as the ring buffers produced, which may
5208  // be less than framesPerBuffer (during "stutter")
5210  gAudioIO->mTime = gAudioIO->mScrubQueue->Consumer(maxLen);
5211 #endif
5212 
5213  em.RealtimeProcessEnd();
5214 
5215  gAudioIO->mLastPlaybackTimeMillis = ::wxGetLocalTimeMillis();
5216 
5217  //
5218  // Clip output to [-1.0,+1.0] range (msmeyer)
5219  //
5220  for( i = 0; i < framesPerBuffer*numPlaybackChannels; i++)
5221  {
5222  float f = outputFloats[i];
5223  if (f > 1.0)
5224  outputFloats[i] = 1.0;
5225  else if (f < -1.0)
5226  outputFloats[i] = -1.0;
5227  }
5228 
5229  // Same for meter output
5230  if (outputMeterFloats != outputFloats)
5231  {
5232  for (i = 0; i < framesPerBuffer*numPlaybackChannels; ++i)
5233  {
5234  float f = outputMeterFloats[i];
5235  if (f > 1.0)
5236  outputMeterFloats[i] = 1.0;
5237  else if (f < -1.0)
5238  outputMeterFloats[i] = -1.0;
5239  }
5240  }
5241  }
5242 
5243  //
5244  // Copy from PortAudio to our input buffers.
5245  //
5246 
5247  if( inputBuffer && (numCaptureChannels > 0) )
5248  {
5249  // If there are no playback tracks, and we are recording, then the
5250  // earlier checks for being passed the end won't happen, so do it here.
5251  if (gAudioIO->mTime >= gAudioIO->mT1) {
5252  callbackReturn = paComplete;
5253  }
5254 
5255  // The error likely from a too-busy CPU falling behind real-time data
5256  // is paInputOverflow
5257  bool inputError =
5258  (statusFlags & (paInputOverflow))
5259  && !(statusFlags & paPrimingOutput);
5260 
5261  // But it seems it's easy to get false positives, at least on Mac
5262  // So we have not decided to enable this extra detection yet in
5263  // production
5264 
5265  size_t len = framesPerBuffer;
5266  for(unsigned t = 0; t < numCaptureChannels; t++)
5267  len = std::min( len,
5268  gAudioIO->mCaptureBuffers[t]->AvailForPut());
5269 
5270  if (gAudioIO->mSimulateRecordingErrors && 100LL * rand() < RAND_MAX)
5271  // Make spurious errors for purposes of testing the error
5272  // reporting
5273  len = 0;
5274 
5275  // A different symptom is that len < framesPerBuffer because
5276  // the other thread, executing FillBuffers, isn't consuming fast
5277  // enough from mCaptureBuffers; maybe it's CPU-bound, or maybe the
5278  // storage device it writes is too slow
5279  if (gAudioIO->mDetectDropouts &&
5280  ((gAudioIO->mDetectUpstreamDropouts && inputError) ||
5281  len < framesPerBuffer) ) {
5282  // Assume that any good partial buffer should be written leftmost
5283  // and zeroes will be padded after; label the zeroes.
5284  auto start = gAudioIO->mTime + len / gAudioIO->mRate +
5286  auto duration = (framesPerBuffer - len) / gAudioIO->mRate;
5287  auto interval = std::make_pair( start, duration );
5288  gAudioIO->mLostCaptureIntervals.push_back( interval );
5289  }
5290 
5291  if (len < framesPerBuffer)
5292  {
5293  gAudioIO->mLostSamples += (framesPerBuffer - len);
5294  wxPrintf(wxT("lost %d samples\n"), (int)(framesPerBuffer - len));
5295  }
5296 
5297  if (len > 0) {
5298  for(unsigned t = 0; t < numCaptureChannels; t++) {
5299 
5300  // dmazzoni:
5301  // Un-interleave. Ugly special-case code required because the
5302  // capture channels could be in three different sample formats;
5303  // it'd be nice to be able to call CopySamples, but it can't
5304  // handle multiplying by the gain and then clipping. Bummer.
5305 
5306  switch(gAudioIO->mCaptureFormat) {
5307  case floatSample: {
5308  float *inputFloats = (float *)inputBuffer;
5309  for( i = 0; i < len; i++)
5310  tempFloats[i] =
5311  inputFloats[numCaptureChannels*i+t];
5312  } break;
5313  case int24Sample:
5314  // We should never get here. Audacity's int24Sample format
5315  // is different from PortAudio's sample format and so we
5316  // make PortAudio return float samples when recording in
5317  // 24-bit samples.
5318  wxASSERT(false);
5319  break;
5320  case int16Sample: {
5321  short *inputShorts = (short *)inputBuffer;
5322  short *tempShorts = (short *)tempBuffer;
5323  for( i = 0; i < len; i++) {
5324  float tmp = inputShorts[numCaptureChannels*i+t];
5325  if (tmp > 32767)
5326  tmp = 32767;
5327  if (tmp < -32768)
5328  tmp = -32768;
5329  tempShorts[i] = (short)(tmp);
5330  }
5331  } break;
5332  } // switch
5333 
5334  const auto put =
5335  gAudioIO->mCaptureBuffers[t]->Put(
5336  (samplePtr)tempBuffer, gAudioIO->mCaptureFormat, len);
5337  // wxASSERT(put == len);
5338  // but we can't assert in this thread
5339  wxUnusedVar(put);
5340  }
5341  }
5342  }
5343 
5344  // Update the current time position if not scrubbing
5345  // (Already did it above, for scrubbing)
5346 #ifdef EXPERIMENTAL_SCRUBBING_SUPPORT
5348 #endif
5349  {
5350  double delta = framesPerBuffer / gAudioIO->mRate;
5351  if (gAudioIO->ReversedTime())
5352  delta *= -1.0;
5353  if (gAudioIO->mTimeTrack)
5354  // MB: this is why SolveWarpedLength is needed :)
5355  gAudioIO->mTime =
5357  else
5358  gAudioIO->mTime += delta;
5359  }
5360 
5361  // Wrap to start if looping
5363  {
5364  while (gAudioIO->ReversedTime()
5365  ? gAudioIO->mTime <= gAudioIO->mT1
5366  : gAudioIO->mTime >= gAudioIO->mT1)
5367  {
5368  // LL: This is not exactly right, but I'm at my wits end trying to
5369  // figure it out. Feel free to fix it. :-)
5370  // MB: it's much easier than you think, mTime isn't warped at all!
5372  }
5373  }
5374 
5375  // Record the reported latency from PortAudio.
5376  // TODO: Don't recalculate this with every callback?
5377 
5378  // 01/21/2009: Disabled until a better solution presents itself.
5379  #if 0
5380  // As of 06/17/2006, portaudio v19 returns inputBufferAdcTime set to
5381  // zero. It is being worked on, but for now we just can't do much
5382  // but follow the leader.
5383  //
5384  // 08/27/2006: too inconsistent for now...just leave it a zero.
5385  //
5386  // 04/16/2008: Looks like si->inputLatency comes back with something useful though.
5387  // This rearranged logic uses si->inputLatency, but if PortAudio fixes inputBufferAdcTime,
5388  // this code won't have to be modified to use it.
5389  // Also avoids setting mLastRecordingOffset except when simultaneously playing and recording.
5390  //
5391  if (numCaptureChannels > 0 && numPlaybackChannels > 0) // simultaneously playing and recording
5392  {
5393  if (timeInfo->inputBufferAdcTime > 0)
5394  gAudioIO->mLastRecordingOffset = timeInfo->inputBufferAdcTime - timeInfo->outputBufferDacTime;
5395  else if (gAudioIO->mLastRecordingOffset == 0.0)
5396  {
5397  const PaStreamInfo* si = Pa_GetStreamInfo( gAudioIO->mPortStreamV19 );
5398  gAudioIO->mLastRecordingOffset = -si->inputLatency;
5399  }
5400  }
5401  #endif
5402  } // if mStreamToken > 0
5403  else {
5404  // No tracks to play, but we should clear the output, and
5405  // possibly do software playthrough...
5406 
5407  if( outputBuffer && (numPlaybackChannels > 0) ) {
5408  float *outputFloats = (float *)outputBuffer;
5409  for( i = 0; i < framesPerBuffer*numPlaybackChannels; i++)
5410  outputFloats[i] = 0.0;
5411 
5412  if (inputBuffer && gAudioIO->mSoftwarePlaythrough) {
5414  numCaptureChannels,
5415  (float *)outputBuffer, (int)framesPerBuffer);
5416  }
5417 
5418  // Copy the results to outputMeterFloats if necessary
5419  if (outputMeterFloats != outputFloats) {
5420  for (i = 0; i < framesPerBuffer*numPlaybackChannels; ++i) {
5421  outputMeterFloats[i] = outputFloats[i];
5422  }
5423  }
5424  }
5425 
5426  }
5427  /* Send data to playback VU meter if applicable */
5428  if (gAudioIO->mOutputMeter &&
5430  outputMeterFloats) {
5431  // Get here if playback meter is live
5432  /* It's critical that we don't update the meters while StopStream is
5433  * trying to stop PortAudio, otherwise it can lead to a freeze. We use
5434  * two variables to synchronize:
5435  * mUpdatingMeters tells StopStream when the callback is about to enter
5436  * the code where it might update the meters, and
5437  * mUpdateMeters is how the rest of the code tells the callback when it
5438  * is allowed to actually do the updating.
5439  * Note that mUpdatingMeters must be set first to avoid a race condition.
5440  */
5441  gAudioIO->mUpdatingMeters = true;
5442  if (gAudioIO->mUpdateMeters) {
5443  gAudioIO->mOutputMeter->UpdateDisplay(numPlaybackChannels,
5444  framesPerBuffer,
5445  outputMeterFloats);
5446 
5447  //v Vaughan, 2011-02-25: Moved this update back to TrackPanel::OnTimer()
5448  // as it helps with playback issues reported by Bill and noted on Bug 258.
5449  // The problem there occurs if Software Playthrough is on.
5450  // Could conditionally do the update here if Software Playthrough is off,
5451  // and in TrackPanel::OnTimer() if Software Playthrough is on, but not now.
5452  // PRL 12 Jul 2015: and what was in TrackPanel::OnTimer is now handled by means of event
5453  // type EVT_TRACK_PANEL_TIMER
5454  //AudacityProject* pProj = GetActiveProject();
5455  //MixerBoard* pMixerBoard = pProj->GetMixerBoard();
5456  //if (pMixerBoard)
5457  // pMixerBoard->UpdateMeters(gAudioIO->GetStreamTime(),
5458  // (pProj->mLastPlayMode == loopedPlay));
5459  }
5460  gAudioIO->mUpdatingMeters = false;
5461  } // end playback VU meter update
5462 
5463  return callbackReturn;
5464 }
double LimitStreamTime(double absoluteTime) const
Clamps the given time to be between mT0 and mT1.
Definition: AudioIO.cpp:2919
bool GetSolo() const
Definition: Track.h:384
A ToolBar that has the main Transport buttons.
double ComputeWarpedLength(double t0, double t1) const
Compute the duration (in seconds at playback) of the specified region of the track.
Definition: TimeTrack.cpp:160
size_t RealtimeProcess(int group, unsigned chans, float **buffers, size_t numSamples)
bool GetSelected() const
Definition: Track.h:276
enum AudioIO::@3 mPlayMode
bool mDetectDropouts
Definition: AudioIO.h:831
void CopySamples(samplePtr src, sampleFormat srcFormat, samplePtr dst, sampleFormat dstFormat, unsigned int len, bool highQuality, unsigned int srcStride, unsigned int dstStride)
bool mDetectUpstreamDropouts
Definition: AudioIO.h:843
volatile bool mUpdatingMeters
Definition: AudioIO.h:730
float mMixerOutputVol
Definition: AudioIO.h:746
#define USE_MIDI_THREAD
Definition: AudioIO.h:116
double mTime
Current time position during playback, in seconds. Between mT0 and mT1.
Definition: AudioIO.h:684
bool mSoftwarePlaythrough
Definition: AudioIO.h:704
bool GetLinked() const
Definition: Track.h:279
const TimeTrack * mTimeTrack
Definition: AudioIO.h:769
struct AudioIO::RecordingSchedule mRecordingSchedule
MeterPanel * mOutputMeter
Definition: AudioIO.h:728
float GetChannelGain(int channel) const
Definition: WaveTrack.cpp:440
ArrayOf< std::unique_ptr< RingBuffer > > mPlaybackBuffers
Definition: AudioIO.h:670
float mSilenceLevel
Definition: AudioIO.h:707
sampleFormat mCaptureFormat
Definition: AudioIO.h:710
ArrayOf< std::unique_ptr< Mixer > > mPlaybackMixers
Definition: AudioIO.h:673
std::unique_ptr< ScrubQueue > mScrubQueue
Definition: AudioIO.h:815
double mWarpedTime
Definition: AudioIO.h:689
wxMutex mSuspendAudioThread
Definition: AudioIO.h:812
AudacityProject provides the main window, with tools and tracks contained within it.
Definition: Project.h:176
bool mPaused
True if audio playback is paused.
Definition: AudioIO.h:702
ArrayOf< std::unique_ptr< RingBuffer > > mCaptureBuffers
Definition: AudioIO.h:668
bool ReversedTime() const
True if the end time is before the start time.
Definition: AudioIO.h:541
volatile int mStreamToken
Definition: AudioIO.h:674
bool mEmulateMixerOutputVol
Definition: AudioIO.h:737
PaStream * mPortStreamV19
Definition: AudioIO.h:703
bool IsMeterDisabled() const
Find out if the level meter is disabled or not.
Definition: Meter.cpp:1773
bool IsPaused()
Find out if playback / recording is currently paused.
Definition: AudioIO.cpp:2857
void UpdateDisplay(unsigned numChannels, int numFrames, float *sampleData)
Update the meters with a block of audio data.
Definition: Meter.cpp:886
char * samplePtr
Definition: Types.h:203
A Track that contains audio waveform data.
Definition: WaveTrack.h:60
if(pTrack &&pTrack->GetDisplay()!=WaveTrack::Spectrum)
EffectManager is the class that handles effects and effect categories.
Definition: EffectManager.h:45
int min(int a, int b)
wxLongLong mLastPlaybackTimeMillis
Definition: AudioIO.h:716
volatile bool mAudioThreadShouldCallFillBuffersOnce
Definition: AudioIO.h:712
unsigned int mNumPlaybackChannels
Definition: AudioIO.h:709
double mSeek
Definition: AudioIO.h:696
unsigned int mNumCaptureChannels
Definition: AudioIO.h:708
static EffectManager & Get()
wxWeakRef< MeterPanel > mInputMeter
Definition: AudioIO.h:727
unsigned long long mLostSamples
Definition: AudioIO.h:711
static void DoSoftwarePlaythrough(const void *inputBuffer, sampleFormat inputFormat, unsigned inputChannels, float *outputBuffer, int len)
Definition: AudioIO.cpp:4702
double mRate
Audio playback rate in samples per second.
Definition: AudioIO.h:678
bool mUpdateMeters
Definition: AudioIO.h:729
AudioIO * gAudioIO
Definition: AudioIO.cpp:482
ControlToolBar * GetControlToolBar()
Definition: Project.cpp:5003
volatile double mLastRecordingOffset
Definition: AudioIO.h:723
AUDACITY_DLL_API AudacityProject * GetActiveProject()
Definition: Project.cpp:308
void ClearSamples(samplePtr dst, sampleFormat format, size_t start, size_t len)
bool mUsingAlsa
Definition: AudioIO.h:771
double mT0
Playback starts at offset of mT0, which is measured in seconds.
Definition: AudioIO.h:680
double SolveWarpedLength(double t0, double length) const
Compute how much unwarped time must have elapsed if length seconds of warped time has elapsed...
Definition: TimeTrack.cpp:165
bool GetMute() const
Definition: Track.h:383
std::vector< std::pair< double, double > > mLostCaptureIntervals
Definition: AudioIO.h:830
volatile bool mAudioThreadFillBuffersLoopActive
Definition: AudioIO.h:714
#define MAX(a, b)
Definition: AudioIO.cpp:4700
void RealtimeProcessEnd()
double mT1
Playback ends at offset of mT1, which is measured in seconds. Note that mT1 may be less than mT0 duri...
Definition: AudioIO.h:682
volatile bool mAudioThreadFillBuffersLoopRunning
Definition: AudioIO.h:713
virtual int GetChannel() const override
Definition: WaveTrack.cpp:236
bool mPauseRec
True if Sound Activated Recording is enabled.
Definition: AudioIO.h:706
WaveTrackConstArray mPlaybackTracks
Definition: AudioIO.h:671
void RealtimeProcessStart()
bool mSimulateRecordingErrors
Definition: AudioIO.h:839
static PaSampleFormat AudacityToPortAudioSampleFormat ( sampleFormat  format)
static

Definition at line 1627 of file AudioIO.cpp.

References floatSample, int16Sample, and int24Sample.

Referenced by AudioIO::StartPortAudioStream().

1628 {
1629  switch(format) {
1630  case int16Sample:
1631  return paInt16;
1632  case int24Sample:
1633  return paInt24;
1634  case floatSample:
1635  default:
1636  return paFloat32;
1637  }
1638 }
int format
Definition: ExportPCM.cpp:56
void DeinitAudioIO ( )

Definition at line 1149 of file AudioIO.cpp.

Referenced by AudacityApp::OnExit().

1150 {
1151  ugAudioIO.reset();
1152 }
std::unique_ptr< AudioIO > ugAudioIO
Definition: AudioIO.cpp:481
wxString DeviceName ( const PaDeviceInfo *  info)

Definition at line 1154 of file AudioIO.cpp.

Referenced by AudioIO::GetDeviceInfo(), AudioIO::getPlayDevIndex(), AudioIO::getRecordDevIndex(), and InitAudioIO().

1155 {
1156  wxString infoName = wxSafeConvertMB2WX(info->name);
1157 
1158  return infoName;
1159 }
static void DoSoftwarePlaythrough ( const void *  inputBuffer,
sampleFormat  inputFormat,
unsigned  inputChannels,
float *  outputBuffer,
int  len 
)
static

Definition at line 4702 of file AudioIO.cpp.

References CopySamples(), floatSample, and SAMPLE_SIZE.

Referenced by audacityAudioCallback().

4707 {
4708  for (unsigned int i=0; i < inputChannels; i++) {
4709  samplePtr inputPtr = ((samplePtr)inputBuffer) + (i * SAMPLE_SIZE(inputFormat));
4710  samplePtr outputPtr = ((samplePtr)outputBuffer) + (i * SAMPLE_SIZE(floatSample));
4711 
4712  CopySamples(inputPtr, inputFormat,
4713  (samplePtr)outputPtr, floatSample,
4714  len, true, inputChannels, 2);
4715  }
4716 
4717  // One mono input channel goes to both output channels...
4718  if (inputChannels == 1)
4719  for (int i=0; i < len; i++)
4720  outputBuffer[2*i + 1] = outputBuffer[2*i];
4721 }
void CopySamples(samplePtr src, sampleFormat srcFormat, samplePtr dst, sampleFormat dstFormat, unsigned int len, bool highQuality, unsigned int srcStride, unsigned int dstStride)
#define SAMPLE_SIZE(SampleFormat)
Definition: Types.h:198
char * samplePtr
Definition: Types.h:203
wxString HostName ( const PaDeviceInfo *  info)

Definition at line 1161 of file AudioIO.cpp.

Referenced by AudioIO::GetDeviceInfo(), and InitAudioIO().

1162 {
1163  wxString hostapiName = wxSafeConvertMB2WX(Pa_GetHostApiInfo(info->hostApi)->name);
1164 
1165  return hostapiName;
1166 }
void InitAudioIO ( )

Definition at line 1116 of file AudioIO.cpp.

References DeviceName(), gAudioIO, AudioIO::getPlayDevIndex(), AudioIO::getRecordDevIndex(), gPrefs, HostName(), AudioIO::mThread, and safenew.

Referenced by AudacityApp::OnInit().

1117 {
1118  ugAudioIO.reset(safenew AudioIO());
1119  gAudioIO = ugAudioIO.get();
1120  gAudioIO->mThread->Run();
1121 #ifdef EXPERIMENTAL_MIDI_OUT
1122 #ifdef USE_MIDI_THREAD
1123  gAudioIO->mMidiThread->Run();
1124 #endif
1125 #endif
1126 
1127  // Make sure device prefs are initialized
1128  if (gPrefs->Read(wxT("AudioIO/RecordingDevice"), wxT("")) == wxT("")) {
1129  int i = AudioIO::getRecordDevIndex();
1130  const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
1131  if (info) {
1132  gPrefs->Write(wxT("/AudioIO/RecordingDevice"), DeviceName(info));
1133  gPrefs->Write(wxT("/AudioIO/Host"), HostName(info));
1134  }
1135  }
1136 
1137  if (gPrefs->Read(wxT("AudioIO/PlaybackDevice"), wxT("")) == wxT("")) {
1138  int i = AudioIO::getPlayDevIndex();
1139  const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
1140  if (info) {
1141  gPrefs->Write(wxT("/AudioIO/PlaybackDevice"), DeviceName(info));
1142  gPrefs->Write(wxT("/AudioIO/Host"), HostName(info));
1143  }
1144  }
1145 
1146  gPrefs->Flush();
1147 }
AudioIO uses the PortAudio library to play and record sound.
Definition: AudioIO.h:172
AudacityPrefs * gPrefs
Definition: Prefs.cpp:73
std::unique_ptr< AudioIO > ugAudioIO
Definition: AudioIO.cpp:481
wxString DeviceName(const PaDeviceInfo *info)
Definition: AudioIO.cpp:1154
static int getPlayDevIndex(const wxString &devName=wxEmptyString)
get the index of the device selected in the preferences.
Definition: AudioIO.cpp:3328
wxString HostName(const PaDeviceInfo *info)
Definition: AudioIO.cpp:1161
#define safenew
Definition: Audacity.h:230
std::unique_ptr< AudioThread > mThread
Definition: AudioIO.h:661
AudioIO * gAudioIO
Definition: AudioIO.cpp:482
static int getRecordDevIndex(const wxString &devName=wxEmptyString)
get the index of the supplied (named) recording device, or the device selected in the preferences if ...
Definition: AudioIO.cpp:3385
wxDEFINE_EVENT ( EVT_AUDIOIO_PLAYBACK  ,
wxCommandEvent   
)
wxDEFINE_EVENT ( EVT_AUDIOIO_CAPTURE  ,
wxCommandEvent   
)
wxDEFINE_EVENT ( EVT_AUDIOIO_MONITOR  ,
wxCommandEvent   
)

Variable Documentation

AudioIO* gAudioIO {}

Definition at line 482 of file AudioIO.cpp.

Referenced by audacityAudioCallback(), ControlToolBar::CanStopAudioStream(), Scrubber::ContinueScrubbingPoll(), AudacityProject::CreateMenusAndCommands(), CreateNewAudacityProject(), LabelTrack::DoCaptureKey(), AudacityProject::DoPlayStopSelect(), ControlToolBar::DoRecord(), PlayIndicatorOverlayBase::Draw(), DeviceToolBar::EnableDisableButtons(), ControlToolBar::EnableDisableButtons(), AudioThread::Entry(), AudacityProject::GetUpdateFlags(), InitAudioIO(), EffectUIHost::Initialize(), WaveTrackMenuTable::InitMenu(), AudacityProject::IsAudioActive(), AudacityProject::MakeReadyToPlay(), Scrubber::MaybeStartScrubbing(), AudacityProject::OnAddLabelPlaying(), AudacityProject::OnAudioDeviceInfo(), AudacityProject::OnAudioIOStopRecording(), AudacityProject::OnBoundaryMove(), DeviceToolBar::OnChoice(), AudacityProject::OnCloseWindow(), AudacityProject::OnCursorPositionStore(), AudacityProject::OnDetectUpstreamDropouts(), EffectUIHost::OnFFwd(), AudacityApp::OnKeyDown(), ControlToolBar::OnKeyEvent(), TranscriptionToolBar::OnKeyEvent(), MeterPanel::OnMeterUpdate(), PrefsDialog::OnOK(), ControlToolBar::OnPause(), EffectUIHost::OnPlay(), AudacityProject::OnPlayStop(), AudacityProject::OnPlayStopSelect(), AudacityProject::OnPunchAndRoll(), EffectUIHost::OnRewind(), AudacityProject::OnSelectCursorStoredCursor(), AudacityProject::OnSetLeftSelection(), AudacityProject::OnSetRightSelection(), AudacityProject::OnSimulateRecordingErrors(), WaveTrackMenuTable::OnSpectrogramSettings(), AudacityProject::OnStopSelect(), LyricsWindow::OnTimer(), PlayIndicatorOverlay::OnTimer(), ViewInfo::OnTimer(), MixerBoard::OnTimer(), TrackPanel::OnTimer(), AudacityProject::OnTimer(), ControlToolBar::Pause(), TranscriptionToolBar::PlayAtSpeed(), ControlToolBar::PlayPlayRegion(), MixerToolBar::Populate(), Effect::Preview(), AudacityProject::PushState(), DeviceManager::Rescan(), AudacityProject::SeekWhenAudioActive(), AudacityProject::SetCaptureMeter(), MixerToolBar::SetMixer(), AudacityProject::SetPlaybackMeter(), MixerToolBar::SetToolTips(), MeterPanel::StartMonitoring(), ControlToolBar::StartScrolling(), AudioIO::StartStream(), MeterPanel::StopMonitoring(), ControlToolBar::StopPlaying(), AudacityProject::TP_DisplaySelection(), AudacityProject::TP_DisplayStatusMessage(), MixerToolBar::UpdateControls(), MixerToolBar::UpdatePrefs(), AudacityProject::ZoomInByFactor(), and AudioIO::~AudioIO().

std::unique_ptr<AudioIO> ugAudioIO

Definition at line 481 of file AudioIO.cpp.