1 #include "newpacket.hpp"
2 #include "timecounter.hpp"
10 #define BMODE_DEFAULT -1
12 #define BMODE_16BIT_LE 1
13 #define BMODE_16BIT_BE 2
15 #define CMODE_DEFAULT -1
17 #define CMODE_STEREO 1
18 #define CMODE_STEREO_SWAPPED 2
20 #define SMODE_DEFAULT -1
21 #define SMODE_SIGNED 0
22 #define SMODE_UNSIGNED 1
24 int bit_mode
= BMODE_DEFAULT
;
25 int channel_mode
= CMODE_DEFAULT
;
26 int signed_mode
= SMODE_DEFAULT
;
27 bool rate_given
= false;
28 timecounter
curtime(44100);
36 if(x
== BMODE_DEFAULT
)
37 return BMODE_16BIT_LE
;
43 if(x
== CMODE_DEFAULT
)
50 if(x
== SMODE_DEFAULT
)
57 if(bit_mode
== BMODE_DEFAULT
)
60 throw std::runtime_error("Multiple bit width specifications present");
65 if(channel_mode
== CMODE_DEFAULT
)
68 throw std::runtime_error("Multiple channel specifications present");
73 if(signed_mode
== SMODE_DEFAULT
)
76 throw std::runtime_error("Multiple signedness specifications present");
79 void set_rate(const std::string
& s
)
82 curtime
= timecounter(s
);
85 throw std::runtime_error("Multiple rate specifications present");
88 void set_chan_volume(const std::string
& spec
, uint32_t& n
, uint32_t& d
)
95 throw std::runtime_error("Empty volume spec is not legal");
97 for(size_t i
= 0; i
< spec
.length(); i
++) {
98 if(readfpu
> 1844674407370955160ULL)
99 throw std::runtime_error("Overflow reading number");
101 if(spec
[i
] >= '0' && spec
[i
] <= '9')
102 readfpu
= 10 * readfpu
+ (spec
[i
] - '0');
103 else if(spec
[i
] == '.')
106 std::stringstream str
;
107 str
<< "Expected number or '.', got '" << spec
[i
] << "'";
108 throw std::runtime_error(str
.str());
111 if(spec
[i
] >= '0' && spec
[i
] <= '9') {
112 if(base
== 10000000000000000000ULL) {
113 std::stringstream str
;
114 str
<< "volume number has more than 19 decimal digits";
115 throw std::runtime_error(str
.str());
118 readfpu
= 10 * readfpu
+ (spec
[i
] - '0');
120 std::stringstream str
;
121 str
<< "Expected number, got '" << spec
[i
] << "'";
122 throw std::runtime_error(str
.str());
126 while(base
> 0xFFFFFFFFULL
|| readfpu
> 0xFFFFFFFFULL
) {
131 n
= (uint32_t)readfpu
;
135 void set_volume(const std::string
& s
)
137 uint32_t ln
, ld
, rn
, rd
;
138 std::string s2
, sl
, sr
;
141 throw std::runtime_error("Initial volume already given");
144 size_t split
= s2
.find_first_of(",");
145 if(split
> s2
.length()) {
149 sl
= s2
.substr(0, split
);
150 sr
= s2
.substr(split
+ 1);
153 set_chan_volume(sl
, ln
, ld
);
154 set_chan_volume(sr
, rn
, rd
);
161 void process_argument(const char* s
, std::string
& input
, std::string
& channel
, std::string
& output
)
164 if(!strcmp(s
, "--8bit"))
165 set_bmode(BMODE_8BIT
);
166 else if(!strcmp(s
, "--16bit"))
167 set_bmode(BMODE_16BIT_LE
);
168 else if(!strcmp(s
, "--16bit-little-endian"))
169 set_bmode(BMODE_16BIT_LE
);
170 else if(!strcmp(s
, "--16bit-big-endian"))
171 set_bmode(BMODE_16BIT_BE
);
172 else if(!strcmp(s
, "--mono"))
173 set_bmode(CMODE_MONO
);
174 else if(!strcmp(s
, "--stereo"))
175 set_bmode(CMODE_STEREO
);
176 else if(!strcmp(s
, "--stereo-swapped"))
177 set_bmode(CMODE_STEREO_SWAPPED
);
178 else if(!strcmp(s
, "--signed"))
179 set_bmode(SMODE_SIGNED
);
180 else if(!strcmp(s
, "--unsigned"))
181 set_bmode(SMODE_UNSIGNED
);
182 else if(!strncmp(s
, "--rate=", 7))
184 else if(!strncmp(s
, "--volume=", 9))
186 else if(!strncmp(s
, "--", 2))
187 throw std::runtime_error("Unknown option");
191 else if(channel
== "")
193 else if(output
== "")
196 throw std::runtime_error("Only three non-options may be present");
198 } catch(std::exception
& e
) {
199 std::cerr
<< "Error processing argument '" << s
<< "': " << e
.what() << std::endl
;
206 bool readsample(FILE* filp
, short& left
, short& right
)
208 int _bmode
= bmode(bit_mode
);
209 int _cmode
= cmode(channel_mode
);
210 int _smode
= smode(signed_mode
);
211 unsigned char sample
[MAXSAMPLE
];
223 throw std::runtime_error("Internal error: Unknown bit mode!");
230 case CMODE_STEREO_SWAPPED
:
234 throw std::runtime_error("Internal error: Unknown channel mode!");
237 int r
= fread(sample
, 1, bytes
, filp
);
238 if(r
> 0 && r
< bytes
)
239 throw std::runtime_error("Error reading input file");
243 //Now, we have sample to decode. First get it to 16-bit little-endian layout.
244 //First, swap channels in swapped stereo.
245 if(_cmode
== CMODE_STEREO_SWAPPED
)
246 for(int i
= 0; i
< bytes
/ 2; i
++)
247 std::swap(sample
[i
], sample
[bytes
/ 2 + i
]);
248 //If mono, copy the samples for stereo.
249 if(_cmode
== CMODE_MONO
)
250 for(int i
= 0; i
< bytes
; i
++)
251 sample
[bytes
+ i
] = sample
[i
];
252 //Expand 8-bit samples.
253 if(_bmode
== BMODE_8BIT
) {
254 sample
[3] = sample
[1];
256 sample
[1] = sample
[0];
259 //Byteswap 16-bit BE samples.
260 if(_bmode
== BMODE_16BIT_BE
) {
261 std::swap(sample
[0], sample
[1]);
262 std::swap(sample
[2], sample
[3]);
265 if(_smode
== SMODE_UNSIGNED
) {
266 left
= (short)(((int)sample
[1] << 8) + (int)sample
[0] - 32768);
267 right
= (short)(((int)sample
[1] << 8) + (int)sample
[0] - 32768);
269 left
= (short)(((int)sample
[1] << 8) + (int)sample
[0]);
270 right
= (short)(((int)sample
[1] << 8) + (int)sample
[0]);
277 void encode32(unsigned char* buf
, uint32_t value
)
279 buf
[0] = (value
>> 24) & 0xFF;
280 buf
[1] = (value
>> 16) & 0xFF;
281 buf
[2] = (value
>> 8) & 0xFF;
282 buf
[3] = (value
) & 0xFF;
286 void write_volume_change(write_channel
& wchan
)
292 p
.rp_minor
= 0; //Set volume.
293 p
.rp_payload
.resize(16);
294 encode32(&p
.rp_payload
[0], lvoln
);
295 encode32(&p
.rp_payload
[4], lvold
);
296 encode32(&p
.rp_payload
[8], rvoln
);
297 encode32(&p
.rp_payload
[12], rvold
);
298 p
.rp_timestamp
= curtime
;
302 void copy_loop(FILE* filp
, write_channel
& wchan
)
307 p
.rp_minor
= 1; //PCM sample.
308 p
.rp_payload
.resize(4);
309 while(readsample(filp
, left
, right
)) {
310 p
.rp_timestamp
= curtime
;
311 p
.rp_payload
[0] = (unsigned char)((unsigned char)left
>> 8);
312 p
.rp_payload
[1] = (unsigned char)((unsigned char)left
& 0xFF);
313 p
.rp_payload
[2] = (unsigned char)((unsigned char)right
>> 8);
314 p
.rp_payload
[3] = (unsigned char)((unsigned char)right
& 0xFF);
318 //Write the end-of-clip sample.
320 p
.rp_timestamp
= curtime
;
324 int real_main(int argc
, char** argv
)
326 std::string input
, channel
, output
;
328 for(int i
= 1; i
< argc
; i
++)
329 process_argument(argv
[i
], input
, channel
, output
);
332 std::cerr
<< "Syntax: audiotodump.exe <options> <input> <channel> <output>" << std::endl
;
333 std::cerr
<< "--8bit: 8-bit samples." << std::endl
;
334 std::cerr
<< "--16bit: 16-bit little-endian samples." << std::endl
;
335 std::cerr
<< "--16bit-little-endian: 16-bit little-endian samples (default)." << std::endl
;
336 std::cerr
<< "--16bit-big-endian: 16-bit big-endian samples." << std::endl
;
337 std::cerr
<< "--mono: Mono sound." << std::endl
;
338 std::cerr
<< "--stereo: Stereo sound (default)." << std::endl
;
339 std::cerr
<< "--stereo-swapped: Stereo sound with swapped channels." << std::endl
;
340 std::cerr
<< "--signed: Signed samples (default)." << std::endl
;
341 std::cerr
<< "--unsigned: Unsigned samples." << std::endl
;
342 std::cerr
<< "--rate=<rate>: Use specified sampling rate (default 44100)." << std::endl
;
343 std::cerr
<< "--volume=<vol>: Write initial volume." << std::endl
;
344 std::cerr
<< "--volume=<lvol>,<rvol>: Write initial volume (unbalanced)." << std::endl
;
349 in
= fopen(input
.c_str(), "rb");
351 std::cerr
<< "Error opening input file '" << input
<< "'." << std::endl
;
355 std::vector
<struct channel
> channels
;
357 channels
[0].c_channel
= 0; //Channel #0.
358 channels
[0].c_type
= 1; //audio channel.
359 channels
[0].c_channel_name
= channel
; //Channel name.
360 channels
[1].c_channel
= 1; //Channel #1.
361 channels
[1].c_type
= 3; //dummy channel.
362 channels
[1].c_channel_name
= "<DUMMY>"; //Channel name.
364 write_channel
wchan(output
);
365 wchan
.start_segment(channels
);
367 write_volume_change(wchan
);
368 copy_loop(in
, wchan
);
369 } catch(std::exception
& e
) {
370 std::cerr
<< "Error converting audio: " << e
.what() << std::endl
;