转换音频文件以创建图像,并将音频文件转换为类Picture可使用的格式

时间:2019-11-17 09:33:54

标签: java image-processing audio visualization javasound

我必须用Java编写一个程序,该程序使用StdAudioPicture来创建声音文件在播放时的有趣的二维彩色可视化效果,但我确实确定该怎么做。

有人可以告诉我我需要做的所有事情,或者告诉我做些什么来“转换”声音文件,以便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);
}`

1 个答案:

答案 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,我得到的图像是:
enter image description here

我使用的代码是:

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并延迟绘制每列像素才能获得动画效果。