Advertisement
Guest User

libsndfile_portaudio_asio.cpp

a guest
Feb 7th, 2012
298
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <stdio.h>
  2. #include <math.h>
  3. #include "portaudio.h"
  4. #include "pa_asio.h"
  5. #include <sndfile.h>
  6. #include <stdlib.h>
  7.  
  8. #define NUM_SECONDS   (2)
  9. #define SAMPLE_RATE   (48000)
  10. #define FRAMES_PER_BUFFER  (64)
  11. #define OUTPUT_DEVICE Pa_GetDefaultOutputDevice()
  12.  
  13. typedef struct
  14. {
  15.     short* data;
  16.     unsigned long cursor;
  17.     unsigned long num_frames;
  18. }
  19. paTestData;
  20.  
  21. /* This routine will be called by the PortAudio engine when audio is needed.
  22. ** It may called at interrupt level on some machines so don't do anything
  23. ** that could mess up the system like calling malloc() or free().
  24. */
  25. static int patestCallback( const void *inputBuffer, void *outputBuffer,
  26.                             unsigned long framesPerBuffer,
  27.                             const PaStreamCallbackTimeInfo* timeInfo,
  28.                             PaStreamCallbackFlags statusFlags,
  29.                             void *userData )
  30. {
  31.     //convert the pointers to the correct data type
  32.     paTestData* data_struct = (paTestData*)userData;
  33.     short* out = (short*)outputBuffer;
  34.     unsigned long i;
  35.     int finished = 0;
  36.    
  37.     //avoid unused variable warnings
  38.     (void) inputBuffer;
  39.     (void) timeInfo;
  40.     (void) statusFlags;
  41.  
  42.     //copy data into output buffer
  43.    
  44.     for( i=0; i<framesPerBuffer; i++ )
  45.     {
  46.         if(data_struct->cursor < data_struct->num_frames)
  47.         {
  48.             out[i] = data_struct->data[data_struct->cursor]; //TODO: is this correct?
  49.             data_struct->cursor++;
  50.         }
  51.         else
  52.         {
  53.             out[i] = 0; // if you've used up all the data, just fill the rest with silence.
  54.             finished = paComplete; // this tells portaudio not to call the callback function anymore?
  55.         }
  56.     }
  57.    
  58.     return finished;
  59. }
  60.  
  61. // we're going to read the data from filename (which should be a .wav file) into the "data" buffer
  62. paTestData* read_wav(char* filename)
  63. {
  64.     //filename should contain the path to the .wav file.
  65.     //For now, let's assume that the file contains 1-channel, 16-bit audio data, sampled at 48000Hz.
  66.     //This function allocates a struct containing an array of shorts for the audio data, and then returns a pointer to it.
  67.    
  68.     SF_INFO my_sf_info;
  69.     my_sf_info.format = 0;
  70.     SNDFILE* my_sndfile = sf_open(filename, SFM_READ, &my_sf_info);
  71.  
  72.     if (NULL == my_sndfile)
  73.     {
  74.         printf(sf_strerror(my_sndfile));
  75.     }
  76.    
  77.     paTestData* data_struct = (paTestData*)malloc(sizeof(paTestData)); // TODO: is this correct?
  78.     data_struct->data = (short*)malloc(my_sf_info.frames * my_sf_info.channels * sizeof(short)); // TODO: is this correct?
  79.  
  80.     sf_count_t num_frames_read = sf_readf_short(my_sndfile, data_struct->data, my_sf_info.frames); // request all the frames
  81.  
  82.     sf_close(my_sndfile);
  83.  
  84.     data_struct->cursor = 0;
  85.     data_struct->num_frames = (unsigned long)num_frames_read;
  86.    
  87.     return data_struct;
  88. }
  89.  
  90. /*******************************************************************/
  91. int main(void);
  92. int main(void)
  93. {
  94.     PaStreamParameters outputParameters;
  95.     PaAsioStreamInfo asioOutputInfo;
  96.     PaStream *stream;
  97.     PaError err;
  98.  
  99.     int outputChannelSelectors[1];
  100.    
  101.     paTestData* data_struct = read_wav("mid_up_cos.wav");
  102.    
  103.     err = Pa_Initialize();
  104.     if( err != paNoError ) goto error;
  105.    
  106.     //const PaDeviceInfo* deviceInfo = Pa_GetDeviceInfo(OUTPUT_DEVICE);
  107.     //const PaHostApiInfo* hostInfo = Pa_GetHostApiInfo(deviceInfo->hostApi);
  108.     //printf("default output device hostapiinfo: %s\n" , hostInfo->name); //this would print "ASIO".
  109.  
  110.     outputParameters.device = OUTPUT_DEVICE;
  111.     outputParameters.channelCount = 1; // MONO output
  112.     outputParameters.sampleFormat = paInt16; // 16 bit signed integer output
  113.     outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
  114.  
  115.     // Use an ASIO specific structure. WARNING - this is not portable.
  116.     asioOutputInfo.size = sizeof(PaAsioStreamInfo);
  117.     asioOutputInfo.hostApiType = paASIO;
  118.     asioOutputInfo.version = 1;
  119.     asioOutputInfo.flags = paAsioUseChannelSelectors;
  120.     outputChannelSelectors[0] = 1; // skip channel 0 and use the second (right) ASIO device channel
  121.     asioOutputInfo.channelSelectors = outputChannelSelectors;
  122.     outputParameters.hostApiSpecificStreamInfo = &asioOutputInfo;
  123.  
  124.     //err = Pa_IsFormatSupported(NULL, &outputParameters, SAMPLE_RATE);
  125.     //if( err == paFormatIsSupported )
  126.     //{
  127.     //    printf("this format is supported.\n"); // this works.
  128.     //}
  129.  
  130.     err = Pa_OpenStream(
  131.               &stream,
  132.               NULL,
  133.               &outputParameters,
  134.               SAMPLE_RATE,
  135.               FRAMES_PER_BUFFER,
  136.               paClipOff, // we won't output out of range samples so don't bother clipping them
  137.               patestCallback,
  138.               data_struct );
  139.     if( err != paNoError ) goto error;
  140.  
  141.     err = Pa_StartStream( stream );
  142.     if( err != paNoError ) goto error;
  143.    
  144.     printf("Play for %d seconds.\n", NUM_SECONDS ); fflush(stdout);
  145.     Pa_Sleep( NUM_SECONDS * 1000 );
  146.  
  147.     err = Pa_StopStream( stream );
  148.     if( err != paNoError ) goto error;
  149.    
  150.     err = Pa_CloseStream( stream );
  151.     if( err != paNoError ) goto error;
  152.    
  153.     Pa_Terminate();
  154.     free(data_struct->data); // TODO: is this correct?
  155.     free(data_struct); // TODO: is this correct?
  156.     printf("Test finished.\n");
  157.     return err;
  158.  
  159. error:
  160.     Pa_Terminate();
  161.     free(data_struct->data); // TODO: is this correct?
  162.     free(data_struct); // TODO: is this correct?
  163.     fprintf( stderr, "An error occured while using the portaudio stream\n" );
  164.     fprintf( stderr, "Error number: %d\n", err );
  165.     fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
  166.     return err;
  167. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement