我必须用Java编写一个程序,该程序使用StdAudio和Picture来创建声音文件在播放时的有趣的二维彩色可视化效果,但我确实确定该怎么做。
有人可以告诉我我需要做的所有事情,或者告诉我做些什么来“转换”声音文件,以便Picture可以读取它吗? 我可以从声音文件中获取样本,并将其作为双精度数组返回,但是那怎么会创建图像呢?这些值甚至如何与图像同步?
我真的很困惑,我已经在月食中玩了几个小时,现在只是想弄清楚这怎么可能甚至起作用,但是我的代码最终变得一团糟。
更新:
`private最终静态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);
}`
答案 0 :(得分:0)
要使用StdAudio
,您需要wav
文件,其采样率为44100
。这意味着该声音的每一秒都包含44100个值(样本)。当使用方法double[] read(String filename)
加载持续时间为1秒的此类文件时,您将获得一个包含44100个元素的数组。该方法的Javadoc告诉我们,值将为between -1.0 and +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并延迟绘制每列像素才能获得动画效果。