/[svn]/linuxsampler/trunk/src/audioio.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/audioio.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 30 by schoenebeck, Fri Jan 2 00:02:56 2004 UTC revision 31 by schoenebeck, Sun Jan 18 20:31:31 2004 UTC
# Line 23  Line 23 
23  #include "audioio.h"  #include "audioio.h"
24    
25  AudioIO::AudioIO() {  AudioIO::AudioIO() {
26      pcm_handle    = NULL;      bInitialized = false;
27      pOutputBuffer = NULL;      pEngine     = NULL;
     Initialized   = false;  
     stream        = SND_PCM_STREAM_PLAYBACK;  
28  }  }
29    
30  AudioIO::~AudioIO() {  AudioIO::~AudioIO() {
31      Close();      //this->Close();
 }  
   
 int AudioIO::Initialize(uint channels, uint samplerate, uint numfragments, uint fragmentsize) {  
     this->Channels     = channels;  
     this->Samplerate   = samplerate;  
     this->Fragments    = numfragments;  
     this->FragmentSize = fragmentsize;  
   
     if (HardwareParametersSupported(channels, samplerate, numfragments, fragmentsize)) {  
         pcm_name = "hw:0,0";  
     }  
     else {  
         printf("Warning: your soundcard doesn't support chosen hardware parameters; ");  
         printf("trying to compensate support lack with plughw...");  
         fflush(stdout);  
         pcm_name = "plughw:0,0";  
     }  
   
     int err;  
   
     snd_pcm_hw_params_alloca(&hwparams);  // Allocate the snd_pcm_hw_params_t structure on the stack.  
   
     /* Open PCM. The last parameter of this function is the mode. */  
     /* If this is set to 0, the standard mode is used. Possible   */  
     /* other values are SND_PCM_NONBLOCK and SND_PCM_ASYNC.       */  
     /* If SND_PCM_NONBLOCK is used, read / write access to the    */  
     /* PCM device will return immediately. If SND_PCM_ASYNC is    */  
     /* specified, SIGIO will be emitted whenever a period has     */  
     /* been completely processed by the soundcard.                */  
     if ((err = snd_pcm_open(&pcm_handle, pcm_name.c_str(), stream, 0)) < 0) {  
         fprintf(stderr, "Error opening PCM device %s: %s\n", pcm_name.c_str(), snd_strerror(err));  
         return EXIT_FAILURE;  
     }  
   
     if ((err = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) {  
         fprintf(stderr, "Error, cannot initialize hardware parameter structure: %s.\n", snd_strerror(err));  
         return EXIT_FAILURE;  
     }  
   
     /* Set access type. This can be either    */  
     /* SND_PCM_ACCESS_RW_INTERLEAVED or       */  
     /* SND_PCM_ACCESS_RW_NONINTERLEAVED.      */  
     if ((err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {  
         fprintf(stderr, "Error snd_pcm_hw_params_set_access: %s.\n", snd_strerror(err));  
         return EXIT_FAILURE;  
     }  
   
     /* Set sample format */  
     #if WORDS_BIGENDIAN  
     if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_BE)) < 0) {  
     #else // little endian  
     if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE)) < 0) {  
     #endif  
         fprintf(stderr, "Error setting sample format. : %s\n", snd_strerror(err));  
         return EXIT_FAILURE;  
     }  
   
     int dir = 0;  
   
     /* Set sample rate. If the exact rate is not supported */  
     /* by the hardware, use nearest possible rate.         */  
     #if ALSA_MAJOR > 0  
     if((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &samplerate, &dir)) < 0) {  
     #else  
     if((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, samplerate, &dir)) < 0) {  
     #endif  
         fprintf(stderr, "Error setting sample rate. : %s\n", snd_strerror(err));  
         return EXIT_FAILURE;  
     }  
   
     if ((err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, channels)) < 0) {  
         fprintf(stderr, "Error setting number of channels. : %s\n", snd_strerror(err));  
         return EXIT_FAILURE;  
     }  
   
     /* Set number of periods. Periods used to be called fragments. */  
     if ((err = snd_pcm_hw_params_set_periods(pcm_handle, hwparams, numfragments, dir)) < 0) {  
         fprintf(stderr, "Error setting number of periods. : %s\n", snd_strerror(err));  
         return EXIT_FAILURE;  
     }  
   
     /* Set buffer size (in frames). The resulting latency is given by */  
     /* latency = periodsize * periods / (rate * bytes_per_frame)     */  
     if ((err = snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, (fragmentsize * numfragments))) < 0) {  
         fprintf(stderr, "Error setting buffersize. : %s\n", snd_strerror(err));  
         return EXIT_FAILURE;  
     }  
   
     /* Apply HW parameter settings to */  
     /* PCM device and prepare device  */  
     if ((err = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {  
         fprintf(stderr, "Error setting HW params. : %s\n", snd_strerror(err));  
         return EXIT_FAILURE;  
     }  
   
     if (snd_pcm_sw_params_malloc(&swparams) != 0) {  
         fprintf(stderr, "Error in snd_pcm_sw_params_malloc. : %s\n", snd_strerror(err));  
         return EXIT_FAILURE;  
     }  
   
     if (snd_pcm_sw_params_current(pcm_handle, swparams) != 0) {  
         fprintf(stderr, "Error in snd_pcm_sw_params_current. : %s\n", snd_strerror(err));  
         return EXIT_FAILURE;  
     }  
   
     if (snd_pcm_sw_params_set_stop_threshold(pcm_handle, swparams, 0xffffffff) != 0) {  
         fprintf(stderr, "Error in snd_pcm_sw_params_set_stop_threshold. : %s\n", snd_strerror(err));  
         return EXIT_FAILURE;  
     }  
   
     if (snd_pcm_sw_params(pcm_handle, swparams) != 0) {  
         fprintf(stderr, "Error in snd_pcm_sw_params. : %s\n", snd_strerror(err));  
         return EXIT_FAILURE;  
     }  
   
     if ((err = snd_pcm_prepare(pcm_handle)) < 0) {  
         fprintf(stderr, "Error snd_pcm_prepare : %s\n", snd_strerror(err));  
         return EXIT_FAILURE;  
     }  
   
     // allocate the audio output buffer  
     pOutputBuffer = new int16_t[channels * fragmentsize];  
       
     this->Initialized = true;  
   
     return EXIT_SUCCESS;  
 }  
   
 /**  
  *  Checks if sound card supports the chosen parameters.  
  *  
  *  @returns  true if hardware supports it  
  */  
 bool AudioIO::HardwareParametersSupported(uint channels, int samplerate, uint numfragments, uint fragmentsize) {  
     pcm_name = "hw:0,0";  
     if (snd_pcm_open(&pcm_handle, pcm_name.c_str(), stream, 0) < 0) return false;  
     snd_pcm_hw_params_alloca(&hwparams);  
     if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) {  
         snd_pcm_close(pcm_handle);  
         return false;  
     }  
     if (snd_pcm_hw_params_test_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {  
         snd_pcm_close(pcm_handle);  
         return false;  
     }  
     #if WORDS_BIGENDIAN  
     if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_BE) < 0) {  
     #else // little endian  
     if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0) {  
     #endif  
         snd_pcm_close(pcm_handle);  
         return false;  
     }  
     int dir = 0;  
     if (snd_pcm_hw_params_test_rate(pcm_handle, hwparams, samplerate, dir) < 0) {  
         snd_pcm_close(pcm_handle);  
         return false;  
     }  
     if (snd_pcm_hw_params_test_channels(pcm_handle, hwparams, channels) < 0) {  
         snd_pcm_close(pcm_handle);  
         return false;  
     }  
     if (snd_pcm_hw_params_test_periods(pcm_handle, hwparams, numfragments, dir) < 0) {  
         snd_pcm_close(pcm_handle);  
         return false;  
     }  
     if (snd_pcm_hw_params_test_buffer_size(pcm_handle, hwparams, (fragmentsize * numfragments)) < 0) {  
         snd_pcm_close(pcm_handle);  
         return false;  
     }  
   
     snd_pcm_close(pcm_handle);  
     return true;  
 }  
   
 /**  
  *  Will be called by the audio engine after every audio fragment cycle, to  
  *  output the audio data of the current fragment to the soundcard.  
  *  
  *  @returns  0 on success  
  */  
 int AudioIO::Output() {  
     int err = snd_pcm_writei(pcm_handle, pOutputBuffer, FragmentSize);  
     if (err < 0) {  
         fprintf(stderr, "Error snd_pcm_writei failed. : %s\n", snd_strerror(err));  
         return EXIT_FAILURE;  
     }  
     return EXIT_SUCCESS;  
 }  
   
 void AudioIO::Close(void) {  
     if (Initialized) {  
         if (pcm_handle) {  
             //FIXME: currently commented out due to segfault  
             //snd_pcm_close(pcm_handle);  
             pcm_handle = NULL;  
         }  
         if (pOutputBuffer) {  
             //FIXME: currently commented out due to segfault  
             //delete[] pOutputBuffer;  
             pOutputBuffer = NULL;  
         }  
         Initialized = false;  
     }  
32  }  }

Legend:
Removed from v.30  
changed lines
  Added in v.31

  ViewVC Help
Powered by ViewVC