Lines 2-7
Link Here
|
2 |
// Advanced Linux Sound Architecture (ALSA) specific audio driver interface. |
2 |
// Advanced Linux Sound Architecture (ALSA) specific audio driver interface. |
3 |
// -------------------------------------------------------------------------- |
3 |
// -------------------------------------------------------------------------- |
4 |
/*************************************************************************** |
4 |
/*************************************************************************** |
|
|
5 |
* 2005-07-12: Heikki Orsila <heikki.orsila@iki.fi> |
6 |
* Fixed use of obsolete parts of ALSA API |
7 |
* |
5 |
* $Log: audiodrv.cpp,v $ |
8 |
* $Log: audiodrv.cpp,v $ |
6 |
* Revision 1.7 2002/03/04 19:07:48 s_a_white |
9 |
* Revision 1.7 2002/03/04 19:07:48 s_a_white |
7 |
* Fix C++ use of nothrow. |
10 |
* Fix C++ use of nothrow. |
Lines 31-36
Link Here
|
31 |
#include "audiodrv.h" |
34 |
#include "audiodrv.h" |
32 |
#ifdef HAVE_ALSA |
35 |
#ifdef HAVE_ALSA |
33 |
|
36 |
|
|
|
37 |
#include <iostream> |
34 |
#include <stdio.h> |
38 |
#include <stdio.h> |
35 |
#ifdef HAVE_EXCEPTIONS |
39 |
#ifdef HAVE_EXCEPTIONS |
36 |
# include <new> |
40 |
# include <new> |
Lines 57-144
Link Here
|
57 |
void *Audio_ALSA::open (AudioConfig &cfg, const char *) |
61 |
void *Audio_ALSA::open (AudioConfig &cfg, const char *) |
58 |
{ |
62 |
{ |
59 |
AudioConfig tmpCfg; |
63 |
AudioConfig tmpCfg; |
60 |
int mask, wantedFormat, format; |
64 |
snd_pcm_uframes_t buffer_frames; |
61 |
int rtn; |
65 |
snd_pcm_hw_params_t *hw_params; |
62 |
int card = -1, dev = 0; |
66 |
|
63 |
|
67 |
// Transfer input parameters to this object. |
64 |
if (_audioHandle != NULL) |
68 |
// May later be replaced with driver defaults. |
65 |
{ |
69 |
tmpCfg = cfg; |
|
|
70 |
unsigned int rate = tmpCfg.frequency; |
71 |
|
72 |
if (_audioHandle != NULL) { |
66 |
_errorString = "ERROR: Device already in use"; |
73 |
_errorString = "ERROR: Device already in use"; |
67 |
return NULL; |
74 |
return NULL; |
68 |
} |
75 |
} |
69 |
|
76 |
|
70 |
if ((rtn = snd_pcm_open_preferred (&_audioHandle, &card, &dev, SND_PCM_OPEN_PLAYBACK))) |
77 |
if (snd_pcm_open (&_audioHandle, "default", SND_PCM_STREAM_PLAYBACK, 0)) { |
71 |
{ |
|
|
72 |
_errorString = "ERROR: Could not open audio device."; |
78 |
_errorString = "ERROR: Could not open audio device."; |
73 |
goto open_error; |
79 |
goto open_error; |
74 |
} |
80 |
} |
75 |
|
|
|
76 |
// Transfer input parameters to this object. |
77 |
// May later be replaced with driver defaults. |
78 |
tmpCfg = cfg; |
79 |
|
81 |
|
80 |
snd_pcm_channel_params_t pp; |
82 |
if (snd_pcm_hw_params_malloc(&hw_params)) { |
81 |
snd_pcm_channel_setup_t setup; |
83 |
_errorString = "ERROR: could not malloc hwparams."; |
82 |
|
84 |
goto open_error; |
83 |
snd_pcm_channel_info_t pi; |
|
|
84 |
|
85 |
memset (&pi, 0, sizeof (pi)); |
86 |
pi.channel = SND_PCM_CHANNEL_PLAYBACK; |
87 |
if ((rtn = snd_pcm_plugin_info (_audioHandle, &pi))) |
88 |
{ |
89 |
_errorString = "ALSA: snd_pcm_plugin_info failed."; |
90 |
goto open_error; |
91 |
} |
85 |
} |
92 |
|
86 |
|
93 |
memset(&pp, 0, sizeof (pp)); |
87 |
if (snd_pcm_hw_params_any (_audioHandle, hw_params)) { |
94 |
|
88 |
_errorString = "ERROR: could not initialize hw params"; |
95 |
pp.mode = SND_PCM_MODE_BLOCK; |
89 |
goto open_error; |
96 |
pp.channel = SND_PCM_CHANNEL_PLAYBACK; |
|
|
97 |
pp.start_mode = SND_PCM_START_FULL; |
98 |
pp.stop_mode = SND_PCM_STOP_STOP; |
99 |
|
100 |
pp.buf.block.frag_size = pi.max_fragment_size; |
101 |
|
102 |
pp.buf.block.frags_max = 1; |
103 |
pp.buf.block.frags_min = 1; |
104 |
|
105 |
pp.format.interleave = 1; |
106 |
pp.format.rate = tmpCfg.frequency; |
107 |
pp.format.voices = tmpCfg.channels; |
108 |
|
109 |
// Set sample precision and type of encoding. |
110 |
if ( tmpCfg.precision == 8 ) |
111 |
{ |
112 |
tmpCfg.encoding = AUDIO_UNSIGNED_PCM; |
113 |
pp.format.format = SND_PCM_SFMT_U8; |
114 |
} |
90 |
} |
115 |
if ( tmpCfg.precision == 16 ) |
91 |
|
116 |
{ |
92 |
if (snd_pcm_hw_params_set_access (_audioHandle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) { |
117 |
tmpCfg.encoding = AUDIO_SIGNED_PCM; |
93 |
_errorString = "ERROR: could not set access type"; |
118 |
pp.format.format = SND_PCM_SFMT_S16_LE; |
94 |
goto open_error; |
119 |
} |
95 |
} |
120 |
|
96 |
|
121 |
if ((rtn = snd_pcm_plugin_params (_audioHandle, &pp)) < 0) |
97 |
snd_pcm_format_t alsamode; |
122 |
{ |
98 |
switch (tmpCfg.precision) { |
123 |
_errorString = "ALSA: snd_pcm_plugin_params failed."; |
99 |
case 8: |
124 |
goto open_error; |
100 |
tmpCfg.encoding = AUDIO_UNSIGNED_PCM; |
|
|
101 |
alsamode = SND_PCM_FORMAT_U8; |
102 |
break; |
103 |
case 16: |
104 |
tmpCfg.encoding = AUDIO_SIGNED_PCM; |
105 |
alsamode = SND_PCM_FORMAT_S16; |
106 |
break; |
107 |
default: |
108 |
_errorString = "ERROR: set desired number of bits for audio device."; |
109 |
goto open_error; |
125 |
} |
110 |
} |
126 |
|
111 |
|
127 |
if ((rtn = snd_pcm_plugin_prepare (_audioHandle, SND_PCM_CHANNEL_PLAYBACK)) < 0) |
112 |
if (snd_pcm_hw_params_set_format (_audioHandle, hw_params, alsamode)) { |
128 |
{ |
113 |
_errorString = "ERROR: could not set sample format"; |
129 |
_errorString = "ALSA: snd_pcm_plugin_prepare failed."; |
114 |
goto open_error; |
130 |
goto open_error; |
|
|
131 |
} |
115 |
} |
132 |
|
116 |
|
133 |
memset (&setup, 0, sizeof (setup)); |
117 |
if (snd_pcm_hw_params_set_channels (_audioHandle, hw_params, tmpCfg.channels)) { |
134 |
setup.channel = SND_PCM_CHANNEL_PLAYBACK; |
118 |
_errorString = "ERROR: could not set channel count"; |
135 |
if ((rtn = snd_pcm_plugin_setup (_audioHandle, &setup)) < 0) |
119 |
goto open_error; |
136 |
{ |
|
|
137 |
_errorString = "ALSA: snd_pcm_plugin_setup failed."; |
138 |
goto open_error; |
139 |
} |
120 |
} |
140 |
|
121 |
|
141 |
tmpCfg.bufSize = setup.buf.block.frag_size; |
122 |
if (snd_pcm_hw_params_set_rate_near (_audioHandle, hw_params, &rate, 0)) { |
|
|
123 |
_errorString = "ERROR: could not set sample rate"; |
124 |
goto open_error; |
125 |
} |
126 |
|
127 |
_alsa_to_frames_divisor = tmpCfg.channels * tmpCfg.precision / 8; |
128 |
buffer_frames = 4096; |
129 |
snd_pcm_hw_params_set_period_size_near(_audioHandle, hw_params, &buffer_frames, 0); |
130 |
|
131 |
if (snd_pcm_hw_params (_audioHandle, hw_params)) { |
132 |
_errorString = "ERROR: could not set hw parameters"; |
133 |
goto open_error; |
134 |
} |
135 |
|
136 |
snd_pcm_hw_params_free (hw_params); |
137 |
|
138 |
if (snd_pcm_prepare (_audioHandle)) { |
139 |
_errorString = "ERROR: could not prepare audio interface for use"; |
140 |
goto open_error; |
141 |
} |
142 |
|
143 |
tmpCfg.bufSize = buffer_frames * _alsa_to_frames_divisor; |
142 |
#ifdef HAVE_EXCEPTIONS |
144 |
#ifdef HAVE_EXCEPTIONS |
143 |
_sampleBuffer = new(std::nothrow) int_least8_t[tmpCfg.bufSize]; |
145 |
_sampleBuffer = new(std::nothrow) int_least8_t[tmpCfg.bufSize]; |
144 |
#else |
146 |
#else |
Lines 158-170
Link Here
|
158 |
return _sampleBuffer; |
160 |
return _sampleBuffer; |
159 |
|
161 |
|
160 |
open_error: |
162 |
open_error: |
|
|
163 |
std::cerr << "ALSA open error: " << _errorString << std::endl; |
161 |
if (_audioHandle != NULL) |
164 |
if (_audioHandle != NULL) |
162 |
{ |
|
|
163 |
close (); |
165 |
close (); |
164 |
} |
|
|
165 |
|
166 |
perror ("ALSA"); |
166 |
perror ("ALSA"); |
167 |
return NULL; |
167 |
return NULL; |
168 |
} |
168 |
} |
169 |
|
169 |
|
170 |
// Close an opened audio device, free any allocated buffers and |
170 |
// Close an opened audio device, free any allocated buffers and |
Lines 174-180
Link Here
|
174 |
if (_audioHandle != NULL ) |
174 |
if (_audioHandle != NULL ) |
175 |
{ |
175 |
{ |
176 |
snd_pcm_close(_audioHandle); |
176 |
snd_pcm_close(_audioHandle); |
177 |
delete [] _sampleBuffer; |
177 |
delete [] ((int_least8_t *) _sampleBuffer); |
178 |
outOfOrder (); |
178 |
outOfOrder (); |
179 |
} |
179 |
} |
180 |
} |
180 |
} |
Lines 192-198
Link Here
|
192 |
return NULL; |
192 |
return NULL; |
193 |
} |
193 |
} |
194 |
|
194 |
|
195 |
snd_pcm_plugin_write (_audioHandle, _sampleBuffer, _settings.bufSize); |
195 |
snd_pcm_writei (_audioHandle, _sampleBuffer, _settings.bufSize / _alsa_to_frames_divisor); |
196 |
return (void *) _sampleBuffer; |
196 |
return (void *) _sampleBuffer; |
197 |
} |
197 |
} |
198 |
|
198 |
|