loading请求处理中...

android音频开发

2021-12-02 18:31:48 阅读 11574次 标签: 音频开发 作者: 陈先生12121
在音频技术的发展中,我们需要对声音有所了解,掌握音频的基本知识,这样我们才能更好地发展这项技术。

首先介绍了音频的基本知识,然后介绍了音频量化与编码、音频压缩技术、音频编解码器的选择。

声音三要素

  • 音调 : 就是音频,男生->女生->儿童。

声音频率的高低叫做音调。表示人的听觉分辨一个声音的调子高低的程度。音调主要由声音的频率决定,同时也与声音强度有关。对一定强度的纯音,音调随频率的升降而升降;对一定频率的纯音、低频纯音的音调随声强增加而下降,高频纯音的音调却随强度增加而上升。

  • 音量: 振动的幅度。

音量又称响度、音强,是指人耳对所听到的声音大小强弱的主观感受,其客观评价尺度是声音的振幅大小。这种感受源自物体振动时所产生的压力,即声压。物体振动通过不同的介质,将其振动能量传导开去。人们为了对声音的感受量化成可以监测的指标,就把声压分成“级”——声压级,以便能客观的表示声音的强弱,其单位称为“分贝”(dB)。

  • 音色: 它与材质有很大关系,本质就是谐波。

音色(Timbre)是指不同的声音的频率表现在波形方面总是有与众不同的特性。不同的物体振动都有不同的特点。

我们为什么要了解声音,音频技术不是有音频采集,音频编码,音频解码,算法等等就行了么,还要了解这么基本的知识有必要么,如果你了解个音频技术里的倍速播放功能时,就你会发现当你倍速播放时,音调也发生了变化。

音频采集

音频采集一般使用 AudioRecod或者 MediaRecord

音频采集的来源是什么?

一般是指麦克风:MediaRecorder.AudioSource.MIC

关于音频是怎么采集的,到时候专门写一篇音频采集的文章,这章主要是了解音频基础知识。当我们采集到了声音数据后都要对声音数据进行量化。

音频量化的过程

获取模拟数据(即采集到的音频波片段的数据)——>采样(对音频波进行采样)——>量化(根据采样点的值进行一一量化)——>编码(根据样本序号进行编码)——>转换成数字信号(即把样本一一转换01这样的机器能识别的数字信号)

音频量化基本概念

  • 采样大小: 一个采样用多少bit存放。常用的是16bit(也有用8bit存放)

16bit 表示Y轴振幅的高度 2的16次方(声音的振幅最高也高示过65535)

  • 采样率: 采样频率可分为8k 、16k、 32k、 44.1k、 48k等(对于AAC来说是采用44.1K的采样率)

以44.1K为例,就是说每秒在模拟信号上,我们采样441000次,比如说20Hz的频率(20Hz也就是人听到的最低频率,20Hz的频率即每秒采样了20次),每秒钟正弦波里,要采集多少次呢,要采样2000次,那么对于高频呢,比如20000Hz,那么就要采样2次

  • 声道数: 单声道、双声道、多声道(什么叫双声道?就是有两个喇叭,多声道就是有多个喇叭)

AudioFormat.CHANNEL_IN_MONO 单声道,一个声道进行采样
AudioFormat.CHANNEL_IN_STEREO 双声道,两个声道进行采样

  • 音频采样精度

采样精度:声音样本大小bit/s表示。位数越高,声音的保真度越高。
采样精度决定了记录声音的动态范围,它以位(Bit)为单位,比如8位、16位。8位可以把声波分成256级,16位可以把同样的波分成65536级的信号。
它反映度量声音波形幅度的精度。例如,每个声音样本用16位(2字节)表示,测得的声音样本值是在0~65535的范围里,它的精度就是输入信号的1/65536。样本位数的大小影响到声音的质量,位数越多,声音的质量越高,而需要的存储空间也越多;位数越少,声音的质量越低,需要的存储空间越少。

一般都采用这个 AudioFormat.ENCODING_PCM_16BIT(官方文档表示,该采样精度保证所有设备都支持)

码率计算

要算一个PCM音频的码率是一件很轻松的事情,采样率 * 采样大小 * 声道数
例如:
采样率为44.1KHz
采样大小为16bit
双声道的PCM编码的WAV文件
它是码率为 44.1k * 16 * 2 =1411200b=1411.2Kb/s

