天天看點

Linux下音頻開發: 讀取聲霸卡PCM資料儲存到檔案(alsa-lib庫)

一、環境介紹

系統: ubuntu18.04 (64位)

聲霸卡: 電腦自帶

二、功能介紹

通過alsa-lib庫讀取電腦聲霸卡的PCM資料儲存到檔案。

在ubuntu系統上安裝alsa-lib庫方法:

sudo apt-get install libasound2-dev      

如果是在其他發行版linux系統上或者需要在嵌入式linux系統上使用alsa-lib庫,可以下載下傳alsa-lib源碼包,自行編譯。

開源ALSA架構的官網位址:

https://www.alsa-project.org/wiki/Main_Page
Linux下音頻開發: 讀取聲霸卡PCM資料儲存到檔案(alsa-lib庫)

三、擷取本機可用的聲霸卡裝置

擷取聲霸卡可以使用arecord -L指令。

在ubuntu系統下如果沒有這個指令,直接根據提示安裝一個即可。

    示例:   一般  hw:0 或者 default 表示預設聲霸卡裝置。

wbyq@wbyq:/mnt/hgfs/linux-share-dir/linux_c/linux_pcm_save$ arecord -L
 
default
 
    Playback/recording through the PulseAudio sound server
 
null
 
    Discard all samples (playback) or generate zero samples (capture)
 
pulse
 
    PulseAudio Sound Server
 
sysdefault:CARD=AudioPCI
 
    Ensoniq AudioPCI, ES1371 DAC2/ADC
 
    Default Audio Device
 
front:CARD=AudioPCI,DEV=0
 
    Ensoniq AudioPCI, ES1371 DAC2/ADC
 
    Front speakers
 
iec958:CARD=AudioPCI,DEV=0
 
    Ensoniq AudioPCI, ES1371 DAC2/ADC
 
    IEC958 (S/PDIF) Digital Audio Output
 
dmix:CARD=AudioPCI,DEV=0
 
    Ensoniq AudioPCI, ES1371 DAC2/ADC
 
    Direct sample mixing device
 
dsnoop:CARD=AudioPCI,DEV=0
 
    Ensoniq AudioPCI, ES1371 DAC2/ADC
 
    Direct sample snooping device
 
hw:CARD=AudioPCI,DEV=0
 
    Ensoniq AudioPCI, ES1371 DAC2/ADC
 
    Direct hardware device without any conversions
 
plughw:CARD=AudioPCI,DEV=0
 
    Ensoniq AudioPCI, ES1371 DAC2/ADC
 
    Hardware device with all software conversions      

四、示例代碼

參考文檔:

https://users.suse.com/~mana/alsa090_howto.html
/*
 進行音頻采集,采集pcm資料并直接儲存pcm資料
 音頻參數: 
     聲道數:       2
     采樣位數:  16bit、LE格式
     采樣頻率:  44100Hz
*/
#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>
#include <signal.h>
 
FILE *pcm_data_file=NULL;
int run_flag=0;
void exit_sighandler(int sig)
{
    run_flag=1;
}
 
