1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-11-27 15:50:10 +01:00

Introduce end-of-line normalization

Ensures that all files that Git considers to be text will have
normalized (LF) line endings in the repository. When core.eol is set to
native (which is the default), Git will convert the line endings of
normalized files in your working directory back to your platform's
native line ending.

See also https://git-scm.com/docs/gitattributes
This commit is contained in:
Benjamin Drung
2016-05-16 21:31:38 +02:00
parent 8d360fe5f3
commit 787f2afd10
535 changed files with 107946 additions and 107944 deletions

View File

@@ -1,221 +1,221 @@
/** @file paex_read_write_wire.c
@ingroup examples_src
@brief Tests full duplex blocking I/O by passing input straight to output.
@author Bjorn Roche. XO Audio LLC for Z-Systems Engineering.
@author based on code by: Phil Burk http://www.softsynth.com
@author based on code by: Ross Bencina rossb@audiomulch.com
*/
/*
* $Id: patest_read_record.c 757 2004-02-13 07:48:10Z rossbencina $
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "portaudio.h"
/* #define SAMPLE_RATE (17932) // Test failure to open with this value. */
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (1024)
#define NUM_CHANNELS (2)
#define NUM_SECONDS (15)
/* #define DITHER_FLAG (paDitherOff) */
#define DITHER_FLAG (0) /**/
/* @todo Underflow and overflow is disabled until we fix priming of blocking write. */
#define CHECK_OVERFLOW (0)
#define CHECK_UNDERFLOW (0)
/* Select sample format. */
#if 0
#define PA_SAMPLE_TYPE paFloat32
#define SAMPLE_SIZE (4)
#define SAMPLE_SILENCE (0.0f)
#define CLEAR(a) memset( (a), 0, FRAMES_PER_BUFFER * NUM_CHANNELS * SAMPLE_SIZE )
#define PRINTF_S_FORMAT "%.8f"
#elif 0
#define PA_SAMPLE_TYPE paInt16
#define SAMPLE_SIZE (2)
#define SAMPLE_SILENCE (0)
#define CLEAR(a) memset( (a), 0, FRAMES_PER_BUFFER * NUM_CHANNELS * SAMPLE_SIZE )
#define PRINTF_S_FORMAT "%d"
#elif 1
#define PA_SAMPLE_TYPE paInt24
#define SAMPLE_SIZE (3)
#define SAMPLE_SILENCE (0)
#define CLEAR(a) memset( (a), 0, FRAMES_PER_BUFFER * NUM_CHANNELS * SAMPLE_SIZE )
#define PRINTF_S_FORMAT "%d"
#elif 0
#define PA_SAMPLE_TYPE paInt8
#define SAMPLE_SIZE (1)
#define SAMPLE_SILENCE (0)
#define CLEAR(a) memset( (a), 0, FRAMES_PER_BUFFER * NUM_CHANNELS * SAMPLE_SIZE )
#define PRINTF_S_FORMAT "%d"
#else
#define PA_SAMPLE_TYPE paUInt8
#define SAMPLE_SIZE (1)
#define SAMPLE_SILENCE (128)
#define CLEAR( a ) { \
int i; \
for( i=0; i<FRAMES_PER_BUFFER*NUM_CHANNELS; i++ ) \
((unsigned char *)a)[i] = (SAMPLE_SILENCE); \
}
#define PRINTF_S_FORMAT "%d"
#endif
/*******************************************************************/
int main(void);
int main(void)
{
PaStreamParameters inputParameters, outputParameters;
PaStream *stream = NULL;
PaError err;
char *sampleBlock;
int i;
int numBytes;
printf("patest_read_write_wire.c\n"); fflush(stdout);
numBytes = FRAMES_PER_BUFFER * NUM_CHANNELS * SAMPLE_SIZE ;
sampleBlock = (char *) malloc( numBytes );
if( sampleBlock == NULL )
{
printf("Could not allocate record array.\n");
exit(1);
}
CLEAR( sampleBlock );
err = Pa_Initialize();
if( err != paNoError ) goto error;
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
printf( "Input device # %d.\n", inputParameters.device );
printf( "Input LL: %g s\n", Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency );
printf( "Input HL: %g s\n", Pa_GetDeviceInfo( inputParameters.device )->defaultHighInputLatency );
inputParameters.channelCount = NUM_CHANNELS;
inputParameters.sampleFormat = PA_SAMPLE_TYPE;
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultHighInputLatency ;
inputParameters.hostApiSpecificStreamInfo = NULL;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
printf( "Output device # %d.\n", outputParameters.device );
printf( "Output LL: %g s\n", Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency );
printf( "Output HL: %g s\n", Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency );
outputParameters.channelCount = NUM_CHANNELS;
outputParameters.sampleFormat = PA_SAMPLE_TYPE;
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
/* -- setup -- */
err = Pa_OpenStream(
&stream,
&inputParameters,
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
NULL, /* no callback, use blocking API */
NULL ); /* no callback, so no callback userData */
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Wire on. Will run %d seconds.\n", NUM_SECONDS); fflush(stdout);
for( i=0; i<(NUM_SECONDS*SAMPLE_RATE)/FRAMES_PER_BUFFER; ++i )
{
err = Pa_WriteStream( stream, sampleBlock, FRAMES_PER_BUFFER );
if( err && CHECK_UNDERFLOW ) goto xrun;
err = Pa_ReadStream( stream, sampleBlock, FRAMES_PER_BUFFER );
if( err && CHECK_OVERFLOW ) goto xrun;
}
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
CLEAR( sampleBlock );
/*
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Wire on. Interrupt to stop.\n"); fflush(stdout);
while( 1 )
{
err = Pa_WriteStream( stream, sampleBlock, FRAMES_PER_BUFFER );
if( err ) goto xrun;
err = Pa_ReadStream( stream, sampleBlock, FRAMES_PER_BUFFER );
if( err ) goto xrun;
}
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
Pa_CloseStream( stream );
*/
free( sampleBlock );
Pa_Terminate();
return 0;
xrun:
if( stream ) {
Pa_AbortStream( stream );
Pa_CloseStream( stream );
}
free( sampleBlock );
Pa_Terminate();
if( err & paInputOverflow )
fprintf( stderr, "Input Overflow.\n" );
if( err & paOutputUnderflow )
fprintf( stderr, "Output Underflow.\n" );
return -2;
error:
if( stream ) {
Pa_AbortStream( stream );
Pa_CloseStream( stream );
}
free( sampleBlock );
Pa_Terminate();
fprintf( stderr, "An error occured while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return -1;
}
/** @file paex_read_write_wire.c
@ingroup examples_src
@brief Tests full duplex blocking I/O by passing input straight to output.
@author Bjorn Roche. XO Audio LLC for Z-Systems Engineering.
@author based on code by: Phil Burk http://www.softsynth.com
@author based on code by: Ross Bencina rossb@audiomulch.com
*/
/*
* $Id: patest_read_record.c 757 2004-02-13 07:48:10Z rossbencina $
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "portaudio.h"
/* #define SAMPLE_RATE (17932) // Test failure to open with this value. */
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (1024)
#define NUM_CHANNELS (2)
#define NUM_SECONDS (15)
/* #define DITHER_FLAG (paDitherOff) */
#define DITHER_FLAG (0) /**/
/* @todo Underflow and overflow is disabled until we fix priming of blocking write. */
#define CHECK_OVERFLOW (0)
#define CHECK_UNDERFLOW (0)
/* Select sample format. */
#if 0
#define PA_SAMPLE_TYPE paFloat32
#define SAMPLE_SIZE (4)
#define SAMPLE_SILENCE (0.0f)
#define CLEAR(a) memset( (a), 0, FRAMES_PER_BUFFER * NUM_CHANNELS * SAMPLE_SIZE )
#define PRINTF_S_FORMAT "%.8f"
#elif 0
#define PA_SAMPLE_TYPE paInt16
#define SAMPLE_SIZE (2)
#define SAMPLE_SILENCE (0)
#define CLEAR(a) memset( (a), 0, FRAMES_PER_BUFFER * NUM_CHANNELS * SAMPLE_SIZE )
#define PRINTF_S_FORMAT "%d"
#elif 1
#define PA_SAMPLE_TYPE paInt24
#define SAMPLE_SIZE (3)
#define SAMPLE_SILENCE (0)
#define CLEAR(a) memset( (a), 0, FRAMES_PER_BUFFER * NUM_CHANNELS * SAMPLE_SIZE )
#define PRINTF_S_FORMAT "%d"
#elif 0
#define PA_SAMPLE_TYPE paInt8
#define SAMPLE_SIZE (1)
#define SAMPLE_SILENCE (0)
#define CLEAR(a) memset( (a), 0, FRAMES_PER_BUFFER * NUM_CHANNELS * SAMPLE_SIZE )
#define PRINTF_S_FORMAT "%d"
#else
#define PA_SAMPLE_TYPE paUInt8
#define SAMPLE_SIZE (1)
#define SAMPLE_SILENCE (128)
#define CLEAR( a ) { \
int i; \
for( i=0; i<FRAMES_PER_BUFFER*NUM_CHANNELS; i++ ) \
((unsigned char *)a)[i] = (SAMPLE_SILENCE); \
}
#define PRINTF_S_FORMAT "%d"
#endif
/*******************************************************************/
int main(void);
int main(void)
{
PaStreamParameters inputParameters, outputParameters;
PaStream *stream = NULL;
PaError err;
char *sampleBlock;
int i;
int numBytes;
printf("patest_read_write_wire.c\n"); fflush(stdout);
numBytes = FRAMES_PER_BUFFER * NUM_CHANNELS * SAMPLE_SIZE ;
sampleBlock = (char *) malloc( numBytes );
if( sampleBlock == NULL )
{
printf("Could not allocate record array.\n");
exit(1);
}
CLEAR( sampleBlock );
err = Pa_Initialize();
if( err != paNoError ) goto error;
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
printf( "Input device # %d.\n", inputParameters.device );
printf( "Input LL: %g s\n", Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency );
printf( "Input HL: %g s\n", Pa_GetDeviceInfo( inputParameters.device )->defaultHighInputLatency );
inputParameters.channelCount = NUM_CHANNELS;
inputParameters.sampleFormat = PA_SAMPLE_TYPE;
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultHighInputLatency ;
inputParameters.hostApiSpecificStreamInfo = NULL;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
printf( "Output device # %d.\n", outputParameters.device );
printf( "Output LL: %g s\n", Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency );
printf( "Output HL: %g s\n", Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency );
outputParameters.channelCount = NUM_CHANNELS;
outputParameters.sampleFormat = PA_SAMPLE_TYPE;
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
/* -- setup -- */
err = Pa_OpenStream(
&stream,
&inputParameters,
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
NULL, /* no callback, use blocking API */
NULL ); /* no callback, so no callback userData */
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Wire on. Will run %d seconds.\n", NUM_SECONDS); fflush(stdout);
for( i=0; i<(NUM_SECONDS*SAMPLE_RATE)/FRAMES_PER_BUFFER; ++i )
{
err = Pa_WriteStream( stream, sampleBlock, FRAMES_PER_BUFFER );
if( err && CHECK_UNDERFLOW ) goto xrun;
err = Pa_ReadStream( stream, sampleBlock, FRAMES_PER_BUFFER );
if( err && CHECK_OVERFLOW ) goto xrun;
}
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
CLEAR( sampleBlock );
/*
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Wire on. Interrupt to stop.\n"); fflush(stdout);
while( 1 )
{
err = Pa_WriteStream( stream, sampleBlock, FRAMES_PER_BUFFER );
if( err ) goto xrun;
err = Pa_ReadStream( stream, sampleBlock, FRAMES_PER_BUFFER );
if( err ) goto xrun;
}
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
Pa_CloseStream( stream );
*/
free( sampleBlock );
Pa_Terminate();
return 0;
xrun:
if( stream ) {
Pa_AbortStream( stream );
Pa_CloseStream( stream );
}
free( sampleBlock );
Pa_Terminate();
if( err & paInputOverflow )
fprintf( stderr, "Input Overflow.\n" );
if( err & paOutputUnderflow )
fprintf( stderr, "Output Underflow.\n" );
return -2;
error:
if( stream ) {
Pa_AbortStream( stream );
Pa_CloseStream( stream );
}
free( sampleBlock );
Pa_Terminate();
fprintf( stderr, "An error occured while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return -1;
}

View File

@@ -1,453 +1,453 @@
/** @file paex_record_file.c
@ingroup examples_src
@brief Record input into a file, then playback recorded data from file (Windows only at the moment)
@author Robert Bielik
*/
/*
* $Id: paex_record_file.c 1752 2011-09-08 03:21:55Z philburk $
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <stdlib.h>
#include "portaudio.h"
#include "pa_ringbuffer.h"
#include "pa_util.h"
#ifdef _WIN32
#include <windows.h>
#include <process.h>
#endif
/* #define SAMPLE_RATE (17932) // Test failure to open with this value. */
#define FILE_NAME "audio_data.raw"
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (512)
#define NUM_SECONDS (10)
#define NUM_CHANNELS (2)
#define NUM_WRITES_PER_BUFFER (4)
/* #define DITHER_FLAG (paDitherOff) */
#define DITHER_FLAG (0) /**/
/* Select sample format. */
#if 1
#define PA_SAMPLE_TYPE paFloat32
typedef float SAMPLE;
#define SAMPLE_SILENCE (0.0f)
#define PRINTF_S_FORMAT "%.8f"
#elif 1
#define PA_SAMPLE_TYPE paInt16
typedef short SAMPLE;
#define SAMPLE_SILENCE (0)
#define PRINTF_S_FORMAT "%d"
#elif 0
#define PA_SAMPLE_TYPE paInt8
typedef char SAMPLE;
#define SAMPLE_SILENCE (0)
#define PRINTF_S_FORMAT "%d"
#else
#define PA_SAMPLE_TYPE paUInt8
typedef unsigned char SAMPLE;
#define SAMPLE_SILENCE (128)
#define PRINTF_S_FORMAT "%d"
#endif
typedef struct
{
unsigned frameIndex;
int threadSyncFlag;
SAMPLE *ringBufferData;
PaUtilRingBuffer ringBuffer;
FILE *file;
void *threadHandle;
}
paTestData;
/* This routine is run in a separate thread to write data from the ring buffer into a file (during Recording) */
static int threadFunctionWriteToRawFile(void* ptr)
{
paTestData* pData = (paTestData*)ptr;
/* Mark thread started */
pData->threadSyncFlag = 0;
while (1)
{
ring_buffer_size_t elementsInBuffer = PaUtil_GetRingBufferReadAvailable(&pData->ringBuffer);
if ( (elementsInBuffer >= pData->ringBuffer.bufferSize / NUM_WRITES_PER_BUFFER) ||
pData->threadSyncFlag )
{
void* ptr[2] = {0};
ring_buffer_size_t sizes[2] = {0};
/* By using PaUtil_GetRingBufferReadRegions, we can read directly from the ring buffer */
ring_buffer_size_t elementsRead = PaUtil_GetRingBufferReadRegions(&pData->ringBuffer, elementsInBuffer, ptr + 0, sizes + 0, ptr + 1, sizes + 1);
if (elementsRead > 0)
{
int i;
for (i = 0; i < 2 && ptr[i] != NULL; ++i)
{
fwrite(ptr[i], pData->ringBuffer.elementSizeBytes, sizes[i], pData->file);
}
PaUtil_AdvanceRingBufferReadIndex(&pData->ringBuffer, elementsRead);
}
if (pData->threadSyncFlag)
{
break;
}
}
/* Sleep a little while... */
Pa_Sleep(20);
}
pData->threadSyncFlag = 0;
return 0;
}
/* This routine is run in a separate thread to read data from file into the ring buffer (during Playback). When the file
has reached EOF, a flag is set so that the play PA callback can return paComplete */
static int threadFunctionReadFromRawFile(void* ptr)
{
paTestData* pData = (paTestData*)ptr;
while (1)
{
ring_buffer_size_t elementsInBuffer = PaUtil_GetRingBufferWriteAvailable(&pData->ringBuffer);
if (elementsInBuffer >= pData->ringBuffer.bufferSize / NUM_WRITES_PER_BUFFER)
{
void* ptr[2] = {0};
ring_buffer_size_t sizes[2] = {0};
/* By using PaUtil_GetRingBufferWriteRegions, we can write directly into the ring buffer */
PaUtil_GetRingBufferWriteRegions(&pData->ringBuffer, elementsInBuffer, ptr + 0, sizes + 0, ptr + 1, sizes + 1);
if (!feof(pData->file))
{
ring_buffer_size_t itemsReadFromFile = 0;
int i;
for (i = 0; i < 2 && ptr[i] != NULL; ++i)
{
itemsReadFromFile += (ring_buffer_size_t)fread(ptr[i], pData->ringBuffer.elementSizeBytes, sizes[i], pData->file);
}
PaUtil_AdvanceRingBufferWriteIndex(&pData->ringBuffer, itemsReadFromFile);
/* Mark thread started here, that way we "prime" the ring buffer before playback */
pData->threadSyncFlag = 0;
}
else
{
/* No more data to read */
pData->threadSyncFlag = 1;
break;
}
}
/* Sleep a little while... */
Pa_Sleep(20);
}
return 0;
}
typedef int (*ThreadFunctionType)(void*);
/* Start up a new thread in the given function, at the moment only Windows, but should be very easy to extend
to posix type OSs (Linux/Mac) */
static PaError startThread( paTestData* pData, ThreadFunctionType fn )
{
#ifdef _WIN32
typedef unsigned (__stdcall* WinThreadFunctionType)(void*);
pData->threadHandle = (void*)_beginthreadex(NULL, 0, (WinThreadFunctionType)fn, pData, CREATE_SUSPENDED, NULL);
if (pData->threadHandle == NULL) return paUnanticipatedHostError;
/* Set file thread to a little higher prio than normal */
SetThreadPriority(pData->threadHandle, THREAD_PRIORITY_ABOVE_NORMAL);
/* Start it up */
pData->threadSyncFlag = 1;
ResumeThread(pData->threadHandle);
#endif
/* Wait for thread to startup */
while (pData->threadSyncFlag) {
Pa_Sleep(10);
}
return paNoError;
}
static int stopThread( paTestData* pData )
{
pData->threadSyncFlag = 1;
/* Wait for thread to stop */
while (pData->threadSyncFlag) {
Pa_Sleep(10);
}
#ifdef _WIN32
CloseHandle(pData->threadHandle);
pData->threadHandle = 0;
#endif
return paNoError;
}
/* This routine will be called by the PortAudio engine when audio is needed.
** It may be called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int recordCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
ring_buffer_size_t elementsWriteable = PaUtil_GetRingBufferWriteAvailable(&data->ringBuffer);
ring_buffer_size_t elementsToWrite = min(elementsWriteable, (ring_buffer_size_t)(framesPerBuffer * NUM_CHANNELS));
const SAMPLE *rptr = (const SAMPLE*)inputBuffer;
(void) outputBuffer; /* Prevent unused variable warnings. */
(void) timeInfo;
(void) statusFlags;
(void) userData;
data->frameIndex += PaUtil_WriteRingBuffer(&data->ringBuffer, rptr, elementsToWrite);
return paContinue;
}
/* This routine will be called by the PortAudio engine when audio is needed.
** It may be called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int playCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
ring_buffer_size_t elementsToPlay = PaUtil_GetRingBufferReadAvailable(&data->ringBuffer);
ring_buffer_size_t elementsToRead = min(elementsToPlay, (ring_buffer_size_t)(framesPerBuffer * NUM_CHANNELS));
SAMPLE* wptr = (SAMPLE*)outputBuffer;
(void) inputBuffer; /* Prevent unused variable warnings. */
(void) timeInfo;
(void) statusFlags;
(void) userData;
data->frameIndex += PaUtil_ReadRingBuffer(&data->ringBuffer, wptr, elementsToRead);
return data->threadSyncFlag ? paComplete : paContinue;
}
static unsigned NextPowerOf2(unsigned val)
{
val--;
val = (val >> 1) | val;
val = (val >> 2) | val;
val = (val >> 4) | val;
val = (val >> 8) | val;
val = (val >> 16) | val;
return ++val;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaStreamParameters inputParameters,
outputParameters;
PaStream* stream;
PaError err = paNoError;
paTestData data = {0};
unsigned delayCntr;
unsigned numSamples;
unsigned numBytes;
printf("patest_record.c\n"); fflush(stdout);
/* We set the ring buffer size to about 500 ms */
numSamples = NextPowerOf2((unsigned)(SAMPLE_RATE * 0.5 * NUM_CHANNELS));
numBytes = numSamples * sizeof(SAMPLE);
data.ringBufferData = (SAMPLE *) PaUtil_AllocateMemory( numBytes );
if( data.ringBufferData == NULL )
{
printf("Could not allocate ring buffer data.\n");
goto done;
}
if (PaUtil_InitializeRingBuffer(&data.ringBuffer, sizeof(SAMPLE), numSamples, data.ringBufferData) < 0)
{
printf("Failed to initialize ring buffer. Size is not power of 2 ??\n");
goto done;
}
err = Pa_Initialize();
if( err != paNoError ) goto done;
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
if (inputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default input device.\n");
goto done;
}
inputParameters.channelCount = 2; /* stereo input */
inputParameters.sampleFormat = PA_SAMPLE_TYPE;
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = NULL;
/* Record some audio. -------------------------------------------- */
err = Pa_OpenStream(
&stream,
&inputParameters,
NULL, /* &outputParameters, */
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
recordCallback,
&data );
if( err != paNoError ) goto done;
/* Open the raw audio 'cache' file... */
data.file = fopen(FILE_NAME, "wb");
if (data.file == 0) goto done;
/* Start the file writing thread */
err = startThread(&data, threadFunctionWriteToRawFile);
if( err != paNoError ) goto done;
err = Pa_StartStream( stream );
if( err != paNoError ) goto done;
printf("\n=== Now recording to '" FILE_NAME "' for %d seconds!! Please speak into the microphone. ===\n", NUM_SECONDS); fflush(stdout);
/* Note that the RECORDING part is limited with TIME, not size of the file and/or buffer, so you can
increase NUM_SECONDS until you run out of disk */
delayCntr = 0;
while( delayCntr++ < NUM_SECONDS )
{
printf("index = %d\n", data.frameIndex ); fflush(stdout);
Pa_Sleep(1000);
}
if( err < 0 ) goto done;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto done;
/* Stop the thread */
err = stopThread(&data);
if( err != paNoError ) goto done;
/* Close file */
fclose(data.file);
data.file = 0;
/* Playback recorded data. -------------------------------------------- */
data.frameIndex = 0;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto done;
}
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = PA_SAMPLE_TYPE;
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
printf("\n=== Now playing back from file '" FILE_NAME "' until end-of-file is reached ===\n"); fflush(stdout);
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
playCallback,
&data );
if( err != paNoError ) goto done;
if( stream )
{
/* Open file again for reading */
data.file = fopen(FILE_NAME, "rb");
if (data.file != 0)
{
/* Start the file reading thread */
err = startThread(&data, threadFunctionReadFromRawFile);
if( err != paNoError ) goto done;
err = Pa_StartStream( stream );
if( err != paNoError ) goto done;
printf("Waiting for playback to finish.\n"); fflush(stdout);
/* The playback will end when EOF is reached */
while( ( err = Pa_IsStreamActive( stream ) ) == 1 ) {
printf("index = %d\n", data.frameIndex ); fflush(stdout);
Pa_Sleep(1000);
}
if( err < 0 ) goto done;
}
err = Pa_CloseStream( stream );
if( err != paNoError ) goto done;
fclose(data.file);
printf("Done.\n"); fflush(stdout);
}
done:
Pa_Terminate();
if( data.ringBufferData ) /* Sure it is NULL or valid. */
PaUtil_FreeMemory( data.ringBufferData );
if( err != paNoError )
{
fprintf( stderr, "An error occured while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
err = 1; /* Always return 0 or 1, but no other return codes. */
}
return err;
}
/** @file paex_record_file.c
@ingroup examples_src
@brief Record input into a file, then playback recorded data from file (Windows only at the moment)
@author Robert Bielik
*/
/*
* $Id: paex_record_file.c 1752 2011-09-08 03:21:55Z philburk $
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <stdlib.h>
#include "portaudio.h"
#include "pa_ringbuffer.h"
#include "pa_util.h"
#ifdef _WIN32
#include <windows.h>
#include <process.h>
#endif
/* #define SAMPLE_RATE (17932) // Test failure to open with this value. */
#define FILE_NAME "audio_data.raw"
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (512)
#define NUM_SECONDS (10)
#define NUM_CHANNELS (2)
#define NUM_WRITES_PER_BUFFER (4)
/* #define DITHER_FLAG (paDitherOff) */
#define DITHER_FLAG (0) /**/
/* Select sample format. */
#if 1
#define PA_SAMPLE_TYPE paFloat32
typedef float SAMPLE;
#define SAMPLE_SILENCE (0.0f)
#define PRINTF_S_FORMAT "%.8f"
#elif 1
#define PA_SAMPLE_TYPE paInt16
typedef short SAMPLE;
#define SAMPLE_SILENCE (0)
#define PRINTF_S_FORMAT "%d"
#elif 0
#define PA_SAMPLE_TYPE paInt8
typedef char SAMPLE;
#define SAMPLE_SILENCE (0)
#define PRINTF_S_FORMAT "%d"
#else
#define PA_SAMPLE_TYPE paUInt8
typedef unsigned char SAMPLE;
#define SAMPLE_SILENCE (128)
#define PRINTF_S_FORMAT "%d"
#endif
typedef struct
{
unsigned frameIndex;
int threadSyncFlag;
SAMPLE *ringBufferData;
PaUtilRingBuffer ringBuffer;
FILE *file;
void *threadHandle;
}
paTestData;
/* This routine is run in a separate thread to write data from the ring buffer into a file (during Recording) */
static int threadFunctionWriteToRawFile(void* ptr)
{
paTestData* pData = (paTestData*)ptr;
/* Mark thread started */
pData->threadSyncFlag = 0;
while (1)
{
ring_buffer_size_t elementsInBuffer = PaUtil_GetRingBufferReadAvailable(&pData->ringBuffer);
if ( (elementsInBuffer >= pData->ringBuffer.bufferSize / NUM_WRITES_PER_BUFFER) ||
pData->threadSyncFlag )
{
void* ptr[2] = {0};
ring_buffer_size_t sizes[2] = {0};
/* By using PaUtil_GetRingBufferReadRegions, we can read directly from the ring buffer */
ring_buffer_size_t elementsRead = PaUtil_GetRingBufferReadRegions(&pData->ringBuffer, elementsInBuffer, ptr + 0, sizes + 0, ptr + 1, sizes + 1);
if (elementsRead > 0)
{
int i;
for (i = 0; i < 2 && ptr[i] != NULL; ++i)
{
fwrite(ptr[i], pData->ringBuffer.elementSizeBytes, sizes[i], pData->file);
}
PaUtil_AdvanceRingBufferReadIndex(&pData->ringBuffer, elementsRead);
}
if (pData->threadSyncFlag)
{
break;
}
}
/* Sleep a little while... */
Pa_Sleep(20);
}
pData->threadSyncFlag = 0;
return 0;
}
/* This routine is run in a separate thread to read data from file into the ring buffer (during Playback). When the file
has reached EOF, a flag is set so that the play PA callback can return paComplete */
static int threadFunctionReadFromRawFile(void* ptr)
{
paTestData* pData = (paTestData*)ptr;
while (1)
{
ring_buffer_size_t elementsInBuffer = PaUtil_GetRingBufferWriteAvailable(&pData->ringBuffer);
if (elementsInBuffer >= pData->ringBuffer.bufferSize / NUM_WRITES_PER_BUFFER)
{
void* ptr[2] = {0};
ring_buffer_size_t sizes[2] = {0};
/* By using PaUtil_GetRingBufferWriteRegions, we can write directly into the ring buffer */
PaUtil_GetRingBufferWriteRegions(&pData->ringBuffer, elementsInBuffer, ptr + 0, sizes + 0, ptr + 1, sizes + 1);
if (!feof(pData->file))
{
ring_buffer_size_t itemsReadFromFile = 0;
int i;
for (i = 0; i < 2 && ptr[i] != NULL; ++i)
{
itemsReadFromFile += (ring_buffer_size_t)fread(ptr[i], pData->ringBuffer.elementSizeBytes, sizes[i], pData->file);
}
PaUtil_AdvanceRingBufferWriteIndex(&pData->ringBuffer, itemsReadFromFile);
/* Mark thread started here, that way we "prime" the ring buffer before playback */
pData->threadSyncFlag = 0;
}
else
{
/* No more data to read */
pData->threadSyncFlag = 1;
break;
}
}
/* Sleep a little while... */
Pa_Sleep(20);
}
return 0;
}
typedef int (*ThreadFunctionType)(void*);
/* Start up a new thread in the given function, at the moment only Windows, but should be very easy to extend
to posix type OSs (Linux/Mac) */
static PaError startThread( paTestData* pData, ThreadFunctionType fn )
{
#ifdef _WIN32
typedef unsigned (__stdcall* WinThreadFunctionType)(void*);
pData->threadHandle = (void*)_beginthreadex(NULL, 0, (WinThreadFunctionType)fn, pData, CREATE_SUSPENDED, NULL);
if (pData->threadHandle == NULL) return paUnanticipatedHostError;
/* Set file thread to a little higher prio than normal */
SetThreadPriority(pData->threadHandle, THREAD_PRIORITY_ABOVE_NORMAL);
/* Start it up */
pData->threadSyncFlag = 1;
ResumeThread(pData->threadHandle);
#endif
/* Wait for thread to startup */
while (pData->threadSyncFlag) {
Pa_Sleep(10);
}
return paNoError;
}
static int stopThread( paTestData* pData )
{
pData->threadSyncFlag = 1;
/* Wait for thread to stop */
while (pData->threadSyncFlag) {
Pa_Sleep(10);
}
#ifdef _WIN32
CloseHandle(pData->threadHandle);
pData->threadHandle = 0;
#endif
return paNoError;
}
/* This routine will be called by the PortAudio engine when audio is needed.
** It may be called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int recordCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
ring_buffer_size_t elementsWriteable = PaUtil_GetRingBufferWriteAvailable(&data->ringBuffer);
ring_buffer_size_t elementsToWrite = min(elementsWriteable, (ring_buffer_size_t)(framesPerBuffer * NUM_CHANNELS));
const SAMPLE *rptr = (const SAMPLE*)inputBuffer;
(void) outputBuffer; /* Prevent unused variable warnings. */
(void) timeInfo;
(void) statusFlags;
(void) userData;
data->frameIndex += PaUtil_WriteRingBuffer(&data->ringBuffer, rptr, elementsToWrite);
return paContinue;
}
/* This routine will be called by the PortAudio engine when audio is needed.
** It may be called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int playCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
ring_buffer_size_t elementsToPlay = PaUtil_GetRingBufferReadAvailable(&data->ringBuffer);
ring_buffer_size_t elementsToRead = min(elementsToPlay, (ring_buffer_size_t)(framesPerBuffer * NUM_CHANNELS));
SAMPLE* wptr = (SAMPLE*)outputBuffer;
(void) inputBuffer; /* Prevent unused variable warnings. */
(void) timeInfo;
(void) statusFlags;
(void) userData;
data->frameIndex += PaUtil_ReadRingBuffer(&data->ringBuffer, wptr, elementsToRead);
return data->threadSyncFlag ? paComplete : paContinue;
}
static unsigned NextPowerOf2(unsigned val)
{
val--;
val = (val >> 1) | val;
val = (val >> 2) | val;
val = (val >> 4) | val;
val = (val >> 8) | val;
val = (val >> 16) | val;
return ++val;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaStreamParameters inputParameters,
outputParameters;
PaStream* stream;
PaError err = paNoError;
paTestData data = {0};
unsigned delayCntr;
unsigned numSamples;
unsigned numBytes;
printf("patest_record.c\n"); fflush(stdout);
/* We set the ring buffer size to about 500 ms */
numSamples = NextPowerOf2((unsigned)(SAMPLE_RATE * 0.5 * NUM_CHANNELS));
numBytes = numSamples * sizeof(SAMPLE);
data.ringBufferData = (SAMPLE *) PaUtil_AllocateMemory( numBytes );
if( data.ringBufferData == NULL )
{
printf("Could not allocate ring buffer data.\n");
goto done;
}
if (PaUtil_InitializeRingBuffer(&data.ringBuffer, sizeof(SAMPLE), numSamples, data.ringBufferData) < 0)
{
printf("Failed to initialize ring buffer. Size is not power of 2 ??\n");
goto done;
}
err = Pa_Initialize();
if( err != paNoError ) goto done;
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
if (inputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default input device.\n");
goto done;
}
inputParameters.channelCount = 2; /* stereo input */
inputParameters.sampleFormat = PA_SAMPLE_TYPE;
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = NULL;
/* Record some audio. -------------------------------------------- */
err = Pa_OpenStream(
&stream,
&inputParameters,
NULL, /* &outputParameters, */
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
recordCallback,
&data );
if( err != paNoError ) goto done;
/* Open the raw audio 'cache' file... */
data.file = fopen(FILE_NAME, "wb");
if (data.file == 0) goto done;
/* Start the file writing thread */
err = startThread(&data, threadFunctionWriteToRawFile);
if( err != paNoError ) goto done;
err = Pa_StartStream( stream );
if( err != paNoError ) goto done;
printf("\n=== Now recording to '" FILE_NAME "' for %d seconds!! Please speak into the microphone. ===\n", NUM_SECONDS); fflush(stdout);
/* Note that the RECORDING part is limited with TIME, not size of the file and/or buffer, so you can
increase NUM_SECONDS until you run out of disk */
delayCntr = 0;
while( delayCntr++ < NUM_SECONDS )
{
printf("index = %d\n", data.frameIndex ); fflush(stdout);
Pa_Sleep(1000);
}
if( err < 0 ) goto done;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto done;
/* Stop the thread */
err = stopThread(&data);
if( err != paNoError ) goto done;
/* Close file */
fclose(data.file);
data.file = 0;
/* Playback recorded data. -------------------------------------------- */
data.frameIndex = 0;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto done;
}
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = PA_SAMPLE_TYPE;
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
printf("\n=== Now playing back from file '" FILE_NAME "' until end-of-file is reached ===\n"); fflush(stdout);
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
playCallback,
&data );
if( err != paNoError ) goto done;
if( stream )
{
/* Open file again for reading */
data.file = fopen(FILE_NAME, "rb");
if (data.file != 0)
{
/* Start the file reading thread */
err = startThread(&data, threadFunctionReadFromRawFile);
if( err != paNoError ) goto done;
err = Pa_StartStream( stream );
if( err != paNoError ) goto done;
printf("Waiting for playback to finish.\n"); fflush(stdout);
/* The playback will end when EOF is reached */
while( ( err = Pa_IsStreamActive( stream ) ) == 1 ) {
printf("index = %d\n", data.frameIndex ); fflush(stdout);
Pa_Sleep(1000);
}
if( err < 0 ) goto done;
}
err = Pa_CloseStream( stream );
if( err != paNoError ) goto done;
fclose(data.file);
printf("Done.\n"); fflush(stdout);
}
done:
Pa_Terminate();
if( data.ringBufferData ) /* Sure it is NULL or valid. */
PaUtil_FreeMemory( data.ringBufferData );
if( err != paNoError )
{
fprintf( stderr, "An error occured while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
err = 1; /* Always return 0 or 1, but no other return codes. */
}
return err;
}

