Linux基于ALSA的声音录制

简介

linux环境使用ALSA实现声音录制,保存pcm到本地文件。

代码

void AudioCapture::run()
{
    qDebug() << "AudioCapture start";

    snd_pcm_t *pcm_st_ = nullptr;
    std::string device_name = "default";
    int ret = snd_pcm_open(&pcm_st_, device_name.c_str(), SND_PCM_STREAM_CAPTURE, 0);
    if(ret < 0)
    {
        qDebug("error capture snd_pcm_open %s\n", device_name.c_str());
        return ;
    }

    snd_pcm_hw_params_t *param = nullptr;
    snd_pcm_hw_params_malloc(&param);
    snd_pcm_hw_params_any(pcm_st_, param);

    //设置参数
    unsigned int sample_rate = 16000;
    int channel = 1;
    snd_pcm_format_t pcmFormat = SND_PCM_FORMAT_S16_LE;

    ret = snd_pcm_hw_params_set_access(pcm_st_, param, SND_PCM_ACCESS_RW_INTERLEAVED);
    if(ret < 0)
    {
        qDebug("snd_pcm_hw_params_set_access SND_PCM_ACCESS_RW_INTERLEAVED\n");
        return;
    }

    ret = snd_pcm_hw_params_set_format(pcm_st_, param, pcmFormat);
    if(ret < 0)
    {
        qDebug("snd_pcm_hw_params_set_format SND_PCM_FORMAT_S16_LE\n");
        return;
    }
    ret = snd_pcm_hw_params_set_channels(pcm_st_, param, channel);
    if(ret < 0)
    {
        qDebug("snd_pcm_hw_params_set_channels\n");
        return;
    }

    int dir = 0;
    ret = snd_pcm_hw_params_set_rate_near(pcm_st_, param, &sample_rate, &dir);
    if(ret < 0)
    {
        qDebug("snd_pcm_hw_params_set_rate_near %d\n", sample_rate);
        return;
    }

    //设置缓存采样点数
    dir = 0;
    snd_pcm_uframes_t frames = 512;
    ret = snd_pcm_hw_params_set_period_size_near(pcm_st_, param, &frames, &dir);
    if(ret < 0)
    {
        qDebug("snd_pcm_hw_params_set_period_size_near\n");
        return;
    }

    snd_pcm_uframes_t buffer_frames =  frames ;
    ret = snd_pcm_hw_params_set_buffer_size_near(pcm_st_, param, &buffer_frames);
    if(ret < 0)
    {
        qDebug("snd_pcm_hw_params_set_buffer_size_near\n");
        return;
    }

    ret = snd_pcm_hw_params(pcm_st_, param);
    if(ret < 0)
    {
        qDebug("snd_pcm_hw_params\n");
        return;
    }

    // 设置缓存buffer 2倍大小  frames*2字节(单采样点16bit)*声道数
    int bufferSize = frames * channel * 2;
    uint8_t *audio_buffer = (uint8_t *)malloc(bufferSize * 2);
    if(! audio_buffer)
    {
        qDebug("malloc audio buffer\n");
        return;
    }

    //创建pcm文件
    FILE *file = fopen("./16000_1_s16.pcm", "wb");
    if(!file)
    {
        qDebug("fopen pcm error\n");
        m_isRun = false;
    }

    // 开始捕捉
    snd_pcm_start(pcm_st_);

    // 读取音频数据
    while (m_isRun)
    {
        // 阻塞读取一次数据
        /**
         * if the blocking behaviour was selected and it is running, then routine waits until all requested frames are filled
         * the returned number of frames can be less only a signal or underrun occurred
         */
        int readFrames = snd_pcm_readi(pcm_st_, audio_buffer, frames);
        if(readFrames == -EPIPE)
        {
            ret = snd_pcm_prepare(pcm_st_);
            if(ret < 0)
            {
                qDebug("failed to recover form overrun");
            }

        }
        else if(ret < 0)
        {
            qDebug("error from read:%s\n", snd_strerror(ret));
            return;
        }

        //处理数据
        int readSize = readFrames * 2 * channel;
        fwrite(audio_buffer, readSize, 1, file);
    }

    // 释放硬件参数内存
    snd_pcm_hw_params_free(param);
    // 关闭捕捉设备
    snd_pcm_close(pcm_st_);

    //关闭文件
    fclose(file);

    if(audio_buffer)
    {
        free(audio_buffer);
        audio_buffer = nullptr;
    }
    qDebug() << "AudioCapture stop";
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

你是周小哥啊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值