Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >libmad学习进阶2----利用libmad将mp3转码成pcm

libmad学习进阶2----利用libmad将mp3转码成pcm

作者头像
用户4148957
发布于 2022-06-14 00:15:53
发布于 2022-06-14 00:15:53
6990
举报
文章被收录于专栏:C/C++与音视频C/C++与音视频

# include <stdio.h> # include <unistd.h> # include <sys/stat.h> # include <sys/mman.h> # include "mad.h" #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<stdlib.h> /* * This is perhaps the simplest example use of the MAD high-level API. * Standard input is mapped into memory via mmap(), then the high-level API * is invoked with three callbacks: input, output, and error. The output * callback converts MAD's high-resolution PCM samples to 16 bits, then * writes them to standard output in little-endian, stereo-interleaved * format. */ #define printf static Get_file_length(char *PATH); static int decode(unsigned char const *, unsigned long); int main(int argc, char *argv[]) { printf("The main is start!\n"); struct stat stat; void *fdm; int fd; //char buffer1[80000]; printf("###The input file is %s ! the arc=%d###\n",argv[1],argc); if (argc == 1) { printf("The argc is wrong!\n"); return 1; } #if 0 if (fstat(STDIN_FILENO, &stat) == -1 || stat.st_size == 0) return 2; #endif fd =open(argv[1],O_RDWR); if(-1==fd) { printf("sorry,The file open is faild!\n"); } else { printf("The file open is sucessed!\n"); } //read(fd,buffer1,sizeof(buffer1)); //printf("%s", buffer1); stat.st_size = Get_file_length(argv[1]); printf("The file size is %d\n",stat.st_size ); printf("The Map is begin!\n"); fdm = mmap(0, stat.st_size, PROT_READ, MAP_SHARED, fd, 0); if (fdm == MAP_FAILED) { printf("mmap is failed\n"); return 3; } decode(fdm, stat.st_size); if (munmap(fdm, stat.st_size) == -1) return 4; return 0; } /* * This is a private message structure. A generic pointer to this structure * is passed to each of the callback functions. Put here any data you need * to access from within the callbacks. */ struct buffer { unsigned char const *start; unsigned long length; }; /* * This is the input callback. The purpose of this callback is to (re)fill * the stream buffer which is to be decoded. In this example, an entire file * has been mapped into memory, so we just call mad_stream_buffer() with the * address and length of the mapping. When this callback is called a second * time, we are finished decoding. */ static enum mad_flow input(void *data, struct mad_stream *stream) { struct buffer *buffer = data; if (!buffer->length) return MAD_FLOW_STOP; mad_stream_buffer(stream, buffer->start, buffer->length); buffer->length = 0; printf("1111"); return MAD_FLOW_CONTINUE; } /* * The following utility routine performs simple rounding, clipping, and * scaling of MAD's high-resolution samples down to 16 bits. It does not * perform any dithering or noise shaping, which would be recommended to * obtain any exceptional audio quality. It is therefore not recommended to * use this routine if high-quality output is desired. */ static inline signed int scale(mad_fixed_t sample) { /* round */ sample += (1L << (MAD_F_FRACBITS - 16)); /* clip */ if (sample >= MAD_F_ONE) sample = MAD_F_ONE - 1; else if (sample < -MAD_F_ONE) sample = -MAD_F_ONE; /* quantize */ return sample >> (MAD_F_FRACBITS + 1 - 16); } static int Get_file_length(char *PATH) { FILE *fp; fp=fopen(PATH,"r"); if(!fp) { printf("sorry,The file open is faild!\n"); } else { printf("The file open is sucessed!\n"); } fseek(fp, 0L,SEEK_END); return (ftell(fp)); } /* * This is the output callback function. It is called after each frame of * MPEG audio data has been completely decoded. The purpose of this callback * is to output (or play) the decoded PCM audio. */ static enum mad_flow output(void *data, struct mad_header const *header, struct mad_pcm *pcm) { unsigned int nchannels, nsamples; mad_fixed_t const *left_ch, *right_ch; static FILE *fdout; char buf[1]; /* pcm->samplerate contains the sampling frequency */ fdout= fopen("mypcm.pcm","ab+"); if(!fdout) { printf("open is failed\n"); } else printf("out open is ok\n"); nchannels = pcm->channels; nsamples = pcm->length; left_ch = pcm->samples[0]; right_ch = pcm->samples[1]; //printf("channels=%d, samples=%d\n", nchannels,nsamples); while (nsamples--) { signed int sample; /* output sample(s) in 16-bit signed little-endian PCM */ // printf("2222\n"); sample = scale(*left_ch++); buf[0]=(sample >> 0) & 0xff; printf("%d\t",buf[0]); fwrite(buf,1,1,fdout); buf[0]=(sample >> 8) & 0xff; printf("%d\t",buf[0]); fwrite(buf,1,1,fdout); if (nchannels == 2) { sample = scale(*right_ch++); buf[0]=(sample >> 0) & 0xff; fwrite(buf,1,1,fdout); buf[0]=(sample >> 8) & 0xff; fwrite(buf,1,1,fdout); } } fclose(fdout); return MAD_FLOW_CONTINUE; } /* * This is the error callback function. It is called whenever a decoding * error occurs. The error is indicated by stream->error; the list of * possible MAD_ERROR_* errors can be found in the mad.h (or stream.h) * header file. */ static enum mad_flow error(void *data, struct mad_stream *stream, struct mad_frame *frame) { struct buffer *buffer = data; fprintf(stderr, "decoding error 0x%04x (%s) at byte offset %u\n", stream->error, mad_stream_errorstr(stream), stream->this_frame - buffer->start); /* return MAD_FLOW_BREAK here to stop decoding (and propagate an error) */ return MAD_FLOW_CONTINUE; } /* * This is the function called by main() above to perform all the decoding. * It instantiates a decoder object and configures it with the input, * output, and error callback functions above. A single call to * mad_decoder_run() continues until a callback function returns * MAD_FLOW_STOP (to stop decoding) or MAD_FLOW_BREAK (to stop decoding and * signal an error). */ static int decode(unsigned char const *start, unsigned long length) { struct buffer buffer; struct mad_decoder decoder; int result; /* initialize our private message structure */ buffer.start = start; buffer.length = length; /* configure input, output, and error functions */ mad_decoder_init(&decoder, &buffer, input, 0 /* header */, 0 /* filter */, output, error, 0 /* message */); /* start decoding */ result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC); /* release the decoder */ mad_decoder_finish(&decoder); return result;

}

