我必须用 Java 编写一个使用 StdAudio 的程序和 Picture在播放声音文件时创建声音文件的二维颜色可视化,但我不太确定如何操作。
有人可以告诉我我需要的一切,或者告诉我需要做什么来“转换”声音文件,以便图片可以读取它吗?
我可以从声音文件中获取样本并将它们作为 double 组返回,但是那如何创建图像呢?这些值如何与图像同步?
我一直在 eclipse 中玩耍,只是想弄清楚这可能如何工作,但我的代码最终变得一团糟。
private final static int SAMPLE_RATE = 44100;
private static int WIDTH = 500;
private static int HEIGHT = 100;
private static JFrame frame;
private static Picture pic;
public static void main(String[] args) throws IOException
{
pic = new Picture(WIDTH, HEIGHT); // <- blank black image
String audioFile = "SampleTest2.wav";
double[] audio = StdAudio.read(audioFile);
frame = new JFrame();
frame.setContentPane(pic.getJLabel());
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setTitle("Sound Visualization");
frame.setResizable(false);
frame.pack();
frame.setVisible(true);
for (int k = 0; k < audio.length; k++)
StdAudio.play(audio[k]);
for (int i = 0; i < pic.width(); i ++)
{
for (int j = 0; j < pic.height(); j++)
{
pic.set(i, j, toColor(audio[SAMPLE_RATE + i]));
//frame.setContentPane(pic.getJLabel());
}
frame.repaint();
}
}
private static Color toColor(double colVal)
{
int r = (int) (((colVal + 1) / 2) * 255);
int g = (int) (((colVal + 1) / 2) * 255);
int b = (int) (((colVal + 1) / 2) * 255);
return new Color(r, g, b);
}
最佳答案
要使用StdAudio
,您需要采样率为44100
的wav
文件。这意味着该声音的每一秒都包含 44100 个值(样本)。当您使用方法 double[] read(String filename)
加载持续时间为 1 秒的此类文件时,您将获得一个包含 44100 个元素的数组。该方法的 Javadoc 告诉我们这些值将在 -1.0 和 +1.0 之间。我们可以迭代每个样本,将值从 -1..1 范围映射到 0..255 范围(因为颜色需要从 0 到 255 的值),并用该颜色绘制每个像素。为了获得更好的效果,我们不要绘制单个像素,而是绘制 100 个像素的列。
我将创建 500x100 的图像。它仅显示 500 个样本,因此表示 500/44100 = 仅 0.01 秒。要创建该尺寸的空图片,请使用:
Picture p = new Picture(500, 100);
要沿图像绘制单独的像素,请使用:
for (int i = 0; i < 500; i++) {
p.set(i, 0, color);
}
要显示此图片,请使用:
p.show();
接下来,要创建颜色,我们需要 3 个值:红色、绿色和蓝色分量。这里我们只有一个值,因此生成的图像将是一张灰度图像,因为每个分量的饱和度都将是相同的值new Color(value, value, value)
。要快速将范围从 -1..1 转换为 0..255,请使用以下公式:(int) (((d + 1)/2) * 255)
我使用了该站点的第一个声音文件:
http://www.music.helsinki.fi/tmt/opetus/uusmedia/esim/index-e.html我获得的图像是:
我使用的代码是:
import java.awt.Color;
import java.io.IOException;
public class StackOverflow58899141 {
private static int IMAGE_WIDTH = 500;
private static int IMAGE_HEIGHT = 100;
static String filename = "O:\\1.wav";
public static void main(final String[] args) throws IOException {
// reading sound file to samples
double[] samples = StdAudio.read(filename);
// creating empty image
Picture p = new Picture(IMAGE_WIDTH, IMAGE_HEIGHT);
// filling image from left to right
for (int i = 0; i < IMAGE_WIDTH; i++) {
// filling image from top to bottom
for (int j = 0; j < IMAGE_HEIGHT; j++) {
// adding 44100 to skip 1s of silence at the beginning
p.set(i, j, doubleToColor(samples[44100 + i]));
}
}
p.show();
}
// convert number from range -1.0..1.0 to 0..255
private static Color doubleToColor(double d) {
int val = (int) (((d + 1) / 2) * 255);
return new Color(val, val, val);
}
}
现在您已经开始了解它的工作原理了。虽然 Picture
类允许轻松保存图像,但它不允许动画。要实现这一目标,您需要 create own JFrame and draw image并延迟绘制每一列像素以获得动画效果。
关于java - 转换音频文件以创建图像,并将音频文件转换为 Picture 类可用的格式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58899141/