1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // container-voc.c - a parser/builder for a container of Creative Voice File.
4 //
5 // Copyright (c) 2018 Takashi Sakamoto <o-takashi@sakamocchi.jp>
6 //
7 // Licensed under the terms of the GNU General Public License, version 2.
8
9 #include "container.h"
10 #include "misc.h"
11
12 // Not portable to all of UNIX platforms.
13 #include <endian.h>
14
15 // References:
16 // - http://sox.sourceforge.net/
17
18 #define VOC_MAGIC "Creative Voice File\x1a"
19 #define VOC_VERSION_1_10 0x010a
20 #define VOC_VERSION_1_20 0x0114
21
22 enum block_type {
23 BLOCK_TYPE_TERMINATOR = 0x00,
24 BLOCK_TYPE_V110_DATA = 0x01,
25 BLOCK_TYPE_CONTINUOUS_DATA = 0x02,
26 BLOCK_TYPE_SILENCE = 0x03,
27 BLOCK_TYPE_MARKER = 0x04,
28 BLOCK_TYPE_STRING = 0x05,
29 BLOCK_TYPE_REPEAT_START = 0x06,
30 BLOCK_TYPE_REPEAT_END = 0x07,
31 BLOCK_TYPE_EXTENDED_V110_FORMAT = 0x08,
32 BLOCK_TYPE_V120_DATA = 0x09,
33 };
34
35 enum code_id {
36 // Version 1.10.
37 CODE_ID_GENERIC_MBLA_U8 = 0x00,
38 CODE_ID_CREATIVE_ADPCM_8BIT_TO_4BIT_LE = 0x01,
39 CODE_ID_CREATIVE_ADPCM_8BIT_TO_3BIT_LE = 0x02,
40 CODE_ID_CREATIVE_ADPCM_8BIT_TO_2BIT_LE = 0x03,
41 // Version 1.20.
42 CODE_ID_GENERIC_MBLA_S16_LE = 0x04,
43 CODE_ID_CCIT_A_LAW_LE = 0x06,
44 CODE_ID_CCIT_MU_LAW_LE = 0x07,
45 CODE_ID_CREATIVE_ADPCM_16BIT_TO_4BIT_LE = 0x2000,
46 };
47
48 struct format_map {
49 unsigned int minimal_version;
50 enum code_id code_id;
51 snd_pcm_format_t format;
52 };
53
54 static const struct format_map format_maps[] = {
55 {VOC_VERSION_1_10, CODE_ID_GENERIC_MBLA_U8, SND_PCM_FORMAT_U8},
56 {VOC_VERSION_1_20, CODE_ID_GENERIC_MBLA_S16_LE, SND_PCM_FORMAT_S16_LE},
57 {VOC_VERSION_1_20, CODE_ID_CCIT_A_LAW_LE, SND_PCM_FORMAT_A_LAW},
58 {VOC_VERSION_1_20, CODE_ID_CCIT_MU_LAW_LE, SND_PCM_FORMAT_MU_LAW},
59 // The other formats are not supported by ALSA.
60 };
61
62 struct container_header {
63 uint8_t magic[20];
64 uint16_t hdr_size;
65 uint16_t version;
66 uint16_t version_compr;
67 };
68
69 // A format for data blocks except for terminator type.
70 struct block_header {
71 uint8_t type;
72 uint8_t size[3];
73
74 uint8_t data[0];
75 };
76
77 // Data block for terminator type has an exceptional format.
78 struct block_terminator {
79 uint8_t type;
80 };
81
82 struct time_const {
83 unsigned int frames_per_second;
84 uint16_t code;
85 };
86
87 static const struct time_const v110_time_consts[] = {
88 {5512, 74},
89 {8000, 130},
90 {11025, 165},
91 {16000, 193},
92 {22050, 210},
93 {32000, 224},
94 {44100, 233},
95 {48000, 235},
96 {64000, 240},
97 // Time constant for the upper sampling rate is not identical.
98 };
99
100 static const struct time_const ex_v110_time_consts[] = {
101 {5512, 19092},
102 {8000, 33536},
103 {11025, 42317},
104 {16000, 49536},
105 {22050, 53927},
106 {32000, 57536},
107 {44100, 59732},
108 {48000, 60203},
109 {64000, 61536},
110 {88200, 62634},
111 {96000, 62870},
112 {176400, 64085},
113 {192000, 64203},
114 // This support up to 192.0 kHz. The rest is for cases with 2ch.
115 {352800, 64811},
116 {384000, 64870},
117 };
118
119 // v1.10 format:
120 // - monaural.
121 // - frames_per_second = 1,000,000 / (256 - time_const)
122 struct block_v110_data {
123 uint8_t type;
124 uint8_t size[3]; // Equals to (2 + the size of frames).
125
126 uint8_t time_const;
127 uint8_t code_id;
128 uint8_t frames[0]; // Aligned to little-endian.
129 };
130
131 struct block_continuous_data {
132 uint8_t type;
133 uint8_t size[3]; // Equals to the size of frames.
134
135 uint8_t frames[0]; // Aligned to little-endian.
136 };
137
138 // v1.10 format:
139 // - monaural.
140 // - frames_per_second = 1,000,000 / (256 - time_const).
141 struct block_silence {
142 uint8_t type;
143 uint8_t size[3]; // Equals to 3.
144
145 uint16_t frame_count;
146 uint8_t time_const;
147 };
148
149 struct block_marker {
150 uint8_t type;
151 uint8_t size[3]; // Equals to 2.
152
153 uint16_t mark;
154 };
155
156 struct block_string {
157 uint8_t type;
158 uint8_t size[3]; // Equals to the length of string with 0x00.
159
160 uint8_t chars[0];
161 };
162
163 struct block_repeat_start {
164 uint8_t type;
165 uint8_t size[3]; // Equals to 2.
166
167 uint16_t count;
168 };
169
170 struct block_repeat_end {
171 uint8_t type;
172 uint8_t size[3]; // Equals to 0.
173 };
174
175 // Extended v1.10 format:
176 // - manaural/stereo.
177 // - frames_per_second =
178 // 256,000,000 / (samples_per_frame * (65536 - time_const)).
179 // - Appear just before v110_data block.
180 struct block_extended_v110_format {
181 uint8_t type;
182 uint8_t size[3]; // Equals to 4.
183
184 uint16_t time_const;
185 uint8_t code_id;
186 uint8_t ch_mode; // 0 is monaural, 1 is stereo.
187 };
188
189 // v1.20 format:
190 // - monaural/stereo.
191 // - 8/16 bits_per_sample.
192 // - time_const is not used.
193 // - code_id is extended.
194 struct block_v120_format {
195 uint8_t type;
196 uint8_t size[3]; // Equals to (12 + ).
197
198 uint32_t frames_per_second;
199 uint8_t bits_per_sample;
200 uint8_t samples_per_frame;
201 uint16_t code_id;
202 uint8_t reserved[4];
203
204 uint8_t frames[0]; // Aligned to little-endian.
205 };
206
207 // Aligned to little endian order but 24 bits field.
parse_block_data_size(uint8_t fields[3])208 static uint32_t parse_block_data_size(uint8_t fields[3])
209 {
210 return (fields[2] << 16) | (fields[1] << 8) | fields[0];
211 }
212
build_block_data_size(uint8_t fields[3],unsigned int size)213 static void build_block_data_size(uint8_t fields[3], unsigned int size)
214 {
215 fields[0] = (size & 0x0000ff);
216 fields[1] = (size & 0x00ff00) >> 8;
217 fields[2] = (size & 0xff0000) >> 16;
218 }
219
build_time_constant(unsigned int frames_per_second,unsigned int samples_per_frame,uint16_t * code,bool extended)220 static int build_time_constant(unsigned int frames_per_second,
221 unsigned int samples_per_frame, uint16_t *code,
222 bool extended)
223 {
224 int i;
225
226 // 16 bits are available for this purpose.
227 if (extended) {
228 if (samples_per_frame > 2)
229 return -EINVAL;
230 frames_per_second *= samples_per_frame;
231
232 for (i = 0; i < ARRAY_SIZE(ex_v110_time_consts); ++i) {
233 if (ex_v110_time_consts[i].frames_per_second ==
234 frames_per_second)
235 break;
236 }
237 if (i < ARRAY_SIZE(ex_v110_time_consts) &&
238 frames_per_second <= 192000) {
239 *code = ex_v110_time_consts[i].code;
240 } else {
241 *code = 65536 - 256000000 / frames_per_second;
242 }
243 } else {
244 if (samples_per_frame != 1)
245 return -EINVAL;
246
247 for (i = 0; i < ARRAY_SIZE(v110_time_consts); ++i) {
248 if (v110_time_consts[i].frames_per_second ==
249 frames_per_second)
250 break;
251 }
252 // Should be within 8 bit.
253 if (i < ARRAY_SIZE(v110_time_consts))
254 *code = (uint8_t)v110_time_consts[i].code;
255 else
256 *code = 256 - 1000000 / frames_per_second;
257 }
258
259 return 0;
260 }
261
parse_time_constant(uint16_t code,unsigned int samples_per_frame,unsigned int * frames_per_second,bool extended)262 static unsigned int parse_time_constant(uint16_t code,
263 unsigned int samples_per_frame,
264 unsigned int *frames_per_second,
265 bool extended)
266 {
267 int i;
268
269 if (extended) {
270 if (samples_per_frame > 2)
271 return -EINVAL;
272
273 for (i = 0; i < ARRAY_SIZE(ex_v110_time_consts); ++i) {
274 if (ex_v110_time_consts[i].code == code ||
275 ex_v110_time_consts[i].code - 1 == code)
276 break;
277 }
278 if (i < ARRAY_SIZE(ex_v110_time_consts)) {
279 *frames_per_second =
280 ex_v110_time_consts[i].frames_per_second /
281 samples_per_frame;
282 } else {
283 *frames_per_second = 256000000 / samples_per_frame /
284 (65536 - code);
285 }
286 } else {
287 if (samples_per_frame != 1)
288 return -EINVAL;
289
290 for (i = 0; i < ARRAY_SIZE(v110_time_consts); ++i) {
291 if (v110_time_consts[i].code == code ||
292 v110_time_consts[i].code - 1 == code)
293 break;
294 }
295 if (i < ARRAY_SIZE(v110_time_consts)) {
296 *frames_per_second =
297 v110_time_consts[i].frames_per_second;
298 } else {
299 *frames_per_second = 1000000 / (256 - code);
300 }
301 }
302
303 return 0;
304 }
305
306 struct parser_state {
307 unsigned int version;
308 bool extended;
309
310 unsigned int frames_per_second;
311 unsigned int samples_per_frame;
312 unsigned int bytes_per_sample;
313 enum code_id code_id;
314 uint32_t byte_count;
315 };
316
parse_container_header(struct parser_state * state,struct container_header * header)317 static int parse_container_header(struct parser_state *state,
318 struct container_header *header)
319 {
320 uint16_t hdr_size;
321 uint16_t version;
322 uint16_t version_compr;
323
324 hdr_size = le16toh(header->hdr_size);
325 version = le16toh(header->version);
326 version_compr = le16toh(header->version_compr);
327
328 if (memcmp(header->magic, VOC_MAGIC, sizeof(header->magic)))
329 return -EIO;
330
331 if (hdr_size != sizeof(*header))
332 return -EIO;
333
334 if (version_compr != 0x1234 + ~version)
335 return -EIO;
336
337 if (version != VOC_VERSION_1_10 && version != VOC_VERSION_1_20)
338 return -EIO;
339
340 state->version = version;
341
342 return 0;
343 }
344
check_code_id(uint8_t code_id,unsigned int version)345 static bool check_code_id(uint8_t code_id, unsigned int version)
346 {
347 int i;
348
349 for (i = 0; i < ARRAY_SIZE(format_maps); ++i) {
350 if (code_id != format_maps[i].code_id)
351 continue;
352 if (version >= format_maps[i].minimal_version)
353 return true;
354 }
355
356 return false;
357 }
358
parse_v120_format_block(struct parser_state * state,struct block_v120_format * block)359 static int parse_v120_format_block(struct parser_state *state,
360 struct block_v120_format *block)
361 {
362 state->frames_per_second = le32toh(block->frames_per_second);
363 state->bytes_per_sample = block->bits_per_sample / 8;
364 state->samples_per_frame = block->samples_per_frame;
365 state->code_id = le16toh(block->code_id);
366 state->byte_count = parse_block_data_size(block->size) - 12;
367
368 if (!check_code_id(state->code_id, VOC_VERSION_1_20))
369 return -EIO;
370
371 return 0;
372 }
373
parse_extended_v110_format(struct parser_state * state,struct block_extended_v110_format * block)374 static int parse_extended_v110_format(struct parser_state *state,
375 struct block_extended_v110_format *block)
376 {
377 unsigned int time_const;
378 unsigned int frames_per_second;
379 int err;
380
381 state->code_id = block->code_id;
382 if (!check_code_id(state->code_id, VOC_VERSION_1_10))
383 return -EIO;
384
385 if (block->ch_mode == 0)
386 state->samples_per_frame = 1;
387 else if (block->ch_mode == 1)
388 state->samples_per_frame = 2;
389 else
390 return -EIO;
391
392 time_const = le16toh(block->time_const);
393 err = parse_time_constant(time_const, state->samples_per_frame,
394 &frames_per_second, true);
395 if (err < 0)
396 return err;
397 state->frames_per_second = frames_per_second;
398
399 state->extended = true;
400
401 return 0;
402 }
403
parse_v110_data(struct parser_state * state,struct block_v110_data * block)404 static int parse_v110_data(struct parser_state *state,
405 struct block_v110_data *block)
406 {
407 unsigned int time_const;
408 unsigned int frames_per_second;
409 int err;
410
411 if (!state->extended) {
412 state->code_id = block->code_id;
413 if (!check_code_id(state->code_id, VOC_VERSION_1_10))
414 return -EIO;
415
416 time_const = block->time_const;
417 err = parse_time_constant(time_const, 1, &frames_per_second,
418 false);
419 if (err < 0)
420 return err;
421 state->frames_per_second = frames_per_second;
422 state->samples_per_frame = 1;
423 }
424
425 state->bytes_per_sample = 1;
426 state->byte_count = parse_block_data_size(block->size) - 2;
427
428 return 0;
429 }
430
detect_container_version(struct container_context * cntr)431 static int detect_container_version(struct container_context *cntr)
432 {
433 struct parser_state *state = cntr->private_data;
434 struct container_header header = {0};
435 int err;
436
437 // 4 bytes were alread read to detect container type.
438 memcpy(&header.magic, cntr->magic, sizeof(cntr->magic));
439 err = container_recursive_read(cntr,
440 (char *)&header + sizeof(cntr->magic),
441 sizeof(header) - sizeof(cntr->magic));
442 if (err < 0)
443 return err;
444 if (cntr->eof)
445 return 0;
446
447 return parse_container_header(state, &header);
448 }
449
allocate_for_block_cache(struct container_context * cntr,struct block_header * header,void ** buf)450 static int allocate_for_block_cache(struct container_context *cntr,
451 struct block_header *header, void **buf)
452 {
453 uint32_t block_size;
454 char *cache;
455 int err;
456
457 if (header->type == BLOCK_TYPE_V110_DATA)
458 block_size = sizeof(struct block_v110_data);
459 else if (header->type == BLOCK_TYPE_CONTINUOUS_DATA)
460 block_size = sizeof(struct block_continuous_data);
461 else if (header->type == BLOCK_TYPE_EXTENDED_V110_FORMAT)
462 block_size = sizeof(struct block_extended_v110_format);
463 else if (header->type == BLOCK_TYPE_V120_DATA)
464 block_size = sizeof(struct block_v120_format);
465 else
466 block_size = parse_block_data_size(header->size);
467
468 cache = malloc(block_size);
469 if (cache == NULL)
470 return -ENOMEM;
471 memset(cache, 0, block_size);
472
473 memcpy(cache, header, sizeof(*header));
474 err = container_recursive_read(cntr, cache + sizeof(*header),
475 block_size - sizeof(*header));
476 if (err < 0) {
477 free(cache);
478 return err;
479 }
480 if (cntr->eof) {
481 free(cache);
482 return 0;
483 }
484
485 *buf = cache;
486
487 return 0;
488 }
489
cache_data_block(struct container_context * cntr,struct block_header * header,void ** buf)490 static int cache_data_block(struct container_context *cntr,
491 struct block_header *header, void **buf)
492 {
493 int err;
494
495 // Check type of this block.
496 err = container_recursive_read(cntr, &header->type,
497 sizeof(header->type));
498 if (err < 0)
499 return err;
500 if (cntr->eof)
501 return 0;
502
503 if (header->type > BLOCK_TYPE_V120_DATA)
504 return -EIO;
505 if (header->type == BLOCK_TYPE_TERMINATOR)
506 return 0;
507
508 // Check size of this block. If the block includes a batch of data,
509 err = container_recursive_read(cntr, &header->size,
510 sizeof(header->size));
511 if (err < 0)
512 return err;
513 if (cntr->eof)
514 return 0;
515
516 return allocate_for_block_cache(cntr, header, buf);
517 }
518
detect_format_block(struct container_context * cntr)519 static int detect_format_block(struct container_context *cntr)
520 {
521 struct parser_state *state = cntr->private_data;
522 struct block_header header;
523 void *buf;
524 int err;
525
526 again:
527 buf = NULL;
528 err = cache_data_block(cntr, &header, &buf);
529 if (err < 0)
530 return err;
531 if (buf) {
532 if (header.type == BLOCK_TYPE_EXTENDED_V110_FORMAT) {
533 err = parse_extended_v110_format(state, buf);
534 } else if (header.type == BLOCK_TYPE_V120_DATA) {
535 err = parse_v120_format_block(state, buf);
536 } else if (header.type == BLOCK_TYPE_V110_DATA) {
537 err = parse_v110_data(state, buf);
538 } else {
539 free(buf);
540 goto again;
541 }
542
543 free(buf);
544
545 if (err < 0)
546 return err;
547 }
548
549 // Expect to detect block_v110_data.
550 if (header.type == BLOCK_TYPE_EXTENDED_V110_FORMAT)
551 goto again;
552
553 return 0;
554 }
555
voc_parser_pre_process(struct container_context * cntr,snd_pcm_format_t * format,unsigned int * samples_per_frame,unsigned int * frames_per_second,uint64_t * byte_count)556 static int voc_parser_pre_process(struct container_context *cntr,
557 snd_pcm_format_t *format,
558 unsigned int *samples_per_frame,
559 unsigned int *frames_per_second,
560 uint64_t *byte_count)
561 {
562 struct parser_state *state = cntr->private_data;
563 int i;
564 int err;
565
566 err = detect_container_version(cntr);
567 if (err < 0)
568 return err;
569
570 err = detect_format_block(cntr);
571 if (err < 0)
572 return err;
573
574 for (i = 0; i < ARRAY_SIZE(format_maps); ++i) {
575 if (format_maps[i].code_id == state->code_id)
576 break;
577 }
578 if (i == ARRAY_SIZE(format_maps))
579 return -EINVAL;
580
581 *format = format_maps[i].format;
582 *samples_per_frame = state->samples_per_frame;
583 *frames_per_second = state->frames_per_second;
584
585 // This program handles PCM frames in this data block only.
586 *byte_count = state->byte_count;
587
588 return 0;
589 }
590
591 struct builder_state {
592 unsigned int version;
593 bool extended;
594 enum code_id code_id;
595
596 unsigned int samples_per_frame;
597 unsigned int bytes_per_sample;
598 };
599
write_container_header(struct container_context * cntr,struct container_header * header)600 static int write_container_header(struct container_context *cntr,
601 struct container_header *header)
602 {
603 struct builder_state *state = cntr->private_data;
604
605 // Process container header.
606 memcpy(header->magic, VOC_MAGIC, sizeof(header->magic));
607 header->hdr_size = htole16(sizeof(*header));
608 header->version = htole16(state->version);
609 header->version_compr = htole16(0x1234 + ~state->version);
610
611 return container_recursive_write(cntr, header, sizeof(*header));
612 }
613
write_v120_format_block(struct container_context * cntr,struct block_v120_format * block,unsigned int frames_per_second,uint64_t byte_count)614 static int write_v120_format_block(struct container_context *cntr,
615 struct block_v120_format *block,
616 unsigned int frames_per_second,
617 uint64_t byte_count)
618 {
619 struct builder_state *state = cntr->private_data;
620
621 block->type = BLOCK_TYPE_V120_DATA;
622 build_block_data_size(block->size, 12 + byte_count);
623
624 block->frames_per_second = htole32(frames_per_second);
625 block->bits_per_sample = state->bytes_per_sample * 8;
626 block->samples_per_frame = state->samples_per_frame;
627 block->code_id = htole16(state->code_id);
628
629 return container_recursive_write(cntr, block, sizeof(*block));
630 }
631
write_extended_v110_format_block(struct container_context * cntr,unsigned int frames_per_second,struct block_extended_v110_format * block)632 static int write_extended_v110_format_block(struct container_context *cntr,
633 unsigned int frames_per_second,
634 struct block_extended_v110_format *block)
635 {
636 struct builder_state *state = cntr->private_data;
637 uint16_t time_const;
638 int err;
639
640 block->type = BLOCK_TYPE_EXTENDED_V110_FORMAT;
641 build_block_data_size(block->size, 4);
642
643 // 16 bits are available for this purpose.
644 err = build_time_constant(frames_per_second, state->samples_per_frame,
645 &time_const, true);
646 if (err < 0)
647 return err;
648 block->time_const = htole16(time_const);
649 block->code_id = htole16(state->code_id);
650
651 if (state->samples_per_frame == 1)
652 block->ch_mode = 0;
653 else
654 block->ch_mode = 1;
655
656 return container_recursive_write(cntr, block, sizeof(*block));
657 }
658
write_v110_format_block(struct container_context * cntr,struct block_v110_data * block,unsigned int frames_per_second,uint64_t byte_count)659 static int write_v110_format_block(struct container_context *cntr,
660 struct block_v110_data *block,
661 unsigned int frames_per_second,
662 uint64_t byte_count)
663 {
664 struct builder_state *state = cntr->private_data;
665 uint16_t time_const;
666 int err;
667
668 block->type = BLOCK_TYPE_V110_DATA;
669 build_block_data_size(block->size, 2 + byte_count);
670
671 // These fields were obsoleted by extension.
672 err = build_time_constant(frames_per_second, 1, &time_const, false);
673 if (err < 0)
674 return err;
675 block->time_const = (uint8_t)time_const;
676 block->code_id = state->code_id;
677 return container_recursive_write(cntr, block, sizeof(*block));
678 }
679
write_data_blocks(struct container_context * cntr,unsigned int frames_per_second,uint64_t byte_count)680 static int write_data_blocks(struct container_context *cntr,
681 unsigned int frames_per_second,
682 uint64_t byte_count)
683 {
684 union {
685 struct container_header header;
686 struct block_v110_data v110_data;
687 struct block_extended_v110_format extended_v110_format;
688 struct block_v120_format v120_format;
689 } buf = {0};
690 struct builder_state *state = cntr->private_data;
691 int err;
692
693 err = write_container_header(cntr, &buf.header);
694 if (err < 0)
695 return err;
696
697 if (state->version == VOC_VERSION_1_20) {
698 err = write_v120_format_block(cntr, &buf.v120_format,
699 frames_per_second, byte_count);
700 } else {
701 if (state->extended) {
702 err = write_extended_v110_format_block(cntr,
703 frames_per_second,
704 &buf.extended_v110_format);
705 if (err < 0)
706 return err;
707 }
708 err = write_v110_format_block(cntr, &buf.v110_data,
709 frames_per_second, byte_count);
710 }
711
712 return err;
713 }
714
voc_builder_pre_process(struct container_context * cntr,snd_pcm_format_t * format,unsigned int * samples_per_frame,unsigned int * frames_per_second,uint64_t * byte_count)715 static int voc_builder_pre_process(struct container_context *cntr,
716 snd_pcm_format_t *format,
717 unsigned int *samples_per_frame,
718 unsigned int *frames_per_second,
719 uint64_t *byte_count)
720 {
721 struct builder_state *state = cntr->private_data;
722 int i;
723
724 // Validate parameters.
725 for (i = 0; i < ARRAY_SIZE(format_maps); ++i) {
726 if (format_maps[i].format == *format)
727 break;
728 }
729 if (i == ARRAY_SIZE(format_maps))
730 return -EINVAL;
731 state->code_id = format_maps[i].code_id;
732
733 // Decide container version.
734 if (*samples_per_frame > 2)
735 state->version = VOC_VERSION_1_20;
736 else
737 state->version = format_maps[i].minimal_version;
738 if (state->version == VOC_VERSION_1_10) {
739 if (*samples_per_frame == 2) {
740 for (i = 0;
741 i < ARRAY_SIZE(ex_v110_time_consts); ++i) {
742 if (ex_v110_time_consts[i].frames_per_second ==
743 *frames_per_second)
744 break;
745 }
746 if (i == ARRAY_SIZE(ex_v110_time_consts))
747 state->version = VOC_VERSION_1_20;
748 else
749 state->extended = true;
750 } else {
751 for (i = 0; i < ARRAY_SIZE(v110_time_consts); ++i) {
752 if (v110_time_consts[i].frames_per_second ==
753 *frames_per_second)
754 break;
755 }
756 if (i == ARRAY_SIZE(v110_time_consts))
757 state->version = VOC_VERSION_1_20;
758 }
759 }
760
761 state->bytes_per_sample = snd_pcm_format_physical_width(*format) / 8;
762 state->samples_per_frame = *samples_per_frame;
763
764 return write_data_blocks(cntr, *frames_per_second, *byte_count);
765 }
766
write_block_terminator(struct container_context * cntr)767 static int write_block_terminator(struct container_context *cntr)
768 {
769 struct block_terminator block = {0};
770
771 block.type = BLOCK_TYPE_TERMINATOR;
772 return container_recursive_write(cntr, &block, sizeof(block));
773 }
774
write_data_size(struct container_context * cntr,uint64_t byte_count)775 static int write_data_size(struct container_context *cntr, uint64_t byte_count)
776 {
777 struct builder_state *state = cntr->private_data;
778 off64_t offset;
779 uint8_t size_field[3];
780 int err;
781
782 offset = sizeof(struct container_header) + sizeof(uint8_t);
783 if (state->version == VOC_VERSION_1_10 && state->extended)
784 offset += sizeof(struct block_extended_v110_format);
785 err = container_seek_offset(cntr, offset);
786 if (err < 0)
787 return err;
788
789 if (state->version == VOC_VERSION_1_10)
790 offset = 2;
791 else
792 offset = 12;
793
794 if (byte_count > cntr->max_size - offset)
795 byte_count = cntr->max_size;
796 else
797 byte_count += offset;
798 build_block_data_size(size_field, byte_count);
799
800 return container_recursive_write(cntr, &size_field, sizeof(size_field));
801 }
802
voc_builder_post_process(struct container_context * cntr,uint64_t handled_byte_count)803 static int voc_builder_post_process(struct container_context *cntr,
804 uint64_t handled_byte_count)
805 {
806 int err;
807
808 err = write_block_terminator(cntr);
809 if (err < 0)
810 return err;
811
812 return write_data_size(cntr, handled_byte_count);
813 }
814
815 const struct container_parser container_parser_voc = {
816 .format = CONTAINER_FORMAT_VOC,
817 .magic = VOC_MAGIC,
818 .max_size = 0xffffff - // = UINT24_MAX.
819 sizeof(struct block_terminator),
820 .ops = {
821 .pre_process = voc_parser_pre_process,
822 },
823 .private_size = sizeof(struct parser_state),
824 };
825
826 const struct container_builder container_builder_voc = {
827 .format = CONTAINER_FORMAT_VOC,
828 .max_size = 0xffffff - // = UINT24_MAX.
829 sizeof(struct block_terminator),
830 .ops = {
831 .pre_process = voc_builder_pre_process,
832 .post_process = voc_builder_post_process,
833 },
834 .private_size = sizeof(struct builder_state),
835 };
836