每秒传送的比特(bit)数。单位为 bps(Bit Per Second),比特率越高,传送数据速度越快。

PCM

PCM是英文Pulse-code modulation的缩写,中文译名是脉冲编码调制。

我们知道在现实生活中,人耳听到的声音是模拟信号,PCM就是要把声音从模拟转换成数字信号的一种技术,他的原理简单地说就是利用一个固定的频率对模拟信号进行采样,采样后的信号在波形上看就像一串连续的幅值不一的脉冲,把这些脉冲的幅值按一定的精度进行量化,这些量化后的数值还要进行编码,就是用一组二进制码组来表示每一个量化值,然后记录到存储介质中,所有这些组成了数字音频的产生过程。

音频压缩技术

音频压缩技术有两种方法,如下:

  • 消除冗余数据(久损压缩技术)

在音频采集过程中,会采集到各种各样的声音,其中只有一部分声音是我们人能够识别出来的,其他声音我们可以直接删除掉,这样能够大大减少存储的数据,删除掉的这些数据,当我们压缩完之后是完全没有了也无法恢复。

  • 哈夫曼无损编码(无损压缩技术)

将人无法识别的声音删除之后,留下来的声音对其压缩编码,压缩后的编码还能恢复为原来一模一样的数据,这就称为无损压缩技术。

音频冗余信息

  • 压缩的主要方法是去除采集到的音频冗余信息,所谓冗余信息包括人耳听觉范围外的音频信号以及被掩蔽掉的音频信号

  • 信号的掩蔽可以分为:频域掩蔽、时域掩蔽

频域掩蔽: 人耳所能察觉的声音信号的频率范围为20Hz~20KHz,在这个频率范围以外的音频信号属于冗余信号;或一个强纯音会掩蔽在其附近同时发声的弱纯音,那么弱纯音也被掩蔽,弱纯音属于冗余信号。

时域掩蔽: 在时间上相邻的声音之间也有掩蔽现象,主要原因是人的大脑处理信息需要花费时间。同步掩蔽效应和不同频率声音的频率和相对竟是有关,而时间掩蔽则仅仅和时间有关。如果两个声音在时间上特别接近,分辨会有困难(如两个声音音量相差较大且两个声音间隔时间低于5毫秒,则其中弱的那个声音会听不到)。

下面简单列出常见的音频压缩格式:
MP3,AAC,OGG,WMA,Opus,FLAC,APE,m4a,AMR,等等

音频编码的过程

时域转频域变换 —(声学模型)—> 量化编码 —> 比特流格式 (也可以添加辅助的数据)—> 比特流

音频编解码器选型

常见的音频编码器

  • 常见的音频编码器包括 OPUS、AAC、Vorbis、Speex、iLBC、AMR、G.711等
  • 网上评测结果: OPUS>AAC>Vorbis

常见的音频编码器他们的性能对比就不一一列举了,感兴趣的可以网上查阅一下。下面重点介绍一下AAC编码器。

AAC介绍

为什么重点介绍AAC呢?

  • AAC是的应用范围广(市面上95%以上的都是AAC编码器)
  • 传输协议是用rtmp,RTMP是支持AAC的不支持OPUS
  • AAC是的编码质量非常高,有一个高保帧,保持音频的高保帧,这样也导致很多应用使用AAC

AAC为了解决什么问题?

  • AAC(Advanced Audio Coding) 目的是取代MP3格式
  • MPEG-4标准出现后,AAC加入了SBR技术和PS技术
  • 目前常用的规格有AAC LC、AAC HE V1、AAC HE V2

AAC规格

AAC +SBR -> AAC HE V1
AAC+SBR+PS -> AAC HE V2

AAC规格描述

  • AAC LC: (Low Complexity)低复杂度,码流128k
  • AAC HE V1: AAC LC +SBR(Spectral Band Replication)码流64k(码流减少了,音频质量也提高了)
  • AAC HE V2: AAC LC +SBR + PS(Parametric Stereo)码流32k(码流减少了,音频质量也提高了)

