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