├── demo ├── test.mp3 ├── MusicURI.jar ├── dependencies.zip ├── MusicURIReferences.db └── README.txt ├── src ├── META-INF │ └── MANIFEST.MF ├── it │ └── univpm │ │ └── deit │ │ └── semedia │ │ └── musicuri │ │ ├── core │ │ ├── Result.class │ │ ├── Toolset.class │ │ ├── Toolset.java │ │ ├── MusicURIQuery.class │ │ ├── MusicURISearch.class │ │ ├── SearchStrategy.class │ │ ├── MusicURIDatabase.class │ │ ├── MusicURIReference.class │ │ ├── MusicURIWebSource.class │ │ ├── ResultRankingList.class │ │ ├── MusicURIDataSource.class │ │ ├── MusicURILocalSource.class │ │ ├── MusicURIDataSource.java │ │ ├── MusicURIWebSource.java │ │ ├── MusicURILocalSource.java │ │ ├── Result.java │ │ ├── SearchStrategy.java │ │ ├── ResultRankingList.java │ │ ├── MusicURIQuery.java │ │ ├── MusicURIReference.java │ │ └── MusicURIDatabase.java │ │ ├── statistics │ │ ├── Test.class │ │ ├── Stopwatch.class │ │ ├── TestCaseCaller.class │ │ ├── PerformanceStatistic.class │ │ ├── Stopwatch.java │ │ ├── Test.java │ │ ├── PerformanceStatistic.java │ │ └── TestCaseCaller.java │ │ ├── utils │ │ ├── dbadmin │ │ │ ├── DbPopulator.class │ │ │ ├── QueryObjectDbPopulator.class │ │ │ ├── QueryObjectDbPopulator.java │ │ │ └── DbPopulator.java │ │ ├── misc │ │ │ ├── MusicURILibraryDemo.class │ │ │ ├── SoCProjectLineCounter.class │ │ │ ├── SoCProjectLineCounter.java │ │ │ └── MusicURILibraryDemo.java │ │ └── experimental │ │ │ ├── FilenameScrambler.class │ │ │ ├── LambdaCalculator.class │ │ │ ├── DbAverageDistanceCalculator.class │ │ │ ├── Mpeg7XMAudioSignatureSearch.class │ │ │ ├── Mpeg7XMAudioSignatureSearch.java │ │ │ ├── DbAverageDistanceCalculator.java │ │ │ ├── LambdaCalculator.java │ │ │ └── FilenameScrambler.java │ │ └── webservice │ │ ├── client │ │ ├── MusicURIWebSearch.class │ │ ├── MusicURIWebSearchService.class │ │ ├── MusicURIWebSearchServiceLocator.class │ │ ├── MusicURIWebSearchSoapBindingStub.class │ │ ├── MusicURIWebSearch.java │ │ ├── MusicURIWebSearchService.java │ │ ├── MusicURIWebSearchServiceLocator.java │ │ └── MusicURIWebSearchSoapBindingStub.java │ │ └── server │ │ ├── MusicURIWebSearch.class │ │ └── MusicURIWebSearch.java ├── .project ├── .classpath ├── README.txt └── COPYING.txt └── README.md /demo/test.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/demo/test.mp3 -------------------------------------------------------------------------------- /demo/MusicURI.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/demo/MusicURI.jar -------------------------------------------------------------------------------- /demo/dependencies.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/demo/dependencies.zip -------------------------------------------------------------------------------- /demo/MusicURIReferences.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/demo/MusicURIReferences.db -------------------------------------------------------------------------------- /src/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: it.univpm.deit.semedia.musicuri.utils.misc.MusicURILibrary 3 | Demo 4 | 5 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/core/Result.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/core/Result.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/core/Toolset.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/core/Toolset.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/core/Toolset.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/core/Toolset.java -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | musicuri 2 | ======== 3 | 4 | A Java library for fingerprinting music files, assigning unique URIs to them, and matching them to unknown audio clips. 5 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/statistics/Test.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/statistics/Test.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/core/MusicURIQuery.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/core/MusicURIQuery.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/core/MusicURISearch.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/core/MusicURISearch.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/core/SearchStrategy.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/core/SearchStrategy.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/core/MusicURIDatabase.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/core/MusicURIDatabase.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/core/MusicURIReference.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/core/MusicURIReference.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/core/MusicURIWebSource.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/core/MusicURIWebSource.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/core/ResultRankingList.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/core/ResultRankingList.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/statistics/Stopwatch.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/statistics/Stopwatch.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/core/MusicURIDataSource.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/core/MusicURIDataSource.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/core/MusicURILocalSource.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/core/MusicURILocalSource.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/statistics/TestCaseCaller.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/statistics/TestCaseCaller.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/utils/dbadmin/DbPopulator.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/utils/dbadmin/DbPopulator.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/statistics/PerformanceStatistic.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/statistics/PerformanceStatistic.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/utils/misc/MusicURILibraryDemo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/utils/misc/MusicURILibraryDemo.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/utils/misc/SoCProjectLineCounter.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/utils/misc/SoCProjectLineCounter.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/utils/dbadmin/QueryObjectDbPopulator.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/utils/dbadmin/QueryObjectDbPopulator.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/utils/experimental/FilenameScrambler.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/utils/experimental/FilenameScrambler.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/utils/experimental/LambdaCalculator.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/utils/experimental/LambdaCalculator.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/webservice/client/MusicURIWebSearch.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/webservice/client/MusicURIWebSearch.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/webservice/server/MusicURIWebSearch.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/webservice/server/MusicURIWebSearch.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/webservice/client/MusicURIWebSearchService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/webservice/client/MusicURIWebSearchService.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/utils/experimental/DbAverageDistanceCalculator.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/utils/experimental/DbAverageDistanceCalculator.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/utils/experimental/Mpeg7XMAudioSignatureSearch.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/utils/experimental/Mpeg7XMAudioSignatureSearch.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/webservice/client/MusicURIWebSearchServiceLocator.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/webservice/client/MusicURIWebSearchServiceLocator.class -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/webservice/client/MusicURIWebSearchSoapBindingStub.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkourtesis/musicuri/HEAD/src/it/univpm/deit/semedia/musicuri/webservice/client/MusicURIWebSearchSoapBindingStub.class -------------------------------------------------------------------------------- /src/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | MusicURI 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/core/MusicURIDataSource.java: -------------------------------------------------------------------------------- 1 | package it.univpm.deit.semedia.musicuri.core; 2 | 3 | import java.io.File; 4 | import java.net.URL; 5 | 6 | /** 7 | * @author Dimitrios Kourtesis 8 | */ 9 | public interface MusicURIDataSource 10 | { 11 | public URL getDataSourceLocation(); 12 | public void index(File musicItemToIndex); 13 | public void identify(File musicItemToIdentify); 14 | public void listMusicURIReferences(); 15 | } 16 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/webservice/client/MusicURIWebSearch.java: -------------------------------------------------------------------------------- 1 | /** 2 | * MusicURIWebSearch.java 3 | * 4 | * This file was auto-generated from WSDL 5 | * by the Apache Axis 1.2.1 Jun 14, 2005 (09:15:57 EDT) WSDL2Java emitter. 6 | */ 7 | 8 | package it.univpm.deit.semedia.musicuri.webservice.client; 9 | 10 | public interface MusicURIWebSearch extends java.rmi.Remote 11 | { 12 | public java.lang.String getMusicURIReferenceList() throws java.rmi.RemoteException; 13 | public int getNumOfMusicURIReferences() throws java.rmi.RemoteException; 14 | public java.lang.String performSearch(java.lang.String xmlAudioSignature, java.lang.String filename) throws java.rmi.RemoteException; 15 | } 16 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/core/MusicURIWebSource.java: -------------------------------------------------------------------------------- 1 | package it.univpm.deit.semedia.musicuri.core; 2 | 3 | import java.io.File; 4 | import java.net.URL; 5 | 6 | /** 7 | * @author Dimitrios Kourtesis 8 | */ 9 | public class MusicURIWebSource implements MusicURIDataSource 10 | { 11 | private URL dataSourceLocation; 12 | 13 | public URL getDataSourceLocation() 14 | { 15 | return dataSourceLocation; 16 | } 17 | 18 | public void index(File musicItemToIndex) 19 | { 20 | // TODO Auto-generated method stub 21 | 22 | } 23 | 24 | public void identify(File musicItemToIdentify) 25 | { 26 | // TODO Auto-generated method stub 27 | 28 | } 29 | 30 | public void listMusicURIReferences() 31 | { 32 | // TODO Auto-generated method stub 33 | 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/core/MusicURILocalSource.java: -------------------------------------------------------------------------------- 1 | package it.univpm.deit.semedia.musicuri.core; 2 | 3 | import java.io.File; 4 | import java.net.URL; 5 | 6 | /** 7 | * @author Dimitrios Kourtesis 8 | */ 9 | public class MusicURILocalSource implements MusicURIDataSource 10 | { 11 | private URL dataSourceLocation; 12 | 13 | public URL getDataSourceLocation() 14 | { 15 | return dataSourceLocation; 16 | } 17 | 18 | public void index(File musicItemToIndex) 19 | { 20 | // TODO Auto-generated method stub 21 | 22 | } 23 | 24 | public void identify(File musicItemToIdentify) 25 | { 26 | // TODO Auto-generated method stub 27 | 28 | } 29 | 30 | public void listMusicURIReferences() 31 | { 32 | // TODO Auto-generated method stub 33 | 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/webservice/client/MusicURIWebSearchService.java: -------------------------------------------------------------------------------- 1 | /** 2 | * MusicURIWebSearchService.java 3 | * 4 | * This file was auto-generated from WSDL 5 | * by the Apache Axis 1.2.1 Jun 14, 2005 (09:15:57 EDT) WSDL2Java emitter. 6 | */ 7 | 8 | package it.univpm.deit.semedia.musicuri.webservice.client; 9 | 10 | public interface MusicURIWebSearchService extends javax.xml.rpc.Service { 11 | public java.lang.String getMusicURIWebSearchAddress(); 12 | 13 | public it.univpm.deit.semedia.musicuri.webservice.client.MusicURIWebSearch getMusicURIWebSearch() throws javax.xml.rpc.ServiceException; 14 | 15 | public it.univpm.deit.semedia.musicuri.webservice.client.MusicURIWebSearch getMusicURIWebSearch(java.net.URL portAddress) throws javax.xml.rpc.ServiceException; 16 | } 17 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/utils/misc/SoCProjectLineCounter.java: -------------------------------------------------------------------------------- 1 | package it.univpm.deit.semedia.musicuri.utils.misc; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.File; 5 | import java.io.FileNotFoundException; 6 | import java.io.FileReader; 7 | import java.io.IOException; 8 | 9 | 10 | /** 11 | * Utility class used for calculating the SoC (Summer of Code) LOC (Lines Of Code) in a java source code directory 12 | */ 13 | public class SoCProjectLineCounter 14 | { 15 | public static void main(String[] args) throws IOException 16 | { 17 | File directory = new File(args[0]); 18 | File[] allFiles = directory.listFiles(); 19 | File currentFile; 20 | int totalLinesOfCode = 0; 21 | 22 | for (int i=0; i< allFiles.length; i++) 23 | { 24 | currentFile = allFiles[i]; 25 | if (isJavaFile(currentFile)) totalLinesOfCode += countLines (currentFile); 26 | } 27 | System.out.println("Total Lines Of Java Code in Directory: " + directory.getName() + " - " + totalLinesOfCode); 28 | } 29 | 30 | private static int countLines(File file) throws IOException 31 | { 32 | BufferedReader br = new BufferedReader(new FileReader(file)); 33 | int line = 0; 34 | while(br.readLine() != null) line++; 35 | return line; 36 | } 37 | 38 | private static boolean isJavaFile(File file) 39 | { 40 | String fname = file.getName(); 41 | String extension = fname.substring(fname.lastIndexOf('.') + 1); 42 | if (extension.equalsIgnoreCase("java")) return true; 43 | else return false; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/core/Result.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2005, Dimitrios Kourtesis 3 | 4 | This file is part of MusicURI. 5 | 6 | MusicURI is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | MusicURI is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with MPEG7AudioEnc; see the file COPYING. If not, write to 18 | the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 19 | MA 02111-1307 USA 20 | */ 21 | 22 | package it.univpm.deit.semedia.musicuri.core; 23 | 24 | /** 25 | * @author Dimitrios Kourtesis 26 | */ 27 | public class Result 28 | { 29 | 30 | /** 31 | * A generic double value denoting the distance of the specific result from the query used in comparison 32 | */ 33 | public double distance; 34 | 35 | /** 36 | * The MD5 key contained in the MusicURIReference this result corresponds to 37 | */ 38 | public String md5; 39 | 40 | 41 | 42 | 43 | /** 44 | * Constructs a Result object by setting its private attributes to the ones specified 45 | * @param dist the distance of the correponding reference from the query it was compared with 46 | * @param key the MD5 key contained in the MusicURIReference this result corresponds to 47 | */ 48 | public Result (double dist, String key) 49 | { 50 | this.distance = dist; 51 | this.md5 = key; 52 | } 53 | 54 | /** 55 | * Compares a Result object with another by comparing their private attributes 56 | * (Experimental use only) 57 | * @param other the Result object to compare with 58 | */ 59 | public boolean isSameWith(Result other) 60 | { 61 | if (other != null) 62 | { 63 | 64 | if ((other.distance == this.distance) 65 | && other.md5.equalsIgnoreCase(this.md5)) 66 | { 67 | return true; 68 | } 69 | else return false; 70 | } 71 | else 72 | { 73 | System.out.println("other == null"); 74 | return false; 75 | } 76 | 77 | } 78 | 79 | 80 | }//end class 81 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/statistics/Stopwatch.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2005, John O'Hanley, Canada 3 | 4 | Code for this class was taken from http://www.javapractices.com/ 5 | */ 6 | 7 | package it.univpm.deit.semedia.musicuri.statistics; 8 | 9 | 10 | 11 | 12 | /** 13 | * Allows timing of the execution of any block of code. 14 | */ 15 | 16 | public final class Stopwatch 17 | { 18 | 19 | /** 20 | * Starts the stopwatch. 21 | * @throws IllegalStateException if the stopwatch is already running. 22 | */ 23 | public void start(){ 24 | if ( fIsRunning ) { 25 | throw new IllegalStateException("Must stop before calling start again."); 26 | } 27 | //reset both start and stop 28 | fStart = System.currentTimeMillis(); 29 | fStop = 0; 30 | fIsRunning = true; 31 | fHasBeenUsedOnce = true; 32 | } 33 | 34 | /** 35 | * Stops the stopwatch. 36 | * @throws IllegalStateException if the stopwatch is not already running. 37 | */ 38 | public void stop() { 39 | if ( !fIsRunning ) { 40 | throw new IllegalStateException("Cannot stop if not currently running."); 41 | } 42 | fStop = System.currentTimeMillis(); 43 | fIsRunning = false; 44 | } 45 | 46 | /** 47 | * Expresses the "reading" on the stopwatch. 48 | * @throws IllegalStateException if the Stopwatch has never been used, 49 | * or if the stopwatch is still running. 50 | */ 51 | public String toString() { 52 | validateIsReadable(); 53 | StringBuffer result = new StringBuffer(); 54 | result.append(fStop - fStart); 55 | result.append(" ms"); 56 | return result.toString(); 57 | } 58 | 59 | /** 60 | * Expresses the "reading" on the stopwatch as a numeric type. 61 | * @throws IllegalStateException if the Stopwatch has never been used, 62 | * or if the stopwatch is still running. 63 | */ 64 | public long toValue() { 65 | validateIsReadable(); 66 | return fStop - fStart; 67 | } 68 | 69 | // PRIVATE //// 70 | private long fStart; 71 | private long fStop; 72 | 73 | private boolean fIsRunning; 74 | private boolean fHasBeenUsedOnce; 75 | 76 | /** 77 | * @throws IllegalStateException if the watch has never been started, 78 | * or if the watch is still running. 79 | */ 80 | private void validateIsReadable() { 81 | if ( fIsRunning ) { 82 | String message = "Cannot read a stopwatch which is still running."; 83 | throw new IllegalStateException(message); 84 | } 85 | if ( !fHasBeenUsedOnce ) { 86 | String message = "Cannot read a stopwatch which has never been started."; 87 | throw new IllegalStateException(message); 88 | } 89 | } 90 | } 91 | 92 | -------------------------------------------------------------------------------- /src/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/utils/dbadmin/QueryObjectDbPopulator.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2005, Dimitrios Kourtesis 3 | 4 | This file is part of MusicURI. 5 | 6 | MusicURI is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | MusicURI is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with MPEG7AudioEnc; see the file COPYING. If not, write to 18 | the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 19 | MA 02111-1307 USA 20 | */ 21 | 22 | package it.univpm.deit.semedia.musicuri.utils.dbadmin; 23 | 24 | 25 | import it.univpm.deit.semedia.musicuri.core.MusicURIQuery; 26 | import it.univpm.deit.semedia.musicuri.core.Toolset; 27 | 28 | import java.io.File; 29 | import java.io.FileWriter; 30 | import java.io.IOException; 31 | 32 | import com.thoughtworks.xstream.XStream; 33 | 34 | 35 | /** 36 | * Utility class used for experimenting with object serialization 37 | */ 38 | public class QueryObjectDbPopulator 39 | { 40 | 41 | public static void main(String[] args) throws Exception 42 | { 43 | //System.out.println("Input: " + args[0]); 44 | 45 | if ((args.length == 1) && (new File (args[0]).exists())) 46 | { 47 | // get the file's canonical path 48 | File givenHandle = new File(args[0]); 49 | String queryAudioCanonicalPath = givenHandle.getCanonicalPath(); 50 | System.out.println("New Query Source: " + queryAudioCanonicalPath); 51 | 52 | // for a naive mp3 format check 53 | final String MP3MASK = ".*\\." + "mp3"; 54 | File[] list = null; 55 | 56 | if (givenHandle.isFile()) 57 | { 58 | list = new File[1]; 59 | list[0] = givenHandle; 60 | } 61 | if (givenHandle.isDirectory()) 62 | { 63 | list = givenHandle.listFiles(); 64 | 65 | if (list.length == 0) 66 | { 67 | System.out.println("No files in directory"); 68 | return; 69 | } 70 | } 71 | 72 | MusicURIQuery newQuery; 73 | File mp3File; 74 | String parentDirectory; 75 | 76 | for (int i = 0; i < list.length; i++) 77 | { 78 | mp3File = list[i]; 79 | parentDirectory = mp3File.getParent(); 80 | try 81 | { 82 | if (mp3File.getName().matches(MP3MASK)) 83 | { 84 | byte[] bytes = Toolset.createMD5Hash(mp3File); 85 | String md5 = Toolset.toHexString(bytes); 86 | 87 | if ((new File(parentDirectory + "/" + md5 + ".xml")).exists()) 88 | { 89 | System.out.println("File : " + md5 + ".xml" + " already exists on disk"); 90 | } 91 | else 92 | { 93 | System.out.print("MusicURIQuery for '" + mp3File.getName() + "' gets serialized to '" + md5 + ".xml' -- "); 94 | newQuery = new MusicURIQuery(mp3File); 95 | serializeToXmlFile(newQuery, parentDirectory + "/" + md5 + ".xml"); 96 | } 97 | } 98 | else 99 | { 100 | if (mp3File.isDirectory()) 101 | { 102 | String[] recursiveArgs = {mp3File.getCanonicalPath()}; 103 | QueryObjectDbPopulator.main(recursiveArgs); 104 | } 105 | } 106 | } 107 | catch (Exception e) 108 | { 109 | e.printStackTrace(); 110 | } 111 | } 112 | } 113 | else System.out.println("file or dir does not exist"); 114 | if (args.length==0) System.out.println("no input given"); 115 | 116 | } 117 | 118 | public static void serializeToXmlFile(Object object, String filename) 119 | { 120 | XStream xstream = new XStream(); 121 | String xml = xstream.toXML(object); 122 | try 123 | { 124 | FileWriter fw = new FileWriter(filename); 125 | fw.write(xml); 126 | fw.close(); 127 | } 128 | catch (IOException e) 129 | { 130 | e.printStackTrace(); 131 | } 132 | } 133 | 134 | } 135 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/utils/dbadmin/DbPopulator.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2005, Dimitrios Kourtesis 3 | 4 | This file is part of MusicURI. 5 | 6 | MusicURI is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | MusicURI is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with MPEG7AudioEnc; see the file COPYING. If not, write to 18 | the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 19 | MA 02111-1307 USA 20 | */ 21 | 22 | package it.univpm.deit.semedia.musicuri.utils.dbadmin; 23 | 24 | 25 | import it.univpm.deit.semedia.musicuri.core.MusicURIDatabase; 26 | import it.univpm.deit.semedia.musicuri.core.MusicURIReference; 27 | import it.univpm.deit.semedia.musicuri.core.Toolset; 28 | 29 | import java.io.File; 30 | 31 | 32 | /** 33 | * Utility class used for adding audio files to the db 34 | */ 35 | public class DbPopulator 36 | { 37 | 38 | public static void main(String[] args) throws Exception 39 | { 40 | if ((args.length == 1) && (new File (args[0]).exists())) 41 | { 42 | // get the file's canonical path 43 | File givenHandle = new File(args[0]); 44 | String queryAudioCanonicalPath = givenHandle.getCanonicalPath(); 45 | System.out.println("New Reference Source: " + queryAudioCanonicalPath); 46 | 47 | // create reference db 48 | String databasePath = "D:/"; 49 | //String databasePath = "C:/temp/"; 50 | String databaseFileName = "MusicURIReferences.db"; 51 | MusicURIDatabase db = new MusicURIDatabase(databasePath, databaseFileName); 52 | 53 | // for a naive mp3 format check 54 | final String MP3MASK = ".*\\." + "mp3"; 55 | final String WAVMASK = ".*\\." + "wav"; 56 | 57 | if (givenHandle.isDirectory()) 58 | { 59 | File[] list = givenHandle.listFiles(); 60 | if (list.length == 0) 61 | { 62 | System.out.println("no files in directory"); 63 | return; 64 | } 65 | else 66 | { 67 | for (int i = 0; i < list.length; i++) 68 | { 69 | File file = list[i]; 70 | try 71 | { 72 | if (file.getName().matches(MP3MASK) || file.getName().matches(WAVMASK)) 73 | { 74 | byte[] bytes = Toolset.createMD5Hash(file); 75 | String md5 = Toolset.toHexString(bytes); 76 | System.out.println(md5 + " - " + file.getName()); 77 | 78 | // if (md5.equalsIgnoreCase("d910f7ee9a7a0b23edeaaac20368eb1d")) 79 | // { 80 | // System.out.print("special add (d910f7ee9a7a0b23edeaaac20368eb1d) : " + file.getName()); 81 | // MusicURIReference newref = new MusicURIReference(file); 82 | // db.addMusicURIReference(newref); 83 | // } 84 | 85 | File serializedMusicURIObject = new File(databasePath + md5 + ".xml"); 86 | if (serializedMusicURIObject.exists()) 87 | { 88 | System.out.print("the file " + databasePath + md5 + ".xml" + " exists on disk, "); 89 | if ((MusicURIReference) db.getMusicURIReference(md5)!=null) 90 | System.out.println("and in the db as well"); 91 | else 92 | System.out.println("but not in the db"); 93 | } 94 | else 95 | { 96 | 97 | System.out.print("the file " + databasePath + md5 + ".xml" + " gets added "); 98 | MusicURIReference newref = new MusicURIReference(file); 99 | db.addMusicURIReference(newref); 100 | 101 | } 102 | 103 | } 104 | } 105 | catch (Exception e) 106 | { 107 | e.printStackTrace(); 108 | } 109 | } 110 | } 111 | } 112 | if (givenHandle.isFile()) 113 | { 114 | if (givenHandle.getName().matches(MP3MASK)|| givenHandle.getName().matches(WAVMASK)) 115 | { 116 | MusicURIReference newref = new MusicURIReference(givenHandle); 117 | db.addMusicURIReference(newref); 118 | } 119 | } 120 | 121 | } 122 | else System.out.println("file or dir does not exist"); 123 | if (args.length==0) System.out.println("no param"); 124 | 125 | 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/utils/experimental/Mpeg7XMAudioSignatureSearch.java: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // This software module was originally developed by 4 | // 5 | // Thorsten Heinz 6 | // Fraunhofer IIS 7 | // 8 | // in the course of development of the MPEG-7 Experimentation Model. 9 | // 10 | // This software module is an implementation of a part of one or more MPEG-7 11 | // Experimentation Model tools as specified by the MPEG-7 Requirements. 12 | // 13 | // ISO/IEC gives users of MPEG-7 free license to this software module or 14 | // modifications thereof for use in hardware or software products claiming 15 | // conformance to MPEG-7. 16 | // 17 | // Those intending to use this software module in hardware or software products 18 | // are advised that its use may infringe existing patents. The original 19 | // developer of this software module and his/her company, the subsequent 20 | // editors and their companies, and ISO/IEC have no liability for use of this 21 | // software module or modifications thereof in an implementation. 22 | // 23 | // Copyright is not released for non MPEG-7 conforming products. The 24 | // organizations named above retain full right to use the code for their own 25 | // purpose, assign or donate the code to a third party and inhibit third 26 | // parties from using the code for non MPEG-7 conforming products. 27 | // 28 | // Copyright (c) 1998-1999. 29 | // 30 | // This notice must be included in all copies or derivative works. 31 | // 32 | // Applicable File Name: AudioSignatureSearch.cpp 33 | // 34 | 35 | package it.univpm.deit.semedia.musicuri.utils.experimental; 36 | 37 | public class Mpeg7XMAudioSignatureSearch 38 | { 39 | 40 | // Weighting vector for the mean vectors (unit variance) 41 | public static double meanWeight[] = 42 | { 43 | 11.933077, 11.103332, 10.464845, 10.231990, 9.743346, 9.645541, 9.644496, 9.672296, 44 | 8.791485, 8.741418, 8.613710, 8.741487, 8.126337, 8.257461, 8.053868, 8.387219 45 | }; 46 | 47 | // Weighting vector for the variance vectors (unit variance) 48 | public static double varWeight[] = 49 | { 50 | 69.486160, 69.157463, 73.134132, 73.182343, 76.521751, 77.552032, 81.201492, 85.420212, 51 | 74.791885, 76.823540, 79.335228, 82.347801, 65.784485, 69.698914, 67.417160, 67.184540 52 | }; 53 | 54 | // determines the weighted Euclidian distance between a reference and a query audio signature 55 | public static double WeightedEuclidianDistance ( double[] refMean, 56 | double[] refVar, 57 | int numRefVec, 58 | double[] queryMean, 59 | double[] queryVar, 60 | int numQueryVec, 61 | int vectorDim) 62 | { 63 | //--- Check whether the vector dimensions are compatible 64 | if(meanWeight.length != vectorDim) 65 | { 66 | System.out.println("Vector dimensions not identical"); 67 | return -1.0f; 68 | } 69 | 70 | int i, j, k; 71 | double distance = 0.0f; 72 | 73 | //--- Loop over all query vectors (scalable series) 74 | for(i = 0; i < numQueryVec; ++i) 75 | { 76 | //System.out.println("query i: " + i); 77 | 78 | double minDistance = 9999.999; 79 | 80 | //--- Loop over reference fingerprint vectors (16-dimensional fingerprint vectors) 81 | for(j = 0; j < numRefVec; ++j) //eg 136 times for 136 seconds of query audio 82 | { 83 | //System.out.println("reference j: " + j); 84 | double tmpDistance = 0.0f; 85 | //--- Calculate distance of mean vector 86 | for(k = 0; k < vectorDim; ++k) //16 times == freq bands 87 | { 88 | //System.out.println("mean k: " + k); 89 | double v1 = queryMean[vectorDim*i + k] * meanWeight[k]; 90 | double v2 = refMean[vectorDim*j + k] * meanWeight[k]; 91 | tmpDistance += (v1-v2)*(v1-v2); 92 | } 93 | 94 | //--- Calculate distance of variance vector 95 | for(k = 0; k < vectorDim; ++k) //16 times == freq bands 96 | { 97 | //System.out.println("variance k: " + k); 98 | double v1 = queryVar[vectorDim*i + k] * varWeight[k]; 99 | double v2 = refVar[vectorDim*j + k] * varWeight[k]; 100 | tmpDistance += (v1-v2)*(v1-v2); 101 | } 102 | 103 | if(tmpDistance < minDistance) {minDistance = tmpDistance;} 104 | } 105 | 106 | //--- Cumulate overall distance for all query vectors 107 | distance += minDistance; 108 | } 109 | 110 | return Math.sqrt(distance/(vectorDim*numQueryVec)); 111 | } 112 | 113 | }//end class 114 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/core/SearchStrategy.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package it.univpm.deit.semedia.musicuri.core; 5 | 6 | /** 7 | * @author Dimitrios Kourtesis 8 | */ 9 | public interface SearchStrategy 10 | { 11 | /** 12 | * A perfect audio fingerprinting system would correctly match a query with 13 | * a known, previously indexed reference, 100% of the time, and reject an 14 | * unknown query, 100% of the time. However, audio fingerprints can be 15 | * extracted from a variety of audio signals (FM broadcasts, GSM telephony, 16 | * internet streams, mp3 files) which are captured under uncontrollable 17 | * conditions (cabling, speaker-microphone chains, AD conversions), and can 18 | * therefore be of questionable perceptual audio quality. This in turn leads 19 | * to matching of questionable accuracy. The overall accuracy of an audio 20 | * fingerprinting system is assessed by its tendency to produce either a 21 | * "false match" (false acceptance or false positive) or a "false non-match" 22 | * (false rejection or false negative). The point at which these two rates 23 | * intersect is called the equal error rate (EER). This indicates the rate 24 | * of errors (errors/attempts) occurring when a system's decision threshold 25 | * is set so that the number of false rejections will be approximately equal 26 | * to the number of false acceptances. The lower the equal error rate value, 27 | * the higher the accuracy of the system. 28 | * 29 | * The false acceptance rate, or FAR, is the measure of the likelihood that 30 | * the system will falsely accept a query as matching to a known reference, 31 | * while in fact the music item that the query actually belongs to, is 32 | * unknown to the system. Ie states the probability that the some irrelevant 33 | * reference will be wrongly selected. For example matching a sample from a 34 | * Metallica song, to a song by Madonna, while the database does not contain 35 | * any songs by Metallica. A system's FIR is stated as the ratio of the 36 | * number of false identifications divided by the number of identification 37 | * attempts. 38 | * 39 | * The false rejection rate, or FRR, is the measure of the likelihood that 40 | * the system will falsely reject a query as not matching to any known 41 | * reference, while the music item that the query actually belongs to, is 42 | * known to the system. Ie states the probability that the actual reference 43 | * will be wrongly rejected. For example refuse to match a sample from a 44 | * Metallica song, while the database contains every song ever produced by 45 | * Metallica. A system's FIR is stated as the ratio of the number of false 46 | * identifications divided by the number of identification attempts. 47 | * 48 | * This interface class is used to realize different implementations of 49 | * MusicURI search, reflecting the system's policy with regard to matching. 50 | * One of the questions is "what is the fine line separating acceptable from 51 | * non-acceptable matches?". In general, raising the decision threshold 52 | * leads to having less false acceptance or false-positive matches, but also 53 | * leads to having more false rejection or false-negative matches, and vice 54 | * versa. In a highly demanding application where the cost of a erroneous 55 | * identification could be high, system policy might prefer false-rejections 56 | * over false acceptances, and thus raise the decision threshold. In a 57 | * setting where the MusicURI service is provided at a "best-effort" basis, 58 | * and the cost of a erroneous identification is small, system policy might 59 | * favor a false-acceptance matching, in order not to over-reject queries, 60 | * and thereby under-utilize its reference database. 61 | * 62 | * 63 | * To fine tune the system and obtain the ERR, the FAR and FRR must 64 | * converge to an equal value: 65 | * 66 | * int numberOfQueries = 100; 67 | * float decision_threshold = 0.0f; 68 | * int falseAcceptances = 100; 69 | * int falseRejections = 0; 70 | * 71 | * 72 | * while (falseAcceptances > falseRejections) 73 | * { 74 | * decision_threshold += 0.01f; 75 | * stats = runQueriesBatch(); 76 | * falseAcceptances = stats.getFalseAcceptances(); 77 | * falseRejections = stats.getFalseRejections(); 78 | * } 79 | * 80 | * float EER = falseAcceptances / numberOfQueries; 81 | * 82 | * Since it is true that the lower the equal error rate value, the higher 83 | * the accuracy of the system, we will use ERR as a benchmark to determine 84 | * the efficiency of different search strategies. 85 | * 86 | */ 87 | 88 | } 89 | -------------------------------------------------------------------------------- /demo/README.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | ****************************************************************************** 4 | ************************ Getting started with MusicURI *********************** 5 | ****************************************************************************** 6 | 7 | 8 | I have put together some instructions to demonstrate the functionality that 9 | MusicURI offers at its current point of development. To get an idea of what is 10 | offered, please follow the instructions below. 11 | 12 | 13 | 14 | ****************************************************************************** 15 | Step 1. Install the MusicURI package 16 | ****************************************************************************** 17 | 18 | 1. Extract the contents of 'dependencies.zip'. 19 | 20 | 2. Add the .jar files to your CLASSPATH. One way to do this is to place them 21 | inside the extension directory of your Java Runtime Environment installation 22 | (JAVA_HOME/jre/lib/ext/). 23 | 24 | 3. Place the MusicURI.jar and MusicURIReferences.db somewhere in 25 | your system. The MusicURI.jar contains the executable you will use in the next 26 | step, and the MusicURIReferences.db is the actual database flat file. 27 | 28 | 29 | 30 | ****************************************************************************** 31 | Step 2. Use the MusicURI package 32 | ****************************************************************************** 33 | 34 | Execute the Music.jar as described below. The entry point for the MusicURI 35 | jar file is a demo application. It currently supports only local MusicURI data 36 | sources (ie working with local database files). Support for MusicURI data 37 | sources that are exposed as Web Services has been removed for now, but will 38 | be provided again shortly (i am currently doing some refactoring and redesign). 39 | 40 | The demo application intends to practically demonstrate the basic funcionality 41 | that MusicURI offers, which is to enable the mapping between a piece of music 42 | and a unique URI. The following operations are currently offered : 43 | 44 | a) Query a MusicURI local database with a music item, and retrieve a URI 45 | b) Add a reference music item to a local MusicURI database 46 | c) List all reference music items inside a local MusicURI database 47 | 48 | Explanation: 49 | 50 | a) Query the local MusicURI database file at the specified path, with the 51 | given audio file, to retrieve a URI. The -q switch is accompanied by the path 52 | to the local database, and the -f flag (optional) signals if the filename 53 | should be utilized as a reliable hint within search. 54 | 55 | Format: java -jar MusicURI.jar [] [<-q> ] [<-f>] 56 | example: "c:\demo\test.mp3" -q "c:\demo\MusicURIReferences.db" -f 57 | 58 | 59 | b) Add, to the local MusicURI database file at the specified path, the given 60 | audio file. The -a switch is accompanied by the path to the local database, 61 | into which the music item will be indexed. 62 | 63 | 64 | Format: java -jar MusicURI.jar [] [<-a> ] 65 | example: "c:\demo\test.mp3" -a "c:\demo\MusicURIReferences.db" 66 | 67 | 68 | c) List the URIs of all music items indexed in the local MusicURI database 69 | file, at the specified path. 70 | 71 | Format: java -jar MusicURI.jar [<-l> ] 72 | Example: -l "c:\demo\MusicURIReferences.db" 73 | 74 | 75 | Before proceeding with any of the aforementioned operations, the 76 | application verifies that any files that have been specified exist, 77 | and are valid. 78 | 79 | For query operations, the user has to specify Where, What and How to identify. 80 | I.e. the user must specify the URL where the MusicURI data source resides, 81 | the audio file containing the unknown piece of music, and whether the system 82 | should utilize the provided filename as a reliable hint within the search, or 83 | not (default is false). The filename should be taken into consideration only 84 | if the user is absolutely confident that it does not contain any misleading 85 | information about the artist and title of the respective piece of music. For 86 | example, this option could be safely used for a filename of the form: 87 | .<EXTENSION> 88 | 89 | @param Where: URL specifying the location of the MusicURI data source 90 | @param What : Audio file containing the piece of music to use as a query 91 | @param How : Flag determining whether to utilize the filename in search 92 | 93 | 94 | The MusicURIReferences.db database file is provided to be used as a starting 95 | point. It contains 14 MusicURIReference objects corresponding to 14 reference 96 | music items from the "Buena Vista Social Club" album that was released in 1997. 97 | The "test.mp3" file is a 6-second long excerpt from the album's 9th track. 98 | 99 | 100 | ****************************************************************************** 101 | November 15, 2005 102 | Dimitrios Kourtesis 103 | d.kourtesis at gmail dot com 104 | ****************************************************************************** -------------------------------------------------------------------------------- /src/README.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | ****************************************************************************** 4 | ************************ Getting started with MusicURI *********************** 5 | ****************************************************************************** 6 | 7 | 8 | I have put together some instructions to demonstrate the functionality that 9 | MusicURI offers at its current point of development. To get an idea of what is 10 | offered, please follow the instructions below. 11 | 12 | 13 | 14 | ****************************************************************************** 15 | Step 1. Install the MusicURI package 16 | ****************************************************************************** 17 | 18 | 1. Extract the contents of 'dependencies.zip'. 19 | 20 | 2. Add the .jar files to your CLASSPATH. One way to do this is to place them 21 | inside the extension directory of your Java Runtime Environment installation 22 | (JAVA_HOME/jre/lib/ext/). 23 | 24 | 3. Place the MusicURI.jar and MusicURIReferences.db somewhere in 25 | your system. The MusicURI.jar contains the executable you will use in the next 26 | step, and the MusicURIReferences.db is the actual database flat file. 27 | 28 | 29 | 30 | ****************************************************************************** 31 | Step 2. Use the MusicURI package 32 | ****************************************************************************** 33 | 34 | Execute the Music.jar as described below. The entry point for the MusicURI 35 | jar file is a demo application. It currently supports only local MusicURI data 36 | sources (ie working with local database files). Support for MusicURI data 37 | sources that are exposed as Web Services has been removed for now, but will 38 | be provided again shortly (i am currently doing some refactoring and redesign). 39 | 40 | The demo application intends to practically demonstrate the basic funcionality 41 | that MusicURI offers, which is to enable the mapping between a piece of music 42 | and a unique URI. The following operations are currently offered : 43 | 44 | a) Query a MusicURI local database with a music item, and retrieve a URI 45 | b) Add a reference music item to a local MusicURI database 46 | c) List all reference music items inside a local MusicURI database 47 | 48 | Explanation: 49 | 50 | a) Query the local MusicURI database file at the specified path, with the 51 | given audio file, to retrieve a URI. The -q switch is accompanied by the path 52 | to the local database, and the -f flag (optional) signals if the filename 53 | should be utilized as a reliable hint within search. 54 | 55 | Format: java -jar MusicURI.jar [<audiofile>] [<-q> <DBfile>] [<-f>] 56 | example: "c:\demo\test.mp3" -q "c:\demo\MusicURIReferences.db" -f 57 | 58 | 59 | b) Add, to the local MusicURI database file at the specified path, the given 60 | audio file. The -a switch is accompanied by the path to the local database, 61 | into which the music item will be indexed. 62 | 63 | 64 | Format: java -jar MusicURI.jar [<audiofile>] [<-a> <DBfile>] 65 | example: "c:\demo\test.mp3" -a "c:\demo\MusicURIReferences.db" 66 | 67 | 68 | c) List the URIs of all music items indexed in the local MusicURI database 69 | file, at the specified path. 70 | 71 | Format: java -jar MusicURI.jar [<-l> <databasefile>] 72 | Example: -l "c:\demo\MusicURIReferences.db" 73 | 74 | 75 | Before proceeding with any of the aforementioned operations, the 76 | application verifies that any files that have been specified exist, 77 | and are valid. 78 | 79 | For query operations, the user has to specify Where, What and How to identify. 80 | I.e. the user must specify the URL where the MusicURI data source resides, 81 | the audio file containing the unknown piece of music, and whether the system 82 | should utilize the provided filename as a reliable hint within the search, or 83 | not (default is false). The filename should be taken into consideration only 84 | if the user is absolutely confident that it does not contain any misleading 85 | information about the artist and title of the respective piece of music. For 86 | example, this option could be safely used for a filename of the form: 87 | <ARTIST> <SEPARATOR> <TITLE>.<EXTENSION> 88 | 89 | @param Where: URL specifying the location of the MusicURI data source 90 | @param What : Audio file containing the piece of music to use as a query 91 | @param How : Flag determining whether to utilize the filename in search 92 | 93 | 94 | The MusicURIReferences.db database file is provided to be used as a starting 95 | point. It contains 14 MusicURIReference objects corresponding to 14 reference 96 | music items from the "Buena Vista Social Club" album that was released in 1997. 97 | The "test.mp3" file is a 6-second long excerpt from the album's 9th track. 98 | 99 | 100 | ****************************************************************************** 101 | November 15, 2005 102 | Dimitrios Kourtesis 103 | d.kourtesis at gmail dot com 104 | ****************************************************************************** -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/webservice/server/MusicURIWebSearch.java: -------------------------------------------------------------------------------- 1 | package it.univpm.deit.semedia.musicuri.webservice.server; 2 | 3 | import java.io.BufferedWriter; 4 | import java.io.File; 5 | import java.io.FileWriter; 6 | import java.io.IOException; 7 | import java.net.URL; 8 | import java.util.ArrayList; 9 | import java.util.Iterator; 10 | import java.util.Set; 11 | 12 | import org.apache.axis.AxisProperties; 13 | import org.xml.sax.SAXException; 14 | 15 | import it.univpm.deit.database.datatypes.AudioLLDmeta; 16 | import it.univpm.deit.database.datatypes.Mp7ACT; 17 | import it.univpm.deit.semedia.musicuri.core.MusicURIDatabase; 18 | import it.univpm.deit.semedia.musicuri.core.MusicURIQuery; 19 | import it.univpm.deit.semedia.musicuri.core.MusicURIReference; 20 | import it.univpm.deit.semedia.musicuri.core.MusicURISearch; 21 | import it.univpm.deit.semedia.musicuri.core.Result; 22 | import it.univpm.deit.semedia.musicuri.core.ResultRankingList; 23 | import it.univpm.deit.semedia.musicuri.core.Toolset; 24 | import it.univpm.deit.semedia.musicuri.statistics.PerformanceStatistic; 25 | import it.univpm.deit.semedia.musicuri.utils.misc.MusicURILibraryDemo; 26 | 27 | public class MusicURIWebSearch 28 | { 29 | 30 | private static MusicURIDatabase db = new MusicURIDatabase 31 | (getWebServiceDatabaseDirectory(), "\\MusicURIReferences.db"); // C:\WINDOWS\SYSTEM32 32 | 33 | private MusicURISearch engine = new MusicURISearch(db); 34 | 35 | public String performSearch(String xmlAudioSignature, String filename) 36 | { 37 | try 38 | { 39 | String returnString = ""; 40 | 41 | String tempXMLFile = Toolset.getCWD() + "/temp.xml"; 42 | 43 | BufferedWriter out = new BufferedWriter(new FileWriter(tempXMLFile)); 44 | out.write(xmlAudioSignature); 45 | out.close(); 46 | 47 | Mp7ACT act = new Mp7ACT(); 48 | act.fromXML(tempXMLFile); 49 | MusicURIQuery query = new MusicURIQuery(); 50 | query.setAudioCompactType(act); 51 | 52 | boolean usingPruningHeuristic; 53 | boolean usingCombinedDistance; 54 | boolean finalResortIsCombinedDistance; 55 | ResultRankingList finalDistanceRankingList; 56 | Result theBestResult = null; 57 | Result theSecondBestResult = null; 58 | float maximumThreshold = 0.9f; 59 | 60 | 61 | if (db == null) 62 | { 63 | returnString = "DB was not deserialized (null)"; 64 | return returnString; 65 | } 66 | else 67 | { 68 | // if a filename has been provided, use it as a heuristic in search, 69 | // if not, perform a blind search, based on the audio signature only 70 | if (filename != null) 71 | { 72 | usingPruningHeuristic = true; 73 | usingCombinedDistance = true; 74 | finalResortIsCombinedDistance = true; 75 | query.setLabel(filename); 76 | 77 | returnString += queryDB(query, new Boolean(true)); 78 | } 79 | else 80 | { 81 | usingPruningHeuristic = false; 82 | usingCombinedDistance = false; 83 | finalResortIsCombinedDistance = false; 84 | query.setLabel("unlabelled"); 85 | 86 | returnString += queryDB(query, new Boolean(false)); 87 | } 88 | 89 | return returnString; 90 | 91 | } 92 | } catch (Exception e) 93 | { 94 | e.printStackTrace(); 95 | return (e.getMessage()); 96 | } 97 | 98 | } 99 | 100 | 101 | public int getNumOfMusicURIReferences() 102 | { 103 | if (db == null) 104 | return (-1); 105 | else 106 | return db.getDbSize(); 107 | } 108 | 109 | public String getMusicURIReferenceList() 110 | { 111 | if (db == null || db.getDbSize() == 0) 112 | return ("Database object could not be deserialized from " 113 | + getWebServiceDatabaseDirectory() ); 114 | else 115 | return db.textFormattedSetOfMusicURIReferences(); 116 | } 117 | 118 | private static String getWebServiceDatabaseDirectory() 119 | { 120 | // Get the "." file representing the cwd 121 | File cwd = new File("."); 122 | // Get the absolute path to the current working directory 123 | return cwd.getAbsolutePath(); 124 | } 125 | 126 | private String queryDB(MusicURIQuery query, Boolean usefilenameValue) 127 | { 128 | String reply = ""; 129 | 130 | ResultRankingList finalDistanceRankingList = engine.identify(query, 131 | usefilenameValue.booleanValue(), 132 | usefilenameValue.booleanValue(), 133 | 0.9f, //90% acceptable similarity rating 134 | usefilenameValue.booleanValue()); 135 | 136 | if (finalDistanceRankingList.getSize() >= 1) 137 | { 138 | Result theBestResult = finalDistanceRankingList.getResultAtIndex(0); 139 | double bestMatchDistance = theBestResult.distance; 140 | 141 | reply += ("\nMatched with : " + (db.getMusicURIReference(theBestResult.md5)).getLabel()); 142 | reply += ("\nScore : " + (float) (100 - (100*(theBestResult.distance))) + "%"); 143 | } 144 | else 145 | { 146 | if (finalDistanceRankingList == null) 147 | reply += ("the ranking list was returned null"); 148 | else 149 | reply += ("the ranking list has " + finalDistanceRankingList.getSize() + " items"); 150 | } 151 | return reply; 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/statistics/Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2005, Dimitrios Kourtesis 3 | 4 | This file is part of MusicURI. 5 | 6 | MusicURI is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | MusicURI is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with MPEG7AudioEnc; see the file COPYING. If not, write to 18 | the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 19 | MA 02111-1307 USA 20 | */ 21 | 22 | package it.univpm.deit.semedia.musicuri.statistics; 23 | 24 | import it.univpm.deit.semedia.musicuri.core.MusicURIDatabase; 25 | 26 | import java.io.File; 27 | import java.util.Arrays; 28 | import java.util.Collections; 29 | import java.util.Iterator; 30 | import java.util.List; 31 | 32 | 33 | import com.wcohen.secondstring.JaroWinkler; 34 | import com.wcohen.secondstring.MongeElkan; 35 | import com.wcohen.secondstring.StringDistance; 36 | import com.wcohen.secondstring.StringWrapper; 37 | import com.wcohen.secondstring.TFIDF; 38 | import com.wcohen.secondstring.tokens.SimpleTokenizer; 39 | import com.wcohen.secondstring.tokens.Token; 40 | 41 | /** 42 | * Utility class used for various tests 43 | */ 44 | public class Test 45 | { 46 | 47 | public static void main(String[] args) 48 | { 49 | 50 | String databasePath = "D:/1000ReferenceDB/"; 51 | String databaseFileName = "MusicURIReferences.db"; 52 | System.out.println("Loading Database : " + databasePath + databaseFileName); 53 | MusicURIDatabase db = new MusicURIDatabase(databasePath, databaseFileName); 54 | System.out.println("db contains: "+ db.getDbSize()); 55 | 56 | System.out.println(db.textFormattedSetOfMusicURIReferences()); 57 | 58 | 59 | //StringDistance dist = new JaroWinkler().compare("frederic", "fredrick"); 60 | // MongeElkan m = new MongeElkan(); 61 | // String exp = m.explainScore("frederic", "fredrick"); 62 | // System.out.println(exp); 63 | 64 | // StringWrapper w1 = new StringWrapper("tribe+called"); 65 | // StringWrapper w2 = new StringWrapper("tribe called"); 66 | // double res = m.score(w1, w2); 67 | // System.out.println(res); 68 | 69 | 70 | // SimpleTokenizer tk = new SimpleTokenizer(false, true); 71 | // Token[] tokens = tk.tokenize("tribe+Called"); 72 | // for (int i = 0; i < tokens.length; i++) 73 | // { 74 | // System.out.println(tokens[i].getValue()); 75 | // } 76 | 77 | // TFIDF test = new TFIDF(); 78 | // w1 = test.prepare("tribe+Called"); 79 | // w2 = test.prepare("tribe Called d"); 80 | // float tfidfDist = (float) test.score(w1, w2); 81 | // float unit = 1.0f; 82 | // System.out.println("Distance: " + (tfidfDist)); 83 | // System.out.println("Reverse : " + (unit - tfidfDist)); 84 | // 85 | 86 | // ResultRankingList ranking = new ResultRankingList(4); 87 | // System.out.println("lastNullIndex: " + ranking.lastNullIndex); 88 | // ranking.RankThis(new Result(2.1,"2.1")); 89 | // System.out.println("lastNullIndex: " + ranking.lastNullIndex); 90 | // ranking.printContents(); 91 | // 92 | // ranking.RankThis(new Result(1.1,"1.1")); 93 | // System.out.println("lastNullIndex: " + ranking.lastNullIndex); 94 | // ranking.printContents(); 95 | // 96 | // ranking.RankThis(new Result(3.1,"3.1")); 97 | // System.out.println("lastNullIndex: " + ranking.lastNullIndex); 98 | // ranking.printContents(); 99 | // 100 | // ranking.RankThis(new Result(2.0,"2.0")); 101 | // System.out.println("lastNullIndex: " + ranking.lastNullIndex); 102 | // ranking.printContents(); 103 | // 104 | // ranking.RankThis(new Result(0.9,"0.9")); 105 | // System.out.println("lastNullIndex: " + ranking.lastNullIndex); 106 | // ranking.printContents(); 107 | // 108 | // ranking.RankThis(new Result(0.7,"0.7")); 109 | // System.out.println("lastNullIndex: " + ranking.lastNullIndex); 110 | // ranking.printContents(); 111 | // 112 | // ranking.RankThis(new Result(3.7,"3.7")); 113 | // System.out.println("lastNullIndex: " + ranking.lastNullIndex); 114 | // ranking.printContents(); 115 | 116 | 117 | // if (Toolset.getTestCaseIdentifier(currentReference.getLabel()) > 1035 ) 118 | // { 119 | // int newId =0; 120 | // 121 | // if (Toolset.getTestCaseIdentifier(currentReference.getLabel()) < 1065) 122 | // newId = Toolset.getTestCaseIdentifier(currentReference.getLabel())-1; 123 | // else 124 | // newId = Toolset.getTestCaseIdentifier(currentReference.getLabel())-2; 125 | // 126 | // db.removeMusicURIReference(currentMD5); 127 | // System.out.print("replacing :" + currentReference.getLabel() ); 128 | // String oldFilenameWithoutIdentifier = Toolset.removeIdentifier(currentReference.getLabel()); 129 | // //System.out.print("oldFilenameWithoutIdentifier :" + oldFilenameWithoutIdentifier ); 130 | // String newLabel = (newId + " " + oldFilenameWithoutIdentifier); 131 | // currentReference.setLabel(newLabel); 132 | // db.addMusicURIReference(currentReference); 133 | // System.out.println(" with " + newLabel); 134 | // //String appendedNonSenseFilename = scrambledTokenFilename.concat("#" + randomInteger +" - " + GeorgeOrwell1984[randomInteger]); 135 | // 136 | // } 137 | 138 | } 139 | 140 | } 141 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/webservice/client/MusicURIWebSearchServiceLocator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * MusicURIWebSearchServiceLocator.java 3 | * 4 | * This file was auto-generated from WSDL 5 | * by the Apache Axis 1.2.1 Jun 14, 2005 (09:15:57 EDT) WSDL2Java emitter. 6 | */ 7 | 8 | package it.univpm.deit.semedia.musicuri.webservice.client; 9 | 10 | public class MusicURIWebSearchServiceLocator 11 | extends org.apache.axis.client.Service 12 | implements it.univpm.deit.semedia.musicuri.webservice.client.MusicURIWebSearchService 13 | { 14 | 15 | public MusicURIWebSearchServiceLocator() { 16 | } 17 | 18 | 19 | public MusicURIWebSearchServiceLocator(org.apache.axis.EngineConfiguration config) { 20 | super(config); 21 | } 22 | 23 | public MusicURIWebSearchServiceLocator(java.lang.String wsdlLoc, javax.xml.namespace.QName sName) throws javax.xml.rpc.ServiceException { 24 | super(wsdlLoc, sName); 25 | } 26 | 27 | // Use to get a proxy class for MusicURIWebSearch 28 | private java.lang.String MusicURIWebSearch_address = "http://localhost:8080/axis/MusicURIWebSearch.jws"; 29 | 30 | public java.lang.String getMusicURIWebSearchAddress() { 31 | return MusicURIWebSearch_address; 32 | } 33 | 34 | // The WSDD service name defaults to the port name. 35 | private java.lang.String MusicURIWebSearchWSDDServiceName = "MusicURIWebSearch"; 36 | 37 | public java.lang.String getMusicURIWebSearchWSDDServiceName() { 38 | return MusicURIWebSearchWSDDServiceName; 39 | } 40 | 41 | public void setMusicURIWebSearchWSDDServiceName(java.lang.String name) { 42 | MusicURIWebSearchWSDDServiceName = name; 43 | } 44 | 45 | public it.univpm.deit.semedia.musicuri.webservice.client.MusicURIWebSearch getMusicURIWebSearch() throws javax.xml.rpc.ServiceException { 46 | java.net.URL endpoint; 47 | try { 48 | endpoint = new java.net.URL(MusicURIWebSearch_address); 49 | } 50 | catch (java.net.MalformedURLException e) { 51 | throw new javax.xml.rpc.ServiceException(e); 52 | } 53 | return getMusicURIWebSearch(endpoint); 54 | } 55 | 56 | public it.univpm.deit.semedia.musicuri.webservice.client.MusicURIWebSearch getMusicURIWebSearch(java.net.URL portAddress) throws javax.xml.rpc.ServiceException { 57 | try { 58 | it.univpm.deit.semedia.musicuri.webservice.client.MusicURIWebSearchSoapBindingStub _stub = new it.univpm.deit.semedia.musicuri.webservice.client.MusicURIWebSearchSoapBindingStub(portAddress, this); 59 | _stub.setPortName(getMusicURIWebSearchWSDDServiceName()); 60 | return _stub; 61 | } 62 | catch (org.apache.axis.AxisFault e) { 63 | return null; 64 | } 65 | } 66 | 67 | public void setMusicURIWebSearchEndpointAddress(java.lang.String address) { 68 | MusicURIWebSearch_address = address; 69 | } 70 | 71 | /** 72 | * For the given interface, get the stub implementation. 73 | * If this service has no port for the given interface, 74 | * then ServiceException is thrown. 75 | */ 76 | public java.rmi.Remote getPort(Class serviceEndpointInterface) throws javax.xml.rpc.ServiceException { 77 | try { 78 | if (it.univpm.deit.semedia.musicuri.webservice.client.MusicURIWebSearch.class.isAssignableFrom(serviceEndpointInterface)) { 79 | it.univpm.deit.semedia.musicuri.webservice.client.MusicURIWebSearchSoapBindingStub _stub = new it.univpm.deit.semedia.musicuri.webservice.client.MusicURIWebSearchSoapBindingStub(new java.net.URL(MusicURIWebSearch_address), this); 80 | _stub.setPortName(getMusicURIWebSearchWSDDServiceName()); 81 | return _stub; 82 | } 83 | } 84 | catch (java.lang.Throwable t) { 85 | throw new javax.xml.rpc.ServiceException(t); 86 | } 87 | throw new javax.xml.rpc.ServiceException("There is no stub implementation for the interface: " + (serviceEndpointInterface == null ? "null" : serviceEndpointInterface.getName())); 88 | } 89 | 90 | /** 91 | * For the given interface, get the stub implementation. 92 | * If this service has no port for the given interface, 93 | * then ServiceException is thrown. 94 | */ 95 | public java.rmi.Remote getPort(javax.xml.namespace.QName portName, Class serviceEndpointInterface) throws javax.xml.rpc.ServiceException { 96 | if (portName == null) { 97 | return getPort(serviceEndpointInterface); 98 | } 99 | java.lang.String inputPortName = portName.getLocalPart(); 100 | if ("MusicURIWebSearch".equals(inputPortName)) { 101 | return getMusicURIWebSearch(); 102 | } 103 | else { 104 | java.rmi.Remote _stub = getPort(serviceEndpointInterface); 105 | ((org.apache.axis.client.Stub) _stub).setPortName(portName); 106 | return _stub; 107 | } 108 | } 109 | 110 | public javax.xml.namespace.QName getServiceName() { 111 | return new javax.xml.namespace.QName("http://kourtesis.homeip.net:8080/axis/MusicURIWebSearch.jws", "MusicURIWebSearchService"); 112 | } 113 | 114 | private java.util.HashSet ports = null; 115 | 116 | public java.util.Iterator getPorts() { 117 | if (ports == null) { 118 | ports = new java.util.HashSet(); 119 | ports.add(new javax.xml.namespace.QName("http://kourtesis.homeip.net:8080/axis/MusicURIWebSearch.jws", "MusicURIWebSearch")); 120 | } 121 | return ports.iterator(); 122 | } 123 | 124 | /** 125 | * Set the endpoint address for the specified port name. 126 | */ 127 | public void setEndpointAddress(java.lang.String portName, java.lang.String address) throws javax.xml.rpc.ServiceException { 128 | 129 | if ("MusicURIWebSearch".equals(portName)) { 130 | setMusicURIWebSearchEndpointAddress(address); 131 | } 132 | else 133 | { // Unknown Port Name 134 | throw new javax.xml.rpc.ServiceException(" Cannot set Endpoint Address for Unknown Port" + portName); 135 | } 136 | } 137 | 138 | /** 139 | * Set the endpoint address for the specified port name. 140 | */ 141 | public void setEndpointAddress(javax.xml.namespace.QName portName, java.lang.String address) throws javax.xml.rpc.ServiceException { 142 | setEndpointAddress(portName.getLocalPart(), address); 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/statistics/PerformanceStatistic.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2005, Dimitrios Kourtesis 3 | 4 | This file is part of MusicURI. 5 | 6 | MusicURI is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | MusicURI is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with MPEG7AudioEnc; see the file COPYING. If not, write to 18 | the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 19 | MA 02111-1307 USA 20 | */ 21 | 22 | package it.univpm.deit.semedia.musicuri.statistics; 23 | 24 | 25 | public class PerformanceStatistic 26 | { 27 | private int numOfReferenceFiles; 28 | private int numberOfComparisonsMade; 29 | private int numberOfRejections; 30 | private int totalReferenceSeconds; 31 | private long pruningTime; 32 | private long matchingTime; 33 | private float rejectionPercentage; 34 | private float speedPerRef; 35 | private boolean truePositive = false; 36 | private boolean falsePositive = false; 37 | private boolean trueNegative = false; 38 | private boolean falseNegative = false; 39 | private double bestMatchDistance; 40 | private double secondBestMatchDistance; 41 | private double worstMatchDistance; 42 | 43 | /** 44 | * Constructs a PerformanceStatistic object, calculates and assigns values to performance attibutes 45 | * @param numOfReferenceFiles the number of MusicURIReference objects in the db 46 | * @param numberOfComparisonsMade the number of comparisons made (certain MusicURIReference were rejected during db pruning) 47 | * @param totalReferenceSeconds the seconds of audio referenced by the db, (ie total playtime of all referenced audio files) 48 | * @param pruningTime the time spent during pruning the db 49 | * @param matchingTime the time spent for completing search and finding the match 50 | * @param identificationValidity an integer ranging [0..4] indincating wether the match was a true positive, false positive, true negative, false negative 51 | * @param bestMatchDistance the distance of the best match (ranked first) from the query 52 | * @param secondBestMatchDistance the distance of the second-best match (ranked second) from the query 53 | * @param worstMatchDistance the distance of the worst match (ranked last) from the query 54 | */ 55 | public PerformanceStatistic(int numOfReferenceFiles, 56 | int numberOfComparisonsMade, 57 | int totalReferenceSeconds, 58 | long pruningTime, 59 | long matchingTime, 60 | int identificationValidity, 61 | double bestMatchDistance, 62 | double secondBestMatchDistance, 63 | double worstMatchDistance) 64 | { 65 | this.numOfReferenceFiles = numOfReferenceFiles; 66 | this.numberOfComparisonsMade = numberOfComparisonsMade; 67 | this.numberOfRejections = numOfReferenceFiles - numberOfComparisonsMade; 68 | this.totalReferenceSeconds = totalReferenceSeconds; 69 | this.pruningTime = pruningTime; 70 | this.matchingTime = matchingTime; 71 | 72 | double execTime = pruningTime + matchingTime; 73 | 74 | // Checking if the number of reference files exceeds 0 75 | if (numOfReferenceFiles > 0 && numOfReferenceFiles - numberOfRejections > 0) 76 | { 77 | rejectionPercentage = (float) (((float) 100/numOfReferenceFiles) * numberOfRejections); 78 | speedPerRef = (float)(((float) execTime/1000) /(numOfReferenceFiles - numberOfRejections)); 79 | } 80 | 81 | if (identificationValidity == 1) truePositive = true; 82 | if (identificationValidity == 2) falsePositive = true; 83 | if (identificationValidity == 3) trueNegative = true; 84 | if (identificationValidity == 4) falseNegative = true; 85 | 86 | this.bestMatchDistance = bestMatchDistance; 87 | this.secondBestMatchDistance = secondBestMatchDistance; 88 | this.worstMatchDistance = worstMatchDistance; 89 | } 90 | 91 | /** 92 | * Prints some of the statistics related to speed and pruning efficiency 93 | */ 94 | public void printStatistics() 95 | { 96 | System.out.println("Reference Files in DB : " + numOfReferenceFiles); 97 | System.out.println("Reference Files Processed : " + numberOfComparisonsMade); 98 | System.out.println("Reference Files Rejected : " + numberOfRejections + " (" + rejectionPercentage + " % of reference files)"); 99 | // TODO: there probably is some error in how "Reference Audio Processed in Total" is calculated 100 | System.out.println("Reference Audio Processed in Total : " + totalReferenceSeconds + " audio sec (" + (float)totalReferenceSeconds/60 +" min / "+ (float)((float)(totalReferenceSeconds/60)/60) +" hrs)"); 101 | System.out.println("Identification Completed in : " + ((float) (pruningTime + matchingTime)/1000) + " seconds"); //elapsed_time 102 | System.out.println("Average Search Speed (Per Reference): " + speedPerRef + " seconds per reference"); 103 | } 104 | 105 | /** 106 | * @return the distance of the best match (ranked first) from the query 107 | */ 108 | public double getBestMatchDistance() 109 | { 110 | return bestMatchDistance; 111 | } 112 | 113 | /** 114 | * @return the distance of the second-best match (ranked second) from the query 115 | */ 116 | public double getSecondBestMatchDistance() 117 | { 118 | return secondBestMatchDistance; 119 | } 120 | 121 | /** 122 | * @return the distance of the worst match (ranked last) from the query 123 | */ 124 | public double getWorstMatchDistance() 125 | { 126 | return worstMatchDistance; 127 | } 128 | 129 | /** 130 | * @return the time spent during pruning the db 131 | */ 132 | public long getPruningTime() 133 | { 134 | return pruningTime; 135 | } 136 | 137 | /** 138 | * @return the time spent for completing search and finding the match 139 | */ 140 | public long getMatchingTime() 141 | { 142 | return matchingTime; 143 | } 144 | 145 | /** 146 | * @return true if the MusicURIReference ranked first was a True Positive, false otherwise 147 | */ 148 | public boolean isTruePositive() 149 | { 150 | return truePositive; 151 | } 152 | 153 | /** 154 | * @return true if the MusicURIReference ranked first was a False Positive, false otherwise 155 | */ 156 | public boolean isFalsePositive() 157 | { 158 | return falsePositive; 159 | } 160 | 161 | /** 162 | * @return true if the MusicURIReference ranked first was a True Negative, false otherwise 163 | */ 164 | public boolean isTrueNegative() 165 | { 166 | return trueNegative; 167 | } 168 | 169 | /** 170 | * @return true if the MusicURIReference ranked first was a False Negative, false otherwise 171 | */ 172 | public boolean isFalseNegative() 173 | { 174 | return falseNegative; 175 | } 176 | 177 | }//end class 178 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/core/ResultRankingList.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2005, Dimitrios Kourtesis 3 | 4 | This file is part of MusicURI. 5 | 6 | MusicURI is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | MusicURI is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with MPEG7AudioEnc; see the file COPYING. If not, write to 18 | the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 19 | MA 02111-1307 USA 20 | */ 21 | 22 | package it.univpm.deit.semedia.musicuri.core; 23 | 24 | 25 | import java.util.ArrayList; 26 | 27 | /** 28 | * @author Dimitrios Kourtesis 29 | */ 30 | public class ResultRankingList 31 | { 32 | 33 | /** 34 | * An array of Result objects 35 | */ 36 | public Result[] rankList; 37 | 38 | /** 39 | * The last index in the rankList attribute, which is currently null 40 | */ 41 | int lastNullIndex; 42 | 43 | /** 44 | * The maximum allowed size for the ranking list 45 | */ 46 | int maxSize; 47 | 48 | 49 | 50 | 51 | /** 52 | * Constructs an empty ResultRankingList object having size equal to the one specified 53 | * @param size the maximum allowed size of the ranking list 54 | */ 55 | public ResultRankingList(int size) 56 | { 57 | this.rankList = new Result[size]; 58 | this.lastNullIndex = 0; 59 | this.maxSize = size; 60 | } 61 | 62 | /** 63 | * Adds the given Result object to its sorted position, according to distance, 64 | * and shifts all other results downwards. The worst result is removed, if the 65 | * maximum number of results in the list has been reached. If the given result 66 | * is not better than any other result in the list, and the max size has been 67 | * reached, the given result is ignored. 68 | * @param theNewResult the Result object to add to the list 69 | * @return the number of results currently in the list 70 | */ 71 | public int RankThis(Result theNewResult) 72 | { 73 | Result currentResult; 74 | 75 | if (lastNullIndex == 0) 76 | { 77 | rankList[0] = theNewResult; 78 | lastNullIndex++; 79 | } 80 | else 81 | { 82 | for (int i = 0; i < maxSize; i++) 83 | { 84 | currentResult = (Result) rankList[i]; 85 | 86 | if ( currentResult == null) 87 | { 88 | //shift all results downwards, deleting the last one 89 | for (int j = lastNullIndex-1; j > i; j--) 90 | { 91 | rankList[j] = rankList[j-1]; 92 | } 93 | // insert into position i 94 | rankList[i] = theNewResult; 95 | lastNullIndex++; 96 | return lastNullIndex; 97 | } 98 | if ( currentResult != null && theNewResult.distance <= currentResult.distance ) 99 | { 100 | if (lastNullIndex == maxSize) 101 | { 102 | for (int j = lastNullIndex-1; j > i; j--) 103 | { 104 | rankList[j] = rankList[j-1]; 105 | } 106 | // insert into position i 107 | rankList[i] = theNewResult; 108 | } 109 | else 110 | { 111 | for (int j = lastNullIndex; j > i; j--) 112 | { 113 | rankList[j] = rankList[j-1]; 114 | } 115 | // insert into position i 116 | rankList[i] = theNewResult; 117 | lastNullIndex++; 118 | } 119 | return lastNullIndex; 120 | } 121 | } 122 | } 123 | return lastNullIndex; 124 | } 125 | 126 | /** 127 | * Returns the ranking list 128 | * @return rankList the ranking list 129 | */ 130 | public Result[] getRankList() 131 | { 132 | return rankList; 133 | } 134 | 135 | /** 136 | * Returns the size that the ranking list has been initialized to 137 | * @return the ranking list's initialization size 138 | */ 139 | public int getSize() 140 | { 141 | return rankList.length; 142 | } 143 | 144 | /** 145 | * Returns an ArrayList object containing all MD5 keys of the 146 | * results currently contained in the ranking list 147 | * @return keyList the ArrayList object containing all MD5 keys 148 | */ 149 | public ArrayList getRankListMd5Keys() 150 | { 151 | Result currentResult; 152 | String currentMD5; 153 | ArrayList keyList = new ArrayList(); 154 | 155 | for (int i = 0; i < lastNullIndex; i++) 156 | { 157 | currentResult = (Result) rankList[i]; 158 | currentMD5 = currentResult.md5; 159 | keyList.add(currentMD5); 160 | } 161 | return keyList; 162 | } 163 | 164 | /** 165 | * Returns the value of the distance atribute inside a Result object, that 166 | * has been added to the ranking list. If a Result object with the given 167 | * MD5 key does not exist in the ranking list, the return value is 1.0; 168 | * @param wantedKey the MD5 hash key of the wanted Result object 169 | * @return the value of the distance attribute in the Result object requested 170 | */ 171 | public double getResultDistance(String wantedKey) 172 | { 173 | Result currentResult; 174 | 175 | for (int i = 0; i < lastNullIndex; i++) 176 | { 177 | currentResult = (Result) rankList[i]; 178 | if (currentResult.md5.equalsIgnoreCase(wantedKey)) 179 | return currentResult.distance; 180 | } 181 | 182 | return 1.0; 183 | } 184 | 185 | /** 186 | * Returns the ranking index of a Result object that has been added to 187 | * the ranking list. If a Result object with the given MD5 key does not 188 | * exist in the ranking list, the return value is the maximum raking list size; 189 | * @param wantedKey the MD5 hash key of the wanted Result object 190 | * @return the ranking index of the Result object requested 191 | */ 192 | public int getRankingPositionOf(String wantedKey) 193 | { 194 | Result currentResult; 195 | 196 | for (int i = 0; i < maxSize; i++) 197 | { 198 | currentResult = (Result) rankList[i]; 199 | if (currentResult.md5.equalsIgnoreCase(wantedKey)) 200 | { 201 | return i+1; 202 | } 203 | } 204 | //System.out.println("returning " + position); 205 | return maxSize; 206 | } 207 | 208 | /** 209 | * Returns the Result object located in the given index. If the given index 210 | * is larger than the index of the last known valid entry, null is returned. 211 | * @param index the index (starting at zero) of the wanted Result object 212 | * @return the Result object stored in the ranking index specified 213 | */ 214 | public Result getResultAtIndex(int index) 215 | { 216 | if (index <= lastNullIndex) return (Result) rankList[index]; 217 | else return null; 218 | } 219 | 220 | /** 221 | * Prints some of the private attribute's values on screen (Experimental use only) 222 | */ 223 | public void printContents() 224 | { 225 | for (int i = 0; i < lastNullIndex; i++) 226 | { 227 | if (rankList[i]==null) 228 | System.out.println("-"); 229 | else 230 | { 231 | System.out.println(rankList[i].distance + " - " + rankList[i].md5); 232 | } 233 | } 234 | } 235 | 236 | 237 | }//end class 238 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/statistics/TestCaseCaller.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2005, Dimitrios Kourtesis 3 | 4 | This file is part of MusicURI. 5 | 6 | MusicURI is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | MusicURI is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with MPEG7AudioEnc; see the file COPYING. If not, write to 18 | the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 19 | MA 02111-1307 USA 20 | */ 21 | 22 | package it.univpm.deit.semedia.musicuri.statistics; 23 | 24 | import it.univpm.deit.semedia.musicuri.core.MusicURISearch; 25 | 26 | import java.sql.Date; 27 | import java.text.SimpleDateFormat; 28 | 29 | 30 | /** 31 | * Utility class used for various tests 32 | */ 33 | public class TestCaseCaller 34 | { 35 | 36 | public static void main(String[] args) throws Exception 37 | { 38 | String[] argString = new String[2]; 39 | 40 | 41 | SimpleDateFormat df = new SimpleDateFormat ("dd-MM-yyyy HH:mm:ss"); 42 | // long time = System.currentTimeMillis(); 43 | 44 | //known --high quality labelling 45 | // System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 46 | // argString[0]="D:/NewBatch/Known/128kbps-FhG/TotallyAccurateLabelling"; argString[1]= "1"; MusicURISearch.main(argString); //combined distance final resort 47 | // System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 48 | // System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 49 | // argString[0]="D:/NewBatch/Known/64kbps-FhG/TotallyAccurateLabelling"; argString[1]= "1"; MusicURISearch.main(argString); 50 | // System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 51 | // System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 52 | // argString[0]="D:/NewBatch/Known/32kbps-FhG/TotallyAccurateLabelling"; argString[1]= "1"; MusicURISearch.main(argString); 53 | // System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 54 | // 55 | // System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 56 | // argString[0]="D:/NewBatch/Known/128kbps-FhG/TotallyAccurateLabelling"; argString[1]= "0"; MusicURISearch.main(argString); 57 | // System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 58 | // System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 59 | // argString[0]="D:/NewBatch/Known/64kbps-FhG/TotallyAccurateLabelling"; argString[1]= "0"; MusicURISearch.main(argString); 60 | // System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 61 | // System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 62 | // argString[0]="D:/NewBatch/Known/32kbps-FhG/TotallyAccurateLabelling"; argString[1]= "0"; MusicURISearch.main(argString); 63 | // System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 64 | 65 | //known --mid quality labelling 66 | System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 67 | argString[0]="D:/NewBatch/Known/128kbps-FhG/BarelyReadable"; argString[1]= "1"; MusicURISearch.main(argString); //combined distance final resort 68 | System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 69 | System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 70 | argString[0]="D:/NewBatch/Known/64kbps-FhG/BarelyReadable"; argString[1]= "1"; MusicURISearch.main(argString); 71 | System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 72 | System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 73 | argString[0]="D:/NewBatch/Known/32kbps-FhG/BarelyReadable"; argString[1]= "1"; MusicURISearch.main(argString); 74 | System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 75 | 76 | // System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 77 | // argString[0]="D:/NewBatch/Known/128kbps-FhG/BarelyReadable"; argString[1]= "0"; MusicURISearch.main(argString); 78 | // System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 79 | // System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 80 | // argString[0]="D:/NewBatch/Known/64kbps-FhG/BarelyReadable"; argString[1]= "0"; MusicURISearch.main(argString); 81 | // System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 82 | // System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 83 | // argString[0]="D:/NewBatch/Known/32kbps-FhG/BarelyReadable"; argString[1]= "0"; MusicURISearch.main(argString); 84 | // System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 85 | 86 | 87 | // //unknown 88 | System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 89 | argString[0]="D:/NewBatch/Unknown/128kbps"; argString[1]= "1"; MusicURISearch.main(argString); 90 | System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 91 | System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 92 | argString[0]="D:/NewBatch/Unknown/64kbps"; argString[1]= "1"; MusicURISearch.main(argString); 93 | System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 94 | System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 95 | argString[0]="D:/NewBatch/Unknown/32kbps"; argString[1]= "1"; MusicURISearch.main(argString); 96 | System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 97 | 98 | System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 99 | argString[0]="D:/NewBatch/Unknown/128kbps"; argString[1]= "0"; MusicURISearch.main(argString); 100 | System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 101 | System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 102 | argString[0]="D:/NewBatch/Unknown/64kbps"; argString[1]= "0"; MusicURISearch.main(argString); 103 | System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 104 | System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 105 | argString[0]="D:/NewBatch/Unknown/32kbps"; argString[1]= "0"; MusicURISearch.main(argString); 106 | System.out.println ("\n"); System.out.println (df.format(new Date(System.currentTimeMillis()))); 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/utils/experimental/DbAverageDistanceCalculator.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2005, Dimitrios Kourtesis 3 | 4 | This file is part of MusicURI. 5 | 6 | MusicURI is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | MusicURI is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with MPEG7AudioEnc; see the file COPYING. If not, write to 18 | the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 19 | MA 02111-1307 USA 20 | */ 21 | 22 | package it.univpm.deit.semedia.musicuri.utils.experimental; 23 | 24 | 25 | import it.univpm.deit.database.datatypes.AudioLLDmeta; 26 | import it.univpm.deit.database.datatypes.Mp7ACT; 27 | import it.univpm.deit.semedia.musicuri.core.MusicURIDatabase; 28 | import it.univpm.deit.semedia.musicuri.core.MusicURIReference; 29 | import it.univpm.deit.semedia.musicuri.core.Toolset; 30 | 31 | 32 | import java.util.Iterator; 33 | import java.util.Set; 34 | 35 | 36 | /** 37 | * Utility class used for calculating the average distance of one MusicURIReference against the rest in the db 38 | */ 39 | public class DbAverageDistanceCalculator 40 | { 41 | static String databasePath = "D:/100ReferenceDB/"; 42 | static String databaseFileName = "MusicURIReferences.db"; 43 | static MusicURIDatabase db = new MusicURIDatabase(databasePath, databaseFileName); 44 | 45 | public static void main(String[] args) 46 | { 47 | 48 | double overallAverageDistance = 0; 49 | double overallDistanceSum = 0; 50 | 51 | //***************************************************************************** 52 | //************ Q U E R Y D A T A P R E P A R A T I O N **************** 53 | //***************************************************************************** 54 | 55 | // gets the set of keys from the db hashmap 56 | Set queryIterator = db.getSetOfMusicURIReferences(); 57 | 58 | for (Iterator iter = queryIterator.iterator(); iter.hasNext();) 59 | { 60 | // get the next md5 key 61 | String currentMD5 = (String) iter.next(); 62 | MusicURIReference qqq = db.getMusicURIReference(currentMD5); 63 | 64 | Mp7ACT queryMp7 = qqq.getAudioCompactType(); 65 | 66 | // if its null then there is some problem 67 | if (queryMp7 == null) 68 | System.out.println("Problem: queryMp7 is null"); 69 | 70 | // read the required data from the AudioCompactType 71 | AudioLLDmeta queryMean = queryMp7.featureByName(Mp7ACT.FLATNESS, Mp7ACT.MEAN); 72 | AudioLLDmeta queryVariance = queryMp7.featureByName(Mp7ACT.FLATNESS, Mp7ACT.VARIANCE); 73 | 74 | // is audioSignatureType included in the act file? 75 | if (queryMean == null || queryVariance == null ) 76 | { 77 | System.out.println("Problem: AudioSignatureType is not included in ACT or cannot be extracted from audio file. Aborting."); 78 | } 79 | 80 | int vectorSize = queryMean.vectorSize; // internal! stay out! read the matrix size instead 81 | float[][] queryMeanMatrix = queryMean.__rawVectors; 82 | float[][] queryVarianceMatrix = queryVariance.__rawVectors; 83 | 84 | // instantiate and initialize query data 85 | int QueryNumOfVectors = queryMeanMatrix.length; // ==number of vectors, seconds 86 | int QueryVectorDim = vectorSize; // ==number of dimensions, subbands 87 | double [] QueryMean = new double[QueryNumOfVectors * QueryVectorDim]; 88 | double [] QueryVar = new double[QueryNumOfVectors * QueryVectorDim]; 89 | 90 | // Copy the query data from the 2-d matrix of floats to a 1-d array of doubles 91 | QueryMean = Toolset.copyFloatMatrixToDoubleArray(queryMeanMatrix, vectorSize); 92 | QueryVar = Toolset.copyFloatMatrixToDoubleArray(queryVarianceMatrix, vectorSize); 93 | 94 | 95 | 96 | //***************************************************************************** 97 | //******************** D I S T A N C E S E A R C H ********************* 98 | //***************************************************************************** 99 | 100 | // declare here, initialize inside the for loop 101 | int RefNumOfVectors = 0; // number of vectors, seconds 102 | int RefVectorDim = 0; // number of subbands, dimensions 103 | double[] RefMean; 104 | double[] RefVar; 105 | 106 | // something big 107 | double distance = 0; 108 | 109 | // flag used to skip entering the for loop 110 | boolean skipThis = false; 111 | 112 | 113 | // a counter used for display purposes 114 | int counter = 1; 115 | 116 | 117 | //System.out.print("Searching for " + numOfClosestMatches + " closest matches among " + db.getDbSize() + " reference signatures "); 118 | 119 | double currentQueryDistanceSum = 0; 120 | double currentQueryAverageDistance = 0; 121 | int numberOfComparisonsMade = 0; 122 | 123 | 124 | // gets the set of keys from the db hashmap 125 | Set keys = db.getSetOfMusicURIReferences(); 126 | // beam me up scotty 127 | for (Iterator iter2 = keys.iterator(); iter2.hasNext();) 128 | { 129 | // get the next md5 key 130 | String currentMD52 = (String) iter2.next(); 131 | 132 | // retrieve the MusicURIReference object corrsponding to this key 133 | MusicURIReference currentReference = db.getMusicURIReference(currentMD52); 134 | 135 | // retrieve the mp7act encapsulated in the MusicURIReference object 136 | Mp7ACT mp7 = currentReference.getAudioCompactType(); 137 | 138 | // if it's null it shouldn't be 139 | if (mp7 == null) 140 | System.out.println("Problem: No mpeg7 exists for given uri"); 141 | 142 | //System.out.print("[" + counter + "] "+ mp7.getLabel()); 143 | 144 | // read the required data from the ACT 145 | AudioLLDmeta refMean = mp7.featureByName(Mp7ACT.FLATNESS, Mp7ACT.MEAN); 146 | AudioLLDmeta refVariance = mp7.featureByName(Mp7ACT.FLATNESS, Mp7ACT.VARIANCE); 147 | 148 | // if any of these are null there was some problem when extracting them, so skip them 149 | if ((refMean == null) || (refVariance == null)) 150 | { 151 | System.out.println("Skipping: problematic mpeg7 description!!! - "+mp7.getLabel()+")"); 152 | skipThis = true; 153 | } 154 | 155 | //System.out.println("if all goes well..."); 156 | // if all goes well... 157 | if (!skipThis) 158 | { 159 | //System.out.println(" does well..."); 160 | // instantiate and initialize reference data 161 | float[][] refMeanMatrix = refMean.__rawVectors; 162 | float[][] refVarianceMatrix = refVariance.__rawVectors; 163 | RefNumOfVectors = refMeanMatrix.length; // number of vectors-seconds 164 | RefVectorDim = vectorSize; // number of subbands 165 | RefMean = new double[RefNumOfVectors * RefVectorDim]; 166 | RefVar = new double[RefNumOfVectors * RefVectorDim]; 167 | 168 | // Copy the reference data from the 2-d matrix of floats to a 1-d array of doubles 169 | RefMean = Toolset.copyFloatMatrixToDoubleArray(refMeanMatrix, vectorSize); 170 | RefVar = Toolset.copyFloatMatrixToDoubleArray(refVarianceMatrix, vectorSize); 171 | 172 | // get the distance from query to reference 173 | distance = Mpeg7XMAudioSignatureSearch.WeightedEuclidianDistance(RefMean, RefVar, RefNumOfVectors, QueryMean, QueryVar, QueryNumOfVectors, QueryVectorDim); 174 | //distance = Toolset.getAlternativeDistance(refMeanMatrix, refVarianceMatrix, queryMeanMatrix, queryVarianceMatrix, QueryVectorDim); 175 | 176 | 177 | // print every reference in loop 178 | //System.out.println(distance + " \t" + currentReference.getLabel()); 179 | 180 | currentQueryDistanceSum += distance; 181 | //get the average distance 182 | 183 | numberOfComparisonsMade++; 184 | } 185 | counter++; 186 | skipThis = false; 187 | }// for referenceIterator 188 | 189 | currentQueryAverageDistance = currentQueryDistanceSum / numberOfComparisonsMade; 190 | //System.out.println("currentQueryDistanceSum : " + currentQueryDistanceSum); 191 | //System.out.println("numberOfComparisonsMade : " + numberOfComparisonsMade); 192 | System.out.println(counter + "\tcurrentQueryAverageDistance: " + currentQueryAverageDistance); 193 | 194 | overallDistanceSum += currentQueryAverageDistance; 195 | }//for queryIterator 196 | 197 | overallAverageDistance = overallDistanceSum / db.getDbSize(); 198 | System.out.println("overallDistanceSum : " + overallDistanceSum); 199 | System.out.println("db.getDbSize() : " + db.getDbSize()); 200 | System.out.println("overallAverageDistance: " + overallAverageDistance); 201 | } 202 | 203 | } 204 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/core/MusicURIQuery.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2005, Dimitrios Kourtesis 3 | 4 | This file is part of MusicURI. 5 | 6 | MusicURI is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | MusicURI is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with MPEG7AudioEnc; see the file COPYING. If not, write to 18 | the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 19 | MA 02111-1307 USA 20 | */ 21 | 22 | package it.univpm.deit.semedia.musicuri.core; 23 | 24 | 25 | import it.univpm.deit.database.datatypes.Mp7ACT; 26 | import it.univpm.deit.semedia.musicuri.core.Toolset; 27 | import java.io.File; 28 | import java.io.IOException; 29 | import java.io.StringReader; 30 | import java.util.ArrayList; 31 | import org.xml.sax.InputSource; 32 | import org.xml.sax.SAXException; 33 | 34 | /** 35 | * @author Dimitrios Kourtesis 36 | */ 37 | public class MusicURIQuery 38 | { 39 | 40 | /** 41 | * An Audio Compact Type object as defined in the Mpeg7AudioDB library, 42 | * probably containing not only an AudioSignatureDS instance, 43 | * but the whole mpeg7-audio descriptor suite 44 | */ 45 | private Mp7ACT audioCompactType; 46 | 47 | /** 48 | * The MD5 hash key of the original audiofile, produced by hashing 49 | * the actual binary file (and not the path to where it is located) 50 | */ 51 | private String originalAudioFileMD5; 52 | 53 | /** 54 | * List of keywords taken from the original audiofile's filename and/or id3 tag 55 | * The keywords are currently extracted by tokenizing the filename 56 | * Experimental use only 57 | */ 58 | private ArrayList keywords; 59 | 60 | /** 61 | * List of terms that are the metaphone equivalents of each keyword in the keywords list 62 | * The list of keywords was extracted from the original audiofile's filename and/or ID3 tag 63 | * The terms are generated using the double metaphone equivalent algorithm 64 | * Experimental use only 65 | */ 66 | private ArrayList metaphones; 67 | 68 | /** 69 | * An informative label describing a piece of music (eg could be a filename) 70 | */ 71 | private String label; 72 | 73 | 74 | 75 | 76 | 77 | /** 78 | * Constructs a MusicURIQuery object setting all its private atributes to null 79 | */ 80 | public MusicURIQuery() 81 | { 82 | this.audioCompactType = null; 83 | this.originalAudioFileMD5 = null; 84 | this.keywords = null; 85 | this.metaphones = null; 86 | this.label = null; 87 | } 88 | 89 | /** 90 | * Constructs a MusicURIQuery object by creating the given audio file's MPEG-7 91 | * AudioCompactType, hashing its binary content to create an MD5 key, and 92 | * tokenizing its filename and/or ID3 tag to create a list of keywords and their 93 | * double metaphone equivalent terms. 94 | * @param musicFile the path to the source audio file 95 | */ 96 | public MusicURIQuery(File musicFile) throws SAXException, IOException, Exception 97 | { 98 | File queryFile = musicFile;//.getCanonicalFile(); 99 | 100 | 101 | //***************** AUDIO COMPACT TYPE ********************* 102 | //System.out.println("Creating Audio Compact Type"); 103 | //Create an empty Mp7ACT object 104 | Mp7ACT myNewMpeg7 = new Mp7ACT(); 105 | // get an intermediary XML stream (String) containing the encoder-generated mpeg7 description 106 | // extracted from the given audio file, and copy the audiosignature data to our ACT 107 | myNewMpeg7.fromXML(new InputSource(new StringReader(Toolset.createMPEG7Description(queryFile)))); 108 | this.audioCompactType = myNewMpeg7; 109 | 110 | //URI queryFileURI = queryFile.toURI(); 111 | //String pathFromURI = queryFileURI.getPath(); 112 | //URI md5DataURI = Toolset.generateMD5URI(queryFileURI); 113 | // initialize the two private attributes of class Mp7ACT (describedResource=uri describedFilePath=label) 114 | // describedResource :urn:md5:yVh5jeZOwRwwLqUUwEXUtQ== 115 | // describedFilePath: /C:/musicURI/queries/0001 A Tribe Called Quest - Can I Kick It_10sec.mp3 116 | //Mp7ACT myNewMpeg7 = new Mp7ACT(md5DataURI, pathFromURI); 117 | // get an intermediary XML stream (String) containing the encoder-generated mpeg7 description 118 | // (from the audio file specified in the URI), and copy the audiosignature data to our ACT 119 | //myNewMpeg7.fromXML(new InputSource(new StringReader(Toolset.retriveMP7(queryFileURI)))); 120 | //this.audioCompactType = myNewMpeg7; 121 | 122 | 123 | //************************** MD-5 ************************** 124 | //System.out.println("Creating MD5 hash key"); 125 | // Hash the given audio file's binary contents to create the MD5 hash 126 | byte[] md = Toolset.createMD5Hash(queryFile); 127 | this.originalAudioFileMD5 = Toolset.toHexString(md); 128 | //System.out.println("hash: " + Utils.toHexString(md)); 129 | 130 | 131 | //************************** KEYWORDS ************************** 132 | //System.out.println("Extracting list of keywords"); 133 | // Tokenize the audio file's name to create a list of keywords 134 | this.keywords = Toolset.ExtractKeywords(queryFile); 135 | //System.out.println("keywords size: " + keywords.size()); 136 | //for (int i = 0; i < keywords.size(); i++) System.out.println(keywords.get(i).toString()); 137 | 138 | 139 | // ************************ METAPHONES ************************* 140 | //System.out.println("Extracting keywords' metaphone equivalents"); 141 | // Convert the elements of the keywords list to their metaphone equivalents, 142 | // to enable fuzzy phonetic matching, and robustness against mispellings 143 | this.metaphones = Toolset.GenerateMetaphones(keywords); 144 | //System.out.println("metaphones size: " + metaphones.size()); 145 | //for (int i = 0; i < metaphones.size(); i++) System.out.println(metaphones.get(i).toString()); 146 | 147 | 148 | // ************************** LABEL **************************** 149 | //System.out.println("Extracting label"); 150 | this.label = queryFile.getName(); 151 | //System.out.println("label: " + label); 152 | } 153 | 154 | /** 155 | * Gets the Mp7ACT object that is encapsulated in this MusicURIQuery object 156 | * @return audioCompactType the Mp7ACT object 157 | */ 158 | public Mp7ACT getAudioCompactType() 159 | { 160 | return audioCompactType; 161 | } 162 | 163 | /** 164 | * Sets the Mp7ACT object that is encapsulated in this MusicURIQuery object to the one specified 165 | * @param audioCompactType the Mp7ACT object to be set 166 | */ 167 | public void setAudioCompactType(Mp7ACT audioCompactType) 168 | { 169 | this.audioCompactType = audioCompactType; 170 | } 171 | 172 | /** 173 | * Gets the MD5 key of the original audio file that this MusicURIQuery object was created from 174 | * @return originalAudioFileMD5 the MD5 hash key 175 | */ 176 | public String getOriginalAudioFileMD5() 177 | { 178 | return originalAudioFileMD5; 179 | } 180 | 181 | /** 182 | * Sets the MD5 key of the original audio file that this MusicURIQuery corresponds to 183 | * @param originalAudioFileMD5 the MD5 hash key to set 184 | */ 185 | public void setOriginalAudioFileMD5(String originalAudioFileMD5) 186 | { 187 | this.originalAudioFileMD5 = originalAudioFileMD5; 188 | } 189 | 190 | /** 191 | * Gets the list of keywords in this MusicURIQuery object 192 | * @return keywords the list of keywords 193 | */ 194 | public ArrayList getKeywords() 195 | { 196 | return keywords; 197 | } 198 | 199 | /** 200 | * Sets the list of keywords in this MusicURIQuery object 201 | * @return keywords the list of keywords to set 202 | */ 203 | public void setKeywords(ArrayList keywords) 204 | { 205 | this.keywords = keywords; 206 | } 207 | 208 | /** 209 | * Gets the list of metaphone equivalent terms that correspond to the keywords contained in the keywords list 210 | * @return metaphones the list of metaphones 211 | */ 212 | public ArrayList getMetaphones() 213 | { 214 | return metaphones; 215 | } 216 | 217 | /** 218 | * Sets the list of metaphone equivalent terms that correspond to the keywords contained in the keywords list 219 | * @param metaphones the list of metaphones to set 220 | */ 221 | public void setMetaphones(ArrayList metaphones) 222 | { 223 | this.metaphones = metaphones; 224 | } 225 | 226 | /** 227 | * Gets the label describing the audio file this MusicURIQuery has been created from 228 | * @return label the label describing the original audio file 229 | */ 230 | public String getLabel() 231 | { 232 | return label; 233 | } 234 | 235 | /** 236 | * Sets the label describing the audio file this MusicURIQuery has been created from 237 | * @param label the label to be set, describing the original audio file 238 | */ 239 | public void setLabel(String label) 240 | { 241 | this.label = label; 242 | } 243 | 244 | 245 | }//end class 246 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/webservice/client/MusicURIWebSearchSoapBindingStub.java: -------------------------------------------------------------------------------- 1 | /** 2 | * MusicURIWebSearchSoapBindingStub.java 3 | * 4 | * This file was auto-generated from WSDL 5 | * by the Apache Axis 1.2.1 Jun 14, 2005 (09:15:57 EDT) WSDL2Java emitter. 6 | */ 7 | 8 | package it.univpm.deit.semedia.musicuri.webservice.client; 9 | 10 | public class MusicURIWebSearchSoapBindingStub 11 | extends org.apache.axis.client.Stub 12 | implements it.univpm.deit.semedia.musicuri.webservice.client.MusicURIWebSearch 13 | { 14 | private java.util.Vector cachedSerClasses = new java.util.Vector(); 15 | 16 | private java.util.Vector cachedSerQNames = new java.util.Vector(); 17 | 18 | private java.util.Vector cachedSerFactories = new java.util.Vector(); 19 | 20 | private java.util.Vector cachedDeserFactories = new java.util.Vector(); 21 | 22 | static org.apache.axis.description.OperationDesc[] _operations; 23 | 24 | static 25 | { 26 | _operations = new org.apache.axis.description.OperationDesc[3]; 27 | _initOperationDesc1(); 28 | } 29 | 30 | private static void _initOperationDesc1() 31 | { 32 | org.apache.axis.description.OperationDesc oper; 33 | org.apache.axis.description.ParameterDesc param; 34 | oper = new org.apache.axis.description.OperationDesc(); 35 | oper.setName("getMusicURIReferenceList"); 36 | oper.setReturnType(new javax.xml.namespace.QName( 37 | "http://www.w3.org/2001/XMLSchema", "string")); 38 | oper.setReturnClass(java.lang.String.class); 39 | oper.setReturnQName(new javax.xml.namespace.QName("", 40 | "getMusicURIReferenceListReturn")); 41 | oper.setStyle(org.apache.axis.constants.Style.RPC); 42 | oper.setUse(org.apache.axis.constants.Use.ENCODED); 43 | _operations[0] = oper; 44 | 45 | oper = new org.apache.axis.description.OperationDesc(); 46 | oper.setName("getNumOfMusicURIReferences"); 47 | oper.setReturnType(new javax.xml.namespace.QName( 48 | "http://www.w3.org/2001/XMLSchema", "int")); 49 | oper.setReturnClass(int.class); 50 | oper.setReturnQName(new javax.xml.namespace.QName("", 51 | "getNumOfMusicURIReferencesReturn")); 52 | oper.setStyle(org.apache.axis.constants.Style.RPC); 53 | oper.setUse(org.apache.axis.constants.Use.ENCODED); 54 | _operations[1] = oper; 55 | 56 | oper = new org.apache.axis.description.OperationDesc(); 57 | oper.setName("performSearch"); 58 | param = new org.apache.axis.description.ParameterDesc( 59 | new javax.xml.namespace.QName("", "xmlAudioSignature"), 60 | org.apache.axis.description.ParameterDesc.IN, 61 | new javax.xml.namespace.QName( 62 | "http://www.w3.org/2001/XMLSchema", "string"), 63 | java.lang.String.class, false, false); 64 | oper.addParameter(param); 65 | param = new org.apache.axis.description.ParameterDesc( 66 | new javax.xml.namespace.QName("", "filename"), 67 | org.apache.axis.description.ParameterDesc.IN, 68 | new javax.xml.namespace.QName( 69 | "http://www.w3.org/2001/XMLSchema", "string"), 70 | java.lang.String.class, false, false); 71 | oper.addParameter(param); 72 | oper.setReturnType(new javax.xml.namespace.QName( 73 | "http://www.w3.org/2001/XMLSchema", "string")); 74 | oper.setReturnClass(java.lang.String.class); 75 | oper.setReturnQName(new javax.xml.namespace.QName("", 76 | "performSearchReturn")); 77 | oper.setStyle(org.apache.axis.constants.Style.RPC); 78 | oper.setUse(org.apache.axis.constants.Use.ENCODED); 79 | _operations[2] = oper; 80 | 81 | } 82 | 83 | public MusicURIWebSearchSoapBindingStub() throws org.apache.axis.AxisFault 84 | { 85 | this(null); 86 | } 87 | 88 | public MusicURIWebSearchSoapBindingStub(java.net.URL endpointURL, 89 | javax.xml.rpc.Service service) throws org.apache.axis.AxisFault 90 | { 91 | this(service); 92 | super.cachedEndpoint = endpointURL; 93 | } 94 | 95 | public MusicURIWebSearchSoapBindingStub(javax.xml.rpc.Service service) 96 | throws org.apache.axis.AxisFault 97 | { 98 | if (service == null) 99 | { 100 | super.service = new org.apache.axis.client.Service(); 101 | } else 102 | { 103 | super.service = service; 104 | } 105 | ((org.apache.axis.client.Service) super.service) 106 | .setTypeMappingVersion("1.2"); 107 | } 108 | 109 | protected org.apache.axis.client.Call createCall() 110 | throws java.rmi.RemoteException 111 | { 112 | try 113 | { 114 | org.apache.axis.client.Call _call = super._createCall(); 115 | if (super.maintainSessionSet) 116 | { 117 | _call.setMaintainSession(super.maintainSession); 118 | } 119 | if (super.cachedUsername != null) 120 | { 121 | _call.setUsername(super.cachedUsername); 122 | } 123 | if (super.cachedPassword != null) 124 | { 125 | _call.setPassword(super.cachedPassword); 126 | } 127 | if (super.cachedEndpoint != null) 128 | { 129 | _call.setTargetEndpointAddress(super.cachedEndpoint); 130 | } 131 | if (super.cachedTimeout != null) 132 | { 133 | _call.setTimeout(super.cachedTimeout); 134 | } 135 | if (super.cachedPortName != null) 136 | { 137 | _call.setPortName(super.cachedPortName); 138 | } 139 | java.util.Enumeration keys = super.cachedProperties.keys(); 140 | while (keys.hasMoreElements()) 141 | { 142 | java.lang.String key = (java.lang.String) keys.nextElement(); 143 | _call.setProperty(key, super.cachedProperties.get(key)); 144 | } 145 | return _call; 146 | } catch (java.lang.Throwable _t) 147 | { 148 | throw new org.apache.axis.AxisFault( 149 | "Failure trying to get the Call object", _t); 150 | } 151 | } 152 | 153 | public java.lang.String getMusicURIReferenceList() 154 | throws java.rmi.RemoteException 155 | { 156 | if (super.cachedEndpoint == null) 157 | { 158 | throw new org.apache.axis.NoEndPointException(); 159 | } 160 | org.apache.axis.client.Call _call = createCall(); 161 | _call.setOperation(_operations[0]); 162 | _call.setUseSOAPAction(true); 163 | _call.setSOAPActionURI(""); 164 | _call 165 | .setSOAPVersion(org.apache.axis.soap.SOAPConstants.SOAP11_CONSTANTS); 166 | _call.setOperationName(new javax.xml.namespace.QName( 167 | "http://DefaultNamespace", "getMusicURIReferenceList")); 168 | 169 | setRequestHeaders(_call); 170 | setAttachments(_call); 171 | try 172 | { 173 | java.lang.Object _resp = _call.invoke(new java.lang.Object[] {}); 174 | 175 | if (_resp instanceof java.rmi.RemoteException) 176 | { 177 | throw (java.rmi.RemoteException) _resp; 178 | } else 179 | { 180 | extractAttachments(_call); 181 | try 182 | { 183 | return (java.lang.String) _resp; 184 | } catch (java.lang.Exception _exception) 185 | { 186 | return (java.lang.String) org.apache.axis.utils.JavaUtils 187 | .convert(_resp, java.lang.String.class); 188 | } 189 | } 190 | } catch (org.apache.axis.AxisFault axisFaultException) 191 | { 192 | throw axisFaultException; 193 | } 194 | } 195 | 196 | public int getNumOfMusicURIReferences() throws java.rmi.RemoteException 197 | { 198 | if (super.cachedEndpoint == null) 199 | { 200 | throw new org.apache.axis.NoEndPointException(); 201 | } 202 | org.apache.axis.client.Call _call = createCall(); 203 | _call.setOperation(_operations[1]); 204 | _call.setUseSOAPAction(true); 205 | _call.setSOAPActionURI(""); 206 | _call 207 | .setSOAPVersion(org.apache.axis.soap.SOAPConstants.SOAP11_CONSTANTS); 208 | _call.setOperationName(new javax.xml.namespace.QName( 209 | "http://DefaultNamespace", "getNumOfMusicURIReferences")); 210 | 211 | setRequestHeaders(_call); 212 | setAttachments(_call); 213 | try 214 | { 215 | java.lang.Object _resp = _call.invoke(new java.lang.Object[] {}); 216 | 217 | if (_resp instanceof java.rmi.RemoteException) 218 | { 219 | throw (java.rmi.RemoteException) _resp; 220 | } else 221 | { 222 | extractAttachments(_call); 223 | try 224 | { 225 | return ((java.lang.Integer) _resp).intValue(); 226 | } catch (java.lang.Exception _exception) 227 | { 228 | return ((java.lang.Integer) org.apache.axis.utils.JavaUtils 229 | .convert(_resp, int.class)).intValue(); 230 | } 231 | } 232 | } catch (org.apache.axis.AxisFault axisFaultException) 233 | { 234 | throw axisFaultException; 235 | } 236 | } 237 | 238 | public java.lang.String performSearch(java.lang.String xmlAudioSignature, 239 | java.lang.String filename) throws java.rmi.RemoteException 240 | { 241 | if (super.cachedEndpoint == null) 242 | { 243 | throw new org.apache.axis.NoEndPointException(); 244 | } 245 | org.apache.axis.client.Call _call = createCall(); 246 | _call.setOperation(_operations[2]); 247 | _call.setUseSOAPAction(true); 248 | _call.setSOAPActionURI(""); 249 | _call.setSOAPVersion(org.apache.axis.soap.SOAPConstants.SOAP11_CONSTANTS); 250 | _call.setOperationName(new javax.xml.namespace.QName( 251 | "http://DefaultNamespace", "performSearch")); 252 | 253 | setRequestHeaders(_call); 254 | setAttachments(_call); 255 | try 256 | { 257 | java.lang.Object _resp = _call.invoke(new java.lang.Object[] 258 | { xmlAudioSignature, filename }); 259 | 260 | if (_resp instanceof java.rmi.RemoteException) 261 | { 262 | throw (java.rmi.RemoteException) _resp; 263 | } else 264 | { 265 | extractAttachments(_call); 266 | try 267 | { 268 | return (java.lang.String) _resp; 269 | } catch (java.lang.Exception _exception) 270 | { 271 | return (java.lang.String) org.apache.axis.utils.JavaUtils 272 | .convert(_resp, java.lang.String.class); 273 | } 274 | } 275 | } catch (org.apache.axis.AxisFault axisFaultException) 276 | { 277 | throw axisFaultException; 278 | } 279 | } 280 | 281 | } 282 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/core/MusicURIReference.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2005, Dimitrios Kourtesis 3 | 4 | This file is part of MusicURI. 5 | 6 | MusicURI is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | MusicURI is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with MPEG7AudioEnc; see the file COPYING. If not, write to 18 | the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 19 | MA 02111-1307 USA 20 | */ 21 | 22 | package it.univpm.deit.semedia.musicuri.core; 23 | 24 | 25 | import it.univpm.deit.database.datatypes.Mp7ACT; 26 | import it.univpm.deit.semedia.musicuri.core.Toolset; 27 | import java.io.File; 28 | import java.io.Serializable; 29 | import java.io.StringReader; 30 | import java.net.URI; 31 | import java.util.ArrayList; 32 | import org.xml.sax.InputSource; 33 | 34 | /** 35 | * @author Dimitrios Kourtesis 36 | */ 37 | public class MusicURIReference implements Serializable 38 | { 39 | 40 | /** 41 | * An Audio Compact Type object as defined in the Mpeg7AudioDB library, 42 | * probably containing not only an AudioSignatureDS instance, 43 | * but the whole mpeg7-audio descriptor suite 44 | */ 45 | private Mp7ACT audioCompactType; 46 | 47 | /** 48 | * The MD5 hash key of the audiofile that is identified as a "representative" physical 49 | * resource containing a digitally encoded conceptual resource. For example, this could be 50 | * the MD5 key of the first mp3 file containing Eric Clapton's "Layla", that has been presented 51 | * to the system. Thereafter all digital audio files containing the same song will be collapsed 52 | * onto the specific musicURIReference containing the MD5 key of the first, original file. 53 | * the actual binary file (and not the path to where it is located) 54 | */ 55 | private String originalAudioFileMD5; 56 | 57 | /** 58 | * List of keywords taken from the original audiofile's filename and/or id3 tag 59 | * The keywords are currently extracted by tokenizing the filename 60 | * Experimental use only 61 | */ 62 | private ArrayList keywords; 63 | 64 | /** 65 | * List of terms that are the metaphone equivalents of each keyword in the keywords list 66 | * The list of keywords was extracted from the original audiofile's filename and/or ID3 tag 67 | * The terms are generated using the double metaphone equivalent algorithm 68 | * Experimental use only 69 | */ 70 | private ArrayList metaphones; 71 | 72 | /** 73 | * An informative label describing a piece of music (eg could be a filename) 74 | */ 75 | private String label; 76 | 77 | /** 78 | * The actual music URI that uniquely identifies the specific MusicURIReference, 79 | * and thus, the underlying conceptual resource, which is a song 80 | */ 81 | private URI musicUri; 82 | 83 | 84 | 85 | 86 | /** 87 | * Constructs a MusicURIReference object by creating the given audio file's 88 | * MPEG-7 AudioCompactType, hashing its binary content to create an MD5 key, and 89 | * tokenizing its filename and/or ID3 tag to create a list of keywords and their 90 | * double metaphone equivalent terms. 91 | * @param musicFile the path to the source audio file 92 | */ 93 | public MusicURIReference(File musicFile) throws Exception 94 | { 95 | File queryFile = musicFile.getCanonicalFile(); 96 | 97 | //***************** AUDIO COMPACT TYPE ********************* 98 | Mp7ACT myNewMpeg7 = new Mp7ACT(); 99 | // get an intermediary XML stream (String) containing the encoder-generated mpeg7 description 100 | // extracted from the given audio file, and copy the audiosignature data to our ACT 101 | myNewMpeg7.fromXML(new InputSource(new StringReader(Toolset.createMPEG7Description(queryFile)))); 102 | this.audioCompactType = myNewMpeg7; 103 | 104 | 105 | //************************** MD-5 ************************** 106 | // Hash the given audio file's binary contents to create the MD5 hash 107 | byte[] md = Toolset.createMD5Hash(queryFile); 108 | this.originalAudioFileMD5 = Toolset.toHexString(md); 109 | //System.out.println("hash: " + Toolset.toHexString(md)); 110 | 111 | 112 | //************************** KEYWORDS ************************** 113 | // Tokenize the audio file's name to create a list of keywords 114 | this.keywords = Toolset.ExtractKeywords(queryFile); 115 | //System.out.println("keywords size: " + keywords.size()); 116 | //for (int i = 0; i < keywords.size(); i++) System.out.println(keywords.get(i).toString()); 117 | 118 | 119 | // ************************ METAPHONES ************************* 120 | // Convert the elements of the keywords list to their metaphone equivalents, 121 | // to enable fuzzy phonetic matching, and robustness against mispellings 122 | this.metaphones = Toolset.GenerateMetaphones(keywords); 123 | //System.out.println("metaphones size: " + metaphones.size()); 124 | //for (int i = 0; i < metaphones.size(); i++) System.out.println(metaphones.get(i).toString()); 125 | 126 | 127 | // ************************ MUSIC URI ************************** 128 | musicUri = new URI("http://musicuri.org/" + originalAudioFileMD5); 129 | //System.out.println("musicUri: " + musicUri.toString()); 130 | 131 | 132 | // ************************** LABEL **************************** 133 | label = queryFile.getName(); 134 | //System.out.println("label: " + label); 135 | } 136 | 137 | /** 138 | * Constructs a MusicURIReference object by setting its private attributes to the ones given 139 | * @param audioCompactType the Mp7ACT object extracted from the source audio file 140 | * @param originalAudioFileMD5 the MD5 hash key of the audio file 141 | * @param keywords the list of keywaords extracted from the source audio file 142 | * @param metaphones the list of metaphone equivalent terms generated from the keywords 143 | * @param musicUri the actual URI identifying this MusicURIReference 144 | * @param label the label describing the source audio file 145 | */ 146 | MusicURIReference(Mp7ACT audioCompactType, 147 | String originalAudioFileMD5, 148 | ArrayList keywords, 149 | ArrayList metaphones, 150 | URI musicUri, 151 | String label) 152 | { 153 | this.audioCompactType = audioCompactType; 154 | this.originalAudioFileMD5 = originalAudioFileMD5; 155 | this.keywords = keywords; 156 | this.metaphones = metaphones; 157 | this.musicUri = musicUri; 158 | this.label = label; 159 | } 160 | 161 | /** 162 | * Gets the Mp7ACT object that is encapsulated in this MusicURIQuery object 163 | * @return audioCompactType the Mp7ACT object 164 | */ 165 | public Mp7ACT getAudioCompactType() 166 | { 167 | return audioCompactType; 168 | } 169 | 170 | /** 171 | * Sets the Mp7ACT object that is encapsulated in this MusicURIQuery object to the one specified 172 | * @param audioCompactType the Mp7ACT object to be set 173 | */ 174 | public void setAudioCompactType(Mp7ACT audioCompactType) 175 | { 176 | this.audioCompactType = audioCompactType; 177 | } 178 | 179 | /** 180 | * Gets the MD5 key of the original audio file that this MusicURIQuery object was created from 181 | * @return originalAudioFileMD5 the MD5 hash key 182 | */ 183 | public String getOriginalAudioFileMD5() 184 | { 185 | return originalAudioFileMD5; 186 | } 187 | 188 | /** 189 | * Sets the MD5 key of the original audio file that this MusicURIQuery corresponds to 190 | * @param originalAudioFileMD5 the MD5 hash key to set 191 | */ 192 | public void setOriginalAudioFileMD5(String originalAudioFileMD5) 193 | { 194 | this.originalAudioFileMD5 = originalAudioFileMD5; 195 | } 196 | 197 | /** 198 | * Gets the list of keywords in this MusicURIQuery object 199 | * @return keywords the list of keywords 200 | */ 201 | public ArrayList getKeywords() 202 | { 203 | return keywords; 204 | } 205 | 206 | /** 207 | * Sets the list of keywords in this MusicURIQuery object 208 | * @return keywords the list of keywords to set 209 | */ 210 | public void setKeywords(ArrayList keywords) 211 | { 212 | this.keywords = keywords; 213 | } 214 | 215 | /** 216 | * Gets the list of metaphone equivalent terms that correspond to the keywords contained in the keywords list 217 | * @return metaphones the list of metaphones 218 | */ 219 | public ArrayList getMetaphones() 220 | { 221 | return metaphones; 222 | } 223 | 224 | /** 225 | * Sets the list of metaphone equivalent terms that correspond to the keywords contained in the keywords list 226 | * @param metaphones the list of metaphones to set 227 | */ 228 | public void setMetaphones(ArrayList metaphones) 229 | { 230 | this.metaphones = metaphones; 231 | } 232 | 233 | /** 234 | * Gets the label describing the audio file this MusicURIQuery has been created from 235 | * @return label the label describing the original audio file 236 | */ 237 | public String getLabel() 238 | { 239 | return label; 240 | } 241 | 242 | /** 243 | * Sets the label describing the audio file this MusicURIQuery has been created from 244 | * @param label the label to be set, describing the original audio file 245 | */ 246 | public void setLabel(String label) 247 | { 248 | this.label = label; 249 | } 250 | 251 | /** 252 | * Gets the URI this MusicURIReference has been assigned to 253 | * @return musicUri the URI assigned to this reference 254 | */ 255 | public URI getMusicUri() 256 | { 257 | return musicUri; 258 | } 259 | 260 | /** 261 | * Sets the URI this MusicURIReference should be assigned to 262 | * @param uri the URI to be set 263 | */ 264 | public void setMusicUri(URI uri) 265 | { 266 | this.musicUri = uri; 267 | } 268 | 269 | /** 270 | * Prints some of the private attribute's values on screen (Experimental use only) 271 | */ 272 | public void printToScreen() 273 | { 274 | System.out.println("MD5: " + getOriginalAudioFileMD5() + ", Label: "+ getLabel() + ", musicuri: " + getMusicUri()); 275 | 276 | ArrayList keys = getKeywords(); 277 | ArrayList metas = getMetaphones(); 278 | for (int i = 0; i < keys.size(); i++) 279 | { 280 | System.out.println("keyword: "+ keys.get(i) + " metaphone: " + metas.get(i)); 281 | } 282 | } 283 | 284 | 285 | }//end class 286 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/core/MusicURIDatabase.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2005, Dimitrios Kourtesis 3 | 4 | This file is part of MusicURI. 5 | 6 | MusicURI is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | MusicURI is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with MPEG7AudioEnc; see the file COPYING. If not, write to 18 | the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 19 | MA 02111-1307 USA 20 | */ 21 | 22 | package it.univpm.deit.semedia.musicuri.core; 23 | 24 | 25 | import java.io.File; 26 | import java.io.FileInputStream; 27 | import java.io.FileOutputStream; 28 | import java.io.FileWriter; 29 | import java.io.IOException; 30 | import java.io.InvalidClassException; 31 | import java.io.ObjectInputStream; 32 | import java.io.ObjectOutputStream; 33 | import java.io.Serializable; 34 | import java.net.URI; 35 | import java.net.URISyntaxException; 36 | import java.util.HashMap; 37 | import java.util.Iterator; 38 | import java.util.Map; 39 | import java.util.Set; 40 | import com.thoughtworks.xstream.XStream; 41 | 42 | /** 43 | * @author Dimitrios Kourtesis 44 | */ 45 | public class MusicURIDatabase implements Serializable 46 | { 47 | 48 | private static final long serialVersionUID = 1L; 49 | /** 50 | * A HashMap object containing pairs of an MD5 String as key and a MusicURIReference object as value 51 | */ 52 | private HashMap table; 53 | /** 54 | * The path to where the serialized HashMap database is located 55 | */ 56 | private String databasePath; 57 | /** 58 | * The database file name 59 | */ 60 | private String databaseFileName; 61 | 62 | 63 | 64 | 65 | /** 66 | * Constructs a MusicURIDatabase object by deserializing the HashMap specified by the path 67 | * @param databasePath the path to the directory containing the db 68 | * @param databaseFileName the filename of the serialized hashmap 69 | */ 70 | public MusicURIDatabase(String databasePath, String databaseFileName) 71 | { 72 | table = new HashMap(); 73 | this.databasePath = databasePath; 74 | this.databaseFileName = databaseFileName; 75 | 76 | try 77 | { 78 | table = (HashMap) deserialize(databasePath + databaseFileName); 79 | //System.out.println(table.size() + " references loaded from " + databaseFileName); 80 | } 81 | catch (ClassNotFoundException e) 82 | { 83 | e.toString(); 84 | //System.out.println("Can't load database file (" + databasePath + databaseFileName + ")"); 85 | } 86 | catch (InvalidClassException e) 87 | { 88 | e.toString(); 89 | //System.out.println("Can't load database file (" + databasePath + databaseFileName + ")"); 90 | } 91 | catch (IOException e) 92 | { 93 | e.toString(); 94 | //System.out.println("Can't load database file (" + databasePath + databaseFileName + ")"); 95 | } 96 | catch (Exception e) 97 | { 98 | e.toString(); 99 | //System.out.println("Can't load database file (" + databasePath + databaseFileName + ")"); 100 | } 101 | } 102 | 103 | /** 104 | * Creates and adds to the DB a MusicURIReference object for every audio file contained in the directory specified 105 | * @param directoryPath the path to the directory containing the audio files to be added to the DB 106 | */ 107 | public void indexAudioFilesInDirectory(String directoryPath) 108 | { 109 | File path = new File(directoryPath); 110 | File[] list = path.listFiles(); 111 | if (list.length == 0) 112 | { 113 | return; 114 | } 115 | else 116 | { 117 | for (int i = 0; i < list.length; i++) 118 | { 119 | File file = list[i]; 120 | try 121 | { 122 | if (Toolset.isSupportedAudioFile(file)) 123 | addMusicURIReference(new MusicURIReference(file)); 124 | } 125 | catch (Exception e) 126 | { 127 | e.printStackTrace(); 128 | } 129 | } 130 | } 131 | } 132 | 133 | /** 134 | * Adds the given MusicURIReference object to the DB, and also serializes it to xml 135 | * @param newReference the MusicURIReference object to add to the DB 136 | */ 137 | public boolean addMusicURIReference(MusicURIReference newReference) 138 | { 139 | 140 | String md5 = newReference.getOriginalAudioFileMD5(); // MD5 used askey 141 | String filename = md5 + ".xml"; 142 | File serializedObject = new File(databasePath + filename); 143 | 144 | // check if MD5 is already in use, and if the object serialized to xml exists on disk 145 | if (table.containsKey(md5)) 146 | { 147 | //System.out.println("This MD5 is already in use"); 148 | //if (serializedObject.exists()) System.out.println("XML file exists"); 149 | //else System.out.println("XML file does not exist in DB directory"); 150 | return false; 151 | } 152 | else 153 | { 154 | //although not required, also serialize to xml for easy debugging 155 | serializeToXmlFile(newReference, databasePath + filename); 156 | //add newReference to list with MD5 String as key, MusicURIReference object as value 157 | table.put(md5, newReference); 158 | saveDb(); 159 | return true; 160 | } 161 | } 162 | 163 | /** 164 | * Serializes the HashMap table containing all references, saving its state 165 | */ 166 | public void saveDb() 167 | { 168 | serialize(table, databasePath + databaseFileName); 169 | //System.out.println(table.keySet().size() + " references saved in " + databaseFileName); 170 | } 171 | 172 | /** 173 | * Removes a MusicURIReference object from the DB 174 | * @param md5 the MD5 key of the MusicURIReference object to remove 175 | */ 176 | public boolean removeMusicURIReference (String md5) 177 | { 178 | if (!table.containsKey(md5)) // check if MD5 key exists in db 179 | { 180 | //System.out.println ("This MD5 key is not registered in the DB"); 181 | return false; 182 | } 183 | else 184 | { 185 | //remove MD5 and associated MusicURIReference from db 186 | table.remove(md5); 187 | saveDb(); 188 | return true; 189 | } 190 | 191 | } 192 | 193 | /** 194 | * Fetches a MusicURIReference object from the DB 195 | * @param md5 the MD5 key of the MusicURIReference object to fetch 196 | * @return the MusicURIReference that was fetched, if it exists, null otherwise 197 | */ 198 | public MusicURIReference getMusicURIReference(String md5) 199 | { 200 | if (!table.containsKey(md5)) // check if MD5 key exists in db 201 | { 202 | //System.out.println ("This MD5 key is not registered in the DB"); 203 | return null; 204 | } 205 | else 206 | { 207 | // get associated MusicURIReference 208 | return (MusicURIReference)table.get(md5); 209 | } 210 | } 211 | 212 | /** 213 | * Fetches the HashMap object that comprises the DB as a set view (object removals supported) 214 | * @return a set view of the keys contained in the HashMap 215 | */ 216 | public Set getSetOfMusicURIReferences() 217 | { 218 | try 219 | { 220 | //HashMap tableClone = (HashMap) Cloner.cloneObject(table); 221 | //return tableClone.keySet(); 222 | return table.keySet(); 223 | } 224 | catch (Exception e) 225 | { 226 | e.printStackTrace(); 227 | return null; 228 | } 229 | } 230 | 231 | /** 232 | * Returns a String containing a formatted list of all the audio files that have 233 | * been indexed as references in the DB (lists their titles and URIs). 234 | */ 235 | public String textFormattedSetOfMusicURIReferences() 236 | { 237 | String text = "\nReference audio files indexed in the DB, and their assigned URIs:\n\n"; 238 | 239 | Set set = table.entrySet(); 240 | Iterator it = set.iterator(); 241 | int index = 1; 242 | while (it.hasNext()) 243 | { 244 | Map.Entry e = (Map.Entry)it.next(); 245 | text = text.concat("["+ index + "]" + "\tTitle : " + ((MusicURIReference)e.getValue()).getLabel() + "\n"); 246 | text = text.concat("\tURI : " + ((MusicURIReference)e.getValue()).getMusicUri() + "\n\n"); 247 | index ++; 248 | } 249 | return text; 250 | } 251 | 252 | /** 253 | * Gets the number of entries in the HashMap object that comprises the DB 254 | * @return the size of the DB 255 | */ 256 | public int getDbSize() 257 | { 258 | return table.size(); 259 | } 260 | 261 | /** 262 | * Serializes any object to the filename specified 263 | * @param object the object to be serialized 264 | * @param fileName the filename of the serialized object 265 | */ 266 | public void serialize(Object object,String fileName) 267 | { 268 | try 269 | { 270 | ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(fileName)); 271 | out.writeObject(object); 272 | out.flush(); 273 | } 274 | catch (IOException e) 275 | { 276 | System.err.println("Unable to serialize object: " + e.toString()); 277 | } 278 | } 279 | 280 | /** 281 | * Deserializes any object from the filename specified 282 | * @param filePath the filename of the serialized object 283 | * @return the object that was deserialized 284 | */ 285 | public Object deserialize(String filePath) throws IOException, ClassNotFoundException 286 | { 287 | Object object = new Object(); 288 | ObjectInputStream in = new ObjectInputStream(new FileInputStream(filePath)); 289 | object = in.readObject(); 290 | return object; 291 | } 292 | 293 | /** 294 | * Deserializes a HashMap object from the filename specified 295 | * @param filePath the filename of the serialized HashMap 296 | * @return the HashMap object that was deserialized 297 | */ 298 | public HashMap deserializeHashMap(String filePath) throws IOException, ClassNotFoundException 299 | { 300 | HashMap object = new HashMap(); 301 | ObjectInputStream in = new ObjectInputStream(new FileInputStream(filePath)); 302 | object = (HashMap) in.readObject(); 303 | return object; 304 | } 305 | 306 | /** 307 | * Serializes any object to an XML file with the filename specified 308 | * @param object the object to be serialized 309 | * @param filename the XML filename of the serialized object 310 | */ 311 | public void serializeToXmlFile(Object object, String filename) 312 | { 313 | XStream xstream = new XStream(); 314 | String xml = xstream.toXML(object); 315 | try 316 | { 317 | FileWriter fw = new FileWriter(filename); 318 | fw.write(xml); 319 | fw.close(); 320 | } 321 | catch (IOException e) 322 | { 323 | e.printStackTrace(); 324 | } 325 | } 326 | 327 | 328 | // /** 329 | // * Adds an Mp7ACT object to the DB 330 | // * @param act the Mp7ACT object to be added 331 | // * Experimental use only 332 | // */ 333 | // private void ACT2ReferenceConverter(Mp7ACT act) throws NoSuchAlgorithmException, IOException, URISyntaxException 334 | // { 335 | // String label = act.getLabel(); 336 | // File mp3File = new File(label); 337 | // byte[] md5bytes = Toolset.createMD5Hash(mp3File); 338 | // String md5 = Toolset.toHexString(md5bytes); 339 | // ArrayList keywords = Toolset.ExtractKeywords(mp3File); 340 | // ArrayList metaphones = Toolset.GenerateMetaphones(keywords); 341 | // URI musicUri = new URI ("file", label, null); 342 | // 343 | // MusicURIReference newref = new MusicURIReference(act, md5, keywords, metaphones, musicUri, label); 344 | // addMusicURIReference(newref); 345 | // } 346 | 347 | 348 | 349 | } 350 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/utils/experimental/LambdaCalculator.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2005, Dimitrios Kourtesis 3 | 4 | This file is part of MusicURI. 5 | 6 | MusicURI is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | MusicURI is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with MPEG7AudioEnc; see the file COPYING. If not, write to 18 | the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 19 | MA 02111-1307 USA 20 | */ 21 | 22 | package it.univpm.deit.semedia.musicuri.utils.experimental; 23 | 24 | 25 | import it.univpm.deit.database.datatypes.AudioLLDmeta; 26 | import it.univpm.deit.database.datatypes.Mp7ACT; 27 | import it.univpm.deit.semedia.musicuri.core.MusicURIDatabase; 28 | import it.univpm.deit.semedia.musicuri.core.MusicURIQuery; 29 | import it.univpm.deit.semedia.musicuri.core.MusicURIReference; 30 | import it.univpm.deit.semedia.musicuri.core.Toolset; 31 | import it.univpm.deit.semedia.musicuri.statistics.PerformanceStatistic; 32 | 33 | import java.io.File; 34 | import java.util.ArrayList; 35 | import java.util.Iterator; 36 | import java.util.Set; 37 | 38 | 39 | import org.apache.commons.math.stat.descriptive.SummaryStatistics; 40 | 41 | 42 | import com.wcohen.secondstring.JaroWinkler; 43 | import com.wcohen.secondstring.StringWrapper; 44 | 45 | /** 46 | * Utility class used for calculating the optimal lambda for a linear combination of heterogeneous distance metrics 47 | */ 48 | public class LambdaCalculator 49 | { 50 | static String databasePath = "D:/1000ReferenceDB/"; 51 | static String databaseFileName = "MusicURIReferences.db"; 52 | static MusicURIDatabase db = new MusicURIDatabase(databasePath, databaseFileName); 53 | 54 | public static void main(String[] args) throws Exception 55 | { 56 | 57 | //***************************************************************************** 58 | //************************* F I L E I N P U T *************************** 59 | //***************************************************************************** 60 | 61 | if ((args.length == 1) && (new File (args[0]).exists())) 62 | { 63 | // get the file's canonical path 64 | File givenHandle = new File(args[0]); 65 | String queryAudioCanonicalPath = givenHandle.getCanonicalPath(); 66 | System.out.println("Input: " + queryAudioCanonicalPath); 67 | 68 | //PerformanceStatistic tempStat; 69 | SummaryStatistics lambdaSummary = SummaryStatistics.newInstance(); 70 | 71 | if (givenHandle.isDirectory()) 72 | { 73 | 74 | File[] list = givenHandle.listFiles(); 75 | if (list.length == 0) 76 | { 77 | System.out.println("Directory is empty"); 78 | return; 79 | } 80 | else 81 | { 82 | ArrayList allStats = new ArrayList(); 83 | File currentFile; 84 | for (int i = 0; i < list.length; i++) 85 | { 86 | currentFile = list[i]; 87 | try 88 | { 89 | if (Toolset.isSupportedAudioFile(currentFile)) 90 | { 91 | System.out.println("\nCalculating optimal lambda : " + currentFile.getName()); 92 | lambdaSummary.addValue(getBestLambda (new MusicURIQuery(currentFile))); 93 | } 94 | } 95 | catch (Exception e) 96 | { 97 | e.printStackTrace(); 98 | } 99 | } 100 | // System.out.println("\n\nStatistics for Test Case: " + queryAudioCanonicalPath); 101 | // mergeStatistics(allStats); 102 | } 103 | } 104 | if (givenHandle.isFile()) 105 | { 106 | if (Toolset.isSupportedAudioFile(givenHandle)) 107 | { 108 | // tempStat = getBestLambda (new MusicURIQuery(givenHandle)); 109 | // if (tempStat!=null) 110 | // { 111 | // //tempStat.printStatistics(); 112 | // ArrayList allStats = new ArrayList(); 113 | // allStats.add(tempStat); 114 | // mergeStatistics(allStats); 115 | // } 116 | // else 117 | // System.out.println("Error in identification "); 118 | } 119 | } 120 | 121 | }//end if 122 | else 123 | { 124 | System.err.println("LambdaCalculator"); 125 | System.err.println("Usage: java tester.LambdaCalculator {directory}"); 126 | } 127 | 128 | }//end main method 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | public static double getBestLambda (MusicURIQuery query) 143 | { 144 | 145 | //***************************************************************************** 146 | //************ Q U E R Y D A T A P R E P A R A T I O N **************** 147 | //***************************************************************************** 148 | 149 | // get the act object encapsulated in the MusicURIQuery object 150 | Mp7ACT queryMp7 = query.getAudioCompactType(); 151 | // if its null then there is some problem 152 | if (queryMp7 == null) 153 | System.out.println("Problem: queryMp7 is null"); 154 | // read the required data from the AudioCompactType 155 | AudioLLDmeta queryMean = queryMp7.featureByName(Mp7ACT.FLATNESS, Mp7ACT.MEAN); 156 | AudioLLDmeta queryVariance = queryMp7.featureByName(Mp7ACT.FLATNESS, Mp7ACT.VARIANCE); 157 | // are audioSignatureType data included in the act file? 158 | if (queryMean == null || queryVariance == null ) 159 | { 160 | System.out.println("Problem: AudioSignatureType is not included in ACT or cannot be extracted from audio file. Aborting."); 161 | } 162 | int vectorSize = queryMean.vectorSize; // internal! stay out! read the matrix size instead 163 | float[][] queryMeanMatrix = queryMean.__rawVectors; 164 | float[][] queryVarianceMatrix = queryVariance.__rawVectors; 165 | int QueryVectorDim = vectorSize; // ==number of dimensions, subbands 166 | String queryLabelling = query.getLabel(); 167 | int queryIdentifier = Toolset.getTestCaseIdentifier(queryLabelling); 168 | StringWrapper queryWrapper = null; 169 | JaroWinkler test = new JaroWinkler(); 170 | queryLabelling = Toolset.removeTestCaseIdentifier(queryLabelling); 171 | queryWrapper = test.prepare(queryLabelling); 172 | 173 | //***************************************************************************** 174 | //********* R E F E R E N C E D A T A P R E P A R A T I O N *********** 175 | //***************************************************************************** 176 | 177 | int RefVectorDim = 0; // number of subbands, dimensions 178 | double combinedDistance; 179 | double currentLabelDistance = 0.0; 180 | double currentSignatureDistance = 0.0; 181 | double normalizedSignatureDistance = 0.0; 182 | double confidence = 0.0; 183 | Mp7ACT mp7; 184 | String currentMD5; 185 | MusicURIReference currentReference; 186 | AudioLLDmeta refMean; 187 | AudioLLDmeta refVariance; 188 | float[][] refMeanMatrix; 189 | float[][] refVarianceMatrix; 190 | 191 | StringWrapper refWrapper = null; 192 | float editDistance; 193 | int referenceIdentifier; 194 | String referenceLabelling; 195 | 196 | double lambdaYeldingSmallestCombinedDistance = 0.0; 197 | double smallestCombinedDistanceYet = 0.0; 198 | 199 | Set allMusicURIReferenceKeys = db.getSetOfMusicURIReferences(); 200 | 201 | //System.out.println("queryId: " + queryIdentifier); 202 | 203 | for (Iterator iter = allMusicURIReferenceKeys.iterator(); iter.hasNext();) 204 | { 205 | currentMD5 = (String) iter.next(); 206 | currentReference = db.getMusicURIReference(currentMD5); 207 | referenceLabelling = currentReference.getLabel(); 208 | referenceIdentifier = Toolset.getTestCaseIdentifier(referenceLabelling); 209 | 210 | if (referenceIdentifier == queryIdentifier) 211 | { 212 | mp7 = currentReference.getAudioCompactType(); 213 | if (mp7 == null) 214 | { 215 | System.out.println("Problem: No mpeg7 exists for given uri"); 216 | } 217 | refMean = mp7.featureByName(Mp7ACT.FLATNESS, Mp7ACT.MEAN); 218 | refVariance = mp7.featureByName(Mp7ACT.FLATNESS, Mp7ACT.VARIANCE); 219 | if ((refMean == null) || (refVariance == null)) 220 | { 221 | System.out.println("Skipping: problematic mpeg7 description!!! - "+mp7.getLabel()+")"); 222 | } 223 | refMeanMatrix = refMean.__rawVectors; 224 | refVarianceMatrix = refVariance.__rawVectors; 225 | RefVectorDim = vectorSize; // number of subbands 226 | 227 | currentSignatureDistance = Toolset.getEuclidianDistance(refMeanMatrix, refVarianceMatrix, queryMeanMatrix, queryVarianceMatrix, QueryVectorDim, false); 228 | double theoreticalMaximum = (RefVectorDim * Math.sqrt(1)) * queryMeanMatrix.length; 229 | normalizedSignatureDistance = currentSignatureDistance / theoreticalMaximum; //eg (16 * sqrootof(1) ) * 10 --to scale at 0-1 230 | 231 | String refname = currentReference.getLabel(); 232 | refname = Toolset.removeTestCaseIdentifier(refname); 233 | refWrapper = test.prepare(refname); 234 | editDistance = 1 - (float) test.score(queryWrapper, refWrapper); 235 | currentLabelDistance = editDistance; 236 | 237 | System.out.println("currentLabelDistance: " + currentLabelDistance); 238 | System.out.println("normalizedSignatureDistance: " + normalizedSignatureDistance); 239 | 240 | //combinedDistance = (0.5 * currentLabelDistance) + (0.5 * normalizedSignatureDistance); 241 | //smallestCombinedDistanceYet = (0.5 * currentLabelDistance) + (0.5 * normalizedSignatureDistance); 242 | for (double lambda = 0.0; lambda < 1.0; lambda += 0.01) 243 | { 244 | combinedDistance = lambda * currentLabelDistance + (1-lambda) * normalizedSignatureDistance; 245 | if (combinedDistance < smallestCombinedDistanceYet) 246 | { 247 | smallestCombinedDistanceYet = combinedDistance; 248 | lambdaYeldingSmallestCombinedDistance = lambda; 249 | } 250 | } 251 | System.out.println("smallestCombinedDistanceYet: " + smallestCombinedDistanceYet); 252 | System.out.println("Best lambda: " + lambdaYeldingSmallestCombinedDistance); 253 | confidence = 100 - (100 * smallestCombinedDistanceYet); 254 | System.out.println("Best confidence: " + confidence); 255 | } 256 | } 257 | return lambdaYeldingSmallestCombinedDistance; 258 | } 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | public static void mergeStatistics(ArrayList allStats) 270 | { 271 | PerformanceStatistic tempStat; 272 | 273 | int truePositives = 0; 274 | int falsePositives = 0; 275 | int trueNegatives = 0; 276 | int falseNegatives = 0; 277 | 278 | SummaryStatistics TPBestMatchSummary = SummaryStatistics.newInstance(); 279 | SummaryStatistics TPSecondBestSummary = SummaryStatistics.newInstance(); 280 | 281 | SummaryStatistics FPBestMatchSummary = SummaryStatistics.newInstance(); 282 | 283 | SummaryStatistics BothTP_FPBestMatchSummary = SummaryStatistics.newInstance(); 284 | 285 | SummaryStatistics TNSummary = SummaryStatistics.newInstance(); 286 | SummaryStatistics FNSummary = SummaryStatistics.newInstance(); 287 | 288 | SummaryStatistics pruningSpeedSummary = SummaryStatistics.newInstance(); 289 | SummaryStatistics matchingSpeedSummary = SummaryStatistics.newInstance(); 290 | SummaryStatistics totalSpeedSummary = SummaryStatistics.newInstance(); 291 | 292 | 293 | for (int i = 0; i < allStats.size(); i++) 294 | { 295 | tempStat = (PerformanceStatistic) allStats.get(i); 296 | 297 | if (tempStat.isTruePositive()) truePositives++; 298 | if (tempStat.isFalsePositive()) falsePositives++; 299 | if (tempStat.isTrueNegative()) trueNegatives++; 300 | if (tempStat.isFalseNegative()) falseNegatives++; 301 | 302 | // accurate results only 303 | //if (tempStat.isTruePositive() || tempStat.isTrueNegative()) 304 | 305 | pruningSpeedSummary.addValue(tempStat.getPruningTime()); 306 | matchingSpeedSummary.addValue(tempStat.getMatchingTime()); 307 | totalSpeedSummary.addValue(tempStat.getPruningTime() + tempStat.getMatchingTime()); 308 | 309 | if (tempStat.isTruePositive()) 310 | { 311 | TPBestMatchSummary.addValue(tempStat.getBestMatchDistance()); 312 | TPSecondBestSummary.addValue(tempStat.getSecondBestMatchDistance()); 313 | } 314 | 315 | if (tempStat.isFalsePositive()) 316 | { 317 | FPBestMatchSummary.addValue(tempStat.getBestMatchDistance()); 318 | } 319 | 320 | BothTP_FPBestMatchSummary.addValue(tempStat.getBestMatchDistance()); 321 | 322 | } 323 | 324 | System.out.println("---------------------------------------------------------"); 325 | 326 | System.out.println("\nTrue Positives : " + truePositives + "/" + allStats.size()); 327 | System.out.println("False Positives : " + falsePositives + "/" + allStats.size()); 328 | System.out.println("True Negatives : " + trueNegatives + "/" + allStats.size()); 329 | System.out.println("False Negatives : " + falseNegatives + "/" + allStats.size()); 330 | 331 | System.out.println("\nTrue Positive Best Match Statistics"); 332 | System.out.println("Distance Min : " + TPBestMatchSummary.getMin()); 333 | System.out.println("Distance Max : " + TPBestMatchSummary.getMax()); 334 | System.out.println("Distance Mean : " + TPBestMatchSummary.getMean()); 335 | System.out.println("Distance Variance : " + TPBestMatchSummary.getVariance()); 336 | System.out.println("Distance StdDev : " + TPBestMatchSummary.getStandardDeviation()); 337 | System.out.println("Confidence Mean : " + (100 - (100 * (TPBestMatchSummary.getMean())))+ " %"); 338 | 339 | System.out.println("\nTrue Positive Second Best Statistics"); 340 | System.out.println("Distance Min : " + TPSecondBestSummary.getMin()); 341 | System.out.println("Distance Max : " + TPSecondBestSummary.getMax()); 342 | System.out.println("Distance Mean : " + TPSecondBestSummary.getMean()); 343 | System.out.println("Confidence Mean : " + (100 - (100 * (TPSecondBestSummary.getMean())))+ " %"); 344 | 345 | System.out.println("\nFalse Positive Best Match Statistics"); 346 | System.out.println("Distance Min : " + FPBestMatchSummary.getMin()); 347 | System.out.println("Distance Max : " + FPBestMatchSummary.getMax()); 348 | System.out.println("Distance Mean : " + FPBestMatchSummary.getMean()); 349 | System.out.println("Distance Variance : " + FPBestMatchSummary.getVariance()); 350 | System.out.println("Distance StdDev : " + FPBestMatchSummary.getStandardDeviation()); 351 | System.out.println("Confidence Mean : " + (100 - (100 * (FPBestMatchSummary.getMean()))) + " %"); 352 | 353 | System.out.println("\nBest Match Statistics (Regardless being False or True Positive) "); 354 | System.out.println("Distance Min : " + BothTP_FPBestMatchSummary.getMin()); 355 | System.out.println("Distance Max : " + BothTP_FPBestMatchSummary.getMax()); 356 | System.out.println("Distance Mean : " + BothTP_FPBestMatchSummary.getMean()); 357 | System.out.println("Distance Variance : " + BothTP_FPBestMatchSummary.getVariance()); 358 | System.out.println("Distance StdDev : " + BothTP_FPBestMatchSummary.getStandardDeviation()); 359 | System.out.println("Confidence Mean : " + (100 - (100 * (BothTP_FPBestMatchSummary.getMean()))) + " %"); 360 | 361 | System.out.println("\n\nPruning Speed Statistics"); 362 | System.out.println("Speed Min : " + (pruningSpeedSummary.getMin()/1000) + " sec" ); 363 | System.out.println("Speed Max : " + (pruningSpeedSummary.getMax()/1000) + " sec" ); 364 | System.out.println("Speed Mean : " + (pruningSpeedSummary.getMean()/1000) + " sec" ); 365 | 366 | System.out.println("\nMatching Speed Statistics"); 367 | System.out.println("Speed Min : " + (matchingSpeedSummary.getMin()/1000) + " sec" ); 368 | System.out.println("Speed Max : " + (matchingSpeedSummary.getMax()/1000) + " sec" ); 369 | System.out.println("Speed Mean : " + (matchingSpeedSummary.getMean()/1000) + " sec" ); 370 | 371 | System.out.println("\nOverall Speed Statistics"); 372 | System.out.println("Speed Min : " + (totalSpeedSummary.getMin()/1000) + " sec" ); 373 | System.out.println("Speed Max : " + (totalSpeedSummary.getMax()/1000) + " sec" ); 374 | System.out.println("Speed Mean : " + (totalSpeedSummary.getMean()/1000) + " sec" ); 375 | 376 | 377 | } 378 | 379 | } -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/utils/experimental/FilenameScrambler.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2005, Dimitrios Kourtesis 3 | 4 | This file is part of MusicURI. 5 | 6 | MusicURI is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | MusicURI is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with MPEG7AudioEnc; see the file COPYING. If not, write to 18 | the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 19 | MA 02111-1307 USA 20 | */ 21 | 22 | package it.univpm.deit.semedia.musicuri.utils.experimental; 23 | 24 | import it.univpm.deit.semedia.musicuri.core.Toolset; 25 | 26 | import java.io.File; 27 | import java.util.ArrayList; 28 | import java.util.Random; 29 | import java.util.StringTokenizer; 30 | 31 | 32 | /** 33 | * Utility class used for scrambling the filenames of audio files in order to generate new test cases. 34 | * The srambling is done either using sentences generated by context-free grammars, or by inserting 35 | * random words and random character flips. This code was initially used to test the robustness 36 | * of various approximate string matching algorithms. 37 | */ 38 | public class FilenameScrambler 39 | { 40 | // list of words to ignore 41 | private static ArrayList ignored = new ArrayList(); 42 | 43 | // 100 non-existing band names, created using a context free grammar 44 | // taken from http://www.elsewhere.org/cgi-bin/bandname 45 | private static String[] ContextFreeGrammarBandNames = 46 | { "Order Of The Old Time Tree", "The Universal Ladies", "Four Creeks With Colors", 47 | "The Salamander Gambit", "Bob Stardust and the Telluride Buckaroos", "Still Clown", 48 | "Hammerbreeder", "The Venomous Badgers", "Donna Piro and the Jerusalem Police", 49 | "Stack of Creeks", "Large Dog", "The Famous Box Society", "Bob Lovlace and the Smokable Whiskey Session", 50 | "A Taste of Lakes", "Badgerbeagle", "Box of Wookiees", "Five Chains and Omega", 51 | "Six Good Ducks", "Frogbreeder", "The Moon Company", "The Metaphysical Alpha Session", 52 | "Donna Claypool and the Detroit Anteaters", "A Taste of Puppies", "A Sack of Guys", 53 | "The Ravenous Devil Headquarters", "The Venomous Flower Scheme", "Four Fellows and a Mouse", 54 | "Grace Badabing and the Venomous Motor Symphony", "Pink Color", "A Tower of Creeks", 55 | "Kamikaze Cholera", "Adam Banzai and the Screaming Carpenters", "Handful of Sounds", 56 | "Bumblebeewater", "Peter Tarantino and the Montgomery Daleks", "House of Fears", 57 | "Purityduck", "Box of Wookiees", "Screaming Bishop", "Four Ladies and a Thumb", 58 | "Crystal Cow", "The Flying Grrrl Trio", "Three Rasta Horses", "Peter Stallone and the Cleveland Crickets", 59 | "Buddy Johnson and the Still Oddities", "A Handful of Colors", "The Honey Group", 60 | "The Confederate River Symphony", "Bag of Ducks", "Leather Cat", "The Flying Temple Combo", 61 | "Metaphysical Milk", "The Amazing Delta Brotherhood", "Buckaroo Lovlace and the Large Juggler Gambit", 62 | "Box of Goats", "Four Womyn and a Axe", "Old Time Fear", "A Handful of Mice", "Puppyfennel", 63 | "Britney Summers and the Messiest Patrol", "Grace Stallone and the San Francisco All Stars", 64 | "Wall of Heads", "The Thick Star Factor", "Temple of Badgers", "Templebumblebee", "The Ganja Quintet", 65 | "Britney LaZonga and the Kamikaze Boingers", "Hamsterpurity", "A Stack of Oysters", 66 | "Buck Cooper and the Rasta Oddities", "Modern Hog", "A Tower of Anvils", 67 | "Buck and the Stellar Replicants", "The Garden Brotherhood", "Mothergun", "Starving Duck", 68 | "The Live Delta Incident", "Two Womyn and a Synth", "Taste of Horses", "A House of Hogs", 69 | "Linda Cornell and the Blindfolded Angels", "Les Claypool and the Heavenly All Stars", 70 | "Sylvester and the Stellar Leisurelies", "Six Clowns and a Woman", "The Liquid Gamma Company", 71 | "Temple of Ladies", "The Snout Conspiracy", "A Fistful of Beagles", "A Fistful of Fish", 72 | "Five Candles With Guns", "The Swollen Beagles", "Grace Turgidson and the Kamikaze Fulcrum Symphony", 73 | "Fabulous War", "The Live Ladies", "Two Venomous Sheep", "The Red Beagle Shrine", "A Temple of Heads", 74 | "The Abundant Badger Sound", "The Anvil Policy", "Quentin Phillips and the Seattle Plumbers" }; 75 | 76 | // 123 words extracted from George Orwell's "1984" 77 | // taken from http://www.vocabulary.com/VUctnineteen.html 78 | private static String[] GeorgeOrwell1984 = 79 | { 80 | "depict", "simultaneously", "predicament", "interminable", "unorthodox", "renegade", "polysyllabic", 81 | "refute", "flog", "inscrutable", "discountenanced", "gamboling", "saboteur", "raspingly", 82 | "reverberate", "reproach", "fathom", "disdain", "annihilate", "repudiate", "shrewish", "orifice", 83 | "collate", "multifarious", "kaleidoscope", "denounce", "implicate", "hoard", "remorselessly", 84 | "venerate", "heretic", "catapult", "irrepressible", "proliferate", "debauchery", "promiscuity", 85 | "aquiline", "jostle", "flog", "listless", "incriminate", "posterity", "stratum", "balminess", 86 | "sordid", "altercation", "meditatively", "innumerable", "cumbersome", "officiousness", "unprocurable", 87 | "niggling", "hallucination", "malignant", "guise", "dapple", "swine", "strenuousness", "demeanor", 88 | "stagnant", "commodity", "chastity", "inconceivable", "eccentricity", "unendurable", "effigies", 89 | "rowdy", "indignation", "perish", "mutability", "invariably", "queue", "intermittent", "luminous", 90 | "scrounge", "pathos", "remonstrance", "proles", "intimidate", "wainscoting", "salutation", "allusion", 91 | "fretted", "voluptuous", "reprisal", "fecundity", "dilapidated", "ravage", "austere", "spurious", 92 | "preponderance", "tacitly", "ruminant", "plunder", "irrevocable", "irreconcilable", "recurrence", 93 | "hierarchy", "infallible", "oligarchical", "scrutinize", "dissipate", "repression", "supple", 94 | "reverence", "gnawing", "peddler", "timorously", "irony", "sabotage", "truncheon", "embezzlement", 95 | "inquisitor", "despicable", "bludgeon", "forlorn", "degradation", "taut", "improvisation", 96 | "interpose", "haggling", "digression", "tiddlywinks" 97 | }; 98 | 99 | 100 | public static void main(String[] args) throws Exception 101 | { 102 | 103 | //***************************************************************************** 104 | //************************* F I L E I N P U T *************************** 105 | //***************************************************************************** 106 | 107 | if ((args.length == 1) && (new File (args[0]).exists())) 108 | { 109 | // get the file's canonical path 110 | File givenHandle = new File(args[0]); 111 | String queryAudioCanonicalPath = givenHandle.getCanonicalPath(); 112 | System.out.println("Input: " + queryAudioCanonicalPath); 113 | 114 | 115 | if (givenHandle.isDirectory()) 116 | { 117 | File[] list = givenHandle.listFiles(); 118 | if (list.length == 0) 119 | { 120 | System.out.println("Directory is empty"); 121 | return; 122 | } 123 | else 124 | { 125 | File currentFile; 126 | for (int i = 0; i < list.length; i++) 127 | { 128 | currentFile = list[i]; 129 | if (Toolset.isSupportedAudioFile(currentFile)) 130 | { 131 | String oldFilename = currentFile.getName(); 132 | String newFilename = generateSubstitute(oldFilename); 133 | //String newFilename = generateBogusBandNameSubstitute(oldFilename, i); 134 | System.out.println("From : " + oldFilename); 135 | System.out.println("To : " + newFilename); 136 | String parent = currentFile.getParent(); 137 | doRename(parent+"\\"+oldFilename, parent+"\\"+newFilename); 138 | } 139 | 140 | } 141 | } 142 | } 143 | 144 | if (givenHandle.isFile()) 145 | { 146 | if (Toolset.isSupportedAudioFile(givenHandle)) 147 | { 148 | String oldFilename = givenHandle.getName(); 149 | String newFilename = generateSubstitute(oldFilename); 150 | //String newFilename = generateBogusBandNameSubstitute(oldFilename, 0); 151 | System.out.println("From : " + oldFilename); 152 | System.out.println("To : " + newFilename); 153 | String parent = givenHandle.getParent(); 154 | doRename(parent+"\\"+oldFilename, parent+"\\"+newFilename); 155 | } 156 | } 157 | 158 | }//end if 159 | 160 | 161 | else 162 | { 163 | System.err.println("FilenameScrambler"); 164 | System.err.println("Usage: java tester.FilenameScrambler {original.mp3}"); 165 | } 166 | 167 | }//end main method 168 | 169 | 170 | public static String generateBogusBandNameSubstitute(String oldFilename, int index) 171 | { 172 | String band = ContextFreeGrammarBandNames[index]; 173 | String newFilename = ""; 174 | 175 | StringTokenizer chop = new StringTokenizer(oldFilename,"-"); 176 | //System.out.println("num of tokens : " + chop.countTokens()); 177 | 178 | int testCaseId = Toolset.getTestCaseIdentifier(oldFilename); 179 | String idPrePadding = ""; 180 | if (testCaseId >= 1 ) 181 | { 182 | if (testCaseId <10 )idPrePadding = "000"; 183 | if (testCaseId >=10 && testCaseId < 100 )idPrePadding = "00"; 184 | if (testCaseId >=100 && testCaseId < 1000 )idPrePadding = "0"; 185 | } 186 | 187 | int i = 0; 188 | String token; 189 | int numOfToks = chop.countTokens(); 190 | while (chop.hasMoreTokens()) 191 | { 192 | token = chop.nextToken(); 193 | //System.out.println(i + " token : " + token); 194 | if ( i == numOfToks-1 ) 195 | { 196 | //System.out.println(i + "/ newFilename: " + newFilename); 197 | newFilename = newFilename.concat(idPrePadding + testCaseId + " " + band + " -" + token); 198 | //System.out.println(i + "/ newFilename: " + newFilename); 199 | } 200 | i++; 201 | } 202 | 203 | 204 | return newFilename; 205 | } 206 | 207 | 208 | public static void doRename (String oldname, String newname) 209 | { 210 | File file = new File(oldname); 211 | File file2 = new File(newname); 212 | 213 | // Rename file (or directory) 214 | boolean success = file.renameTo(file2); 215 | if (!success) 216 | { 217 | if (!file.exists()) System.out.println("File does not exist"); 218 | if (!file.canWrite()) System.out.println("No write access"); 219 | System.out.println("File could not be renamed"); 220 | } 221 | } 222 | 223 | 224 | public static String generateSubstitute(String oldFilename) 225 | { 226 | // The 50 most common words in the english language 227 | // http://esl.about.com/library/vocabulary/bl1000_list1.htm 228 | // http://www.world-english.org/english500.htm 229 | // http://www.duboislc.org/EducationWatch/First100Words.html 230 | 231 | ignored.add("the"); ignored.add("of"); ignored.add("and"); 232 | ignored.add("a"); ignored.add("to"); ignored.add("in"); 233 | ignored.add("is"); ignored.add("you"); ignored.add("that"); 234 | ignored.add("it"); ignored.add("he"); ignored.add("was"); 235 | ignored.add("for"); ignored.add("on"); ignored.add("are"); 236 | ignored.add("as"); ignored.add("with"); ignored.add("his"); 237 | ignored.add("they"); ignored.add("i"); ignored.add("at"); 238 | ignored.add("be"); ignored.add("this"); ignored.add("have"); 239 | ignored.add("from"); ignored.add("or"); ignored.add("one"); 240 | ignored.add("had"); ignored.add("by"); ignored.add("word"); 241 | ignored.add("but"); ignored.add("not"); ignored.add("what"); 242 | ignored.add("all"); ignored.add("were"); ignored.add("we"); 243 | ignored.add("when"); ignored.add("your"); ignored.add("can"); 244 | ignored.add("said"); ignored.add("there"); ignored.add("use"); 245 | ignored.add("an"); ignored.add("each"); ignored.add("which"); 246 | ignored.add("she"); ignored.add("do"); ignored.add("how"); 247 | ignored.add("their"); ignored.add("if"); 248 | 249 | // Some frequently occuring words related to music filenames 250 | ignored.add("mp3"); ignored.add("&"); ignored.add("featuring"); 251 | ignored.add("+"); ignored.add("feat"); ignored.add("presenting"); 252 | ignored.add("pres"); ignored.add("live"); ignored.add("track"); 253 | ignored.add("album"); ignored.add("various"); ignored.add("artists"); 254 | ignored.add("artist"); ignored.add("va"); ignored.add("collection"); 255 | ignored.add("sampler"); ignored.add("mix"); ignored.add("complilation"); 256 | ignored.add("mixed"); ignored.add("remix"); ignored.add("remixed"); 257 | ignored.add("lp"); ignored.add("ep"); ignored.add("cd"); 258 | ignored.add(""); 259 | 260 | String identifier = ""; 261 | int testCaseId = Toolset.getTestCaseIdentifier(oldFilename); 262 | if (testCaseId >= 1 ) 263 | { 264 | if (testCaseId >=0 && testCaseId <10 )identifier = "000" + testCaseId + " "; 265 | if (testCaseId >=10 && testCaseId < 100 )identifier = "00" + testCaseId + " "; 266 | if (testCaseId >=100 && testCaseId < 1000 )identifier = "0" + testCaseId + " "; 267 | } 268 | String oldFilenameWithoutIdentifier = Toolset.removeTestCaseIdentifier(oldFilename); 269 | String extension = oldFilenameWithoutIdentifier.substring(oldFilenameWithoutIdentifier.lastIndexOf('.') + 1); 270 | String noId_noExtension = oldFilenameWithoutIdentifier.substring(0, oldFilenameWithoutIdentifier.lastIndexOf('.')); 271 | oldFilenameWithoutIdentifier.replaceAll(".mp3",""); 272 | String scrambledTokenFilename = ""; 273 | String whitespaceFreeFilename = ""; 274 | String finalFilename = ""; 275 | 276 | StringTokenizer tok = new StringTokenizer(noId_noExtension," `~!@#$%^&*()_-+={}[]|\\:;\"'<>,.?/\t\n\r"); 277 | 278 | int numOfTokensInString = tok.countTokens(); 279 | String[] tokens = new String[numOfTokensInString]; // list of tokens to return 280 | int i = 0; 281 | 282 | while (tok.hasMoreTokens()) 283 | { 284 | String token = tok.nextToken(); 285 | tokens[i] = token; 286 | i++; 287 | } 288 | 289 | boolean okToScramble = false; 290 | String selectedToken = ""; 291 | int randomInteger = 0; 292 | Random rand = null; 293 | 294 | while (!okToScramble) 295 | { 296 | rand = new Random(); 297 | // Random integer from from 0 to numOfTokensInString 298 | randomInteger = rand.nextInt(numOfTokensInString); 299 | selectedToken = tokens[randomInteger]; 300 | if (!ignored.contains(selectedToken) //not a common english word 301 | && !isInteger(selectedToken) //not an integer 302 | //&& selectedToken.length() > 2 303 | ) //not a small word 304 | okToScramble = true; 305 | } 306 | okToScramble = false; 307 | int excludedAlreadyScrambledTokenNumber = randomInteger; //exclude this token from further mangling 308 | String scrambledToken = insertRandomAsciiFlip (selectedToken, 2); 309 | scrambledTokenFilename = noId_noExtension.replaceFirst(selectedToken, scrambledToken); 310 | 311 | while (!okToScramble) 312 | { 313 | rand = new Random(); 314 | // Random integer from from 0 to numOfTokensInString 315 | randomInteger = rand.nextInt(numOfTokensInString); 316 | selectedToken = tokens[randomInteger]; 317 | if (!ignored.contains(selectedToken) //not a common english word 318 | && !isInteger(selectedToken) //not an integer 319 | //&& selectedToken.length() > 2 //not a small word 320 | && randomInteger != excludedAlreadyScrambledTokenNumber) //not already scrambled 321 | okToScramble = true; 322 | } 323 | scrambledToken = insertRandomAsciiFlip (selectedToken, 2); 324 | scrambledTokenFilename = scrambledTokenFilename.replaceFirst(selectedToken, scrambledToken); 325 | 326 | rand = new Random(); 327 | randomInteger = rand.nextInt(122); // Random integer from from 0 to 125 328 | String appendedNonSenseFilename = scrambledTokenFilename.concat("#" + randomInteger +" - " + GeorgeOrwell1984[randomInteger]); 329 | 330 | finalFilename = whitespaceFreeFilename.concat(identifier + removeSpaces(appendedNonSenseFilename) + "." + extension); 331 | return finalFilename; 332 | } 333 | 334 | 335 | // [JDK1.4] http://www.rgagnon.com/javadetails/java-0352.html 336 | public static String removeSpaces(String whitespacesIncluded) 337 | { 338 | StringTokenizer st = new StringTokenizer(whitespacesIncluded, " ", false); 339 | String whitespaceFree = ""; 340 | while (st.hasMoreElements()) whitespaceFree += st.nextElement(); 341 | return whitespaceFree; 342 | } 343 | 344 | 345 | public static String insertRandomAsciiFlip (String original, int numberOfFlips) 346 | { 347 | //System.out.println("Modified token : " + original); 348 | Random rand = new Random(); 349 | Random rand2 = new Random(); 350 | int randomInteger; 351 | int randomInteger2; 352 | char[] scrambledCharArray = original.toCharArray(); 353 | 354 | for (int i = 0; i < numberOfFlips; i++) 355 | { 356 | randomInteger = rand.nextInt(original.length()); //random position 357 | randomInteger2 = 65 + rand2.nextInt(25); //result will be an integer ranging 65-90 (capital ascii characters) 358 | scrambledCharArray[randomInteger] = (char)randomInteger2; 359 | } 360 | 361 | String ret = new String(scrambledCharArray); 362 | return ret; 363 | } 364 | 365 | 366 | public static String replace(String str, String oldToken, String newToken) 367 | { 368 | //System.out.println("str: " + str); 369 | int s = 0; 370 | int e = 0; 371 | StringBuffer result = new StringBuffer(); 372 | 373 | while ((e = str.indexOf(oldToken, s)) >= 0) 374 | { 375 | result.append(str.substring(s, e)); 376 | result.append(newToken); 377 | s = e + oldToken.length(); 378 | } 379 | result.append(str.substring(s)); 380 | 381 | String tmp = result.toString(); 382 | //System.out.println("str: " + tmp); 383 | return tmp; 384 | } 385 | 386 | 387 | public static boolean isInteger(String token) 388 | { 389 | try 390 | { 391 | Integer.parseInt(token); 392 | return true; 393 | } 394 | catch (NumberFormatException e) 395 | { 396 | // it wasn't 397 | return false; 398 | } 399 | } 400 | 401 | } 402 | -------------------------------------------------------------------------------- /src/COPYING.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | <one line to give the program's name and a brief idea of what it does.> 294 | Copyright (C) <year> <name of author> 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 309 | 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) year name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | <signature of Ty Coon>, 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Library General 340 | Public License instead of this License. 341 | -------------------------------------------------------------------------------- /src/it/univpm/deit/semedia/musicuri/utils/misc/MusicURILibraryDemo.java: -------------------------------------------------------------------------------- 1 | package it.univpm.deit.semedia.musicuri.utils.misc; 2 | 3 | import it.univpm.deit.semedia.musicuri.core.MusicURIDatabase; 4 | import it.univpm.deit.semedia.musicuri.core.MusicURIQuery; 5 | import it.univpm.deit.semedia.musicuri.core.MusicURIReference; 6 | import it.univpm.deit.semedia.musicuri.core.MusicURISearch; 7 | import it.univpm.deit.semedia.musicuri.core.Result; 8 | import it.univpm.deit.semedia.musicuri.core.ResultRankingList; 9 | import it.univpm.deit.semedia.musicuri.core.Toolset; 10 | import it.univpm.deit.semedia.musicuri.webservice.client.MusicURIWebSearchServiceLocator; 11 | import it.univpm.deit.semedia.musicuri.webservice.client.MusicURIWebSearchSoapBindingStub; 12 | 13 | import java.io.File; 14 | import java.net.URL; 15 | import java.net.HttpURLConnection; 16 | import java.net.MalformedURLException; 17 | 18 | import jargs.gnu.CmdLineParser; 19 | 20 | /** 21 | * @author Dimitrios Kourtesis 22 | */ 23 | public class MusicURILibraryDemo 24 | { 25 | 26 | 27 | /** 28 | * 29 | * This application intends to practically demonstrate the basic 30 | * funcionality that MusicURI offers, which is to enable the mapping between 31 | * a piece of music and a unique URI. 32 | * 33 | * The demo application currently offers the following operations: 34 | * 35 | * a) Query a MusicURI local database with a music item, and retrieve a URI 36 | * b) Add a reference music item to a local MusicURI database 37 | * c) List all reference music items inside a local MusicURI database 38 | * 39 | * The main method in this class enables a user to: 40 | * 41 | * a) Query the local MusicURI database file at the specified path, with the 42 | * given audio file, to retrieve a URI. The -q switch is accompanied by the 43 | * path to the local database, and the -f flag (optional) signals if the 44 | * filename should be utilized as a reliable hint within search. Format: 45 | * java -jar MusicURI.jar [<audiofile>] [<-q> <DBfile>] [<-f>] example: 46 | * "c:\test.wav" -q "C:\WINDOWS\system32\MusicURIReferences.db" -f 47 | * 48 | * b) Add, to the local MusicURI database file at the specified path, the 49 | * given audio file. The -a switch is accompanied by the path to the local 50 | * database, into which the music item will be indexed. Format: java -jar 51 | * MusicURI.jar [<audiofile>] [<-a> <DBfile>] example: "c:\test.wav" -a 52 | * "C:\WINDOWS\system32\MusicURIReferences.db" 53 | * 54 | * c) List the URIs of all music items indexed in the local MusicURI 55 | * database file, at the specified path. Format: java -jar MusicURI.jar [<-l> 56 | * <databasefile>] Example: -l "C:\WINDOWS\system32\MusicURIReferences.db" 57 | * 58 | * Before proceeding with any of the aforementioned operations, the 59 | * application verifies that any files that have been specified exist, and 60 | * are valid. 61 | * 62 | * For query operations, the user has to specify Where, What and How to 63 | * identify. I.e. the user must specify the URL where the MusicURI data 64 | * source resides, the audio file containing the unknown piece of music, and 65 | * whether the system should utilize the provided filename as a reliable 66 | * hint within the search, or not (default is false). 67 | * 68 | * The filename should be taken into consideration only if the user is 69 | * absolutely confident that it does not contain any misleading information 70 | * about the artist and title of the respective piece of music. For example, 71 | * this option could be safely used for a filename of the form <ARTIST> 72 | * <SEPARATOR> <TITLE>.<EXTENSION> 73 | * 74 | * Where: The URL specifying the location of the MusicURI data source 75 | * What : The audio file containing the piece of music to use as a query 76 | * How : A flag determining whether to utilize the filename in search 77 | */ 78 | 79 | 80 | static MusicURIWebSearchSoapBindingStub stub; 81 | 82 | public static void main(String[] args) 83 | { 84 | if (args.length == 0) 85 | printUsage(); 86 | else 87 | { 88 | /****************** ARGUMENT SETTING **************/ 89 | // A command line parser to handle all options and arguments. 90 | CmdLineParser parser = new CmdLineParser(); 91 | 92 | // The -f option is a flag determining whether to use or not use the filename 93 | // within the search. No value follows, the flag is either present, or not. 94 | CmdLineParser.Option usefilename = parser.addBooleanOption('f', "usefilename"); 95 | 96 | // The -q option is followed by a String value specifying the path 97 | // of the database file to be queried. 98 | CmdLineParser.Option queryOption = parser.addStringOption('q', "query"); 99 | 100 | // The -a switch is followed by a String value specifying the path to the 101 | // local database, into which a given audio file will be indexed. 102 | CmdLineParser.Option addReferenceOption = parser.addStringOption('a', "addReference"); 103 | 104 | // The -l switch is followed by a String value specifying the path to the 105 | // local database, the contents of which will be listed. 106 | CmdLineParser.Option listReferencesOption = parser.addStringOption('l', "listReferences"); 107 | 108 | 109 | 110 | /****************** ARGUMENT PARSING **************/ 111 | 112 | // Parse the user-provided command line arguments, and catch any errors 113 | try 114 | { 115 | parser.parse(args); 116 | } 117 | catch (CmdLineParser.OptionException e) 118 | { 119 | System.err.println(e.getMessage()); 120 | printUsage(); 121 | System.exit(1); 122 | } 123 | 124 | 125 | 126 | // The location of the MusicURI data source defaults to the loopback address. 127 | //String queryValue = (String) parser.getOptionValue(queryWS, "http://localhost:8080/axis/MusicURIWebSearch.jws?wsdl"); 128 | 129 | String queryValue = (String) parser.getOptionValue(queryOption); 130 | String addReferenceValue = (String) parser.getOptionValue(addReferenceOption); 131 | String listReferencesValue = (String) parser.getOptionValue(listReferencesOption); 132 | 133 | 134 | 135 | 136 | /****************** PERFORM OPERATION **************/ 137 | String audiofileValue = null; 138 | 139 | // At any time only one option value should be selected, and therefore be non-null, 140 | // while the rest must be null. If any two option values are found to be non-null, 141 | // at the same time, print usage and abort. 142 | if ( ((queryValue != null) && (addReferenceValue != null)) || 143 | ((queryValue != null) && (listReferencesValue != null)) || 144 | ((addReferenceValue != null) && (listReferencesValue != null)) ) 145 | { 146 | printUsage(); 147 | System.exit(1); 148 | } 149 | else 150 | { 151 | /****************** QUERY OPERATION **************/ 152 | // The requested operation was a query to a Web Service or local database file 153 | if (queryValue != null) 154 | { 155 | // The flag determining whether to use the filename within search, defaults to false. 156 | Boolean usefilenameValue = (Boolean) parser.getOptionValue(usefilename, Boolean.FALSE); 157 | 158 | // There should remain only one free argument (not preceeded by a switch); 159 | // the one specifying the filename of the audio file. 160 | if (parser.getRemainingArgs().length == 1) 161 | { 162 | audiofileValue = parser.getRemainingArgs()[0]; 163 | } 164 | if (!isValidAudioFile(audiofileValue)) 165 | { 166 | printUsage(); 167 | System.exit(1); 168 | } 169 | 170 | boolean done = false; 171 | String musicURIDataSource = queryValue; 172 | 173 | // if the given MusicURI data source is a valid web service URL, query it. 174 | if (isValidWebServiceURL(musicURIDataSource)) 175 | { 176 | // Set the done flag, to signal that the MusicURI data source 177 | // has been identified as a Web Service 178 | done = true; 179 | try 180 | { 181 | queryWS(new URL(musicURIDataSource), new File(audiofileValue), usefilenameValue); 182 | } 183 | catch (MalformedURLException e) 184 | { 185 | //impossible to reach here, the URL has already been checked 186 | } 187 | } 188 | 189 | // if the given MusicURI data source is a valid local database file, query it. 190 | if (!done && isValidDatabaseFile(musicURIDataSource)) 191 | { 192 | // Set the done flag, to signal that the MusicURI data source 193 | // has been identified as a local database file 194 | done = true; 195 | queryDB(new File (musicURIDataSource), new File(audiofileValue), usefilenameValue); 196 | } 197 | // if the given MusicURI data source is non of the above, abort. 198 | if (!done) 199 | { 200 | printUsage(); 201 | System.exit(1); 202 | } 203 | } 204 | 205 | /****************** ADDITION OPERATION **************/ 206 | // The requested operation was a MusicURI reference addition to a 207 | // Web Service or local database file 208 | if (addReferenceValue != null) 209 | { 210 | // There should remain only one free argument (not preceded by a switch); 211 | // the one specifying the filename of the audio file. 212 | if (parser.getRemainingArgs().length == 1) 213 | { 214 | audiofileValue = parser.getRemainingArgs()[0]; 215 | } 216 | 217 | if (!isValidAudioFile(audiofileValue)) 218 | { 219 | printUsage(); 220 | System.exit(1); 221 | } 222 | 223 | boolean done = false; 224 | String musicURIDataSource = addReferenceValue; 225 | 226 | // if the given MusicURI data source is a valid web service URL, query it. 227 | if (isValidWebServiceURL(musicURIDataSource)) 228 | { 229 | // Set the done flag, to signal that the MusicURI data source 230 | // has been identified as a Web Service 231 | done = true; 232 | try 233 | { 234 | addReferenceToWS(new URL(musicURIDataSource), new File(audiofileValue)); 235 | } 236 | catch (MalformedURLException e) 237 | { 238 | //impossible to reach here, the URL has already been checked 239 | } 240 | } 241 | 242 | 243 | // if the given MusicURI data source is a valid local database file, query it. 244 | if (!done && isValidDatabaseFile(musicURIDataSource)) 245 | { 246 | // Set the done flag, to signal that the MusicURI data source 247 | // has been identified as a local database file 248 | done = true; 249 | addReferenceToDB(new File (musicURIDataSource), new File(audiofileValue)); 250 | } 251 | // if the given MusicURI data source is non of the above, abort. 252 | if (!done) 253 | { 254 | printUsage(); 255 | System.exit(1); 256 | } 257 | } 258 | 259 | /****************** LIST OPERATION **************/ 260 | // The requested operation was a listing of all the MusicURI references 261 | // that reside on a Web Service or local database file 262 | if (listReferencesValue != null) 263 | { 264 | boolean done = false; 265 | String musicURIDataSource = listReferencesValue; 266 | 267 | // if the given MusicURI data source is a valid web service URL, query it. 268 | if (isValidWebServiceURL(musicURIDataSource)) 269 | { 270 | // Set the done flag, to signal that the MusicURI data source 271 | // has been identified as a Web Service 272 | done = true; 273 | try 274 | { 275 | listWSReferences(new URL(musicURIDataSource)); 276 | } 277 | catch (MalformedURLException e) 278 | { 279 | //impossible to reach here, the URL has already been checked 280 | } 281 | } 282 | 283 | // if the given MusicURI data source is a valid local database file, query it. 284 | if (!done && isValidDatabaseFile(musicURIDataSource)) 285 | { 286 | // Set the done flag, to signal that the MusicURI data source 287 | // has been identified as a local database file 288 | done = true; 289 | listDBReferences(new File (musicURIDataSource)); 290 | } 291 | // if the given MusicURI data source is non of the above, abort. 292 | if (!done) 293 | { 294 | printUsage(); 295 | System.exit(1); 296 | } 297 | } 298 | } 299 | 300 | } 301 | }// end main method 302 | 303 | private static void printUsage() 304 | { 305 | System.out.println("USAGE: This MusicURI demo currently supports the following operations: "); 306 | System.out.println(""); 307 | System.out.println("1) To query a MusicURI local database with a music item, and retrieve a URI:"); 308 | System.out.println(" The -f flag signals if the filename should be considered as a hint in search."); 309 | System.out.println(" The -q switch is followed by the local database file's path"); 310 | System.out.println(""); 311 | System.out.println(" - java -jar MusicURI.jar [audiofile] [-f] [-q localDB]"); 312 | System.out.println(" "); 313 | System.out.println("2) To add a reference music item into a local MusicURI database file "); 314 | System.out.println(" The -a switch is followed by the local database file's path]"); 315 | System.out.println(" "); 316 | System.out.println(" - java -jar MusicURI.jar [audiofile] [-a localDB]"); 317 | System.out.println(" "); 318 | System.out.println("3) To list all reference music items indexed inside a local MusicURI database"); 319 | System.out.println(" The -l switch is followed by the local database file's path]"); 320 | System.out.println(" "); 321 | System.out.println(" - java -jar MusicURI.jar [-l localDB]"); 322 | } 323 | 324 | 325 | 326 | 327 | 328 | private static void queryWS(URL webServiceURL, File audioFile, Boolean usefilenameValue) 329 | { 330 | System.out.println("Starting MusicURI Demo: Query a MusicURI Web Service Data Source"); 331 | 332 | String response = null; 333 | try 334 | { 335 | //the object that will be our proxy 336 | stub = new MusicURIWebSearchSoapBindingStub(webServiceURL, new MusicURIWebSearchServiceLocator()); 337 | 338 | if (audioFile.exists()) 339 | { 340 | System.out.println("Creating query for : " + audioFile.getName()); 341 | String xmlAudioSignature = Toolset.createMPEG7Description(audioFile); 342 | 343 | String filename = audioFile.getName(); 344 | 345 | System.out.println("Waiting for Web Service to return results..."); 346 | 347 | // If the useFileName flag has been set to true, the filename should be provided 348 | // and used within the search. If not, don't the provide the filename at all. 349 | if (usefilenameValue.booleanValue()) 350 | { 351 | response = stub.performSearch(xmlAudioSignature, filename); 352 | } 353 | else 354 | { 355 | response = stub.performSearch(xmlAudioSignature, null); 356 | } 357 | System.out.println("Web Service response: "); 358 | System.out.println(response); 359 | } 360 | } 361 | catch (Exception e) 362 | { 363 | System.err.println("An error occured while querying the Web Service"); 364 | e.printStackTrace(); 365 | } 366 | 367 | } 368 | 369 | 370 | private static void addReferenceToWS(URL webServiceURL, File audioFile) 371 | { 372 | System.out.println("Starting MusicURI Demo: Add a MusicURI reference to a MusicURI Web Service Data Source"); 373 | System.out.println("Not implemented yet"); 374 | } 375 | 376 | private static void listWSReferences(URL webServiceURL) 377 | { 378 | System.out.println("Starting MusicURI Demo: List the MusicURI references of a MusicURI Web Service Data Source"); 379 | 380 | 381 | 382 | 383 | String response = null; 384 | try 385 | { 386 | //the object that will be our proxy 387 | stub = new MusicURIWebSearchSoapBindingStub(webServiceURL, new MusicURIWebSearchServiceLocator()); 388 | 389 | System.out.println("Waiting for Web Service to return results..."); 390 | 391 | response = stub.getMusicURIReferenceList(); 392 | System.out.println("Web Service response: "); 393 | System.out.println(response); 394 | } 395 | catch (Exception ex) 396 | { 397 | ex.printStackTrace(); 398 | response = "An error occured while querying the Web Service"; 399 | } 400 | 401 | 402 | 403 | 404 | } 405 | 406 | 407 | 408 | private static void queryDB(File databaseFile, File audioFile, Boolean usefilenameValue) 409 | { 410 | System.out.println("Starting MusicURI Demo: Query a local MusicURI Data Source"); 411 | 412 | String databasePath = databaseFile.getParent() + "\\"; 413 | String databaseFileName = databaseFile.getName(); 414 | MusicURIDatabase db = new MusicURIDatabase (databasePath, databaseFileName); 415 | MusicURISearch engine = new MusicURISearch (db); 416 | 417 | try 418 | { 419 | ResultRankingList finalDistanceRankingList = engine.identify(new MusicURIQuery(audioFile), 420 | usefilenameValue.booleanValue(), 421 | usefilenameValue.booleanValue(), 422 | 0.9f, //90% acceptable similarity rating 423 | usefilenameValue.booleanValue()); 424 | 425 | if (finalDistanceRankingList.getSize() >= 1) 426 | { 427 | Result theBestResult = finalDistanceRankingList.getResultAtIndex(0); 428 | double bestMatchDistance = theBestResult.distance; 429 | 430 | System.out.println("Matched with : " + (db.getMusicURIReference(theBestResult.md5)).getLabel()); 431 | System.out.println("Score : " + (float) (100 - (100*(theBestResult.distance))) + "%"); 432 | } 433 | } 434 | catch (Exception e) 435 | { 436 | e.printStackTrace(); 437 | } 438 | 439 | } 440 | 441 | private static void addReferenceToDB(File databaseFile, File audioFile) 442 | { 443 | System.out.println("Starting MusicURI Demo: Add a MusicURI reference to a local MusicURI Data Source"); 444 | 445 | String databasePath = databaseFile.getParent() + "\\"; 446 | String databaseFileName = databaseFile.getName(); 447 | MusicURIDatabase db = new MusicURIDatabase (databasePath, databaseFileName); 448 | 449 | boolean success = false; 450 | 451 | MusicURIReference newref = null; 452 | try 453 | { 454 | newref = new MusicURIReference(audioFile); 455 | success = db.addMusicURIReference(newref); 456 | } 457 | catch (Exception e) 458 | { 459 | e.printStackTrace(); 460 | } 461 | 462 | if (success) 463 | { 464 | System.out.println("The MusicURI reference was added successfully."); 465 | System.out.println("The local MusicURI Data Source now holds " + db.getDbSize() + " references."); 466 | } 467 | else 468 | System.out.println("The MusicURI reference could not be added"); 469 | } 470 | 471 | private static void listDBReferences(File databaseFile) 472 | { 473 | System.out.println("Starting MusicURI Demo: List the MusicURI references of a local MusicURI Data Source"); 474 | 475 | String databasePath = databaseFile.getParent() + "\\"; 476 | String databaseFileName = databaseFile.getName(); 477 | MusicURIDatabase db = new MusicURIDatabase (databasePath, databaseFileName); 478 | 479 | String list = db.textFormattedSetOfMusicURIReferences(); 480 | System.out.println(list); 481 | } 482 | 483 | 484 | 485 | 486 | 487 | public static boolean isValidAudioFile(String audiofileValue) 488 | { 489 | if (audiofileValue != null) 490 | { 491 | // Verify that the specified file exists, and it is not a directory 492 | File audioFile = new File(audiofileValue); 493 | if (!audioFile.exists()) 494 | { 495 | System.err.println("The specified file does not exist"); 496 | return false; 497 | } 498 | 499 | if (!audioFile.isFile()) 500 | { 501 | System.err.println("The specified file is a directory"); 502 | return false; 503 | } 504 | 505 | // Verify that the specified file is of a supported type 506 | if (!Toolset.isSupportedAudioFile(audioFile)) 507 | { 508 | System.err.println("The specified file is not a supported audio file"); 509 | return false; 510 | } 511 | return true; 512 | } 513 | else 514 | { 515 | System.out.println("Unspecified audiofileValue"); 516 | return false; 517 | } 518 | } 519 | 520 | 521 | public static boolean isValidWebServiceURL(String queryValue) 522 | { 523 | if (queryValue != null) 524 | { 525 | // Verify that the URL is well-formed and valid (both host and 526 | // resource exist) 527 | URL webServiceURL = null; 528 | try 529 | { 530 | webServiceURL = new URL(queryValue); 531 | HttpURLConnection urlConn = (HttpURLConnection) webServiceURL 532 | .openConnection(); 533 | // Try to connect. If the URL is malformed throw a 534 | // MalformedURLException. 535 | urlConn.connect(); 536 | 537 | // To take care of the chance of having an invalid, although 538 | // well-formed URL, check the HTTP Status Code. If it's not 539 | // 200 (HTTP_OK), throw an Exception. 540 | if (urlConn.getResponseCode() != 200) 541 | throw new Exception(); 542 | 543 | } 544 | catch (MalformedURLException e) 545 | { 546 | return false; 547 | } 548 | catch (Exception e) 549 | { 550 | return false; 551 | } 552 | return true; 553 | } 554 | else 555 | return false; 556 | } 557 | 558 | public static boolean isValidDatabaseFile(String musicURIDataSource) 559 | { 560 | if (musicURIDataSource != null) 561 | { 562 | // Verify that the specified file exists, and it is not a directory 563 | File databaseFile = new File(musicURIDataSource); 564 | if (!databaseFile.exists() || !databaseFile.isFile()) 565 | { 566 | return false; 567 | } 568 | 569 | // Verify that the specified file is a valid MusicURI Hashmap flatfile 570 | // (ends with .db, and can be deserialized into a Java Hashmap object) 571 | if (!isDBFile(databaseFile)) 572 | { 573 | System.err.println("The specified file is not a valid MusicURI database file"); 574 | return false; 575 | } 576 | // else 577 | // System.out.println("file ends with .db"); 578 | // try 579 | // { 580 | // HashMap object = new HashMap(); 581 | // ObjectInputStream in = new ObjectInputStream(new FileInputStream(musicURIDataSource)); 582 | // object = (HashMap) in.readObject(); 583 | // System.out.println("file can be deserialized"); 584 | // } 585 | // catch (Exception e) 586 | // { 587 | // e.toString(); 588 | // System.out.println("Can't load database file (" + musicURIDataSource + ")"); 589 | // return false; 590 | // } 591 | return true; 592 | } 593 | else 594 | { 595 | System.out.println("Unspecified musicURIDataSource"); 596 | return false; 597 | } 598 | } 599 | 600 | /** 601 | * Reports if the filename of the given file ends with ".db" 602 | * @param file the file to check 603 | * @return true if the filename ends with a ".db" extension, false otherwise 604 | */ 605 | public static boolean isDBFile(File file) 606 | { 607 | String fname = file.getName(); 608 | String extension = fname.substring(fname.lastIndexOf('.') + 1); 609 | if (extension.equalsIgnoreCase("db")) return true; 610 | else return false; 611 | } 612 | 613 | 614 | } 615 | --------------------------------------------------------------------------------