32 class ALSAAudioDevice:
public AudioDevice
35 int mNChannelsWritten;
36 bool mChannelsWritten[256];
39 bool mChannelsRead[256];
42 Array<short> mWriteBuf;
45 Array<short> mReadBuf;
50 int HighestChannelID();
53 ALSAAudioDevice(
const std::string& name,
const std::string& device);
56 void Start(
void) throw(Err);
57 void Stop(
void) throw(Err);
58 void Read(Audio& audio,const
int channelID);
59 void Write(const Audio& audio,const
int channelID);
62 ALSAAudioDevice::ALSAAudioDevice(const std::
string& name,const std::
string& device):
70 mNChannelsWritten = 0;
72 mChannelsWritten[i] =
false;
76 mChannelsRead[i] =
false;
81 int ALSAAudioDevice::HighestChannelID(
void)
85 std::vector<AudioIn*>::const_iterator in_it;
88 if ( (*in_it)->GetChannelID() > max_id)
89 max_id = (*in_it)->GetChannelID();
92 std::vector<AudioOut*>::const_iterator out_it;
95 if ( (*out_it)->GetChannelID() > max_id)
96 max_id = (*out_it)->GetChannelID();
103 void ALSAAudioDevice::Start(
void) throw(Err)
106 bool needs_start =
false;
113 int used_channels = HighestChannelID() + 1;
114 if (used_channels > mNChannels)
115 throw Err(
"ALSAAudioDevice::Start(): more inputs or outputs than requested channels.");
120 if ( HighestChannelID() + 1 != mNChannels)
134 mSndpcm = new ::SndPcm(
SampleRate(),mNReadChannels,mNWriteChannels,
Latency(),mDevice.c_str(),mDevice.c_str());
137 Err ne(
"ALSAAudioDevice::Start(): Failed to create PCM device.");
145 mReadBuf.Resize(bufSize);
146 mWriteBuf.Resize(bufSize);
147 mReadBuf.SetSize(bufSize);
148 mWriteBuf.SetSize(bufSize);
150 for (i=0; i<bufSize; i++) {
164 void ALSAAudioDevice::Stop(
void) throw(Err)
171 ALSAAudioDevice::~ALSAAudioDevice()
180 void ALSAAudioDevice::Read(Audio& audio,
const int channelID)
183 "ALSAAudioDevice::Read(): Invalid Channel ID");
185 TData* ptrA = audio.GetBuffer().GetPtr();
186 short* ptrB = mReadBuf.GetPtr() + channelID;
189 if (mChannelsRead[channelID])
190 throw Err(
"ALSAAudioDevice::Read(): Tried to read "
191 "twice from a channel in a single time frame!");
193 throw Err(
"ALSAAudioDevice::Read(): Device not configured.");
195 if (mReadBufSize==0) mReadBufSize=audio.GetSize();
197 CLAM_ASSERT(mReadBufSize==audio.GetSize(),
"ALSADevice: Inconsistent Audio size");
199 if (mReadBufSize>mSndpcm->latency)
200 throw Err(
"You are trying to read audio in blocks bigger than the latency");
202 if (mNChannelsRead == 0)
205 mSndpcm->ReadBuf(mReadBuf.GetPtr(),mReadBufSize);
211 *ptrA++ =
TData(*ptrB) / 32767.;
215 mChannelsRead[channelID] =
true;
218 if (mNChannelsRead==mNReadChannels)
222 mChannelsRead[i] =
false;
226 void ALSAAudioDevice::Write(
const Audio& audio,
const int channelID)
229 "ALSAAudioDevice::Write(): Invalid Channel ID");
231 TData* ptrA = audio.GetBuffer().GetPtr();
232 short* ptrB = mWriteBuf.GetPtr() + channelID;
237 if (mWriteBufSize==0) mWriteBufSize=audio.GetSize();
239 CLAM_ASSERT(mWriteBufSize==audio.GetSize(),
"ALSADevice Write: Inconsistent Audio size");
242 if (mWriteBufSize>mSndpcm->latency)
243 throw Err(
"You are trying to write audio in blocks bigger than the latency");
246 if (mChannelsWritten[channelID])
247 throw Err(
"ALSAAudioDevice::Write(): Tried to write "
248 "twice into a channel in a single time frame.");
250 throw Err(
"ALSAAudioDevice::Write(): Device not configured.");
255 *ptrB = (short) (32767.*(*ptrA++));
259 mChannelsWritten[channelID] =
true;
262 if (mNChannelsWritten==mNWriteChannels)
264 if (mNReadChannels==0) mSndpcm->Poll();
265 mSndpcm->WriteBuf(mWriteBuf.GetPtr(),mWriteBufSize);
267 mNChannelsWritten = 0;
269 mChannelsWritten[i] =
false;
274 class ALSAAudioDeviceList:
public AudioDeviceList
276 static ALSAAudioDeviceList sDevices;
278 ALSAAudioDeviceList()
279 :AudioDeviceList(std::string(
"alsa"))
283 snd_ctl_card_info_t *info;
285 snd_ctl_card_info_alloca(&info);
287 if (snd_card_next(&card) < 0 || card < 0)
290 std::stringstream namestr;
291 namestr <<
"hw:" << card;
292 std::string name(namestr.str());
293 if (snd_ctl_open(&handle, name.c_str(), 0) < 0)
295 if (snd_ctl_card_info(handle, info) < 0) {
296 snd_ctl_close(handle);
301 snd_ctl_pcm_next_device(handle, &dev);
304 std::stringstream dnamestr;
305 dnamestr << name <<
"," << dev;
306 std::string dname(dnamestr.str());
307 mAvailableDevices.push_back(dname.c_str());
309 std::stringstream plug;
310 plug <<
"plug" << dname;
311 mAvailableDevices.push_back(plug.str());
313 snd_ctl_close(handle);
314 if (snd_card_next(&card) < 0)
322 std::string DefaultDevice(
void)
328 const std::string& name,
const std::string& device)
330 return new ALSAAudioDevice(name,device);
334 ALSAAudioDeviceList ALSAAudioDeviceList::sDevices;