patest_read_record.c (8115B)
1 /** @file patest_read_record.c 2 @ingroup test_src 3 @brief Record input into an array; Save array to a file; Playback recorded 4 data. Implemented using the blocking API (Pa_ReadStream(), Pa_WriteStream() ) 5 @author Phil Burk http://www.softsynth.com 6 @author Ross Bencina rossb@audiomulch.com 7 */ 8 /* 9 * $Id$ 10 * 11 * This program uses the PortAudio Portable Audio Library. 12 * For more information see: http://www.portaudio.com 13 * Copyright (c) 1999-2000 Ross Bencina and Phil Burk 14 * 15 * Permission is hereby granted, free of charge, to any person obtaining 16 * a copy of this software and associated documentation files 17 * (the "Software"), to deal in the Software without restriction, 18 * including without limitation the rights to use, copy, modify, merge, 19 * publish, distribute, sublicense, and/or sell copies of the Software, 20 * and to permit persons to whom the Software is furnished to do so, 21 * subject to the following conditions: 22 * 23 * The above copyright notice and this permission notice shall be 24 * included in all copies or substantial portions of the Software. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 29 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 30 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 31 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 32 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 33 */ 34 35 /* 36 * The text above constitutes the entire PortAudio license; however, 37 * the PortAudio community also makes the following non-binding requests: 38 * 39 * Any person wishing to distribute modifications to the Software is 40 * requested to send the modifications to the original developer so that 41 * they can be incorporated into the canonical version. It is also 42 * requested that these non-binding requests be included along with the 43 * license above. 44 */ 45 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include "portaudio.h" 49 50 /* #define SAMPLE_RATE (17932) // Test failure to open with this value. */ 51 #define SAMPLE_RATE (44100) 52 #define FRAMES_PER_BUFFER (1024) 53 #define NUM_SECONDS (5) 54 #define NUM_CHANNELS (2) 55 /* #define DITHER_FLAG (paDitherOff) */ 56 #define DITHER_FLAG (0) /**/ 57 58 /* Select sample format. */ 59 #if 1 60 #define PA_SAMPLE_TYPE paFloat32 61 typedef float SAMPLE; 62 #define SAMPLE_SILENCE (0.0f) 63 #define PRINTF_S_FORMAT "%.8f" 64 #elif 1 65 #define PA_SAMPLE_TYPE paInt16 66 typedef short SAMPLE; 67 #define SAMPLE_SILENCE (0) 68 #define PRINTF_S_FORMAT "%d" 69 #elif 0 70 #define PA_SAMPLE_TYPE paInt8 71 typedef char SAMPLE; 72 #define SAMPLE_SILENCE (0) 73 #define PRINTF_S_FORMAT "%d" 74 #else 75 #define PA_SAMPLE_TYPE paUInt8 76 typedef unsigned char SAMPLE; 77 #define SAMPLE_SILENCE (128) 78 #define PRINTF_S_FORMAT "%d" 79 #endif 80 81 82 /*******************************************************************/ 83 int main(void); 84 int main(void) 85 { 86 PaStreamParameters inputParameters, outputParameters; 87 PaStream *stream; 88 PaError err; 89 SAMPLE *recordedSamples; 90 int i; 91 int totalFrames; 92 int numSamples; 93 int numBytes; 94 SAMPLE max, average, val; 95 96 97 printf("patest_read_record.c\n"); fflush(stdout); 98 99 totalFrames = NUM_SECONDS * SAMPLE_RATE; /* Record for a few seconds. */ 100 numSamples = totalFrames * NUM_CHANNELS; 101 102 numBytes = numSamples * sizeof(SAMPLE); 103 recordedSamples = (SAMPLE *) malloc( numBytes ); 104 if( recordedSamples == NULL ) 105 { 106 printf("Could not allocate record array.\n"); 107 exit(1); 108 } 109 for( i=0; i<numSamples; i++ ) recordedSamples[i] = 0; 110 111 err = Pa_Initialize(); 112 if( err != paNoError ) goto error; 113 114 inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */ 115 if (inputParameters.device == paNoDevice) { 116 fprintf(stderr,"Error: No default input device.\n"); 117 goto error; 118 } 119 inputParameters.channelCount = NUM_CHANNELS; 120 inputParameters.sampleFormat = PA_SAMPLE_TYPE; 121 inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency; 122 inputParameters.hostApiSpecificStreamInfo = NULL; 123 124 /* Record some audio. -------------------------------------------- */ 125 err = Pa_OpenStream( 126 &stream, 127 &inputParameters, 128 NULL, /* &outputParameters, */ 129 SAMPLE_RATE, 130 FRAMES_PER_BUFFER, 131 paClipOff, /* we won't output out of range samples so don't bother clipping them */ 132 NULL, /* no callback, use blocking API */ 133 NULL ); /* no callback, so no callback userData */ 134 if( err != paNoError ) goto error; 135 136 err = Pa_StartStream( stream ); 137 if( err != paNoError ) goto error; 138 printf("Now recording!!\n"); fflush(stdout); 139 140 err = Pa_ReadStream( stream, recordedSamples, totalFrames ); 141 if( err != paNoError ) goto error; 142 143 err = Pa_CloseStream( stream ); 144 if( err != paNoError ) goto error; 145 146 /* Measure maximum peak amplitude. */ 147 max = 0; 148 average = 0; 149 for( i=0; i<numSamples; i++ ) 150 { 151 val = recordedSamples[i]; 152 if( val < 0 ) val = -val; /* ABS */ 153 if( val > max ) 154 { 155 max = val; 156 } 157 average += val; 158 } 159 160 average = average / numSamples; 161 162 printf("Sample max amplitude = "PRINTF_S_FORMAT"\n", max ); 163 printf("Sample average = "PRINTF_S_FORMAT"\n", average ); 164 /* Was as below. Better choose at compile time because this 165 keeps generating compiler-warnings: 166 if( PA_SAMPLE_TYPE == paFloat32 ) 167 { 168 printf("sample max amplitude = %f\n", max ); 169 printf("sample average = %f\n", average ); 170 } 171 else 172 { 173 printf("sample max amplitude = %d\n", max ); 174 printf("sample average = %d\n", average ); 175 } 176 */ 177 /* Write recorded data to a file. */ 178 #if 0 179 { 180 FILE *fid; 181 fid = fopen("recorded.raw", "wb"); 182 if( fid == NULL ) 183 { 184 printf("Could not open file."); 185 } 186 else 187 { 188 fwrite( recordedSamples, NUM_CHANNELS * sizeof(SAMPLE), totalFrames, fid ); 189 fclose( fid ); 190 printf("Wrote data to 'recorded.raw'\n"); 191 } 192 } 193 #endif 194 195 /* Playback recorded data. -------------------------------------------- */ 196 197 outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ 198 if (outputParameters.device == paNoDevice) { 199 fprintf(stderr,"Error: No default output device.\n"); 200 goto error; 201 } 202 outputParameters.channelCount = NUM_CHANNELS; 203 outputParameters.sampleFormat = PA_SAMPLE_TYPE; 204 outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; 205 outputParameters.hostApiSpecificStreamInfo = NULL; 206 207 printf("Begin playback.\n"); fflush(stdout); 208 err = Pa_OpenStream( 209 &stream, 210 NULL, /* no input */ 211 &outputParameters, 212 SAMPLE_RATE, 213 FRAMES_PER_BUFFER, 214 paClipOff, /* we won't output out of range samples so don't bother clipping them */ 215 NULL, /* no callback, use blocking API */ 216 NULL ); /* no callback, so no callback userData */ 217 if( err != paNoError ) goto error; 218 219 if( stream ) 220 { 221 err = Pa_StartStream( stream ); 222 if( err != paNoError ) goto error; 223 printf("Waiting for playback to finish.\n"); fflush(stdout); 224 225 err = Pa_WriteStream( stream, recordedSamples, totalFrames ); 226 if( err != paNoError ) goto error; 227 228 err = Pa_CloseStream( stream ); 229 if( err != paNoError ) goto error; 230 printf("Done.\n"); fflush(stdout); 231 } 232 free( recordedSamples ); 233 234 Pa_Terminate(); 235 return 0; 236 237 error: 238 Pa_Terminate(); 239 fprintf( stderr, "An error occured while using the portaudio stream\n" ); 240 fprintf( stderr, "Error number: %d\n", err ); 241 fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); 242 return -1; 243 } 244