1 /******************************************/
2 /*
3   teststop.cpp
4   by Gary P. Scavone, 2011
5 
6   This program starts and stops an RtAudio
7   stream many times in succession and in
8   different ways to to test its functionality.
9 */
10 /******************************************/
11 
12 #include "RtAudio.h"
13 #include <iostream>
14 #include <cstdlib>
15 #include <cstring>
16 #include <cstdio>
17 
18 #define PULSE_RATE 0.01  // seconds
19 #define RUNTIME    0.4   // seconds
20 #define PAUSETIME  0.1   // seconds
21 #define REPETITIONS 10
22 
23 // Platform-dependent sleep routines.
24 #if defined( WIN32 )
25   #include <windows.h>
26   #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds )
27 #else // Unix variants
28   #include <unistd.h>
29   #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) )
30 #endif
31 
usage(void)32 void usage( void ) {
33   // Error function in case of incorrect command-line
34   // argument specifications
35   std::cout << "\nuseage: teststops N fs <iDevice> <oDevice> <iChannelOffset> <oChannelOffset>\n";
36   std::cout << "    where N = number of channels,\n";
37   std::cout << "    fs = the sample rate,\n";
38   std::cout << "    iDevice = optional input device to use (default = 0),\n";
39   std::cout << "    oDevice = optional output device to use (default = 0),\n";
40   std::cout << "    iChannelOffset = an optional input channel offset (default = 0),\n";
41   std::cout << "    and oChannelOffset = optional output channel offset (default = 0).\n\n";
42   exit( 0 );
43 }
44 
45 struct MyData {
46   unsigned int channels;
47   unsigned int pulseCount;
48   unsigned int frameCounter;
49   unsigned int nFrames;
50   unsigned int returnValue;
51 };
52 
53 // Interleaved buffers
pulse(void * outputBuffer,void *,unsigned int nBufferFrames,double,RtAudioStreamStatus status,void * mydata)54 int pulse( void *outputBuffer, void * /*inputBuffer*/, unsigned int nBufferFrames,
55            double /*streamTime*/, RtAudioStreamStatus status, void *mydata )
56 {
57   // Write out a pulse signal and ignore the input buffer.
58   unsigned int i, j;
59   float sample;
60   float *buffer = (float *) outputBuffer;
61   MyData *data = (MyData *) mydata;
62 
63   if ( status ) std::cout << "Stream over/underflow detected!" << std::endl;
64 
65   for ( i=0; i<nBufferFrames; i++ ) {
66     if ( data->frameCounter % data->pulseCount == 0 ) sample = 0.9f;
67     else sample = 0.0;
68     for ( j=0; j<data->channels; j++ )
69       *buffer++ = sample;
70 
71     data->frameCounter++;
72   }
73 
74   if ( data->frameCounter >= data->nFrames )
75     return data->returnValue;
76   else
77     return 0;
78 }
79 
main(int argc,char * argv[])80 int main( int argc, char *argv[] )
81 {
82   unsigned int bufferFrames, fs, oDevice = 0, iDevice = 0, iOffset = 0, oOffset = 0;
83   unsigned int runtime, pausetime;
84   char input;
85 
86   // minimal command-line checking
87   if (argc < 3 || argc > 7 ) usage();
88 
89   RtAudio *adc = new RtAudio();
90   if ( adc->getDeviceCount() < 1 ) {
91     std::cout << "\nNo audio devices found!\n";
92     exit( 1 );
93   }
94 
95   MyData mydata;
96   mydata.channels = (unsigned int) atoi( argv[1] );
97   fs = (unsigned int) atoi( argv[2] );
98   if ( argc > 3 )
99     iDevice = (unsigned int) atoi( argv[3] );
100   if ( argc > 4 )
101     oDevice = (unsigned int) atoi(argv[4]);
102   if ( argc > 5 )
103     iOffset = (unsigned int) atoi(argv[5]);
104   if ( argc > 6 )
105     oOffset = (unsigned int) atoi(argv[6]);
106 
107   // Let RtAudio print messages to stderr.
108   adc->showWarnings( true );
109 
110   runtime = static_cast<unsigned int>(RUNTIME * 1000);
111   pausetime = static_cast<unsigned int>(PAUSETIME * 1000);
112 
113   // Set our stream parameters for a duplex stream.
114   bufferFrames = 512;
115   RtAudio::StreamParameters oParams, iParams;
116   oParams.deviceId = oDevice;
117   oParams.nChannels = mydata.channels;
118   oParams.firstChannel = oOffset;
119 
120   iParams.deviceId = iDevice;
121   iParams.nChannels = mydata.channels;
122   iParams.firstChannel = iOffset;
123 
124   if ( iDevice == 0 )
125     iParams.deviceId = adc->getDefaultInputDevice();
126   if ( oDevice == 0 )
127     oParams.deviceId = adc->getDefaultOutputDevice();
128 
129   // First, test external stopStream() calls.
130   mydata.pulseCount = static_cast<unsigned int>(PULSE_RATE * fs);
131   mydata.nFrames = 50 * fs;
132   mydata.returnValue = 0;
133   try {
134     adc->openStream( &oParams, &iParams, RTAUDIO_SINT32, fs, &bufferFrames, &pulse, (void *)&mydata );
135 
136     std::cout << "Press <enter> to start test.\n";
137     std::cin.get( input );
138 
139     for (int i=0; i<REPETITIONS; i++ ) {
140       mydata.frameCounter = 0;
141       adc->startStream();
142       std::cout << "Stream started ... ";
143       SLEEP( runtime );
144       adc->stopStream();
145       std::cout << "stream externally stopped.\n";
146       SLEEP( pausetime );
147     }
148   }
149   catch ( RtAudioError& e ) {
150     e.printMessage();
151     goto cleanup;
152   }
153 
154   adc->closeStream();
155 
156   // Next, test internal stopStream() calls.
157   mydata.nFrames = (unsigned int) (RUNTIME * fs);
158   mydata.returnValue = 1;
159   try {
160     adc->openStream( &oParams, &iParams, RTAUDIO_SINT32, fs, &bufferFrames, &pulse, (void *)&mydata );
161 
162     std::cin.clear();
163     fflush(stdin);
164     std::cout << "\nPress <enter> to continue test.\n";
165     std::cin.get( input );
166 
167     for (int i=0; i<REPETITIONS; i++ ) {
168       mydata.frameCounter = 0;
169       adc->startStream();
170       std::cout << "Stream started ... ";
171       while ( adc->isStreamRunning() ) SLEEP( 5 );
172       std::cout << "stream stopped via callback return value = 1.\n";
173       SLEEP( pausetime );
174     }
175   }
176   catch ( RtAudioError& e ) {
177     e.printMessage();
178     goto cleanup;
179   }
180 
181   adc->closeStream();
182 
183   // Test internal abortStream() calls.
184   mydata.returnValue = 2;
185   try {
186     adc->openStream( &oParams, &iParams, RTAUDIO_SINT32, fs, &bufferFrames, &pulse, (void *)&mydata );
187     std::cin.clear();
188     fflush(stdin);
189     std::cout << "\nPress <enter> to continue test.\n";
190     std::cin.get( input );
191 
192     for (int i=0; i<REPETITIONS; i++ ) {
193       mydata.frameCounter = 0;
194       adc->startStream();
195       std::cout << "Stream started ... ";
196       while ( adc->isStreamRunning() ) SLEEP( 5 );
197       std::cout << "stream aborted via callback return value = 2.\n";
198       SLEEP( pausetime );
199     }
200   }
201   catch ( RtAudioError& e ) {
202     e.printMessage();
203     goto cleanup;
204   }
205 
206   adc->closeStream();
207 
208   // Test consecutive stream re-opening.
209   mydata.returnValue = 0;
210   mydata.nFrames = 50 * fs;
211   try {
212 
213     std::cin.clear();
214     fflush(stdin);
215     std::cout << "\nPress <enter> to continue test.\n";
216     std::cin.get( input );
217 
218     for (int i=0; i<REPETITIONS; i++ ) {
219       adc->openStream( &oParams, &iParams, RTAUDIO_SINT32, fs, &bufferFrames, &pulse, (void *)&mydata );
220       mydata.frameCounter = 0;
221       adc->startStream();
222       std::cout << "New stream started ... ";
223       SLEEP( runtime );
224       adc->stopStream();
225       adc->closeStream();
226       std::cout << "stream stopped externally and closed.\n";
227       SLEEP( pausetime );
228     }
229   }
230   catch ( RtAudioError& e ) {
231     e.printMessage();
232     goto cleanup;
233   }
234 
235   delete adc;
236   adc = 0;
237 
238   // Test consecutive RtAudio creating and deletion.
239   try {
240 
241     std::cin.clear();
242     fflush(stdin);
243     std::cout << "\nPress <enter> to continue test.\n";
244     std::cin.get( input );
245 
246     for (int i=0; i<REPETITIONS; i++ ) {
247       adc = new RtAudio();
248       adc->openStream( &oParams, &iParams, RTAUDIO_SINT32, fs, &bufferFrames, &pulse, (void *)&mydata );
249       mydata.frameCounter = 0;
250       adc->startStream();
251       std::cout << "New instance and stream started ... ";
252       SLEEP( runtime );
253       adc->stopStream();
254       adc->closeStream();
255       delete adc;
256       adc = 0;
257       std::cout << "stream stopped and instance deleted.\n";
258       SLEEP( pausetime );
259     }
260   }
261   catch ( RtAudioError& e ) {
262     e.printMessage();
263     goto cleanup;
264   }
265 
266  cleanup:
267   if ( adc && adc->isStreamOpen() ) adc->closeStream();
268   if ( adc ) delete adc;
269 
270   return 0;
271 }
272