文章目录
- 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
#endifstatic 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;} elseres = 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)