Main Page   Packages   Class Hierarchy   Compound List   File List   Compound Members  

HeadBangComposer.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.composers;
00024 
00025 import gnu.getopt.Getopt;
00026 
00027 import java.io.IOException;
00028 import java.text.NumberFormat;
00029 import java.util.Random;
00030 import java.util.Vector;
00031 
00032 import com.meapsoft.BasicHist;
00033 import com.meapsoft.Chunk;
00034 import com.meapsoft.EDLChunk;
00035 import com.meapsoft.EDLFile;
00036 import com.meapsoft.FeatChunk;
00037 import com.meapsoft.FeatFile;
00038 import com.meapsoft.ParserException;
00039 
00047 public class HeadBangComposer extends Composer
00048 {
00049         public static String description = "HeadBangComposer rocks it hard-core style. \n" +
00050                         "Finds the most common chunk length L and lengths related by a " + 
00051                         "factor of 2, i.e. L/2, L/4, L/8, L*2. "+
00052                         "These chunks are then shuffled to create a new piece with a clear beat.\n";
00053                         
00054     String outFileName = "headBang.edl";
00055 
00056     FeatFile featFile;
00057         
00058         int binsNum;
00059         int durRange;
00060         int newPieceLength;
00061     boolean debug = false;
00062 
00063     public HeadBangComposer(String featFN, String outFN)
00064     {
00065         this(featFN, outFN, 5000, 300);
00066     }
00067 
00068     public HeadBangComposer(FeatFile featFN, EDLFile outFN)
00069     {
00070         this(featFN, outFN, 5000,300);
00071     }
00072 
00073     public HeadBangComposer(String featFN, String outFN, int binsNum, int newPieceLength)
00074     {
00075         this(new FeatFile(featFN), new EDLFile(outFN), binsNum, newPieceLength);
00076     }
00077 
00078     public HeadBangComposer(FeatFile featFN, EDLFile outFN, int binsNum, int newPieceLength)
00079     {
00080         featFile = featFN;
00081         outFile = outFN;
00082                 this.binsNum = binsNum;
00083                 //this.durRange = durRange;
00084                 this.newPieceLength = newPieceLength;
00085 
00086         if(outFile == null)
00087             outFile = new EDLFile("");
00088     }
00089 
00090     public void printUsageAndExit() 
00091     {
00092         System.out.println("Usage: HeadBangComposer [-options] features.feat \n\n" + 
00093                "  where options include:\n" + 
00094                "    -o output_file  the file to write the output to (defaults to sorted.edl)\n" +
00095                "    -g              debug mode (prints out chunk features on each line of output file)\n" +
00096                "    -b              number of bins for length histogram\n" +
00097                            "    -l              new piece length in number of chunks");
00098         printCommandLineOptions('i');
00099         //printCommandLineOptions('d');
00100         System.out.println();
00101         System.exit(0);
00102     }
00103 
00104     public HeadBangComposer(String[] args) 
00105     {
00106         if(args.length == 0)
00107             printUsageAndExit();
00108 
00109         Vector features = new Vector();
00110 
00111         // Parse arguments
00112         String argString = "o:gb:l:";
00113 
00114         Getopt opt = new Getopt("HeadBangComposer", args, argString);
00115         opt.setOpterr(false);
00116         
00117         int c = -1;
00118         while ((c =opt.getopt()) != -1) 
00119         {
00120             switch(c) 
00121             {
00122             case 'o':
00123                 outFileName = opt.getOptarg();
00124                 break;
00125             case 'l':
00126                                 //System.out.println( opt.getOptarg());
00127                 newPieceLength = Integer.valueOf( opt.getOptarg() ).intValue();
00128                 break;
00129             case 'g':
00130                 debug = true;
00131                 break;
00132             case 'b':
00133                                 //System.out.println( opt.getOptarg());
00134                                 binsNum = Integer.valueOf( opt.getOptarg() ).intValue();
00135                                 break;
00136             case '?':
00137                 printUsageAndExit();
00138                 break;
00139             default:
00140                 System.out.print("getopt() returned " + c + "\n");
00141             }
00142         }
00143         
00144         // parse arguments
00145         int ind = opt.getOptind();
00146         if(ind > args.length)
00147             printUsageAndExit();
00148         
00149         featFile = new FeatFile(args[args.length-1]);
00150         outFile = new EDLFile(outFileName);
00151 
00152         System.out.println("Composing " + outFileName + 
00153                            " from " +  args[args.length-1] + ".");
00154     }
00155 
00156     public void setup() throws IOException, ParserException
00157     {
00158         super.setup();
00159 
00160         if(!featFile.haveReadFile)
00161             featFile.readFile();
00162 
00163         if(featFile.chunks.size() == 0)
00164             throw new ParserException(featFile.filename, "No chunks found");
00165         
00166         progress.setMaximum(featFile.chunks.size());
00167     }
00168     
00169     public EDLFile compose()
00170     {
00171                 // make a histogram of chunk lengths
00172                 int bins = binsNum;
00173                 int range = 25856;
00174                 BasicHist hist = new BasicHist(bins,0,range);
00175                 
00176         for (int i = 0; i < featFile.chunks.size(); i=i+1 ){
00177             //System.out.println(i);
00178             double len = Math.floor(((Chunk)featFile.chunks.get(i)).length * samplingRate);
00179                         hist.add(Math.log(len)/Math.log(2));
00180                         //System.out.println(i+" "+len+" "+((FeatChunk)featFile.chunks.get(i)).getFeatures()[0]);                       
00181                 }
00182                 
00183                 
00184                 // find mode of histogram
00185                 int currentValue = 0;
00186                 int maxValue = 0;
00187                 int maxValueBin =0;
00188                 for (int i=0; i< bins; i++)
00189                 {
00190                         currentValue = hist.getValue(i);
00191                         if (currentValue > maxValue)
00192                         {
00193                                 maxValue = currentValue;
00194                                 maxValueBin = i;
00195                         }
00196                         
00197                         
00198                         //System.out.println("histo [" + i +"]" + hist.getValue(i));
00199                 }
00200                 //System.out.println(" maxValueBin =" + maxValueBin);
00201                 
00202                 // get length ranges to recover
00203                 double lowBound = Math.pow(2, ((double)range / (double)bins * maxValueBin));
00204                 double highBound = Math.pow(2, ((double)range / (double)bins * (maxValueBin + 1)));
00205                 //System.out.println("low bound " + lowBound);
00206                 //System.out.println("high bound " + highBound);
00207 
00208                 double lowBoundDiv = lowBound / 2;
00209                 double highBoundDiv = highBound / 2;
00210                 double lowBoundDiv2 = lowBound / 4;
00211                 double highBoundDiv2 = highBound / 4;
00212                 double lowBoundMult = lowBound * 2;
00213                 double highBoundMult = highBound * 2;
00214 
00215                 Vector featChunks = new Vector(featFile.chunks);
00216 
00217                 //find chunks that fall in divisions or multiples of mode.
00218                 FeatChunk tempFeatChunk;
00219                 double tempFeatLen;
00220                 Vector modeChunks = new Vector();
00221                 Vector multModeChunks = new Vector();
00222                 Vector divModeChunks = new Vector();
00223                 Vector div2ModeChunks = new Vector();
00224 
00225                 
00226                 for (int i=0; i < featChunks.size(); i++)
00227                 {
00228                         tempFeatChunk = (FeatChunk)featChunks.get(i);
00229                         tempFeatLen = Math.floor(tempFeatChunk.length * samplingRate);
00230 
00231                         if (lowBoundDiv2 < tempFeatLen && tempFeatLen < highBoundDiv2)
00232                         {
00233                                 div2ModeChunks.add(featChunks.get(i));
00234                                 //System.out.println(" found a div2 in chunk" + i);
00235                         }
00236                         else if (lowBoundDiv < tempFeatLen && tempFeatLen < highBoundDiv)
00237                         {
00238                                 divModeChunks.add(featChunks.get(i));
00239                                 //System.out.println(" found a div in chunk" + i);
00240                         }
00241                         else if (lowBoundMult < tempFeatLen && tempFeatLen < highBoundMult)
00242                         {
00243                                 multModeChunks.add(featChunks.get(i));
00244                                 //System.out.println(" found a mult in chunk" + i);
00245                         }
00246                         else if (lowBound < tempFeatLen && tempFeatLen < highBound)
00247                         {
00248                                 modeChunks.add(featChunks.get(i));
00249                                 //System.out.println(" found a mode in chunk" + i);
00250                         }
00251                 }
00252                 
00253                 
00254                 Vector outChunks = new Vector();
00255                 
00256                 
00257                 Random rand = new Random();
00258                 int index;
00259                 for (int i=0; i < newPieceLength; i++)
00260                 {
00261                         index  = rand.nextInt(16);
00262                         if (0 <= index && index < 4)
00263                         {
00264                                 if (div2ModeChunks.size() > 0)
00265                                 {
00266                                         outChunks.add(div2ModeChunks.get(rand.nextInt(div2ModeChunks.size())));
00267                                         outChunks.add(div2ModeChunks.get(rand.nextInt(div2ModeChunks.size())));
00268                                         outChunks.add(div2ModeChunks.get(rand.nextInt(div2ModeChunks.size())));
00269                                         outChunks.add(div2ModeChunks.get(rand.nextInt(div2ModeChunks.size())));
00270                                         outChunks.add(div2ModeChunks.get(rand.nextInt(div2ModeChunks.size())));
00271                                         outChunks.add(div2ModeChunks.get(rand.nextInt(div2ModeChunks.size())));
00272                                         outChunks.add(div2ModeChunks.get(rand.nextInt(div2ModeChunks.size())));
00273                                         outChunks.add(div2ModeChunks.get(rand.nextInt(div2ModeChunks.size())));
00274                                         //System.out.println("Wrote 8 mode / 4 chunks");
00275 
00276                                 }
00277                         }
00278                         else if (4 <= index && index < 6)
00279                         {
00280                                 if (divModeChunks.size() > 0)
00281                                 {
00282                                         outChunks.add(divModeChunks.get(rand.nextInt(divModeChunks.size())));
00283                                         outChunks.add(divModeChunks.get(rand.nextInt(divModeChunks.size())));
00284                                         outChunks.add(divModeChunks.get(rand.nextInt(divModeChunks.size())));
00285                                         outChunks.add(divModeChunks.get(rand.nextInt(divModeChunks.size())));
00286                                         //System.out.println("Wrote 4 mode / 2 chunks");
00287                                 }
00288                         }
00289                         else if (6 <= index && index < 14)
00290                         {
00291                                 if (modeChunks.size() > 0)
00292                                 {
00293                                         outChunks.add(modeChunks.get(rand.nextInt(modeChunks.size())));
00294                                         outChunks.add(modeChunks.get(rand.nextInt(modeChunks.size())));
00295                                         //System.out.println("Wrote 2 mode chunks");
00296                                 }
00297                         }
00298                         else if (14 <= index )
00299                         {
00300                                 if (multModeChunks.size() > 0)
00301                                 {
00302                                         outChunks.add(multModeChunks.get(rand.nextInt(multModeChunks.size())));
00303                                         //System.out.println("Wrote 1 mode * 2 chunk");
00304                                 }
00305                         }
00306                         
00307             progress.setValue(progress.getValue()+1);   
00308                 }
00309                 
00310         
00311         double currTime = 0;
00312         while(outChunks.size() > 0)
00313         {
00314             FeatChunk match = (FeatChunk)outChunks.remove(0);
00315             
00316             // turn match chunk into an EDL chunk 
00317             EDLChunk nc = new EDLChunk(match, currTime);
00318 
00319             if(debug)
00320             {
00321                                 NumberFormat fmt = NumberFormat.getInstance();
00322                                 fmt.setMaximumFractionDigits(3);
00323                 nc.comment = "    # feats = ";
00324                 double[] feat = match.getFeatures();
00325                 for(int x = 0; x < feat.length-1; x++)
00326                     nc.comment += fmt.format(feat[x]) + ", ";
00327                 nc.comment += fmt.format(feat[feat.length-1]);
00328             }
00329 
00330             outFile.chunks.add(nc);
00331             
00332             currTime += match.length;
00333         }
00334 
00335         // outFile now contains some chunks.
00336         outFile.haveReadFile = true;
00337 
00338         return outFile;
00339     } 
00340 
00341     public static void main(String[] args) 
00342     {
00343         HeadBangComposer m = new HeadBangComposer(args);
00344         long startTime = System.currentTimeMillis();
00345         m.run();
00346         System.out.println("Done. Took " +
00347                            ((System.currentTimeMillis() - startTime)/1000.0)
00348                            + "s");
00349         System.exit(0);
00350     }
00351 }

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