47 #include "pa_ringbuffer.h"
56 #define FILE_NAME "audio_data.raw"
57 #define SAMPLE_RATE (44100)
58 #define FRAMES_PER_BUFFER (512)
59 #define NUM_SECONDS (10)
60 #define NUM_CHANNELS (2)
61 #define NUM_WRITES_PER_BUFFER (4)
63 #define DITHER_FLAG (0)
68 #define PA_SAMPLE_TYPE paFloat32
70 #define SAMPLE_SILENCE (0.0f)
71 #define PRINTF_S_FORMAT "%.8f"
73 #define PA_SAMPLE_TYPE paInt16
75 #define SAMPLE_SILENCE (0)
76 #define PRINTF_S_FORMAT "%d"
78 #define PA_SAMPLE_TYPE paInt8
80 #define SAMPLE_SILENCE (0)
81 #define PRINTF_S_FORMAT "%d"
83 #define PA_SAMPLE_TYPE paUInt8
84 typedef unsigned char SAMPLE;
85 #define SAMPLE_SILENCE (128)
86 #define PRINTF_S_FORMAT "%d"
93 SAMPLE *ringBufferData;
94 PaUtilRingBuffer ringBuffer;
101 static int threadFunctionWriteToRawFile(
void* ptr)
106 pData->threadSyncFlag = 0;
110 ring_buffer_size_t elementsInBuffer = PaUtil_GetRingBufferReadAvailable(&pData->ringBuffer);
111 if ( (elementsInBuffer >= pData->ringBuffer.bufferSize / NUM_WRITES_PER_BUFFER) ||
112 pData->threadSyncFlag )
115 ring_buffer_size_t sizes[2] = {0};
118 ring_buffer_size_t elementsRead = PaUtil_GetRingBufferReadRegions(&pData->ringBuffer, elementsInBuffer, ptr + 0, sizes + 0, ptr + 1, sizes + 1);
119 if (elementsRead > 0)
122 for (i = 0; i < 2 && ptr[i] != NULL; ++i)
124 fwrite(ptr[i], pData->ringBuffer.elementSizeBytes, sizes[i], pData->file);
126 PaUtil_AdvanceRingBufferReadIndex(&pData->ringBuffer, elementsRead);
129 if (pData->threadSyncFlag)
139 pData->threadSyncFlag = 0;
146 static int threadFunctionReadFromRawFile(
void* ptr)
152 ring_buffer_size_t elementsInBuffer = PaUtil_GetRingBufferWriteAvailable(&pData->ringBuffer);
154 if (elementsInBuffer >= pData->ringBuffer.bufferSize / NUM_WRITES_PER_BUFFER)
157 ring_buffer_size_t sizes[2] = {0};
160 PaUtil_GetRingBufferWriteRegions(&pData->ringBuffer, elementsInBuffer, ptr + 0, sizes + 0, ptr + 1, sizes + 1);
162 if (!feof(pData->file))
164 ring_buffer_size_t itemsReadFromFile = 0;
166 for (i = 0; i < 2 && ptr[i] != NULL; ++i)
168 itemsReadFromFile += (ring_buffer_size_t)fread(ptr[i], pData->ringBuffer.elementSizeBytes, sizes[i], pData->file);
170 PaUtil_AdvanceRingBufferWriteIndex(&pData->ringBuffer, itemsReadFromFile);
173 pData->threadSyncFlag = 0;
178 pData->threadSyncFlag = 1;
190 typedef int (*ThreadFunctionType)(
void*);
197 typedef unsigned (__stdcall* WinThreadFunctionType)(
void*);
198 pData->threadHandle = (
void*)_beginthreadex(NULL, 0, (WinThreadFunctionType)fn, pData, CREATE_SUSPENDED, NULL);
199 if (pData->threadHandle == NULL)
return paUnanticipatedHostError;
202 SetThreadPriority(pData->threadHandle, THREAD_PRIORITY_ABOVE_NORMAL);
205 pData->threadSyncFlag = 1;
206 ResumeThread(pData->threadHandle);
211 while (pData->threadSyncFlag) {
220 pData->threadSyncFlag = 1;
222 while (pData->threadSyncFlag) {
226 CloseHandle(pData->threadHandle);
227 pData->threadHandle = 0;
238 static int recordCallback(
const void *inputBuffer,
void *outputBuffer,
239 unsigned long framesPerBuffer,
245 ring_buffer_size_t elementsWriteable = PaUtil_GetRingBufferWriteAvailable(&data->ringBuffer);
246 ring_buffer_size_t elementsToWrite = min(elementsWriteable, (ring_buffer_size_t)(framesPerBuffer * NUM_CHANNELS));
247 const SAMPLE *rptr = (
const SAMPLE*)inputBuffer;
254 data->frameIndex += PaUtil_WriteRingBuffer(&data->ringBuffer, rptr, elementsToWrite);
263 static int playCallback(
const void *inputBuffer,
void *outputBuffer,
264 unsigned long framesPerBuffer,
270 ring_buffer_size_t elementsToPlay = PaUtil_GetRingBufferReadAvailable(&data->ringBuffer);
271 ring_buffer_size_t elementsToRead = min(elementsToPlay, (ring_buffer_size_t)(framesPerBuffer * NUM_CHANNELS));
272 SAMPLE* wptr = (SAMPLE*)outputBuffer;
279 data->frameIndex += PaUtil_ReadRingBuffer(&data->ringBuffer, wptr, elementsToRead);
284 static unsigned NextPowerOf2(
unsigned val)
287 val = (val >> 1) | val;
288 val = (val >> 2) | val;
289 val = (val >> 4) | val;
290 val = (val >> 8) | val;
291 val = (val >> 16) | val;
308 printf(
"patest_record.c\n"); fflush(stdout);
311 numSamples = NextPowerOf2((
unsigned)(SAMPLE_RATE * 0.5 * NUM_CHANNELS));
312 numBytes = numSamples *
sizeof(SAMPLE);
313 data.ringBufferData = (SAMPLE *) PaUtil_AllocateMemory( numBytes );
314 if( data.ringBufferData == NULL )
316 printf(
"Could not allocate ring buffer data.\n");
320 if (PaUtil_InitializeRingBuffer(&data.ringBuffer,
sizeof(SAMPLE), numSamples, data.ringBufferData) < 0)
322 printf(
"Failed to initialize ring buffer. Size is not power of 2 ??\n");
327 if( err != paNoError )
goto done;
331 fprintf(stderr,
"Error: No default input device.\n");
349 if( err != paNoError )
goto done;
352 data.file = fopen(FILE_NAME,
"wb");
353 if (data.file == 0)
goto done;
356 err = startThread(&data, threadFunctionWriteToRawFile);
357 if( err != paNoError )
goto done;
360 if( err != paNoError )
goto done;
361 printf(
"\n=== Now recording to '" FILE_NAME
"' for %d seconds!! Please speak into the microphone. ===\n", NUM_SECONDS); fflush(stdout);
366 while( delayCntr++ < NUM_SECONDS )
368 printf(
"index = %d\n", data.frameIndex ); fflush(stdout);
371 if( err < 0 )
goto done;
374 if( err != paNoError )
goto done;
377 err = stopThread(&data);
378 if( err != paNoError )
goto done;
389 fprintf(stderr,
"Error: No default output device.\n");
397 printf(
"\n=== Now playing back from file '" FILE_NAME
"' until end-of-file is reached ===\n"); fflush(stdout);
407 if( err != paNoError )
goto done;
412 data.file = fopen(FILE_NAME,
"rb");
416 err = startThread(&data, threadFunctionReadFromRawFile);
417 if( err != paNoError )
goto done;
420 if( err != paNoError )
goto done;
422 printf(
"Waiting for playback to finish.\n"); fflush(stdout);
426 printf(
"index = %d\n", data.frameIndex ); fflush(stdout);
429 if( err < 0 )
goto done;
433 if( err != paNoError )
goto done;
437 printf(
"Done.\n"); fflush(stdout);
442 if( data.ringBufferData )
443 PaUtil_FreeMemory( data.ringBufferData );
444 if( err != paNoError )
446 fprintf( stderr,
"An error occured while using the portaudio stream\n" );
447 fprintf( stderr,
"Error number: %d\n", err );
The portable PortAudio API.
PaError Pa_Terminate(void)
PaError Pa_IsStreamActive(PaStream *stream)
PaError Pa_OpenStream(PaStream **stream, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate, unsigned long framesPerBuffer, PaStreamFlags streamFlags, PaStreamCallback *streamCallback, void *userData)
unsigned long PaStreamCallbackFlags
PaError Pa_StartStream(PaStream *stream)
PaError Pa_CloseStream(PaStream *stream)
PaError Pa_Initialize(void)
PaDeviceIndex Pa_GetDefaultInputDevice(void)
const PaDeviceInfo * Pa_GetDeviceInfo(PaDeviceIndex device)
PaDeviceIndex Pa_GetDefaultOutputDevice(void)
const char * Pa_GetErrorText(PaError errorCode)
PaTime defaultLowInputLatency
PaSampleFormat sampleFormat
void * hostApiSpecificStreamInfo