1 module main;
2 
3 import std.stdio;
4 import std.file;
5 
6 import audioformats;
7 import dplug.core;
8 import core.stdc.stdlib;
9 
10 // Currently it can take a MOD and dump patterns in the wrong order...
11 // Is or seek function conceptually correct?
12 
13 void main(string[] args)
14 {
15     if (args.length != 3)
16         throw new Exception("usage: dump-patterns input.{mod|xm} doubled.wav");
17 
18     string inputPath = args[1];
19     string outputPath = args[2];
20 
21     try
22     {
23 
24         AudioStream input, output;
25 
26         input.openFromFile(args[1]);
27         float sampleRate = input.getSamplerate();
28         int channels = input.getNumChannels();
29         long lengthFrames = input.getLengthInFrames();
30 
31         if (!input.isModule)
32             throw mallocNew!Exception("Must be a module");
33         if (!input.canSeek)
34             throw mallocNew!Exception("Must be seekable");
35 
36         float[] buf;
37         output.openToFile(outputPath, AudioFileFormat.wav, sampleRate, channels);
38 
39 
40         int patternCount = input.getModuleLength();
41 
42         for (int pattern = 0; pattern < patternCount; ++pattern) // Note: that iterated patterns in order, but that's not the right order in the MOD
43         {
44             input.seekPosition(pattern, 0);
45 
46             // how many remaining frames in this pattern?
47             int remain = cast(int) input.framesRemainingInPattern();
48             buf.length = remain * channels;
49             int framesRead = input.readSamplesFloat(buf); // this should read the whole pattern
50             assert( (framesRead == remain) );
51 
52             output.writeSamplesFloat(buf[0..framesRead*channels]);
53         }
54 
55         output.destroy();
56         
57         writefln("=> %s patterns decoded and encoded to %s", patternCount, outputPath);
58     }
59     catch(Exception e)
60     {
61         writeln(e.msg);
62         destroyFree(e);
63     }
64 }