概述
2019独角兽企业重金招聘Python工程师标准>>>
从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
最后
以上就是高贵饼干为你收集整理的波形文件数据的表示的全部内容,希望文章能够帮你解决波形文件数据的表示所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复