我是靠谱客的博主 平常咖啡豆,最近开发中收集的这篇文章主要介绍睡眠音频分割及识别问题(十一)--基于Android的YAMNet音频识别(总结)WAV文件格式介绍Android端实现读取音频文件源码介绍,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

WAV文件格式介绍

WAV文件遵守资源交换文件格式之规则,在文件的前44(或46)字节放置标头(header),使播放器或编辑器能够简单掌握文件的基本信息,其内容以区块(chunk)为最小单位,每一区块长度为4字节,而区块之上则由子区块包裹,每一子区块长度不拘,但须在前头先宣告标签及长度(字节)。标头的前3个区块记录文件格式及长度;接着第一个子区块包含8个区块,记录声道数量、采样率等信息;接着第二个子区块才是真正的音频资料,长度则视音频长度而定。内容如下表所示。须注意的是,每个区块的端序不尽相同,而音频内容本身则是采用小端序。
在这里插入图片描述
Android端使用java对wav进行数据读取,具体实现参考AudioReader的readHead()方法代码细节。

Android端实现读取音频文件源码介绍

主要使用Java io库中的 InputStream 接口,实现读取文件的字节流信息。主要实现类为AudioReader类,工具类为Utils,项目代码结构如下所示:
在这里插入图片描述
PO包的文件说明如下:

  • AudioFragment为一个接口,存放0.975s音频文件的相关信息;
  • IAudioFragment 为AudioFragment实现的接口;
  • Score包含一个字符串(label)和一个浮点数(score),存放???;
  • AudioReader为读取wav文件信息、预测音频标签的实现类;
  • LabelsName存储着521个标签的字符串;
  • MyComparator主要实现对Score对象数组的排序;
  • Utils中包括几个常用的音频数据处理方法(工具类)。

IAudioFragment接口

该接口主要对功能进行初步定义。主要包含前N名的Score数组,以及实现是否在打鼾、咳嗽和打喷嚏。

public interface IAudioFragment { 
	float start = 0; 
	float end = 0; 
	public Score[] scores = null; 
	public abstract boolean isSnore(); 
	public abstract boolean isCough(); 
	public abstract boolean isSneeze(); 
	public Score[] getScores(); 
	public void setScores(Score[] scores); 
}

AudioFragment实现类

对接口IAudioFragment进行实现,实现原理为:只保存前5的评分时,若Snore标签在前5中,则isSnore()返回true,否则返回false,其他方法同理。其中浮点数start和end表示该AudioFragment对象的起始与结束时间。例如:当你传入一段10s的音频进行预测时,会返回一个AudioFragment对象数组,其数组中第一个元素的起始时间为start = 0,结束时间为end = 0.975;第二个元素的起始时间为start =0.975,结束时间为end = 1.950(单位s)。
以下为部分核心代码:

float start = 0; 
float end = 0; 
Score[] scores = null; 
Score scoreSnoring = null; // 打鼾 38 
Score scoreCough = null; // 咳嗽 42 
Score scoreSneeze = null; // 打喷嚏 44 
······ 
@Override public boolean isSnore() { 
	return isContain("Snore",scores); 
}
@Override public boolean isCough() { 
	return isContain("Cough",scores); 
}

Score类

该对象只包含两个属性,将标签与评分绑定在一个对象中。

String label; 
float score;

LabelsName类

主要存储521个标签的字符串数组,供其他类调用。

IAudioProcess接口

主要对音频的加载与处理功能的定义。

// 通过传入Android上下文环境,音频文件路径,获取该音频文件的输入流 
public InputStream initInputStream(Context context, String fileName); 
// 初始化Yamnet模型 
public Yamnet initYamnetModel(Context context); 
// 预测函数,该函数应该在传入音频文件后再调用,应该返回多个AudioFragment对象,AudioFragment对象中默认存储评分前5的标签 
public AudioFragment[] predict(); 
// 同predict(),可以指存储评分中前topN个标签 
public AudioFragment[] predict(int topN); 
// 在初始化后使用,对目标fileName音频文件进预测,返回多个AudioFragment对象,AudioFragment对象中存储评分前topN的标签 
public AudioFragment[] predictByAudioFile(String fileName,int topN);
// 预测0.975s音频数据的具体实现方法,Yamnet模型要求输入input为[-1,1]的长度为 15600的数组,经过预测得到评分结果,再与 start、end与topN一起用于构造一个 AudioFragment对象。 
public AudioFragment predictOneSecond(Yamnet model, float[] input, float start, float end, int topN); // 0.975s

AudioReader类

主要对IAudioReader进行实现。其构造函数必须传入解析的文件名,以及上下文环境。以下为构造函数:

/** 
* @param context Android Context 
* @param fileName The target wav format file that needs to be predicted 
* */
public AudioReader(Context context, String fileName){ 
	this.context = context; 
	this.fileName = fileName; 
	initInputStream(context,fileName); 
	getInstance(context); 
}

在安卓活动中构建AudioReader对象并执行预测的示例如下:
(1)在初始化时直接指定文件并预测

AudioReader audioReader = new AudioReader(this,"demo.wav"); 
AudioFragment[] audioFragments = audioReader.predict(); // 默认只保存 前5评分

(2)在初始化时直接指定文件并预测前10个标签

AudioReader audioReader = new AudioReader(this,"demo.wav"); 
AudioFragment[] audioFragments = audioReader.predict(10);

(3)在初始化后改变预测文件

AudioReader audioReader = new AudioReader(this,"demo.wav"); 
// 预测other.wav中评分前10的标签 
AudioFragment[] audioFragments = audioReader.predict("other.wav",10);

MyComprator类

主要对Score对象数组的排序,主要使用方法如下:

// resultScores 为Score对象数组,升序。在原有的resultScores上改变 
Arrays.sort(resultScores, new MyComprator());

Utils类

主要完成重复性工作,例如Byte与int的转换、Byte与String的转换、Byte与int的转换,打印AudioFragment数组。

最后

以上就是平常咖啡豆为你收集整理的睡眠音频分割及识别问题(十一)--基于Android的YAMNet音频识别(总结)WAV文件格式介绍Android端实现读取音频文件源码介绍的全部内容,希望文章能够帮你解决睡眠音频分割及识别问题(十一)--基于Android的YAMNet音频识别(总结)WAV文件格式介绍Android端实现读取音频文件源码介绍所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(36)

评论列表共有 0 条评论

立即
投稿
返回
顶部