首页 > 解决方案 > 如何使一组频率准确地描绘解码的 mp3 文件?

问题描述

我正在使用 mp3spi 和 Triton,此代码将专门处理 192kbps mp3 文件。我面临的问题是 hz 的第一秒主要由以下组成:

0,0,0,0 或 255,255,255,255

我确实相信我可能没有正确跳过标题,在这种情况下,频率并不是该特定 ms 的 mp3 的真实描述。有没有人看到我跳过标题的方式有什么问题,或者我如何将字节添加到数组中?

换句话说,我想要它,所以位置 [0] 的数组等于位置 00:00:00 的 mp3,位置 [44100] 的数组正好等于 1 秒的歌曲。

这是我用于从 mp3 文件中读取字节并将其添加到 arraylist 字节的代码。

import javax.sound.sampled.*;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;


public class ReadMP3 {


private ArrayList<Integer> bytes = new ArrayList<>();
private AudioFormat decodedFormat;

public ReadMP3() throws UnsupportedAudioFileException, IOException {

    String filename = new ReadFiles().getFile();
    File file = new File(filename);
    AudioInputStream in = AudioSystem.getAudioInputStream(file);
    AudioInputStream din = null;
    AudioFormat baseFormat = in.getFormat();
    AudioFormat decodedFormat = new 
    AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
            baseFormat.getSampleRate(),
            16,
            baseFormat.getChannels(),
            baseFormat.getChannels() * 2,
            baseFormat.getSampleRate(),
            false);
    din = AudioSystem.getAudioInputStream(decodedFormat, in);
    this.decodedFormat = decodedFormat;

    int i = 0;
    while(true){
        int currentByte = din.read();
        if (currentByte == -1) {break;}
        bytes.add(i, currentByte);
        i++;
    }
    din.close();
    in.close();
}

这是我的代码的第二部分,我将 4 个字节添加到数组的每个索引,这样 array.length / 44100 就等于歌曲的长度(以秒为单位)。这意味着每个 array[i][4] 等于 1hz。并且 array[0][4] 到 array[44100][4] 是歌曲的第一秒。

public class AnalyzeMP3 {


//adds 4 bytes to offset[i], where each i represents 1hz, 
//and 44100hz=1sec

public static int[][] calculate(ReadMP3 mp3) {

    //calculates and prints how long the song is
    double seconds = mp3.getBytes().size() / 
    mp3.getDecodedFormat().getFrameRate() / 4;
    System.out.println("Length of song: " + (int)seconds + "s");

    //adds 4 values to i through the whole song
    int[][] offset  = new int[mp3.getBytes().size()/4][4];
    for(int i = 0; i < mp3.getBytes().size()/4; i++) {
        for(int j = 0; j < 4; j++) {
            offset[i][j] = mp3.getBytes().get(i+j);
        }
    }

    return offset;
}

}

标签: javaarraysbytemp3decoding

解决方案


感谢 Brad 和 VC.One 让我意识到自己的错误。首先,我必须将正确的值添加到 PCM 签名编码中,如下所示:

AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
            (float)44.1,       //samplerate
            16,                //sampleSizeInBits
            2,                 //channels
            626,               //frameSize
            (float)38.4615385, //frameRate
            false);            //bigEndian

然后我需要准确地表示数组中的 2 个通道。我上面在AnalyzeMP3类中的做法是错误的,应该像这样添加:

    //adds 4 values to i through the whole song
    int[][] offset  = new int[mp3.getBytes().size()/4][4];
    int counter = 0;
    for(int i = 0; i < mp3.getBytes().size()/4;i++) {
        for(int j = 0; j < 4; j++) {
            offset[i][j] = mp3.getBytes().get(counter);
            counter++;
        }

    }

进行这些更改后,数组的大小为 4351104。4351104 / 44100 等于歌曲长度(以秒为单位)。并且没有标题或任何我必须跳过的内容,该数组现在可以准确地表示整首歌曲,每秒有 44100 个频率。可以很容易地将其转换为将 10ms 表示为 441 个频率等。


推荐阅读