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
https://libav.org/
https://ffmpeg.org/
而音频这块,就有点差强人意了。
当然dr_libs 也已经做了不少工作了。
https://github.com/mackron/dr_libs
可惜的是,他做了wav的编解码库,mp3的解码库,就是没有mp3的编码库。
而一般mp3 的编码库,大众使用最多的是lame
http://lame.sourceforge.net/
在一阵寻寻觅觅之后,俺找到了一个mp3的编码库。
其原官网已经成为历史资源了。
https://web.archive.org/web/20060102002813/http://www.everett9981.freeserve.co.uk/pete.htm
也是相当历史久远了。
也有人对其进行了回炉重造。
https://github.com/toots/shine
俺一直惦念着,找个时间,进行代码整合,blabla
秉承着简洁简单的态度,就这么新鲜出炉了。
在写示例代码的时候,踩了几个小坑。
贴上完整代码:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <time.h> 5 #include "timing.h" 6 #include "shine_mp3.h" 7 8 #define DR_WAV_IMPLEMENTATION 9 10 #include "dr_wav.h" 11 12 #define DR_MP3_IMPLEMENTATION 13 14 #include "dr_mp3.h" 15 16 void error(char *s); 17 18 19 int16_t *wavRead_int16(char *filename, uint32_t *sampleRate, uint32_t *channels, uint64_t *totalSampleCount) { 20 int16_t *buffer = drwav_open_and_read_file_s16(filename, channels, sampleRate, totalSampleCount); 21 if (buffer == NULL) { 22 drmp3_config pConfig; 23 float *mp3_buffer = drmp3_open_and_decode_file_f32(filename, &pConfig, totalSampleCount); 24 if (mp3_buffer != NULL) { 25 buffer = (int16_t *) calloc(*totalSampleCount, sizeof(int16_t)); 26 *channels = pConfig.outputChannels; 27 *sampleRate = pConfig.outputSampleRate; 28 if (buffer != NULL) 29 drwav_f32_to_s16(buffer, mp3_buffer, *totalSampleCount); 30 free(mp3_buffer); 31 } else { 32 printf("read file [%s] error.\n", filename); 33 } 34 } 35 return buffer; 36 } 37 38 39 /* Some global vars. */ 40 char *infname, *outfname; 41 FILE *outfile; 42 int quiet = 0; 43 int stereo = STEREO; 44 int force_mono = 0; 45 46 /* Write out the MP3 file */ 47 int write_mp3(long bytes, void *buffer, void *config) { 48 return fwrite(buffer, sizeof(unsigned char), bytes, outfile) / sizeof(unsigned char); 49 } 50 51 /* Output error message and exit */ 52 void error(char *s) { 53 fprintf(stderr, "Error: %s\n", s); 54 exit(1); 55 } 56 57 static void print_usage() { 58 printf("Audio Processing\n"); 59 printf("mp3 encoder && decoder\n"); 60 printf("blog: http://cpuimage.cnblogs.com/\n"); 61 printf("Usage: mp3 encoder && decoder [options] <infile> <outfile>\n\n"); 62 printf("Use \"-\" for standard input or output.\n\n"); 63 printf("Options:\n"); 64 printf(" -h this help message\n"); 65 printf(" -b <bitrate> set the bitrate [8-320], default 64 kbit\n"); 66 printf(" -m force encoder to operate in mono\n"); 67 printf(" -c set copyright flag, default off\n"); 68 printf(" -j encode in joint stereo (stereo data only)\n"); 69 printf(" -d encode in dual-channel (stereo data only)\n"); 70 printf(" -q quiet mode\n"); 71 printf(" -v verbose mode\n"); 72 } 73 74 /* Use these default settings, can be overridden */ 75 static void set_defaults(shine_config_t *config) { 76 shine_set_config_mpeg_defaults(&config->mpeg); 77 } 78 79 /* Parse command line arguments */ 80 static int parse_command(int argc, char **argv, shine_config_t *config) { 81 int i = 0; 82 83 if (argc < 3) return 0; 84 85 while (argv[++i][0] == '-' && argv[i][1] != '\000' && argv[i][1] != ' ') 86 switch (argv[i][1]) { 87 case 'b': 88 config->mpeg.bitr = atoi(argv[++i]); 89 break; 90 91 case 'm': 92 force_mono = 1; 93 break; 94 95 case 'j': 96 stereo = JOINT_STEREO; 97 break; 98 99 case 'd': 100 stereo = DUAL_CHANNEL; 101 break; 102 103 case 'c': 104 config->mpeg.copyright = 1; 105 break; 106 107 case 'q': 108 quiet = 1; 109 break; 110 111 case 'v': 112 quiet = 0; 113 break; 114 115 case 'h': 116 default : 117 return 0; 118 } 119 120 if (argc - i != 2) return 0; 121 infname = argv[i++]; 122 outfname = argv[i]; 123 return 1; 124 } 125 126 /* Print some info about what we're going to encode */ 127 static void check_config(shine_config_t *config) { 128 static char *version_names[4] = {"2.5", "reserved", "II", "I"}; 129 static char *mode_names[4] = {"stereo", "joint-stereo", "dual-channel", "mono"}; 130 static char *demp_names[4] = {"none", "50/15us", "", "CITT"}; 131 132 printf("MPEG-%s layer III, %s Psychoacoustic Model: Shine\n", 133 version_names[shine_check_config(config->wave.samplerate, config->mpeg.bitr)], 134 mode_names[config->mpeg.mode]); 135 printf("Bitrate: %d kbps ", config->mpeg.bitr); 136 printf("De-emphasis: %s %s %s\n", 137 demp_names[config->mpeg.emph], 138 ((config->mpeg.original) ? "Original" : ""), 139 ((config->mpeg.copyright) ? "(C)" : "")); 140 printf("Encoding \"%s\" to \"%s\"\n", infname, outfname); 141 } 142 143 int main(int argc, char **argv) { 144 shine_config_t config; 145 shine_t s; 146 int written; 147 unsigned char *data; 148 /* Set the default MPEG encoding paramters - basically init the struct */ 149 set_defaults(&config); 150 151 if (!parse_command(argc, argv, &config)) { 152 print_usage(); 153 exit(1); 154 } 155 156 quiet = quiet || !strcmp(outfname, "-"); 157 158 if (!quiet) { 159 printf("Audio Processing\n"); 160 printf("mp3 encoder && decoder\n"); 161 printf("blog:http://cpuimage.cnblogs.com/\n"); 162 } 163 uint32_t sampleRate = 0; 164 uint64_t totalSampleCount = 0; 165 uint32_t channels = 0; 166 int16_t *data_in = wavRead_int16(infname, &sampleRate, &channels, &totalSampleCount); 167 if (data_in == NULL) 168 return -1; 169 double startTime = now(); 170 config.wave.samplerate = sampleRate; 171 config.wave.channels = channels; 172 173 if (force_mono) 174 config.wave.channels = 1; 175 176 /* See if samplerate and bitrate are valid */ 177 if (shine_check_config(config.wave.samplerate, config.mpeg.bitr) < 0) 178 error("Unsupported samplerate/bitrate configuration."); 179 180 /* open the output file */ 181 if (!strcmp(outfname, "-")) 182 outfile = stdout; 183 else 184 outfile = fopen(outfname, "wb"); 185 if (!outfile) { 186 fprintf(stderr, "Could not create \"%s\".\n", outfname); 187 exit(1); 188 } 189 190 /* Set to stereo mode if wave data is stereo, mono otherwise. */ 191 if (config.wave.channels > 1) 192 config.mpeg.mode = stereo; 193 else 194 config.mpeg.mode = MONO; 195 196 /* Initiate encoder */ 197 s = shine_initialise(&config); 198 199 // assert(s != NULL); 200 /* Print some info about the file about to be created (optional) */ 201 if (!quiet) check_config(&config); 202 203 int samples_per_pass = shine_samples_per_pass(s) * channels; 204 205 /* All the magic happens here */ 206 size_t count = totalSampleCount / samples_per_pass; 207 int16_t *buffer = data_in; 208 for (int i = 0; i < count; i++) { 209 data = shine_encode_buffer_interleaved(s, buffer, &written); 210 if (write_mp3(written, data, &config) != written) { 211 fprintf(stderr, "mp3 encoder && decoder: write error\n"); 212 return 1; 213 } 214 buffer += samples_per_pass; 215 } 216 size_t last = totalSampleCount % samples_per_pass; 217 if (last != 0) { 218 int16_t *cache = (int16_t *) calloc(samples_per_pass, sizeof(int16_t)); 219 if (cache != NULL) { 220 memcpy(cache, buffer, last * sizeof(int16_t)); 221 data = shine_encode_buffer_interleaved(s, cache, &written); 222 free(cache); 223 if (write_mp3(written, data, &config) != written) { 224 fprintf(stderr, "mp3 encoder && decoder: write error\n"); 225 return 1; 226 } 227 } 228 } 229 /* Flush and write remaining data. */ 230 data = shine_flush(s, &written); 231 write_mp3(written, data, &config); 232 /* Close encoder. */ 233 shine_close(s); 234 /* Close the MP3 file */ 235 fclose(outfile); 236 free(data_in); 237 double time_interval = calcElapsed(startTime, now()); 238 if (!quiet) 239 printf("time interval: %d ms\n ", (int) (time_interval * 1000)); 240 241 return 0; 242 }
熟悉我的风格的朋友们,估计一看就清楚了。
也不多做解释,当然了,这份代码是学习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
转载于:https://www.cnblogs.com/cpuimage/p/9427457.html
MP3 编码解码 附完整c代码相关推荐
- java mp3静音检测,音频自动增益 与 静音检测 算法 附完整C代码
前面分享过一个算法<音频增益响度分析 ReplayGain 附完整C代码示例> 主要用于评估一定长度音频的音量强度, 而分析之后,很多类似的需求,肯定是做音频增益,提高音量诸如此类做法. ...
- 音频自动增益 与 静音检测 算法 附完整C代码
前面分享过一个算法<音频增益响度分析 ReplayGain 附完整C代码示例> 主要用于评估一定长度音频的音量强度, 而分析之后,很多类似的需求,肯定是做音频增益,提高音量诸如此类做法. ...
- 音频降噪算法 附完整C代码
本文转载自博客:https://cloud.tencent.com/developer/article/1117226 降噪是音频图像算法中的必不可少的. 目的肯定是让图片或语音 更加自然平滑,简而言 ...
- wav文件降噪c语言,音频降噪算法 附完整C代码
降噪是音频图像算法中的必不可少的. 目的肯定是让图片或语音 更加自然平滑,简而言之,美化. 图像算法和音频算法 都有其共通点. 图像是偏向 空间 处理,例如图片中的某个区域. 图像很多时候是以二维数据 ...
- Pytorch LSTM实现中文单词预测(附完整训练代码)
Pytorch LSTM实现中文单词预测(附完整训练代码) 目录 Pytorch LSTM实现中文单词预测(词语预测 附完整训练代码) 1.项目介绍 2.中文单词预测方法(N-Gram 模型) 3.训 ...
- 基于傅里叶变换的音频重采样算法 (附完整c代码)
前面有提到音频采样算法: WebRTC 音频采样算法 附完整C++示例代码 简洁明了的插值音频重采样算法例子 (附完整C代码) 近段时间有不少朋友给我写过邮件,说了一些他们使用的情况和问题. 坦白讲, ...
- 灰狼(GWO)算法(附完整Matlab代码,可直接复制)
尊重他人劳动成果,请勿转载! 有问题可留言或私信,看到了都会回复解答! 其他算法请参考: 1.粒子群(PSO)优化算法(附完整Matlab代码,可直接复制)https://blog.csdn.net/ ...
- Pytorch TextCNN实现中文文本分类(附完整训练代码)
Pytorch TextCNN实现中文文本分类(附完整训练代码) 目录 Pytorch TextCNN实现中文文本分类(附完整训练代码) 一.项目介绍 二.中文文本数据集 (1)THUCNews文本数 ...
- java 对音频文件降噪_(转)音频降噪算法 附完整C代码
转:https://www.cnblogs.com/cpuimage/p/8905965.html 降噪是音频图像算法中的必不可少的. 目的肯定是让图片或语音 更加自然平滑,简而言之,美化. 图像算法 ...
最新文章
- Python源码学习:Python函数浅析-有参函数
- Python 进阶_模块 包
- The type List is not generic
- 八月22日,django知识点总结:
- Halcon:手眼标定——眼在手外与眼在手上
- pycharm 快捷键大全
- 4G通信技术LTE介绍
- Leetcode每日一题:53.maximum-subarray(最大子序和)
- 二进制像素绘制程序 scratch编程三级
- 单词测试通关学英语的软件,推荐5款最火的英语学习类app
- OA是什么?OA系统,OA,OA解决方案有哪些,OA有什么功能,OA有什么作用
- 电脑开机一直自动重启
- Windows 11 (updated Dec 2021) 简体中文版、英文版(64-bit、ARM64)下载(2022 年 1 月发布)
- vivo 应用商店推荐系统探索与实践
- null与undefined的异同点
- 【PS】ps基础绘画球体
- 跨端融合!探索前沿科技无限可能,深圳腾讯2018TLC大会再度来袭,早鸟票最后一天...
- Python4班平均成绩统计_郑州十一中2020届高考成绩简析(含新疆内高班)
- 线性代数(四十) : 正交补与正交投影
- Spring Cloud H SR5集成 Jaeger
热门文章
- 第十六周程序阅读(4)
- 计算机数据恢复教程视频,视频删了怎么恢复?小技巧帮你快速解决
- Swift 注释规范和文档注释
- (0061)iOS开发之iPad开发:UISplitViewController分割视图控制器
- dxf转nc代码软件_eCAM高速激光加工软件
- 解锁UI自动化新姿势-UI Recorder
- java_环境安装(window10)
- 单变量线性回归中的梯度下降法求解代价函数的最小值
- 苹果的浏览器safari无法识别 2016-1-1这样的日期,会返回Invalid Date
- 【LeetCode】87. Scramble String