/* * tune.c * * Generate a sine wave * in an ascending chromatic scale * * Author: Christopher Dobrian * * This program uses the PortAudio Portable Audio Library. * For more information see: http://www.portaudio.com * */ #include #include #include "portaudio.h" #define SAMPLE_RATE (44100.) #define BUFFER_SIZE (256) #define TWOPI (6.283185307179586) #define BASE_FREQ (440.) #define MAX_AMP (0.5) #define NUM_NOTES (13) typedef struct { float amplitude; float frequency; float phase; unsigned long count; } paAudioData; /* This routine will be called by the PortAudio engine when audio is needed. */ static int cosineCallback( void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, PaTimestamp outTime, void *userData ); static int cosineCallback( void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, PaTimestamp outTime, void *userData ) { /* Cast data passed through stream to the format of the local structure. */ paAudioData *data = (paAudioData*)userData; // float *in = (float*)inputBuffer; // input buffer only needed for input float *out = (float*)outputBuffer; unsigned int i; // just a counter float A = data->amplitude; float twopiFoverR = TWOPI*data->frequency/SAMPLE_RATE; float phase = data->phase; float y; // temp variable for output sample for( i = 0 ; i < framesPerBuffer ; i++ ) { y = A*sin(twopiFoverR*(data->count++)+phase); *out++ = y; /* left channel */ *out++ = y; /* right channel*/ } return 0; } /*******************************************************************/ static paAudioData data; int main(void); int main(void) { PortAudioStream *stream; PaError err; int i; // counter of notes /* Initialize data for use by callback. */ data.amplitude = MAX_AMP; data.frequency = BASE_FREQ; data.phase = 0.; data.count = 0; /* Initialize library before making any other calls. */ err = Pa_Initialize(); if( err != paNoError ) goto error; /* Open an audio I/O stream. */ err = Pa_OpenDefaultStream( &stream, 0, /* no input channels */ 2, /* stereo output */ paFloat32, /* 32 bit floating point output */ SAMPLE_RATE, BUFFER_SIZE, /* frames per buffer */ 0, /* number of buffers, if zero then use default minimum */ cosineCallback, &data ); if( err != paNoError ) goto error; err = Pa_StartStream( stream ); if( err != paNoError ) goto error; fprintf( stdout, "Current time is %lf\n", Pa_StreamTime( stream ) ); /* Loop, and increase the frequency every second */ i = 0; while ( i <= NUM_NOTES ) { if ( (int)(data.count/SAMPLE_RATE) >= i ) { data.frequency = BASE_FREQ*pow(2., i/12.); // equal tempered semitones fprintf( stdout, "Current time is %lf\n", Pa_StreamTime( stream ) ); if (i < NUM_NOTES) { fprintf(stdout, "PortAudio: Sine Wave, %.2f Hz.\n", data.frequency); } i++; } } err = Pa_StopStream( stream ); if( err != paNoError ) goto error; err = Pa_CloseStream( stream ); if( err != paNoError ) goto error; Pa_Terminate(); printf("Calculated %ld samples.\n", data.count); printf("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; }