* Using snd_pcm_set_params() on a capture handle
@ 2015-10-25 6:44 Erik de Castro Lopo
2015-10-25 20:11 ` Clemens Ladisch
2015-10-26 15:26 ` Raymond Yau
0 siblings, 2 replies; 11+ messages in thread
From: Erik de Castro Lopo @ 2015-10-25 6:44 UTC (permalink / raw)
To: alsa-devel
Hi all,
I've got a simple PCM capture test program below, which is basically
a slightly tweak version of something from:
http://equalarea.com/paul/alsa-audio.html
The program uses two different methods of setting up the capture
handle; one that works (and is complex) and one that doesn't but
seems like it should (and is simple). I'm trying to figure out
why the simple one (using snd_pcm_set_params) doesn't work.
The program can be compiled and run in two ways:
gcc -Wall -O2 -DUSE_SET_PARAMS=1 alsa_capture.c -lasound -o alsa_capture
./alsa_capture
which fails with:
Read from audio interface failed (Input/output error)
and:
gcc -Wall -O2 -DUSE_SET_PARAMS=0 alsa_capture.c -lasound -o alsa_capture
./alsa_capture
which works as expected.
Questions:
* Is snd_pcm_set_params() supposed to work on capture handles (I've used
it successfully on playback handles)?
* Is my use of snd_pcm_set_params() missing something and if so what?
* If snd_pcm_set_params() is not supposed to work on capture handles
would it be possible to update the documentation to reflect that?
Thanks,
Erik
//---------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>
#include <alsa/pcm.h>
int
main (int argc, char *argv[])
{
int i;
int err;
char *buffer;
int buffer_frames = 128;
unsigned int rate = 44100;
snd_pcm_t *capture_handle;
snd_pcm_format_t format = SND_PCM_FORMAT_S32_LE;
char* device = "default";
if (argc > 1) device = argv[1];
if ((err = snd_pcm_open (&capture_handle, device, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
printf ("Cannot open audio device %s (%s)\n", device, snd_strerror (err)); exit (1) ;
}
if (USE_SET_PARAMS) {
if ((err = snd_pcm_set_params (capture_handle, format, SND_PCM_ACCESS_RW_INTERLEAVED, 2, rate, 0, 500000)) < 0) { /* 0.5sec */
printf ("Capture open error: %s\n", snd_strerror (err)); exit (1) ;
}
}
else {
snd_pcm_hw_params_t *hw_params;
if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
printf ("Cannot allocate hardware parameter structure (%s)\n", snd_strerror (err)); exit (1) ;
}
if ((err = snd_pcm_hw_params_any (capture_handle, hw_params)) < 0) {
printf ("Cannot initialize hardware parameter structure (%s)\n", snd_strerror (err)); exit (1) ;
}
if ((err = snd_pcm_hw_params_set_access (capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
printf ("cannot set access type (%s)\n", snd_strerror (err)); exit (1) ;
}
if ((err = snd_pcm_hw_params_set_format (capture_handle, hw_params, format)) < 0) {
printf ("Cannot set sample format (%s)\n", snd_strerror (err)); exit (1) ;
}
if ((err = snd_pcm_hw_params_set_rate_near (capture_handle, hw_params, &rate, 0)) < 0) {
printf ("Cannot set sample rate (%s)\n", snd_strerror (err)); exit (1) ;
}
if ((err = snd_pcm_hw_params_set_channels (capture_handle, hw_params, 2)) < 0) {
printf ("cannot set channel count (%s)\n", snd_strerror (err)); exit (1) ;
}
if ((err = snd_pcm_hw_params (capture_handle, hw_params)) < 0) {
printf ("cannot set parameters (%s)\n", snd_strerror (err)); exit (1) ;
}
snd_pcm_hw_params_free (hw_params);
}
buffer = malloc (buffer_frames * snd_pcm_format_width(format) / 8 * 2);
if ((err = snd_pcm_prepare (capture_handle)) < 0) {
printf ("cannot prepare audio interface for use (%s)\n", snd_strerror (err)); exit (1) ;
}
for (i = 0; i < 10; ++i) {
if ((err = snd_pcm_readi (capture_handle, buffer, buffer_frames)) != buffer_frames) {
printf ("Read from audio interface failed (%s)\n", snd_strerror (err)); exit (1) ;
break;
}
printf("read %d done\n", i);
}
free(buffer);
snd_pcm_close (capture_handle);
puts ("Audio interface closed");
return 0;
}
--
----------------------------------------------------------------------
Erik de Castro Lopo
http://www.mega-nerd.com/
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Using snd_pcm_set_params() on a capture handle
2015-10-25 6:44 Using snd_pcm_set_params() on a capture handle Erik de Castro Lopo
@ 2015-10-25 20:11 ` Clemens Ladisch
2015-10-26 8:47 ` Erik de Castro Lopo
2015-10-26 15:26 ` Raymond Yau
1 sibling, 1 reply; 11+ messages in thread
From: Clemens Ladisch @ 2015-10-25 20:11 UTC (permalink / raw)
To: Erik de Castro Lopo, alsa-devel
Erik de Castro Lopo wrote:
> * Is snd_pcm_set_params() supposed to work on capture handles?
Yes.
> * Is my use of snd_pcm_set_params() missing something and if so what?
No. But it does not set exactly the same parameters as the manual
hw_params calls.
Please check for differences with snd_pcm_hw_params_dump() (or look into
/proc/asound/cardX/pcm0c/sub0/hw_params).
> The program can be compiled and run in two ways:
>
> gcc -Wall -O2 -DUSE_SET_PARAMS=1 alsa_capture.c -lasound -o alsa_capture
> ./alsa_capture
>
> which fails with:
>
> Read from audio interface failed (Input/output error)
Which driver? Any messages in the system log?
> if ((err = snd_pcm_prepare (capture_handle)) < 0) {
This is done automatically by snd_pcm_hw_params().
> if ((err = snd_pcm_readi (capture_handle, buffer, buffer_frames)) != buffer_frames) {
If less than the full number of frames have been read, you get a return
value that is not an error code but a positive number.
Regards,
Clemens
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Using snd_pcm_set_params() on a capture handle
2015-10-25 20:11 ` Clemens Ladisch
@ 2015-10-26 8:47 ` Erik de Castro Lopo
2015-10-26 9:17 ` Clemens Ladisch
0 siblings, 1 reply; 11+ messages in thread
From: Erik de Castro Lopo @ 2015-10-26 8:47 UTC (permalink / raw)
To: alsa-devel
Clemens Ladisch wrote:
> > * Is my use of snd_pcm_set_params() missing something and if so what?
>
> No. But it does not set exactly the same parameters as the manual
> hw_params calls.
>
> Please check for differences with snd_pcm_hw_params_dump()
That showed some differences. The params when its working:
ACCESS: RW_INTERLEAVED
FORMAT: S32_LE
SUBFORMAT: STD
SAMPLE_BITS: 32
FRAME_BITS: 64
CHANNELS: 2
RATE: 44100
PERIOD_TIME: (5011 5012)
PERIOD_SIZE: 221
PERIOD_BYTES: 1768
PERIODS: (593 594)
BUFFER_TIME: (2972154 2972155)
BUFFER_SIZE: 131072
BUFFER_BYTES: 1048576
TICK_TIME: 0
and the one that doesn't:
ACCESS: MMAP_INTERLEAVED RW_INTERLEAVED
FORMAT: S32_LE
SUBFORMAT: STD
SAMPLE_BITS: 32
FRAME_BITS: 64
CHANNELS: 2
RATE: [44100 96000]
PERIOD_TIME: [125 1486078)
PERIOD_SIZE: [8 65536]
PERIOD_BYTES: [64 524288]
PERIODS: [2 1024]
BUFFER_TIME: (166 2972155)
BUFFER_SIZE: [16 131072]
BUFFER_BYTES: [128 1048576]
TICK_TIME: ALL
which seems rather odd!
> Which driver?
snd_usb_audio
> Any messages in the system log?
Just the connect message when the device is plugged in:
usb 1-1: new high-speed USB device number 43 using xhci_hcd
usb 1-1: New USB device found, idVendor=1235, idProduct=8016
usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 1-1: Product: Scarlett 2i2 USB
usb 1-1: Manufacturer: Focusrite
> If less than the full number of frames have been read, you get a return
> value that is not an error code but a positive number.
Its definitely an error message. I changed the code to:
if ((err = snd_pcm_readi (capture_handle, buffer, buffer_frames)) < 0) {
printf ("Read from audio interface failed (%d, %s)\n", err, snd_strerror (err));
break;
}
and that results in:
Read from audio interface failed (-5, Input/output error)
Cheers,
Erik
--
----------------------------------------------------------------------
Erik de Castro Lopo
http://www.mega-nerd.com/
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Using snd_pcm_set_params() on a capture handle
2015-10-26 8:47 ` Erik de Castro Lopo
@ 2015-10-26 9:17 ` Clemens Ladisch
2015-10-26 9:23 ` Erik de Castro Lopo
0 siblings, 1 reply; 11+ messages in thread
From: Clemens Ladisch @ 2015-10-26 9:17 UTC (permalink / raw)
To: alsa-devel
Erik de Castro Lopo wrote:
> RATE: [44100 96000]
snd_pcm_set_params() should have chosen a single rate.
Did you dump this after that call?
Regards,
Clemens
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Using snd_pcm_set_params() on a capture handle
2015-10-26 9:17 ` Clemens Ladisch
@ 2015-10-26 9:23 ` Erik de Castro Lopo
2015-10-26 9:44 ` Clemens Ladisch
0 siblings, 1 reply; 11+ messages in thread
From: Erik de Castro Lopo @ 2015-10-26 9:23 UTC (permalink / raw)
To: alsa-devel
Clemens Ladisch wrote:
> Erik de Castro Lopo wrote:
> > RATE: [44100 96000]
>
> snd_pcm_set_params() should have chosen a single rate.
> Did you dump this after that call?
Yep, the code is:
snd_pcm_format_t format = SND_PCM_FORMAT_S32_LE;
snd_pcm_hw_params_t *hw_params;
snd_output_t *output ;
unsigned int rate = 48000 ;
if ((err = snd_pcm_set_params (capture_handle, format, SND_PCM_ACCESS_RW_INTERLEAVED, 2, rate, 0, 25000)) < 0) { /* 0.5sec */
printf ("Capture open error: %s\n", snd_strerror (err));exit(1);
}
if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
printf ("Cannot allocate hardware parameter structure (%s)\n", snd_strerror (err));exit(1);
}
if ((err = snd_pcm_hw_params_any (capture_handle, hw_params)) < 0) {
printf ("Cannot initialize hardware parameter structure (%s)\n", snd_strerror (err));exit(1);
}
snd_output_stdio_attach (&output, stderr, 0) ;
snd_pcm_hw_params_dump (hw_params, output) ;
snd_output_close (output) ;
snd_pcm_hw_params_free (hw_params);
Erik
--
----------------------------------------------------------------------
Erik de Castro Lopo
http://www.mega-nerd.com/
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Using snd_pcm_set_params() on a capture handle
2015-10-26 9:23 ` Erik de Castro Lopo
@ 2015-10-26 9:44 ` Clemens Ladisch
2015-10-26 9:54 ` Erik de Castro Lopo
0 siblings, 1 reply; 11+ messages in thread
From: Clemens Ladisch @ 2015-10-26 9:44 UTC (permalink / raw)
To: alsa-devel
Erik de Castro Lopo wrote:
> Clemens Ladisch wrote:
>> Erik de Castro Lopo wrote:
>>> RATE: [44100 96000]
>>
>> snd_pcm_set_params() should have chosen a single rate.
>> Did you dump this after that call?
>
> Yep, the code is:
>
> snd_pcm_set_params (capture_handle, format, SND_PCM_ACCESS_RW_INTERLEAVED, 2, rate, 0, 25000))
> snd_pcm_hw_params_any (capture_handle, hw_params)
> snd_pcm_hw_params_dump (hw_params, output) ;
snd_pcm_hw_params_any() gets a _new_ set of parameters. You would use
it when you want to configure the device for the first time, or when you
want to reconfigure it from scratch.
To get the current parameters of the device, use snd_pcm_hw_params_current().
Regards,
Clemens
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Using snd_pcm_set_params() on a capture handle
2015-10-26 9:44 ` Clemens Ladisch
@ 2015-10-26 9:54 ` Erik de Castro Lopo
2015-10-26 11:27 ` Lars-Peter Clausen
0 siblings, 1 reply; 11+ messages in thread
From: Erik de Castro Lopo @ 2015-10-26 9:54 UTC (permalink / raw)
To: alsa-devel
Clemens Ladisch wrote:
> To get the current parameters of the device, use snd_pcm_hw_params_current().
Ah, that makes sense. Now I get:
ACCESS: RW_INTERLEAVED
FORMAT: S32_LE
SUBFORMAT: STD
SAMPLE_BITS: [0 0]
FRAME_BITS: [64 64]
CHANNELS: [2 2]
RATE: [48000 48000]
PERIOD_TIME: [6250 6250]
PERIOD_SIZE: [300 300]
PERIOD_BYTES: [0 0]
PERIODS: [0 0]
BUFFER_TIME: [0 0]
BUFFER_SIZE: [1200 1200]
BUFFER_BYTES: [9600 9600]
TICK_TIME: [0 0]
Why is SAMPLE_BITS == [0 0], even though the format is S32_LE?
Erik
--
----------------------------------------------------------------------
Erik de Castro Lopo
http://www.mega-nerd.com/
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Using snd_pcm_set_params() on a capture handle
2015-10-26 9:54 ` Erik de Castro Lopo
@ 2015-10-26 11:27 ` Lars-Peter Clausen
0 siblings, 0 replies; 11+ messages in thread
From: Lars-Peter Clausen @ 2015-10-26 11:27 UTC (permalink / raw)
To: alsa-devel
On 10/26/2015 10:54 AM, Erik de Castro Lopo wrote:
> Clemens Ladisch wrote:
>
>> To get the current parameters of the device, use snd_pcm_hw_params_current().
>
> Ah, that makes sense. Now I get:
>
> ACCESS: RW_INTERLEAVED
> FORMAT: S32_LE
> SUBFORMAT: STD
> SAMPLE_BITS: [0 0]
> FRAME_BITS: [64 64]
> CHANNELS: [2 2]
> RATE: [48000 48000]
> PERIOD_TIME: [6250 6250]
> PERIOD_SIZE: [300 300]
> PERIOD_BYTES: [0 0]
> PERIODS: [0 0]
> BUFFER_TIME: [0 0]
> BUFFER_SIZE: [1200 1200]
> BUFFER_BYTES: [9600 9600]
> TICK_TIME: [0 0]
>
> Why is SAMPLE_BITS == [0 0], even though the format is S32_LE?
That appears to be a bug in snd_pcm_hw_params_current() which does simply
not set SAMPLE_BITS.
- Lars
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Using snd_pcm_set_params() on a capture handle
2015-10-25 6:44 Using snd_pcm_set_params() on a capture handle Erik de Castro Lopo
2015-10-25 20:11 ` Clemens Ladisch
@ 2015-10-26 15:26 ` Raymond Yau
2015-10-26 20:00 ` Erik de Castro Lopo
1 sibling, 1 reply; 11+ messages in thread
From: Raymond Yau @ 2015-10-26 15:26 UTC (permalink / raw)
To: Erik de Castro Lopo; +Cc: ALSA Development Mailing List
>
> I've got a simple PCM capture test program below, which is basically
> a slightly tweak version of something from:
>
> http://equalarea.com/paul/alsa-audio.html
>
>
> The program uses two different methods of setting up the capture
> handle; one that works (and is complex) and one that doesn't but
> seems like it should (and is simple). I'm trying to figure out
> why the simple one (using snd_pcm_set_params) doesn't work.
>
> The program can be compiled and run in two ways:
>
> gcc -Wall -O2 -DUSE_SET_PARAMS=1 alsa_capture.c -lasound -o
alsa_capture
> ./alsa_capture
>
> which fails with:
>
> Read from audio interface failed (Input/output error)
>
> and:
>
> gcc -Wall -O2 -DUSE_SET_PARAMS=0 alsa_capture.c -lasound -o
alsa_capture
> ./alsa_capture
>
> which works as expected.
>
> Questions:
>
> * Is snd_pcm_set_params() supposed to work on capture handles (I've used
> it successfully on playback handles)?
>
> * Is my use of snd_pcm_set_params() missing something and if so what?
Do your sound card driver support 0.5 second buffer?
>
> * If snd_pcm_set_params() is not supposed to work on capture handles
> would it be possible to update the documentation to reflect that?
>
>
> int buffer_frames = 128;
> unsigned int rate = 44100;
> snd_pcm_t *capture_handle;
> snd_pcm_format_t format = SND_PCM_FORMAT_S32_LE;
> if (USE_SET_PARAMS) {
> if ((err = snd_pcm_set_params (capture_handle, format,
SND_PCM_ACCESS_RW_INTERLEAVED, 2, rate, 0, 500000)) < 0) { /* 0.5sec */
> printf ("Capture open error: %s\n", snd_strerror
(err)); exit (1) ;
> }
> }
> else {
> snd_pcm_hw_params_t *hw_params;
>
> if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
> printf ("Cannot allocate hardware parameter
structure (%s)\n", snd_strerror (err)); exit (1) ;
> }
>
> if ((err = snd_pcm_hw_params_any (capture_handle,
hw_params)) < 0) {
> printf ("Cannot initialize hardware parameter
structure (%s)\n", snd_strerror (err)); exit (1) ;
> }
>
> if ((err = snd_pcm_hw_params_set_access (capture_handle,
hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
> printf ("cannot set access type (%s)\n",
snd_strerror (err)); exit (1) ;
> }
>
> if ((err = snd_pcm_hw_params_set_format (capture_handle,
hw_params, format)) < 0) {
> printf ("Cannot set sample format (%s)\n",
snd_strerror (err)); exit (1) ;
> }
>
> if ((err = snd_pcm_hw_params_set_rate_near
(capture_handle, hw_params, &rate, 0)) < 0) {
> printf ("Cannot set sample rate (%s)\n",
snd_strerror (err)); exit (1) ;
> }
>
> if ((err = snd_pcm_hw_params_set_channels
(capture_handle, hw_params, 2)) < 0) {
> printf ("cannot set channel count (%s)\n",
snd_strerror (err)); exit (1) ;
> }
>
> if ((err = snd_pcm_hw_params (capture_handle, hw_params))
< 0) {
> printf ("cannot set parameters (%s)\n",
snd_strerror (err)); exit (1) ;
> }
If you does not specify period, period_size or buffer size, period_time or
buffer_time before calling snd_pcm_hw_params , you have to use use those
hw_params_get_* functions after calling snd_pcm_hw_params to get back those
values
>
> buffer = malloc (buffer_frames * snd_pcm_format_width(format) / 8
* 2);
>
> if ((err = snd_pcm_prepare (capture_handle)) < 0) {
> printf ("cannot prepare audio interface for use (%s)\n",
snd_strerror (err)); exit (1) ;
> }
>
> for (i = 0; i < 10; ++i) {
> if ((err = snd_pcm_readi (capture_handle, buffer,
buffer_frames)) != buffer_frames) {
> printf ("Read from audio interface failed
(%s)\n", snd_strerror (err)); exit (1) ;
> break;
> }
> printf("read %d done\n", i);
> }
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Using snd_pcm_set_params() on a capture handle
2015-10-26 15:26 ` Raymond Yau
@ 2015-10-26 20:00 ` Erik de Castro Lopo
2015-10-27 5:01 ` Raymond Yau
0 siblings, 1 reply; 11+ messages in thread
From: Erik de Castro Lopo @ 2015-10-26 20:00 UTC (permalink / raw)
To: alsa-devel
Raymond Yau wrote:
> Do your sound card driver support 0.5 second buffer?
If it doesn't, it should return an error instead of just not working.
Erik
--
----------------------------------------------------------------------
Erik de Castro Lopo
http://www.mega-nerd.com/
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Using snd_pcm_set_params() on a capture handle
2015-10-26 20:00 ` Erik de Castro Lopo
@ 2015-10-27 5:01 ` Raymond Yau
0 siblings, 0 replies; 11+ messages in thread
From: Raymond Yau @ 2015-10-27 5:01 UTC (permalink / raw)
To: ALSA Development Mailing List
>
> > Do your sound card driver support 0.5 second buffer?
>
> If it doesn't, it should return an error instead of just not working.
The application have to use snd_pcm_get_params after calling
snd_pcmset_params
snd_pcm_get_params ( snd_pcm_t * pcm,
snd_pcm_uframes_t * buffer_size,
snd_pcm_uframes_t * period_size
)
Get the transfer size parameters in a simple way.
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2015-10-27 5:01 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-10-25 6:44 Using snd_pcm_set_params() on a capture handle Erik de Castro Lopo
2015-10-25 20:11 ` Clemens Ladisch
2015-10-26 8:47 ` Erik de Castro Lopo
2015-10-26 9:17 ` Clemens Ladisch
2015-10-26 9:23 ` Erik de Castro Lopo
2015-10-26 9:44 ` Clemens Ladisch
2015-10-26 9:54 ` Erik de Castro Lopo
2015-10-26 11:27 ` Lars-Peter Clausen
2015-10-26 15:26 ` Raymond Yau
2015-10-26 20:00 ` Erik de Castro Lopo
2015-10-27 5:01 ` Raymond Yau
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.