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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 13 - (hide annotations) (download)
Fri Nov 21 15:07:23 2003 UTC (20 years, 5 months ago) by schoenebeck
File size: 8770 byte(s)
* src/voice.cpp: fixed bug which caused a voice not free it's disk stream
  when the whole sample was already played back and the voice was going to
  free itself resulting in outage of unused disk streams after a while
* src/audioio.cpp: implemented automatic fallback to ALSA plughw when the
  sound card doesn't support one of the hardware parameters
* src/linuxsampler.cpp: solved segmentation fault issue when receiving a
  SIGINT which was caused due to the fact that all threads entered the
  signal handler (there still seems to occur a segfault on some certain
  circumstances though)
* added print out of all-time maximum usage of voices and streams and the
  current number of unused streams
* src/thread.cpp: the StopThread() method will now block until the
  associated thread actually stopped it's execution

1 schoenebeck 9 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003 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 "audioio.h"
24    
25     AudioIO::AudioIO() {
26     pcm_handle = NULL;
27     pOutputBuffer = NULL;
28 schoenebeck 13 Initialized = false;
29     stream = SND_PCM_STREAM_PLAYBACK;
30 schoenebeck 9 }
31    
32     AudioIO::~AudioIO() {
33     Close();
34     }
35    
36     int AudioIO::Initialize(uint channels, uint samplerate, uint numfragments, uint fragmentsize) {
37 schoenebeck 13 this->Channels = channels;
38     this->Samplerate = samplerate;
39     this->Fragments = numfragments;
40     this->FragmentSize = fragmentsize;
41 schoenebeck 9
42 schoenebeck 13 if (HardwareParametersSupported(channels, samplerate, numfragments, fragmentsize)) {
43     pcm_name = "hw:0,0";
44     }
45     else {
46     printf("Warning: your soundcard doesn't support chosen hardware parameters; ");
47     printf("trying to compensate support lack with plughw...");
48     fflush(stdout);
49     pcm_name = "plughw:0,0";
50     }
51 schoenebeck 9
52     int err;
53    
54 schoenebeck 13 snd_pcm_hw_params_alloca(&hwparams); // Allocate the snd_pcm_hw_params_t structure on the stack.
55 schoenebeck 9
56     /* Open PCM. The last parameter of this function is the mode. */
57     /* If this is set to 0, the standard mode is used. Possible */
58     /* other values are SND_PCM_NONBLOCK and SND_PCM_ASYNC. */
59     /* If SND_PCM_NONBLOCK is used, read / write access to the */
60     /* PCM device will return immediately. If SND_PCM_ASYNC is */
61     /* specified, SIGIO will be emitted whenever a period has */
62     /* been completely processed by the soundcard. */
63 schoenebeck 13 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.c_str(), snd_strerror(err));
65 schoenebeck 9 return EXIT_FAILURE;
66     }
67    
68     if ((err = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) {
69     fprintf(stderr, "Error, cannot initialize hardware parameter structure: %s.\n", snd_strerror(err));
70     return EXIT_FAILURE;
71     }
72    
73     /* Set access type. This can be either */
74     /* SND_PCM_ACCESS_RW_INTERLEAVED or */
75     /* SND_PCM_ACCESS_RW_NONINTERLEAVED. */
76     if ((err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
77     fprintf(stderr, "Error snd_pcm_hw_params_set_access: %s.\n", snd_strerror(err));
78     return EXIT_FAILURE;
79     }
80    
81     /* Set sample format */
82     if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE)) < 0) {
83     fprintf(stderr, "Error setting sample format. : %s\n", snd_strerror(err));
84     return EXIT_FAILURE;
85     }
86    
87     /* Set sample rate. If the exact rate is not supported */
88     /* by the hardware, use nearest possible rate. */
89     if((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, samplerate, 0)) < 0) {
90     fprintf(stderr, "Error setting sample rate. : %s\n", snd_strerror(err));
91     return EXIT_FAILURE;
92     }
93    
94     if ((err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, channels)) < 0) {
95     fprintf(stderr, "Error setting number of channels. : %s\n", snd_strerror(err));
96     return EXIT_FAILURE;
97     }
98    
99     /* Set number of periods. Periods used to be called fragments. */
100     if ((err = snd_pcm_hw_params_set_periods(pcm_handle, hwparams, numfragments, 0)) < 0) {
101     fprintf(stderr, "Error setting number of periods. : %s\n", snd_strerror(err));
102     return EXIT_FAILURE;
103     }
104    
105     /* Set buffer size (in frames). The resulting latency is given by */
106     /* latency = periodsize * periods / (rate * bytes_per_frame) */
107     if ((err = snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, (fragmentsize * numfragments))) < 0) {
108     fprintf(stderr, "Error setting buffersize. : %s\n", snd_strerror(err));
109     return EXIT_FAILURE;
110     }
111    
112     /* Apply HW parameter settings to */
113     /* PCM device and prepare device */
114     if ((err = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
115     fprintf(stderr, "Error setting HW params. : %s\n", snd_strerror(err));
116     return EXIT_FAILURE;
117     }
118    
119     if (snd_pcm_sw_params_malloc(&swparams) != 0) {
120     fprintf(stderr, "Error in snd_pcm_sw_params_malloc. : %s\n", snd_strerror(err));
121     return EXIT_FAILURE;
122     }
123    
124     if (snd_pcm_sw_params_current(pcm_handle, swparams) != 0) {
125     fprintf(stderr, "Error in snd_pcm_sw_params_current. : %s\n", snd_strerror(err));
126     return EXIT_FAILURE;
127     }
128    
129     if (snd_pcm_sw_params_set_stop_threshold(pcm_handle, swparams, 0xffffffff) != 0) {
130     fprintf(stderr, "Error in snd_pcm_sw_params_set_stop_threshold. : %s\n", snd_strerror(err));
131     return EXIT_FAILURE;
132     }
133    
134     if (snd_pcm_sw_params(pcm_handle, swparams) != 0) {
135     fprintf(stderr, "Error in snd_pcm_sw_params. : %s\n", snd_strerror(err));
136     return EXIT_FAILURE;
137     }
138    
139     if ((err = snd_pcm_prepare(pcm_handle)) < 0) {
140     fprintf(stderr, "Error snd_pcm_prepare : %s\n", snd_strerror(err));
141     return EXIT_FAILURE;
142     }
143    
144     // allocate the audio output buffer
145     pOutputBuffer = new int16_t[channels * fragmentsize];
146 schoenebeck 13
147     this->Initialized = true;
148 schoenebeck 9
149     return EXIT_SUCCESS;
150     }
151    
152 schoenebeck 13 /**
153     * Checks if sound card supports the chosen parameters.
154     *
155     * @returns true if hardware supports it
156     */
157     bool AudioIO::HardwareParametersSupported(uint channels, int samplerate, uint numfragments, uint fragmentsize) {
158     pcm_name = "hw:0,0";
159     if (snd_pcm_open(&pcm_handle, pcm_name.c_str(), stream, 0) < 0) return false;
160     snd_pcm_hw_params_alloca(&hwparams);
161     if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) {
162     snd_pcm_close(pcm_handle);
163     return false;
164     }
165     if (snd_pcm_hw_params_test_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
166     snd_pcm_close(pcm_handle);
167     return false;
168     }
169     if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0) {
170     snd_pcm_close(pcm_handle);
171     return false;
172     }
173     if (snd_pcm_hw_params_test_rate(pcm_handle, hwparams, samplerate, 0) < 0) {
174     snd_pcm_close(pcm_handle);
175     return false;
176     }
177     if (snd_pcm_hw_params_test_channels(pcm_handle, hwparams, channels) < 0) {
178     snd_pcm_close(pcm_handle);
179     return false;
180     }
181     if (snd_pcm_hw_params_test_periods(pcm_handle, hwparams, numfragments, 0) < 0) {
182     snd_pcm_close(pcm_handle);
183     return false;
184     }
185     if (snd_pcm_hw_params_test_buffer_size(pcm_handle, hwparams, (fragmentsize * numfragments)) < 0) {
186     snd_pcm_close(pcm_handle);
187     return false;
188     }
189    
190     snd_pcm_close(pcm_handle);
191     return true;
192     }
193    
194 schoenebeck 9 int AudioIO::Output() {
195     int err = snd_pcm_writei(pcm_handle, pOutputBuffer, FragmentSize);
196     if (err < 0) {
197     fprintf(stderr, "Error snd_pcm_writei failed. : %s\n", snd_strerror(err));
198     return EXIT_FAILURE;
199     }
200     return EXIT_SUCCESS;
201     }
202    
203     void AudioIO::Close(void) {
204 schoenebeck 13 if (Initialized) {
205     if (pcm_handle) {
206     //FIXME: currently commented out due to segfault
207     //snd_pcm_close(pcm_handle);
208     pcm_handle = NULL;
209     }
210     if (pOutputBuffer) {
211     //FIXME: currently commented out due to segfault
212     //delete[] pOutputBuffer;
213     pOutputBuffer = NULL;
214     }
215     Initialized = false;
216 schoenebeck 9 }
217     }

  ViewVC Help
Powered by ViewVC