/[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 392 - (show annotations) (download)
Sat Feb 19 02:40:24 2005 UTC (19 years, 1 month ago) by schoenebeck
File size: 22905 byte(s)
* fixed possibility that memory got not locked
* immediately set instrument status when calling LOAD INSTUMENT NON_MODAL

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, 0) < 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, 0) < 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, 0) < 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, 0) < 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 */
434 bool AudioOutputDeviceAlsa::HardwareParametersSupported(String card, uint channels, int samplerate, uint numfragments, uint fragmentsize) {
435 pcm_name = "hw:" + card;
436 if (snd_pcm_open(&pcm_handle, pcm_name.c_str(), stream, 0) < 0) return false;
437 snd_pcm_hw_params_alloca(&hwparams);
438 if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) {
439 snd_pcm_close(pcm_handle);
440 return false;
441 }
442 if (snd_pcm_hw_params_test_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
443 snd_pcm_close(pcm_handle);
444 return false;
445 }
446 #if WORDS_BIGENDIAN
447 if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_BE) < 0)
448 #else // little endian
449 if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0)
450 #endif
451 {
452 snd_pcm_close(pcm_handle);
453 return false;
454 }
455 int dir = 0;
456 if (snd_pcm_hw_params_test_rate(pcm_handle, hwparams, samplerate, dir) < 0) {
457 snd_pcm_close(pcm_handle);
458 return false;
459 }
460 if (snd_pcm_hw_params_test_channels(pcm_handle, hwparams, channels) < 0) {
461 snd_pcm_close(pcm_handle);
462 return false;
463 }
464 if (snd_pcm_hw_params_test_periods(pcm_handle, hwparams, numfragments, dir) < 0) {
465 snd_pcm_close(pcm_handle);
466 return false;
467 }
468 if (snd_pcm_hw_params_test_buffer_size(pcm_handle, hwparams, (fragmentsize * numfragments)) < 0) {
469 snd_pcm_close(pcm_handle);
470 return false;
471 }
472
473 snd_pcm_close(pcm_handle);
474 return true;
475 }
476
477 void AudioOutputDeviceAlsa::Play() {
478 StartThread();
479 }
480
481 bool AudioOutputDeviceAlsa::IsPlaying() {
482 return IsRunning(); // if Thread is running
483 }
484
485 void AudioOutputDeviceAlsa::Stop() {
486 StopThread();
487 }
488
489 AudioChannel* AudioOutputDeviceAlsa::CreateChannel(uint ChannelNr) {
490 // just create a mix channel
491 return new AudioChannel(ChannelNr, Channel(ChannelNr % uiAlsaChannels));
492 }
493
494 uint AudioOutputDeviceAlsa::MaxSamplesPerCycle() {
495 return FragmentSize;
496 }
497
498 uint AudioOutputDeviceAlsa::SampleRate() {
499 return uiSamplerate;
500 }
501
502 String AudioOutputDeviceAlsa::Name() {
503 return "ALSA";
504 }
505
506 String AudioOutputDeviceAlsa::Driver() {
507 return Name();
508 }
509
510 String AudioOutputDeviceAlsa::Description() {
511 return "Advanced Linux Sound Architecture";
512 }
513
514 String AudioOutputDeviceAlsa::Version() {
515 String s = "$Revision: 1.17 $";
516 return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
517 }
518
519 /**
520 * Entry point for the thread.
521 */
522 int AudioOutputDeviceAlsa::Main() {
523 while (true) {
524
525 // let all connected engines render 'FragmentSize' sample points
526 RenderAudio(FragmentSize);
527
528 // convert from DSP value range (-1.0..+1.0) to 16 bit integer value
529 // range (-32768..+32767), check clipping and copy to Alsa output buffer
530 // (note: we use interleaved output method to Alsa)
531 for (int c = 0; c < uiAlsaChannels; c++) {
532 float* in = Channels[c]->Buffer();
533 for (int i = 0, o = c; i < FragmentSize; i++ , o += uiAlsaChannels) {
534 float sample_point = in[i] * 32768.0f;
535 if (sample_point < -32768.0) sample_point = -32768.0;
536 if (sample_point > 32767.0) sample_point = 32767.0;
537 pAlsaOutputBuffer[o] = (int16_t) sample_point;
538 }
539 }
540
541 // output sound
542 int res = Output();
543 if (res < 0) {
544 fprintf(stderr, "Alsa: Audio output error, exiting.\n");
545 exit(EXIT_FAILURE);
546 }
547 }
548 }
549
550 /**
551 * Will be called after every audio fragment cycle, to output the audio data
552 * of the current fragment to the soundcard.
553 *
554 * @returns 0 on success, a value < 0 on error
555 */
556 int AudioOutputDeviceAlsa::Output() {
557 int err = snd_pcm_writei(pcm_handle, pAlsaOutputBuffer, FragmentSize);
558 if (err < 0) {
559 fprintf(stderr, "Error snd_pcm_writei failed: %s\n", snd_strerror(err));
560 return -1;
561 }
562 return 0;
563 }
564
565 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC