Update of /cvsroot/audacity/audacity-src/src
In directory sc8-pr-cvs11.sourceforge.net:/tmp/cvs-serv23264

Modified Files:
        AudioIO.cpp AudioIO.h Project.cpp Project.h 
Log Message:
Support any sampling rate with indicator of actual rate used in status bar.


Index: Project.h
===================================================================
RCS file: /cvsroot/audacity/audacity-src/src/Project.h,v
retrieving revision 1.112
retrieving revision 1.113
diff -u -d -r1.112 -r1.113
--- Project.h   6 Nov 2006 10:20:50 -0000       1.112
+++ Project.h   19 Nov 2006 19:03:40 -0000      1.113
@@ -295,6 +295,7 @@
    void ReleaseKeyboard();
    
    // Audio IO callback methods
+   virtual void OnAudioIORate(int rate);
    virtual void OnAudioIOStartRecording();
    virtual void OnAudioIOStopRecording();
    virtual void OnAudioIONewBlockFiles(const wxString& blockFileLog);

Index: Project.cpp
===================================================================
RCS file: /cvsroot/audacity/audacity-src/src/Project.cpp,v
retrieving revision 1.290
retrieving revision 1.291
diff -u -d -r1.290 -r1.291
--- Project.cpp 17 Nov 2006 03:57:11 -0000      1.290
+++ Project.cpp 19 Nov 2006 19:03:40 -0000      1.291
@@ -471,7 +471,9 @@
       mProgressDialog[mProgressCurrent] = NULL;
    }
 
-   mStatusBar = CreateStatusBar();
+   int widths[] = {-1, 150};
+   mStatusBar = CreateStatusBar(2);
+   mStatusBar->SetStatusWidths(2, widths);
 
 #if wxUSE_DRAG_AND_DROP
    SetDropTarget(new AudacityDropTarget(this));
@@ -2268,7 +2270,8 @@
       // msmeyer: Before changing rate, check if rate is supported
       // by current sound card. If it is not, don't change it,
       // otherwise playback won't work.
-      if (AudioIO::GetSupportedSampleRates().Index((int)newRate) != 
wxNOT_FOUND)
+      wxArrayLong rates = AudioIO::GetSupportedSampleRates(wxT(""), wxT(""), 
newRate);
+      if (rates.Index((int)newRate) != wxNOT_FOUND)
       {
          mRate = newRate;
          GetSelectionBar()->SetRate(mRate);
@@ -3098,6 +3101,13 @@
    mLastAutoSaveTime = wxGetLocalTime();
 }
 
+void AudacityProject::OnAudioIORate(int rate)
+{
+   mStatusBar->SetStatusText(wxString::Format(_("Actual Rate %d"),
+                                              rate), 1);
+   
+}
+
 void AudacityProject::OnAudioIOStartRecording()
 {
    // Before recording is started, auto-save the file. The file will have

Index: AudioIO.cpp
===================================================================
RCS file: /cvsroot/audacity/audacity-src/src/AudioIO.cpp,v
retrieving revision 1.148
retrieving revision 1.149
diff -u -d -r1.148 -r1.149
--- AudioIO.cpp 5 Nov 2006 08:08:46 -0000       1.148
+++ AudioIO.cpp 19 Nov 2006 19:03:40 -0000      1.149
@@ -59,6 +59,7 @@
 #include "AudioIO.h"
 #include "WaveTrack.h"
 #include "Mix.h"
+#include "Resample.h"
 #include "RingBuffer.h"
 #include "Prefs.h"
 #include "TimeTrack.h"
@@ -72,6 +73,16 @@
 // static
 int AudioIO::mNextStreamToken = 0;
 
+const int AudioIO::StandardRates[] = {
+   8000,
+   16000,
+   22050,
+   44100,
+   48000
+};
+const int AudioIO::NumStandardRates = sizeof(AudioIO::StandardRates) /
+                                      sizeof(AudioIO::StandardRates[0]);
+
 #if USE_PORTAUDIO_V19
 int audacityAudioCallback(const void *inputBuffer, void *outputBuffer,
                           unsigned long framesPerBuffer,
@@ -532,7 +543,10 @@
                                    sampleFormat captureFormat)
 {
    mLastPaError = paNoError;
-   mRate = GetBestRate(sampleRate);
+   mRate = GetBestRate(numCaptureChannels > 0, sampleRate);
+   if (mListener) {
+      mListener->OnAudioIORate((int)mRate);
+   }
    
    // Special case: Our 24-bit sample format is different from PortAudio's
    // 3-byte packed format. So just make PortAudio return float samples,
@@ -962,10 +976,15 @@
       sampleCount captureBufferSize =
          (sampleCount)(mRate * mCaptureRingBufferSecs + 0.5);
       mCaptureBuffers = new RingBuffer* [mCaptureTracks.GetCount()];
+      mResample = new Resample* [mCaptureTracks.GetCount()];
+      mFactor = sampleRate / mRate;
 
       for( unsigned int i = 0; i < mCaptureTracks.GetCount(); i++ )
+      {
          mCaptureBuffers[i] = new RingBuffer( 
mCaptureTracks[i]->GetSampleFormat(),
                                               captureBufferSize );
+         mResample[i] = new Resample( true, mFactor, mFactor );
+      }
    }
 
    // We signal the audio thread to call FillBuffers, to prime the RingBuffers
@@ -1303,158 +1322,218 @@
 }
 
 
