网站可以制作ios,用vue开发好看的官网,带着购物系统回到80年代,二维码制作方法1#xff1a;前言 在进行音频开发之前需要先知道一些基础知识#xff0c;一些有必要的指导的概念。
1.1 声音的产生、获取和转换 声音的产生的本质是靠震动#xff0c;声音的传播需要借助媒介#xff0c;比如空气、液体、固体等媒介。在自然界中声音的可视化为音波的形式前言 在进行音频开发之前需要先知道一些基础知识一些有必要的指导的概念。
1.1 声音的产生、获取和转换 声音的产生的本质是靠震动声音的传播需要借助媒介比如空气、液体、固体等媒介。在自然界中声音的可视化为音波的形式那么音波是什么形成的了声音在信号学中对应的是模拟信号我们想要可视化声音就是通过采用获取声音的模拟信号然后转化为数字信号然后通过转化过后的信号量转化为可视化波形也就得到了常见的声波。在电子领域进行转化的工具常见的就DA-AD转化在嵌入式中采用的是ADC采集。
也就是说在对音频操作中 声音的录制-将外界的声音的模拟型号转化为数字信号进行处理 声音的播放-将数字信号转化为模拟型号释放出来。
1.2 音频的参数 1采样率音频采样率是指在数字化音频信号时每秒钟对模拟信号进行采样的次数。一般采样的数值在4800HZ左右的标准具体设备具体应用场景更具需要选定。 2声道数声道数是指在音频信号处理和播放中同时传输和播放的独立音频信号的数量。一般声道数常见的为单声道、双声道。 3采样格式采样格式是指在数字音频处理中用来表示音频信号样本的数据类型和编码方式。
常用的有S16F32。S16把声音量化为16bitF32则量化为浮点型。 4采样数采样数Sample Size通常指的是在数字音频中每个采样点所占用的位数也就是位深度Bit Depth。一般有1024、256、512、1152等。
2FFMPEG音频开发流程
2.1 FFMPEG安装
我所安装的版本为4.2.10。
在线安装指令
sudo apt-get install ffmpeg
安装需要的库指令
sudo apt-get install libfdk-aac-dev libx264-dev
libx265-dev libmp3lame-dev libdrm-dev libopengl-dev
yasm libx264-dev libsdl2-dev libmp3lamedev libopus-dev libavdevice-dev libfdk-aac-dev -y
配置FFMPEG
./configure --target-oslinux --
prefix/home/lyx/ffmpeg/install --archx86_64 --disable-doc --
enable-libx264 --enable-libmp3lame --enable-libopus --enabledebug3 --enable-alsa --enable-gpl --enable-opengl --enable-sdl2 --
enable-avdevice --enable-indevv4l2 --enable-shared --disablestatic --enable-nonfree --enable-libfdk-aac --enable-sse --enablesse2 --enable-sse3 --enable-ssse3 --enable-sse4 --enable-sse42 --
enable-avx --enable-avx2 --enable-avx512 --enable-xop --enable-fma4
--enable-libdrm
然后编译生成对应文件后安装即可。 文件成功编译后生产的文件有bin、include、lib、share分别对应生产的可执行文件、头文件库、二次开发支持库、示例代码。
3:FFMPEG 音频开发接口函数
3.1 avformat_open_input 函数的功能打开一个输入流(设备、文件、地址) 函数头文件 libavformat/avformat.h 函数的原型 int avformat_open_input(AVFormatContext **ps,const char *url,ff_const59 AVInputFormat *fmt,AVDictionary **options); 函数的参数 ps: Context: 上下文句柄 上下文一般有专用的函数创建 avformat_alloc_context(); avcodec_alloc_context(); swscale_alloc_context()..... 后续该结构体起承上启下的左右 url直播地址 文件的路径 设备文件: 音频设备 hw:0 视频设备 /dev/videox fmt 你指定要打开的流的格式 如果是文件或者直播地址往往直接传入 NULL 如果是设备需要你传入指定的格式 这个格式结构体 则需要 av_find_input_format(const char*short_name);做创建 音频 alsa 视频 v4l2 options 设置相关参数 也只只针对 input_device NULL 函数返回值 成功返回 0 失败返回 非 0 3.2 av_read_frame 函数的功能读取输入流的数据 函数头文件同上 函数的原型 int av_read_frame(AVFormatContext *s, AVPacket *pkt); 函数的参数 s : 提供输入 AvFormat 的上下文结构体 pkt: 是 FFMPEG 的数据格式之一 AVPacket AVFrame 函数返回值 读取成功返回 0 读取失败返回 非 0 4音频编码
编码类型wav-没有编码的格式音频即为原始音频文件 G711A、G711U MP2、MP3 AAC目前指令压缩率都是最好的一个编码 4.1 AAC 的介绍 高级音频编码(英语:Advanced Audio Coding AAC)出现于 1997 年基于 MPEG- 2 的音频编码技术。由 Fraunhofer IIS、杜比实验室、 ATT、 Sony(新力)等公司共同开 发目的是取代 MP3 格式。 2000 年 MPEG-4 标准出现后 AAC 重新集成了其特性加入了SBR 技术和 PS 技术为了区别于传统的 MPEG-2 AAC 又称为 MPEG-4 AAC。 AAC(高级音频编码技术 Advanced Audio Coding)是杜比实验室为音乐社区提供的 技术。 AAC 号称「最大能容纳 48 通道的音轨采样率达 96 KHz并且在 320Kbps 的数据速率下能为 5.1 声道音乐节目提供相当于 ITU-R 广播的品质」。和 MP3 比起来它的音质比较 好也能够节省大约 30%的储存空间与带宽。它是遵循 MPEG-2 的规格所开发的技术。松下的 mp3 产品都采用了这种编码方式当然也兼容 mp3 格式可以说 aac 是一种非常好用的音频格式 128kbps 的 aac 足以和 224kbps 的 mp3 抗衡空间却小了差不多一半但是在空间上和结构上 aac 和 mp3 编码出来后的风格不太一样。 AAC编码流程1打开输入流 hw0 4.2 FFMPEG编码AAC的接口讲解和编写流程 1创建一个编码的上下文-2:寻找编码器编码器绑定上下文-设置上下文参数 4开辟空间-5读取音频数据把音频数据送入到编码器里面-6读取编码后的数据写入到文件里面 4.3 接口函数 4.3.1 AVCodec *avcodec_find_encoder_by_name 函数功能寻找编码器 函数头文件 libavcodec/avcodec.h 函数的原型 AVCodec *avcodec_find_encoder_by_name(const char *name); AVCodec *avcodec_find_encoder(enum AVCodecID id); 函数的参数 name: 通过名字寻找编码器 如果专业 FFMPEG 开发工程师 一定会用 avcodec_find_encoder_by_name 他能去寻找支持硬件编码器(GPU OpenGL....) 寻找外部的一些支持库做编码功能fdk_aac id: 可以通过枚举自行跳转查找 函数返回值 就是编码器 从来都是把编码器绑定到上下文 通过上下文结构体做编解码工作 4.3.2 avcodec_open2 函数的功能绑定 解码器/编码器 给上下文 函数的原型 int avcodec_open2( AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options ); 函数的参数 avctx 你想把你的编码器/解码器 绑定到哪个上下文里面 codec 你要绑定的编码器/解码器 options 固定填 NULL * 绑定之前 上下文应该做相应参数初始化 音频参数 time_base 时间基 time_base 采集第一个音频数据 发生 1/48000 S 采集第二个音频数据 发生 2/48000 S .............................. 后期在音视频同步有关 sample_fmt 采样格式 AV_SAMPLE_FMT_S16 sample_rate 采样率 48000 channels 2 bit_rate: 32K 64K 96K 128K 192K.... channel_layout: AV_CH_LAYOUT_STEREO frame_size: 1024 函数返回值 绑定成功 返回 0 代表的你的编码器/解码器可以开始工作了 失败则返回 非 0 4.3.3 av_samples_get_buffer_size 函数功能开辟空间 FFMPEG 的空间概念 你通过 FFMPEG 读取的设备数据/文件数据 你通过 FFMPEG 编码读取来数据 已经你解码读出来数据 由 FFMPEG 内部开辟空间 这个空间 没有 释放 int av_samples_get_buffer_size( linesize;//行大小 给你往里面填充 声道数 采样数 采样格式 对齐方式 1 字节对齐 ); 通过你提供的参数算出你需要一个数据包空间大小 av_samples_fill_arrays(frame-data,linesize,buf,2,1024,AV_SAMPLE_F MT_S16,1); 绑定到哪里 绑定行大小 绑定数据缓冲区 空间 声道数 采样数 采样格式 几个字节对其 4.3.4 读取音频数据、写入音频数据
读取函数
avcodec_send_frame();
写入函数
avcodec_receive_packet();
5音频解码 5.1 解码流程 1打开输入流(文件) avformat_open_input(); 2从文件中获取输入的流信息 获取的流信息不确定是音频设备还是视屏设备亦或者是音视频 所以需要对获取的数据进行解析和判断、 avformat_find_stream_info(); 3寻找对应的解码器 创建解码器上下文把获取到的信息填充解码器上下文 然后绑定解码器上下文 avcodec_find_decoder(); 创建解码器上下文 avcodec_alloc_context3(); 寻找到音频流的参数信息拷贝给上下文 avcodec_parameters_to_context(); 4持续接收输入流的数据包 送到解码器里面 读取解码后的数据 avcodec_send_frame(); avcodec_receive_frame(); 5.2核心接口函数 函数功能主要是从打开的输入流文件里面获取流信息 头文件libavformat/avformat.h 函数的原型 int avformat_find_stream_info( AVFormatContext *ic, AVDictionary **options ); 函数参数 ICavformat_open_input()函数的返回值 options: 填 NULL 设置相关参数 fctx-nb_streams;//有几个媒体信息 fctx-streams[0];//第一个流信息 fctx-streams[1];//第二个流信息 fctx-streams[0]-codecpar//流的信息结构体 fctx-streams[0]-codecpar//流的信息结构体 fctx-streams[0]-codecpar-codec_id;//编码器 ID fctx-streams[0]-codecpar-codec_type;//音频/还是视频 函数功能主要是拷贝编码器/解码器的参数信息 函数的原型 int avcodec_parameters_to_context( AVCodecContext *codec, const AVCodecParameters *par ); 函数的参数 codec 已经创建的编解码器上下文结构体 par 我们刚才在 avformat_find_stream_info 发现流里面信息 fctx-streams[0]-codecpar 函数返回值 拷贝成功返回 0 拷贝失败返回 非 0 解码功能实例参考
#include stdio.h
#include stdlib.h
#include stdint.h
#include string.h
#include unistd.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h#include libavcodec/avcodec.h
#include libavutil/avutil.h
#include libavdevice/avdevice.h
#include libavformat/avformat.h
int video_index;
int audio_index;
int main(int argc,char **argv)
{if(argc !2 ){printf(Usage Is Errors!\r\n);return -1;}//1 打开流输入 文件AVFormatContext * fctx avformat_alloc_context();int ret avformat_open_input(fctx,argv[1],NULL,NULL);if(ret 0 ){printf(为找到该文件文件打开失败 \r\n);return -1;}//2从里面获取流信息ret avformat_find_stream_info(fctx,NULL);if(ret 0 ){printf(这个文件没有 流信息 \r\n);return -1;}printf(寻找到里面的流信息 \r\n);//3寻找到的信息有哪些fctx-nb_streams;//有几个媒体信息printf(有 %d 个流信息 \r\n,fctx-nb_streams);fctx-streams[0];//第一个流信息fctx-streams[1];//第二个流信息fctx-streams[0]-codecpar-codec_id;//编码器 IDfctx-streams[0]-codecpar-codec_type;//音频/还是视频for(int i0;ifctx-nb_streams;i){if(fctx-streams[i]-codecpar-codec_type AVMEDIA_TYPE_VIDEO){video_index i;}else if(fctx-streams[i]-codecpar-codec_type AVMEDIA_TYPE_AUDIO){audio_index i;}}printf(第%d 条流是视频 第%d 条流是音频!\r\n,video_index,audio_index);printf(视频流对应解码器 ID%x\t 音频对应的解码器%x\r\n,\fctx-streams[video_index]-codecpar-codec_id,\fctx-streams[audio_index]-codecpar-codec_id);//4寻找音频的解码器AVCodec * audio_codec avcodec_find_decoder_by_name(libfdk_aac);//AVCodec * audio_codec avcodec_find_decoder(fctx-streams[audio_index]-codecpar-codec_id);if(audio_codec NULL){printf(没有寻找到对应的解码器 \r\n);return -1;}//5参数拷贝//创建一个 编解码器的上下文AVCodecContext * actx avcodec_alloc_context3(NULL);//把寻找到音频 流的参数信息拷贝给 上下文avcodec_parameters_to_context(actx,fctx-streams[audio_index]-codecpar);//6绑定解码器和上下文printf(采样率%d\r\n,actx-sample_rate);printf(采样格式%d\r\n,actx-sample_fmt);printf(声道数%d\r\n,actx-channels);ret avcodec_open2(actx,audio_codec,NULL);//actx-sample_fmt AV_SAMPLE_FMT_S16;//AV_SAMPLE_FMT_S16Pif(ret 0){printf(解码器创建失败请检查参数 \r\n);return -1;}printf(解码器创建初始化成功 你就可以解码 \r\n);//printf();//7:不断的读取流的信息 送入到 解码器AVPacket pkt;AVFrame * readfrm av_frame_alloc();FILE * file fopen(./test.pcm,w);while(!av_read_frame(fctx,pkt)){if(pkt.stream_index audio_index)//读取音频数据{//作解码avcodec_send_packet(actx,pkt);while(1){ret avcodec_receive_frame(actx,readfrm);if(ret -EAGAIN){break;}else if(ret 0){fwrite(readfrm-data[0],1,readfrm-linesize[0],file);fflush(file);}}}}return 0;
}
6:如何播放PCM音频数据文件 6.1SDL简介 SDL Simple DirectMedia Layer是一个非常流行和强大的跨平台开发库它主要被 用来开发视频游戏和实时多媒体应用程序。它提供了一系列的功能来处理视频、音频、键 盘、鼠标、操纵杆、图形硬件加速以及聚焦 3D 硬件的各种功能。 SDL 的 API 通过 C 编程语 言被设计和实现但存在多种语言的绑定方便不同的开发者使用不同的编程语言。 安装SDL库sudo apt-get install libsdl12-dev 6.2SDL音频播放参考示例代码 //SDL 的音频初始化部分 SDL_AudioSpec audioSpec; void Init_audio(void) { int audioFreq, audioChannels; double delay; SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER); audioSpec.freq 48000; audioSpec.channels 2; audioSpec.format AUDIO_S16SYS; audioSpec.samples 1024; audioSpec.callback NULL; audioSpec.userdata NULL; if (SDL_OpenAudio(audioSpec,NULL) 0) { printf(Error: 无法打开音频设备! %s\n,SDL_GetError()); SDL_Quit(); return; } SDL_PauseAudio(0); } //SDL 音频播放 SDL_QueueAudio(1,buf,readlen); 对讲机流程 1初始化声卡设备- 2初始化编码器和解码器、SDL声卡输出、初始化SDL的声卡输出- 3开辟相关的空间- 4创建套接字初始化服务器、客户端- 5创建两个线程 分别读取声卡数据音频数据编码成AAC的线程且发送到网络 第二个线程读取网络数据解码aac到pcm送入到SDL进行播放。