From: David Henningsson <david.henningsson@canonical.com>
To: Shane Loretz <a10.shane@gmail.com>
Cc: alsa-devel@alsa-project.org
Subject: Re: Segmentation fault during snd_pcm_prepare()
Date: Wed, 15 May 2013 07:14:07 +0200 [thread overview]
Message-ID: <5193199F.1000900@canonical.com> (raw)
In-Reply-To: <CAJAps6CVLcknWGDZrbewfTyUS3ra7tmwtv3oK0NHWBbqQY8dOw@mail.gmail.com>
On 05/15/2013 06:47 AM, Shane Loretz wrote:
> I'm interested in writing an application using alsa. I've chosen to
> explore the library by writing a program to echo sound data from a
> microphone back to my speakers.
>
> I'm only interested in mono sound.
>
> When running this program, the first call to snd_pcm_readi() fails,
> and a segmentation fault occurs inside of the snd_pcm_prepare()
> function according to a backtrace from gdb. I suspect I'm not
> allocating enough space for the pointer capdata, but I don't know how
> to determine how much space I need.
S16_LE = 16 bits = 2 bytes per frame.
So if you're trying to read num_frames frames, the amount allocated must
be at least num_frames * 2. (Also multiplied with the number of
channels, which is 1 in this case.)
Also snd_pcm_recover is recommended to use to recover from error (rather
than snd_pcm_prepare).
>
> Here is the code
>
> // Test out the alsa library
> //
> #include <alsa/asoundlib.h>
> #include <cstdio>
> #include <unistd.h>
>
> bool getMonoDevice(snd_pcm_t *pcm_handle, snd_pcm_stream_t stream,
> unsigned int rate, int periods, snd_pcm_uframes_t periodsize);
>
> int main()
> {
> snd_pcm_t *pcm_handle_read;
> snd_pcm_t *pcm_handle_write;
> snd_pcm_stream_t stream = SND_PCM_STREAM_CAPTURE;
>
> unsigned int rate = 44100;
> int periods = 2;
> snd_pcm_uframes_t periodsize = 8192;
>
> if (!getMonoDevice(pcm_handle_write,
> SND_PCM_STREAM_PLAYBACK,rate,periods,periodsize))
> {
> fprintf(stderr, "Error couldn't open speakers\n");
> return -1;
> }
> if (!getMonoDevice(pcm_handle_read,
> SND_PCM_STREAM_CAPTURE,rate,periods,periodsize))
> {
> fprintf(stderr, "Error couldn't open microphone\n");
> return -1;
> }
>
> //read frames from device
> //and echo them out
> unsigned char *capdata;
> int pcmreturn;
> int num_frames;
> int error;
>
> capdata = (unsigned char *)malloc(periodsize);
> num_frames = periodsize * 2;
> while (true)
> {
> while ((pcmreturn = snd_pcm_readi(pcm_handle_read, capdata,
> num_frames)) < 0)
> {
> usleep(10);
> error = snd_pcm_prepare(pcm_handle_read);
> if (error < 0)
> {
> fprintf(stderr, "Unrecoverable mic error
> %s\n",snd_strerror(error));
> return error;
> }
> }
> while ((pcmreturn = snd_pcm_writei(pcm_handle_write, capdata,
> num_frames)) < 0)
> {
> usleep(10);
> error = snd_pcm_prepare(pcm_handle_write);
> if (error < 0)
> {
> fprintf(stderr, "Unrecoverable speaker error
> %s\n",snd_strerror(error));
> return error;
> }
> }
> }
>
> //stop pcm device and drop pending frames
> snd_pcm_drop(pcm_handle_read);
> snd_pcm_drain(pcm_handle_read);
> snd_pcm_drop(pcm_handle_write);
> snd_pcm_drain(pcm_handle_write);
> }
>
>
> bool getMonoDevice(snd_pcm_t *pcm_handle, snd_pcm_stream_t stream,
> unsigned int rate, int periods, snd_pcm_uframes_t periodsize)
> {
> snd_pcm_hw_params_t *hwparams;
>
> char *pcm_name;
>
> pcm_name = strdup("plughw:0,0");
>
> snd_pcm_hw_params_alloca(&hwparams);
>
> if (snd_pcm_open(&pcm_handle, pcm_name, stream, 0) < 0)
> {
> fprintf(stderr, "Error opening PCM device %s\n", pcm_name);
> return false;
> }
>
> if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0 )
> {
> fprintf(stderr, "Can not configure this PCM device.\n");
> return false;
> }
>
> unsigned int exact_rate;
> int dir;
>
> if (snd_pcm_hw_params_set_access(pcm_handle, hwparams,
> SND_PCM_ACCESS_RW_INTERLEAVED) < 0)
> {
> fprintf(stderr, "Error setting access.\n");
> return false;
> }
>
> if (snd_pcm_hw_params_set_format(pcm_handle, hwparams,
> SND_PCM_FORMAT_S16_LE) < 0)
> {
> fprintf(stderr, "Error setting format.\n");
> return false;
> }
>
> exact_rate = rate;
> if (snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams,
> &exact_rate, 0) < 0)
> {
> fprintf(stderr, "Error setting rate.\n");
> return false;
> }
> if (rate != exact_rate)
> {
> fprintf(stderr, "The rate %d is not supported by your
> hardware.\n Using %d Hz instead.\n", rate, exact_rate);
> }
>
> //Configure mono sound
> if (snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 1) < 0)
> {
> fprintf(stderr, "Error setting channels.\n");
> return false;
> }
>
> if (snd_pcm_hw_params_set_periods(pcm_handle, hwparams, periods, 0) < 0)
> {
> fprintf(stderr, "Error setting periods.\n");
> return false;
> }
>
> if (snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams,
> (periodsize * periods) >> 2) < 0 )
> {
> fprintf(stderr, "Error setting buffersize.\n");
> return false;
> }
>
> if (snd_pcm_hw_params(pcm_handle, hwparams) < 0)
> {
> fprintf(stderr, "Error setting HW params.\n");
> return false;
> }
>
> //device is finally configured
> return true;
> }
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
>
--
David Henningsson, Canonical Ltd.
https://launchpad.net/~diwic
prev parent reply other threads:[~2013-05-15 5:13 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-05-15 4:47 Segmentation fault during snd_pcm_prepare() Shane Loretz
2013-05-15 5:14 ` David Henningsson [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5193199F.1000900@canonical.com \
--to=david.henningsson@canonical.com \
--cc=a10.shane@gmail.com \
--cc=alsa-devel@alsa-project.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.