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