Further repository structure changes (gps).
[rtaudio-cdist.git] / tests / testall.cpp
1 /******************************************/
2 /*
3   testall.cpp
4   by Gary P. Scavone, 2007
5
6   This program will make a variety of calls
7   to extensively test RtAudio functionality.
8 */
9 /******************************************/
10
11 #include "RtAudio.h"
12 #include <iostream>
13
14 #define BASE_RATE 0.005
15 #define TIME   1.0
16
17 void usage( void ) {
18   // Error function in case of incorrect command-line
19   // argument specifications
20   std::cout << "\nuseage: testall N fs <device> <channelOffset>\n";
21   std::cout << "    where N = number of channels,\n";
22   std::cout << "    fs = the sample rate,\n";
23   std::cout << "    device = optional device to use (default = 0),\n";
24   std::cout << "    and channelOffset = an optional channel offset on the device (default = 0).\n\n";
25   exit( 0 );
26 }
27
28 unsigned int channels;
29
30 // Interleaved buffers
31 int sawi( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
32           double streamTime, RtAudioStreamStatus status, void *data )
33 {
34   unsigned int i, j;
35   extern unsigned int channels;
36   double *buffer = (double *) outputBuffer;
37   double *lastValues = (double *) data;
38
39   if ( status )
40     std::cout << "Stream underflow detected!" << std::endl;
41
42   for ( i=0; i<nBufferFrames; i++ ) {
43     for ( j=0; j<channels; j++ ) {
44       *buffer++ = (double) lastValues[j];
45       lastValues[j] += BASE_RATE * (j+1+(j*0.1));
46       if ( lastValues[j] >= 1.0 ) lastValues[j] -= 2.0;
47     }
48   }
49
50   return 0;
51 }
52
53 // Non-interleaved buffers
54 int sawni( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
55            double streamTime, RtAudioStreamStatus status, void *data )
56 {
57   unsigned int i, j;
58   extern unsigned int channels;
59   double *buffer = (double *) outputBuffer;
60   double *lastValues = (double *) data;
61
62   if ( status )
63     std::cout << "Stream underflow detected!" << std::endl;
64
65   float increment;
66   for ( j=0; j<channels; j++ ) {
67     increment = BASE_RATE * (j+1+(j*0.1));
68     for ( i=0; i<nBufferFrames; i++ ) {
69       *buffer++ = (double) lastValues[j];
70       lastValues[j] += increment;
71       if ( lastValues[j] >= 1.0 ) lastValues[j] -= 2.0;
72     }
73   }
74
75   return 0;
76 }
77
78 int inout( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
79            double streamTime, RtAudioStreamStatus status, void *data )
80 {
81   // Since the number of input and output channels is equal, we can do
82   // a simple buffer copy operation here.
83   if ( status ) std::cout << "Stream over/underflow detected." << std::endl;
84
85   unsigned long *bytes = (unsigned long *) data;
86   memcpy( outputBuffer, inputBuffer, *bytes );
87   return 0;
88 }
89
90 int main( int argc, char *argv[] )
91 {
92   unsigned int bufferFrames, fs, device = 0, offset = 0;
93   char input;
94
95   // minimal command-line checking
96   if (argc < 3 || argc > 5 ) usage();
97
98   RtAudio dac;
99   if ( dac.getDeviceCount() < 1 ) {
100     std::cout << "\nNo audio devices found!\n";
101     exit( 1 );
102   }
103
104   channels = (unsigned int) atoi( argv[1] );
105   fs = (unsigned int) atoi( argv[2] );
106   if ( argc > 3 )
107     device = (unsigned int) atoi( argv[3] );
108   if ( argc > 4 )
109     offset = (unsigned int) atoi( argv[4] );
110
111   double *data = (double *) calloc( channels, sizeof( double ) );
112
113   // Let RtAudio print messages to stderr.
114   dac.showWarnings( true );
115
116   // Set our stream parameters for output only.
117   bufferFrames = 256;
118   RtAudio::StreamParameters oParams, iParams;
119   oParams.deviceId = device;
120   oParams.nChannels = channels;
121   oParams.firstChannel = offset;
122
123   RtAudio::StreamOptions options;
124   options.flags = RTAUDIO_HOG_DEVICE;
125   try {
126     dac.openStream( &oParams, NULL, RTAUDIO_FLOAT64, fs, &bufferFrames, &sawi, (void *)data, &options );
127     std::cout << "\nStream latency = " << dac.getStreamLatency() << std::endl;
128
129     // Start the stream
130     dac.startStream();
131     std::cout << "\nPlaying ... press <enter> to stop.\n";
132     std::cin.get( input );
133
134     // Stop the stream
135     dac.stopStream();
136
137     // Restart again
138     std::cout << "Press <enter> to restart.\n";
139     std::cin.get( input );
140     dac.startStream();
141
142     // Test abort function
143     std::cout << "Playing again ... press <enter> to abort.\n";
144     std::cin.get( input );
145     dac.abortStream();
146
147     // Restart another time
148     std::cout << "Press <enter> to restart again.\n";
149     std::cin.get( input );
150     dac.startStream();
151
152     std::cout << "Playing again ... press <enter> to close the stream.\n";
153     std::cin.get( input );
154   }
155   catch ( RtError& e ) {
156     e.printMessage();
157     goto cleanup;
158   }
159
160   if ( dac.isStreamOpen() ) dac.closeStream();
161
162   // Test non-interleaved functionality
163   options.flags = RTAUDIO_NONINTERLEAVED;
164   try {
165     dac.openStream( &oParams, NULL, RTAUDIO_FLOAT64, fs, &bufferFrames, &sawni, (void *)data, &options );
166
167     std::cout << "Press <enter> to start non-interleaved playback.\n";
168     std::cin.get( input );
169
170     // Start the stream
171     dac.startStream();
172     std::cout << "\nPlaying ... press <enter> to stop.\n";
173     std::cin.get( input );
174   }
175   catch ( RtError& e ) {
176     e.printMessage();
177     goto cleanup;
178   }
179
180   if ( dac.isStreamOpen() ) dac.closeStream();
181
182   // Now open a duplex stream.
183   unsigned int bufferBytes;
184   iParams.deviceId = device;
185   iParams.nChannels = channels;
186   iParams.firstChannel = offset;
187   options.flags = RTAUDIO_NONINTERLEAVED;
188   try {
189     dac.openStream( &oParams, &iParams, RTAUDIO_SINT32, fs, &bufferFrames, &inout, (void *)&bufferBytes, &options );
190
191     bufferBytes = bufferFrames * channels * 4;
192
193     std::cout << "Press <enter> to start duplex operation.\n";
194     std::cin.get( input );
195
196     // Start the stream
197     dac.startStream();
198     std::cout << "\nRunning ... press <enter> to stop.\n";
199     std::cin.get( input );
200
201     // Stop the stream
202     dac.stopStream();
203     std::cout << "\nStopped ... press <enter> to restart.\n";
204     std::cin.get( input );
205
206     // Restart the stream
207     dac.startStream();
208     std::cout << "\nRunning ... press <enter> to stop.\n";
209     std::cin.get( input );
210   }
211   catch ( RtError& e ) {
212     e.printMessage();
213   }
214
215  cleanup:
216   if ( dac.isStreamOpen() ) dac.closeStream();
217   free( data );
218
219   return 0;
220 }