1 /******************************************/
4 by Gary P. Scavone, 2001
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.
13 /******************************************/
19 typedef signed long MY_TYPE;
20 #define FORMAT RTAUDIO_SINT24
21 #define SCALE 2147483647.0
24 #define FORMAT RTAUDIO_SINT8
27 typedef signed short MY_TYPE;
28 #define FORMAT RTAUDIO_SINT16
31 typedef signed long MY_TYPE;
32 #define FORMAT RTAUDIO_SINT32
33 #define SCALE 2147483647.0
36 typedef float MY_TYPE;
37 #define FORMAT RTAUDIO_FLOAT32
41 typedef double MY_TYPE;
42 #define FORMAT RTAUDIO_FLOAT64
46 #define BASE_RATE 0.005
50 /* Error function in case of incorrect command-line
51 argument specifications
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";
60 int main(int argc, char *argv[])
62 int chans, fs, buffer_size, device = 0;
63 long frames, counter = 0, i, j;
64 MY_TYPE *buffer1, *buffer2;
65 RtAudio *stream1, *stream2;
69 // minimal command-line checking
70 if (argc != 3 && argc != 4 ) usage();
72 chans = (int) atoi(argv[1]);
73 fs = (int) atoi(argv[2]);
75 device = (int) atoi(argv[3]);
77 // Open the realtime output device
80 stream1 = new RtAudio(device, chans, 0, 0,
81 FORMAT, fs, &buffer_size, 8);
83 catch (RtError &error) {
89 stream2 = new RtAudio(0, 0, device, chans,
90 FORMAT, fs, &buffer_size, 8);
92 catch (RtError &error) {
99 buffer1 = (MY_TYPE *) stream1->getStreamBuffer();
100 buffer2 = (MY_TYPE *) stream2->getStreamBuffer();
102 catch (RtError &error) {
103 error.printMessage();
107 frames = (long) (fs * TIME);
108 data = (double *) calloc(chans, sizeof(double));
111 stream1->startStream();
113 catch (RtError &error) {
114 error.printMessage();
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;
129 stream1->tickStream();
131 catch (RtError &error) {
132 error.printMessage();
136 counter += buffer_size;
139 std::cout << "\nStopping playback stream." << std::endl;
141 stream1->stopStream();
143 catch (RtError &error) {
144 error.printMessage();
148 fd = fopen("test.raw","wb");
151 stream2->startStream();
153 catch (RtError &error) {
154 error.printMessage();
159 std::cout << "\nStarting recording stream for " << TIME << " seconds." << std::endl;
160 while (counter < frames) {
163 stream2->tickStream();
165 catch (RtError &error) {
166 error.printMessage();
170 fwrite(buffer2, sizeof(MY_TYPE), chans * buffer_size, fd);
171 counter += buffer_size;
175 std::cout << "\nAborting recording." << std::endl;
178 stream2->abortStream();
179 stream1->startStream();
180 stream2->startStream();
182 catch (RtError &error) {
183 error.printMessage();
188 std::cout << "\nStarting playback and record streams (quasi-duplex) for " << TIME << " seconds." << std::endl;
189 while (counter < frames) {
192 stream2->tickStream();
193 memcpy(buffer1, buffer2, sizeof(MY_TYPE) * chans * buffer_size);
194 stream1->tickStream();
196 catch (RtError &error) {
197 error.printMessage();
201 counter += buffer_size;
204 std::cout << "\nStopping both streams." << std::endl;
206 stream1->stopStream();
207 stream2->stopStream();
209 catch (RtError &error) {
210 error.printMessage();
214 stream1->closeStream();
215 stream2->closeStream();
218 if (data) free(data);