sound.musicg.fingerprint.FingerprintManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of etyllica Show documentation
Show all versions of etyllica Show documentation
A game engine made in pure java.
/*
* Copyright (C) 2012 Jacquet Wong
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sound.musicg.fingerprint;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import sound.musicg.dsp.Resampler;
import sound.musicg.processor.TopManyPointsProcessorChain;
import sound.musicg.properties.FingerprintProperties;
import sound.musicg.wave.Wave;
import sound.musicg.wave.WaveHeader;
import sound.musicg.wave.extension.Spectrogram;
/**
* Audio fingerprint manager, handle fingerprint operations
*
* @author jacquet
*
*/
public class FingerprintManager{
private FingerprintProperties fingerprintProperties=FingerprintProperties.getInstance();
private int sampleSizePerFrame=fingerprintProperties.getSampleSizePerFrame();
private int overlapFactor=fingerprintProperties.getOverlapFactor();
private int numRobustPointsPerFrame=fingerprintProperties.getNumRobustPointsPerFrame();
private int numFilterBanks=fingerprintProperties.getNumFilterBanks();
/**
* Constructor
*/
public FingerprintManager(){
}
/**
* Extract fingerprint from Wave object
*
* @param wave Wave Object to be extracted fingerprint
* @return fingerprint in bytes
*/
public byte[] extractFingerprint(Wave wave){
int[][] coordinates; // coordinates[x][0..3]=y0..y3
byte[] fingerprint=new byte[0];
// resample to target rate
Resampler resampler=new Resampler();
int sourceRate = wave.getWaveHeader().getSampleRate();
int targetRate = fingerprintProperties.getSampleRate();
byte[] resampledWaveData=resampler.reSample(wave.getBytes(), wave.getWaveHeader().getBitsPerSample(), sourceRate, targetRate);
// update the wave header
WaveHeader resampledWaveHeader=wave.getWaveHeader();
resampledWaveHeader.setSampleRate(targetRate);
// make resampled wave
Wave resampledWave=new Wave(resampledWaveHeader,resampledWaveData);
// end resample to target rate
// get spectrogram's data
Spectrogram spectrogram=resampledWave.getSpectrogram(sampleSizePerFrame, overlapFactor);
double[][] spectorgramData=spectrogram.getNormalizedSpectrogramData();
List[] pointsLists=getRobustPointList(spectorgramData);
int numFrames=pointsLists.length;
// prepare fingerprint bytes
coordinates=new int[numFrames][numRobustPointsPerFrame];
for (int x=0; x pointsListsIterator=pointsLists[x].iterator();
for (int y=0; y byteList=new LinkedList();
for (int i=0; i>8));
byteList.add((byte)x);
// next 2 bytes is y
int y=coordinates[i][j];
byteList.add((byte)(y>>8));
byteList.add((byte)y);
// next 4 bytes is intensity
int intensity=(int)(spectorgramData[x][y]*Integer.MAX_VALUE); // spectorgramData is ranged from 0~1
byteList.add((byte)(intensity>>24));
byteList.add((byte)(intensity>>16));
byteList.add((byte)(intensity>>8));
byteList.add((byte)intensity);
}
}
}
// end for each valid coordinate, append with its intensity
fingerprint=new byte[byteList.size()];
Iterator byteListIterator=byteList.iterator();
int pointer=0;
while(byteListIterator.hasNext()){
fingerprint[pointer++]=byteListIterator.next();
}
return fingerprint;
}
/**
* Get bytes from fingerprint file
*
* @param fingerprintFile fingerprint filename
* @return fingerprint in bytes
*/
public byte[] getFingerprintFromFile(String fingerprintFile){
byte[] fingerprint=null;
try {
InputStream fis=new FileInputStream(fingerprintFile);
fingerprint=getFingerprintFromInputStream(fis);
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return fingerprint;
}
/**
* Get bytes from fingerprint inputstream
*
* @param fingerprintFile fingerprint inputstream
* @return fingerprint in bytes
*/
public byte[] getFingerprintFromInputStream(InputStream inputStream){
byte[] fingerprint=null;
try {
fingerprint = new byte[inputStream.available()];
inputStream.read(fingerprint);
} catch (IOException e) {
e.printStackTrace();
}
return fingerprint;
}
/**
* Save fingerprint to a file
*
* @param fingerprint fingerprint bytes
* @param filename fingerprint filename
* @see fingerprint file saved
*/
public void saveFingerprintAsFile(byte[] fingerprint, String filename){
FileOutputStream fileOutputStream;
try {
fileOutputStream = new FileOutputStream(filename);
fileOutputStream.write(fingerprint);
fileOutputStream.close();
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
// robustLists[x]=y1,y2,y3,...
private List[] getRobustPointList(double[][] spectrogramData){
int numX=spectrogramData.length;
int numY=spectrogramData[0].length;
double[][] allBanksIntensities=new double[numX][numY];
int bandwidthPerBank=numY/numFilterBanks;
for (int b=0; b robustPointList=new LinkedList();
// find robust points
for (int i=0; i0){
int[] point=new int[]{i,j};
//System.out.println(i+","+frequency);
robustPointList.add(point);
}
}
}
// end find robust points
List[] robustLists=new LinkedList[spectrogramData.length];
for (int i=0; i();
}
// robustLists[x]=y1,y2,y3,...
Iterator robustPointListIterator=robustPointList.iterator();
while (robustPointListIterator.hasNext()){
int[] coor=robustPointListIterator.next();
robustLists[coor[0]].add(coor[1]);
}
// return the list per frame
return robustLists;
}
/**
* Number of frames in a fingerprint
* Each frame lengths 8 bytes
* Usually there is more than one point in each frame, so it cannot simply divide the bytes length by 8
* Last 8 byte of thisFingerprint is the last frame of this wave
* First 2 byte of the last 8 byte is the x position of this wave, i.e. (number_of_frames-1) of this wave
*
* @param fingerprint fingerprint bytes
* @return number of frames of the fingerprint
*/
public static int getNumFrames(byte[] fingerprint){
if (fingerprint.length<8){
return 0;
}
// get the last x-coordinate (length-8&length-7)bytes from fingerprint
int numFrames=((int)(fingerprint[fingerprint.length-8]&0xff)<<8 | (int)(fingerprint[fingerprint.length-7]&0xff))+1;
return numFrames;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy