MP3 编码解码 附完整c代码
近期一直不间断学习音频处理,一直也没想着要去碰音频编解码相关。
主要是觉得没什么实际的作用和意义。
不管视频编解码,图像编解码,音频编解码,都有很多组织基金在推动。
当然,在一些特定的情景下,需要用起来编解码库,
而一般这些库都会有编译困难,使用困难等等困难综合症。
图像方面,已经有stb_image,spot,freeimage等编解码库系列,做得特别赞。
https://github.com/nothings/stb/
https://github.com/r-lyeh-archived/spot
http://freeimage.sourceforge.net/index.html
当然有一段时间,jpeg的编码库也是个头疼的事情,直到tinyjpg的出现。
视频这块有libav,ffmpeg
而音频这块,就有点差强人意了。
当然dr_libs 也已经做了不少工作了。
https://github.com/mackron/dr_libs
可惜的是,他做了wav的编解码库,mp3的解码库,就是没有mp3的编码库。
而一般mp3 的编码库,大众使用最多的是lame
在一阵寻寻觅觅之后,俺找到了一个mp3的编码库。
其原官网已经成为历史资源了。
https://web.archive.org/web/20060102002813/http://www.everett9981.freeserve.co.uk/pete.htm
也是相当历史久远了。
也有人对其进行了回炉重造。
https://github.com/toots/shine
俺一直惦念着,找个时间,进行代码整合,blabla
秉承着简洁简单的态度,就这么新鲜出炉了。
在写示例代码的时候,踩了几个小坑。
贴上完整代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "timing.h"
#include "shine_mp3.h" #define DR_WAV_IMPLEMENTATION #include "dr_wav.h" #define DR_MP3_IMPLEMENTATION #include "dr_mp3.h" void error(char *s); int16_t *wavRead_int16(char *filename, uint32_t *sampleRate, uint32_t *channels, uint64_t *totalSampleCount) {
int16_t *buffer = drwav_open_and_read_file_s16(filename, channels, sampleRate, totalSampleCount);
if (buffer == NULL) {
drmp3_config pConfig;
float *mp3_buffer = drmp3_open_and_decode_file_f32(filename, &pConfig, totalSampleCount);
if (mp3_buffer != NULL) {
buffer = (int16_t *) calloc(*totalSampleCount, sizeof(int16_t));
*channels = pConfig.outputChannels;
*sampleRate = pConfig.outputSampleRate;
if (buffer != NULL)
drwav_f32_to_s16(buffer, mp3_buffer, *totalSampleCount);
free(mp3_buffer);
} else {
printf("read file [%s] error.\n", filename);
}
}
return buffer;
} /* Some global vars. */
char *infname, *outfname;
FILE *outfile;
int quiet = ;
int stereo = STEREO;
int force_mono = ; /* Write out the MP3 file */
int write_mp3(long bytes, void *buffer, void *config) {
return fwrite(buffer, sizeof(unsigned char), bytes, outfile) / sizeof(unsigned char);
} /* Output error message and exit */
void error(char *s) {
fprintf(stderr, "Error: %s\n", s);
exit();
} static void print_usage() {
printf("Audio Processing\n");
printf("mp3 encoder && decoder\n");
printf("blog: http://cpuimage.cnblogs.com/\n");
printf("Usage: mp3 encoder && decoder [options] <infile> <outfile>\n\n");
printf("Use \"-\" for standard input or output.\n\n");
printf("Options:\n");
printf(" -h this help message\n");
printf(" -b <bitrate> set the bitrate [8-320], default 64 kbit\n");
printf(" -m force encoder to operate in mono\n");
printf(" -c set copyright flag, default off\n");
printf(" -j encode in joint stereo (stereo data only)\n");
printf(" -d encode in dual-channel (stereo data only)\n");
printf(" -q quiet mode\n");
printf(" -v verbose mode\n");
} /* Use these default settings, can be overridden */
static void set_defaults(shine_config_t *config) {
shine_set_config_mpeg_defaults(&config->mpeg);
} /* Parse command line arguments */
static int parse_command(int argc, char **argv, shine_config_t *config) {
int i = ; if (argc < ) return ; while (argv[++i][] == '-' && argv[i][] != '\000' && argv[i][] != ' ')
switch (argv[i][]) {
case 'b':
config->mpeg.bitr = atoi(argv[++i]);
break; case 'm':
force_mono = ;
break; case 'j':
stereo = JOINT_STEREO;
break; case 'd':
stereo = DUAL_CHANNEL;
break; case 'c':
config->mpeg.copyright = ;
break; case 'q':
quiet = ;
break; case 'v':
quiet = ;
break; case 'h':
default :
return ;
} if (argc - i != ) return ;
infname = argv[i++];
outfname = argv[i];
return ;
} /* Print some info about what we're going to encode */
static void check_config(shine_config_t *config) {
static char *version_names[] = {"2.5", "reserved", "II", "I"};
static char *mode_names[] = {"stereo", "joint-stereo", "dual-channel", "mono"};
static char *demp_names[] = {"none", "50/15us", "", "CITT"}; printf("MPEG-%s layer III, %s Psychoacoustic Model: Shine\n",
version_names[shine_check_config(config->wave.samplerate, config->mpeg.bitr)],
mode_names[config->mpeg.mode]);
printf("Bitrate: %d kbps ", config->mpeg.bitr);
printf("De-emphasis: %s %s %s\n",
demp_names[config->mpeg.emph],
((config->mpeg.original) ? "Original" : ""),
((config->mpeg.copyright) ? "(C)" : ""));
printf("Encoding \"%s\" to \"%s\"\n", infname, outfname);
} int main(int argc, char **argv) {
shine_config_t config;
shine_t s;
int written;
unsigned char *data;
/* Set the default MPEG encoding paramters - basically init the struct */
set_defaults(&config); if (!parse_command(argc, argv, &config)) {
print_usage();
exit();
} quiet = quiet || !strcmp(outfname, "-"); if (!quiet) {
printf("Audio Processing\n");
printf("mp3 encoder && decoder\n");
printf("blog:http://cpuimage.cnblogs.com/\n");
}
uint32_t sampleRate = ;
uint64_t totalSampleCount = ;
uint32_t channels = ;
int16_t *data_in = wavRead_int16(infname, &sampleRate, &channels, &totalSampleCount);
if (data_in == NULL)
return -;
double startTime = now();
config.wave.samplerate = sampleRate;
config.wave.channels = channels; if (force_mono)
config.wave.channels = ; /* See if samplerate and bitrate are valid */
if (shine_check_config(config.wave.samplerate, config.mpeg.bitr) < )
error("Unsupported samplerate/bitrate configuration."); /* open the output file */
if (!strcmp(outfname, "-"))
outfile = stdout;
else
outfile = fopen(outfname, "wb");
if (!outfile) {
fprintf(stderr, "Could not create \"%s\".\n", outfname);
exit();
} /* Set to stereo mode if wave data is stereo, mono otherwise. */
if (config.wave.channels > )
config.mpeg.mode = stereo;
else
config.mpeg.mode = MONO; /* Initiate encoder */
s = shine_initialise(&config); // assert(s != NULL);
/* Print some info about the file about to be created (optional) */
if (!quiet) check_config(&config); int samples_per_pass = shine_samples_per_pass(s) * channels; /* All the magic happens here */
size_t count = totalSampleCount / samples_per_pass;
int16_t *buffer = data_in;
for (int i = ; i < count; i++) {
data = shine_encode_buffer_interleaved(s, buffer, &written);
if (write_mp3(written, data, &config) != written) {
fprintf(stderr, "mp3 encoder && decoder: write error\n");
return ;
}
buffer += samples_per_pass;
}
size_t last = totalSampleCount % samples_per_pass;
if (last != ) {
int16_t *cache = (int16_t *) calloc(samples_per_pass, sizeof(int16_t));
if (cache != NULL) {
memcpy(cache, buffer, last * sizeof(int16_t));
data = shine_encode_buffer_interleaved(s, cache, &written);
free(cache);
if (write_mp3(written, data, &config) != written) {
fprintf(stderr, "mp3 encoder && decoder: write error\n");
return ;
}
}
}
/* Flush and write remaining data. */
data = shine_flush(s, &written);
write_mp3(written, data, &config);
/* Close encoder. */
shine_close(s);
/* Close the MP3 file */
fclose(outfile);
free(data_in);
double time_interval = calcElapsed(startTime, now());
if (!quiet)
printf("time interval: %d ms\n ", (int) (time_interval * )); return ;
}
熟悉我的风格的朋友们,估计一看就清楚了。
也不多做解释,当然了,这份代码是学习mp3编解码的不二之选。
使用示例:
tinymp3 -b 64 input.mp3 ouput.mp3
tinymp3 -b 64 input.wav ouput.mp3
相关参数说明:
Usage: tinymp3 [options] <infile> <outfile>
Use "-" for standard input or output.
Options:
-h this help message
-b <bitrate> set the bitrate [8-320], default 64 kbit
-m force encoder to operate in mono
-c set copyright flag, default off
-j encode in joint stereo (stereo data only)
-d encode in dual-channel (stereo data only)
-q quiet mode
不做解释,直接上取下项目,cmake一下,你懂的。
项目地址:
https://github.com/cpuimage/tinymp3
前面有不少朋友问到音频重采样库的问题,抽空整理了下speex的resampler。
我想重采样这方面也是够用的了。
项目地址:
https://github.com/cpuimage/speex_resampler
以上,权当抛砖引玉。
另外感谢 热心网友打赏两瓶可乐。
独乐乐,不如众乐乐。
若有其他相关问题或者需求也可以邮件联系俺探讨。
邮箱地址是:
gaozhihan@vip.qq.com
MP3 编码解码 附完整c代码的更多相关文章
- 音频降噪算法 附完整C代码
降噪是音频图像算法中的必不可少的. 目的肯定是让图片或语音 更加自然平滑,简而言之,美化. 图像算法和音频算法 都有其共通点. 图像是偏向 空间 处理,例如图片中的某个区域. 图像很多时候是以二维数据 ...
- 音频自动增益 与 静音检测 算法 附完整C代码
前面分享过一个算法<音频增益响度分析 ReplayGain 附完整C代码示例> 主要用于评估一定长度音频的音量强度, 而分析之后,很多类似的需求,肯定是做音频增益,提高音量诸如此类做法. ...
- 音频自动增益 与 静音检测 算法 附完整C代码【转】
转自:https://www.cnblogs.com/cpuimage/p/8908551.html 前面分享过一个算法<音频增益响度分析 ReplayGain 附完整C代码示例> 主要用 ...
- 基于RNN的音频降噪算法 (附完整C代码)
前几天无意间看到一个项目rnnoise. 项目地址: https://github.com/xiph/rnnoise 基于RNN的音频降噪算法. 采用的是 GRU/LSTM 模型. 阅读下训练代码,可 ...
- mser 最大稳定极值区域(文字区域定位)算法 附完整C代码
mser 的全称:Maximally Stable Extremal Regions 第一次听说这个算法时,是来自当时部门的一个同事, 提及到他的项目用它来做文字区域的定位,对这个算法做了一些优化. ...
- 经典傅里叶算法小集合 附完整c代码
前面写过关于傅里叶算法的应用例子. <基于傅里叶变换的音频重采样算法 (附完整c代码)> 当然也就是举个例子,主要是学习傅里叶变换. 这个重采样思路还有点瑕疵, 稍微改一下,就可以支持多通 ...
- 自动曝光修复算法 附完整C代码
众所周知, 图像方面的3A算法有: AF自动对焦(Automatic Focus)自动对焦即调节摄像头焦距自动得到清晰的图像的过程 AE自动曝光(Automatic Exposure)自动曝光的是为了 ...
- 基于傅里叶变换的音频重采样算法 (附完整c代码)
前面有提到音频采样算法: WebRTC 音频采样算法 附完整C++示例代码 简洁明了的插值音频重采样算法例子 (附完整C代码) 近段时间有不少朋友给我写过邮件,说了一些他们使用的情况和问题. 坦白讲, ...
- Java架构师方案—多数据源开发详解及原理(二)(附完整项目代码)
1. mybatis下数据源开发工作 2. 数据源与DAO的关系原理模型 3. 为什么要配置SqlSessionTemplate类的bean 4. 多数据源应用测试 1. mybatis下数据源开发工 ...
随机推荐
- C++使用BOOST操作文件、目录
开始使用 在BOOST库出现之前,C++对于文件和目录的操作,大都借助于UNIX提供的底层文件和目录接口,从使用角度来看,这些底层的操作不够友好.BOOST中filesystem库是一种可移植的文件系 ...
- 小技巧:Mac下Metasploit渗透Oracle环境的搭建
Metasploit是一款开源的安全漏洞检测工具,可以帮助安全和IT专业人士识别安全性问题,验证漏洞的缓解措施,并管理专家驱动的安全性进行评估,提供真正的安全风险情报.这些功能包括智能开发,密码审计, ...
- D3——动态绑定数据
一.绑定数组元素 , , , , ]; d3.select("body") .selectAll("p") .data(dataset) .enter() .a ...
- IntelliJ IDEA 2017 完美注册方法及破解方法
本文使用破解方式注册. 下载破解文件JetbrainsCrack-2.6.2.jar 下载地址: http://idea.lanyus.com/ 开始破解 一.将下载的 JetbrainsCrack- ...
- jemter多种方式查看结果树及正则的使用
最近才发现jemter结果是有一种正则表达式匹配的显示方式,以前直接在TEXT下显示和来匹配正则,真是费时间,使用方式如下: 默认使用TEXT方式显示: 显示方式有以下几种: RegExp Teste ...
- python date,datetime 和time的区别
这是三个不同类型的数据,例如 2015-11-21 10:51:20: date是日期,表示的是 2015-11-21: datetime是日期时间,表示的是 2015-11-21 10:51:20: ...
- Oracle中的rownum不能使用大于>的问题
标题:Oracle中的rownum不能使用大于>的问题 一.对rownum的说明 关于Oracle 的 rownum 问题,很多资料都说不支持SQL语句中的“>.>=.=.betwe ...
- CentOS下go 安装
go 语言源码安装依赖 ,gcc ,make glibc库,等,上述工具安装省略,另外,其源代码更新采用的是mercurial 工具,安装前先安装mercureal : 1.mercurial安 ...
- 2018 Multi-University Training Contest 4 Problem J. Let Sudoku Rotate 【DFS+剪枝+矩阵旋转】
任意门:http://acm.hdu.edu.cn/showproblem.php?pid=6341 Problem J. Let Sudoku Rotate Time Limit: 2000/100 ...
- 如何选择PHP项目的开发方案?
我说的项目开发方案并不是谈论到底用不用PHP去开发的问题,而是当你遇到一个项目,已经决定了用PHP,然后才来看的问题:用PHP的什么开发方案. 基本上有这么几种方案.各有各的说法,良莠不齐,我就谈谈我 ...