/*
* 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.text.NumberFormat;
import java.util.Collections;
import java.util.Vector;
import com.meapsoft.ChunkDist;
import com.meapsoft.EDLChunk;
import com.meapsoft.EDLFile;
import com.meapsoft.FeatChunk;
import com.meapsoft.FeatFile;
/**
* Steps through input sound and swaps each segment with its nearest neighbor.
* Ideally this will preserve the original structure of the input.
*
* @author Ron Weiss (ronw@ee.columbia.edu)
*/
public class NNSwapComposer extends SortComposer
{
public static String oldDesc = "NNSwapComposer swaps each chunk of sound with the chunk that it is most " +
"similar to. This should preserve much of the sonic structure of the input while swapping similar " +
"chunks from different parts of the sound.";
boolean reuseChunks = false;
//@mike: empty constructor just to sniff this guy
//please don't call this constructor, it will not work
public NNSwapComposer()
{
initNameAndDescription("Nearest Neighbor Swap", new String(oldDesc));
}
public NNSwapComposer(String featFN, String outFN)
{
super(featFN, outFN);
}
public NNSwapComposer(FeatFile featFN, EDLFile outFN)
{
super(featFN, outFN);
}
public NNSwapComposer(String featFN, String outFN, ChunkDist cd)
{
super(featFN, outFN, cd);
}
public NNSwapComposer(FeatFile featFN, EDLFile outFN, ChunkDist cd)
{
super(featFN, outFN, cd);
}
public void printUsageAndExit()
{
System.out
.println("Usage: NNSwapComposer [-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"
+ " -u reuse mode allow the reuse of chunks as Nearest Neighbors, so that a given chunk may be used more than once.");
printCommandLineOptions('i');
printCommandLineOptions('d');
printCommandLineOptions('c');
System.out.println();
System.exit(0);
}
/**
* NNSwapComposer constructor. Parses command line arguments
*/
public NNSwapComposer(String[] args)
{
if (args.length == 0)
printUsageAndExit();
// Vector features = new Vector();
// Parse arguments
String argString = "d:i:o:c:r:gu";
featdim = parseFeatDim(args, argString);
dist = parseChunkDist(args, argString, featdim);
parseCommands(args, argString);
Getopt opt = new Getopt("NNSwapComposer", args, argString);
opt.setOpterr(false);
int c = -1;
while ((c = opt.getopt()) != -1)
{
switch (c)
{
case 'o':
outFileName = opt.getOptarg();
break;
case 'r':
reverseSort = true;
break;
case 'g':
debug = true;
break;
case 'u':
reuseChunks = true;
break;
case 'd': // already handled above
break;
case 'i': // already handled above
break;
case 'c': // already handled above
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 setReuseChunks(boolean reuse)
{
reuseChunks = reuse;
}
public EDLFile compose()
{
Vector chunks = new Vector(featFile.chunks);
if (reuseChunks)
{
//System.out.println("reusing chunks!");
int numChunks = chunks.size();
for (int chunkNum = 0; chunkNum < numChunks; chunkNum++)
{
FeatChunk targetChunk = (FeatChunk) chunks.get(chunkNum);
chunks.remove(targetChunk);
dist.setTarget(targetChunk);
FeatChunk nnChunk = (FeatChunk) Collections.min(chunks, dist);
//System.out.println(targetChunk);
//System.out.println(nnChunk);
//System.out.println(chunks.size()+"\n");
chunks.add(chunkNum, targetChunk);
outFile.chunks.add(new EDLChunk(nnChunk, targetChunk.startTime));
progress.setValue(progress.getValue() + 1);
}
}
else
{
while (chunks.size() > 1)
{
FeatChunk targetChunk = (FeatChunk) chunks.get(0);
chunks.remove(targetChunk);
dist.setTarget(targetChunk);
FeatChunk nnChunk = (FeatChunk) Collections.min(chunks, dist);
chunks.remove(nnChunk);
//System.out.println(targetChunk);
//System.out.println(nnChunk);
//System.out.println(chunks.size()+"\n");
outFile.chunks.add(new EDLChunk(nnChunk, targetChunk.startTime));
outFile.chunks.add(new EDLChunk(targetChunk, nnChunk.startTime));
progress.setValue(progress.getValue() + 1);
}
}
// outFile now contains some chunks.
outFile.haveReadFile = true;
return outFile;
}
public static void main(String[] args)
{
NNSwapComposer m = new NNSwapComposer(args);
long startTime = System.currentTimeMillis();
m.run();
System.out.println("Done. Took "
+ ((System.currentTimeMillis() - startTime) / 1000.0) + "s");
System.exit(0);
}
}