使用portaudio 使用Pa_ReadStream and Pa_WriteStream,如下
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include "portaudio.h"
42
43 /* #define SAMPLE_RATE (17932) /* Test failure to open with this value. */
44 #define SAMPLE_RATE (44100)
45 #define FRAMES_PER_BUFFER (1024)
46 #define NUM_SECONDS (5)
47 #define NUM_CHANNELS (2)
48 /* #define DITHER_FLAG (paDitherOff) */
49 #define DITHER_FLAG (0) /**/
50
51 /* Select sample format. */
52 #if 1
53 #define PA_SAMPLE_TYPE paFloat32
54 typedef float SAMPLE;
55 #define SAMPLE_SILENCE (0.0f)
56 #define PRINTF_S_FORMAT "%.8f"
57 #elif 1
58 #define PA_SAMPLE_TYPE paInt16
59 typedef short SAMPLE;
60 #define SAMPLE_SILENCE (0)
61 #define PRINTF_S_FORMAT "%d"
62 #elif 0
63 #define PA_SAMPLE_TYPE paInt8
64 typedef char SAMPLE;
65 #define SAMPLE_SILENCE (0)
66 #define PRINTF_S_FORMAT "%d"
67 #else
68 #define PA_SAMPLE_TYPE paUInt8
69 typedef unsigned char SAMPLE;
70 #define SAMPLE_SILENCE (128)
71 #define PRINTF_S_FORMAT "%d"
72 #endif
73
74 #define FORMATID "fmt "
75 #define DATAID "data"
76
77 typedef struct {
78 char chunkID[4];
79 long chunkSize;
80 short wFormatTag;
81 unsigned short wChannels;
82 unsigned long dwSamplesPerSec;
83 unsigned long dwAvgBytesPerSec;
84 unsigned short wBlockAlign;
85 unsigned short wBitsPerSample;
86 } FormatChunk;
87
88 typedef struct {
89 char chunkID[4];
90 long chunkSize;
91 } DataChunkHeader;
92
93
94
95 int checkHeader(FILE *fid) {
96
97 char riff[4];
98 char wave[4];
99
100 fread(riff, 4, sizeof(char), fid);
101 /* throwaway 4 bytes */
102 fread(wave, 4, sizeof(char), fid);
103 fread(wave, 4, sizeof(char), fid);
104
105 if (!((strncmp(riff, "RIFF", 4) == 0) &&
106 (strncmp(wave, "WAVE", 4) == 0))) {
107 return -1;
108 }
109
110 return 0;
111 }
112
113
114 int getData(FILE *fid, char **data) {
115
116 DataChunkHeader dch;
117
118 while (strncmp(dch.chunkID, DATAID, 4) != 0) {
119 fread(&dch, sizeof(DataChunkHeader), 1, fid);
120 if (feof(fid) || ferror(fid))
121 return -1;
122 }
123
124 printf("Size of data: %d\n", dch.chunkSize);
125
126 *data = (char *) malloc ( dch.chunkSize * sizeof(char) );
127 fread(*data, sizeof(char), dch.chunkSize, fid);
128 if (feof(fid) || ferror(fid)) {
129 free(data);
130 return -1;
131 }
132
133 return dch.chunkSize;
134 }
135
136 int getFormatChunk(FILE *fid, FormatChunk *formatChunk) {
137
138 while (strncmp(formatChunk->chunkID, FORMATID, 4) != 0) {
139 fread(formatChunk, sizeof(FormatChunk), 1, fid);
140 if (feof(fid) || ferror(fid))
141 return -1;
142 }
143 return 0;
144 }
145
146
147
148 /*******************************************************************/
149 int main(int argc, char *argv[])
150 {
151 PaStreamParameters outputParameters;
152 PaStream *stream;
153 PaError err;
154 /*int i;
155 int totalFrames;
156 int numSamples;
157 int numBytes;
158 */
159
160 /* read wave file */
161 char *filename;
162 FILE *fid;
163
164 if (argc < 2) {
165 printf("Usage: %s filename.wav\n", argv[0]);
166 return -1;
167 }
168
169 /* filename */
170 filename = argv[1];
171 printf("Filename: %s\n", filename);
172
173 /* open file */
174 fid = fopen(filename, "rb");
175 if (fid == NULL) {
176 printf("Could not open file %s\n", filename);
177 return -1;
178 }
179
180 /* check header */
181 if (checkHeader(fid) < 0) {
182 printf("Not a wave file!\n");
183 return -1;
184 }
185
186 FormatChunk formatChunk;
187 int data_size;
188 char *data;
189
190 if (getFormatChunk(fid, &formatChunk) < 0) {
191 printf("Couldn't read header\n");
192 return -1;
193 }
194
195 printf("Chunk Size : %d\n", formatChunk.chunkSize);
196 printf("Compressed : %d\n", formatChunk.wFormatTag != 1);
197 printf("Channels : %d\n", formatChunk.wChannels);
198 printf("SamplesPerSecond : %d\n", formatChunk.dwSamplesPerSec);
199 printf("dwAvgBytesPerSec : %d\n", formatChunk.dwAvgBytesPerSec);
200 printf("wBlockAlign : %d\n", formatChunk.wBlockAlign);
201 printf("wBitsPerSample : %d\n", formatChunk.wBitsPerSample);
202
203 if ((data_size = getData(fid, &data)) < 0) {
204 printf("Couldn't read data\n");
205 return -1;
206 }
207
208 int total_frames = data_size / formatChunk.wBlockAlign;
209
210 printf("Total Frames : %d\n", total_frames);
211 /* fclose(fid); */
212
213
214 err = Pa_Initialize();
215 if( err != paNoError ) goto error;
216
217 /* Playback recorded data. -------------------------------------------- */
218
219 outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
220
221 outputParameters.channelCount = formatChunk.wChannels;
222 outputParameters.sampleFormat = paInt16;
223
224 outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
225
226 printf("YO YO\n"); fflush(stdout);
227 outputParameters.hostApiSpecificStreamInfo = NULL;
228
229 printf("Begin playback.\n"); fflush(stdout);
230 err = Pa_OpenStream(
231 &stream,
232 NULL, /* no input */
233 &outputParameters,
234 formatChunk.dwSamplesPerSec,
235 0, /*FRAMES_PER_BUFFER, */
236 paClipOff, /* we won't output out of range samples so don't bother clipping them */
237 NULL, /* no callback, use blocking API */
238 NULL ); /* no callback, so no callback userData */
239 if( err != paNoError ) goto error;
240
241 if( stream )
242 {
243 err = Pa_StartStream( stream );
244 if( err != paNoError ) goto error;
245 printf("Waiting for playback to finish.\n"); fflush(stdout);
246
247 err = Pa_WriteStream( stream, data, total_frames );
248 if( err != paNoError ) goto error;
249
250 err = Pa_CloseStream( stream );
251 if( err != paNoError ) goto error;
252 printf("Done.\n"); fflush(stdout);
253 }
254 free( data );
255
256 Pa_Terminate();
257 return 0;
258
259 error:
260 Pa_Terminate();
261 fprintf( stderr, "An error occured while using the portaudio stream\n" );
262 fprintf( stderr, "Error number: %d\n", err );
263 fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
264 return -1;
265 }