美文网首页
Android 音频入门之理论知识

Android 音频入门之理论知识

作者: ReleaseYH | 来源:发表于2019-10-28 10:19 被阅读0次

    简介

    音频是个专业术语,音频一词已用作一般性描述音频范围内和声音有关的设备及其作用。人类能够听到的所有声音都称之为音频,它可能包括噪音等。声音被录制下来以后,无论是说话声、歌声、乐器都可以通过数字音乐软件处理,把它制作成音频文件。而音频只是储存在计算机里的声音。

    简单讲,其实就是将采集到的音频模拟信号,经过一定的转换,变成方便在信道中传输的数字信号。在不同的使用场景,也许会使用不同的编码方式,那么音频质量、码率、安全系数等都不一样。

    音频基础知识

    采样和采样频率:
    一秒钟内采样的次数称为采样频率。采样频率越高,越接近原始信号,但是也加大了运算处理的复杂度。根据Nyquist采样定理,要想重建原始信号,采样频率必须大于信号中最高频率的两倍。人能感受到的频率范围为20HZ--20kHZ, 一般音乐的采样频率为44.1kHZ, 更高的可以是48kHZ和96kHZ,不过一般人用耳听感觉不出差别了。语音主要是以沟通为主,不需要像音乐那样清晰,用16k采样的语音就称为高清语音了。现在主流的语音采样频率为16kHz。

    采样位数:
    数字信号是用0和1来表示的。采样位数就是采样值用多少位0和1来表示,也叫采样精度,用的位数越多就越接近真实声音。如用8位表示,采样值取值范围就是-128--127,如用16位表示,采样值取值范围就是-32768--32767。现在一般都用16位采样位数。

    声道:
    声道是指处理的声音是单声道还是立体声。Android支持双声道立体声和单声道。CHANNEL_IN_MONO单声道,CHANNEL_IN_STEREO立体声。单声道在声音处理过程中只有单数据流,而立体声则需要左、右声道的两个数据流。显然,立体声的效果要好,但相应的数据量要比单声道的数据量加倍。

    码率:
    就是比特率。比特率是指每秒传送的比特(bit)数。码率=采样率X采样位数X声道数。

    音频采集和播放:
    一般用专门的芯片(通常叫codec芯片)采集音频,做AD转换,然后把数字信号通过I2S总线(主流用I2S总线,也可以用其他总线,比如PCM总线)送给CPU处理(也有的会把codec芯片与CPU芯片集成在一块芯片中)。当要播放时CPU会把音频数字信号通过I2S总线送给codec芯片,然后做DA转换得到模拟信号再播放出来。

    音频编码过程

    image

    时域转频域变化
    时域是描述数学函数或物理信号对时间的关系。
    在研究时域的信号时,常会用示波器将信号转换为其时域的波形
    频域是指在对函数或信号进行分析时,分析其和频率有关部份,而不是和时间有关的部份
    有兴趣的可以去了解一下傅里叶变换

    心理声学原理
    心理声学原理是指用功能强大的算法将我们听不到的音频信息去掉。
    20hz-20000hz之间的,才是人能听到的。之外的可以称为冗余数据。
    冗余数据还有被遮蔽掉的数据,分为频域遮蔽和时域遮蔽。

    量化编码
    通常也把音频采样过程叫脉冲编码调制编码,即PCM(Pulse Code Modulation)编码,采样值也叫PCM值。
    PCM通过抽样、量化、编码三个步骤将连续变化的模拟信号转换为数字编码。

    image

    如图,我们首先对一段音频片段进行10次抽样。
    每次采样,都存在不同的振幅。为了实现以数字码表示样值,必须采用“四舍五入”的方法把样值分级“取整”,使一定取值范围内的样值由无限多个值变为有限个值。这一过程称为量化。
    然后我们将不同的样值进行编码,将十进制的值转化为计算机认识的二进制的值。
    最后根据二进制的值,我们转化为数字信号。就是所形成的方波。

    音频压缩

    音频压缩类型
    1.有损压缩,就是消除冗余数据。音频采集过程中采集到各种各样的声音,只有一部分是人能识别出来的。其他的声音,我们直接删除掉。恢复回来的时候没有了,所以称为有损压缩。
    2.哈夫曼无损压缩,利用数据的统计冗余进行压缩,可完全恢复原始数据而不引起任何数据丢失的,称为无损压缩。

    使用音频压缩技术的原因
    要计算一个PCM音频流的码率是一件很轻松的事情,采样率值×采样大小值×声道数。一个采样率为44.1KHz,采样大小为16bit,双声道的PCM编码的音频文件,它的码率则为 44.1K×16×2 =1411.2 Kbps。注意这边的单位是小b,单位是位。如果我们将单位转换为字节,则需要将码率除以8,就可以得到这个WAV的数据速率,即176.4KB/s。这表示存储一秒钟采样率为44.1KHz,采样大小为16bit,双声道的PCM编码的音频信号,需要176.4KB的空间,1分钟则约为10.34M,这对大部分用户是不可接受的,尤其是喜欢在电脑上听音乐的朋友,要降低磁盘占用,只有2种方法,降低采样指标或者压缩。降低指标是不可取的,因此专家们研发了各种压缩方案。
    MP3发展已经有10个年头了,MP3作为前几年最为普及的音频压缩格式,他是MPEG(MPEG:Moving Picture Experts Group) Audio Layer-3的简称,是MPEG1的衍生编码方案,1993年由德国Fraunhofer IIS研究院和汤姆生公司合作发展成功。MP3可以做到12:1的惊人压缩比并保持基本可听的音质,在当年硬盘天价的日子里,MP3迅速被用户接受,为大家所大量接受。

    常见音频的压缩编码
    目前主要有三大技术标准组织制定压缩标准:
    a)ITU,主要制定有线语音的压缩标准(g系列),有g711/g722/g726/g729等。
    b)3GPP,主要制定无线语音的压缩标准(amr系列等), 有amr-nb/amr-wb。后来ITU吸纳了amr-wb,形成了g722.2。
    c)MPEG,主要制定音乐的压缩标准,有11172-3,13818-3/7,14496-3等。
    一些大公司或者组织也制定压缩标准,比如iLBC,OPUS。

    目前市场编解码器性能比较OPUS > Vorbis > AAC ,其他的已经随时间慢慢退出市场了

    在android中使用最多的音频文件莫属于mp3文件。如果读取一些mp3文件的一些格式信息呢。在代码中可以这样实现。

    通过一个MP3文件地址,解析文件信息。
    假设现在有一个地址

    String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "莫文蔚-外面的世界.mp3";
    
    

    通过MediaMetadataRetriever来解析MP3文件信息
    代码如下

    MediaMetadataRetriever mmr = new MediaMetadataRetriever();
            mmr.setDataSource(path);
    Log.d(TAG, "parseMp3File名称: " + mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE));
    Log.d(TAG, "parseMp3File专辑: " + mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM));
    Log.d(TAG, "parseMp3File歌手: " + mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST));
    Log.d(TAG, "parseMp3File码率: " + mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE));
    Log.d(TAG, "parseMp3File时长: " + mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
    Log.d(TAG, "parseMp3File类型: " + mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE));
    
    

    MediaMetadataRetriever类可以解析出媒体文件的基本信息,例如音频和视频文件。视频文件可以解析出,视频的宽、高等信息。具体可以解析出哪些信息,可以自行查看该类。

    获取MP3专辑图片也是通过MediaMetadataRetriever类获取,只是跟普通字符信息获取方式不同,代码如下:

     byte[] data = mmr.getEmbeddedPicture();
     Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
     imageView.setImageBitmap(bitmap);
    
    

    类用完,要记得释放:

     mmr.release();
    
    

    获得mp3文件的频率,通过MediaFormat类,代码如下:

    MediaExtractor mex = new MediaExtractor();
    try {
          mex.setDataSource(path);
      } catch (IOException e) {
          e.printStackTrace();
     }
    MediaFormat mf = mex.getTrackFormat(0);
    int sampleRate = mf.getInteger(MediaFormat.KEY_SAMPLE_RATE);
    mex.release();
    Log.d(TAG, "parseMp3File频率: " + sampleRate);
    

    下篇,将详细讲解mp3音频的拓展使用。

    参考于:
    https://www.jianshu.com/p/916813e847d3
    https://www.jianshu.com/p/e38178f008ab

    相关文章

      网友评论

          本文标题:Android 音频入门之理论知识

          本文链接:https://www.haomeiwen.com/subject/afevvctx.html