Created
May 1, 2009 05:59
-
-
Save albanpeignier/104902 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
A Minimal Capture Program | |
This program opens an audio interface for capture, configures it for | |
stereo, 16 bit, 44.1kHz, interleaved conventional read/write | |
access. Then its reads a chunk of random data from it, and exits. It | |
isn't meant to be a real program. | |
From on Paul David's tutorial : http://equalarea.com/paul/alsa-audio.html | |
Fixes rate and buffer problems | |
sudo apt-get install libasound2-dev | |
gcc -o alsa-record-example -lasound alsa-record-example.c && ./alsa-record-example hw:0 | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <alsa/asoundlib.h> | |
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_hw_params_t *hw_params; | |
snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE; | |
if ((err = snd_pcm_open (&capture_handle, argv[1], SND_PCM_STREAM_CAPTURE, 0)) < 0) { | |
fprintf (stderr, "cannot open audio device %s (%s)\n", | |
argv[1], | |
snd_strerror (err)); | |
exit (1); | |
} | |
fprintf(stdout, "audio interface opened\n"); | |
if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) { | |
fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", | |
snd_strerror (err)); | |
exit (1); | |
} | |
fprintf(stdout, "hw_params allocated\n"); | |
if ((err = snd_pcm_hw_params_any (capture_handle, hw_params)) < 0) { | |
fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", | |
snd_strerror (err)); | |
exit (1); | |
} | |
fprintf(stdout, "hw_params initialized\n"); | |
if ((err = snd_pcm_hw_params_set_access (capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { | |
fprintf (stderr, "cannot set access type (%s)\n", | |
snd_strerror (err)); | |
exit (1); | |
} | |
fprintf(stdout, "hw_params access setted\n"); | |
if ((err = snd_pcm_hw_params_set_format (capture_handle, hw_params, format)) < 0) { | |
fprintf (stderr, "cannot set sample format (%s)\n", | |
snd_strerror (err)); | |
exit (1); | |
} | |
fprintf(stdout, "hw_params format setted\n"); | |
if ((err = snd_pcm_hw_params_set_rate_near (capture_handle, hw_params, &rate, 0)) < 0) { | |
fprintf (stderr, "cannot set sample rate (%s)\n", | |
snd_strerror (err)); | |
exit (1); | |
} | |
fprintf(stdout, "hw_params rate setted\n"); | |
if ((err = snd_pcm_hw_params_set_channels (capture_handle, hw_params, 2)) < 0) { | |
fprintf (stderr, "cannot set channel count (%s)\n", | |
snd_strerror (err)); | |
exit (1); | |
} | |
fprintf(stdout, "hw_params channels setted\n"); | |
if ((err = snd_pcm_hw_params (capture_handle, hw_params)) < 0) { | |
fprintf (stderr, "cannot set parameters (%s)\n", | |
snd_strerror (err)); | |
exit (1); | |
} | |
fprintf(stdout, "hw_params setted\n"); | |
snd_pcm_hw_params_free (hw_params); | |
fprintf(stdout, "hw_params freed\n"); | |
if ((err = snd_pcm_prepare (capture_handle)) < 0) { | |
fprintf (stderr, "cannot prepare audio interface for use (%s)\n", | |
snd_strerror (err)); | |
exit (1); | |
} | |
fprintf(stdout, "audio interface prepared\n"); | |
buffer = malloc(128 * snd_pcm_format_width(format) / 8 * 2); | |
fprintf(stdout, "buffer allocated\n"); | |
for (i = 0; i < 10; ++i) { | |
if ((err = snd_pcm_readi (capture_handle, buffer, buffer_frames)) != buffer_frames) { | |
fprintf (stderr, "read from audio interface failed (%s)\n", | |
err, snd_strerror (err)); | |
exit (1); | |
} | |
fprintf(stdout, "read %d done\n", i); | |
} | |
free(buffer); | |
fprintf(stdout, "buffer freed\n"); | |
snd_pcm_close (capture_handle); | |
fprintf(stdout, "audio interface closed\n"); | |
exit (0); | |
} |
- "128": the frames count, declared at top of the program.
- "2" : one for each stereo channel.
- "snd_pcm_format_width(format)": bit width of
format
, in bits count. - " / 8": to get bytes instead of bits (the result of snd_pcm_format_width).
I read the doc: about "snd_pcm_readi", it say it reads interleaved frames when non-blocking
mode is set.
so im wondering:
- in which place do you set the
non-blocking
mode ? - if this is only a audio channel, why it is "interleaved" ? In my poor understanding i can understand we need a interleaved chunk when we mix them with video frames, in other words we interleave a video chunk and a audio chunk togheter in single row, so i cant understand how you read a interleaved audio frame.
:)
The following line (in the loop) could lead to crash due to missing %d :)
fprintf (stderr, "read from audio interface failed (%s)\n",
err, snd_strerror (err));
@christiansalazar https://alsa-project.org/wiki/PCM_Ring_Buffer
Ring buffer organization
Interleaved access
Interleaved format is like this (C means channel sample):
C0 C1 C2 C3 C0 C1 C2 C3 ....
Non-Interleaved access
Non-Interleaved format is like this (C means channel sample):
C0 C0 C0 C0 ................ C1 C1 C1 C1 ............. C2 C2 C2 C2 ............... C3 C3 C3 C3 ...........
It's like separate mono buffers. Note that offsets of buffers might not be continuous (there might be a gap between channel areas).
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In the following line:
Thanks