Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <math.h>
- #include "portaudio.h"
- #include "pa_asio.h"
- #include <sndfile.h>
- #include <stdlib.h>
- #define NUM_SECONDS (2)
- #define SAMPLE_RATE (48000)
- #define FRAMES_PER_BUFFER (64)
- #define OUTPUT_DEVICE Pa_GetDefaultOutputDevice()
- typedef struct
- {
- short* data;
- unsigned long cursor;
- unsigned long num_frames;
- }
- 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 )
- {
- //convert the pointers to the correct data type
- paTestData* data_struct = (paTestData*)userData;
- short* out = (short*)outputBuffer;
- unsigned long i;
- int finished = 0;
- //avoid unused variable warnings
- (void) inputBuffer;
- (void) timeInfo;
- (void) statusFlags;
- //copy data into output buffer
- for( i=0; i<framesPerBuffer; i++ )
- {
- if(data_struct->cursor < data_struct->num_frames)
- {
- out[i] = data_struct->data[data_struct->cursor]; //TODO: is this correct?
- data_struct->cursor++;
- }
- else
- {
- out[i] = 0; // if you've used up all the data, just fill the rest with silence.
- finished = paComplete; // this tells portaudio not to call the callback function anymore?
- }
- }
- return finished;
- }
- // we're going to read the data from filename (which should be a .wav file) into the "data" buffer
- paTestData* read_wav(char* filename)
- {
- //filename should contain the path to the .wav file.
- //For now, let's assume that the file contains 1-channel, 16-bit audio data, sampled at 48000Hz.
- //This function allocates a struct containing an array of shorts for the audio data, and then returns a pointer to it.
- SF_INFO my_sf_info;
- my_sf_info.format = 0;
- SNDFILE* my_sndfile = sf_open(filename, SFM_READ, &my_sf_info);
- if (NULL == my_sndfile)
- {
- printf(sf_strerror(my_sndfile));
- }
- paTestData* data_struct = (paTestData*)malloc(sizeof(paTestData)); // TODO: is this correct?
- data_struct->data = (short*)malloc(my_sf_info.frames * my_sf_info.channels * sizeof(short)); // TODO: is this correct?
- sf_count_t num_frames_read = sf_readf_short(my_sndfile, data_struct->data, my_sf_info.frames); // request all the frames
- sf_close(my_sndfile);
- data_struct->cursor = 0;
- data_struct->num_frames = (unsigned long)num_frames_read;
- return data_struct;
- }
- /*******************************************************************/
- int main(void);
- int main(void)
- {
- PaStreamParameters outputParameters;
- PaAsioStreamInfo asioOutputInfo;
- PaStream *stream;
- PaError err;
- int outputChannelSelectors[1];
- paTestData* data_struct = read_wav("mid_up_cos.wav");
- err = Pa_Initialize();
- if( err != paNoError ) goto error;
- //const PaDeviceInfo* deviceInfo = Pa_GetDeviceInfo(OUTPUT_DEVICE);
- //const PaHostApiInfo* hostInfo = Pa_GetHostApiInfo(deviceInfo->hostApi);
- //printf("default output device hostapiinfo: %s\n" , hostInfo->name); //this would print "ASIO".
- outputParameters.device = OUTPUT_DEVICE;
- outputParameters.channelCount = 1; // MONO output
- outputParameters.sampleFormat = paInt16; // 16 bit signed integer output
- outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
- // Use an ASIO specific structure. WARNING - this is not portable.
- asioOutputInfo.size = sizeof(PaAsioStreamInfo);
- asioOutputInfo.hostApiType = paASIO;
- asioOutputInfo.version = 1;
- asioOutputInfo.flags = paAsioUseChannelSelectors;
- outputChannelSelectors[0] = 1; // skip channel 0 and use the second (right) ASIO device channel
- asioOutputInfo.channelSelectors = outputChannelSelectors;
- outputParameters.hostApiSpecificStreamInfo = &asioOutputInfo;
- //err = Pa_IsFormatSupported(NULL, &outputParameters, SAMPLE_RATE);
- //if( err == paFormatIsSupported )
- //{
- // printf("this format is supported.\n"); // this works.
- //}
- err = Pa_OpenStream(
- &stream,
- NULL,
- &outputParameters,
- SAMPLE_RATE,
- FRAMES_PER_BUFFER,
- paClipOff, // we won't output out of range samples so don't bother clipping them
- patestCallback,
- data_struct );
- if( err != paNoError ) goto error;
- err = Pa_StartStream( stream );
- if( err != paNoError ) goto error;
- printf("Play for %d seconds.\n", NUM_SECONDS ); fflush(stdout);
- 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_struct->data); // TODO: is this correct?
- free(data_struct); // TODO: is this correct?
- printf("Test finished.\n");
- return err;
- error:
- Pa_Terminate();
- free(data_struct->data); // TODO: is this correct?
- free(data_struct); // TODO: is this correct?
- 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;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement