All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sound.musicg.fingerprint.FingerprintManager Maven / Gradle / Ivy

There is a newer version: 6.0.0
Show newest version
/*
 * 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