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 
24 void encode(CommandLineArgs args) {
25   assert(args.raw, "Non-raw mode is not supported currently");
26 
27   // Create the OPUS Encoder
28   Encoder enc = new Encoder(args.frameRate, args.channels);
29 
30   // Set some base options
31   enc.setBandwidth(Bandwidth.FULLBAND);
32   enc.setBitrate(args.bitrate);
33   enc.setInbandFEC(args.fec);
34   enc.setPacketLossPercent(args.packetLossPercent);
35 
36   File input;
37   if (args.input == "pipe:0") {
38     input = std.stdio.stdin;
39   } else {
40     input = File(args.input, "r");
41   }
42 
43   File output;
44   if (args.output == "pipe:1") {
45     output = std.stdio.stdout;
46   } else {
47     output = File(args.output, "w");
48   }
49 
50   short[] rawData;
51   rawData.length = (args.frameSize * args.channels);
52 
53   while (true) {
54     const short[] data = input.rawRead(rawData);
55 
56     if (data.length != rawData.length) {
57       break;
58     }
59 
60     Frame(enc.encode(data, args.frameSize)).write(output);
61   }
62 
63   output.close();
64 }
65 
66 void main(string[] rawargs) {
67   CommandLineArgs args;
68 
69   auto opts = getopt(
70     rawargs,
71     "channels|ac", "Number of audio channels (1 = mono, 2 = stero)", &args.channels,
72     "rate|ar", "Audio sampling rate", &args.frameRate,
73     "size|as", "Audio frame size", &args.frameSize,
74     "rate|ab", "Audio bitrate", &args.bitrate,
75     "fec", "Enable FEC (forward error correction)", &args.fec,
76     "packet-loss-percent", "FEC packet loss percent", &args.packetLossPercent,
77     "raw", "Don't include DCA metadata/magic bytes (raw OPUS)", &args.raw,
78     "input", "Input file or pipe", &args.input,
79     "output", "Output file or pipe", &args.output,
80   );
81 
82   if (opts.helpWanted) {
83     return defaultGetoptPrinter("DCAD - a DCA audio encoder", opts.options);
84   }
85 
86   encode(args);
87 
88 }