/[svn]/linuxsampler/tags/singlechannel/src/audioio.cpp
ViewVC logotype

Diff of /linuxsampler/tags/singlechannel/src/audioio.cpp

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

revision 9 by schoenebeck, Wed Nov 5 14:47:10 2003 UTC revision 28 by schoenebeck, Fri Jan 2 00:02:56 2004 UTC
# Line 25  Line 25 
25  AudioIO::AudioIO() {  AudioIO::AudioIO() {
26      pcm_handle    = NULL;      pcm_handle    = NULL;
27      pOutputBuffer = NULL;      pOutputBuffer = NULL;
28        Initialized   = false;
29        stream        = SND_PCM_STREAM_PLAYBACK;
30  }  }
31    
32  AudioIO::~AudioIO() {  AudioIO::~AudioIO() {
# Line 32  AudioIO::~AudioIO() { Line 34  AudioIO::~AudioIO() {
34  }  }
35    
36  int AudioIO::Initialize(uint channels, uint samplerate, uint numfragments, uint fragmentsize) {  int AudioIO::Initialize(uint channels, uint samplerate, uint numfragments, uint fragmentsize) {
37      this->Channels         = channels;      this->Channels     = channels;
38      this->Samplerate       = samplerate;      this->Samplerate   = samplerate;
39      this->Fragments        = numfragments;      this->Fragments    = numfragments;
40      this->FragmentSize     = fragmentsize;      this->FragmentSize = fragmentsize;
41    
42      /* Playback stream */      if (HardwareParametersSupported(channels, samplerate, numfragments, fragmentsize)) {
43      snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;          pcm_name = "hw:0,0";
44        }
45      /* This structure contains information about    */      else {
46      /* the hardware and can be used to specify the  */          printf("Warning: your soundcard doesn't support chosen hardware parameters; ");
47      /* configuration to be used for the PCM stream. */          printf("trying to compensate support lack with plughw...");
48      snd_pcm_hw_params_t* hwparams;          fflush(stdout);
49            pcm_name = "plughw:0,0";
50      snd_pcm_sw_params_t* swparams;      }
   
     /* Name of the PCM device, like plughw:0,0          */  
     /* The first number is the number of the soundcard, */  
     /* the second number is the number of the device.   */  
     char* pcm_name;  
   
     /* Init pcm_name. Of course, later you */  
51    
52      int err;      int err;
53    
54      pcm_name = strdup("hw:0,0");      snd_pcm_hw_params_alloca(&hwparams);  // Allocate the snd_pcm_hw_params_t structure on the stack.
   
     /* Allocate the snd_pcm_hw_params_t structure on the stack. */  
     snd_pcm_hw_params_alloca(&hwparams);  
55    
56      /* Open PCM. The last parameter of this function is the mode. */      /* Open PCM. The last parameter of this function is the mode. */
57      /* If this is set to 0, the standard mode is used. Possible   */      /* If this is set to 0, the standard mode is used. Possible   */
# Line 68  int AudioIO::Initialize(uint channels, u Line 60  int AudioIO::Initialize(uint channels, u
60      /* PCM device will return immediately. If SND_PCM_ASYNC is    */      /* PCM device will return immediately. If SND_PCM_ASYNC is    */
61      /* specified, SIGIO will be emitted whenever a period has     */      /* specified, SIGIO will be emitted whenever a period has     */
62      /* been completely processed by the soundcard.                */      /* been completely processed by the soundcard.                */
63      if ((err = snd_pcm_open(&pcm_handle, pcm_name, stream, 0)) < 0) {      if ((err = snd_pcm_open(&pcm_handle, pcm_name.c_str(), stream, 0)) < 0) {
64          fprintf(stderr, "Error opening PCM device %s: %s\n", pcm_name, snd_strerror(err));          fprintf(stderr, "Error opening PCM device %s: %s\n", pcm_name.c_str(), snd_strerror(err));
65          return EXIT_FAILURE;          return EXIT_FAILURE;
66      }      }
67    
# Line 87  int AudioIO::Initialize(uint channels, u Line 79  int AudioIO::Initialize(uint channels, u
79      }      }
80    
81      /* Set sample format */      /* Set sample format */
82        #if WORDS_BIGENDIAN
83        if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_BE)) < 0) {
84        #else // little endian
85      if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE)) < 0) {      if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE)) < 0) {
86        #endif
87          fprintf(stderr, "Error setting sample format. : %s\n", snd_strerror(err));          fprintf(stderr, "Error setting sample format. : %s\n", snd_strerror(err));
88          return EXIT_FAILURE;          return EXIT_FAILURE;
89      }      }
90    
91        int dir = 0;
92    
93      /* Set sample rate. If the exact rate is not supported */      /* Set sample rate. If the exact rate is not supported */
94      /* by the hardware, use nearest possible rate.         */      /* by the hardware, use nearest possible rate.         */
95      if((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, samplerate, 0)) < 0) {      #if ALSA_MAJOR > 0
96        if((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &samplerate, &dir)) < 0) {
97        #else
98        if((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, samplerate, &dir)) < 0) {
99        #endif
100          fprintf(stderr, "Error setting sample rate. : %s\n", snd_strerror(err));          fprintf(stderr, "Error setting sample rate. : %s\n", snd_strerror(err));
101          return EXIT_FAILURE;          return EXIT_FAILURE;
102      }      }
# Line 105  int AudioIO::Initialize(uint channels, u Line 107  int AudioIO::Initialize(uint channels, u
107      }      }
108    
109      /* Set number of periods. Periods used to be called fragments. */      /* Set number of periods. Periods used to be called fragments. */
110      if ((err = snd_pcm_hw_params_set_periods(pcm_handle, hwparams, numfragments, 0)) < 0) {      if ((err = snd_pcm_hw_params_set_periods(pcm_handle, hwparams, numfragments, dir)) < 0) {
111          fprintf(stderr, "Error setting number of periods. : %s\n", snd_strerror(err));          fprintf(stderr, "Error setting number of periods. : %s\n", snd_strerror(err));
112          return EXIT_FAILURE;          return EXIT_FAILURE;
113      }      }
# Line 151  int AudioIO::Initialize(uint channels, u Line 153  int AudioIO::Initialize(uint channels, u
153    
154      // allocate the audio output buffer      // allocate the audio output buffer
155      pOutputBuffer = new int16_t[channels * fragmentsize];      pOutputBuffer = new int16_t[channels * fragmentsize];
156        
157        this->Initialized = true;
158    
159      return EXIT_SUCCESS;      return EXIT_SUCCESS;
160  }  }
161    
162    /**
163     *  Checks if sound card supports the chosen parameters.
164     *
165     *  @returns  true if hardware supports it
166     */
167    bool AudioIO::HardwareParametersSupported(uint channels, int samplerate, uint numfragments, uint fragmentsize) {
168        pcm_name = "hw:0,0";
169        if (snd_pcm_open(&pcm_handle, pcm_name.c_str(), stream, 0) < 0) return false;
170        snd_pcm_hw_params_alloca(&hwparams);
171        if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) {
172            snd_pcm_close(pcm_handle);
173            return false;
174        }
175        if (snd_pcm_hw_params_test_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
176            snd_pcm_close(pcm_handle);
177            return false;
178        }
179        #if WORDS_BIGENDIAN
180        if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_BE) < 0) {
181        #else // little endian
182        if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0) {
183        #endif
184            snd_pcm_close(pcm_handle);
185            return false;
186        }
187        int dir = 0;
188        if (snd_pcm_hw_params_test_rate(pcm_handle, hwparams, samplerate, dir) < 0) {
189            snd_pcm_close(pcm_handle);
190            return false;
191        }
192        if (snd_pcm_hw_params_test_channels(pcm_handle, hwparams, channels) < 0) {
193            snd_pcm_close(pcm_handle);
194            return false;
195        }
196        if (snd_pcm_hw_params_test_periods(pcm_handle, hwparams, numfragments, dir) < 0) {
197            snd_pcm_close(pcm_handle);
198            return false;
199        }
200        if (snd_pcm_hw_params_test_buffer_size(pcm_handle, hwparams, (fragmentsize * numfragments)) < 0) {
201            snd_pcm_close(pcm_handle);
202            return false;
203        }
204    
205        snd_pcm_close(pcm_handle);
206        return true;
207    }
208    
209    /**
210     *  Will be called by the audio engine after every audio fragment cycle, to
211     *  output the audio data of the current fragment to the soundcard.
212     *
213     *  @returns  0 on success
214     */
215  int AudioIO::Output() {  int AudioIO::Output() {
216      int err = snd_pcm_writei(pcm_handle, pOutputBuffer, FragmentSize);      int err = snd_pcm_writei(pcm_handle, pOutputBuffer, FragmentSize);
217      if (err < 0) {      if (err < 0) {
# Line 165  int AudioIO::Output() { Line 222  int AudioIO::Output() {
222  }  }
223    
224  void AudioIO::Close(void) {  void AudioIO::Close(void) {
225      if (pcm_handle) {      if (Initialized) {
226          snd_pcm_close(pcm_handle);          if (pcm_handle) {
227          pcm_handle = NULL;              //FIXME: currently commented out due to segfault
228      }              //snd_pcm_close(pcm_handle);
229      if (pOutputBuffer) {              pcm_handle = NULL;
230          delete[] pOutputBuffer;          }
231          pOutputBuffer = NULL;          if (pOutputBuffer) {
232                //FIXME: currently commented out due to segfault
233                //delete[] pOutputBuffer;
234                pOutputBuffer = NULL;
235            }
236            Initialized = false;
237      }      }
238  }  }

Legend:
Removed from v.9  
changed lines
  Added in v.28

  ViewVC Help
Powered by ViewVC