-wxArrayLong AudioIO::GetSupportedSampleRates(wxString playDevice, wxString 
recDevice)
+wxArrayLong AudioIO::GetSupportedPlaybackRates(wxString devName, double rate)
 {
-   int numDefaultRates = 7;
-   int defaultRates[] = {
-      8000,
-      11025,
-      16000,
-      22050,
-      44100,
-      48000,
-      96000
-   };
+   wxArrayLong supported;
+   int irate = (int)rate;
+   const PaDeviceInfo* devInfo = NULL;
+   int devIndex = -1;
+   int i;
 
-   const PaDeviceInfo* playInfo = NULL;
-   const PaDeviceInfo* recInfo = NULL;
-   int playIndex = -1, recIndex = -1;
+   if (devName.IsEmpty())
+   {
+      devName = gPrefs->Read(wxT("/AudioIO/PlaybackDevice"), wxT(""));
+   }
 
 #if USE_PORTAUDIO_V19
-   double latencyDuration = 100.0;
-   long recordChannels = 1;
-   gPrefs->Read(wxT("/AudioIO/LatencyDuration"), &latencyDuration);
-   gPrefs->Read(wxT("/AudioIO/RecordChannels"), &recordChannels);
+   for (i = 0; i < Pa_GetDeviceCount(); i++)
+#else
+   for (i = 0; i < Pa_CountDevices(); i++)
 #endif
+   {
+      const PaDeviceInfo* info = Pa_GetDeviceInfo(i);
 
-   if (playDevice.IsEmpty())
-      playDevice = gPrefs->Read(wxT("/AudioIO/PlaybackDevice"), wxT(""));
-   if (recDevice.IsEmpty())
-      recDevice = gPrefs->Read(wxT("/AudioIO/RecordingDevice"), wxT(""));
+      if (info && DeviceName(info) == devName && info->maxOutputChannels > 0)
+      {
+         devInfo = info;
+         devIndex = i;
+         break;
+      }
+   }
 
-   int i;
+   if (!devInfo)
+   {
+      return supported;
+   }
 
-   // msmeyer: Find info structs for playing/recording devices
 #if USE_PORTAUDIO_V19
-   for (i = 0; i < Pa_GetDeviceCount(); i++) {
-#else
-   for (i = 0; i < Pa_CountDevices(); i++) {
-#endif
-      const PaDeviceInfo* info = Pa_GetDeviceInfo(i);
+   PaStreamParameters pars;
 
-      if(!info)
-         continue;
+   pars.device = devIndex;
+   pars.channelCount = 2;
+   pars.sampleFormat = paFloat32;
+   pars.suggestedLatency = devInfo->defaultHighOutputLatency;
+   pars.hostApiSpecificStreamInfo = NULL;
+   
+   for (i = 0; i < NumStandardRates; i++)
+   {
+      if (Pa_IsFormatSupported(NULL, &pars, StandardRates[i]) == 0)
+      {
+         supported.Add(StandardRates[i]);
+      }
+   }
 
-      if (DeviceName(info) == playDevice && info->maxOutputChannels > 0)
+   if (irate != 0 && supported.Index(irate) == wxNOT_FOUND)
+   {
+      if (Pa_IsFormatSupported(NULL, &pars, irate) == 0)
       {
-         playInfo = info;
-         playIndex = i;
+         supported.Add(irate);
       }
-      if (DeviceName(info) == recDevice && info->maxInputChannels > 0)
+   }
+#else
+   if (devInfo->numSampleRates == -1)
+   {
+      for (i = 0; i < NumStandardRates; i++)
       {
-         recInfo = info;
-         recIndex = i;
+         if (StandardRates[i] >= devInfo->sampleRates[0] &&
+             StandardRates[i] <= devInfo->sampleRates[1])
+         {
+            supported.Add(StandardRates[i]);
+         }
+      }
+
+      if (irate != 0 && supported.Index(irate) == wxNOT_FOUND)
+      {
+         if (irate >= devInfo->sampleRates[0] &&
+             irate <= devInfo->sampleRates[1])
+         {
+            supported.Add(irate);
+         }
       }
    }
+   else
+   {
+      for (i = 0; i < devInfo->numSampleRates; i++)
+      {
+         supported.Add((int)devInfo->sampleRates[i]);
+      }
+   }
+#endif
 
-   // msmeyer: Check which sample rates the play device supports
-   wxArrayLong playSampleRates;
+   return supported;
+}
 
-   if (playInfo)
+wxArrayLong AudioIO::GetSupportedCaptureRates(wxString devName, double rate)
+{
+   wxArrayLong supported;
+   int irate = (int)rate;
+   const PaDeviceInfo* devInfo = NULL;
+   int devIndex = -1;
+   int i;
+
+   if (devName.IsEmpty())
    {
+      devName = gPrefs->Read(wxT("/AudioIO/RecordingDevice"), wxT(""));
+   }
+
 #if USE_PORTAUDIO_V19
-      PaStreamParameters pars;
+   double latencyDuration = 100.0;
+   long recordChannels = 1;
+   gPrefs->Read(wxT("/AudioIO/LatencyDuration"), &latencyDuration);
+   gPrefs->Read(wxT("/AudioIO/RecordChannels"), &recordChannels);
+#endif
 
-      pars.device = playIndex;
-      pars.channelCount = 2;
-      pars.sampleFormat = paFloat32;
-      pars.suggestedLatency = latencyDuration;
-      pars.hostApiSpecificStreamInfo = NULL;
-      
-      for (i = 0; i < numDefaultRates; i++)
-      {
-         if (Pa_IsFormatSupported(NULL, &pars, defaultRates[i]) == 0)
-            playSampleRates.Add(defaultRates[i]);
-      }
+#if USE_PORTAUDIO_V19
+   for (i = 0; i < Pa_GetDeviceCount(); i++)
 #else
-      if (playInfo->numSampleRates == -1)
-      {
-         for (i = 0; i < numDefaultRates; i++)
-            if (defaultRates[i] >= playInfo->sampleRates[0] &&
-                defaultRates[i] <= playInfo->sampleRates[1])
-               playSampleRates.Add(defaultRates[i]);
-      } else
+   for (i = 0; i < Pa_CountDevices(); i++)
+#endif
+   {
+      const PaDeviceInfo* info = Pa_GetDeviceInfo(i);
+
+      if (info && DeviceName(info) == devName && info->maxInputChannels > 0)
       {
-         for (i = 0; i < playInfo->numSampleRates; i++)
-            playSampleRates.Add((int)playInfo->sampleRates[i]);
+         devInfo = info;
+         devIndex = i;
+         break;
       }
-#endif
    }
 
-   if (playSampleRates.IsEmpty())
+   if (!devInfo)
    {
-      for (i = 0; i < numDefaultRates; i++)
-         playSampleRates.Add(defaultRates[i]);
+      return supported;
    }
 
-   // msmeyer: Check which sample rates the record device supports
-   wxArrayLong recSampleRates;
+#if USE_PORTAUDIO_V19
+   PaStreamParameters pars;
 
-   if (recInfo)
+   pars.device = devIndex;
+   pars.channelCount = recordChannels;
+   pars.sampleFormat = paFloat32;
+   pars.suggestedLatency = latencyDuration;
+   pars.hostApiSpecificStreamInfo = NULL;
+   
+   for (i = 0; i < NumStandardRates; i++)
    {
-#if USE_PORTAUDIO_V19
-      PaStreamParameters pars;
+      if (Pa_IsFormatSupported(NULL, &pars, StandardRates[i]) == 0)
+      {
+         supported.Add(StandardRates[i]);
+      }
+   }
 
-      pars.device = recIndex;
-      pars.channelCount = recordChannels;
-      pars.sampleFormat = paFloat32;
-      pars.suggestedLatency = latencyDuration;
-      pars.hostApiSpecificStreamInfo = NULL;
-      
-      for (i = 0; i < numDefaultRates; i++)
+   if (irate != 0 && supported.Index(irate) == wxNOT_FOUND)
+   {
+      if (Pa_IsFormatSupported(NULL, &pars, irate) == 0)
       {
-         if (Pa_IsFormatSupported(&pars, NULL, defaultRates[i]) == 0)
-            recSampleRates.Add(defaultRates[i]);
+         supported.Add(irate);
       }
+   }
 #else
-      if (recInfo->numSampleRates == -1)
+   if (devInfo->numSampleRates == -1)
+   {
+      for (i = 0; i < NumStandardRates; i++)
       {
-         for (i = 0; i < numDefaultRates; i++)
-            if (defaultRates[i] >= recInfo->sampleRates[0] &&
-                defaultRates[i] <= recInfo->sampleRates[1])
-               recSampleRates.Add(defaultRates[i]);
-      } else
+         if (StandardRates[i] >= devInfo->sampleRates[0] &&
+             StandardRates[i] <= devInfo->sampleRates[1])
+         {
+            supported.Add(StandardRates[i]);
+         }
+      }
+
+      if (irate != 0 && supported.Index(irate) == wxNOT_FOUND)
       {
-         for (i = 0; i < recInfo->numSampleRates; i++)
-            recSampleRates.Add((int)recInfo->sampleRates[i]);
+         if (irate >= devInfo->sampleRates[0] &&
+             irate <= devInfo->sampleRates[1])
+         {
+            supported.Add(irate);
+         }
       }
-#endif
    }
-
-   if (recSampleRates.IsEmpty())
+   else
    {
-      for (i = 0; i < numDefaultRates; i++)
-         recSampleRates.Add(defaultRates[i]);
+      for (i = 0; i < devInfo->numSampleRates; i++)
+      {
+         supported.Add((int)devInfo->sampleRates[i]);
+      }
    }
+#endif
+
+   return supported;
+}
+
+wxArrayLong AudioIO::GetSupportedSampleRates(wxString playDevice, wxString 
recDevice, double rate)
+{
+   wxArrayLong playback = GetSupportedPlaybackRates(playDevice, rate);
+   wxArrayLong capture = GetSupportedCaptureRates(recDevice, rate);
+   int i;
 
    // Return only sample rates which are in both arrays
    wxArrayLong result;
 
-   for (i = 0; i < (int)playSampleRates.GetCount(); i++)
-      if (recSampleRates.Index(playSampleRates[i]) != wxNOT_FOUND)
-         result.Add(playSampleRates[i]);
+   for (i = 0; i < (int)playback.GetCount(); i++)
+      if (capture.Index(playback[i]) != wxNOT_FOUND)
+         result.Add(playback[i]);
 
    // If this yields no results, use the default sample rates nevertheless
    if (result.IsEmpty())
    {
-      for (i = 0; i < numDefaultRates; i++)
-         result.Add(defaultRates[i]);
+      for (i = 0; i < NumStandardRates; i++)
+         result.Add(StandardRates[i]);
    }
 
    return result;
 }
 
-
 int AudioIO::GetOptimalSupportedSampleRate()
 {
    wxArrayLong rates = GetSupportedSampleRates();
@@ -1468,15 +1547,36 @@
    return rates[rates.GetCount() - 1];
 }
 
-long AudioIO::GetBestRate(double sampleRate)
+long AudioIO::GetBestRate(bool capturing, double sampleRate)
 {
-   wxArrayLong rates = GetSupportedSampleRates();
+   wxArrayLong rates;
+   int i;
+
+   if (capturing) {
+      rates = GetSupportedCaptureRates(wxT(""), sampleRate);
+   }
+   else {
+      rates = GetSupportedPlaybackRates(wxT(""), sampleRate);
+   }
+
    long rate = (long)sampleRate;
    
    if (rates.Index(rate) != wxNOT_FOUND) {
       return rate;
    }
 
+   if (rates.IsEmpty() || rate < 44100 && rates.Index(44100)) {
+      return 44100;
+   }
+
+   if (rate < 48000 && rates.Index(48000)) {
+      return 48000;
+   }
+
+   if (rate < 96000 && rates.Index(96000)) {
+      return 96000;
+   }
+
    return rates[rates.GetCount() - 1];
 }      
 
@@ -1642,13 +1742,30 @@
             sampleFormat trackFormat = mCaptureTracks[i]->GetSampleFormat();
 
             XMLStringWriter appendLog;
-            
-            samplePtr temp = NewSamples(avail, trackFormat);
-            mCaptureBuffers[i]->Get   (temp, trackFormat, avail);
-            mCaptureTracks[i]-> Append(temp, trackFormat, avail, 1, 
-                                       &appendLog);
-            DeleteSamples(temp);
-                                       
+
+            if( mFactor == 1.0 )
+            {
+               samplePtr temp = NewSamples(avail, trackFormat);
+               mCaptureBuffers[i]->Get   (temp, trackFormat, avail);
+               mCaptureTracks[i]-> Append(temp, trackFormat, avail, 1, 
+                                          &appendLog);
+               DeleteSamples(temp);
+            }
+            else
+            {
+               int size = avail * mFactor;
+               samplePtr temp1 = NewSamples(avail, floatSample);
+               samplePtr temp2 = NewSamples(size, floatSample);
+               mCaptureBuffers[i]->Get(temp1, floatSample, avail);
+
+               size = mResample[i]->Process(mFactor, (float *)temp1, avail, 
true,
+                                            &size, (float *)temp2, size);
+               mCaptureTracks[i]-> Append(temp2, floatSample, size, 1, 
+                                          &appendLog);
+               DeleteSamples(temp1);
+               DeleteSamples(temp2);
+            }
+
             if (!appendLog.IsEmpty())
             {
                blockFileLog.StartTag(wxT("recordingrecovery"));

Index: AudioIO.h
===================================================================
RCS file: /cvsroot/audacity/audacity-src/src/AudioIO.h,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -d -r1.46 -r1.47
--- AudioIO.h   4 Oct 2006 02:58:10 -0000       1.46
+++ AudioIO.h   19 Nov 2006 19:03:40 -0000      1.47
@@ -30,6 +30,7 @@
 class AudioIO;
 class RingBuffer;
 class Mixer;
+class Resample;
 class TimeTrack;
 class AudioThread;
 class Meter;
@@ -45,6 +46,7 @@
    AudioIOListener() {}
    virtual ~AudioIOListener() {}
    
+   virtual void OnAudioIORate(int rate) = 0;
    virtual void OnAudioIOStartRecording() = 0;
    virtual void OnAudioIOStopRecording() = 0;
    virtual void OnAudioIONewBlockFiles(const wxString& blockFileLog) = 0;
@@ -121,6 +123,32 @@
       each call to StartStream currently */
    void SetMeters(Meter *inputMeter, Meter *outputMeter);
    
+   /* Get a list of sample rates the current output device supports.
+    * If no information about available sample rates can be fetched,
+    * an empty list is returned.
+    *
+    * You can explicitely give the name of the device.  If you don't
+    * give it, the default device from the preferences will be used.
+    *
+    * You may also specify a rate for which to check in addition to the
+    * standard rates.
+    */
+   static wxArrayLong GetSupportedPlaybackRates(wxString devName = wxT(""),
+                                                double rate = 0.0);
+
+   /* Get a list of sample rates the current input device supports.
+    * If no information about available sample rates can be fetched,
+    * an empty list is returned.
+    *
+    * You can explicitely give the name of the device.  If you don't
+    * give it, the default device from the preferences will be used.
+    *
+    * You may also specify a rate for which to check in addition to the
+    * standard rates.
+    */
+   static wxArrayLong GetSupportedCaptureRates(wxString devName = wxT(""),
+                                               double rate = 0.0);
+
    /* Get a list of sample rates the current input/output device
     * supports. Since there is no concept (yet) for different input/output
     * sample rates, this currently returns only sample rates that are
@@ -130,9 +158,12 @@
     * You can explicitely give the names of the playDevice/recDevice.
     * If you don't give them, the default devices from the preferences
     * will be used.
+    * You may also specify a rate for which to check in addition to the
+    * standard rates.
     */
    static wxArrayLong GetSupportedSampleRates(wxString playDevice = wxT(""),
-                                              wxString recDevice = wxT(""));
+                                              wxString recDevice = wxT(""),
+                                              double rate = 0.0);
 
    /* Get a supported sample rate which can be used a an optimal
     * default. Currently, this uses the first supported rate in
@@ -150,8 +181,11 @@
    sampleFormat GetCaptureFormat() { return mCaptureFormat; }
    int GetNumCaptureChannels() { return mNumCaptureChannels; }
 
+   static const int StandardRates[];
+   static const int NumStandardRates;
+
 private:
-   long GetBestRate(double sampleRate);
+   long GetBestRate(bool capturing, double sampleRate);
 
    bool StartPortAudioStream(double sampleRate,
                              unsigned int numPlaybackChannels,
@@ -166,6 +200,7 @@
    double NormalizeStreamTime(double absoluteTime) const;
 
    AudioThread        *mThread;
+   Resample          **mResample;
    RingBuffer        **mCaptureBuffers;
    WaveTrackArray      mCaptureTracks;
    RingBuffer        **mPlaybackBuffers;
@@ -174,6 +209,7 @@
    int                 mStreamToken;
    int                 mStopStreamCount;
    static int          mNextStreamToken;
+   double              mFactor;
    double              mRate;
    double              mT;
    double              mT0;


-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Audacity-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/audacity-cvs

Reply via email to