【问题标题】:Converting audio file to create an Image, and converting audio file into a format usable by class Picture转换音频文件以创建图像,并将音频文件转换为图片类可用的格式
【发布时间】:2020-03-12 21:53:47
【问题描述】:

我必须用 Java 编写一个程序,它使用 StdAudioPicture 在声音文件播放时创建二维颜色可视化,但我不确定如何。

谁能告诉我我需要做的一切,或者告诉我需要做什么来“转换”声音文件以便它可以被图片读取?

我可以从声音文件中获取样本并将它们作为双精度数组返回,但是那怎么会创建图像呢?这些值怎么可能与图像同步?

我一直在 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);
}

【问题讨论】:

    标签: java image-processing audio visualization javasound


    【解决方案1】:

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

    【讨论】:

    • 好吧,我确实有正确的想法。我有 for(int i = 0; i
    • 同时播放声音和动画是两个不同的任务。可以,但同步取决于您,因为除了计算经过的时间外,无法判断当前播放的是哪个片段。
    • 另外,如果read()返回-1和+1之间的数组值,为什么我打印出数组中的每个值时,有些值小于-1和大于1?我看到了一个值为 9.0000074782828364E-5 或其他值
    • 9.0000074782828364E-5(注意E-5)表示9.0000074782828364×10^(-5) 所以它是0.000090000074782828364如果你喜欢这个答案记得mark it as accepted
    • 顺便说一下,StdAudio 中的方法 play() 对无效值有很好的保护:if (sample &lt; -1.0) sample = -1.0;if (sample &gt; +1.0) sample = +1.0;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-08
    • 1970-01-01
    • 1970-01-01
    • 2016-04-26
    • 1970-01-01
    相关资源
    最近更新 更多