liamad中的原始的minimad.c数据输入来自于标准 输入,数据 输出到标准输出。通过读写文件的方式,就可以 将一个mp3文件转换成pcm文件。pcm文件就可以直接通过工具播放或送如声音驱动设备中,不同系统不同平台部一样,后面将讲如何一个mp3文件解码成pcm直接送入声卡播放。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2014-02-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
libmad学习进阶3-----基于oss音频驱动架构的一个mp3播放器
以上就是通过libmad将mp3先解码成pcm,然后将pcm直接扔到/ dev/dsp音频设备中,但dsp音频设备属于oss架构,已经逐渐被alsa驱动取代,后续会介绍基于alsa驱动架构的mp3播放器
用户4148957
2022/06/14
7010
libmad学习进阶4 -----基于atlas音频驱动架构的MP3播放器
 /*modify by hfl 20140216*/ #define ALSA_PCM_NEW_HW_PARAMS_API # include <stdio.h> # include <unistd.h> # include <sys/stat.h> # include <sys/mman.h> # include "mad.h" #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<stdlib.h> #include <sys/ioctl.h> #include <sys/soundcard.h> #include <alsa/asoundlib.h> /*  * This is perhaps the simplest example use of the MAD high-level API.  * Standard input is mapped into memory via mmap(), then the high-level API  * is invoked with three callbacks: input, output, and error. The output  * callback converts MAD's high-resolution PCM samples to 16 bits, then  * writes them to standard output in little-endian, stereo-interleaved  * format.  */  //#define printf     static Get_file_length(char *PATH); static int init_dsp(); static int Uninit_dsp(); static int decode(unsigned char const *, unsigned long); static enum mad_flow outputplay(void *data,     struct mad_header const *header,     struct mad_pcm *pcm); int main(int argc, char *argv[]) { printf("The main is start!\n");   struct stat stat;   void *fdm;   int  fd;   //char buffer1[80000];   printf("###The input file is %s  ! the arc=%d###\n",argv[1],argc);   if (argc == 1)    {    printf("The argc is wrong!\n");     return 1;  } #if 0   if (fstat(STDIN_FILENO, &stat) == -1 ||       stat.st_size == 0)     return 2; #endif  fd =open(argv[1],O_RDWR); if(-1==fd) {    printf("sorry,The file open is faild!\n"); } else {  printf("The file open is sucessed!\n"); } //read(fd,buffer1,sizeof(buffer1)); //printf("%s", buffer1); stat.st_size = Get_file_length(argv[1]); printf("The file size is %d\n",stat.st_size ); printf("The Map is begin ok!\n"); fdm = mmap(0, stat.st_size, PROT_READ, MAP_SHARED, fd, 0);   if (fdm == MAP_FAILED) { printf("mmap is failed\n");     return 3; }   decode(fdm, stat.st_size);   if (munmap(fdm, stat.st
