~ubuntu-branches/ubuntu/gutsy/audacity/gutsy-backports

« back to all changes in this revision

Viewing changes to src/AudioIO.cpp

  • Committer: Bazaar Package Importer
  • Author(s): John Dong
  • Date: 2008-02-18 21:58:19 UTC
  • mfrom: (13.1.2 hardy)
  • Revision ID: james.westby@ubuntu.com-20080218215819-tmbcf1rx238r8gdv
Tags: 1.3.4-1.1ubuntu1~gutsy1
Automated backport upload; no source changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
55
55
#include <wx/timer.h>
56
56
#include <wx/intl.h>
57
57
#include <wx/debug.h>
 
58
#include <wx/sstream.h>
 
59
#include <wx/txtstrm.h>
58
60
 
59
61
#include "AudacityApp.h"
60
62
#include "AudioIO.h"
63
65
#include "Resample.h"
64
66
#include "RingBuffer.h"
65
67
#include "Prefs.h"
66
 
#include "TimeTrack.h"
 
68
#include "Project.h"
 
69
#include "toolbars/ControlToolBar.h"
67
70
 
68
71
#include "widgets/Meter.h"
 
72
#include "../Experimental.h"
69
73
 
70
74
#define NO_STABLE_INDICATOR -1000000000
71
75
 
