Package com.meapsoft.composers

Source Code of com.meapsoft.composers.HeadBangComposer

/*
*  Copyright 2006-2007 Columbia University.
*
*  This file is part of MEAPsoft.
*
*  MEAPsoft is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License version 2 as
*  published by the Free Software Foundation.
*
*  MEAPsoft is distributed in the hope that it will be useful, but
*  WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*  General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with MEAPsoft; if not, write to the Free Software
*  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
*  02110-1301 USA
*
*  See the file "COPYING" for the text of the license.
*/

package com.meapsoft.composers;

import gnu.getopt.Getopt;

import java.io.IOException;
import java.text.NumberFormat;
import java.util.Random;
import java.util.Vector;

import com.meapsoft.BasicHist;
import com.meapsoft.Chunk;
import com.meapsoft.EDLChunk;
import com.meapsoft.EDLFile;
import com.meapsoft.FeatChunk;
import com.meapsoft.FeatFile;
import com.meapsoft.ParserException;

/**
* Rocks it hard-core style. Finds the most common chunk length L and lengths
* related by a factor of 2, i.e. L/2, L/4, L/8, L*2. These chunks are then
* shuffled to create a new piece with a clear beat.
*
* @author Victor Adan and Jeff Snyder
*/
public class HeadBangComposer extends Composer
{
  public static String oldDesc = "HeadBangComposer rocks it hard-core style. Finds the most common chunk length L and lengths related by a factor of 2, i.e. L/2, L/4, L/8, L*2. These chunks are then shuffled to create a new piece with a clear beat.\n";

  String outFileName = "headBang.edl";

  FeatFile featFile;

  int binsNum;

  int durRange;

  int newPieceLength;

  boolean debug = false;

  //@mike: empty constructor just to sniff this guy
  //please don't call this constructor, it will not work
  public HeadBangComposer()
  {
    initNameAndDescription("Head Banger", new String(oldDesc));
  }
 
  public HeadBangComposer(String featFN, String outFN)
  {
    this(featFN, outFN, 5000, 300);
  }

  public HeadBangComposer(FeatFile featFN, EDLFile outFN)
  {
    this(featFN, outFN, 5000, 300);
  }

  public HeadBangComposer(String featFN, String outFN, int binsNum,
      int newPieceLength)
  {
    this(new FeatFile(featFN), new EDLFile(outFN), binsNum, newPieceLength);
  }

  public HeadBangComposer(FeatFile featFN, EDLFile outFN, int binsNum,
      int newPieceLength)
  {
    featFile = featFN;
    outFile = outFN;
    this.binsNum = binsNum;
    // this.durRange = durRange;
    this.newPieceLength = newPieceLength;

    if (outFile == null)
      outFile = new EDLFile("");
  }

  public void printUsageAndExit()
  {
    System.out
        .println("Usage: HeadBangComposer [-options] features.feat \n\n"
            + "  where options include:\n"
            + "    -o output_file  the file to write the output to (defaults to sorted.edl)\n"
            + "    -g              debug mode (prints out chunk features on each line of output file)\n"
            + "    -b              number of bins for length histogram\n"
            + "    -l              new piece length in number of chunks");
    printCommandLineOptions('i');
    // printCommandLineOptions('d');
    System.out.println();
    System.exit(0);
  }

  public HeadBangComposer(String[] args)
  {
    if (args.length == 0)
      printUsageAndExit();

    // Vector features = new Vector();

    // Parse arguments
    String argString = "o:gb:l:";

    Getopt opt = new Getopt("HeadBangComposer", args, argString);
    opt.setOpterr(false);

    int c = -1;
    while ((c = opt.getopt()) != -1)
    {
      switch (c)
      {
      case 'o':
        outFileName = opt.getOptarg();
        break;
      case 'l':
        // System.out.println( opt.getOptarg());
        newPieceLength = Integer.valueOf(opt.getOptarg()).intValue();
        break;
      case 'g':
        debug = true;
        break;
      case 'b':
        // System.out.println( opt.getOptarg());
        binsNum = Integer.valueOf(opt.getOptarg()).intValue();
        break;
      case '?':
        printUsageAndExit();
        break;
      default:
        System.out.print("getopt() returned " + c + "\n");
      }
    }

    // parse arguments
    int ind = opt.getOptind();
    if (ind > args.length)
      printUsageAndExit();

    featFile = new FeatFile(args[args.length - 1]);
    outFile = new EDLFile(outFileName);

    System.out.println("Composing " + outFileName + " from "
        + args[args.length - 1] + ".");
  }

  public void setup() throws IOException, ParserException
  {
    super.setup();

    if (!featFile.haveReadFile)
      featFile.readFile();

    if (featFile.chunks.size() == 0)
      throw new ParserException(featFile.filename, "No chunks found");

    progress.setMaximum(featFile.chunks.size());
  }

