1.LAME介绍

  lame是一个有名的开源mp3编码库,这篇文章将会介绍如何调用lame库的接口编码出mp3。

2.lame库编译

  对于lame库,你有两个安装的方法,第一是使用apt-get安装,使用下面的命令。

sudo apt-get install libmp3lame-dev

  这样安装的lame库可能并不是最新版本的。如果你想安装最新版本的lame库,可以选择在官网下载。

  1. 官网下载:https://sourceforge.net/projects/lame/files/lame/
  2. gitx下载:
wget https://nchc.dl.sourceforge.net/project/lame/lame/3.100/lame-3.100.tar.gz
  1. 交叉编译
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的介绍

  1. mp3(MPEG Layer III) :这种格式在生活中很常见,但是mp3有很多种参数,这里讨论一下mp3编码所必须知道的一些参数。
  2. 采样率(sampleRate):采样率越高声音的还原度越好。
  3. 比特率(bitrate):每秒钟的数据量,越高音质越好。
  4. 声道数(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知识介绍相关推荐

  1. linux下lamealsa进行音频流操作(三)alsa音频编程教程

    1. ALSA音频编程介绍   ALSA 代表高级 Linux 声音架构.它由一组内核驱动程序.一个应用程序编程接口 (API) 库和用于在 Linux 下支持声音的实用程序组成.在本文中,我简要概述 ...

  2. linux怎么打开.o文件,Linux下文件I/O操作的相关知识

    Linux文件I/O主要指的是文件的输入输出,很多初学者对文件的I/O不是很了解,Linux文件I/O的操作较多,下面小编就给大家详细介绍下Linux文件I/O. linux 文件I/O教程(1) 一 ...

  3. Linux下对文件的操作及添加新用户

    Linux下对文件的操作及添加新用户 一.对文件的操作 1.打包压缩文件 2.解压缩文件 3.对文件操作的其他命令 二.创建新用户 一.对文件的操作 1.打包压缩文件 2.解压缩文件 3.对文件操作的 ...

  4. Linux下如何避免误操作执行 rm

    转载自 Linux下如何避免误操作执行 rm 最近IT圈子流行着一个段子: 某个蠢萌的程序员,不小心在公司的服务器上输入了 rm -rf/ 指令,结果......现在还没出狱呢. 当然,绝大部分程序员 ...

  5. linux 下卸载nginx的操作步骤

    linux 下卸载nginx的操作步骤 1.执行命令,看nginx是否在运行 ps -ef|grep nginx 2.如上图,发现nginx是在运行状态,所以停止nginx服务 注意,要进入到ngin ...

  6. linux下git的相关操作指令

    linux下git的相关操作指令 git版本管理工具 1.克隆仓库git clone "url" 2.上传2.1标记:告诉git工具需要管理那些文件了git add [filena ...

  7. linux下C语言编程操作数据库(sqlite3)

    前言:C语言中通过调用 sqlite 的函数接口来实现对数据库的管理(创建数据库.创建表格.插入数据.查询.数据.删除数据等),掌握sqlite数据库的语法,以及sqlite提供的函数接口,那么在li ...

  8. linux命令grep和find怎么用,Linux下find和grep常用命令及区别介绍

    在使用linux时,经常需要进行文件查找.其中查找的命令主要有find和grep.两个命令是有区别的. 区别: (1)find命令是根据文件的属性进行查找,如文件名,文件大小,所有者,所属组,是否为空 ...

  9. linux grep的信息不全,Linux下grep显示前后几行信息方法介绍

    本文研究的主要是Linux下grep显示前后几行信息的相关内容,具体如下. 标准unix/linux下的grep通过下面參数控制上下文 grep -C 5 foo file 显示file文件里匹配fo ...

  10. linux mysql c语言编程,在Linux下通过C语言操作MySQL数据库

    2010年1月27日 晚 22:10 作者:longyun(http://www.linuxdiyf.com/mailto:mtd527@gmail.com) 续:小弟最近想学习数据库,并想开发一个简 ...

最新文章

  1. php 判定pc端與移動端
  2. java运行环境变量及自定义变量
  3. qt自定义窗口添加父窗口后,显示不出来
  4. 怎样快速画出一个正方体_图形与几何---正方体
  5. Python Tricks(六)—— 删除一个可迭代序列中等于某值的全部元素
  6. [技术帖] js中,双引号,引发的问题
  7. 用友U872《合同管理》模块操作手册
  8. 嵌入式系统应用开发—FPGA开发板—一位全加器仿真测试
  9. LabVIEW的编程-程序框图入门笔记
  10. Lora入门(1)—— PingPong测试(CubeMX篇)
  11. 太赞了!靠着这份面试题跟答案
  12. C# 通用方法MD5计算
  13. VisualStudio20008快捷键大全
  14. 计算机开机一直无法访问,关于电脑开机一直正在启动的详细处理方法
  15. 虚拟机能ping通,但是telnet某个端口却不行
  16. ICESat2数据hd5文件的预处理
  17. datagrid之修改
  18. Python用Tkinterk开发小球弹弹弹
  19. ARM 指令 对齐访问等
  20. 基于单片机的地铁(公交)无线控制报站系统设计 地铁报站系统设计 公交报站系统设计

热门文章

  1. c语言程序设混分,若要补位上单怎么选?混分选白起,求稳选吕布,想C位直接选他!...
  2. 记一次HDD(机械硬盘)突然出故障,然后数据恢复以及更换HDD的过程
  3. macOS 控件教程(1)
  4. 一、什么是统一社会信用代码
  5. 分布式拒绝服务(DDoS)攻击原理介绍和防范措施
  6. Unity优化——模型合并
  7. BZOJ 3162:独钓寒江雪
  8. 从逻辑学中的偷换概念谈起
  9. hdu2201:熊猫阿波的故事
  10. Java 6.22练习-----模拟物流快递系统程序设计