Version 3.0
[rtaudio.git] / tests / twostreams.cpp
1 /******************************************/
2 /*
3   twostreams.cpp
4   by Gary P. Scavone, 2001
5
6   Test executable for audio playback, recording,
7   duplex operation, stopping, starting, and
8   aborting operations.  Takes number of channels
9   and sample rate as input arguments.  Runs input
10   and output through two separate instances of RtAudio.
11   Uses blocking functionality.
12 */
13 /******************************************/
14
15 #include "RtAudio.h"
16 #include <iostream>
17
18 /*
19 typedef signed long  MY_TYPE;
20 #define FORMAT RTAUDIO_SINT24
21 #define SCALE  2147483647.0
22
23 typedef char  MY_TYPE;
24 #define FORMAT RTAUDIO_SINT8
25 #define SCALE  127.0
26
27 typedef signed short  MY_TYPE;
28 #define FORMAT RTAUDIO_SINT16
29 #define SCALE  32767.0
30
31 typedef signed long  MY_TYPE;
32 #define FORMAT RTAUDIO_SINT32
33 #define SCALE  2147483647.0
34 */
35
36 typedef float  MY_TYPE;
37 #define FORMAT RTAUDIO_FLOAT32
38 #define SCALE  1.0
39
40 /*
41 typedef double  MY_TYPE;
42 #define FORMAT RTAUDIO_FLOAT64
43 #define SCALE  1.0
44 */
45
46 #define BASE_RATE 0.005
47 #define TIME 2.0
48
49 void usage(void) {
50   /* Error function in case of incorrect command-line
51      argument specifications
52   */
53   std::cout << "\nuseage: twostreams N fs <device>\n";
54   std::cout << "    where N = number of channels,\n";
55   std::cout << "    fs = the sample rate,\n";
56   std::cout << "    and device = the device to use (default = 0).\n\n";
57   exit(0);
58 }
59
60 int main(int argc, char *argv[])
61 {
62   int chans, fs, buffer_size, device = 0;
63   long frames, counter = 0, i, j;
64   MY_TYPE *buffer1, *buffer2;
65   RtAudio *stream1, *stream2;
66   FILE *fd;
67   double *data = 0;
68
69   // minimal command-line checking
70   if (argc != 3 && argc != 4 ) usage();
71
72   chans = (int) atoi(argv[1]);
73   fs = (int) atoi(argv[2]);
74   if ( argc == 4 )
75     device = (int) atoi(argv[3]);
76
77   // Open the realtime output device
78   buffer_size = 512;
79   try {
80     stream1 = new RtAudio(device, chans, 0, 0,
81                           FORMAT, fs, &buffer_size, 8);
82   }
83   catch (RtError &error) {
84     error.printMessage();
85     exit(EXIT_FAILURE);
86   }
87
88   try {
89     stream2 = new RtAudio(0, 0, device, chans,
90                           FORMAT, fs, &buffer_size, 8);
91   }
92   catch (RtError &error) {
93     delete stream1;
94     error.printMessage();
95     exit(EXIT_FAILURE);
96   }
97
98   try {
99     buffer1 = (MY_TYPE *) stream1->getStreamBuffer();
100     buffer2 = (MY_TYPE *) stream2->getStreamBuffer();
101   }
102   catch (RtError &error) {
103     error.printMessage();
104     goto cleanup;
105   }
106
107   frames = (long) (fs * TIME);
108   data = (double *) calloc(chans, sizeof(double));
109
110   try {
111     stream1->startStream();
112   }
113   catch (RtError &error) {
114     error.printMessage();
115     goto cleanup;
116   }
117
118   std::cout << "\nStarting sawtooth playback stream for " << TIME << " seconds." << std::endl;
119   while (counter < frames) {
120     for (i=0; i<buffer_size; i++) {
121       for (j=0; j<chans; j++) {
122         buffer1[i*chans+j] = (MY_TYPE) (data[j] * SCALE);
123         data[j] += BASE_RATE * (j+1+(j*0.1));
124         if (data[j] >= 1.0) data[j] -= 2.0;
125       }
126     }
127
128     try {
129       stream1->tickStream();
130     }
131     catch (RtError &error) {
132       error.printMessage();
133       goto cleanup;
134     }
135
136     counter += buffer_size;
137   }
138
139   std::cout << "\nStopping playback stream." << std::endl;
140   try {
141     stream1->stopStream();
142   }
143   catch (RtError &error) {
144     error.printMessage();
145     goto cleanup;
146   }
147
148   fd = fopen("test.raw","wb");
149
150   try {
151     stream2->startStream();
152   }
153   catch (RtError &error) {
154     error.printMessage();
155     goto cleanup;
156   }
157
158   counter = 0;
159   std::cout << "\nStarting recording stream for " << TIME << " seconds." << std::endl;
160   while (counter < frames) {
161
162     try {
163       stream2->tickStream();
164     }
165     catch (RtError &error) {
166       error.printMessage();
167       goto cleanup;
168     }
169
170     fwrite(buffer2, sizeof(MY_TYPE), chans * buffer_size, fd);
171     counter += buffer_size;
172   }
173
174   fclose(fd);
175   std::cout << "\nAborting recording." << std::endl;
176
177   try {
178     stream2->abortStream();
179     stream1->startStream();
180     stream2->startStream();
181   }
182   catch (RtError &error) {
183     error.printMessage();
184     goto cleanup;
185   }
186
187   counter = 0;
188   std::cout << "\nStarting playback and record streams (quasi-duplex) for " << TIME << " seconds." << std::endl;
189   while (counter < frames) {
190
191     try {
192       stream2->tickStream();
193       memcpy(buffer1, buffer2, sizeof(MY_TYPE) * chans * buffer_size);
194       stream1->tickStream();
195     }
196     catch (RtError &error) {
197       error.printMessage();
198       goto cleanup;
199     }
200
201     counter += buffer_size;
202   }
203
204   std::cout << "\nStopping both streams." << std::endl;
205   try {
206     stream1->stopStream();
207     stream2->stopStream();
208   }
209   catch (RtError &error) {
210     error.printMessage();
211   }
212
213  cleanup:
214   stream1->closeStream();
215   stream2->closeStream();
216   delete stream1;
217   delete stream2;
218   if (data) free(data);
219
220   return 0;
221 }