00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 package com.meapsoft;
00024
00025 import gnu.getopt.Getopt;
00026
00027 import java.io.IOException;
00028 import java.util.Arrays;
00029 import java.util.Iterator;
00030
00031 import javax.sound.sampled.AudioFormat;
00032
00039 public class Synthesizer extends MEAPUtil
00040 {
00041 EDLFile edlFile;
00042 String outFile = null;
00043 AudioWriter output;
00044
00045
00046 double[] outSamples;
00047 int outSamplesLength;
00048
00049 public Synthesizer(String infile, String outfile)
00050 {
00051 this(new EDLFile(infile), outfile);
00052 }
00053
00054 public Synthesizer(EDLFile edl, String outfile)
00055 {
00056 edlFile = edl;
00057 outFile = outfile;
00058 }
00059
00060
00061 public void printUsageAndExit()
00062 {
00063 System.out.println("Usage: Synthesizer [-options] file.edl \n\n" +
00064 " where options include:\n" +
00065 " -o output_file output sound file (defaults to line out)\n" +
00066 "");
00067 System.exit(0);
00068 }
00069
00073 public Synthesizer(String[] args)
00074 {
00075 if(args.length == 0)
00076 printUsageAndExit();
00077
00078
00079 Getopt opt = new Getopt("Synthesizer", args, "o:");
00080 opt.setOpterr(false);
00081
00082 int c = -1;
00083 while ((c = opt.getopt()) != -1)
00084 {
00085 switch(c)
00086 {
00087 case 'o':
00088 outFile = opt.getOptarg();
00089 break;
00090 case '?':
00091 printUsageAndExit();
00092 break;
00093 default:
00094 System.out.print("getopt() returned " + c + "\n");
00095 }
00096 }
00097
00098
00099 int ind = opt.getOptind();
00100 if(ind > args.length)
00101 printUsageAndExit();
00102
00103 edlFile = new EDLFile(args[ind]);
00104
00105 System.out.println("Synthesizing " + outFile + " from " + args[ind] + ".");
00106 }
00107
00108
00109 public void setup() throws IOException, ParserException
00110 {
00111 if(!edlFile.haveReadFile)
00112 edlFile.readFile();
00113
00114 if(edlFile.chunks.size() == 0)
00115 throw new ParserException(edlFile.filename, "No chunks found");
00116 }
00117
00118 public void processEDL() throws IOException
00119 {
00120
00121 EDLChunk ch = (EDLChunk)edlFile.chunks.get(0);
00122 outSamples = new double[(int)(samplingRate*(ch.dstTime + ch.length))];
00123 outSamplesLength = outSamples.length;
00124
00125 Arrays.fill(outSamples, 0);
00126
00127
00128 ((Heap)(edlFile.chunks)).sort();
00129
00130 Iterator i = edlFile.chunks.iterator();
00131 int overlapAccumulator = 0;
00132 while(i.hasNext())
00133 {
00134 EDLChunk currChunk = (EDLChunk)i.next();
00135 double[] chunkSamples = currChunk.getSamples(format);
00136 int offset = (int)(currChunk.dstTime*samplingRate) - overlapAccumulator;
00137
00138
00139 for(int c = 0; c < currChunk.commands.size(); c++)
00140 {
00141 String cmd = (String)currChunk.commands.get(c);
00142 if(cmd.equalsIgnoreCase("reverse"))
00143 {
00144
00145 for(int x = 0; x < chunkSamples.length/2; x++)
00146 {
00147 double tmp = chunkSamples[chunkSamples.length-x-1];
00148 chunkSamples[chunkSamples.length-x-1] = chunkSamples[x];
00149 chunkSamples[x] = tmp;
00150 }
00151 }
00152
00153
00154
00155
00156 else if(cmd.toLowerCase().startsWith("crossfade"))
00157 {
00158 int overlap = (int)(.001*samplingRate);
00159
00160 String[] overlapTime = cmd.split("[(),\\s]");
00161
00162 if(overlapTime.length >= 2)
00163 overlap = (int)(samplingRate*Double.parseDouble(overlapTime[1]));
00164
00165 if(offset - overlap > 0)
00166 {
00167 offset -= overlap;
00168 overlapAccumulator += overlap;
00169 }
00170 }
00171
00172
00173
00174
00175 else if(cmd.toLowerCase().startsWith("crossfade") || cmd.toLowerCase().startsWith("fade"))
00176 {
00177 double fadeInTime = .001;
00178 double fadeOutTime = .001;
00179
00180 String[] fadeTimes = cmd.split("[(),\\s]");
00181
00182 if(fadeTimes.length == 2)
00183 {
00184 fadeInTime = Double.parseDouble(fadeTimes[1]);
00185 fadeOutTime = fadeInTime;
00186 }
00187 else if(fadeTimes.length > 2)
00188 {
00189 fadeInTime = Double.parseDouble(fadeTimes[1]);
00190 fadeOutTime = Double.parseDouble(fadeTimes[2]);
00191 }
00192
00193
00194
00195
00196 int fadeInWinSize = (int)(fadeInTime*samplingRate);
00197 for(int x = 0; x < fadeInWinSize; x++)
00198 {
00199 if(x < chunkSamples.length)
00200 chunkSamples[x] *= (double)x / (double)fadeInWinSize;
00201 }
00202
00203 int fadeOutWinSize = (int)(fadeOutTime*samplingRate);
00204 for(int x = 0; x < fadeOutWinSize; x++)
00205 {
00206 if(chunkSamples.length - 1 - x > 0)
00207 chunkSamples[chunkSamples.length - 1 - x]
00208 *= (double)x / (double)fadeOutWinSize;
00209 }
00210 }
00211 else
00212 System.out.println("Ignored unknown command: " + cmd);
00213 }
00214
00215 for(int x = 0; x < chunkSamples.length; x++)
00216 if(offset + x < outSamples.length)
00217 outSamples[offset + x] += chunkSamples[x];
00218 }
00219
00220 outSamplesLength -= overlapAccumulator;
00221 }
00222
00226 public void go()
00227 {
00228 format = new AudioFormat(samplingRate, bitsPerSamp, numChannels,
00229 signed, bigEndian);
00230 try
00231 {
00232 setup();
00233 processEDL();
00234
00235
00236
00237 AudioWriter aw = openAudioWriter(outFile);
00238
00239 aw.write(outSamples, outSamplesLength);
00240 aw.close();
00241 }
00242 catch(Exception e)
00243 {
00244 e.printStackTrace();
00245 }
00246 }
00247
00248 public static void main(String[] args)
00249 {
00250 Synthesizer o2or = new Synthesizer(args);
00251 long startTime = System.currentTimeMillis();
00252 o2or.go();
00253 System.out.println("Done. Took " +
00254 ((System.currentTimeMillis() - startTime)/1000.0)
00255 + "s");
00256 System.exit(0);
00257 }
00258 }