1 module main; 2 3 import std.stdio, 4 std.getopt; 5 6 import dcad.types; 7 import opus.encoder; 8 9 struct CommandLineArgs { 10 int channels = 2; 11 int frameRate = 48000; 12 int frameSize = 960; 13 int bitrate = 128; 14 15 bool fec = true; 16 int packetLossPercent = 30; 17 18 bool raw = true; 19 20 string input = "pipe:0"; 21 string output = "pipe:1"; 22 23 bool flush = true; 24 } 25 26 void encode(CommandLineArgs args) { 27 assert(args.raw, "Non-raw mode is not supported currently"); 28 29 // Create the OPUS Encoder 30 Encoder enc = new Encoder(args.frameRate, args.channels); 31 32 // Set some base options 33 enc.setBandwidth(Bandwidth.FULLBAND); 34 enc.setBitrate(args.bitrate); 35 enc.setInbandFEC(args.fec); 36 enc.setPacketLossPercent(args.packetLossPercent); 37 38 File input; 39 if (args.input == "pipe:0") { 40 input = std.stdio.stdin; 41 } else { 42 input = File(args.input, "r"); 43 } 44 45 File output; 46 if (args.output == "pipe:1") { 47 output = std.stdio.stdout; 48 } else { 49 output = File(args.output, "w"); 50 } 51 52 short[] rawData; 53 rawData.length = (args.frameSize * args.channels); 54 55 while (true) { 56 const short[] data = input.rawRead(rawData); 57 58 if (data.length != rawData.length) { 59 break; 60 } 61 62 Frame(enc.encode(data, args.frameSize)).write(output); 63 64 if (args.flush) { 65 output.flush(); 66 } 67 } 68 69 output.flush(); 70 output.close(); 71 } 72 73 void main(string[] rawargs) { 74 CommandLineArgs args; 75 76 auto opts = getopt( 77 rawargs, 78 "channels|ac", "Number of audio channels (1 = mono, 2 = stero)", &args.channels, 79 "rate|ar", "Audio sampling rate", &args.frameRate, 80 "size|as", "Audio frame size", &args.frameSize, 81 "bitrate|ab", "Audio bitrate", &args.bitrate, 82 "fec", "Enable FEC (forward error correction)", &args.fec, 83 "packet-loss-percent", "FEC packet loss percent", &args.packetLossPercent, 84 "raw", "Don't include DCA metadata/magic bytes (raw OPUS)", &args.raw, 85 "input", "Input file or pipe", &args.input, 86 "output", "Output file or pipe", &args.output, 87 "flush", "Flush output after each frame, assists in real time pipelines", &args.flush, 88 ); 89 90 if (opts.helpWanted) { 91 return defaultGetoptPrinter("DCAD - a DCA audio encoder", opts.options); 92 } 93 94 encode(args); 95 96 }