if( err != paNoError ) goto error;
printf("Hit ENTER to stop sound.\n");
+ fflush(stdout);
getchar();
err = Pa_StopStream( stream );
#define SLEEP_DUR (800)
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (256)
-#if 1
+#if 0
#define MIN_LATENCY_MSEC (200)
#define NUM_BUFFERS ((MIN_LATENCY_MSEC * SAMPLE_RATE) / (FRAMES_PER_BUFFER * 1000))
#else
QaCallback,
&myData )
) == paInvalidFlag) );
+
+#if 0 /* FIXME - this is legal for some implementations. */
+ HOPEFOR( ( /* Use input device as output device. */
+ (result = Pa_OpenStream(
+ &stream,
+ paNoDevice, 0, paFloat32, NULL,
+ Pa_GetDefaultInputDeviceID(), 2, paFloat32, NULL,
+ SAMPLE_RATE, FRAMES_PER_BUFFER, NUM_BUFFERS,
+ paClipOff,
+ QaCallback,
+ &myData )
+ ) == paInvalidDeviceId) );
+
+ HOPEFOR( ( /* Use output device as input device. */
+ (result = Pa_OpenStream(
+ &stream,
+ Pa_GetDefaultOutputDeviceID(), 2, paFloat32, NULL,
+ paNoDevice, 0, paFloat32, NULL,
+ SAMPLE_RATE, FRAMES_PER_BUFFER, NUM_BUFFERS,
+ paClipOff,
+ QaCallback,
+ &myData )
+ ) == paInvalidDeviceId) );
+#endif
+
if( stream != NULL ) Pa_CloseStream( stream );
return result;
}
* $Id$
* patest_dither.c
* Attempt to hear difference between dithered and non-dithered signal.
+ * This only has an effect if the native format is 16 bit.
*
* Author: Phil Burk http://www.softsynth.com
*
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
- data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
+ data.sine[i] = 0.90f * (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
data.sine[TABLE_SIZE] = data.sine[0]; // set guard point
data.left_phase = data.right_phase = 0.0;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Play ASCII keyboard. Hit 'q' to stop. (Use RETURN key on Mac)\n");
+ fflush(stdout);
while ( !done )
{
float freq;
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
+ float outSample;
unsigned long i;
int j;
int finished = 0;
data->phases[j] = phase;
}
-
- *out++ = (float) (output / data->numSines);
+ outSample = (float) (output / data->numSines);
+ *out++ = outSample; /* Left */
+ *out++ = outSample; /* Right */
}
return finished;
}
if( err != paNoError ) goto error;
err = Pa_OpenStream(
&stream,
- paNoDevice,/* default input device */
+ paNoDevice,
0, /* no input */
- paFloat32, /* 32 bit floating point input */
+ paFloat32,
NULL,
Pa_GetDefaultOutputDeviceID(), /* default output device */
- 1, /* mono output */
+ 2, /* stereo output */
paFloat32, /* 32 bit floating point output */
NULL,
SAMPLE_RATE,
- FRAMES_PER_BUFFER, /* frames per buffer */
+ FRAMES_PER_BUFFER,
0, /* number of buffers, if zero then use default minimum */
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
load = Pa_GetCPULoad( stream );
printf("numSines = %d, CPU load = %f\n", data.numSines, load );
+ fflush( stdout );
}
- while( load < 0.8 );
+ while( (load < 0.8) && (data.numSines < MAX_SINES) );
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
/* #define SAMPLE_RATE (17932) /* Test failure to open with this value. */
#define SAMPLE_RATE (44100)
#define NUM_SECONDS (5)
+#define NUM_CHANNELS (2)
+/* #define DITHER_FLAG (paDitherOff) /**/
+#define DITHER_FLAG (0) /**/
/* Select sample format. */
#if 0
#define PA_SAMPLE_TYPE paFloat32
typedef float SAMPLE;
+#define SAMPLE_SILENCE (0.0f)
#elif 0
#define PA_SAMPLE_TYPE paInt16
typedef short SAMPLE;
+#define SAMPLE_SILENCE (0)
+#elif 0
+#define PA_SAMPLE_TYPE paInt8
+typedef char SAMPLE;
+#define SAMPLE_SILENCE (0)
#else
#define PA_SAMPLE_TYPE paUInt8
typedef unsigned char SAMPLE;
+#define SAMPLE_SILENCE (128)
+
#endif
typedef struct
{
int frameIndex; /* Index into sample array. */
int maxFrameIndex;
- int samplesPerFrame;
SAMPLE *recordedSamples;
}
paTestData;
{
paTestData *data = (paTestData*)userData;
SAMPLE *rptr = (SAMPLE*)inputBuffer;
- SAMPLE *wptr = &data->recordedSamples[data->frameIndex * data->samplesPerFrame];
+ SAMPLE *wptr = &data->recordedSamples[data->frameIndex * NUM_CHANNELS];
long framesToCalc;
long i;
int finished;
{
for( i=0; i<framesToCalc; i++ )
{
- *wptr++ = 0; /* left */
- *wptr++ = 0; /* right */
+ *wptr++ = SAMPLE_SILENCE; /* left */
+ if( NUM_CHANNELS == 2 ) *wptr++ = SAMPLE_SILENCE; /* right */
}
}
else
for( i=0; i<framesToCalc; i++ )
{
*wptr++ = *rptr++; /* left */
- *wptr++ = *rptr++; /* right */
+ if( NUM_CHANNELS == 2 ) *wptr++ = *rptr++; /* right */
}
}
data->frameIndex += framesToCalc;
PaTimestamp outTime, void *userData )
{
paTestData *data = (paTestData*)userData;
- SAMPLE *rptr = &data->recordedSamples[data->frameIndex * data->samplesPerFrame];
+ SAMPLE *rptr = &data->recordedSamples[data->frameIndex * NUM_CHANNELS];
SAMPLE *wptr = (SAMPLE*)outputBuffer;
unsigned int i;
int finished;
for( i=0; i<framesLeft; i++ )
{
*wptr++ = *rptr++; /* left */
- *wptr++ = *rptr++; /* right */
+ if( NUM_CHANNELS == 2 ) *wptr++ = *rptr++; /* right */
}
for( ; i<framesPerBuffer; i++ )
{
*wptr++ = 0; /* left */
- *wptr++ = 0; /* right */
+ if( NUM_CHANNELS == 2 ) *wptr++ = 0; /* right */
}
data->frameIndex += framesLeft;
finished = 1;
for( i=0; i<framesPerBuffer; i++ )
{
*wptr++ = *rptr++; /* left */
- *wptr++ = *rptr++; /* right */
+ if( NUM_CHANNELS == 2 ) *wptr++ = *rptr++; /* right */
}
data->frameIndex += framesPerBuffer;
finished = 0;
data.maxFrameIndex = totalFrames = NUM_SECONDS * SAMPLE_RATE; /* Record for a few seconds. */
data.frameIndex = 0;
- data.samplesPerFrame = 2;
- numSamples = totalFrames * data.samplesPerFrame;
+ numSamples = totalFrames * NUM_CHANNELS;
numBytes = numSamples * sizeof(SAMPLE);
data.recordedSamples = (SAMPLE *) malloc( numBytes );
err = Pa_OpenStream(
&stream,
Pa_GetDefaultInputDeviceID(),
- data.samplesPerFrame, /* stereo input */
+ NUM_CHANNELS, /* stereo input */
PA_SAMPLE_TYPE,
NULL,
paNoDevice,
SAMPLE_RATE,
1024, /* frames per buffer */
0, /* number of buffers, if zero then use default minimum */
- paClipOff, /* we won't output out of range samples so don't bother clipping them */
+ 0, //paDitherOff, /* flags */
recordCallback,
&data );
if( err != paNoError ) goto error;
}
average += val;
}
- printf("sample max amplitude = %d\n", max );
+
average = average / numSamples;
- printf("sample average = %d\n", average );
+ if( PA_SAMPLE_TYPE == paFloat32 )
+ {
+ printf("sample max amplitude = %f\n", max );
+ printf("sample average = %f\n", average );
+ }
+ else
+ {
+ printf("sample max amplitude = %d\n", max );
+ printf("sample average = %d\n", average );
+ }
+
/* Write recorded data to a file. */
#if 0
{
}
else
{
- fwrite( data.recordedSamples, data.samplesPerFrame * sizeof(SAMPLE), totalFrames, fid );
+ fwrite( data.recordedSamples, NUM_CHANNELS * sizeof(SAMPLE), totalFrames, fid );
fclose( fid );
printf("Wrote data to 'recorded.raw'\n");
}
PA_SAMPLE_TYPE,
NULL,
Pa_GetDefaultOutputDeviceID(),
- data.samplesPerFrame, /* stereo output */
+ NUM_CHANNELS, /* stereo output */
PA_SAMPLE_TYPE,
NULL,
SAMPLE_RATE,
#define NUM_SECONDS (20)
#define SAMPLE_RATE (44100)
-#define FRAMES_PER_BUFFER (256)
+#define FRAMES_PER_BUFFER (512)
#define LEFT_FREQ (SAMPLE_RATE/256.0) /* So we hit 1.0 */
#define RIGHT_FREQ (500.0)
#define AMPLITUDE (1.0)
#define SAMPLE_ZERO (0x80)
#define DOUBLE_TO_SAMPLE(x) (SAMPLE_ZERO + (SAMPLE_t)(127.0 * (x)))
#define FORMAT_NAME "Unsigned 8 Bit"
-#endif
-#if TEST_INT8
+#elif TEST_INT8
#define TEST_FORMAT paInt8
typedef char SAMPLE_t;
#define SAMPLE_ZERO (0)
#define DOUBLE_TO_SAMPLE(x) (SAMPLE_ZERO + (SAMPLE_t)(127.0 * (x)))
#define FORMAT_NAME "Signed 8 Bit"
-#endif
-#if TEST_INT16
+#elif TEST_INT16
#define TEST_FORMAT paInt16
typedef short SAMPLE_t;
#define SAMPLE_ZERO (0)
-#define DOUBLE_TO_SAMPLE(x) (SAMPLE_ZERO + (SAMPLE_t)(32767.0 * (x)))
+#define DOUBLE_TO_SAMPLE(x) (SAMPLE_ZERO + (SAMPLE_t)(32767 * (x)))
#define FORMAT_NAME "Signed 16 Bit"
-#endif
-#if TEST_FLOAT32
+#elif TEST_FLOAT32
#define TEST_FORMAT paFloat32
typedef float SAMPLE_t;
#define SAMPLE_ZERO (0.0)
#define NUM_SECONDS (8)
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (64)
+#define NUM_BUFFERS (0)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (200)
typedef struct
{
- float sine[TABLE_SIZE];
- int left_phase;
- int right_phase;
- int framesToGo;
+ float sine[TABLE_SIZE];
+ int left_phase;
+ int right_phase;
+ int framesToGo;
+ volatile PaTimestamp outTime;
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
(void) outTime; /* Prevent unused variable warnings. */
(void) inputBuffer;
+ data->outTime = outTime;
+
if( data->framesToGo < framesPerBuffer )
{
framesToCalc = data->framesToGo;
}
return finished;
}
+/*******************************************************************/
+static void ReportStreamTime( PortAudioStream *stream, paTestData *data );
+static void ReportStreamTime( PortAudioStream *stream, paTestData *data )
+{
+ PaTimestamp streamTime, latency, outTime;
+
+ streamTime = Pa_StreamTime( stream );
+ outTime = data->outTime;
+ if( outTime < 0.0 )
+ {
+ printf("Stream time = %8.1f\n", streamTime );
+ }
+ else
+ {
+ latency = outTime - streamTime;
+ printf("Stream time = %8.1f, outTime = %8.1f, latency = %8.1f\n",
+ streamTime, outTime, latency );
+ }
+ fflush(stdout);
+}
+
/*******************************************************************/
int main(void);
int main(void)
{
PortAudioStream *stream;
PaError err;
- paTestData data;
+ paTestData DATA;
int i;
int totalSamps;
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
- data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
+ DATA.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
- data.left_phase = data.right_phase = 0;
- data.framesToGo = totalSamps = NUM_SECONDS * SAMPLE_RATE; /* Play for a few seconds. */
+ DATA.left_phase = DATA.right_phase = 0;
+ DATA.framesToGo = totalSamps = NUM_SECONDS * SAMPLE_RATE; /* Play for a few seconds. */
err = Pa_Initialize();
if( err != paNoError ) goto error;
err = Pa_OpenStream(
NULL,
SAMPLE_RATE,
FRAMES_PER_BUFFER, /* frames per buffer */
- 0, /* number of buffers, if zero then use default minimum */
+ NUM_BUFFERS, /* number of buffers, if zero then use default minimum */
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
- &data );
+ &DATA );
if( err != paNoError ) goto error;
+
+ DATA.outTime = -1.0; // mark time for callback as undefined
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
+
/* Watch until sound is halfway finished. */
printf("Play for %d seconds.\n", NUM_SECONDS/2 ); fflush(stdout);
- while( Pa_StreamTime( stream ) < (totalSamps/2) ) Pa_Sleep(10);
+ do
+ {
+ ReportStreamTime( stream, &DATA );
+ Pa_Sleep(100);
+ } while( Pa_StreamTime( stream ) < (totalSamps/2) );
+
/* Stop sound until ENTER hit. */
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
printf("Pause for 2 seconds.\n"); fflush(stdout);
Pa_Sleep( 2000 );
+ DATA.outTime = -1.0; // mark time for callback as undefined
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
+
printf("Play until sound is finished.\n"); fflush(stdout);
- while( Pa_StreamActive( stream ) ) Pa_Sleep(10);
+ do
+ {
+ ReportStreamTime( stream, &DATA );
+ Pa_Sleep(100);
+ } while( Pa_StreamActive( stream ) );
+
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();