ALSA C语言使用

#ALSA 播放代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <math.h>
#include <alsa/asoundlib.h>

#define SAMPLE_RATE (44100)
#define CHANNELS (2)
#define FRAME_SIZE (2 * CHANNELS)
// snd_pcm_hw_params_alloca snd_pcm_hw_params_set_format
int audio_play(const char *filename)
{
    int rc;
    int size;

    unsigned int val;

    int dir = 0;
    snd_pcm_uframes_t frames;
    char *buffer;

    int fd;
    int err;

    fd = open(filename, O_RDONLY);

    snd_pcm_t *handle;
    //以播放模式打开设备
    rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
    if (rc < 0)
    {
        fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc));
        exit(1);
    }
    //配置硬件参数结构体
    snd_pcm_hw_params_t *params;

    //params申请内存
    snd_pcm_hw_params_malloc(&params);

    //使用pcm设备初始化hwparams
    err = snd_pcm_hw_params_any(handle, params);
    if (err < 0)
    {
        fprintf(stderr, "Can not configure this PCM device: %s\n", snd_strerror(err));
        exit(1);
    }

    //设置多路数据在buffer中的存储方式
    //SND_PCM_ACCESS_RW_INTERLEAVED每个周期(period)左右声道的数据交叉存放
    err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
    if (err < 0)
    {
        fprintf(stderr, "Failed to set PCM device to interleaved: %s\n", snd_strerror(err));
        exit(1);
    }

    //设置16位采样格式,S16为有符号16位,LE是小端模式
    snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE
        err = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
    if (err < 0)
    {
        fprintf(stderr, "Failed to set PCM device to 16-bit signed PCM: %s\n", snd_strerror(err));
        exit(1);
    }

    //设置声道数,双声道
    err = snd_pcm_hw_params_set_channels(handle, params, CHANNELS);
    if (err < 0)
    {
        fprintf(stderr, "Failed to set PCM device to mono: %s\n", snd_strerror(err));
        exit(1);
    }

    //采样率44.1KHZ
    val = SAMPLE_RATE;
    //设置采样率,如果采样率不支持,会用硬件支持最接近的采样率
    err = snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);
    if (err < 0)
    {
        fprintf(stderr, "Failed to set PCM device to sample rate =%d: %s\n", val, snd_strerror(err));
        exit(1);
    }

    unsigned int buffer_time, period_time;
    //获取最大的缓冲时间,buffer_time单位为us,500000us=0.5s
    snd_pcm_hw_params_get_buffer_time_max(params, &buffer_time, 0);
    if (buffer_time > 500000)
        buffer_time = 500000;

    //设置缓冲时间
    err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, 0);
    if (err < 0)
    {
        fprintf(stderr, "Failed to set PCM device to buffer time =%d: %s\n", buffer_time, snd_strerror(err));
        exit(1);
    }

    period_time = buffer_time / 2;
    //设置周期时间
    err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, 0);
    if (err < 0)
    {
        fprintf(stderr, "Failed to set PCM device to period time =%d: %s\n", period_time, snd_strerror(err));
        exit(1);
    }

    snd_pcm_uframes_t buffer_size;
    snd_pcm_hw_params_get_buffer_size_max(params, &buffer_size);
    snd_pcm_hw_params_set_buffer_size_near(handle, params, &buffer_size);

    snd_pcm_uframes_t period_size = buffer_size / 4;
    snd_pcm_hw_params_set_period_size_near(handle, params, &period_size, 0);

    //让这些参数作用于PCM设备
    rc = snd_pcm_hw_params(handle, params);
    if (rc < 0)
    {
        fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc));
        exit(1);
    }

    int bit = snd_pcm_format_physical_width(format);
    snd_pcm_hw_params_get_period_size(params, &frames, &dir);
    // 1 frame = channels * sample_size.
    size = frames * FRAME_SIZE; /* 2 bytes/sample, 1 channels */
    buffer = (char *)malloc(size);

    while (1)
    {
        rc = read(fd, buffer, size);
        if (rc == 0)
        {
            fprintf(stderr, "end of file on input\n");
            break;
        }
        else if (rc != size)
        {
            fprintf(stderr, "short read: read %d bytes\n", rc);
        }
        rc = snd_pcm_writei(handle, buffer, rc / FRAME_SIZE);
        if (rc == -EPIPE)
        {
            fprintf(stderr, "underrun occurred\n");
            err = snd_pcm_prepare(handle);
            if (err < 0)
            {
                fprintf(stderr, "can not recover from underrun: %s\n", snd_strerror(err));
            }
        }
        else if (rc < 0)
        {
            fprintf(stderr, "error from writei: %s\n", snd_strerror(rc));
        }
        else if (rc != (int)frames)
        {
            fprintf(stderr, "short write, write %d frames\n", rc);
        }
    }
    snd_pcm_drain(handle);
    snd_pcm_close(handle);
    free(buffer);
    close(fd);
    return 0;
}

#ALSA 录音代码

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在 Ubuntu 中调节 ALSA 音量可以使用 alsamixer 命令行工具。您可以按照以下步骤进行操作: 1. 打开终端并输入命令 alsamixer。 2. 使用左右箭头键选择 Master 频道,然后使用上下箭头键来调整音量。 3. 如果您需要调节其他频道的音量,可以使用 F6 键来切换到其他频道列表。 4. 如果您想要保存您的设置,可以在退出 alsamixer 之前按下 Esc 键。这将打开一个选项来保存您的音量设置。 如果您想要以编程方式调节 ALSA 音量,可以使用 ALSA 库。您需要包含 alsa/asoundlib.h 头文件,并使用以下代码片段: ```c #include <alsa/asoundlib.h> int main() { long volume, max_volume; snd_mixer_t *handle; snd_mixer_selem_id_t *sid; const char *card = "default"; const char *selem_name = "Master"; // 打开混音器 snd_mixer_open(&handle, 0); snd_mixer_attach(handle, card); snd_mixer_selem_register(handle, NULL, NULL); snd_mixer_load(handle); // 获取 Master 频道的音量 snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_index(sid, 0); snd_mixer_selem_id_set_name(sid, selem_name); snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid); snd_mixer_selem_get_playback_volume_range(elem, &volume, &max_volume); snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_MONO, &volume); // 设置 Master 频道的音量,改变音量范围的值即可 snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_MONO, volume + 10); // 清理并关闭混音器 snd_mixer_close(handle); return 0; } ``` 此代码将打开默认 ALSA 设备的混音器,并获取 Master 频道的音量。然后,它将增加音量值(在此示例中增加了 10),并将其设置回 Master 频道。最后,它将清理并关闭混音器。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小分享

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值