View File

@@ -1,275 +1,275 @@
/** @file paex_sine.c
@ingroup examples_src
@brief Play a sine wave for several seconds.
@author Ross Bencina <rossb@audiomulch.com>
@author Phil Burk <philburk@softsynth.com>
*/
/*
* $Id: paex_sine.c 1752 2011-09-08 03:21:55Z philburk $
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define NUM_SECONDS (5)
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (64)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (200)
class Sine
{
public:
Sine() : stream(0), left_phase(0), right_phase(0)
{
/* initialise sinusoidal wavetable */
for( int i=0; i<TABLE_SIZE; i++ )
{
sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
sprintf( message, "No Message" );
}
bool open(PaDeviceIndex index)
{
PaStreamParameters outputParameters;
outputParameters.device = index;
if (outputParameters.device == paNoDevice) {
return false;
}
const PaDeviceInfo* pInfo = Pa_GetDeviceInfo(index);
if (pInfo != 0)
{
printf("Output device name: '%s'\r", pInfo->name);
}
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
PaError err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
paFramesPerBufferUnspecified,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
&Sine::paCallback,
this /* Using 'this' for userData so we can cast to Sine* in paCallback method */
);
if (err != paNoError)
{
/* Failed to open stream to device !!! */
return false;
}
err = Pa_SetStreamFinishedCallback( stream, &Sine::paStreamFinished );
if (err != paNoError)
{
Pa_CloseStream( stream );
stream = 0;
return false;
}
return true;
}
bool close()
{
if (stream == 0)
return false;
PaError err = Pa_CloseStream( stream );
stream = 0;
return (err == paNoError);
}
bool start()
{
if (stream == 0)
return false;
PaError err = Pa_StartStream( stream );
return (err == paNoError);
}
bool stop()
{
if (stream == 0)
return false;
PaError err = Pa_StopStream( stream );
return (err == paNoError);
}
private:
/* The instance callback, where we have access to every method/variable in object of class Sine */
int paCallbackMethod(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags)
{
float *out = (float*)outputBuffer;
unsigned long i;
(void) timeInfo; /* Prevent unused variable warnings. */
(void) statusFlags;
(void) inputBuffer;
for( i=0; i<framesPerBuffer; i++ )
{
*out++ = sine[left_phase]; /* left */
*out++ = sine[right_phase]; /* right */
left_phase += 1;
if( left_phase >= TABLE_SIZE ) left_phase -= TABLE_SIZE;
right_phase += 3; /* higher pitch so we can distinguish left and right. */
if( right_phase >= TABLE_SIZE ) right_phase -= TABLE_SIZE;
}
return paContinue;
}
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int paCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
/* Here we cast userData to Sine* type so we can call the instance method paCallbackMethod, we can do that since
we called Pa_OpenStream with 'this' for userData */
return ((Sine*)userData)->paCallbackMethod(inputBuffer, outputBuffer,
framesPerBuffer,
timeInfo,
statusFlags);
}
void paStreamFinishedMethod()
{
printf( "Stream Completed: %s\n", message );
}
/*
* This routine is called by portaudio when playback is done.
*/
static void paStreamFinished(void* userData)
{
return ((Sine*)userData)->paStreamFinishedMethod();
}
PaStream *stream;
float sine[TABLE_SIZE];
int left_phase;
int right_phase;
char message[20];
};
class ScopedPaHandler
{
public:
ScopedPaHandler()
: _result(Pa_Initialize())
{
}
~ScopedPaHandler()
{
if (_result == paNoError)
{
Pa_Terminate();
}
}
PaError result() const { return _result; }
private:
PaError _result;
};
/*******************************************************************/
int main(void);
int main(void)
{
Sine sine;
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
ScopedPaHandler paInit;
if( paInit.result() != paNoError ) goto error;
if (sine.open(Pa_GetDefaultOutputDevice()))
{
if (sine.start())
{
printf("Play for %d seconds.\n", NUM_SECONDS );
Pa_Sleep( NUM_SECONDS * 1000 );
sine.stop();
}
sine.close();
}
printf("Test finished.\n");
return paNoError;
error:
fprintf( stderr, "An error occured while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", paInit.result() );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( paInit.result() ) );
return 1;
}
/** @file paex_sine.c
@ingroup examples_src
@brief Play a sine wave for several seconds.
@author Ross Bencina <rossb@audiomulch.com>
@author Phil Burk <philburk@softsynth.com>
*/
/*
* $Id: paex_sine.c 1752 2011-09-08 03:21:55Z philburk $
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define NUM_SECONDS (5)
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (64)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (200)
class Sine
{
public:
Sine() : stream(0), left_phase(0), right_phase(0)
{
/* initialise sinusoidal wavetable */
for( int i=0; i<TABLE_SIZE; i++ )
{
sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
sprintf( message, "No Message" );
}
bool open(PaDeviceIndex index)
{
PaStreamParameters outputParameters;
outputParameters.device = index;
if (outputParameters.device == paNoDevice) {
return false;
}
const PaDeviceInfo* pInfo = Pa_GetDeviceInfo(index);
if (pInfo != 0)
{
printf("Output device name: '%s'\r", pInfo->name);
}
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
PaError err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
paFramesPerBufferUnspecified,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
&Sine::paCallback,
this /* Using 'this' for userData so we can cast to Sine* in paCallback method */
);
if (err != paNoError)
{
/* Failed to open stream to device !!! */
return false;
}
err = Pa_SetStreamFinishedCallback( stream, &Sine::paStreamFinished );
if (err != paNoError)
{
Pa_CloseStream( stream );
stream = 0;
return false;
}
return true;
}
bool close()
{
if (stream == 0)
return false;
PaError err = Pa_CloseStream( stream );
stream = 0;
return (err == paNoError);
}
bool start()
{
if (stream == 0)
return false;
PaError err = Pa_StartStream( stream );
return (err == paNoError);
}
bool stop()
{
if (stream == 0)
return false;
PaError err = Pa_StopStream( stream );
return (err == paNoError);
}
private:
/* The instance callback, where we have access to every method/variable in object of class Sine */
int paCallbackMethod(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags)
{
float *out = (float*)outputBuffer;
unsigned long i;
(void) timeInfo; /* Prevent unused variable warnings. */
(void) statusFlags;
(void) inputBuffer;
for( i=0; i<framesPerBuffer; i++ )
{
*out++ = sine[left_phase]; /* left */
*out++ = sine[right_phase]; /* right */
left_phase += 1;
if( left_phase >= TABLE_SIZE ) left_phase -= TABLE_SIZE;
right_phase += 3; /* higher pitch so we can distinguish left and right. */
if( right_phase >= TABLE_SIZE ) right_phase -= TABLE_SIZE;
}
return paContinue;
}
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int paCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
/* Here we cast userData to Sine* type so we can call the instance method paCallbackMethod, we can do that since
we called Pa_OpenStream with 'this' for userData */
return ((Sine*)userData)->paCallbackMethod(inputBuffer, outputBuffer,
framesPerBuffer,
timeInfo,
statusFlags);
}
void paStreamFinishedMethod()
{
printf( "Stream Completed: %s\n", message );
}
/*
* This routine is called by portaudio when playback is done.
*/
static void paStreamFinished(void* userData)
{
return ((Sine*)userData)->paStreamFinishedMethod();
}
PaStream *stream;
float sine[TABLE_SIZE];
int left_phase;
int right_phase;
char message[20];
};
class ScopedPaHandler
{
public:
ScopedPaHandler()
: _result(Pa_Initialize())
{
}
~ScopedPaHandler()
{
if (_result == paNoError)
{
Pa_Terminate();
}
}
PaError result() const { return _result; }
private:
PaError _result;
};
/*******************************************************************/
int main(void);
int main(void)
{
Sine sine;
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
ScopedPaHandler paInit;
if( paInit.result() != paNoError ) goto error;
if (sine.open(Pa_GetDefaultOutputDevice()))
{
if (sine.start())
{
printf("Play for %d seconds.\n", NUM_SECONDS );
Pa_Sleep( NUM_SECONDS * 1000 );
sine.stop();
}
sine.close();
}
printf("Test finished.\n");
return paNoError;
error:
fprintf( stderr, "An error occured while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", paInit.result() );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( paInit.result() ) );
return 1;
}

