文档章节

波形文件数据的表示

如比如比
 如比如比
发布于 2017/01/23 21:00
字数 926
阅读 264
收藏 0

从wav文件读取数据并用波的形式表示。

 

对于模拟信号不能直接数字化,根据采样定律通过模拟-数字转换才行。

采样定律

对于频率为fi的输入模拟信号,模数转换时的采样率为fs,要保证模数转换后的数字信号能够完全恢复到输入前的模拟信号,则必须满足:

fs≥2fimax

式中  fs为采样频率;fimax为模拟信号的最高频分量的频率。上式称为采样定律(或称奈魁斯特定律)。

 

采样后,接下来是量化。量化指将信号的连续取值(或者大量可能的离散取值)近似为有限多个(或较少的)离散值的过程。量化主要应用于从连续信号到数字信号的转换中。连续信号经过采样成为离散信号,离散信号经过量化即成为数字信号。注意离散信号并不需要经过量化的过程。例如CD音频信号就是按照44110Hz的频率采样,按16位元量化为有着65536(= 2^16)个可能取值的数字信号。

量化就是将模拟声音的波形转换为数字,表示采样值的二进制位数决定了量化的精度。量化的过程是先将整个幅度划分成有限个小幅度(量化阶距)的集合,把落入某个阶距内的样值归为一类,并赋予相同的量化值。

 

编码

 对量化结果进行大端字节序、小端字节序、混合序编码。

 

代码

以无损的wav(PCM) 为例。

 

package javay.test;



import java.io.File;

import java.io.IOException;

import java.nio.ByteBuffer;

import java.nio.ByteOrder;



import javax.sound.sampled.AudioFormat;

import javax.sound.sampled.AudioInputStream;

import javax.sound.sampled.AudioSystem;

import javax.sound.sampled.UnsupportedAudioFileException;



import javafx.application.Application;

import javafx.scene.Node;

import javafx.scene.Scene;

import javafx.scene.chart.LineChart;

import javafx.scene.chart.NumberAxis;

import javafx.scene.chart.XYChart;

import javafx.scene.chart.XYChart.Series;

import javafx.scene.layout.HBox;

import javafx.stage.Stage;



/**

 * 波形文件数据的表示

 * 只表示声道1的信息

 */

public class TestWaveDraw extends Application {

    // 常量

    private final String fileName = "music/dog01.wav"; // 要表示的声音文件

    private final double sec = 0.15; // 要表示的时长(s)



    // 获取声音信息用的变量

    private AudioFormat format = null;

    private int[] values = null;



    public static void main(String[] args) {

        launch(args);

    }



    @Override

    public void start(Stage primaryStage) throws Exception {

        // 字色的设置

        System.setProperty("prism.lcdtext" , "false" );



        // 场景图

        HBox root = new HBox();



        // 图

        init(); // 读取声音文件的信息到values

        root.getChildren().add(createLineChart()); // 折线



        // 现场

        Scene scene = new Scene(root, 900, 300);



        // 窗口

        primaryStage.setScene(scene);

        primaryStage.show();

    }



    /**

     * 读取声音文件的信息到values

     * @throws IOException

     * @throws UnsupportedAudioFileException

     */

    public void init() throws Exception {

        // 获取AudioInputStream

        File file = new File(fileName);

        AudioInputStream is = AudioSystem.getAudioInputStream(file);



        // 获取Format信息

        format = is.getFormat();

        System.out.println(format.toString());

        System.out.println("采样率:" + format.getSampleRate());

        System.out.println("帧大小:" + format.getFrameSize());

        System.out.println("样本大小:" + format.getSampleSizeInBits());



        // 计算获取的样本数

        // 指定时间的样本数

        int mount = (int) (format.getSampleRate() * sec);



        // 读取声音数据

        values  = new int[mount];

        for(int i = 0; i < mount; i ++) {

            // 1帧的大小

            int size = format.getFrameSize();

            byte[] data = new byte[size];

            int readedSize = is.read(data);



            // 读取失败时

            if( readedSize == -1 ){

                break;

            }



            // SampleSizeInBits

            switch( format.getSampleSizeInBits() ) {

                case 8:

                    values[i] = (int) data[0];

                    break;

                case 16:

                    values[i] = (int) ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN).getShort();

                    break;

                default:

                    break;

            }

        }



        // 关闭AudioInputStream

