文章目录
-
- alsa设备文件
-
- /dev/snd/
- /sys/class/sound
- /proc/asound
- alsa-lib
-
- 示例1
- alsa-utils
- alsa-tools
- alsa-plugins
- 参考
alsa设备文件
/dev/snd/
alsa设备文件目录位于,/dev/snd,如下所示
root@xboard:~#ls /dev/snd -l
total 0
drwxr-xr-x 2 root root 60 Nov 6 2023 by-path
crw-rw---- 1 root audio 116, 4 Nov 6 2023 controlC0
crw-rw---- 1 root audio 116, 3 Nov 6 2023 pcmC0D0c
crw-rw---- 1 root audio 116, 2 Nov 6 2023 pcmC0D0p
crw-rw---- 1 root audio 116, 33 Nov 6 2023 timer
其中:
- controlC0 用于声卡的控制,例如通道选择,音效控制等
- pcmC0D0c 用于录音的pcm设备
- pcmC0D0p 用于播放的pcm设备
- timer 作为定时器
有的还有: - /dev/snd/seq用于音序
- /dev/snd/mixerCXDX用于mixer
- /dev/snd/midiCXDX 用于原始MIDI
https://alsa-project.org/wiki/ALSA_Library_API
/sys/class/sound
root@xboard:~# ls /sys/class/sound/ -l
total 0
lrwxrwxrwx 1 root root 0 Nov 6 2023 card0 -> ../../devices/platform/sound/sound/card0
lrwxrwxrwx 1 root root 0 Nov 6 2023 controlC0 -> ../../devices/platform/sound/sound/card0/controlC0
lrwxrwxrwx 1 root root 0 Nov 6 2023 pcmC0D0c -> ../../devices/platform/sound/sound/card0/pcmC0D0c
lrwxrwxrwx 1 root root 0 Nov 6 2023 pcmC0D0p -> ../../devices/platform/sound/sound/card0/pcmC0D0p
lrwxrwxrwx 1 root root 0 Nov 6 2023 timer -> ../../devices/virtual/sound/timer
/proc/asound
root@xboard:~# ls /proc/asound/ -l
total 0
dr-xr-xr-x 4 root root 0 Jan 1 00:24 card0
-r--r--r-- 1 root root 0 Jan 1 00:24 cards
-r--r--r-- 1 root root 0 Jan 1 00:24 devices
-r--r--r-- 1 root root 0 Jan 1 00:24 pcm
lrwxrwxrwx 1 root root 5 Jan 1 00:24 sgtl5000 -> card0
-r--r--r-- 1 root root 0 Jan 1 00:24 timers
-r--r--r-- 1 root root 0 Jan 1 00:24 version
https://www.alsa-project.org/wiki/Main_Page
https://www.alsa-project.org/main/index.php/Download
alsa-lib
在线API接口,
在线demo示例
示例1
/*
* This small demo sends a simple sinusoidal wave to your speakers.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <errno.h>
#include <getopt.h>
#include "../include/asoundlib.h"
#include <sys/time.h>
#include <math.h>
#ifndef ESTRPIPE
#define ESTRPIPE ESPIPE
#endif
static char *device = "plughw:0,0"; /* playback device */
static snd_pcm_format_t format = SND_PCM_FORMAT_S16; /* sample format */
static unsigned int rate = 44100; /* stream rate */
static unsigned int channels = 1; /* count of channels */
static unsigned int buffer_time = 500000; /* ring buffer length in us */
static unsigned int period_time = 100000; /* period time in us */
static double freq = 440; /* sinusoidal wave frequency in Hz */
static int verbose = 0; /* verbose flag */
static int resample = 1; /* enable alsa-lib resampling */
static int period_event = 0; /* produce poll event after each period */
static snd_pcm_sframes_t buffer_size;
static snd_pcm_sframes_t period_size;
static snd_output_t *output = NULL;
static void generate_sine(const snd_pcm_channel_area_t *areas,
snd_pcm_uframes_t offset,
int count, double *_phase)
{
static double max_phase = 2. * M_PI;
double phase = *_phase;
double step = max_phase*freq/(double)rate;
unsigned char *samples[channels];
int steps[channels];
unsigned int chn;
int format_bits = snd_pcm_format_width(format);
unsigned int maxval = (1 << (format_bits - 1)) - 1;
int bps = format_bits / 8; /* bytes per sample */
int phys_bps = snd_pcm_format_physical_width(format) / 8;
int big_endian = snd_pcm_format_big_endian(format) == 1;
int to_unsigned = snd_pcm_format_unsigned(format) == 1;
int is_float = (format == SND_PCM_FORMAT_FLOAT_LE ||
format == SND_PCM_FORMAT_FLOAT_BE);
/* verify and prepare the contents of areas */
for (chn = 0; chn < channels; chn++) {
if ((areas[chn].first % 8) != 0) {
printf("areas[%u].first == %u, aborting...\n", chn, areas[chn].first);
exit(EXIT_FAILURE);
}
samples[chn] = /*(signed short *)*/(((unsigned char *)areas[chn].addr) + (areas[chn].first / 8));
if ((areas[chn].step % 16) != 0) {
printf("areas[%u].step == %u, aborting...\n", chn, areas[chn].step);
exit(EXIT_FAILURE);
}
steps[chn] = areas[chn].step / 8;
samples[chn] += offset * steps[chn];
}
/* fill the channel areas */
while (count-- > 0) {
union {
float f;
int i;
} fval;
int res, i;
if (is_float) {
fval.f = sin(phase);
res = fval.i;
} else
res = sin(phase) * maxval;
if (to_unsigned)
res ^= 1U << (format_bits - 1);
for (chn = 0; chn < channels; chn++) {
/* Generate data in native endian format */
if (big_endian) {
for (i = 0; i < bps; i++)
*(samples[chn] + phys_bps - 1 - i) = (res >> i * 8) & 0xff;
} else {
for (i = 0; i < bps; i++)
*(samples[chn] + i) = (res >> i * 8) & 0xff;
}
samples[chn] += steps[chn];
}
phase += step;
if (phase >= max_phase)
phase -= max_phase;
}
*_phase = phase;
}
static int set_hwparams(snd_pcm_t *handle,
snd_pcm_hw_params_t *params,
snd_pcm_access_t access)
{
unsigned int rrate;
snd_pcm_uframes_t size;
int err, dir;
/* choose all parameters */
err = snd_pcm_hw_params_any(handle, params);
if (err < 0) {
printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err));
return err;
}
/* set hardware resampling */
err = snd_pcm_hw_params_set_rate_resample(handle, params, resample);
if (err < 0) {
printf("Resampling setup failed for playback: %s\n", snd_strerror(err));
return err;
}
/* set the interleaved read/write format */
err = snd_pcm_hw_params_set_access(handle, params, access);
if (err < 0) {
printf("Access type not available for playback: %s\n", snd_strerror(err));
return err;
}
/* set the sample format */
err = snd_pcm_hw_params_set_format(handle, params, format);
if (err < 0) {
printf("Sample format not available for playback: %s\n", snd_strerror(err));
return err;
}
/* set the count of channels */
err = snd_pcm_hw_params_set_channels(handle, params, channels)