日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux下lamealsa进行音频流操作(一)lame知识介绍

發布時間:2023/12/16 linux 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux下lamealsa进行音频流操作(一)lame知识介绍 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.LAME介紹

??lame是一個有名的開源mp3編碼庫,這篇文章將會介紹如何調用lame庫的接口編碼出mp3。

2.lame庫編譯

??對于lame庫,你有兩個安裝的方法,第一是使用apt-get安裝,使用下面的命令。

sudo apt-get install libmp3lame-dev

??這樣安裝的lame庫可能并不是最新版本的。如果你想安裝最新版本的lame庫,可以選擇在官網下載。

  • 官網下載:https://sourceforge.net/projects/lame/files/lame/
  • gitx下載:
  • wget https://nchc.dl.sourceforge.net/project/lame/lame/3.100/lame-3.100.tar.gz
  • 交叉編譯
  • cd lame-3.100 mkdir _install ./configure --host=csky-linux --prefix=xxx/lame-3.100/_install make make install

    ??按照上序流程依次執行,arm-linux為交叉編譯工具鏈,根據編譯條件修改,最后在/lame-3.100/_install生成目標文件

    3.MP3的介紹

  • mp3(MPEG Layer III) :這種格式在生活中很常見,但是mp3有很多種參數,這里討論一下mp3編碼所必須知道的一些參數。
  • 采樣率(sampleRate):采樣率越高聲音的還原度越好。
  • 比特率(bitrate):每秒鐘的數據量,越高音質越好。
  • 聲道數(channels):聲道的數量,通常只有單聲道和雙聲道,雙聲道即所謂的立體聲。
    比特率控制模式:ABR、VBR、CBR,這3中模式含義很容易查詢到,不在贅述。
  • 4.MPEG Layer III

    ?? MPEG有幾個版本的協議,不同版本的協議能夠支持的參數能力是不同的。編碼庫的使用者必須清楚不同版本的區別才能正確的設置參數。

    ??有以下3個版本的協議,MPEG1、MPEG2、MPEG2.5。其中MPEG2.5是非官方的標準,但是流傳廣泛,所以基本也都支持。他們的區別主要集中在支持的比特率和采樣率不同。

    4.1 采樣率支持(Hz)

    4.2 比特率支持(bit/s)

    5.編碼流程

    ??使用lame庫只需要包含lame.h頭文件,編碼mp3基本上遵循以下的流程:

    5.1 初始化編碼參數

    lame_init:初始化一個編碼參數的數據結構,給使用者用來設置參數。

    5.2 設置編碼參數

    lame_set_in_samplerate:設置被輸入編碼器的原始數據的采樣率。
    lame_set_out_samplerate:設置最終mp3編碼輸出的聲音的采樣率,如果不設置則和輸入采樣率一樣。
    lame_set_num_channels :設置被輸入編碼器的原始數據的聲道數。
    lame_set_mode :設置最終mp3編碼輸出的聲道模式,如果不設置則和輸入聲道數一樣。參數是枚舉,STEREO代表雙聲道,MONO代表單聲道。
    lame_set_VBR:設置比特率控制模式,默認是CBR,但是通常我們都會設置VBR。參數是枚舉,vbr_off代表CBR,vbr_abr代表ABR(因為ABR不常見,所以本文不對ABR做講解)vbr_mtrh代表VBR。
    lame_set_brate:設置CBR的比特率,只有在CBR模式下才生效。
    lame_set_VBR_mean_bitrate_kbps:設置VBR的比特率,只有在VBR模式下才生效。
    其中每個參數都有默認的配置,如非必要可以不設置。這里只介紹了幾個關鍵的設置接口,還有其他的設置接口可以參考lame.h(lame的文檔里只有命令行程序的用法,沒有庫接口的用法)。

    5.3 初始化編碼器

    lame_init_params:根據上面設置好的參數建立編碼器

    5.4 編碼PCM數據

    lame_encode_buffer或lame_encode_buffer_interleaved:將PCM數據送入編碼器,獲取編碼出的mp3數據。這些數據寫入文件就是mp3文件。
    ??其中lame_encode_buffer輸入的參數中是雙聲道的數據分別輸入的,lame_encode_buffer_interleaved輸入的參數中雙聲道數據是交錯在一起輸入的。具體使用哪個需要看采集到的數據是哪種格式的,不過現在的設備采集到的數據大部分都是雙聲道數據是交錯在一起。
    ??單聲道輸入只能使用lame_encode_buffer,把單聲道數據當成左聲道數據傳入,右聲道傳NULL即可。
    ??調用這兩個函數時需要傳入一塊內存來獲取編碼器出的數據,這塊內存的大小lame給出了一種建議的計算方式:采樣率/20+7200。

    5.5 結束編碼

    lame_encode_flush:結束編碼,獲取編碼出的結束數據。這部分數據也需要寫入mp3文件。

    5.6 銷毀編碼器

    lame_close銷毀編碼器,釋放資源。

    6.示例代碼

    6.1 wav轉mp3示例程序代碼

    /* gcc -I /usr/include/lame/ lame_test.c -lmp3lame -o lame_test -lm */ #include <stdio.h> #include <stdlib.h> #include <lame.h>#define INBUFSIZE 4096 #define MP3BUFSIZE (int) (1.25 * INBUFSIZE) + 7200int encode(char* inPath, char* outPath) {int status = 0;lame_global_flags* gfp;int ret_code;FILE* infp;FILE* outfp;short* input_buffer;int input_samples;char* mp3_buffer;int mp3_bytes;gfp = lame_init();if (gfp == NULL) {printf("lame_init failed/n");status = -1;goto exit;}ret_code = lame_init_params(gfp);if (ret_code < 0) {printf("lame_init_params returned %d/n",ret_code);status = -1;goto close_lame;}infp = fopen(inPath, "rb");outfp = fopen(outPath, "wb");input_buffer = (short*)malloc(INBUFSIZE*2);mp3_buffer = (char*)malloc(MP3BUFSIZE);do{input_samples = fread(input_buffer, 2, INBUFSIZE, infp);//fprintf(stderr, "input_samples is %d./n", input_samples);mp3_bytes = lame_encode_buffer_interleaved(gfp, input_buffer,input_samples/2,mp3_buffer, MP3BUFSIZE);//fprintf(stderr, "mp3_bytes is %d./n", mp3_bytes);if (mp3_bytes < 0){printf("lame_encode_buffer_interleaved returned %d/n", mp3_bytes);status = -1;goto free_buffers;} else if(mp3_bytes > 0){fwrite(mp3_buffer, 1, mp3_bytes, outfp);}}while (input_samples == INBUFSIZE);mp3_bytes = lame_encode_flush(gfp, mp3_buffer, sizeof(mp3_buffer));if (mp3_bytes > 0) {printf("writing %d mp3 bytes/n", mp3_bytes);fwrite(mp3_buffer, 1, mp3_bytes, outfp);}free_buffers:free(mp3_buffer);free(input_buffer);fclose(outfp);fclose(infp);close_lame:lame_close(gfp);exit:return status; } int main(int argc, char** argv) {if (argc < 3) {printf("usage: lame_test rawinfile mp3outfile/n");}encode(argv[1], argv[2]);return 0; }

    6.2 錄音轉MP3格式程序代碼

    /* gcc -I /usr/include/lame/ -lmp3lame -o mp3_record mp3_record.c -lm */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <signal.h> #include <sys/ioctl.h> #include <memory.h> #include <linux/soundcard.h>#include "lame.h"#define BUFF_SIZE 512 #define INBUFF_SIZE 4096 #define MP3BUFF_SIZE (int) (1.25 * INBUFF_SIZE) + 7200static int run=1;static void stop(int signum) {fprintf(stderr, "exit/n");run=0; }int SetFormat(int fd, unsigned int bit, unsigned int channel, unsigned int hz) {int ioctl_val;/* set bit format */ioctl_val = bit;if(ioctl(fd, SNDCTL_DSP_SETFMT, &ioctl_val) < 0){fprintf(stderr, "Set fmt to bit %d failed:%s/n", bit, strerror(errno));return -1;}if (ioctl_val != bit) {fprintf(stderr, "do not support bit %d, supported %d/n", bit,ioctl_val);return (-1);}/*set channel */ioctl_val = channel;if ((ioctl(fd, SNDCTL_DSP_CHANNELS, &ioctl_val)) == -1){fprintf(stderr, "Set Audio Channels %d failed:%s/n", channel, strerror(errno));return (-1);}if (ioctl_val != channel){fprintf(stderr, "do not support channel %d,supported %d/n", channel, ioctl_val);return (-1);}/*set speed */ioctl_val = hz;if (ioctl(fd, SNDCTL_DSP_SPEED, &ioctl_val) == -1) {fprintf(stderr, "Set speed to %d failed:%s/n", hz, strerror(errno));return (-1);}if (ioctl_val != hz) {fprintf(stderr, "do not support speed %d,supported is %d/n", hz,ioctl_val);return (-1);}return 0; }int main(int argc, char **argv) {int status =0;int snd_f;int fd_f;lame_global_flags* gfp;short *input_buff;char *mp3_buff;if(argc !=2){fprintf(stderr, "useage: ./mp3_record test.mp3/n");return -1;}signal(SIGINT,stop);if((snd_f = open("/dev/dsp", O_RDONLY)) < 0){fprintf(stderr, "open audio device error: %s", strerror(errno));status = -1;goto exit;}if((fd_f = open(argv[1], O_CREAT | O_WRONLY)) < 0){fprintf(stderr, "open file error: %s", strerror(errno));status = -1;goto exit;}if (SetFormat(snd_f, 16, 2, 44100) < 0){fprintf(stderr, "cannot set /dev/dsp in bit 16, channel 2, speed 44100/n");status = -1;goto exit;}gfp = lame_init();if (gfp == NULL) {printf("lame_init failed/n");status = -1;goto exit;}int ret_code = lame_init_params(gfp);if (ret_code < 0){printf("lame_init_params returned %d/n",ret_code);status = -1;goto close_lame;}input_buff = (short *)malloc(INBUFF_SIZE*2);mp3_buff = (char *)malloc(MP3BUFF_SIZE);int samples;int mp3_bytes;int write_bytes;int n=100;while(run){//while(n>0){//n--;//fprintf(stderr, "n is %d./n", n);memset(input_buff, 0 , INBUFF_SIZE*2);memset(mp3_buff, 0 , MP3BUFF_SIZE);samples = read(snd_f, input_buff, INBUFF_SIZE*2);if (samples < 0){perror("read sound device failed");status = -1;goto free_buffers;}// fprintf(stderr, "samples is %d./n", samples);mp3_bytes = lame_encode_buffer_interleaved(gfp, input_buff, samples/4, mp3_buff, MP3BUFF_SIZE);//fprintf(stderr, "mp3_bytes is %d./n", mp3_bytes);if (mp3_bytes < 0){printf("lame_encode_buffer_interleaved returned %d/n", mp3_bytes);status = -1;goto free_buffers;}write_bytes = write(fd_f, mp3_buff, mp3_bytes);//fprintf(stderr, "write_bytes is %d./n", write_bytes);if(write_bytes < 0){perror("write sound data file failed");status = -1;goto free_buffers;}}mp3_bytes = lame_encode_flush(gfp, mp3_buff, sizeof(mp3_buff));if (mp3_bytes > 0){fprintf(stderr, "writing %d mp3 bytes/n", mp3_bytes);if(write(fd_f, mp3_buff, mp3_bytes) <0)fprintf(stderr, "'writing mp3 bytes error/n");}else{fprintf(stderr, "writing mp3 bytes 0/n");}free_buffers:free(mp3_buff);mp3_buff = NULL;free(input_buff);input_buff = NULL;close(snd_f);close(fd_f);close_lame:lame_close(gfp);exit:return status; }

    總結

    以上是生活随笔為你收集整理的linux下lamealsa进行音频流操作(一)lame知识介绍的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。