/[svn]/linuxsampler/trunk/src/drivers/audio/AudioOutputDeviceAlsa.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/drivers/audio/AudioOutputDeviceAlsa.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 485 - (show annotations) (download)
Thu Mar 24 21:06:09 2005 UTC (19 years ago) by schoenebeck
File size: 23200 byte(s)
* ALSA audio driver: don't block for retrieving sound card parameter infos

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
20 * MA 02111-1307 USA *
21 ***************************************************************************/
22
23 #include "AudioOutputDeviceAlsa.h"
24 #include "AudioOutputDeviceFactory.h"
25
26 namespace LinuxSampler {
27
28 // *************** ParameterCard ***************
29 // *
30
31 AudioOutputDeviceAlsa::ParameterCard::ParameterCard() : DeviceCreationParameterString() {
32 InitWithDefault(); // use default card
33 }
34
35 AudioOutputDeviceAlsa::ParameterCard::ParameterCard(String s) throw (LinuxSamplerException) : DeviceCreationParameterString(s) {
36 }
37
38 String AudioOutputDeviceAlsa::ParameterCard::Description() {
39 return "Sound card to be used";
40 }
41
42 bool AudioOutputDeviceAlsa::ParameterCard::Fix() {
43 return true;
44 }
45
46 bool AudioOutputDeviceAlsa::ParameterCard::Mandatory() {
47 return false;
48 }
49
50 std::map<String,DeviceCreationParameter*> AudioOutputDeviceAlsa::ParameterCard::DependsAsParameters() {
51 return std::map<String,DeviceCreationParameter*>(); // no dependencies
52 }
53
54 optional<String> AudioOutputDeviceAlsa::ParameterCard::DefaultAsString(std::map<String,String> Parameters) {
55 std::vector<String> cards = PossibilitiesAsString(Parameters);
56 if (cards.empty()) throw LinuxSamplerException("AudioOutputDeviceAlsa: Can't find any card");
57 return cards[0]; // first card by default
58 }
59
60 std::vector<String> AudioOutputDeviceAlsa::ParameterCard::PossibilitiesAsString(std::map<String,String> Parameters) {
61 int err;
62 std::vector<String> CardNames;
63
64 // iterate through all cards
65 int card_index = -1;
66 while (snd_card_next(&card_index) >= 0 && card_index >= 0) {
67 String hw_name = "hw:" + ToString(card_index);
68 snd_ctl_t* hCardCtrl;
69 if ((err = snd_ctl_open(&hCardCtrl, hw_name.c_str(), 0)) < 0) {
70 std::cerr << "AudioOutputDeviceAlsa: Cannot open sound control for card " << card_index << " - " << snd_strerror(err) << std::endl;
71 continue;
72 }
73
74 // iterate through all devices of that card
75 int device_index = -1;
76 while (!snd_ctl_pcm_next_device(hCardCtrl, &device_index) && device_index >= 0) {
77 String name = ToString(card_index) + "," + ToString(device_index);
78 //dmsg(1,("[possibility:%s]", name.c_str()));
79 CardNames.push_back(name);
80 }
81
82 snd_ctl_close(hCardCtrl);
83 }
84
85 return CardNames;
86 }
87
88 void AudioOutputDeviceAlsa::ParameterCard::OnSetValue(String s) throw (LinuxSamplerException) {
89 // not posssible, as parameter is fix
90 }
91
92 String AudioOutputDeviceAlsa::ParameterCard::Name() {
93 return "CARD";
94 }
95
96
97
98 // *************** ParameterFragments ***************
99 // *
100
101 AudioOutputDeviceAlsa::ParameterFragments::ParameterFragments() : DeviceCreationParameterInt() {
102 InitWithDefault();
103 }
104
105 AudioOutputDeviceAlsa::ParameterFragments::ParameterFragments(String s) throw (LinuxSamplerException) : DeviceCreationParameterInt(s) {
106 }
107
108 String AudioOutputDeviceAlsa::ParameterFragments::Description() {
109 return "Number of buffer fragments";
110 }
111
112 bool AudioOutputDeviceAlsa::ParameterFragments::Fix() {
113 return true;
114 }
115
116 bool AudioOutputDeviceAlsa::ParameterFragments::Mandatory() {
117 return false;
118 }
119
120 std::map<String,DeviceCreationParameter*> AudioOutputDeviceAlsa::ParameterFragments::DependsAsParameters() {
121 static ParameterCard card;
122 std::map<String,DeviceCreationParameter*> dependencies;
123 dependencies[card.Name()] = &card;
124 return dependencies;
125 }
126
127 optional<int> AudioOutputDeviceAlsa::ParameterFragments::DefaultAsInt(std::map<String,String> Parameters) {
128 return 2; // until done
129 }
130
131 optional<int> AudioOutputDeviceAlsa::ParameterFragments::RangeMinAsInt(std::map<String,String> Parameters) {
132 if (!Parameters.count("CARD")) return optional<int>::nothing;
133
134 // obtain information from given sound card
135 String pcm_name = "hw:" + Parameters["CARD"];
136 snd_pcm_t* pcm_handle = NULL;
137 if (snd_pcm_open(&pcm_handle, pcm_name.c_str(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) return optional<int>::nothing;
138 snd_pcm_hw_params_t* hwparams;
139 snd_pcm_hw_params_alloca(&hwparams);
140 if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) {
141 snd_pcm_close(pcm_handle);
142 return optional<int>::nothing;
143 }
144 int dir = 0;
145 uint periods_min;
146 if (snd_pcm_hw_params_get_periods_min(hwparams, &periods_min, &dir) < 0) {
147 snd_pcm_close(pcm_handle);
148 return optional<int>::nothing;
149 }
150 snd_pcm_close(pcm_handle);
151 return (int) periods_min;
152 }
153
154 optional<int> AudioOutputDeviceAlsa::ParameterFragments::RangeMaxAsInt(std::map<String,String> Parameters) {
155 if (!Parameters.count("CARD")) return optional<int>::nothing;
156
157 // obtain information from given sound card
158 String pcm_name = "hw:" + Parameters["CARD"];
159 snd_pcm_t* pcm_handle = NULL;
160 if (snd_pcm_open(&pcm_handle, pcm_name.c_str(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) return optional<int>::nothing;
161 snd_pcm_hw_params_t* hwparams;
162 snd_pcm_hw_params_alloca(&hwparams);
163 if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) {
164 snd_pcm_close(pcm_handle);
165 return optional<int>::nothing;
166 }
167 int dir = 0;
168 uint periods_max;
169 if (snd_pcm_hw_params_get_periods_max(hwparams, &periods_max, &dir) < 0) {
170 snd_pcm_close(pcm_handle);
171 return optional<int>::nothing;
172 }
173 snd_pcm_close(pcm_handle);
174 return (int) periods_max;
175 }
176
177 std::vector<int> AudioOutputDeviceAlsa::ParameterFragments::PossibilitiesAsInt(std::map<String,String> Parameters) {
178 return std::vector<int>();
179 }
180
181 void AudioOutputDeviceAlsa::ParameterFragments::OnSetValue(int i) throw (LinuxSamplerException) {
182 // not posssible, as parameter is fix
183 }
184
185 String AudioOutputDeviceAlsa::ParameterFragments::Name() {
186 return "FRAGMENTS";
187 }
188
189
190
191 // *************** ParameterFragmentSize ***************
192 // *
193
194 AudioOutputDeviceAlsa::ParameterFragmentSize::ParameterFragmentSize() : DeviceCreationParameterInt() {
195 InitWithDefault();
196 }
197
198 AudioOutputDeviceAlsa::ParameterFragmentSize::ParameterFragmentSize(String s) throw (LinuxSamplerException) : DeviceCreationParameterInt(s) {
199 }
200
201 String AudioOutputDeviceAlsa::ParameterFragmentSize::Description() {
202 return "Size of each buffer fragment";
203 }
204
205 bool AudioOutputDeviceAlsa::ParameterFragmentSize::Fix() {
206 return true;
207 }
208
209 bool AudioOutputDeviceAlsa::ParameterFragmentSize::Mandatory() {
210 return false;
211 }
212
213 std::map<String,DeviceCreationParameter*> AudioOutputDeviceAlsa::ParameterFragmentSize::DependsAsParameters() {
214 static ParameterCard card;
215 std::map<String,DeviceCreationParameter*> dependencies;
216 dependencies[card.Name()] = &card;
217 return dependencies;
218 }
219
220 optional<int> AudioOutputDeviceAlsa::ParameterFragmentSize::DefaultAsInt(std::map<String,String> Parameters) {
221 return 128; // until done
222 }
223
224 optional<int> AudioOutputDeviceAlsa::ParameterFragmentSize::RangeMinAsInt(std::map<String,String> Parameters) {
225 if (!Parameters.count("CARD")) return optional<int>::nothing;
226
227 // obtain information from given sound card
228 String pcm_name = "hw:" + Parameters["CARD"];
229 snd_pcm_t* pcm_handle = NULL;
230 if (snd_pcm_open(&pcm_handle, pcm_name.c_str(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) return optional<int>::nothing;
231 snd_pcm_hw_params_t* hwparams;
232 snd_pcm_hw_params_alloca(&hwparams);
233 if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) {
234 snd_pcm_close(pcm_handle);
235 return optional<int>::nothing;
236 }
237 int dir = 0;
238 unsigned long period_size_min;
239 if (snd_pcm_hw_params_get_period_size_min(hwparams, &period_size_min, &dir) < 0) {
240 snd_pcm_close(pcm_handle);
241 return optional<int>::nothing;
242 }
243 snd_pcm_close(pcm_handle);
244 return (int) period_size_min;
245 }
246
247 optional<int> AudioOutputDeviceAlsa::ParameterFragmentSize::RangeMaxAsInt(std::map<String,String> Parameters) {
248 if (!Parameters.count("CARD")) return optional<int>::nothing;
249
250 // obtain information from given sound card
251 String pcm_name = "hw:" + Parameters["CARD"];
252 snd_pcm_t* pcm_handle = NULL;
253 if (snd_pcm_open(&pcm_handle, pcm_name.c_str(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) return optional<int>::nothing;
254 snd_pcm_hw_params_t* hwparams;
255 snd_pcm_hw_params_alloca(&hwparams);
256 if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) {
257 snd_pcm_close(pcm_handle);
258 return optional<int>::nothing;
259 }
260 int dir = 0;
261 unsigned long period_size_max;
262 if (snd_pcm_hw_params_get_period_size_max(hwparams, &period_size_max, &dir) < 0) {
263 snd_pcm_close(pcm_handle);
264 return optional<int>::nothing;
265 }
266 snd_pcm_close(pcm_handle);
267 return (int) period_size_max; //FIXME: might overflow int limit
268 }
269
270 std::vector<int> AudioOutputDeviceAlsa::ParameterFragmentSize::PossibilitiesAsInt(std::map<String,String> Parameters) {
271 return std::vector<int>();
272 }
273
274 void AudioOutputDeviceAlsa::ParameterFragmentSize::OnSetValue(int i) throw (LinuxSamplerException) {
275 // not posssible, as parameter is fix
276 }
277
278 String AudioOutputDeviceAlsa::ParameterFragmentSize::Name() {
279 return "FRAGMENTSIZE";
280 }
281
282
283
284 // *************** AudioOutputDeviceAlsa ***************
285 // *
286
287 /**
288 * Create and initialize Alsa audio output device with given parameters.
289 *
290 * @param Parameters - optional parameters
291 * @throws AudioOutputException if output device cannot be opened
292 */
293 AudioOutputDeviceAlsa::AudioOutputDeviceAlsa(std::map<String,DeviceCreationParameter*> Parameters) : AudioOutputDevice(Parameters), Thread(true, true, 1, 0) {
294 pcm_handle = NULL;
295 stream = SND_PCM_STREAM_PLAYBACK;
296 this->uiAlsaChannels = ((DeviceCreationParameterInt*)Parameters["CHANNELS"])->ValueAsInt();
297 this->uiSamplerate = ((DeviceCreationParameterInt*)Parameters["SAMPLERATE"])->ValueAsInt();
298 this->FragmentSize = ((DeviceCreationParameterInt*)Parameters["FRAGMENTSIZE"])->ValueAsInt();
299 uint Fragments = ((DeviceCreationParameterInt*)Parameters["FRAGMENTS"])->ValueAsInt();
300 String Card = ((DeviceCreationParameterString*)Parameters["CARD"])->ValueAsString();
301
302 dmsg(1,("Checking if hw parameters supported...\n"));
303 if (HardwareParametersSupported(Card, uiAlsaChannels, uiSamplerate, Fragments, FragmentSize)) {
304 pcm_name = "hw:" + Card;
305 }
306 else {
307 printf("Warning: your soundcard doesn't support chosen hardware parameters; ");
308 printf("trying to compensate support lack with plughw...");
309 fflush(stdout);
310 pcm_name = "plughw:" + Card;
311 }
312 dmsg(1,("HW check completed.\n"));
313
314 int err;
315
316 snd_pcm_hw_params_alloca(&hwparams); // Allocate the snd_pcm_hw_params_t structure on the stack.
317
318 /* Open PCM. The last parameter of this function is the mode. */
319 /* If this is set to 0, the standard mode is used. Possible */
320 /* other values are SND_PCM_NONBLOCK and SND_PCM_ASYNC. */
321 /* If SND_PCM_NONBLOCK is used, read / write access to the */
322 /* PCM device will return immediately. If SND_PCM_ASYNC is */
323 /* specified, SIGIO will be emitted whenever a period has */
324 /* been completely processed by the soundcard. */
325 if ((err = snd_pcm_open(&pcm_handle, pcm_name.c_str(), stream, 0)) < 0) {
326 throw AudioOutputException(String("Error opening PCM device ") + pcm_name + ": " + snd_strerror(err));
327 }
328
329 if ((err = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) {
330 throw AudioOutputException(String("Error, cannot initialize hardware parameter structure: ") + snd_strerror(err));
331 }
332
333 /* Set access type. This can be either */
334 /* SND_PCM_ACCESS_RW_INTERLEAVED or */
335 /* SND_PCM_ACCESS_RW_NONINTERLEAVED. */
336 if ((err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
337 throw AudioOutputException(String("Error snd_pcm_hw_params_set_access: ") + snd_strerror(err));
338 }
339
340 /* Set sample format */
341 #if WORDS_BIGENDIAN
342 if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_BE)) < 0)
343 #else // little endian
344 if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE)) < 0)
345 #endif
346 {
347 throw AudioOutputException(String("Error setting sample format: ") + snd_strerror(err));
348 }
349
350 int dir = 0;
351
352 /* Set sample rate. If the exact rate is not supported */
353 /* by the hardware, use nearest possible rate. */
354 #if ALSA_MAJOR > 0
355 if((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &uiSamplerate, &dir)) < 0)
356 #else
357 if((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, uiSamplerate, &dir)) < 0)
358 #endif
359 {
360 throw AudioOutputException(String("Error setting sample rate: ") + snd_strerror(err));
361 }
362
363 if ((err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, uiAlsaChannels)) < 0) {
364 throw AudioOutputException(String("Error setting number of channels: ") + snd_strerror(err));
365 }
366
367 /* Set number of periods. Periods used to be called fragments. */
368 if ((err = snd_pcm_hw_params_set_periods(pcm_handle, hwparams, Fragments, dir)) < 0) {
369 throw AudioOutputException(String("Error setting number of periods: ") + snd_strerror(err));
370 }
371
372 /* Set buffer size (in frames). The resulting latency is given by */
373 /* latency = periodsize * periods / (rate * bytes_per_frame) */
374 if ((err = snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, (FragmentSize * Fragments))) < 0) {
375 throw AudioOutputException(String("Error setting buffersize: ") + snd_strerror(err));
376 }
377
378 /* Apply HW parameter settings to */
379 /* PCM device and prepare device */
380 if ((err = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
381 throw AudioOutputException(String("Error setting HW params: ") + snd_strerror(err));
382 }
383
384 if (snd_pcm_sw_params_malloc(&swparams) != 0) {
385 throw AudioOutputException(String("Error in snd_pcm_sw_params_malloc: ") + snd_strerror(err));
386 }
387
388 if (snd_pcm_sw_params_current(pcm_handle, swparams) != 0) {
389 throw AudioOutputException(String("Error in snd_pcm_sw_params_current: ") + snd_strerror(err));
390 }
391
392 if (snd_pcm_sw_params_set_stop_threshold(pcm_handle, swparams, 0xffffffff) != 0) {
393 throw AudioOutputException(String("Error in snd_pcm_sw_params_set_stop_threshold: ") + snd_strerror(err));
394 }
395
396 if (snd_pcm_sw_params(pcm_handle, swparams) != 0) {
397 throw AudioOutputException(String("Error in snd_pcm_sw_params: ") + snd_strerror(err));
398 }
399
400 if ((err = snd_pcm_prepare(pcm_handle)) < 0) {
401 throw AudioOutputException(String("Error snd_pcm_prepare: ") + snd_strerror(err));
402 }
403
404 // allocate Alsa output buffer
405 pAlsaOutputBuffer = new int16_t[uiAlsaChannels * FragmentSize];
406
407 // create audio channels for this audio device to which the sampler engines can write to
408 for (int i = 0; i < uiAlsaChannels; i++) this->Channels.push_back(new AudioChannel(i, FragmentSize));
409
410 if (((DeviceCreationParameterBool*)Parameters["ACTIVE"])->ValueAsBool()) {
411 Play();
412 }
413 }
414
415 AudioOutputDeviceAlsa::~AudioOutputDeviceAlsa() {
416 //dmsg(0,("Stopping Alsa Thread..."));
417 //StopThread(); //FIXME: commented out due to a bug in thread.cpp (StopThread() doesn't return at all)
418 //dmsg(0,("OK\n"));
419
420 //FIXME: currently commented out due to segfault
421 //snd_pcm_close(pcm_handle);
422
423 if (pAlsaOutputBuffer) {
424 //FIXME: currently commented out due to segfault
425 //delete[] pOutputBuffer;
426 }
427 }
428
429 /**
430 * Checks if sound card supports the chosen parameters.
431 *
432 * @returns true if hardware supports it
433 * @throws AudioOutputException - if device cannot be accessed
434 */
435 bool AudioOutputDeviceAlsa::HardwareParametersSupported(String card, uint channels, int samplerate, uint numfragments, uint fragmentsize) throw (AudioOutputException) {
436 pcm_name = "hw:" + card;
437 int err;
438 if ((err = snd_pcm_open(&pcm_handle, pcm_name.c_str(), stream, 0)) < 0) {
439 throw AudioOutputException(String("Error opening PCM device ") + pcm_name + ": " + snd_strerror(err));
440 }
441 snd_pcm_hw_params_alloca(&hwparams);
442 if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) {
443 snd_pcm_close(pcm_handle);
444 return false;
445 }
446 if (snd_pcm_hw_params_test_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
447 snd_pcm_close(pcm_handle);
448 return false;
449 }
450 #if WORDS_BIGENDIAN
451 if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_BE) < 0)
452 #else // little endian
453 if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0)
454 #endif
455 {
456 snd_pcm_close(pcm_handle);
457 return false;
458 }
459 int dir = 0;
460 if (snd_pcm_hw_params_test_rate(pcm_handle, hwparams, samplerate, dir) < 0) {
461 snd_pcm_close(pcm_handle);
462 return false;
463 }
464 if (snd_pcm_hw_params_test_channels(pcm_handle, hwparams, channels) < 0) {
465 snd_pcm_close(pcm_handle);
466 return false;
467 }
468 if (snd_pcm_hw_params_test_periods(pcm_handle, hwparams, numfragments, dir) < 0) {
469 snd_pcm_close(pcm_handle);
470 return false;
471 }
472 if (snd_pcm_hw_params_test_buffer_size(pcm_handle, hwparams, (fragmentsize * numfragments)) < 0) {
473 snd_pcm_close(pcm_handle);
474 return false;
475 }
476
477 snd_pcm_close(pcm_handle);
478 return true;
479 }
480
481 void AudioOutputDeviceAlsa::Play() {
482 StartThread();
483 }
484
485 bool AudioOutputDeviceAlsa::IsPlaying() {
486 return IsRunning(); // if Thread is running
487 }
488
489 void AudioOutputDeviceAlsa::Stop() {
490 StopThread();
491 }
492
493 AudioChannel* AudioOutputDeviceAlsa::CreateChannel(uint ChannelNr) {
494 // just create a mix channel
495 return new AudioChannel(ChannelNr, Channel(ChannelNr % uiAlsaChannels));
496 }
497
498 uint AudioOutputDeviceAlsa::MaxSamplesPerCycle() {
499 return FragmentSize;
500 }
501
502 uint AudioOutputDeviceAlsa::SampleRate() {
503 return uiSamplerate;
504 }
505
506 String AudioOutputDeviceAlsa::Name() {
507 return "ALSA";
508 }
509
510 String AudioOutputDeviceAlsa::Driver() {
511 return Name();
512 }
513
514 String AudioOutputDeviceAlsa::Description() {
515 return "Advanced Linux Sound Architecture";
516 }
517
518 String AudioOutputDeviceAlsa::Version() {
519 String s = "$Revision: 1.18 $";
520 return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
521 }
522
523 /**
524 * Entry point for the thread.
525 */
526 int AudioOutputDeviceAlsa::Main() {
527 while (true) {
528
529 // let all connected engines render 'FragmentSize' sample points
530 RenderAudio(FragmentSize);
531
532 // convert from DSP value range (-1.0..+1.0) to 16 bit integer value
533 // range (-32768..+32767), check clipping and copy to Alsa output buffer
534 // (note: we use interleaved output method to Alsa)
535 for (int c = 0; c < uiAlsaChannels; c++) {
536 float* in = Channels[c]->Buffer();
537 for (int i = 0, o = c; i < FragmentSize; i++ , o += uiAlsaChannels) {
538 float sample_point = in[i] * 32768.0f;
539 if (sample_point < -32768.0) sample_point = -32768.0;
540 if (sample_point > 32767.0) sample_point = 32767.0;
541 pAlsaOutputBuffer[o] = (int16_t) sample_point;
542 }
543 }
544
545 // output sound
546 int res = Output();
547 if (res < 0) {
548 fprintf(stderr, "Alsa: Audio output error, exiting.\n");
549 exit(EXIT_FAILURE);
550 }
551 }
552 }
553
554 /**
555 * Will be called after every audio fragment cycle, to output the audio data
556 * of the current fragment to the soundcard.
557 *
558 * @returns 0 on success, a value < 0 on error
559 */
560 int AudioOutputDeviceAlsa::Output() {
561 int err = snd_pcm_writei(pcm_handle, pAlsaOutputBuffer, FragmentSize);
562 if (err < 0) {
563 fprintf(stderr, "Error snd_pcm_writei failed: %s\n", snd_strerror(err));
564 return -1;
565 }
566 return 0;
567 }
568
569 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC