5

I want find out, if two audio files are same or one contains the other.

For this I use Fingerprint of 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());

to convert audio to byte array I use sound 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;
}

but when I execute it, I became at fingerprint.getFingerprintsSimilarity() an 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)

How can I compare 2 mp3 files with fingerprint in Java?

dur
  • 15,689
  • 25
  • 79
  • 125
anatoli
  • 1,663
  • 1
  • 17
  • 43

3 Answers3

2

I never did any audio stuff in Java before, but I looked into your code briefly. I think that musicg only works for WAV files, not for MP3. Thus, you need to convert the files first. A web search reveals that you can e.g. use JLayer for that purpose. The corresponding code looks like this:

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());
  }
}

Of course you should make sure that you do not convert each file again whenever the program starts, i.e. you should check if the WAV files already exist. I skipped this step and reduced the sample code to a minimal working version.

kriegaex
  • 63,017
  • 15
  • 111
  • 202
  • By making of programm to compare over 1000 mp3 songs, this would be a bad solution – anatoli Apr 11 '17 at 12:52
  • 2
    Please qualify your comment, the way it is it is just judgemental, but not very useful. "Bad solution" why? Because of storage space? CPU usage? Time needed for conversion? BTW, it is not very good style to present code for a single pair of files, not mentioning the need for batch processing at all. Quote: "How can I compare 2 mp3 files with fingerprint in Java?" I have answered your question correctly. If you think this solution is "bad", maybe you want choose a better library doing exactly what you imagine in a single step. I have no magic wand for you. – kriegaex Apr 11 '17 at 16:37
  • yay, my fault. I just thought there is a simpler solution to compare mp3 files, since there are quite fast programs for comparison over many files. Thanks – anatoli Apr 11 '17 at 18:22
0

For FingerprintSimilarityComputer(input1, input2), it suppose to take in the fingerprint of the loaded audio data and not the loaded audio data itself.

In your case, it should be:

// 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()
0

Maybe I am missing a point, but if I understood you right, this should do:

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

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

int ixS = 0;
int ixB = 0;

boolean contains = false;

for (; ixB<bigger.length; ixB++) {
    
    if (smaller[ixS] == bigger[ixB]) {
        ixS++;
        if (ixS == smaller.length) {
            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");
}
Apostolos
  • 10,033
  • 5
  • 24
  • 39
Torge
  • 2,174
  • 1
  • 23
  • 33
  • Is interessant idea (I self have currently a similar solution, to compare files), but nevertheless i want to use a fingerprint – anatoli Apr 09 '17 at 20:06