View File

@@ -1,221 +1,221 @@
/** @file paex_wmme_ac3.c
@ingroup examples_src
@brief Use WMME-specific interface to send raw AC3 data to a S/PDIF output.
@author Ross Bencina <rossb@audiomulch.com>
*/
/*
* $Id: $
* Portable Audio I/O Library
* Windows MME ac3 sound output test
*
* Copyright (c) 2009 Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include <windows.h> /* required when using pa_win_wmme.h */
#include <mmsystem.h> /* required when using pa_win_wmme.h */
#include "portaudio.h"
#include "pa_win_wmme.h"
#define NUM_SECONDS (20)
#define SAMPLE_RATE (48000)
#define FRAMES_PER_BUFFER (64)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (100)
#define CHANNEL_COUNT (2)
typedef struct
{
short *buffer;
int bufferSampleCount;
int playbackIndex;
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
short *out = (short*)outputBuffer;
unsigned long i,j;
(void) timeInfo; /* Prevent unused variable warnings. */
(void) statusFlags;
(void) inputBuffer;
/* stream out contents of data->buffer looping at end */
for( i=0; i<framesPerBuffer; i++ )
{
for( j = 0; j < CHANNEL_COUNT; ++j ){
*out++ = data->buffer[ data->playbackIndex++ ];
if( data->playbackIndex >= data->bufferSampleCount )
data->playbackIndex = 0; /* loop at end of buffer */
}
}
return paContinue;
}
/*******************************************************************/
int main(int argc, char* argv[])
{
PaStreamParameters outputParameters;
PaWinMmeStreamInfo wmmeStreamInfo;
PaStream *stream;
PaError err;
paTestData data;
int deviceIndex;
FILE *fp;
const char *fileName = "c:\\test_48k.ac3.spdif";
data.buffer = NULL;
printf("usage: patest_wmme_ac3 fileName [paDeviceIndex]\n");
printf("**IMPORTANT*** The provided file must include the spdif preamble at the start of every AC-3 frame. Using a normal ac3 file won't work.\n");
printf("PortAudio Test: output a raw spdif ac3 stream. SR = %d, BufSize = %d, Chans = %d\n",
SAMPLE_RATE, FRAMES_PER_BUFFER, CHANNEL_COUNT);
if( argc >= 2 )
fileName = argv[1];
printf( "reading spdif ac3 raw stream file %s\n", fileName );
fp = fopen( fileName, "rb" );
if( !fp ){
fprintf( stderr, "error opening spdif ac3 file.\n" );
return -1;
}
/* get file size */
fseek( fp, 0, SEEK_END );
data.bufferSampleCount = ftell( fp ) / sizeof(short);
fseek( fp, 0, SEEK_SET );
/* allocate buffer, read the whole file into memory */
data.buffer = (short*)malloc( data.bufferSampleCount * sizeof(short) );
if( !data.buffer ){
fprintf( stderr, "error allocating buffer.\n" );
return -1;
}
fread( data.buffer, sizeof(short), data.bufferSampleCount, fp );
fclose( fp );
data.playbackIndex = 0;
err = Pa_Initialize();
if( err != paNoError ) goto error;
deviceIndex = Pa_GetHostApiInfo( Pa_HostApiTypeIdToHostApiIndex( paMME ) )->defaultOutputDevice;
if( argc >= 3 ){
sscanf( argv[1], "%d", &deviceIndex );
}
printf( "using device id %d (%s)\n", deviceIndex, Pa_GetDeviceInfo(deviceIndex)->name );
outputParameters.device = deviceIndex;
outputParameters.channelCount = CHANNEL_COUNT;
outputParameters.sampleFormat = paInt16; /* IMPORTANT must use paInt16 for WMME AC3 */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
wmmeStreamInfo.size = sizeof(PaWinMmeStreamInfo);
wmmeStreamInfo.hostApiType = paMME;
wmmeStreamInfo.version = 1;
wmmeStreamInfo.flags = paWinMmeWaveFormatDolbyAc3Spdif;
outputParameters.hostApiSpecificStreamInfo = &wmmeStreamInfo;
if( Pa_IsFormatSupported( 0, &outputParameters, SAMPLE_RATE ) == paFormatIsSupported ){
printf( "Pa_IsFormatSupported reports device will support %d channels.\n", CHANNEL_COUNT );
}else{
printf( "Pa_IsFormatSupported reports device will not support %d channels.\n", CHANNEL_COUNT );
}
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
0,
patestCallback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Play for %d seconds.\n", NUM_SECONDS );
Pa_Sleep( NUM_SECONDS * 1000 );
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
free( data.buffer );
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
free( data.buffer );
fprintf( stderr, "An error occured while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}
/** @file paex_wmme_ac3.c
@ingroup examples_src
@brief Use WMME-specific interface to send raw AC3 data to a S/PDIF output.
@author Ross Bencina <rossb@audiomulch.com>
*/
/*
* $Id: $
* Portable Audio I/O Library
* Windows MME ac3 sound output test
*
* Copyright (c) 2009 Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include <windows.h> /* required when using pa_win_wmme.h */
#include <mmsystem.h> /* required when using pa_win_wmme.h */
#include "portaudio.h"
#include "pa_win_wmme.h"
#define NUM_SECONDS (20)
#define SAMPLE_RATE (48000)
#define FRAMES_PER_BUFFER (64)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (100)
#define CHANNEL_COUNT (2)
typedef struct
{
short *buffer;
int bufferSampleCount;
int playbackIndex;
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
short *out = (short*)outputBuffer;
unsigned long i,j;
(void) timeInfo; /* Prevent unused variable warnings. */
(void) statusFlags;
(void) inputBuffer;
/* stream out contents of data->buffer looping at end */
for( i=0; i<framesPerBuffer; i++ )
{
for( j = 0; j < CHANNEL_COUNT; ++j ){
*out++ = data->buffer[ data->playbackIndex++ ];
if( data->playbackIndex >= data->bufferSampleCount )
data->playbackIndex = 0; /* loop at end of buffer */
}
}
return paContinue;
}
/*******************************************************************/
int main(int argc, char* argv[])
{
PaStreamParameters outputParameters;
PaWinMmeStreamInfo wmmeStreamInfo;
PaStream *stream;
PaError err;
paTestData data;
int deviceIndex;
FILE *fp;
const char *fileName = "c:\\test_48k.ac3.spdif";
data.buffer = NULL;
printf("usage: patest_wmme_ac3 fileName [paDeviceIndex]\n");
printf("**IMPORTANT*** The provided file must include the spdif preamble at the start of every AC-3 frame. Using a normal ac3 file won't work.\n");
printf("PortAudio Test: output a raw spdif ac3 stream. SR = %d, BufSize = %d, Chans = %d\n",
SAMPLE_RATE, FRAMES_PER_BUFFER, CHANNEL_COUNT);
if( argc >= 2 )
fileName = argv[1];
printf( "reading spdif ac3 raw stream file %s\n", fileName );
fp = fopen( fileName, "rb" );
if( !fp ){
fprintf( stderr, "error opening spdif ac3 file.\n" );
return -1;
}
/* get file size */
fseek( fp, 0, SEEK_END );
data.bufferSampleCount = ftell( fp ) / sizeof(short);
fseek( fp, 0, SEEK_SET );
/* allocate buffer, read the whole file into memory */
data.buffer = (short*)malloc( data.bufferSampleCount * sizeof(short) );
if( !data.buffer ){
fprintf( stderr, "error allocating buffer.\n" );
return -1;
}
fread( data.buffer, sizeof(short), data.bufferSampleCount, fp );
fclose( fp );
data.playbackIndex = 0;
err = Pa_Initialize();
if( err != paNoError ) goto error;
deviceIndex = Pa_GetHostApiInfo( Pa_HostApiTypeIdToHostApiIndex( paMME ) )->defaultOutputDevice;
if( argc >= 3 ){
sscanf( argv[1], "%d", &deviceIndex );
}
printf( "using device id %d (%s)\n", deviceIndex, Pa_GetDeviceInfo(deviceIndex)->name );
outputParameters.device = deviceIndex;
outputParameters.channelCount = CHANNEL_COUNT;
outputParameters.sampleFormat = paInt16; /* IMPORTANT must use paInt16 for WMME AC3 */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
wmmeStreamInfo.size = sizeof(PaWinMmeStreamInfo);
wmmeStreamInfo.hostApiType = paMME;
wmmeStreamInfo.version = 1;
wmmeStreamInfo.flags = paWinMmeWaveFormatDolbyAc3Spdif;
outputParameters.hostApiSpecificStreamInfo = &wmmeStreamInfo;
if( Pa_IsFormatSupported( 0, &outputParameters, SAMPLE_RATE ) == paFormatIsSupported ){
printf( "Pa_IsFormatSupported reports device will support %d channels.\n", CHANNEL_COUNT );
}else{
printf( "Pa_IsFormatSupported reports device will not support %d channels.\n", CHANNEL_COUNT );
}
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
0,
patestCallback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Play for %d seconds.\n", NUM_SECONDS );
Pa_Sleep( NUM_SECONDS * 1000 );
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
free( data.buffer );
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
free( data.buffer );
fprintf( stderr, "An error occured while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -1,211 +1,211 @@
/** @file paex_wmme_surround.c
@ingroup examples_src
@brief Use WMME-specific channelMask to request 5.1 surround sound output.
@author Ross Bencina <rossb@audiomulch.com>
*/
/*
* $Id: $
* Portable Audio I/O Library
* Windows MME surround sound output test
*
* Copyright (c) 2007 Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include <windows.h> /* required when using pa_win_wmme.h */
#include <mmsystem.h> /* required when using pa_win_wmme.h */
#include "portaudio.h"
#include "pa_win_wmme.h"
#define NUM_SECONDS (12)
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (64)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (100)
#define CHANNEL_COUNT (6)
typedef struct
{
float sine[TABLE_SIZE];
int phase;
int currentChannel;
int cycleCount;
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned long i,j;
(void) timeInfo; /* Prevent unused variable warnings. */
(void) statusFlags;
(void) inputBuffer;
for( i=0; i<framesPerBuffer; i++ )
{
for( j = 0; j < CHANNEL_COUNT; ++j ){
if( j == data->currentChannel && data->cycleCount < 4410 ){
*out++ = data->sine[data->phase];
data->phase += 1 + j; // play each channel at a different pitch so they can be distinguished
if( data->phase >= TABLE_SIZE ){
data->phase -= TABLE_SIZE;
}
}else{
*out++ = 0;
}
}
data->cycleCount++;
if( data->cycleCount > 44100 ){
data->cycleCount = 0;
++data->currentChannel;
if( data->currentChannel >= CHANNEL_COUNT )
data->currentChannel -= CHANNEL_COUNT;
}
}
return paContinue;
}
/*******************************************************************/
int main(int argc, char* argv[])
{
PaStreamParameters outputParameters;
PaWinMmeStreamInfo wmmeStreamInfo;
PaStream *stream;
PaError err;
paTestData data;
int i;
int deviceIndex;
printf("PortAudio Test: output a sine blip on each channel. SR = %d, BufSize = %d, Chans = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER, CHANNEL_COUNT);
err = Pa_Initialize();
if( err != paNoError ) goto error;
deviceIndex = Pa_GetHostApiInfo( Pa_HostApiTypeIdToHostApiIndex( paMME ) )->defaultOutputDevice;
if( argc == 2 ){
sscanf( argv[1], "%d", &deviceIndex );
}
printf( "using device id %d (%s)\n", deviceIndex, Pa_GetDeviceInfo(deviceIndex)->name );
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
data.phase = 0;
data.currentChannel = 0;
data.cycleCount = 0;
outputParameters.device = deviceIndex;
outputParameters.channelCount = CHANNEL_COUNT;
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point processing */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
/* it's not strictly necessary to provide a channelMask for surround sound
output. But if you want to be sure which channel mask PortAudio will use
then you should supply one */
wmmeStreamInfo.size = sizeof(PaWinMmeStreamInfo);
wmmeStreamInfo.hostApiType = paMME;
wmmeStreamInfo.version = 1;
wmmeStreamInfo.flags = paWinMmeUseChannelMask;
wmmeStreamInfo.channelMask = PAWIN_SPEAKER_5POINT1; /* request 5.1 output format */
outputParameters.hostApiSpecificStreamInfo = &wmmeStreamInfo;
if( Pa_IsFormatSupported( 0, &outputParameters, SAMPLE_RATE ) == paFormatIsSupported ){
printf( "Pa_IsFormatSupported reports device will support %d channels.\n", CHANNEL_COUNT );
}else{
printf( "Pa_IsFormatSupported reports device will not support %d channels.\n", CHANNEL_COUNT );
}
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Play for %d seconds.\n", NUM_SECONDS );
Pa_Sleep( NUM_SECONDS * 1000 );
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occured while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}
/** @file paex_wmme_surround.c
@ingroup examples_src
@brief Use WMME-specific channelMask to request 5.1 surround sound output.
@author Ross Bencina <rossb@audiomulch.com>
*/
/*
* $Id: $
* Portable Audio I/O Library
* Windows MME surround sound output test
*
* Copyright (c) 2007 Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include <windows.h> /* required when using pa_win_wmme.h */
#include <mmsystem.h> /* required when using pa_win_wmme.h */
#include "portaudio.h"
#include "pa_win_wmme.h"
#define NUM_SECONDS (12)
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (64)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (100)
#define CHANNEL_COUNT (6)
typedef struct
{
float sine[TABLE_SIZE];
int phase;
int currentChannel;
int cycleCount;
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned long i,j;
(void) timeInfo; /* Prevent unused variable warnings. */
(void) statusFlags;
(void) inputBuffer;
for( i=0; i<framesPerBuffer; i++ )
{
for( j = 0; j < CHANNEL_COUNT; ++j ){
if( j == data->currentChannel && data->cycleCount < 4410 ){
*out++ = data->sine[data->phase];
data->phase += 1 + j; // play each channel at a different pitch so they can be distinguished
if( data->phase >= TABLE_SIZE ){
data->phase -= TABLE_SIZE;
}
}else{
*out++ = 0;
}
}
data->cycleCount++;
if( data->cycleCount > 44100 ){
data->cycleCount = 0;
++data->currentChannel;
if( data->currentChannel >= CHANNEL_COUNT )
data->currentChannel -= CHANNEL_COUNT;
}
}
return paContinue;
}
/*******************************************************************/
int main(int argc, char* argv[])
{
PaStreamParameters outputParameters;
PaWinMmeStreamInfo wmmeStreamInfo;
PaStream *stream;
PaError err;
paTestData data;
int i;
int deviceIndex;
printf("PortAudio Test: output a sine blip on each channel. SR = %d, BufSize = %d, Chans = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER, CHANNEL_COUNT);
err = Pa_Initialize();
if( err != paNoError ) goto error;
deviceIndex = Pa_GetHostApiInfo( Pa_HostApiTypeIdToHostApiIndex( paMME ) )->defaultOutputDevice;
if( argc == 2 ){
sscanf( argv[1], "%d", &deviceIndex );
}
printf( "using device id %d (%s)\n", deviceIndex, Pa_GetDeviceInfo(deviceIndex)->name );
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
data.phase = 0;
data.currentChannel = 0;
data.cycleCount = 0;
outputParameters.device = deviceIndex;
outputParameters.channelCount = CHANNEL_COUNT;
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point processing */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
/* it's not strictly necessary to provide a channelMask for surround sound
output. But if you want to be sure which channel mask PortAudio will use
then you should supply one */
wmmeStreamInfo.size = sizeof(PaWinMmeStreamInfo);
wmmeStreamInfo.hostApiType = paMME;
wmmeStreamInfo.version = 1;
wmmeStreamInfo.flags = paWinMmeUseChannelMask;
wmmeStreamInfo.channelMask = PAWIN_SPEAKER_5POINT1; /* request 5.1 output format */
outputParameters.hostApiSpecificStreamInfo = &wmmeStreamInfo;
if( Pa_IsFormatSupported( 0, &outputParameters, SAMPLE_RATE ) == paFormatIsSupported ){
printf( "Pa_IsFormatSupported reports device will support %d channels.\n", CHANNEL_COUNT );
}else{
printf( "Pa_IsFormatSupported reports device will not support %d channels.\n", CHANNEL_COUNT );
}
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Play for %d seconds.\n", NUM_SECONDS );
Pa_Sleep( NUM_SECONDS * 1000 );
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occured while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}