/[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 531 - (show annotations) (download)
Mon May 9 14:25:09 2005 UTC (16 years, 5 months ago) by schoenebeck
File size: 23317 byte(s)
* ALSA driver: fix of previous ALSA fix ;-)

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

  ViewVC Help
Powered by ViewVC