我是靠谱客的博主 高贵饼干,最近开发中收集的这篇文章主要介绍波形文件数据的表示,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

从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文件结构

 

转载于:https://my.oschina.net/dubenju/blog/829781

最后

以上就是高贵饼干为你收集整理的波形文件数据的表示的全部内容,希望文章能够帮你解决波形文件数据的表示所遇到的程序开发问题。

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

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

评论列表共有 0 条评论

立即
投稿
返回
顶部