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 }