Java 比较两个音频文件与指纹

Java compare two audio files with fingerprint

我想知道,如果两个音频文件相同或一个包含另一个。

为此我使用 musicg

的指纹
byte[] firstAudio = readAudioFileData("first.mp3");
byte[] secondAudio = readAudioFileData("second.mp3");

FingerprintSimilarityComputer fingerprint = 
            new FingerprintSimilarityComputer(firstAudio, secondAudio);

FingerprintSimilarity fingerprintSimilarity = fingerprint.getFingerprintsSimilarity();

System.out.println("clip is found at " + fingerprintSimilarity.getScore());

将音频转换为字节数组我使用声音 API

public static byte[] readAudioFileData(final String filePath) {
    byte[] data = null;
    try {
        final ByteArrayOutputStream baout = new ByteArrayOutputStream();
        final File file = new File(filePath);
        final AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file);

        byte[] buffer = new byte[4096];
        int c;
        while ((c = audioInputStream.read(buffer, 0, buffer.length)) != -1) {
            baout.write(buffer, 0, c);
        }
        audioInputStream.close();
        baout.close();
        data = baout.toByteArray();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return data;
}

但是当我执行它时,我变成了 fingerprint.getFingerprintsSimilarity()Exception

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 15999
at com.musicg.fingerprint.PairManager.getPairPositionList(PairManager.java:133)
at com.musicg.fingerprint.PairManager.getPair_PositionList_Table(PairManager.java:80)
at com.musicg.fingerprint.FingerprintSimilarityComputer.getFingerprintsSimilarity(FingerprintSimilarityComputer.java:71)
at Main.main(Main.java:42)

如何比较 2 个 mp3 文件与 Java 中的指纹?

对于 FingerprintSimilarityComputer(input1, input2),它应该接收加载的音频数据的指纹,而不是加载的音频数据本身。

在你的情况下,应该是:

// Convert your audio to wav using FFMpeg

Wave w1 = new Wave("first.wav");
Wave w2 = new Wave("second.wav");

FingerprintSimilarityComputer fingerprint = 
        new FingerprintSimilarityComputer(w1.getFingerprint(), w2.getFingerprint());

// print fingerprint.getFingerprintSimilarity()

也许我漏掉了一点,但如果我理解正确,应该这样做:

byte[] firstAudio = readAudioFileData("first.mp3");
byte[] secondAudio = readAudioFileData("second.mp3");

byte[] smaller = firstAudio.length <= secondAudio.lenght ? firstAudio : secondAudio;
byte[] bigger = firstAudio.length > secondAudio.length ? firstAudio : secondAudio;

int ixS = 0;
int ixB = 0;

boolean contians = false;

for (; ixB<bigger.length; ixB++) {

    if (smaller[ixS] == bigger[ixB]) {
        ixS++;
        if (ixS == smaller.lenght) {
            contains = true;
            break;
        }
    }
    else {
        ixS = 0;
    }
}

if (contains) {
    if (smaller.length == bigger.length) {
        System.out.println("Both tracks are equal");
    }
    else {
        System.out.println("The bigger track, fully contains the smaller track starting at byte: "+(ixB-smaller.lenght));
    }
}
else {
    System.out.println("No track completely contains the other track");
}

我以前从未在 Java 中做过任何音频内容,但我简要地查看了您的代码。我认为 musicg 只适用于 WAV 文件,不适用于 MP3。因此,您需要先转换文件。网络搜索显示您可以,例如为此目的使用 JLayer。相应的代码如下所示:

package de.scrum_master.so;

import com.musicg.fingerprint.FingerprintManager;
import com.musicg.fingerprint.FingerprintSimilarity;
import com.musicg.fingerprint.FingerprintSimilarityComputer;
import com.musicg.wave.Wave;
import javazoom.jl.converter.Converter;
import javazoom.jl.decoder.JavaLayerException;

public class Application {
  public static void main(String[] args) throws JavaLayerException {
    // MP3 to WAV
    new Converter().convert("White Wedding.mp3", "White Wedding.wav");
    new Converter().convert("Poison.mp3", "Poison.wav");
    // Fingerprint from WAV
    byte[] firstFingerPrint = new FingerprintManager().extractFingerprint(new Wave("White Wedding.wav"));
    byte[] secondFingerPrint = new FingerprintManager().extractFingerprint(new Wave("Poison.wav"));
    // Compare fingerprints
    FingerprintSimilarity fingerprintSimilarity = new FingerprintSimilarityComputer(firstFingerPrint, secondFingerPrint).getFingerprintsSimilarity();
    System.out.println("Similarity score = " + fingerprintSimilarity.getScore());
  }
}

当然你应该确保在程序启动时不要再次转换每个文件,即你应该检查WAV文件是否已经存在。我跳过了这一步并将示例代码缩减为最小工作版本。