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