波形文件数据的表示
波形文件数据的表示
壶漏子 发表于12个月前
波形文件数据的表示
  • 发表于 12个月前
  • 阅读 244
  • 收藏 0
  • 点赞 0
  • 评论 0

标题:腾讯云 新注册用户域名抢购1元起>>>   

摘要: JavaFX

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

 

标签: wav JavaFX 声音 表示
共有 人打赏支持
粉丝 123
博文 175
码字总数 281650
×
壶漏子
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: