简单了解什么是WAV?

它是微软公司为Windows系统开发的一种标准的数字音频可,直接存储声音波形,并且它的波形曲线还原的真实感很好,但是也有缺点:存储磁盘空间大,多用于存储简短的声音片段。

是PC机上最为流行的声音文件格式。


WAV解析样本

格式大小:采样率一般是:44.1K,16bit采样精度,存储:WAV格式大小 = 44.1KHz(采样率) X 16bit(采样位数) X 2(双声道) X  播放时间

WAV格式是没有压缩无损的,MP3格式是按1:12压缩保存的。

WAV结构

由三个块组成:如图:

前44个字节是音频文件的说明,也就是从44个字节后开始就是正式数据了

WAV文件'一般'由3个区块组成:RIFF chunk、Format chunk和Data chunk,当然不包括文件中还有一些附加块。

wav文件中的数据块是小端存储-但是Java以大端存储-所以在进制转换时要转换成大端:

Java大端:

默认网络传输字节为大端,java 全部为大端(与平台无关)

小端存储:字节或半字节的最低位字节(Least Significant Bit,LSB)放置于于内存最低位字节地址上。(通俗:低字节数据存储在低地址

大端存储:数据低位保存在内存的高地址中,数据的高位保存在内存的低地址中。

(通俗:低字节数据存储在低地址)

区别

1,简单:大端存储或小端存储都是由系统设计的,区别在于低地址存储的数据,因此可以写程序进行判断。

2,详情:计算机中以字节为存储单位,每个地址单元都对应着一个字节,对于大于8位的数据类型,就会产生在寄存器中存放顺序问题。

显示例子:

什么是寄存器(Register:

基本寄存器和移位寄存器两大类。基本寄存器只能并行送入数据,也只能并行输出。移位寄存器中的数据可以在移位脉冲作用下依次逐位右移或左移,数据既可以并行输入、并行输出,也可以串行输入、串行输出,还可以并行输入、串行输出,或串行输入、并行输出,十分灵活,用途也很广。


寄存器作用了解:是中央处理器内的组成部分。寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和位址。

寄存器又分为内部寄存器与外部寄存器,所谓内部寄存器,其实也是一些小的存储单元,也能存储数据。但同存储器相比,寄存器又有自己独有的特点:

功能:是存储二进制,它是由具有存储功能的触发器组合起来构成的。

寄存器中:

1,从前往后,先低字节,后高地址,一个存储单元,存放一个字节。

大端:

十进制数字:4328719365

十六进制:0x0102030405

:[0x01(低地址),0x02,0x03,0x04,0x05]

注意:这里很好展示了第一个单元是低地址!

小端:

还是一样十进制:4328719365

:[0x05(低地址),0x04,0x03,0x02,0x01]

注意:无论是小端存储或者大端存储,它读取到的永远是:0x0102030405

小端转进制成大端:

我们看个例子:

//转成大端
public static byte[] int_To_Byte_BigEnding(int num) {byte[] D = new byte[4];D[3] = (byte) (num & 0xff);D[2] = (byte) (num >> 8 & 0xff);D[1] = (byte) (num >> 16 & 0xff);D[0] = (byte) (num >> 24 & 0xff);return D;
}

大端转小端:

//转成大端
public static byte[] int_To_Byte_SmallEnding(int num) {byte[] D = new byte[4];D[0] = (byte) (num & 0xff);D[1] = (byte) (num >> 8 & 0xff);D[2] = (byte) (num >> 16 & 0xff);D[3] = (byte) (num >> 24 & 0xff);return D;
}

是不是明白道理就简单多了?--有人问oxff是什么意思?

oxff意思:

首先了解一下, &表示只有两个位同时为1,才能得到1, 0x代表16进制数,而0xff表示的数二进制1111 1111 占一个字节.和其进行&操作的数,最低8位,不会发生变化.

而这里只是为了取它的高低.

比如:

out.write(num&0xff)

取低八位写入高地址中


out.write((num>>8)&0xff)

取高八位写入地

正题:

了解完成后我们就可以开始,wav的讲解了。

首部地址:

什么是RIFF:是一种在标记块中存储数据的元格式,把资料储存在被标记的区块中,

前4个字节为资源交换文件标志。

1.整个WAV都是由RIFF:数据块组成,可以将整个WAV文件看作一个完整的RIFF数据块,在这个RIFF数据块中又包含若干的子块存放不同的信息。

2.首部结构如下:

截取方式:截取方式也很简单,我们以二进制读取后,以ASCII读取字串:

读取:

    public @NotNull static <V> ByteArrayOutputStream Io_P_OUT(V PATH) throws IOException {FileInputStream obtainData = new FileInputStream(PATH.toString());int StorageByte;byte[] StorageDataHome = new byte[(int) new File(PATH.toString()).length()];ByteArrayOutputStream RETURN_DATA = new ByteArrayOutputStream();while ((StorageByte = obtainData.read(StorageDataHome)) > 0) {RETURN_DATA.write(StorageDataHome, 0, StorageByte);RETURN_DATA.flush();}obtainData.close();return RETURN_DATA;}
System.out.println(new String(__response.Io_P_OUT("PATH").toByteArray(),StandardCharsets.US_ASCII));

这样就可以看到如下信息了:

Format-Chunk:

0x0C 4 String 'fmt'标志
0x10 4 UInteger 块长度
0x12  2  UShort PCM格式类别 
0x14 2 UShort 声道数目 
0x18 4 UInteger 采样率 
0x1C 4 UInteger 传输速率 
0x1E 2 UShort 数据块对齐 
0x20 2 UShort 每样本比特数 
0x22 2 UShort 可选

 附加块Fact-Chunk:

当使用压缩编码的WAV文件时,必须要有Fact-Chunk,这个块中只有一个数据,就是声道的采样总数.

Fact chunk前4个字节为"fact(ID)",然后是4字节的大小,表示本块包含数据的多少-不包含ID和SIZE.

偏移量 字节数 数据类型 内容
0x26 4 String 'fact'标志
0x2A 4 UInteger 块长度
0x2E 4 UInteger 附加信息

数据块Data-Chunk:

0x32 4 String 'data'文件标志(0x64617461)

0x36

4

UInteger

数据块总长

前一段是数据ID,后一段是:代表Data数据块的长度。

DataChunk块:头部和实际数据组成,数据块标示(4bytes)+数据块长度(4bytes)+实际数据。

编码包括了两方面内容,一是按一定格式存储数据,二是采用一定的算法压缩数据。

WAV格式对音频流的编码没有硬性规定,支持非压缩的PCM。

上代码,提取转换代码:

            @NotNull public static boolean _W(byte[] source,byte[] DATA,int Start ,int         End){if (DATA != null) {if (source.length-End >= (0)) {System.arraycopy(DATA, Start, source, 0, End);return true;}else {return false;}} else {return false;}}        --小端转大端读取public static byte[] Io_S_Ending_B(String Path) throws IOException {FileChannel F =(FileChannel) Files.newByteChannel(java.nio.file.Path.of(Path), java.nio.file.StandardOpenOption.READ);ByteBuffer B = ByteBuffer.allocate((int)     F.size());B.order(ByteOrder.LITTLE_ENDIAN);F.read(B);B.flip();byte[] Data=new             byte[B.remaining()];B.get(Data);return Data;}byte[]sub=__response.Io_S_Ending_B("路径XX.wav");byte[] pcm=new byte[sub.length];__response._W(pcm,sub,44,pcm.length-44);AudioFormat.Encoding A=new AudioFormat.Encoding("PCM_SIGNED");SourceDataLine auline;AudioFormat af = new AudioFormat(A,48000, 16, 2,(16/8)*2,48000,false);try {auline = AudioSystem.getSourceDataLine(af);} catch (LineUnavailableException e) {throw new RuntimeException(e);}try {auline.open(af);} catch (LineUnavailableException e) {throw new RuntimeException(e);}auline.start();ByteArrayInputStream D=new ByteArrayInputStream(pcm);byte[] DD = new byte[1024];while(D.read(DD)!=-1){auline.write(DD,0,DD.length);}

录音与转换

其实这和刚才的读取wav数据块一样是pcm音频数据

录音我们需要使用到TargetDataLine官方的API数据从声卡中捕获数据。

他的采样率一般是44.1K,16bit采样精度,双声道速率则为44.1K×16×2小端端序,wav格式保存,之前说过wav->对音频流的编码没有硬性规定,支持非压缩的PCM。脉冲编码调制格式。

        ThreadPoolExecutor core = new ThreadPoolExecutor(1, 2, 100, TimeUnit.MILLISECONDS,new LinkedBlockingDeque<>(10));//这里我直接使用线程池了,为了保证录音时,我们可以输入end结束,后续可以自行更改。//第一次输入System.out.println("Start开始end关闭");Scanner aa = new Scanner(System.in);String a = aa.next();if (a.equalsIgnoreCase("Start")) {core.submit(() -> {float a1 = 44000F;//采样int a2 = 16;//样本中的中位数8,16int a3 = 2;//声道boolean a4 = true;//签名boolean a5 = false;//给定参数//TargetDataLine是一种可以从中 DataLine 读取音频数据的类型。最常见的示例是从音频捕获设备获取数据的数据线//DataLine(简单来说就是捕获数据的)//AudioFormat通道样本AudioFormat.Encoding A=new AudioFormat.Encoding("PCM_SIGNED");DataLine.Info a6 = new DataLine.Info(TargetDataLine.class, new AudioFormat(A,a1,a2,a3,(a2 / 8) * a3,a1, a5));//音频编码 //每秒样本数 //每个样本中的位数 // 通道数(1 个用于单声道,2 个用于立体声,依此类推)//每帧中的字节数 //每秒帧数 //指示单个样本的数据是否以大端字节顺序存储(false 表示小端//通俗来讲就是匹配拿数据,最后一步时将数据以我们限定的格式输出TargetDataLine b = null;try {b = (TargetDataLine) AudioSystem.getLine(a6);} catch (LineUnavailableException e) {throw new RuntimeException(e);}System.out.println("开始录音");AudioFileFormat.Type a8 = null;//指定的文件类型File a9 = null;//声明文件地址a8 = AudioFileFormat.Type.WAVE;//类型a9 = new File("保存路径");//文件地址try {b.open();//音频所用格式b.start();AudioSystem.write(new AudioInputStream(b), a8, a9);//写入文件数据} catch (Exception ignored) {}});}//第二次输入Scanner aaaa = new Scanner(System.in);String aaaaa = aaaa.next();if (aaaaa.equalsIgnoreCase("end")) {System.exit(0);}

操作:输入不分大小start开始录音,end结束录音。


前面讲了提取音频的方法也可以自己练习一下,播放一下自己录的音频,提取各类信息。

完结

一起和Atomic君学习!。

java 录音并包装成wav格式的文件方法-与-WAV解析-大小端-寄存器!,提取wav数据音频,一篇讲完!相关推荐

  1. 将对象集合包装成JSON格式

    import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import ...

  2. 录音如何转换成mp3格式

    录音怎如何转换成mp3格式?因为我们知道录音的格式有很多种,其中常见的有WAV格式(Waveform Audio File Format):是一种无损音频文件格式,音质高保真,通常用于专业录音和音乐制 ...

  3. 使用Java将HTML转成Word格式文件

    转载自  使用Java将HTML转成Word格式文件 import java.io.ByteArrayInputStream; import java.io.File; import java.io. ...

  4. java如何把png转换成jpg_Java实现将png格式图片转换成jpg格式图片的方法【测试可用】...

    Java实现将png格式图片转换成jpg格式图片的方法[测试可用] 发布于 2020-4-9| 复制链接 摘记: 本文实例讲述了Java实现将png格式图片转换成jpg格式图片的方法.分享给大家供大家 ...

  5. 苹果录音怎么转换成mp3格式?

    如果要将苹果录音转换成其他格式来使用,MP3无疑是最好的选择,因为MP3适用的播放器广泛,而且在保障了音质的前提下,还拥有最佳的文件体积,绝对是音频格式转换的最佳选择,当然除了指定格式外.那苹果录音怎 ...

  6. java读写json格式的文件方法详解.txt,并批量存储进redis

    捐躯赴国难,视死忽如归.恸哭六军俱缟素,冲冠一怒为红颜.君子坦荡荡,小人长戚戚.风日晴和人意好,夕阳箫鼓几船归.民为贵,社稷次之,君为轻.Java 读写json格式的文件方法详解 文章录入:7747. ...

  7. pythonutf8转gbk,Python实现把utf-8格式的文件转换成gbk格式的文件

    需求:将utf-8格式的文件转换成gbk格式的文件 实现代码如下: 代码如下: def ReadFile(filePath,encoding="utf-8″): with codecs.op ...

  8. Java Maven项目打包成可执行jar文件

    在pom文件中添加一下内容 <build><plugins><plugin><!-- Build an executable JAR --><gr ...

  9. 把Form转换成TXT格式的文件

    把Form转换成TXT格式的文件 命令: frmcmp_batch INVIDITM.fmb apps/apps@md0yd201 Compile_All=yes Forms_Doc=yes Form ...

最新文章

  1. 如何向非技术人员解释“稀疏傅里叶变换”算法?
  2. ubuntu 设置开机执行脚本_ubuntu-18.04 设置开机启动脚本
  3. Google X垃圾分类机器人横空出世,再也不怕分不清干垃圾湿垃圾有害垃圾了
  4. composer搭建php框架,用 Composer构建自己的 PHP 框架之基础准备
  5. [linux驱动]linux块设备学习笔记(二)
  6. Installing SuiteSparse
  7. DB and RAC(11.2.0.3 ) Patch Set Update(11.2.0.3.6 )
  8. 来了 | Python 官方发布整套中文PDF文档(共27本)
  9. 一位全减器逻辑电路图_半减器逻辑原理图 [全减器]
  10. 2018-2019-2 网络对抗技术 20165322 Exp4 恶意代码分析
  11. 《生物化学与分子生物学》----酶促反应动力学----听课笔记(九)
  12. 智能汽车里究竟“藏”有多少传感器?
  13. 2、ESP8266入门(AT模式)——烧录固件
  14. 为什么法线贴图偏蓝色?
  15. Oracle任意字符串转换成拼音首字母简写
  16. babylon创建文字
  17. ARM汇编中的:比较指令--CMN / CMP / TEQ / TST
  18. android开发系列之性格测试,性格色彩测试android程序开发之十--输出结果
  19. ITPUB BLOG
  20. 小白入门:一听就懂的HCNA华为网络工程师课程-李云鹏-专题视频课程

热门文章

  1. python快速入门【六】----真题测试
  2. maven错误:unknow文件夹--报错:Failure to find xxx:pom:unknown
  3. 冷热温度正反向控制技术在换热器热疲劳试验中的应用
  4. 【论文笔记】半监督的多视图学习:Semi-supervised Multi-view Deep Discriminant Representation Learning
  5. php用while循环做出1到10的乘积,php 数组
  6. [WinApi] C#获取其他窗口文本框内容
  7. 2010-06-24 苏州印象
  8. [java] BlueJ 里显示 ERROR:找不到符号
  9. N76E003的中断向量函数
  10. 利用requests爬取各个城市的麦当劳餐厅位置