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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 28 - (hide annotations) (download)
Fri Jan 2 00:02:56 2004 UTC (20 years, 3 months ago) by schoenebeck
File size: 9446 byte(s)
* src/gig.cpp: fixed looping informations ('LoopStart', 'LoopEnd' and
  'LoopSize')
* src/voice.cpp: pitch sample according to keyboard position only if
  keyrange > 1 key, this was the reason that some gig files were horrible
  detuned
* src/audioio.cpp: bigendian specific fix
* src/ringbuffer.h: removed kernel header dependency by adding own atomic.h

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 schoenebeck 28 #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 schoenebeck 9 if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE)) < 0) {
86 schoenebeck 28 #endif
87 schoenebeck 9 fprintf(stderr, "Error setting sample format. : %s\n", snd_strerror(err));
88     return EXIT_FAILURE;
89     }
90    
91 schoenebeck 18 int dir = 0;
92    
93 schoenebeck 9 /* Set sample rate. If the exact rate is not supported */
94     /* by the hardware, use nearest possible rate. */
95 schoenebeck 18 #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 schoenebeck 9 fprintf(stderr, "Error setting sample rate. : %s\n", snd_strerror(err));
101     return EXIT_FAILURE;
102     }
103    
104     if ((err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, channels)) < 0) {
105     fprintf(stderr, "Error setting number of channels. : %s\n", snd_strerror(err));
106     return EXIT_FAILURE;
107     }
108    
109     /* Set number of periods. Periods used to be called fragments. */
110 schoenebeck 18 if ((err = snd_pcm_hw_params_set_periods(pcm_handle, hwparams, numfragments, dir)) < 0) {
111 schoenebeck 9 fprintf(stderr, "Error setting number of periods. : %s\n", snd_strerror(err));
112     return EXIT_FAILURE;
113     }
114    
115     /* Set buffer size (in frames). The resulting latency is given by */
116     /* latency = periodsize * periods / (rate * bytes_per_frame) */
117     if ((err = snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, (fragmentsize * numfragments))) < 0) {
118     fprintf(stderr, "Error setting buffersize. : %s\n", snd_strerror(err));
119     return EXIT_FAILURE;
120     }
121    
122     /* Apply HW parameter settings to */
123     /* PCM device and prepare device */
124     if ((err = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
125     fprintf(stderr, "Error setting HW params. : %s\n", snd_strerror(err));
126     return EXIT_FAILURE;
127     }
128    
129     if (snd_pcm_sw_params_malloc(&swparams) != 0) {
130     fprintf(stderr, "Error in snd_pcm_sw_params_malloc. : %s\n", snd_strerror(err));
131     return EXIT_FAILURE;
132     }
133    
134     if (snd_pcm_sw_params_current(pcm_handle, swparams) != 0) {
135     fprintf(stderr, "Error in snd_pcm_sw_params_current. : %s\n", snd_strerror(err));
136     return EXIT_FAILURE;
137     }
138    
139     if (snd_pcm_sw_params_set_stop_threshold(pcm_handle, swparams, 0xffffffff) != 0) {
140     fprintf(stderr, "Error in snd_pcm_sw_params_set_stop_threshold. : %s\n", snd_strerror(err));
141     return EXIT_FAILURE;
142     }
143    
144     if (snd_pcm_sw_params(pcm_handle, swparams) != 0) {
145     fprintf(stderr, "Error in snd_pcm_sw_params. : %s\n", snd_strerror(err));
146     return EXIT_FAILURE;
147     }
148    
149     if ((err = snd_pcm_prepare(pcm_handle)) < 0) {
150     fprintf(stderr, "Error snd_pcm_prepare : %s\n", snd_strerror(err));
151     return EXIT_FAILURE;
152     }
153    
154     // allocate the audio output buffer
155     pOutputBuffer = new int16_t[channels * fragmentsize];
156 schoenebeck 13
157     this->Initialized = true;
158 schoenebeck 9
159     return EXIT_SUCCESS;
160     }
161    
162 schoenebeck 13 /**
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 schoenebeck 28 #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 schoenebeck 13 if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0) {
183 schoenebeck 28 #endif
184 schoenebeck 13 snd_pcm_close(pcm_handle);
185     return false;
186     }
187 schoenebeck 18 int dir = 0;
188     if (snd_pcm_hw_params_test_rate(pcm_handle, hwparams, samplerate, dir) < 0) {
189 schoenebeck 13 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 schoenebeck 18 if (snd_pcm_hw_params_test_periods(pcm_handle, hwparams, numfragments, dir) < 0) {
197 schoenebeck 13 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 schoenebeck 18 /**
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 schoenebeck 9 int AudioIO::Output() {
216     int err = snd_pcm_writei(pcm_handle, pOutputBuffer, FragmentSize);
217     if (err < 0) {
218     fprintf(stderr, "Error snd_pcm_writei failed. : %s\n", snd_strerror(err));
219     return EXIT_FAILURE;
220     }
221     return EXIT_SUCCESS;
222     }
223    
224     void AudioIO::Close(void) {
225 schoenebeck 13 if (Initialized) {
226     if (pcm_handle) {
227     //FIXME: currently commented out due to segfault
228     //snd_pcm_close(pcm_handle);
229     pcm_handle = NULL;
230     }
231     if (pOutputBuffer) {
232     //FIXME: currently commented out due to segfault
233     //delete[] pOutputBuffer;
234     pOutputBuffer = NULL;
235     }
236     Initialized = false;
237 schoenebeck 9 }
238     }

  ViewVC Help
Powered by ViewVC