int main(int argc, char *argv[])
{
    int i;
    int err;
    char *buffer;
    int buffer_frames = 128;
    unsigned int rate = 44100;// 常用的采樣頻率: 44100Hz 、16000HZ、8000HZ、48000HZ、22050HZ
    snd_pcm_t *capture_handle;// 一個指向PCM裝置的句柄
    snd_pcm_hw_params_t *hw_params; //此結構包含有關硬體的資訊,可用于指定PCM流的配置
    
    /*注冊信号捕獲退出接口*/
    signal(2,exit_sighandler);
 
    /*PCM的采樣格式在pcm.h檔案裡有定義*/
    snd_pcm_format_t format=SND_PCM_FORMAT_S16_LE; // 采樣位數:16bit、LE格式
 
    /*打開音頻采集卡硬體,并判斷硬體是否打開成功,若打開失敗則列印出錯誤提示*/
    if ((err = snd_pcm_open (&capture_handle, argv[1],SND_PCM_STREAM_CAPTURE,0))<0) 
    {
        printf("無法打開音頻裝置: %s (%s)\n",  argv[1],snd_strerror (err));
        exit(1);
    }
    printf("音頻接口打開成功.\n");
 
    /*建立一個儲存PCM資料的檔案*/
    if((pcm_data_file = fopen(argv[2], "wb")) == NULL)
    {
        printf("無法建立%s音頻檔案.\n",argv[2]);
        exit(1);
    } 
    printf("用于錄制的音頻檔案已打開.\n");
 
    /*配置設定硬體參數結構對象,并判斷是否配置設定成功*/
    if((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) 
    {
        printf("無法配置設定硬體參數結構 (%s)\n",snd_strerror(err));
        exit(1);
    }
    printf("硬體參數結構已配置設定成功.\n");
    
    /*按照預設設定對硬體對象進行設定,并判斷是否設定成功*/
    if((err=snd_pcm_hw_params_any(capture_handle,hw_params)) < 0) 
    {
        printf("無法初始化硬體參數結構 (%s)\n", snd_strerror(err));
        exit(1);
    }
    printf("硬體參數結構初始化成功.\n");
 
    /*
        設定資料為交叉模式,并判斷是否設定成功
        interleaved/non interleaved:交叉/非交叉模式。
        表示在多聲道資料傳輸的過程中是采樣交叉的模式還是非交叉的模式。
        對多聲道資料,如果采樣交叉模式,使用一塊buffer即可,其中各聲道的資料交叉傳輸;
        如果使用非交叉模式,需要為各聲道分别配置設定一個buffer,各聲道資料分别傳輸。
    */
    if((err = snd_pcm_hw_params_set_access (capture_handle,hw_params,SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) 
    {
        printf("無法設定通路類型(%s)\n",snd_strerror(err));
        exit(1);
    }
    printf("通路類型設定成功.\n");
 
    /*設定資料編碼格式,并判斷是否設定成功*/
    if ((err=snd_pcm_hw_params_set_format(capture_handle, hw_params,format)) < 0) 
    {
        printf("無法設定格式 (%s)\n",snd_strerror(err));
        exit(1);
    }
    fprintf(stdout, "PCM資料格式設定成功.\n");
 
    /*設定采樣頻率,并判斷是否設定成功*/
    if((err=snd_pcm_hw_params_set_rate_near (capture_handle,hw_params,&rate,0))<0) 
    {
        printf("無法設定采樣率(%s)\n",snd_strerror(err));
        exit(1);
    }
    printf("采樣率設定成功\n");
 
    /*設定聲道,并判斷是否設定成功*/
    if((err = snd_pcm_hw_params_set_channels(capture_handle, hw_params,2)) < 0) 
    {
        printf("無法設定聲道數(%s)\n",snd_strerror(err));
        exit(1);
    }
    printf("聲道數設定成功.\n");
 
    /*将配置寫入驅動程式中,并判斷是否配置成功*/
    if ((err=snd_pcm_hw_params (capture_handle,hw_params))<0) 
    {
        printf("無法向驅動程式設定參數(%s)\n",snd_strerror(err));
        exit(1);
    }
    printf("參數設定成功.\n");
 
    /*使采集卡處于空閑狀态*/
    snd_pcm_hw_params_free(hw_params);
 
    /*準備音頻接口,并判斷是否準備好*/
    if((err=snd_pcm_prepare(capture_handle))<0) 
    {
        printf("無法使用音頻接口 (%s)\n",snd_strerror(err));
        exit(1);
    }
    printf("音頻接口準備好.\n");
 
    /*配置一個資料緩沖區用來緩沖資料*/
    buffer=malloc(128*snd_pcm_format_width(format)/8*2);
    printf("緩沖區配置設定成功.\n");
 
    /*開始采集音頻pcm資料*/
    printf("開始采集資料...\n");
    while(1) 
    {
        /*從聲霸卡裝置讀取一幀音頻資料*/
        if((err=snd_pcm_readi(capture_handle,buffer,buffer_frames))!=buffer_frames) 
        {
              printf("從音頻接口讀取失敗(%s)\n",snd_strerror(err));
              exit(1);
        }
        /*寫資料到檔案*/
        fwrite(buffer,(buffer_frames*2),sizeof(short),pcm_data_file);
        
        if(run_flag)
        {
            printf("停止采集.\n");
            break;
        }
    }
 
    /*釋放資料緩沖區*/
    free(buffer);
 
    /*關閉音頻采集卡硬體*/
    snd_pcm_close(capture_handle);
 
    /*關閉檔案流*/
    fclose(pcm_data_file);
    return 0;
}
       

編譯方法:

gcc linux_pcm_save.c -lasound      

運作方法:

./a.out hw:0 123.pcm      

錄制過程中如果想要結束錄制,直接按下Ctrl+C即可。

成功之後,會在目前目錄下生成123.pcm檔案。 

五、播放PCM資料

Windows下可以使用audacity軟體進行播放PCM裸流資料。

或者通過ffplay工具(安裝ffmpeg會帶上這個工具)。

ffplay -ar 44100 -channels 2 -f s16le -i 123.pcm      

audacity軟體下載下傳位址:

https://download.csdn.net/download/xiaolong1126626497/12252685
Linux下音頻開發: 讀取聲霸卡PCM資料儲存到檔案(alsa-lib庫)
Linux下音頻開發: 讀取聲霸卡PCM資料儲存到檔案(alsa-lib庫)
Linux下音頻開發: 讀取聲霸卡PCM資料儲存到檔案(alsa-lib庫)

​​

繼續閱讀