Various updates and fixes before 4.0.5 release (GS).
[rtaudio-cdist.git] / tests / playraw.cpp
1 /******************************************/
2 /*
3   playraw.cpp
4   by Gary P. Scavone, 2007
5
6   Play a specified raw file.  It is necessary
7   that the file be of the same data format as
8   defined below.
9 */
10 /******************************************/
11
12 #include "RtAudio.h"
13 #include <iostream>
14 #include <cstdlib>
15 #include <cstring>
16
17 /*
18 typedef char  MY_TYPE;
19 #define FORMAT RTAUDIO_SINT8
20 #define SCALE  127.0
21 */
22
23 typedef signed short  MY_TYPE;
24 #define FORMAT RTAUDIO_SINT16
25 #define SCALE  32767.0
26
27 /*
28 typedef signed long  MY_TYPE;
29 #define FORMAT RTAUDIO_SINT24
30 #define SCALE  8388607.0
31
32 typedef signed long  MY_TYPE;
33 #define FORMAT RTAUDIO_SINT32
34 #define SCALE  2147483647.0
35
36 typedef float  MY_TYPE;
37 #define FORMAT RTAUDIO_FLOAT32
38 #define SCALE  1.0;
39
40 typedef double  MY_TYPE;
41 #define FORMAT RTAUDIO_FLOAT64
42 #define SCALE  1.0;
43 */
44
45 // Platform-dependent sleep routines.
46 #if defined( __WINDOWS_ASIO__ ) || defined( __WINDOWS_DS__ )
47   #include <windows.h>
48   #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) 
49 #else // Unix variants
50   #include <unistd.h>
51   #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) )
52 #endif
53
54 void usage( void ) {
55   // Error function in case of incorrect command-line
56   // argument specifications
57   std::cout << "\nuseage: playraw N fs file <device> <channelOffset>\n";
58   std::cout << "    where N = number of channels,\n";
59   std::cout << "    fs = the sample rate, \n";
60   std::cout << "    file = the raw file to play,\n";
61   std::cout << "    device = optional device to use (default = 0),\n";
62   std::cout << "    and channelOffset = an optional channel offset on the device (default = 0).\n\n";
63   exit( 0 );
64 }
65
66 struct OutputData {
67   FILE *fd;
68   unsigned int channels;
69 };
70
71 // Interleaved buffers
72 int output( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
73             double streamTime, RtAudioStreamStatus status, void *data )
74 {
75   OutputData *oData = (OutputData*) data;
76
77   // In general, it's not a good idea to do file input in the audio
78   // callback function but I'm doing it here because I don't know the
79   // length of the file we are reading.
80   unsigned int count = fread( outputBuffer, oData->channels * sizeof( MY_TYPE ), nBufferFrames, oData->fd);
81   if ( count < nBufferFrames ) {
82     unsigned int bytes = (nBufferFrames - count) * oData->channels * sizeof( MY_TYPE );
83     unsigned int startByte = count * oData->channels * sizeof( MY_TYPE );
84     memset( (char *)(outputBuffer)+startByte, 0, bytes );
85     return 1;
86   }
87
88   return 0;
89 }
90
91 int main( int argc, char *argv[] )
92 {
93   unsigned int channels, fs, bufferFrames, device = 0, offset = 0;
94   char *file;
95
96   // minimal command-line checking
97   if ( argc < 4 || argc > 6 ) usage();
98
99   RtAudio dac;
100   if ( dac.getDeviceCount() < 1 ) {
101     std::cout << "\nNo audio devices found!\n";
102     exit( 0 );
103   }
104
105   channels = (unsigned int) atoi( argv[1]) ;
106   fs = (unsigned int) atoi( argv[2] );
107   file = argv[3];
108   if ( argc > 4 )
109     device = (unsigned int) atoi( argv[4] );
110   if ( argc > 5 )
111     offset = (unsigned int) atoi( argv[5] );
112
113   OutputData data;
114   data.fd = fopen( file, "rb" );
115   if ( !data.fd ) {
116     std::cout << "Unable to find or open file!\n";
117     exit( 1 );
118   }
119
120   // Set our stream parameters for output only.
121   bufferFrames = 512;
122   RtAudio::StreamParameters oParams;
123   oParams.deviceId = device;
124   oParams.nChannels = channels;
125   oParams.firstChannel = offset;
126
127   data.channels = channels;
128   try {
129     dac.openStream( &oParams, NULL, FORMAT, fs, &bufferFrames, &output, (void *)&data );
130     dac.startStream();
131   }
132   catch ( RtError& e ) {
133     std::cout << '\n' << e.getMessage() << '\n' << std::endl;
134     goto cleanup;
135   }
136
137   std::cout << "\nPlaying raw file " << file << " (buffer frames = " << bufferFrames << ")." << std::endl;
138   while ( 1 ) {
139     SLEEP( 100 ); // wake every 100 ms to check if we're done
140     if ( dac.isStreamRunning() == false ) break;
141   }
142
143  cleanup:
144   fclose( data.fd );
145   dac.closeStream();
146
147   return 0;
148 }