linux下lamealsa进行音频流操作(一)lame知识介绍
1.LAME介紹
??lame是一個有名的開源mp3編碼庫,這篇文章將會介紹如何調用lame庫的接口編碼出mp3。
2.lame庫編譯
??對于lame庫,你有兩個安裝的方法,第一是使用apt-get安裝,使用下面的命令。
sudo apt-get install libmp3lame-dev??這樣安裝的lame庫可能并不是最新版本的。如果你想安裝最新版本的lame庫,可以選擇在官網下載。
??按照上序流程依次執行,arm-linux為交叉編譯工具鏈,根據編譯條件修改,最后在/lame-3.100/_install生成目標文件
3.MP3的介紹
比特率控制模式: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知识介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vue单页面应用初始加载登录页_6 种
- 下一篇: android 通知写法_Android