* Audio passthrough on Pandaboard using ALSA API
@ 2014-02-28 8:47 Vadim Izmalkov
2014-02-28 21:53 ` Maarten Baert
0 siblings, 1 reply; 2+ messages in thread
From: Vadim Izmalkov @ 2014-02-28 8:47 UTC (permalink / raw)
To: alsa-devel
Hello
I created simple application that makes audio pass-through (from analog input to analog output),
After 2-10 seconds get error like:
AlsaPassthrough: pcm.c:693: snd_pcm_close: Assertion `pcm' failed.
or
write to audio interface failed (Broken pipe)
Seems I have problem with buffer size/time or somethink like that.
Parameters used:
Buffer - 100 ms / 4800 frames / 19200 bytes
Period - 10 ms / 480 frames / 1920 bytes
Buffer length used 19200 bytes.
char buffer[19200];
Write/read function used as follow
snd_pcm_readi(pcm, buffer, frames);
snd_pcm_writei(pcm, buffer, frames);
Have somebody any suggestion?
Segments of the code you can find bellow.
Alsamixer settings:
amixer cset name='Analog Left Capture Route' 'Headset Mic'
amixer cset name='Analog Right Capture Route' 'Headset Mic'
amixer cset name='MUX_UL00' 'AMic0'
amixer cset name='MUX_UL01' 'AMic1'
amixer cset name='Headset Left Playback' 'HS DAC'
amixer cset name='Headset Right Playback' 'HS DAC'
amixer cset name='Headset Playback Volume' 100
amixer cset name='DL1 Media' 120
Structure for the devices:
typedef struct
{
char *deviceName;
snd_pcm_t *pcm;
snd_pcm_hw_params_t *hwParams;
snd_pcm_stream_t stream;
snd_pcm_access_t access;
snd_pcm_format_t format;
snd_pcm_uframes_t frames;
int mode;
unsigned int sampleRate;
unsigned int bufferTime;
unsigned int periodTime;
unsigned int channels;
} pcmDevice_t;
Parameters for capture:
pcmDevice_t* initRecordDevice()
{
pcmDevice_t *device;
device = malloc(sizeof(pcmDevice_t));
device->deviceName = strdup("plughw:0,0");
device->stream = SND_PCM_STREAM_CAPTURE;
device->access = SND_PCM_ACCESS_RW_INTERLEAVED;
device->format = SND_PCM_FORMAT_S16_LE;
device->mode = 0; //SND_PCM_ASYNC; //SND_PCM_NONBLOCK;
device->sampleRate = 48000;
device->bufferTime = 100 * 1000; // 100 ms
device->periodTime = 10 * 1000; // 20ms
device->channels = 2;
return device;
}
Parameters for playback:
pcmDevice_t* initPlaybackDevice()
{
pcmDevice_t *device;
device = malloc(sizeof(pcmDevice_t));
device->deviceName = strdup("plughw:0,0");
device->stream = SND_PCM_STREAM_PLAYBACK;
device->access = SND_PCM_ACCESS_RW_INTERLEAVED;
device->format = SND_PCM_FORMAT_S16_LE;
device->mode = 0; //SND_PCM_ASYNC; //SND_PCM_NONBLOCK;
device->sampleRate = 48000;
device->bufferTime = 100 * 1000; // 100 ms
device->periodTime = 10 * 1000; // 20ms
device->channels = 2;
return device;
}
Setup devices:
int setupDevice(pcmDevice_t *device)
{
int err;
/* Open PCM. The last parameter of this function is the mode. */
/* If this is set to 0, the standard mode is used. Possible */
/* other values are SND_PCM_NONBLOCK and SND_PCM_ASYNC. */
/* If SND_PCM_NONBLOCK is used, read / write access to the */
/* PCM device will return immediately. If SND_PCM_ASYNC is */
/* specified, SIGIO will be emitted whenever a period has */
/* been completely processed by the soundcard. */
if ((err = snd_pcm_open(&device->pcm, device->deviceName, device->stream, device->mode)) < 0) {
fprintf (stderr, "cannot open audio device %s (%s)\n", device->deviceName, snd_strerror (err));
exit (1);
}
if ((err = snd_pcm_hw_params_malloc (&device->hwParams)) < 0) {
fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", snd_strerror (err));
exit (1);
}
if ((err = snd_pcm_hw_params_any (device->pcm, device->hwParams)) < 0) {
fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", snd_strerror (err));
exit (1);
}
if ((err = snd_pcm_hw_params_set_access (device->pcm, device->hwParams, device->access)) < 0) {
fprintf (stderr, "cannot set access type (%s)\n", snd_strerror (err));
exit (1);
}
if ((err = snd_pcm_hw_params_set_format (device->pcm, device->hwParams, device->format)) < 0) {
fprintf (stderr, "cannot set sample format (%s)\n", snd_strerror (err));
exit (1);
}
if ((err = snd_pcm_hw_params_set_buffer_time_near (device->pcm, device->hwParams, &device->bufferTime, NULL)) < 0) {
fprintf (stderr, "cannot set buffer size (%s)\n", snd_strerror (err));
exit (1);
} else {
/* Set buffer size (in frames). The resulting latency is given by */
/* latency = periodsize * periods / (rate * bytes_per_frame) */
snd_pcm_hw_params_get_buffer_size(device->hwParams, &device->frames);
}
if ((err = snd_pcm_hw_params_set_period_time_near (device->pcm, device->hwParams, &device->periodTime, NULL)) < 0) {
fprintf (stderr, "cannot set period size (%s)\n", snd_strerror (err));
exit (1);
}
if ((err = snd_pcm_hw_params_set_rate_near (device->pcm, device->hwParams, &device->sampleRate, NULL)) < 0) {
fprintf (stderr, "cannot set sample rate (%s)\n", snd_strerror (err));
exit (1);
}
if ((err = snd_pcm_hw_params_set_channels (device->pcm, device->hwParams, device->channels)) < 0) {
fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err));
exit (1);
}
/* Apply HW parameter settings to */
/* PCM device and prepare device */
if ((err = snd_pcm_hw_params (device->pcm, device->hwParams)) < 0) {
fprintf (stderr, "cannot set parameters (%s)\n", snd_strerror (err));
exit (1);
}
snd_pcm_hw_params_free (device->hwParams);
if ((err = snd_pcm_prepare (device->pcm)) < 0) {
fprintf (stderr, "cannot prepare audio interface for use (%s)\n", snd_strerror (err));
exit (1);
}
return 0;
}
Main:
main (int argc, char *argv[])
{
int i;
int err;
char buf[4800*4];
snd_pcm_t *capture_handle;
snd_pcm_hw_params_t *hw_params;
snd_pcm_uframes_t frames;
pcmDevice_t *pcmRecord;
pcmDevice_t *pcmPlayback;
pcmRecord = initRecordDevice();
pcmPlayback = initPlaybackDevice();
printf("\n----------- RECORD DEVICE -----------\n");
setupDevice(pcmRecord);
showConfig(pcmRecord);
printf("\n---------- PLAYBACK DEVICE ----------\n");
setupDevice(pcmPlayback);
showConfig(pcmPlayback);
for (i = 0; i < 100; ++i) {
/* Read num_frames frames from the PCM device */
/* pointed to by pcm_handle to buffer capdata. */
/* Returns the number of frames actually read. */
//if((err = snd_pcm_readi (pcmRecord->pcm, buf, pcmRecord->frames)) != pcmRecord->frames) {
if((err = snd_pcm_readi (pcmRecord->pcm, buf, 480)) != 480) {
fprintf (stderr, "read from audio interface failed (%s)\n", snd_strerror (err));
exit (1);
}
/* Write num_frames frames from buffer data to */
/* the PCM device pointed to by pcm_handle. */
/* Returns the number of frames actually written. */
if((err = snd_pcm_writei (pcmPlayback->pcm, buf, pcmRecord->frames)) != pcmRecord->frames) {
fprintf (stderr, "write to audio interface failed (%s)\n", snd_strerror (err));
exit (1);
}
}
snd_pcm_close (capture_handle);
exit (0);
}?
Best
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: Audio passthrough on Pandaboard using ALSA API
2014-02-28 8:47 Audio passthrough on Pandaboard using ALSA API Vadim Izmalkov
@ 2014-02-28 21:53 ` Maarten Baert
0 siblings, 0 replies; 2+ messages in thread
From: Maarten Baert @ 2014-02-28 21:53 UTC (permalink / raw)
To: alsa-devel, Vadimi
Your application does not handle overruns and underruns (EPIPE indicates
that either of these is happening). It also doesn't have any drift
correction, so overruns/underruns are to be expected (the sample rate of
the capture and playback stream is not guaranteed to be exactly matched).
By the way, there is a tool called 'alsaloop' (from alsa-utils) which
does exactly the same thing, but with drift correction and more options ...
Maarten Baert
On 28/02/14 09:47, Vadim Izmalkov wrote:
> Hello
>
> I created simple application that makes audio pass-through (from analog input to analog output),
>
> After 2-10 seconds get error like:
> AlsaPassthrough: pcm.c:693: snd_pcm_close: Assertion `pcm' failed.
> or
> write to audio interface failed (Broken pipe)
>
> Seems I have problem with buffer size/time or somethink like that.
> Parameters used:
> Buffer - 100 ms / 4800 frames / 19200 bytes
> Period - 10 ms / 480 frames / 1920 bytes
>
> Buffer length used 19200 bytes.
> char buffer[19200];
>
> Write/read function used as follow
> snd_pcm_readi(pcm, buffer, frames);
> snd_pcm_writei(pcm, buffer, frames);
>
> Have somebody any suggestion?
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2014-02-28 21:53 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-28 8:47 Audio passthrough on Pandaboard using ALSA API Vadim Izmalkov
2014-02-28 21:53 ` Maarten Baert
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).