用户4148957
2022/06/14
7950
让终端支持播放mp3,移植mp3解码库libmad和madplay到嵌入式linux
MAD (libmad)是一个开源的高精度 MPEG 音频解码库,支持 MPEG-1(Layer I, Layer II 和 LayerIII(也就是 MP3)。LIBMAD 提供 24 -bit 的 PCM 输出,完全是定点计算,非常适合没有浮点支持的平台上使用。使用 libmad 提供的一系列 API,就可以非常简单地实现 MP3 数据解码工作。
杨永贞
2020/08/04
2.8K0
音视频技术(4)-SDL播放PCM
SDL 是一套跨平台的音视频播放框架,对齐了底层硬件的差异,开发者可以专注于音视频的处理,本文记录在iOS上使用SDL播放pcm音频裸数据的实现过程。pcm是音频的裸数据。 sdl编译:可以直接
公号sumsmile
2020/03/27
9710
使用pjsip实现一个录音机和播放器
录音机:录制为PCM文件 //broadcast_record.c /* 录制wav,之后编码,再通过组播发送出去 组播接收wav, 解码?播放wav */ #include <pjmedia-audiodev/audiodev.h> #include <pjmedia.h> #include <pjlib.h> #include <pjlib-util.h> #include "broadcast_app.h" #define THIS_FILE "broadcast_record.c" s
呱牛笔记
2023/04/25
1.3K0
Linux音频驱动-PCM设备
pcm(Pulse-code modulation)脉冲编码调制,是将模拟信号转化为数字信号的一种方法。声音的转化的过程为,先对连续的模拟信号按照固定频率周期性采样,将采样到的数据按照一定的精度进行量化,量化后的信号和采样后的信号差值叫做量化误差,将量化后的数据进行最后的编码存储,最终模拟信号变化为数字信号。
DragonKingZhu
2020/03/24
9.1K0
Linux音频驱动-PCM设备
音频基础知识 - PCM 浅析
最近有个需求:对音频裁剪时,裁剪条的纵坐标必须是音频音量,以帮助用户更好的选择音频区域,所以就需要快速准确的提取出音频的音量列表。本文主要介绍下从mp4文件中提取音轨音量的方式,以及相关的知识点。
字节流动
2021/03/16
4.1K0
音频基础知识 - PCM 浅析
2023-03-19:使用Go语言和FFmpeg库实现pcm编码为mp3。
本文将介绍如何使用Go语言和FFmpeg库实现PCM音频文件编码为MP3格式。我们将使用moonfdd/ffmpeg-go库,并在Windows 10 64位操作系统下完成本次实验。
福大大架构师每日一题
2023/03/19
6700
2023-03-19:使用Go语言和FFmpeg库实现pcm编码为mp3。
FFMPEG音视频开发: Linux下采集音频(alsa-lib库)与视频(V4L2框架)实时同步编码保存为MP4文件(视频录制)
参考这篇文章: https://blog.csdn.net/xiaolong1126626497/article/details/104919095
DS小龙哥
2022/01/12
2.2K0
FFMPEG音视频开发:  Linux下采集音频(alsa-lib库)与视频(V4L2框架)实时同步编码保存为MP4文件(视频录制)
「SDL第七篇」PCM音频播放器的实现
如果我们要播放一段声音,想当然的认为直接将播放的声音发送给声卡,这样扬声器就会将声音播放出来。只要我们不断的送数据,声音就会不停的输出。
音视频_李超
2020/04/02
2.1K0
Linux ALSA声卡驱动之三:PCM设备的创建
PCM是英文Pulse-code modulation的缩写,中文译名是脉冲编码调制。我们知道在现实生活中,人耳听到的声音是模拟信号,PCM就是要把声音从模拟转换成数字信号的一种技术,他的原理简单地说就是利用一个固定的频率对模拟信号进行采样,采样后的信号在波形上看就像一串连续的幅值不一的脉冲,把这些脉冲的幅值按一定的精度进行量化,这些量化后的数值被连续地输出、传输、处理或记录到存储介质中,所有这些组成了数字音频的产生过程。
用户6280468
2024/01/10
1.2K0
Linux ALSA声卡驱动之三:PCM设备的创建
在Hi3516ev300上调通PJSIP 的音频通话过程记录
这个工作量相对较小,配置host为arm-himix100-linux编译都能顺利通过
呱牛笔记
2023/05/02
9540
在Hi3516ev300上调通PJSIP 的音频通话过程记录
2023-03-23:音视频解混合(demuxer)为PCM和YUV420P,用go语言编写。
2023-03-23:音视频解混合(demuxer)为PCM和YUV420P,用go语言编写。
福大大架构师每日一题
2023/03/23
3750
2023-03-23:音视频解混合(demuxer)为PCM和YUV420P,用go语言编写。
Linux下使用alsa-lib库完成音频开发: 实现放音和录音(从声卡获取PCM数据保存、向声卡写PCM数据输出)
参考文章: https://blog.csdn.net/xiaolong1126626497/article/details/104916277
DS小龙哥
2022/01/12
9.4K2
2023-03-23:音视频解混合(demuxer)为PCM和YUV420P,用go语言编写。
2023-03-23:音视频解混合(demuxer)为PCM和YUV420P,用go语言编写。
福大大架构师每日一题
2023/06/08
2680
2023-03-23:音视频解混合(demuxer)为PCM和YUV420P,用go语言编写。
2023-03-17:使用Go语言和FFmpeg库实现音频重采样解码,并将其保存为PCM格式的文件。
2023-03-17:使用Go语言和FFmpeg库实现音频重采样解码,并将其保存为PCM格式的文件。
福大大架构师每日一题
2023/03/17
2K0
2023-03-17:使用Go语言和FFmpeg库实现音频重采样解码,并将其保存为PCM格式的文件。
mp3格式转wav格式 附完整C++算法实现代码
近期偶然间看到一个开源项目minimp3 Minimalistic MP3 decoder single header library 项目地址: https://github.com/lieff/minimp3 单文件头的最小mp3解码器。 一直很想抽时间好好看上一看。 最好的学习方式就是写个实用性的工程项目。 例如实现mp3转wav格式。 嗯,这篇博文就是这么来的。 阅读了下minimp3的源码,有一两处小bug, 这个解码算法可以进一步提速优化的地方还有不少。 后面有时间,再好好庖丁解牛。 基于这个库
cpuimage
2018/04/12
3.1K0
使用libavcodec将mp3音频文件解码为pcm音频采样数据【[mp3float @ 0x561c1ec49940] Header missing】
  想要解决上面提到的问题,我们需要对mp3文件的格式有个大致了解,为了方便讲解,我这里画了个示意图:
故乡的樱花开了
2023/10/22
5690
2023-03-12:mp3音频解码为pcm,代码用go语言编写,调用moonfdd/ffmpeg-go库。
2023-03-12:mp3音频解码为pcm,代码用go语言编写,调用moonfdd/ffmpeg-go库。
福大大架构师每日一题
2023/06/08
4270
2023-03-12:mp3音频解码为pcm,代码用go语言编写,调用moonfdd/ffmpeg-go库。
2023-04-04:使用 Golang 和 ffmpeg-go 库实现 demuxing_decoding.c,轻松掌握音视频分离解码技巧。
2023-04-04:使用 Golang 和 ffmpeg-go 库实现 demuxing_decoding.c,轻松掌握音视频分离解码技巧。
福大大架构师每日一题
2023/04/05
1.6K0
2023-04-04:使用 Golang 和 ffmpeg-go 库实现 demuxing_decoding.c,轻松掌握音视频分离解码技巧。
推荐阅读
libmad学习进阶3-----基于oss音频驱动架构的一个mp3播放器
7010
libmad学习进阶4 -----基于atlas音频驱动架构的MP3播放器
7950
让终端支持播放mp3,移植mp3解码库libmad和madplay到嵌入式linux
2.8K0
音视频技术(4)-SDL播放PCM
9710
使用pjsip实现一个录音机和播放器
1.3K0
Linux音频驱动-PCM设备
9.1K0
音频基础知识 - PCM 浅析
4.1K0
2023-03-19:使用Go语言和FFmpeg库实现pcm编码为mp3。
6700
FFMPEG音视频开发: Linux下采集音频(alsa-lib库)与视频(V4L2框架)实时同步编码保存为MP4文件(视频录制)
2.2K0
「SDL第七篇」PCM音频播放器的实现
2.1K0
Linux ALSA声卡驱动之三:PCM设备的创建
1.2K0
在Hi3516ev300上调通PJSIP 的音频通话过程记录
9540
2023-03-23:音视频解混合(demuxer)为PCM和YUV420P,用go语言编写。
3750
Linux下使用alsa-lib库完成音频开发: 实现放音和录音(从声卡获取PCM数据保存、向声卡写PCM数据输出)
9.4K2
2023-03-23:音视频解混合(demuxer)为PCM和YUV420P,用go语言编写。
2680
2023-03-17:使用Go语言和FFmpeg库实现音频重采样解码,并将其保存为PCM格式的文件。
2K0
mp3格式转wav格式 附完整C++算法实现代码
3.1K0
使用libavcodec将mp3音频文件解码为pcm音频采样数据【[mp3float @ 0x561c1ec49940] Header missing】
5690
2023-03-12:mp3音频解码为pcm,代码用go语言编写,调用moonfdd/ffmpeg-go库。
4270
2023-04-04:使用 Golang 和 ffmpeg-go 库实现 demuxing_decoding.c,轻松掌握音视频分离解码技巧。
1.6K0
相关推荐
libmad学习进阶3-----基于oss音频驱动架构的一个mp3播放器
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档