        is.close();

    }



    /**

     * 用折线图表示

     * @return Node

     */

    @SuppressWarnings("unchecked")

    public Node createLineChart() {

        // 折线图

        NumberAxis xAxis = new NumberAxis();

        NumberAxis yAxis = new NumberAxis();

        LineChart<Number, Number> chart = new LineChart<Number, Number>(xAxis, yAxis);

        chart.setMinWidth(900);



        //生成数据

        Series<Number, Number> series1 = new Series<Number, Number>();

        series1.setName("声道1");

        for(int i = 0; i < values.length; i ++) {

            series1.getData().add(new XYChart.Data<Number, Number>(i, values[i]));

        }



        // 登录数据

        chart.getData().addAll(series1);

        // 设置标题

        String title = String.format("『%s』的波形数据(采样率:%.1fHz)", fileName, format.getSampleRate());

        chart.setTitle(title);



        // 调整外观

        chart.setCreateSymbols(false); // 去掉符号

        series1.getNode().lookup(".chart-series-line").setStyle("-fx-stroke-width: 1px;"); // 细线



        return chart;

    }

}

 

执行结果

PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian

采样率:44100.0

帧大小:4

样本大小:16

PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian

采样率:44100.0

帧大小:4

样本大小:16


wav文件结构

 

© 著作权归作者所有

上一篇: 朗读
下一篇: URL编码
如比如比
粉丝 127
博文 178
码字总数 286951
作品 0
日本
程序员
私信 提问
python数据建模分析 - 语音识别

语音识别: Getting Started!首先,我们要知道语音的产生过程 voice.png 状态:由肺产生向外的气流,完全放松时声带张开,就是平时的呼吸。如果声带一张一合(振动)形成周期性的脉冲气流。这个...

语落心生
2017/08/07
0
0
Audition 用户指南——数字音频基础知识

为了方便学习,搬运 adobe 官网教程 声波 声音始于空气中的振动,如吉他弦、人的声带或扬声器纸盆产生的振动。这些振动一起推动邻近的空气分子,而轻微增加空气压力。压力下的空气分子随后推...

rieuse
2018/12/24
0
0
SerialTool

SerialTool是一个实用的串口调试工具,这款工具支持串口调试助手、波形显示和文件传输等功能。该工具软件使用GPL许可证发布。用户可以将波形文件保存为文本文件,然后使用Matlab等工具进行数...

过招铁是傻
2018/12/07
0
0
【高速接口-RapidIO】6、RapidIO核仿真与包时序分析

  一、软件平台与硬件平台      软件平台:        操作系统:Windows 8.1 64-bit        开发套件:Vivado2015.4.2      硬件平台:        评估板:ZYNQ-7 ZC...

SEOwhywhy
2018/12/15
0
0
Android系统音频开发遇到的几个问题,求指点

最近在Android系统上做一款APP,需要和硬件外设(基于HiJack)做数据交互,外设采集到业务数据并通过音频口将数据传给APP,同时App通过音频口输出符合硬件要求的波形来给外设供电。 外设向手...

andywster
2013/09/17
406
3

没有更多内容

加载失败,请刷新页面

加载更多

MySql双主架构原理

在企业中,一般系统架构的瓶颈会出现在数据库这一部分,mysql主从架构在很大程度上解决了这部分瓶颈,但是在mysql主从同步的架构也存在很多问题;比如:1.关于数据写入部分(也就是主库)往往很难做...

xiaomin0322
5分钟前
0
0
分布式系统中一致性哈希

问题场景 近年来B2C、O2O等商业概念的提出和移动端的发展,使得分布式系统流行了起来。分布式系统相对于单系统,解决了流量大、系统高可用和高容错等问题。功能强大也意味着实现起来需要更多...

Java领航员
7分钟前
0
0
接口限流算法:漏桶算法和令牌桶算法

漏桶算法 漏桶可以看作是一个带有常量服务时间的单服务器队列,如果漏桶(包缓存)溢出,那么数据包会被丢弃。这一点和线程池原理是很相似的。 把请求比作是水,水来了都先放进桶里,并以限定...

铁骨铮铮
14分钟前
0
0
Android 生成二维码工具类

/** * 生成条形码和二维码的工具 */public class ZXingUtils { /** * 生成二维码 要转换的地址或字符串,可以是中文 * * @param url * @param width ...

lanyu96
19分钟前
0
0
谈谈lucene的DocValues特性之SortedNumericDocValuesField

前面已经介绍过NumericDocValuesField,这里想强调一下SortedNumericDocValuesField是针对同一篇文档中一键多值的情况进行排序的,换句话说不同文档的同一字段值可以乱序。核心的写入流程与谈...

FAT_mt
27分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部