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