paex_record.c
Go to the documentation of this file.00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #include <stdio.h>
00045 #include <stdlib.h>
00046 #include "portaudio.h"
00047
00048
00049 #define SAMPLE_RATE (44100)
00050 #define FRAMES_PER_BUFFER (512)
00051 #define NUM_SECONDS (5)
00052 #define NUM_CHANNELS (2)
00053
00054 #define DITHER_FLAG (0)
00055
00056 #define WRITE_TO_FILE (0)
00057
00058
00059 #if 1
00060 #define PA_SAMPLE_TYPE paFloat32
00061 typedef float SAMPLE;
00062 #define SAMPLE_SILENCE (0.0f)
00063 #define PRINTF_S_FORMAT "%.8f"
00064 #elif 1
00065 #define PA_SAMPLE_TYPE paInt16
00066 typedef short SAMPLE;
00067 #define SAMPLE_SILENCE (0)
00068 #define PRINTF_S_FORMAT "%d"
00069 #elif 0
00070 #define PA_SAMPLE_TYPE paInt8
00071 typedef char SAMPLE;
00072 #define SAMPLE_SILENCE (0)
00073 #define PRINTF_S_FORMAT "%d"
00074 #else
00075 #define PA_SAMPLE_TYPE paUInt8
00076 typedef unsigned char SAMPLE;
00077 #define SAMPLE_SILENCE (128)
00078 #define PRINTF_S_FORMAT "%d"
00079 #endif
00080
00081 typedef struct
00082 {
00083 int frameIndex;
00084 int maxFrameIndex;
00085 SAMPLE *recordedSamples;
00086 }
00087 paTestData;
00088
00089
00090
00091
00092
00093 static int recordCallback( const void *inputBuffer, void *outputBuffer,
00094 unsigned long framesPerBuffer,
00095 const PaStreamCallbackTimeInfo* timeInfo,
00096 PaStreamCallbackFlags statusFlags,
00097 void *userData )
00098 {
00099 paTestData *data = (paTestData*)userData;
00100 const SAMPLE *rptr = (const SAMPLE*)inputBuffer;
00101 SAMPLE *wptr = &data->recordedSamples[data->frameIndex * NUM_CHANNELS];
00102 long framesToCalc;
00103 long i;
00104 int finished;
00105 unsigned long framesLeft = data->maxFrameIndex - data->frameIndex;
00106
00107 (void) outputBuffer;
00108 (void) timeInfo;
00109 (void) statusFlags;
00110 (void) userData;
00111
00112 if( framesLeft < framesPerBuffer )
00113 {
00114 framesToCalc = framesLeft;
00115 finished = paComplete;
00116 }
00117 else
00118 {
00119 framesToCalc = framesPerBuffer;
00120 finished = paContinue;
00121 }
00122
00123 if( inputBuffer == NULL )
00124 {
00125 for( i=0; i<framesToCalc; i++ )
00126 {
00127 *wptr++ = SAMPLE_SILENCE;
00128 if( NUM_CHANNELS == 2 ) *wptr++ = SAMPLE_SILENCE;
00129 }
00130 }
00131 else
00132 {
00133 for( i=0; i<framesToCalc; i++ )
00134 {
00135 *wptr++ = *rptr++;
00136 if( NUM_CHANNELS == 2 ) *wptr++ = *rptr++;
00137 }
00138 }
00139 data->frameIndex += framesToCalc;
00140 return finished;
00141 }
00142
00143
00144
00145
00146
00147 static int playCallback( const void *inputBuffer, void *outputBuffer,
00148 unsigned long framesPerBuffer,
00149 const PaStreamCallbackTimeInfo* timeInfo,
00150 PaStreamCallbackFlags statusFlags,
00151 void *userData )
00152 {
00153 paTestData *data = (paTestData*)userData;
00154 SAMPLE *rptr = &data->recordedSamples[data->frameIndex * NUM_CHANNELS];
00155 SAMPLE *wptr = (SAMPLE*)outputBuffer;
00156 unsigned int i;
00157 int finished;
00158 unsigned int framesLeft = data->maxFrameIndex - data->frameIndex;
00159
00160 (void) inputBuffer;
00161 (void) timeInfo;
00162 (void) statusFlags;
00163 (void) userData;
00164
00165 if( framesLeft < framesPerBuffer )
00166 {
00167
00168 for( i=0; i<framesLeft; i++ )
00169 {
00170 *wptr++ = *rptr++;
00171 if( NUM_CHANNELS == 2 ) *wptr++ = *rptr++;
00172 }
00173 for( ; i<framesPerBuffer; i++ )
00174 {
00175 *wptr++ = 0;
00176 if( NUM_CHANNELS == 2 ) *wptr++ = 0;
00177 }
00178 data->frameIndex += framesLeft;
00179 finished = paComplete;
00180 }
00181 else
00182 {
00183 for( i=0; i<framesPerBuffer; i++ )
00184 {
00185 *wptr++ = *rptr++;
00186 if( NUM_CHANNELS == 2 ) *wptr++ = *rptr++;
00187 }
00188 data->frameIndex += framesPerBuffer;
00189 finished = paContinue;
00190 }
00191 return finished;
00192 }
00193
00194
00195 int main(void);
00196 int main(void)
00197 {
00198 PaStreamParameters inputParameters,
00199 outputParameters;
00200 PaStream* stream;
00201 PaError err = paNoError;
00202 paTestData data;
00203 int i;
00204 int totalFrames;
00205 int numSamples;
00206 int numBytes;
00207 SAMPLE max, val;
00208 double average;
00209
00210 printf("patest_record.c\n"); fflush(stdout);
00211
00212 data.maxFrameIndex = totalFrames = NUM_SECONDS * SAMPLE_RATE;
00213 data.frameIndex = 0;
00214 numSamples = totalFrames * NUM_CHANNELS;
00215 numBytes = numSamples * sizeof(SAMPLE);
00216 data.recordedSamples = (SAMPLE *) malloc( numBytes );
00217 if( data.recordedSamples == NULL )
00218 {
00219 printf("Could not allocate record array.\n");
00220 goto done;
00221 }
00222 for( i=0; i<numSamples; i++ ) data.recordedSamples[i] = 0;
00223
00224 err = Pa_Initialize();
00225 if( err != paNoError ) goto done;
00226
00227 inputParameters.device = Pa_GetDefaultInputDevice();
00228 if (inputParameters.device == paNoDevice) {
00229 fprintf(stderr,"Error: No default input device.\n");
00230 goto done;
00231 }
00232 inputParameters.channelCount = 2;
00233 inputParameters.sampleFormat = PA_SAMPLE_TYPE;
00234 inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
00235 inputParameters.hostApiSpecificStreamInfo = NULL;
00236
00237
00238 err = Pa_OpenStream(
00239 &stream,
00240 &inputParameters,
00241 NULL,
00242 SAMPLE_RATE,
00243 FRAMES_PER_BUFFER,
00244 paClipOff,
00245 recordCallback,
00246 &data );
00247 if( err != paNoError ) goto done;
00248
00249 err = Pa_StartStream( stream );
00250 if( err != paNoError ) goto done;
00251 printf("\n=== Now recording!! Please speak into the microphone. ===\n"); fflush(stdout);
00252
00253 while( ( err = Pa_IsStreamActive( stream ) ) == 1 )
00254 {
00255 Pa_Sleep(1000);
00256 printf("index = %d\n", data.frameIndex ); fflush(stdout);
00257 }
00258 if( err < 0 ) goto done;
00259
00260 err = Pa_CloseStream( stream );
00261 if( err != paNoError ) goto done;
00262
00263
00264 max = 0;
00265 average = 0.0;
00266 for( i=0; i<numSamples; i++ )
00267 {
00268 val = data.recordedSamples[i];
00269 if( val < 0 ) val = -val;
00270 if( val > max )
00271 {
00272 max = val;
00273 }
00274 average += val;
00275 }
00276
00277 average = average / (double)numSamples;
00278
00279 printf("sample max amplitude = "PRINTF_S_FORMAT"\n", max );
00280 printf("sample average = %lf\n", average );
00281
00282
00283 #if WRITE_TO_FILE
00284 {
00285 FILE *fid;
00286 fid = fopen("recorded.raw", "wb");
00287 if( fid == NULL )
00288 {
00289 printf("Could not open file.");
00290 }
00291 else
00292 {
00293 fwrite( data.recordedSamples, NUM_CHANNELS * sizeof(SAMPLE), totalFrames, fid );
00294 fclose( fid );
00295 printf("Wrote data to 'recorded.raw'\n");
00296 }
00297 }
00298 #endif
00299
00300
00301 data.frameIndex = 0;
00302
00303 outputParameters.device = Pa_GetDefaultOutputDevice();
00304 if (outputParameters.device == paNoDevice) {
00305 fprintf(stderr,"Error: No default output device.\n");
00306 goto done;
00307 }
00308 outputParameters.channelCount = 2;
00309 outputParameters.sampleFormat = PA_SAMPLE_TYPE;
00310 outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
00311 outputParameters.hostApiSpecificStreamInfo = NULL;
00312
00313 printf("\n=== Now playing back. ===\n"); fflush(stdout);
00314 err = Pa_OpenStream(
00315 &stream,
00316 NULL,
00317 &outputParameters,
00318 SAMPLE_RATE,
00319 FRAMES_PER_BUFFER,
00320 paClipOff,
00321 playCallback,
00322 &data );
00323 if( err != paNoError ) goto done;
00324
00325 if( stream )
00326 {
00327 err = Pa_StartStream( stream );
00328 if( err != paNoError ) goto done;
00329
00330 printf("Waiting for playback to finish.\n"); fflush(stdout);
00331
00332 while( ( err = Pa_IsStreamActive( stream ) ) == 1 ) Pa_Sleep(100);
00333 if( err < 0 ) goto done;
00334
00335 err = Pa_CloseStream( stream );
00336 if( err != paNoError ) goto done;
00337
00338 printf("Done.\n"); fflush(stdout);
00339 }
00340
00341 done:
00342 Pa_Terminate();
00343 if( data.recordedSamples )
00344 free( data.recordedSamples );
00345 if( err != paNoError )
00346 {
00347 fprintf( stderr, "An error occured while using the portaudio stream\n" );
00348 fprintf( stderr, "Error number: %d\n", err );
00349 fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
00350 err = 1;
00351 }
00352 return err;
00353 }
00354