AAC格式

  • ADIF(Audio Data Interchange Format)这种格式只能从头开始解码,常用在磁盘文件中
  • ADTS(Audio Data Transport Stream)这种格式每一帧都有一个同步字,可以在音频流的任何位置开始解码,它似于数据流格式

AAC编码库那个好?

市面上的库:
Libfdk_AAC > ffmpeg AAC > libfaac > libvo_aacenc
Libfdk_AAC的编码效率更高

Android中播放音频文件一般都是使用MediaPlayer类来实现的,它对多种格式的音频文件提供了非常全面的控制


方法,从而使得播放音乐的工作变得十分简单。


首先创建一个MediaPlayer对象->调用setDataSource()方法来设置音频文件的路径->调用prepare()方法使MediaPlayer


进入到准备状态->调用start()方法可以播放音乐,pause()方法暂时停止播放,reset()方法完全停止播放->最后要调用release()方法释放资源


还是先看activity_main.xml


    android:orientation="vertical"

    android:layout_width="match_parent"

    android:layout_height="match_parent" >

 

    < Button

        android:id="@+id/play"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:text="Play" />

 

    < Button

        android:id="@+id/pause"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:text="Pause" />

 

    < Button

        android:id="@+id/stop"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:text="Stop" />

 

主活动


package com.gougoucompany.clarence.playaudiotest;

 

import android.Manifest;

import android.content.pm.PackageManager;

import android.media.MediaPlayer;

import android.os.Environment;

import android.support.annotation.NonNull;

import android.support.v4.app.ActivityCompat;

import android.support.v4.content.ContextCompat;

import android.support.v4.os.EnvironmentCompat;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

import android.widget.Toast;

 

import java.io.File;

 

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

 

    private MediaPlayer mediaPlayer = new MediaPlayer();

 

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        Button play = (Button) findViewById(R.id.play);

        Button pause = (Button) findViewById(R.id.pause);

        Button stop = (Button) findViewById(R.id.stop);

        play.setOnClickListener(this);

        pause.setOnClickListener(this);

        stop.setOnClickListener(this);

        if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.

        WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {

            ActivityCompat.requestPermissions(MainActivity.this, new String[] {

               Manifest.permission.WRITE_EXTERNAL_STORAGE

            }, 1);

        } else {

            initMediaPlayer(); //初始化MediaPlayer

        }

    }

 

    @Override

    public void onClick(View v) {

        switch(v.getId()) {

            case R.id.play:

                if(!mediaPlayer.isPlaying()) {

                    mediaPlayer.start(); //开始播放

                }

                break;

            case R.id.pause:

                if(mediaPlayer.isPlaying()) {

                    mediaPlayer.pause(); //暂停播放

                }

                break;

            case R.id.stop:

                if(mediaPlayer.isPlaying()) {

                    mediaPlayer.reset(); //停止播放

                    initMediaPlayer();

                }

                break;

            default:

                break;

        }

    }

 

    @Override

    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        switch(requestCode) {

            case 1:

                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    initMediaPlayer();

                } else {

                    Toast.makeText(this, "拒绝权限将无法使用程序", Toast.LENGTH_SHORT).show();

                    finish();

                }

                break;

            default:

                break;

        }

    }

 

    @Override

    protected void onDestroy() {

        super.onDestroy();

        if(mediaPlayer != null){

            mediaPlayer.stop();

            mediaPlayer.release();

        }

    }

 

    private void initMediaPlayer() {

        try {

            File file = new File(Environment.getExternalStorageDirectory(), "music.mp3");

            mediaPlayer.setDataSource(file.getPath()); //指定音频文件的路径

            mediaPlayer.prepare(); //让MediaPlayer进入到准备状态

        } catch (Exception e) {

            e.printStackTrace();

        }

    }


--------------------- 


开发公司推荐

成为一品威客服务商,百万订单等您来有奖注册中

留言( 展开评论

快速发任务

价格是多少?怎样找到合适的人才?

官方顾问免费为您解答

 
相关任务
DESIGN TASK 更多
区块链交易所的ui 二次开发

¥1000 已有2人投标

文件处理应用程序开发

¥5000 已有0人投标

车辆3D模型展示开发

¥5000 已有0人投标

数据展示网站开发

¥10000 已有7人投标

电视机顶盒安装包软件开发

¥20000 已有2人投标

sketchup插件开发

¥50000 已有0人投标