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

标签 java image-processing audio visualization javasound

我必须用 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,您需要采样率为44100wav文件。这意味着该声音的每一秒都包含 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我获得的图像是:
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并延迟绘制每一列像素以获得动画效果。

关于java - 转换音频文件以创建图像,并将音频文件转换为 Picture 类可用的格式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58899141/

相关文章:

python - 如何使用轮廓(链码)计算物体的面积?

ios - 使用Linphone SDK时音频录制失败

ios - AudioOutputUnitStart替换音乐应用

java - 'mix class and interfaces in the same package' 是不好的做法吗?

android - 如何将图像分成两部分?

java - Java 中图像的组合重新缩放和颜色减少?

python - PIL 的 Image.convert() 函数如何使用模式 'P'

actionscript-3 - 在 Adob​​e AIR 应用程序中比较两个声音

Java - 2D 字符串数组、动态表和空指针异常

java - 有没有办法使用 BigInteger 进行迭代?