Main Page   Packages   Class Hierarchy   Compound List   File List   Compound Members  

Segmenter.java

00001 /*
00002  *  Copyright 2006-2007 Columbia University.
00003  *
00004  *  This file is part of MEAPsoft.
00005  *
00006  *  MEAPsoft is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License version 2 as
00008  *  published by the Free Software Foundation.
00009  *
00010  *  MEAPsoft is distributed in the hope that it will be useful, but
00011  *  WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  *  General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with MEAPsoft; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
00018  *  02110-1301 USA
00019  *
00020  *  See the file "COPYING" for the text of the license.
00021  */
00022 
00023 package com.meapsoft;
00024 
00025 import gnu.getopt.Getopt;
00026 
00027 import java.io.IOException;
00028 
00029 import javax.sound.sampled.AudioFormat;
00030 import javax.sound.sampled.AudioInputStream;
00031 import javax.sound.sampled.UnsupportedAudioFileException;
00032 //import featextractors.*;
00033 
00041 public class Segmenter extends MEAPUtil
00042 {
00043     // Files to use
00044     String[] audioFiles;
00045     String outFileName="out.segments";
00046     FeatFile outFile; 
00047     
00048     // Extractor parts
00049     AudioInputStream ais;
00050     STFT stft;
00051     boolean useBeatOD = true;
00052     OnsetDetector detector;
00053     SegmentExtractor extractor;
00054     
00055     boolean onsetAtFirstFrame = false;
00056 
00057     // sensitivity of DpweOnsetDetector.  higher is more sensitive
00058     double threshMult = 1.0;
00059     // length of smoothing window in seconds.
00060     double smtime = 0.1;
00061 
00062     double tempoMult = 1;
00063 
00064     public Segmenter(String[] inFiles, String outputFile)
00065     {
00066         audioFiles = inFiles;
00067 
00068         outFileName = outputFile;
00069         outFile = new FeatFile(outFileName);
00070     }
00071 
00072     public Segmenter(String inFile, String outputFile)
00073     {
00074         audioFiles = new String[1];
00075         audioFiles[0] = inFile;
00076 
00077         outFileName = outputFile;
00078         outFile = new FeatFile(outFileName);
00079     }
00080 
00081     public Segmenter(String[] inFiles, String outputFile, double thr, boolean beatOD, boolean oaff)
00082     {
00083         this(inFiles, outputFile);
00084 
00085         threshMult = thr;
00086         useBeatOD = beatOD;
00087         onsetAtFirstFrame = oaff;
00088     }
00089 
00090    public Segmenter(String[] inFiles, String outputFile, double thr, double smt, boolean beatOD, boolean oaff)
00091    {
00092        this(inFiles, outputFile);
00093        
00094        threshMult = thr;
00095        useBeatOD = beatOD;
00096        onsetAtFirstFrame = oaff;
00097        smtime = smt;
00098    }
00099     public Segmenter(String inFile, String outputFile, double thr, boolean beatOD, boolean oaff)
00100     {
00101         this(inFile, outputFile);
00102 
00103         threshMult = thr;
00104         useBeatOD = beatOD;
00105         onsetAtFirstFrame = oaff;
00106     }
00107 
00108     public Segmenter(String inFile, String outputFile, double thr, double smt, boolean beatOD, boolean oaff)
00109     {
00110         this(inFile, outputFile);
00111 
00112         threshMult = thr;
00113         useBeatOD = beatOD;
00114         onsetAtFirstFrame = oaff;
00115         smtime = smt;
00116     }
00117 
00118     public void printUsageAndExit() 
00119     {
00120         System.out.println("Usage: Segmenter [-options] source1.wav source2.mp3 ... \n\n" + 
00121                "  where options include:\n" + 
00122                        "    -o output_file  the file to write the output to (defaults to ./out.segments)\n" +
00123                        "    -m N      [0]   use mixer N for input\n" +
00124                        "    -t D.D  [1.0]   onset detector threshold (event detector), tempo multiplier (beat detector)\n" +
00125                "    -s D.D  [0.1]   length of smoothing window in seconds for event detector\n" +
00126                "    -d              use the old style onset detector (defaults to BeatOnsetDetector)\n" +
00127                "    -0              add an onset at the very beginning of the file\n" +
00128                        "");
00129         System.exit(0);
00130     }
00131 
00135     public Segmenter(String[] args) 
00136     {
00137         if(args.length == 0)
00138             printUsageAndExit();
00139         
00140         // Parse arguments
00141         Getopt opt = new Getopt("Segmenter", args, "m:t:do:s:0");
00142         opt.setOpterr(false);
00143         
00144         int c = -1;
00145         while ((c = opt.getopt()) != -1) 
00146         {
00147             switch(c) 
00148             {
00149             case 'm':
00150                 mixerToUse = Integer.parseInt(opt.getOptarg());
00151                 System.out.println("Using mixer " + mixerToUse);
00152                 break;
00153             case 't':
00154                 threshMult = Double.parseDouble(opt.getOptarg());
00155                 tempoMult = threshMult;
00156                 break;
00157             case 's':
00158                 smtime = Double.parseDouble(opt.getOptarg());
00159                 break;
00160             case 'd':
00161                 useBeatOD = false;
00162                 break;
00163             case 'o':
00164                 outFileName = opt.getOptarg();
00165                 break;
00166             case '0':
00167                 onsetAtFirstFrame = true;
00168                 break;
00169             case '?':
00170                 printUsageAndExit();
00171                 break;
00172             default:
00173                 System.out.print("getopt() returned " + c + "\n");
00174             }
00175         }
00176         
00177         // parse arguments
00178         int ind = opt.getOptind();
00179         if(ind > args.length)
00180             printUsageAndExit();
00181         
00182         audioFiles = new String[args.length - ind];
00183         for(int i=ind; i<args.length; i++)
00184             audioFiles[i-ind] = args[i];
00185 
00186         outFile = new FeatFile(outFileName);
00187     }
00188 
00189     public FeatFile processAudioFile() throws IOException, UnsupportedAudioFileException
00190     {
00191         return processAudioFile(outFile.filename);
00192     }
00193 
00194     public FeatFile processAudioFile(String fn) throws IOException, UnsupportedAudioFileException
00195     {
00196         // Create Extractor
00197         //ais = openInputStream(fn);
00198         // downsample to 8kHz
00199         ais = openInputStream(fn, new AudioFormat(DpweOnsetDetector.sr, 
00200                                                   bitsPerSamp, 1, signed, 
00201                                                   bigEndian));
00202 
00203         long frameLength = ais.getFrameLength();
00204         // the mp3/flac decoders don't like to tell us the frame
00205         // length, so we have to make a guess.  You might get an
00206         // error and progress bars will be off.
00207         if(frameLength < 0)
00208         {
00209             frameLength = 50000*DpweOnsetDetector.swin/2;
00210 
00211         }
00212         int numFrames = (int) frameLength/(DpweOnsetDetector.swin/2);
00213 
00214         // keep track of our progress in segmenting this file:
00215         progress.setMinimum(0);
00216         progress.setMaximum(numFrames); 
00217         progress.setValue(0);
00218 
00219         // use 30ms window
00220         stft = new STFT(ais, DpweOnsetDetector.swin, DpweOnsetDetector.swin/2, frameLatency);
00221        
00222         if(useBeatOD)
00223             //detector = new BeatOnsetDetector(stft, bandThresh, bandFrac);
00224             detector = new DpweBeatOnsetDetector(stft, numFrames, tempoMult);
00225         else
00226             //detector = new OnsetDetector(stft, bandThresh, bandFrac);
00227             detector = new DpweOnsetDetector(stft, numFrames, threshMult, smtime);
00228 
00229         extractor = new SegmentExtractor(stft, fn, outFile, progress);
00230         detector.addOnsetListener(extractor);
00231 
00232         // Hook things together
00233         stft.addFrameListener(extractor);
00234         
00235         // insert an onset at frame 0?
00236         if(onsetAtFirstFrame) 
00237             extractor.newOnset(0, 0);
00238 
00239         // Extract the entire source file
00240         extractor.run();
00241 
00242         // outFile now contains some chunks.
00243         outFile.haveReadFile = true;
00244 
00245         return outFile;
00246     }
00247    
00251     public void run() 
00252     {
00253         // process supplied files
00254         for(int i=0; i<audioFiles.length; i++) 
00255         {
00256 
00257             if(verbose)
00258                 System.out.println("Writing segments from " + audioFiles[i] + " to " 
00259                                    + outFileName + ".");
00260             
00261             long startTime = System.currentTimeMillis();
00262 
00263             try 
00264             { 
00265                 processAudioFile(audioFiles[i]);
00266 
00267                 if(writeMEAPFile)
00268                     outFile.writeFile();
00269             }
00270             catch(Exception e)
00271             { 
00272                 exceptionHandler.handleException(e);
00273             }
00274             
00275             if(verbose)
00276                 System.out.println("Done.  Took " + 
00277                                    ((System.currentTimeMillis() - startTime)/1000.0) 
00278                                    + "s");
00279         }
00280     }
00281 
00282     // Set the tempo multiplier for the beat onset detector.
00283     public void setTempoMultiplier(double mult)
00284     {
00285         tempoMult = mult;
00286     }
00287 
00288     public FeatFile getSegFile()
00289     {
00290         return outFile;
00291     }
00292 
00293     public static void main(String[] args) 
00294     {
00295         Segmenter o2or = new Segmenter(args);
00296         o2or.verbose = true;
00297         o2or.run();
00298         System.exit(0);
00299     }
00300 }

Generated on Tue Feb 6 19:02:27 2007 for MEAPsoft by doxygen1.2.18