diff options
| author | Gary Scavone <gary@music.mcgill.ca> | 2013-10-09 23:49:32 +0200 |
|---|---|---|
| committer | Stephen Sinclair <sinclair@music.mcgill.ca> | 2013-10-10 01:15:42 +0200 |
| commit | fdc3f15bec57b30fae67f65270392ba7a86680b8 (patch) | |
| tree | c40a558b21ec18df4a4fd2613ead8f54dd3c4156 /tests/Windows/rtaudiotest/rtaudiotest.cpp | |
| parent | 2b55be781872498a3b4c6cde60be4c2f69ec7eb4 (diff) | |
Version 3.0.2
Diffstat (limited to 'tests/Windows/rtaudiotest/rtaudiotest.cpp')
| -rw-r--r-- | tests/Windows/rtaudiotest/rtaudiotest.cpp | 386 |
1 files changed, 386 insertions, 0 deletions
diff --git a/tests/Windows/rtaudiotest/rtaudiotest.cpp b/tests/Windows/rtaudiotest/rtaudiotest.cpp new file mode 100644 index 0000000..90d8c2c --- /dev/null +++ b/tests/Windows/rtaudiotest/rtaudiotest.cpp @@ -0,0 +1,386 @@ +/************************************************************************/
+/*! \brief Interactively Test RtAudio parameters.
+
+ RtAudio is a command-line utility that allows users to enumerate
+ installed devices, and to test input, output and duplex operation
+ of RtAudio devices with various buffer and buffer-size
+ configurations.
+
+ Copyright (c) 2005 Robin Davies.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+/************************************************************************/
+
+#include "RtAudio.h"
+#include "FileWvOut.h"
+
+#include <cmath>
+#include <iostream>
+#include <stdopt.h>
+
+using namespace std;
+using namespace stdopt;
+
+#ifdef _WIN32
+// Correct windows.h standards violation.
+#undef min
+#undef max
+#endif
+
+#define DSOUND 1
+
+RtAudio::RtAudioApi rtApi = RtAudio::WINDOWS_DS;
+
+void DisplayHelp(std::ostream &os)
+{
+ os
+ << "rtaudiotest - Test rtaudio devices." << endl
+ << endl
+ << "Syntax:" << endl
+ << " rtaudiotest [options]* enum" << endl
+ << " - Display installed devices." << endl
+ << " rtaudiotest [options]* inputtest <devicenum> [<filename>]" << endl
+ << " - Capture audio to a .wav file." << endl
+ << " rtaudiotest [options]* outputtest <devicenum>" << endl
+ << " - Generate a test signal on the device.." << endl
+ << " rtaudiotest [options]* duplextest <inputDevicenum> <outputdevicenum>" << endl
+ << " - Echo input to output." << endl
+
+ << "Options:" << endl
+ << " -h -? Display this message." << endl
+ << " -dsound Use DirectX drivers." << endl
+ << " -asio Use ASIO drivers." << endl
+ << " -buffers N Use N buffers." << endl
+ << " -size N Use buffers of size N." << endl
+ << " -srate N Use a sample-rate of N (defaults to 44100)." << endl
+ << " -channels N Use N channels (defaults to 2)." << endl
+ << " -seconds N Run the test for N seconds (default 5)." << endl
+ << "Description: " << endl
+ << " RtAudio is a command-line utility that allows users to enumerate " << endl
+ << " installed devices, and to test input, output and duplex operation " << endl
+ << " of RtAudio devices with various buffer and buffer-size " << endl
+ << " configurations." << endl
+ << "Examples:" << endl
+ << " rtaudio -asio enum" << endl
+ << " rtaudio -dsound -buffers 4 -size 128 -seconds 3 inputtest 0 test.wav" << endl
+ ;
+
+}
+
+void EnumerateDevices(RtAudio::RtAudioApi api)
+{
+ RtAudio rt(api);
+ for (int i = 1; i <= rt.getDeviceCount(); ++i)
+ {
+ RtAudioDeviceInfo info = rt.getDeviceInfo(i);
+ cout << "Device " << i << ": " << info.name << endl;
+ }
+}
+
+struct TestConfiguration
+{
+ long srate;
+ int channels;
+ int bufferSize;
+ int buffers;
+ int seconds;
+};
+
+
+bool DisplayStats(RtAudio::RtAudioApi api)
+{
+#ifdef __WINDOWS_DS__
+ // Display latency results for Windows DSound drivers.
+ if (api == RtAudio::WINDOWS_DS)
+ {
+ RtApiDs::RtDsStatistics s = RtApiDs::getDsStatistics();
+
+ cout << " Latency: " << s.latency*1000.0 << "ms" << endl;
+ if (s.inputFrameSize)
+ {
+ cout << " Read overruns: " << s.numberOfReadOverruns << endl;
+ }
+ if (s.outputFrameSize)
+ {
+ cout << " Write underruns: " << s.numberOfWriteUnderruns << endl;
+ }
+
+ if (s.inputFrameSize)
+ {
+ cout << " Read lead time in sample frames (device): " << s.readDeviceSafeLeadBytes/ s.inputFrameSize << endl;
+ }
+ if (s.outputFrameSize)
+ {
+ cout << " Write lead time in sample frames (device): " << s.writeDeviceSafeLeadBytes / s.outputFrameSize << endl;
+ cout << " Write lead time in sample frames (buffer): " << s.writeDeviceBufferLeadBytes / s.outputFrameSize << endl;
+
+ }
+
+ }
+#endif
+ return true;
+}
+
+void InputTest( RtAudio::RtAudioApi api,
+ int inputDevice,
+ const std::string &fileName,
+ TestConfiguration &configuration )
+{
+ RtAudio rt(api);
+
+ int bufferSize = configuration.bufferSize;
+
+ RtAudioDeviceInfo info = rt.getDeviceInfo(inputDevice);
+ cout << "Reading from device " << inputDevice << " (" << info.name << ")\n";
+
+ rt.openStream(0,0,inputDevice,configuration.channels, RTAUDIO_SINT16, configuration.srate,&bufferSize,configuration.buffers);
+ if (bufferSize != configuration.bufferSize)
+ {
+ cout << "The buffer size was changed to " << bufferSize << " by the device." << endl;
+ configuration.bufferSize = bufferSize;
+
+ }
+
+ int nTicks = (int)ceil((configuration.srate* configuration.seconds)*1.0/configuration.bufferSize);
+
+ if (fileName.length() == 0)
+ {
+ // just run the stream.
+ rt.startStream();
+ for (int i = 0; i < nTicks; ++i)
+ {
+ rt.tickStream();
+ }
+ rt.stopStream();
+ } else
+ {
+ if (configuration.seconds > 10) {
+ throw CommandLineException("Capture of more than 10 seconds of data is not supported.");
+ }
+ std::vector<short> data;
+ // we could be smarter, but the point here is to capture data without interfering with the stream.
+ // File writes while ticking the stream is not cool.
+ data.resize(nTicks*configuration.bufferSize*configuration.channels); // potentially very big. That's why we restrict capture to 10 seconds.
+ short *pData = &data[0];
+
+ rt.startStream();
+ int i;
+ for (i = 0; i < nTicks; ++i)
+ {
+ rt.tickStream();
+ short *streamBuffer = (short*)rt.getStreamBuffer();
+ for (int samples = 0; samples < configuration.bufferSize; ++samples)
+ {
+ for (int channel = 0; channel < configuration.channels; ++channel)
+ {
+ *pData ++ = *streamBuffer++;
+ }
+ }
+ }
+ rt.stopStream();
+ remove(fileName.c_str());
+ FileWvOut wvOut;
+ wvOut.openFile( fileName.c_str(), configuration.channels, FileWrite::FILE_WAV );
+
+ StkFrames frame(1,configuration.channels,false);
+ pData = &data[0];
+
+ for (i = 0; i < nTicks; ++i) {
+ for (int samples = 0; samples < configuration.bufferSize; ++samples) {
+ for (int channel = 0; channel < configuration.channels; ++channel) {
+ frame[channel] = (float)( *pData++*( 1.0 / 32768.0 ) );
+ }
+ wvOut.tickFrame(frame);
+ }
+ }
+ wvOut.closeFile();
+ }
+ rt.closeStream();
+
+ if (DisplayStats(api)) {
+ cout << "Test succeeded." << endl;
+ }
+}
+
+void OutputTest( RtAudio::RtAudioApi api,
+ int outputDevice,
+ TestConfiguration &configuration )
+{
+ RtAudio rt(api);
+ int bufferSize = configuration.bufferSize;
+
+ RtAudioDeviceInfo info = rt.getDeviceInfo(outputDevice);
+ cout << "Writing to " << info.name << "...\n";
+
+ rt.openStream(outputDevice,configuration.channels, 0,0, RTAUDIO_SINT16, configuration.srate,&bufferSize,configuration.buffers);
+ if (bufferSize != configuration.bufferSize) {
+ cout << "The buffer size was changed to " << bufferSize << " by the device." << endl;
+ configuration.bufferSize = bufferSize;
+ }
+
+ rt.startStream();
+ short *pBuffer = (short*)rt.getStreamBuffer();
+ int nTicks = (int)ceil((configuration.srate* configuration.seconds)*1.0/configuration.bufferSize);
+
+ double phase = 0;
+ double deltaPhase = 880.0/configuration.srate;
+ for (int i = 0; i < nTicks; ++i) {
+ short *p = pBuffer;
+ for (int samp = 0; samp < configuration.bufferSize; ++samp) {
+ short val = (short)(sin(phase)*(32768/4)); // sin()*0.25 magnitude. Audible, but not damaging to ears or speakers.
+ phase += deltaPhase;
+
+ for (int chan = 0; chan < configuration.channels; ++chan) {
+ *p++ = val;
+ }
+ }
+ rt.tickStream();
+ }
+ rt.stopStream();
+ rt.closeStream();
+
+ if ( DisplayStats(api) ) {
+ cout << "Test succeeded." << endl;
+ }
+}
+
+void DuplexTest( RtAudio::RtAudioApi api,
+ int inputDevice,
+ int outputDevice,
+ TestConfiguration &configuration )
+{
+ RtAudio rt(api);
+ int bufferSize = configuration.bufferSize;
+
+ RtAudioDeviceInfo info = rt.getDeviceInfo(inputDevice);
+ cout << "Reading from " << info.name << ", " << endl;
+ info = rt.getDeviceInfo(outputDevice);
+ cout << "Writing to " << info.name << "..." << endl;
+
+ rt.openStream(outputDevice,configuration.channels, inputDevice,configuration.channels, RTAUDIO_SINT16, configuration.srate,&bufferSize,configuration.buffers);
+ if (bufferSize != configuration.bufferSize)
+ {
+ cout << "The buffer size was changed to " << bufferSize << " by the device." << endl;
+ configuration.bufferSize = bufferSize;
+ }
+
+ rt.startStream();
+ short *pBuffer = (short*)rt.getStreamBuffer();
+ int nTicks = (int)ceil((configuration.srate* configuration.seconds)*1.0/configuration.bufferSize);
+
+ for (int i = 0; i < nTicks; ++i) {
+ rt.tickStream();
+ }
+ rt.stopStream();
+ rt.closeStream();
+
+ if ( DisplayStats(api) ) {
+ cout << "Test succeeded." << endl;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ try
+ {
+ CommandLine commandLine;
+
+ TestConfiguration configuration;
+ bool displayHelp;
+ bool useDsound;
+ bool useAsio;
+
+ commandLine.AddOption("h",&displayHelp);
+ commandLine.AddOption("?",&displayHelp);
+ commandLine.AddOption("dsound",&useDsound);
+ commandLine.AddOption("asio",&useAsio);
+ commandLine.AddOption("srate",&configuration.srate,44100L);
+ commandLine.AddOption("channels",&configuration.channels,2);
+ commandLine.AddOption("seconds",&configuration.seconds,5);
+ commandLine.AddOption("buffers",&configuration.buffers,2);
+ commandLine.AddOption("size",&configuration.bufferSize,128);
+
+ commandLine.ProcessCommandLine(argc,argv);
+
+ if (displayHelp || commandLine.GetArguments().size() == 0)
+ {
+ DisplayHelp(cout);
+ return 0;
+ }
+ if (useDsound)
+ {
+ rtApi = RtAudio::WINDOWS_DS;
+ } else if (useAsio)
+ {
+ rtApi = RtAudio::WINDOWS_ASIO;
+ } else {
+ throw CommandLineException("Please specify an API to use: '-dsound', or '-asio'");
+ }
+
+ std::string testName;
+ commandLine.GetArgument(0,&testName);
+ if (testName == "enum")
+ {
+ EnumerateDevices(rtApi);
+ } else if (testName == "inputtest")
+ {
+ int inputDevice;
+ std::string fileName;
+ commandLine.GetArgument(1,&inputDevice);
+ if (commandLine.GetArguments().size() >= 2)
+ {
+ commandLine.GetArgument(2,&fileName);
+ }
+ InputTest(rtApi,inputDevice,fileName,configuration);
+ } else if (testName == "outputtest")
+ {
+ int inputDevice;
+ commandLine.GetArgument(1,&inputDevice);
+ OutputTest(rtApi,inputDevice,configuration);
+ } else if (testName == "duplextest")
+ {
+ int inputDevice;
+ int outputDevice;
+ commandLine.GetArgument(1,&inputDevice);
+ commandLine.GetArgument(2,&outputDevice);
+ DuplexTest(rtApi,inputDevice,outputDevice,configuration);
+ } else {
+ throw CommandLineException("Not a valid test name.");
+ }
+
+ } catch (CommandLineException &e)
+ {
+ cerr << e.what() << endl << endl;
+ cerr << "Run 'rtaudiotest -h' to see the commandline syntax." << endl;
+ return 3;
+ } catch (RtError &e)
+ {
+ cerr << e.getMessage() << endl;
+ return 3;
+
+ } catch (std::exception &e)
+ {
+ cerr << "Error: " << e.what() << endl;
+ return 3;
+
+ }
+ return 0;
+}
|