  public EDLFile compose()
  {
    // make a histogram of chunk lengths
    int bins = binsNum;
    int range = 25856;
    BasicHist hist = new BasicHist(bins, 0, range);

    for (int i = 0; i < featFile.chunks.size(); i = i + 1)
    {
      // System.out.println(i);
      double len = Math.floor(((Chunk) featFile.chunks.get(i)).length
          * samplingRate);
      hist.add(Math.log(len) / Math.log(2));
      // System.out.println(i+" "+len+"
      // "+((FeatChunk)featFile.chunks.get(i)).getFeatures()[0]);
    }

    // find mode of histogram
    int currentValue = 0;
    int maxValue = 0;
    int maxValueBin = 0;
    for (int i = 0; i < bins; i++)
    {
      currentValue = hist.getValue(i);
      if (currentValue > maxValue)
      {
        maxValue = currentValue;
        maxValueBin = i;
      }

      // System.out.println("histo [" + i +"]" + hist.getValue(i));
    }
    // System.out.println(" maxValueBin =" + maxValueBin);

    // get length ranges to recover
    double lowBound = Math.pow(2,
        ((double) range / (double) bins * maxValueBin));
    double highBound = Math.pow(2,
        ((double) range / (double) bins * (maxValueBin + 1)));
    // System.out.println("low bound " + lowBound);
    // System.out.println("high bound " + highBound);

    double lowBoundDiv = lowBound / 2;
    double highBoundDiv = highBound / 2;
    double lowBoundDiv2 = lowBound / 4;
    double highBoundDiv2 = highBound / 4;
    double lowBoundMult = lowBound * 2;
    double highBoundMult = highBound * 2;

    Vector featChunks = new Vector(featFile.chunks);

    // find chunks that fall in divisions or multiples of mode.
    FeatChunk tempFeatChunk;
    double tempFeatLen;
    Vector modeChunks = new Vector();
    Vector multModeChunks = new Vector();
    Vector divModeChunks = new Vector();
    Vector div2ModeChunks = new Vector();

    for (int i = 0; i < featChunks.size(); i++)
    {
      tempFeatChunk = (FeatChunk) featChunks.get(i);
      tempFeatLen = Math.floor(tempFeatChunk.length * samplingRate);

      if (lowBoundDiv2 < tempFeatLen && tempFeatLen < highBoundDiv2)
      {
        div2ModeChunks.add(featChunks.get(i));
        // System.out.println(" found a div2 in chunk" + i);
      }
      else if (lowBoundDiv < tempFeatLen && tempFeatLen < highBoundDiv)
      {
        divModeChunks.add(featChunks.get(i));
        // System.out.println(" found a div in chunk" + i);
      }
      else if (lowBoundMult < tempFeatLen && tempFeatLen < highBoundMult)
      {
        multModeChunks.add(featChunks.get(i));
        // System.out.println(" found a mult in chunk" + i);
      }
      else if (lowBound < tempFeatLen && tempFeatLen < highBound)
      {
        modeChunks.add(featChunks.get(i));
        // System.out.println(" found a mode in chunk" + i);
      }
    }

    Vector outChunks = new Vector();

    Random rand = new Random();
    int index;
    for (int i = 0; i < newPieceLength; i++)
    {
      index = rand.nextInt(16);
      if (0 <= index && index < 4)
      {
        if (div2ModeChunks.size() > 0)
        {
          outChunks.add(div2ModeChunks.get(rand
              .nextInt(div2ModeChunks.size())));
          outChunks.add(div2ModeChunks.get(rand
              .nextInt(div2ModeChunks.size())));
          outChunks.add(div2ModeChunks.get(rand
              .nextInt(div2ModeChunks.size())));
          outChunks.add(div2ModeChunks.get(rand
              .nextInt(div2ModeChunks.size())));
          outChunks.add(div2ModeChunks.get(rand
              .nextInt(div2ModeChunks.size())));
          outChunks.add(div2ModeChunks.get(rand
              .nextInt(div2ModeChunks.size())));
          outChunks.add(div2ModeChunks.get(rand
              .nextInt(div2ModeChunks.size())));
          outChunks.add(div2ModeChunks.get(rand
              .nextInt(div2ModeChunks.size())));
          // System.out.println("Wrote 8 mode / 4 chunks");

        }
      }
      else if (4 <= index && index < 6)
      {
        if (divModeChunks.size() > 0)
        {
          outChunks.add(divModeChunks.get(rand.nextInt(divModeChunks
              .size())));
          outChunks.add(divModeChunks.get(rand.nextInt(divModeChunks
              .size())));
          outChunks.add(divModeChunks.get(rand.nextInt(divModeChunks
              .size())));
          outChunks.add(divModeChunks.get(rand.nextInt(divModeChunks
              .size())));
          // System.out.println("Wrote 4 mode / 2 chunks");
        }
      }
      else if (6 <= index && index < 14)
      {
        if (modeChunks.size() > 0)
        {
          outChunks.add(modeChunks.get(rand
              .nextInt(modeChunks.size())));
          outChunks.add(modeChunks.get(rand
              .nextInt(modeChunks.size())));
          // System.out.println("Wrote 2 mode chunks");
        }
      }
      else if (14 <= index)
      {
        if (multModeChunks.size() > 0)
        {
          outChunks.add(multModeChunks.get(rand
              .nextInt(multModeChunks.size())));
          // System.out.println("Wrote 1 mode * 2 chunk");
        }
      }

      progress.setValue(progress.getValue() + 1);
    }

    double currTime = 0;
    while (outChunks.size() > 0)
    {
      FeatChunk match = (FeatChunk) outChunks.remove(0);

      // turn match chunk into an EDL chunk
      EDLChunk nc = new EDLChunk(match, currTime);

      if (debug)
      {
        NumberFormat fmt = NumberFormat.getInstance();
        fmt.setMaximumFractionDigits(3);
        nc.comment = "    # feats = ";
        double[] feat = match.getFeatures();
        for (int x = 0; x < feat.length - 1; x++)
          nc.comment += fmt.format(feat[x]) + ", ";
        nc.comment += fmt.format(feat[feat.length - 1]);
      }

      outFile.chunks.add(nc);

      currTime += match.length;
    }

    // outFile now contains some chunks.
    outFile.haveReadFile = true;

    return outFile;
  }

  public static void main(String[] args)
  {
    HeadBangComposer m = new HeadBangComposer(args);
    long startTime = System.currentTimeMillis();
    m.run();
    System.out.println("Done. Took "
        + ((System.currentTimeMillis() - startTime) / 1000.0) + "s");
    System.exit(0);
  }
}
TOP

Related Classes of com.meapsoft.composers.HeadBangComposer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.