246
250
AudioIO::~AudioIO()
247
251
{
248
252
#if defined(USE_PORTMIXER)
249
 
   if( mPortMixer ) {
 
253
   if (mPortMixer) {
250
254
      #if __WXMAC__
251
255
      if (Px_SupportsPlaythrough(mPortMixer) && mPreviousHWPlaythrough >= 0.0)
252
256
         Px_SetPlaythrough(mPortMixer, mPreviousHWPlaythrough);
 
257
         mPreviousHWPlaythrough = -1.0;
253
258
      #endif
254
259
      Px_CloseMixer(mPortMixer);
 
260
      mPortMixer = NULL;
255
261
   }
256
 
   mPortMixer = NULL;
257
262
#endif
258
263
   Pa_Terminate();
259
264
 
351
356
void AudioIO::HandleDeviceChange()
352
357
{
353
358
   // This should not happen, but it would screw things up if it did.
354
 
   if( IsStreamActive() )
 
359
   if (IsStreamActive())
355
360
      return;
356
361
 
357
362
#if defined(USE_PORTMIXER)
358
363
   const PaDeviceInfo* info;
359
364
 
360
 
   if( mPortMixer )
 
365
   if (mPortMixer) {
 
366
      #if __WXMAC__
 
367
      if (Px_SupportsPlaythrough(mPortMixer) && mPreviousHWPlaythrough >= 0.0)
 
368
         Px_SetPlaythrough(mPortMixer, mPreviousHWPlaythrough);
 
369
         mPreviousHWPlaythrough = -1.0;
 
370
      #endif
361
371
      Px_CloseMixer(mPortMixer);
362
 
   mPortMixer = NULL;
 
372
      mPortMixer = NULL;
 
373
   }
363
374
 
364
375
#if USE_PORTAUDIO_V19
365
376
   int recDeviceNum = Pa_GetDefaultInputDevice();
440
451
   captureParameters.channelCount = 2;
441
452
   if (Pa_GetDeviceInfo(recDeviceNum))
442
453
      captureParameters.suggestedLatency =
443
 
         Pa_GetDeviceInfo(recDeviceNum)->defaultLowOutputLatency;
 
454
         Pa_GetDeviceInfo(recDeviceNum)->defaultLowInputLatency;
444
455
   else
445
456
      captureParameters.suggestedLatency = 100; // we're just probing anyway
446
457
 
658
669
                                 audacityAudioCallback, NULL );
659
670
 
660
671
#if USE_PORTMIXER
661
 
   if (mPortMixer) {
662
 
      #if __WXMAC__
663
 
      if (Px_SupportsPlaythrough(mPortMixer) && mPreviousHWPlaythrough >= 0.0)
664
 
         Px_SetPlaythrough(mPortMixer, mPreviousHWPlaythrough);
665
 
      #endif
666
 
      Px_CloseMixer(mPortMixer);
667
 
   }
668
 
   mPortMixer = NULL;
669
672
   if (mPortStreamV19 != NULL && mLastPaError == paNoError) {
670
 
      mPortMixer = Px_OpenMixer(mPortStreamV19, 0);
671
 
 
672
673
      #ifdef __MACOSX__
673
674
      if (mPortMixer) {
674
675
         if (Px_SupportsPlaythrough(mPortMixer)) {
761
762
                                 audacityAudioCallback, NULL );
762
763
 
763
764
#if USE_PORTMIXER
764
 
   if (mPortMixer) {
765
 
      #if __WXMAC__
766
 
      if (Px_SupportsPlaythrough(mPortMixer) && mPreviousHWPlaythrough >= 0.0)
767
 
         Px_SetPlaythrough(mPortMixer, mPreviousHWPlaythrough);
768
 
      #endif
769
 
      Px_CloseMixer(mPortMixer);
770
 
   }
771
 
   mPortMixer = NULL;
772
765
   if (mPortStreamV18 != NULL && mLastPaError == paNoError) {
773
 
      mPortMixer = Px_OpenMixer(mPortStreamV18, 0);
774
 
 
775
766
      #ifdef __MACOSX__
776
767
      if (mPortMixer) {
777
768
         if (Px_SupportsPlaythrough(mPortMixer)) {
874
865
 
875
866
   gPrefs->Read(wxT("/AudioIO/SWPlaythrough"), &mSoftwarePlaythrough, false);
876
867
 
 
868
#ifdef EXPERIMENTAL_SMART_RECORD
 
869
   gPrefs->Read(wxT("/AudioIO/PauseRecOnSilence"), &mPauseRec, false);
 
870
   int silenceLevelDB;
 
871
   gPrefs->Read(wxT("/AudioIO/SilenceLevel"), &silenceLevelDB, -50);
 
872
   mSilenceLevel = (silenceLevelDB + 60.)/60.;  // meter goes -60dB -> 0dB
 
873
#endif
 
874
 
 
875
   mTimeTrack = timeTrack;
877
876
   mListener = listener;
878
877
   mInputMeter = NULL;
879
878
   mOutputMeter = NULL;
890
889
   mCutPreviewGapStart = cutPreviewGapStart;
891
890
   mCutPreviewGapLen = cutPreviewGapLen;
892
891
 
893
 
   mPlaySpeed = 1.0;
894
 
   if (timeTrack) {
895
 
      mPlaySpeed = timeTrack->GetEnvelope()->GetValue(t0);
896
 
      mPlaySpeed = 1 / ((timeTrack->GetRangeLower() * (1 - mPlaySpeed) +
897
 
                        mPlaySpeed * timeTrack->GetRangeUpper())/100.0);
 
892
   double factor = 1.0;
 
893
   if (mTimeTrack) {
 
894
      factor = mTimeTrack->GetEnvelope()->Average(mT0, mT1);
 
895
      factor = (mTimeTrack->GetRangeLower() *
 
896
               (1 - factor) +
 
897
               factor *
 
898
               mTimeTrack->GetRangeUpper()) / 
 
899
               100.0;
898
900
   }
899
 
   mWarpedT1 = mT0 + ((mT1 - mT0) * mPlaySpeed);
 
901
   mWarpedT1 = factor >= 1 ? mT1 : mT0 + ((mT1 - mT0) / factor);
900
902
 
901
903
   //
902
904
   // The RingBuffer sizes, and the max amount of the buffer to
971
973
         mPlaybackBuffers[i] = new RingBuffer(floatSample, playbackBufferSize);
972
974
 
973
975
         mPlaybackMixers[i]  = new Mixer(1, &mPlaybackTracks[i],
974
 
                                         timeTrack, mT0, mWarpedT1, 1,
 
976
                                         mTimeTrack, mT0, mWarpedT1, 1,
975
977
                                         playbackMixBufferSize, false,
976
978
                                         mRate, floatSample, false);
977
979
         mPlaybackMixers[i]->ApplyTrackGains(false);
1118
1120
      #if __WXMAC__
1119
1121
      if (Px_SupportsPlaythrough(mPortMixer) && mPreviousHWPlaythrough >= 0.0)
1120
1122
         Px_SetPlaythrough(mPortMixer, mPreviousHWPlaythrough);
 
1123
         mPreviousHWPlaythrough = -1.0;
1121
1124
      #endif
1122
1125
   }
1123
1126
  #endif
1177
1180
      //
1178
1181
      // Offset all recorded tracks to account for latency
1179
1182
      //
1180
 
      double latencyCorrection = 0;
1181
 
      gPrefs->Read(wxT("/AudioIO/LatencyCorrection"), &latencyCorrection);
1182
 
      
1183
1183
      if( mCaptureTracks.GetCount() > 0 )
1184
1184
      {
 
1185
         //
 
1186
         // We only apply latency correction when we actually played back
 
1187
         // tracks during the recording. If we did not play back tracks,
 
1188
         // there's nothing we could be out of sync with. This also covers the
 
1189
         // case that we do not apply latency correction when recording the
 
1190
         // first track in a project.
 
1191
         //
 
1192
         double latencyCorrection = 0;
 
1193
         gPrefs->Read(wxT("/AudioIO/LatencyCorrection"), &latencyCorrection);
 
1194
         
 
1195
         double recordingOffset =
 
1196
            mLastRecordingOffset + latencyCorrection / 1000.0;
 
1197
 
1185
1198
         for( unsigned int i = 0; i < mCaptureTracks.GetCount(); i++ )
1186
1199
            {
1187
1200
               delete mCaptureBuffers[i];
1188
 
               mCaptureTracks[i]->Flush();
1189
 
               mCaptureTracks[i]->Offset(mLastRecordingOffset +
1190
 
                                         latencyCorrection/1000.0);
 
1201
               
 
1202
               WaveTrack* track = mCaptureTracks[i];
 
1203
               track->Flush();
 
1204
 
 
1205
               if (mPlaybackTracks.GetCount() > 0)
 
1206
               {  // only do latency correction if some tracks are being played back
 
1207
                  WaveTrackArray playbackTracks;
 
1208
                  AudacityProject *p = GetActiveProject();
 
1209
                  // we need to get this as mPlaybackTracks does not contain tracks being recorded into
 
1210
                  playbackTracks = p->GetTracks()->GetWaveTrackArray(false);
 
1211
                  bool appendRecord = false;
 
1212
                  for( unsigned int j = 0; j < playbackTracks.GetCount(); j++)
 
1213
                  {  // find if we are recording into an existing track (append-record)
 
1214
                     WaveTrack* trackP = playbackTracks[j];
 
1215
                     if( track == trackP )
 
1216
                     {
 
1217
                        if( track->GetStartTime() != mT0 )  // in a new track if these are equal
 
1218
                        {
 
1219
                           appendRecord = true;
 
1220
                           break;
 
1221
                        }
 
1222
                     }
 
1223
                  }
 
1224
                  if( appendRecord )
 
1225
                  {  // append-recording
 
1226
                     if (recordingOffset < 0)
 
1227
                        track->Clear(mT0, mT0 - recordingOffset); // cut the latency out
 
1228
                     else
 
1229
                        track->InsertSilence(mT0, recordingOffset); // put silence in
 
1230
                  }
 
1231
                  else
 
1232
                  {  // recording into a new track
 
1233
                     track->SetOffset(track->GetStartTime() + recordingOffset);
 
1234
                     if(track->GetEndTime() < 0.)
 
1235
                     {
 
1236
                        wxMessageDialog m(NULL, _("Latency setting has caused the recorded audio to be hidden before zero.\nAudacity has brought it back to start at zero.\nYou may have to use the Time Shift Tool (<---> or F5) to drag the track to the right place."), _("Latency problem"), wxOK);
 
1237
                        m.ShowModal();
 
1238
                        track->SetOffset(0.);
 
1239
                     }
 
1240
                  }
 
1241
               }
1191
1242
            }
1192
1243
         
1193
1244
         delete[] mCaptureBuffers;
1299
1350
   if (absoluteTime < mT0)
1300
1351
      absoluteTime = mT0;
1301
1352
 
1302
 
   // dmazzoni: If we're looping, we should wrap around when the
1303
 
   // stream time is past the end.  Otherwise the returned stream
1304
 
   // time is clipped to the end time.
1305
 
   if (mPlayLooped) {
1306
 
      while (absoluteTime > mT1)
1307
 
         absoluteTime -= mT1 - mT0;
1308
 
   }
1309
 
   else {
1310
 
      if (absoluteTime > mT1)
1311
 
         absoluteTime = mT1;
1312
 
   }
 
1353
   if (absoluteTime > mT1)
 
1354
      absoluteTime = mT1;
1313
1355
   
1314
1356
   if (mCutPreviewGapLen > 0)
1315
1357
   {
1646
1688
   return commonlyAvail;
1647
1689
}
1648
1690
 
 
1691
wxString AudioIO::GetDeviceInfo()
 
1692
{
 
1693
   wxStringOutputStream o;
 
1694
   wxTextOutputStream s(o, wxEOL_UNIX);
 
1695
   wxString e(wxT("\n"));
 
1696
 
 
1697
   if (IsStreamActive()) {
 
1698
      return wxT("Stream is active ... unable to gather information.");
 
1699
   }
 
1700
 
 
1701
#if defined(USE_PORTMIXER)
 
1702
   const PaDeviceInfo* info;
 
1703
 
 
1704
#if USE_PORTAUDIO_V19
 
1705
   int recDeviceNum = Pa_GetDefaultInputDevice();
 
1706
   int playDeviceNum = Pa_GetDefaultOutputDevice();
 
1707
#else
 
1708
   int recDeviceNum = Pa_GetDefaultInputDeviceID();
 
1709
   int playDeviceNum = Pa_GetDefaultOutputDeviceID();
 
1710
#endif
 
1711
 
 
1712
   s << wxT("==============================") << e;
 
1713
   s << wxT("Default capture device number: ") << recDeviceNum << e;
 
1714
   s << wxT("Default playback device number: ") << playDeviceNum << e;
 
1715
 
 
1716
   // Sometimes PortAudio returns -1 if it cannot find a suitable default
 
1717
   // device, so we just use the first one available
 
1718
   if (recDeviceNum < 0)
 
1719
      recDeviceNum = 0;
 
1720
   if (playDeviceNum < 0)
 
1721
      playDeviceNum = 0;
 
1722
      
 
1723
   wxString recDevice = gPrefs->Read(wxT("/AudioIO/RecordingDevice"), wxT(""));
 
1724
   wxString playDevice = gPrefs->Read(wxT("/AudioIO/PlaybackDevice"), wxT(""));
 
1725
   int j;
 
1726
 
 
1727
   // msmeyer: This tries to open the device with the highest samplerate
 
1728
   // available on this device, using 44.1kHz as the default, if the info
 
1729
   // cannot be fetched.
 
1730
 
 
1731
#if USE_PORTAUDIO_V19
 
1732
   int cnt = Pa_GetDeviceCount();
 
1733
#else
 
1734
   int cnt = Pa_CountDevices();
 
1735
#endif
 
1736
 
 
1737
   if (cnt <= 0) {
 
1738
      s << wxT("No devices found\n");
 
1739
      return o.GetString();
 
1740
   }
 
1741
      
 
1742
   for (j = 0; j < cnt; j++) {
 
1743
      s << wxT("==============================") << e;
 
1744
 
 
1745
      info = Pa_GetDeviceInfo(j);
 
1746
      if (!info) {
 
1747
         s << wxT("Device info unavailable for: ") << j << wxT("\n");
 
1748
         continue;
 
1749
      }
 
1750
 
 
1751
      wxString name = DeviceName(info);
 
1752
 
 
1753
      s << wxT("Device ID: ") << j << e;
 
1754
      s << wxT("Device name: ") << name << e;
 
1755
      s << wxT("Input channels: ") << info->maxInputChannels << e;
 
1756
      s << wxT("Output channels: ") << info->maxOutputChannels << e;
 
1757
      s << wxT("Low Input Latency: ") << info->defaultLowInputLatency << e;
 
1758
      s << wxT("Low Output Latency: ") << info->defaultLowOutputLatency << e;
 
1759
      s << wxT("High Input Latency: ") << info->defaultHighInputLatency << e;
 
1760
      s << wxT("High Output Latency: ") << info->defaultHighOutputLatency << e;
 
1761
 
 
1762
      wxArrayLong rates = GetSupportedPlaybackRates(name, 0.0);
 
1763
 
 
1764
      s << wxT("Supported Rates:") << e;
 
1765
      for (int k = 0; k < (int) rates.GetCount(); k++) {
 
1766
         s << wxT("    ") << (int)rates[k] << e;
 
1767
      }
 
1768
 
 
1769
      if (name == playDevice && info->maxOutputChannels > 0)
 
1770
         playDeviceNum = j;
 
1771
 
 
1772
      if (name == recDevice && info->maxInputChannels > 0)
 
1773
         recDeviceNum = j;
 
1774
   }
 
1775
 
 
1776
   s << wxT("==============================") << e;
 
1777
   s << wxT("Selected capture device: ") << recDeviceNum << wxT(" - ") << recDevice << e;
 
1778
   s << wxT("Selected playback device: ") << playDeviceNum << wxT(" - ") << playDevice << e;
 
1779
 
 
1780
   wxArrayLong supportedSampleRates = GetSupportedSampleRates(playDevice, recDevice);
 
1781
 
 
1782
   s << wxT("Supported Rates:");
 
1783
   for (int k = 0; k < (int) supportedSampleRates.GetCount(); k++) {
 
1784
      s << wxT("    ") << (int)supportedSampleRates[k] << e;
 
1785
   }
 
1786
 
 
1787
   int highestSampleRate = supportedSampleRates[supportedSampleRates.GetCount() - 1];
 
1788
   bool EmulateMixerInputVol = true;
 
1789
   bool EmulateMixerOutputVol = true;
 
1790
   float MixerInputVol = 1.0;
 
1791
   float MixerOutputVol = 1.0;
 
1792
 
 
1793
   int error;
 
1794
 
 
1795
#if USE_PORTAUDIO_V19
 
1796
 
 
1797
   PaStream *stream;
 
1798
 
 
1799
   PaStreamParameters playbackParameters;
 
1800
 
 
1801
   playbackParameters.device = playDeviceNum;
 
1802
   playbackParameters.sampleFormat = paFloat32;
 
1803
   playbackParameters.hostApiSpecificStreamInfo = NULL;
 
1804
   playbackParameters.channelCount = 2;
 
1805
   if (Pa_GetDeviceInfo(playDeviceNum))
 
1806
      playbackParameters.suggestedLatency =
 
1807
         Pa_GetDeviceInfo(playDeviceNum)->defaultLowOutputLatency;
 
1808
   else
 
1809
      playbackParameters.suggestedLatency = 100; // we're just probing anyway
 
1810
 
 
1811
   PaStreamParameters captureParameters;
 
1812
 
 
1813
   captureParameters.device = recDeviceNum;
 
1814
   captureParameters.sampleFormat = paFloat32;;
 
1815
   captureParameters.hostApiSpecificStreamInfo = NULL;
 
1816
   captureParameters.channelCount = 2;
 
1817
   if (Pa_GetDeviceInfo(recDeviceNum))
 
1818
      captureParameters.suggestedLatency =
 
1819
         Pa_GetDeviceInfo(recDeviceNum)->defaultLowInputLatency;
 
1820
   else
 
1821
      captureParameters.suggestedLatency = 100; // we're just probing anyway
 
1822
 
 
1823
   error = Pa_OpenStream(&stream,
 
1824
                         &captureParameters, &playbackParameters,
 
1825
                         highestSampleRate, paFramesPerBufferUnspecified,
 
1826
                         paClipOff | paDitherOff,
 
1827
                         audacityAudioCallback, NULL);
 
1828
 
 
1829
   if (error) {
 
1830
      error = Pa_OpenStream(&stream,
 
1831
                            &captureParameters, NULL,
 
1832
                            highestSampleRate, paFramesPerBufferUnspecified,
 
1833
                            paClipOff | paDitherOff,
 
1834
                            audacityAudioCallback, NULL);
 
1835
   }
 
1836
  
 
1837
#else
 
1838
 
 
1839
   PortAudioStream *stream;
 
1840
 
 
1841
   error = Pa_OpenStream(&stream, recDeviceNum, 2, paFloat32, NULL,
 
1842
                         playDeviceNum, 2, paFloat32, NULL,
 
1843
                         highestSampleRate, 512, 1, paClipOff | paDitherOff,
 
1844
                         audacityAudioCallback, NULL);
 
1845
 
 
1846
   if (error) {
 
1847
      error = Pa_OpenStream(&stream, recDeviceNum, 2, paFloat32, NULL,
 
1848
                            paNoDevice, 0, paFloat32, NULL,
 
1849
                            highestSampleRate, 512, 1, paClipOff | paDitherOff,
 
1850
                            audacityAudioCallback, NULL);
 
1851
   }
 
1852
 
 
1853
#endif
 
1854
 
 
1855
   if (error) {
 
1856
      s << wxT("Recieved ") << error << wxT(" while opening devices") << e;
 
1857
      return o.GetString();
 
1858
   }
 
1859
 
 
1860
   PxMixer *PortMixer = Px_OpenMixer(stream, 0);
 
1861
 
 
1862
   if (!PortMixer) {
 
1863
      s << wxT("Unable to open Portmixer") << e;
 
1864
      Pa_CloseStream(stream);
 
1865
      return o.GetString();
 
1866
   }
 
1867
 
 
1868
   s << wxT("==============================") << e;
 
1869
   s << wxT("Available mixers:") << e;
 
1870
 
 
1871
   cnt = Px_GetNumMixers(stream);
 
1872
   for (int i = 0; i < cnt; i++) {
 
1873
      wxString name(Px_GetMixerName(stream, i), wxConvLocal);
 
1874
      s << i << wxT(" - ") << name << e;
 
1875
   }
 
1876
 
 
1877
   s << wxT("==============================") << e;
 
1878
   s << wxT("Available capture sources:") << e;
 
1879
   cnt = Px_GetNumInputSources(PortMixer);
 
1880
   for (int i = 0; i < cnt; i++) {
 
1881
      wxString name(Px_GetInputSourceName(PortMixer, i), wxConvLocal);
 
1882
      s << i << wxT(" - ") << name << e;
 
1883
   }
 
1884
 
 
1885
   s << wxT("==============================") << e;
 
1886
   s << wxT("Available playback volumes:") << e;
 
1887
   cnt = Px_GetNumOutputVolumes(PortMixer);
 
1888
   for (int i = 0; i < cnt; i++) {
 
1889
      wxString name(Px_GetOutputVolumeName(PortMixer, i), wxConvLocal);
 
1890
      s << i << wxT(" - ") << name << e;
 
1891
   }
 
1892
 
 
1893
   // Determine mixer capabilities - it it doesn't support either
 
1894
   // input or output, we emulate them (by multiplying this value
 
1895
   // by all incoming/outgoing samples)
 
1896
 
 
1897
   MixerOutputVol = Px_GetPCMOutputVolume(PortMixer);
 
1898
   EmulateMixerOutputVol = false;
 
1899
   Px_SetPCMOutputVolume(PortMixer, 0.0);
 
1900
   if (Px_GetPCMOutputVolume(PortMixer) > 0.1)
 
1901
      EmulateMixerOutputVol = true;
 
1902
   Px_SetPCMOutputVolume(PortMixer, 0.2f);
 
1903
   if (Px_GetPCMOutputVolume(PortMixer) < 0.1 ||
 
1904
       Px_GetPCMOutputVolume(PortMixer) > 0.3)
 
1905
      EmulateMixerOutputVol = true;
 
1906
   Px_SetPCMOutputVolume(PortMixer, MixerOutputVol);
 
1907
 
 
1908
   MixerInputVol = Px_GetInputVolume(PortMixer);
 
1909
   EmulateMixerInputVol = false;
 
1910
   Px_SetInputVolume(PortMixer, 0.0);
 
1911
   if (Px_GetInputVolume(PortMixer) > 0.1)
 
1912
      EmulateMixerInputVol = true;
 
1913
   Px_SetInputVolume(PortMixer, 0.2f);
 
1914
   if (Px_GetInputVolume(PortMixer) < 0.1 ||
 
1915
       Px_GetInputVolume(PortMixer) > 0.3)
 
1916
      EmulateMixerInputVol = true;
 
1917
   Px_SetInputVolume(PortMixer, MixerInputVol);
 
1918
 
 
1919
   Pa_CloseStream(stream);
 
1920
 
 
1921
   s << wxT("==============================") << e;
 
1922
   s << wxT("Capture volume is ") << (EmulateMixerInputVol? wxT("emulated"): wxT("native")) << e;
 
1923
   s << wxT("Capture volume is ") << (EmulateMixerOutputVol? wxT("emulated"): wxT("native")) << e;
 
1924
 
 
1925
   Px_CloseMixer(PortMixer);
 
1926
 
 
1927
#endif
 
1928
 
 
1929
   return o.GetString();
 
1930
}
 
1931
 
1649
1932
// This method is the data gateway between the audio thread (which
1650
1933
// communicates with the disk) and the PortAudio callback thread
1651
1934
// (which communicates with the audio device.
1654
1937
   unsigned int i;
1655
1938
 
1656
1939
   gAudioIO->mAudioThreadFillBuffersLoopActive = true;
1657
 
   
 
1940
 
1658
1941
   if( mPlaybackTracks.GetCount() > 0 )
1659
1942
   {
1660
1943
      // Though extremely unlikely, it is possible that some buffers
1852
2135
   unsigned int i;
1853
2136
   int t;
1854
2137
 
 
2138
   // Send data to VU meters
 
2139
 
 
2140
   // It's critical that we don't update the meters while
 
2141
   // StopStream is trying to stop PortAudio, otherwise it can
 
2142
   // lead to a freeze.  We use two variables to synchronize:
 
2143
   // mUpdatingMeters tells StopStream when the callback is about
 
2144
   // to enter the code where it might update the meters, and
 
2145
   // mUpdateMeters is how the rest of the code tells the callback
 
2146
   // when it is allowed to actually do the updating.  Note that
 
2147
   // mUpdatingMeters must be set first to avoid a race condition.
 
2148
   gAudioIO->mUpdatingMeters = true;
 
2149
   if (gAudioIO->mUpdateMeters) {
 
2150
 
 
2151
      if (gAudioIO->mOutputMeter && 
 
2152
          !gAudioIO->mOutputMeter->IsMeterDisabled() &&
 
2153
          outputBuffer) {
 
2154
         gAudioIO->mOutputMeter->UpdateDisplay(numPlaybackChannels,
 
2155
                                               framesPerBuffer,
 
2156
                                               (float *)outputBuffer);
 
2157
      }
 
2158
 
 
2159
      if (gAudioIO->mInputMeter &&
 
2160
          !gAudioIO->mInputMeter->IsMeterDisabled() &&
 
2161
          inputBuffer) {
 
2162
         if (gAudioIO->mCaptureFormat == floatSample)
 
2163
            gAudioIO->mInputMeter->UpdateDisplay(numCaptureChannels,
 
2164
                                                 framesPerBuffer,
 
2165
                                                 (float *)inputBuffer);
 
2166
         else {
 
2167
            CopySamples((samplePtr)inputBuffer, gAudioIO->mCaptureFormat,
 
2168
                        (samplePtr)tempFloats, floatSample,
 
2169
                        framesPerBuffer * numCaptureChannels);
 
2170
            gAudioIO->mInputMeter->UpdateDisplay(numCaptureChannels,
 
2171
                                                 framesPerBuffer,
 
2172
                                                 tempFloats);
 
2173
         }
 
2174
      }
 
2175
   }
 
2176
   gAudioIO->mUpdatingMeters = false;
 
2177
 
 
2178
#ifdef EXPERIMENTAL_SMART_RECORD
 
2179
   // Stop recording if 'silence' is detected
 
2180
   if(gAudioIO->mPauseRec && inputBuffer) {
 
2181
      if(gAudioIO->mInputMeter->GetMaxPeak() < gAudioIO->mSilenceLevel ) {
 
2182
         if(!gAudioIO->IsPaused()) {
 
2183
            AudacityProject *p = GetActiveProject();
 
2184
            wxCommandEvent dummyEvt;
 
2185
            p->GetControlToolBar()->OnPause(dummyEvt);
 
2186
         }
 
2187
      }
 
2188
      else {
 
2189
         if(gAudioIO->IsPaused()) {
 
2190
            AudacityProject *p = GetActiveProject();
 
2191
            wxCommandEvent dummyEvt;
 
2192
            p->GetControlToolBar()->OnPause(dummyEvt);
 
2193
         }
 
2194
      }
 
2195
   }
 
2196
#endif
1855
2197
   if( gAudioIO->mPaused )
1856
2198
   {
1857
2199
      if (outputBuffer && numPlaybackChannels > 0)
1897
2239
                                  numCaptureChannels,
1898
2240
                                  (float *)outputBuffer, (int)framesPerBuffer, gain);
1899
2241
         }
1900
 
         
 
2242
 
1901
2243
         if (gAudioIO->mSeek)
1902
2244
         {
1903
2245
            // Pause audio thread and wait for it to finish
1916
2258
            gAudioIO->mSeek = 0.0;
1917
2259
            
1918
2260
            // Reset mixer positions and flush buffers for all tracks
 
2261
            gAudioIO->mT = gAudioIO->mT0 + ((gAudioIO->mTime - gAudioIO->mT0));
1919
2262
            for (i = 0; i < (unsigned int)numPlaybackTracks; i++)
1920
2263
            {
1921
 
               gAudioIO->mPlaybackMixers[i]->Reposition( gAudioIO->mTime );
1922
 
               gAudioIO->mPlaybackBuffers[i]->Discard( gAudioIO->mPlaybackBuffers[i]->AvailForGet() );
 
2264
               gAudioIO->mPlaybackMixers[i]->Reposition(gAudioIO->mT);
 
2265
               gAudioIO->mPlaybackBuffers[i]->Discard(gAudioIO->mPlaybackBuffers[i]->AvailForGet());
1923
2266
            }
1924
 
            gAudioIO->mT = gAudioIO->mTime;
1925
2267
 
1926
2268
            // Reload the ring buffers
1927
2269
            gAudioIO->mAudioThreadShouldCallFillBuffersOnce = true;
1987
2329
             #endif
1988
2330
            }
1989
2331
 
1990
 
            // Wrap to start if looping
1991
 
            if (gAudioIO->mPlayLooped && gAudioIO->mTime >= gAudioIO->mT1)
1992
 
            {
1993
 
               gAudioIO->mTime = gAudioIO->mT0 + (gAudioIO->mTime - gAudioIO->mT1);
1994
 
            }
1995
 
 
1996
2332
            if (vt->GetChannel() == Track::LeftChannel ||
1997
2333
                vt->GetChannel() == Track::MonoChannel)
1998
2334
            {
2099
2435
            }
2100
2436
         }
2101
2437
      }
2102
 
      
 
2438
 
 
2439
      // Calcuate the warp factor for this time position
 
2440
      double factor = 1.0;
 
2441
      if (gAudioIO->mTimeTrack) {
 
2442
         factor = gAudioIO->mTimeTrack->GetEnvelope()->GetValue(gAudioIO->mTime);
 
2443
         factor = (gAudioIO->mTimeTrack->GetRangeLower() *
 
2444
                  (1 - factor) +
 
2445
                  factor *
 
2446
                  gAudioIO->mTimeTrack->GetRangeUpper()) / 
 
2447
                  100.0;
 
2448
      }
 
2449
 
 
2450
      // Wrap to start if looping
 
2451
      if (gAudioIO->mPlayLooped && gAudioIO->mTime >= gAudioIO->mT1)
 
2452
      {
 
2453
         // LL:  This is not exactly right, but I'm at my wits end trying to
 
2454
         //      figure it out.  Feel free to fix it.  :-)
 
2455
         gAudioIO->mTime = gAudioIO->mT0 - ((gAudioIO->mTime - gAudioIO->mT1) * factor);
 
2456
      }
 
2457
 
2103
2458
      // Update the current time position
2104
 
      gAudioIO->mTime += ((framesPerBuffer / gAudioIO->mRate) / gAudioIO->mPlaySpeed);
2105
 
      
 
2459
      gAudioIO->mTime += ((framesPerBuffer / gAudioIO->mRate) * factor);
 
2460
 
2106
2461
      // Record the reported latency from PortAudio.
2107
2462
      // TODO: Don't recalculate this with every callback?
2108
2463
     #if USE_PORTAUDIO_V19
2151
2506
      }
2152
2507
   }
2153
2508
 
2154
 
   // Send data to VU meters
2155
 
 
2156
 
   // It's critical that we don't update the meters while
2157
 
   // StopStream is trying to stop PortAudio, otherwise it can
2158
 
   // lead to a freeze.  We use two variables to synchronize:
2159
 
   // mUpdatingMeters tells StopStream when the callback is about
2160
 
   // to enter the code where it might update the meters, and
2161
 
   // mUpdateMeters is how the rest of the code tells the callback
2162
 
   // when it is allowed to actually do the updating.  Note that
2163
 
   // mUpdatingMeters must be set first to avoid a race condition.
2164
 
   gAudioIO->mUpdatingMeters = true;
2165
 
   if (gAudioIO->mUpdateMeters) {
2166
 
 
2167
 
      if (!gAudioIO->mOutputMeter->IsMeterDisabled()
2168
 
            && gAudioIO->mOutputMeter && outputBuffer)
2169
 
         gAudioIO->mOutputMeter->UpdateDisplay(numPlaybackChannels,
2170
 
                                               framesPerBuffer,
2171
 
                                               (float *)outputBuffer);
2172
 
 
2173
 
      if (!gAudioIO->mInputMeter->IsMeterDisabled()
2174
 
            && gAudioIO->mInputMeter && inputBuffer) {
2175
 
         if (gAudioIO->mCaptureFormat == floatSample)
2176
 
            gAudioIO->mInputMeter->UpdateDisplay(numCaptureChannels,
2177
 
                                                 framesPerBuffer,
2178
 
                                                 (float *)inputBuffer);
2179
 
         else {
2180
 
            CopySamples((samplePtr)inputBuffer, gAudioIO->mCaptureFormat,
2181
 
                        (samplePtr)tempFloats, floatSample,
2182
 
                        framesPerBuffer * numCaptureChannels);
2183
 
            gAudioIO->mInputMeter->UpdateDisplay(numCaptureChannels,
2184
 
                                                 framesPerBuffer,
2185
 
                                                 tempFloats);
2186
 
         }
2187
 
      }
2188
 
   }
2189
 
   gAudioIO->mUpdatingMeters = false;
2190
 
 
2191
2509
   return callbackReturn;
2192
2510
}
2193
2511