1// SPDX-License-Identifier: GPL-2.0 2// 3// container-riff-wave.c - a parser/builder for a container of RIFF/Wave 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// - 'Resource Interchange File Format (RIFF)' at msdn.microsoft.com 17// - 'Multiple channel audio data and WAVE files' at msdn.microsoft.com 18// - RFC 2361 'WAVE and AVI Codec Registries' at ietf.org 19// - 'mmreg.h' in Wine project 20// - 'mmreg.h' in ReactOS project 21 22#define RIFF_MAGIC "RIF" // A common part. 23 24#define RIFF_CHUNK_ID_LE "RIFF" 25#define RIFF_CHUNK_ID_BE "RIFX" 26#define RIFF_FORM_WAVE "WAVE" 27#define FMT_SUBCHUNK_ID "fmt " 28#define DATA_SUBCHUNK_ID "data" 29 30// See 'WAVE and AVI Codec Registries (Historic Registry)' in 'iana.org'. 31// https://www.iana.org/assignments/wave-avi-codec-registry/ 32enum wave_format { 33 WAVE_FORMAT_PCM = 0x0001, 34 WAVE_FORMAT_ADPCM = 0x0002, 35 WAVE_FORMAT_IEEE_FLOAT = 0x0003, 36 WAVE_FORMAT_ALAW = 0x0006, 37 WAVE_FORMAT_MULAW = 0x0007, 38 WAVE_FORMAT_G723_ADPCM = 0x0014, 39 // The others are not supported. 40}; 41 42struct format_map { 43 enum wave_format wformat; 44 snd_pcm_format_t format; 45}; 46 47static const struct format_map format_maps[] = { 48 {WAVE_FORMAT_PCM, SND_PCM_FORMAT_U8}, 49 {WAVE_FORMAT_PCM, SND_PCM_FORMAT_S16_LE}, 50 {WAVE_FORMAT_PCM, SND_PCM_FORMAT_S16_BE}, 51 {WAVE_FORMAT_PCM, SND_PCM_FORMAT_S24_LE}, 52 {WAVE_FORMAT_PCM, SND_PCM_FORMAT_S24_BE}, 53 {WAVE_FORMAT_PCM, SND_PCM_FORMAT_S32_LE}, 54 {WAVE_FORMAT_PCM, SND_PCM_FORMAT_S32_BE}, 55 {WAVE_FORMAT_PCM, SND_PCM_FORMAT_S24_3LE}, 56 {WAVE_FORMAT_PCM, SND_PCM_FORMAT_S24_3BE}, 57 {WAVE_FORMAT_PCM, SND_PCM_FORMAT_S20_3LE}, 58 {WAVE_FORMAT_PCM, SND_PCM_FORMAT_S20_3BE}, 59 {WAVE_FORMAT_PCM, SND_PCM_FORMAT_S18_3LE}, 60 {WAVE_FORMAT_PCM, SND_PCM_FORMAT_S18_3BE}, 61 {WAVE_FORMAT_IEEE_FLOAT, SND_PCM_FORMAT_FLOAT_LE}, 62 {WAVE_FORMAT_IEEE_FLOAT, SND_PCM_FORMAT_FLOAT_BE}, 63 {WAVE_FORMAT_IEEE_FLOAT, SND_PCM_FORMAT_FLOAT64_LE}, 64 {WAVE_FORMAT_IEEE_FLOAT, SND_PCM_FORMAT_FLOAT64_BE}, 65 {WAVE_FORMAT_ALAW, SND_PCM_FORMAT_A_LAW}, 66 {WAVE_FORMAT_MULAW, SND_PCM_FORMAT_MU_LAW}, 67 // Below sample formats are not currently supported, due to width of 68 // its sample. 69 // - WAVE_FORMAT_ADPCM 70 // - WAVE_FORMAT_G723_ADPCM 71 // - WAVE_FORMAT_G723_ADPCM 72 // - WAVE_FORMAT_G723_ADPCM 73 // - WAVE_FORMAT_G723_ADPCM 74}; 75 76struct riff_chunk { 77 uint8_t id[4]; 78 uint32_t size; 79 80 uint8_t data[0]; 81}; 82 83struct riff_chunk_data { 84 uint8_t id[4]; 85 86 uint8_t subchunks[0]; 87}; 88 89struct riff_subchunk { 90 uint8_t id[4]; 91 uint32_t size; 92 93 uint8_t data[0]; 94}; 95 96struct wave_fmt_subchunk { 97 uint8_t id[4]; 98 uint32_t size; 99 100 uint16_t format; 101 uint16_t samples_per_frame; 102 uint32_t frames_per_second; 103 uint32_t average_bytes_per_second; 104 uint16_t bytes_per_frame; 105 uint16_t bits_per_sample; 106 uint8_t extension[0]; 107}; 108 109struct wave_data_subchunk { 110 uint8_t id[4]; 111 uint32_t size; 112 113 uint8_t frames[0]; 114}; 115 116struct parser_state { 117 bool be; 118 enum wave_format format; 119 unsigned int samples_per_frame; 120 unsigned int frames_per_second; 121 unsigned int average_bytes_per_second; 122 unsigned int bytes_per_frame; 123 unsigned int bytes_per_sample; 124 unsigned int avail_bits_in_sample; 125 unsigned int byte_count; 126}; 127 128static int parse_riff_chunk_header(struct parser_state *state, 129 struct riff_chunk *chunk, 130 uint64_t *byte_count) 131{ 132 if (!memcmp(chunk->id, RIFF_CHUNK_ID_BE, sizeof(chunk->id))) 133 state->be = true; 134 else if (!memcmp(chunk->id, RIFF_CHUNK_ID_LE, sizeof(chunk->id))) 135 state->be = false; 136 else 137 return -EINVAL; 138 139 if (state->be) 140 *byte_count = be32toh(chunk->size); 141 else 142 *byte_count = le32toh(chunk->size); 143 144 return 0; 145} 146 147static int parse_riff_chunk(struct container_context *cntr, 148 uint64_t *byte_count) 149{ 150 struct parser_state *state = cntr->private_data; 151 union { 152 struct riff_chunk chunk; 153 struct riff_chunk_data chunk_data; 154 } buf = {0}; 155 int err; 156 157 // Chunk header. 4 bytes were alread read to detect container type. 158 memcpy(buf.chunk.id, cntr->magic, sizeof(cntr->magic)); 159 err = container_recursive_read(cntr, 160 (char *)&buf.chunk + sizeof(cntr->magic), 161 sizeof(buf.chunk) - sizeof(cntr->magic)); 162 if (err < 0) 163 return err; 164 if (cntr->eof) 165 return 0; 166 167 err = parse_riff_chunk_header(state, &buf.chunk, byte_count); 168 if (err < 0) 169 return err; 170 171 // Chunk data header. 172 err = container_recursive_read(cntr, &buf, sizeof(buf.chunk_data)); 173 if (err < 0) 174 return err; 175 if (cntr->eof) 176 return 0; 177 178 if (memcmp(buf.chunk_data.id, RIFF_FORM_WAVE, 179 sizeof(buf.chunk_data.id))) 180 return -EINVAL; 181 182 return 0; 183} 184 185static int parse_wave_fmt_subchunk(struct parser_state *state, 186 struct wave_fmt_subchunk *subchunk) 187{ 188 if (state->be) { 189 state->format = be16toh(subchunk->format); 190 state->samples_per_frame = be16toh(subchunk->samples_per_frame); 191 state->frames_per_second = be32toh(subchunk->frames_per_second); 192 state->average_bytes_per_second = 193 be32toh(subchunk->average_bytes_per_second); 194 state->bytes_per_frame = be16toh(subchunk->bytes_per_frame); 195 state->avail_bits_in_sample = 196 be16toh(subchunk->bits_per_sample); 197 } else { 198 state->format = le16toh(subchunk->format); 199 state->samples_per_frame = le16toh(subchunk->samples_per_frame); 200 state->frames_per_second = le32toh(subchunk->frames_per_second); 201 state->average_bytes_per_second = 202 le32toh(subchunk->average_bytes_per_second); 203 state->bytes_per_frame = le16toh(subchunk->bytes_per_frame); 204 state->avail_bits_in_sample = 205 le16toh(subchunk->bits_per_sample); 206 } 207 208 if (state->average_bytes_per_second != 209 state->bytes_per_frame * state->frames_per_second) 210 return -EINVAL; 211 212 return 0; 213} 214 215static int parse_wave_data_subchunk(struct parser_state *state, 216 struct wave_data_subchunk *subchunk) 217{ 218 if (state->be) 219 state->byte_count = be32toh(subchunk->size); 220 else 221 state->byte_count = le32toh(subchunk->size); 222 223 return 0; 224} 225 226static int parse_wave_subchunk(struct container_context *cntr) 227{ 228 union { 229 struct riff_subchunk subchunk; 230 struct wave_fmt_subchunk fmt_subchunk; 231 struct wave_data_subchunk data_subchunk; 232 } buf = {0}; 233 enum { 234 SUBCHUNK_TYPE_UNKNOWN = -1, 235 SUBCHUNK_TYPE_FMT, 236 SUBCHUNK_TYPE_DATA, 237 } subchunk_type; 238 struct parser_state *state = cntr->private_data; 239 unsigned int required_size; 240 unsigned int subchunk_data_size; 241 int err; 242 243 while (1) { 244 err = container_recursive_read(cntr, &buf, 245 sizeof(buf.subchunk)); 246 if (err < 0) 247 return err; 248 if (cntr->eof) 249 return 0; 250 251 // Calculate the size of subchunk data. 252 if (state->be) 253 subchunk_data_size = be32toh(buf.subchunk.size); 254 else 255 subchunk_data_size = le32toh(buf.subchunk.size); 256 257 // Detect type of subchunk. 258 if (!memcmp(buf.subchunk.id, FMT_SUBCHUNK_ID, 259 sizeof(buf.subchunk.id))) { 260 subchunk_type = SUBCHUNK_TYPE_FMT; 261 } else if (!memcmp(buf.subchunk.id, DATA_SUBCHUNK_ID, 262 sizeof(buf.subchunk.id))) { 263 subchunk_type = SUBCHUNK_TYPE_DATA; 264 } else { 265 subchunk_type = SUBCHUNK_TYPE_UNKNOWN; 266 } 267 268 if (subchunk_type != SUBCHUNK_TYPE_UNKNOWN) { 269 // Parse data of this subchunk. 270 if (subchunk_type == SUBCHUNK_TYPE_FMT) { 271 required_size = 272 sizeof(struct wave_fmt_subchunk) - 273 sizeof(struct riff_chunk); 274 } else { 275 required_size = 276 sizeof(struct wave_data_subchunk)- 277 sizeof(struct riff_chunk); 278 } 279 280 if (subchunk_data_size < required_size) 281 return -EINVAL; 282 283 err = container_recursive_read(cntr, &buf.subchunk.data, 284 required_size); 285 if (err < 0) 286 return err; 287 if (cntr->eof) 288 return 0; 289 subchunk_data_size -= required_size; 290 291 if (subchunk_type == SUBCHUNK_TYPE_FMT) { 292 err = parse_wave_fmt_subchunk(state, 293 &buf.fmt_subchunk); 294 } else if (subchunk_type == SUBCHUNK_TYPE_DATA) { 295 err = parse_wave_data_subchunk(state, 296 &buf.data_subchunk); 297 } 298 if (err < 0) 299 return err; 300 301 // Found frame data. 302 if (subchunk_type == SUBCHUNK_TYPE_DATA) 303 break; 304 } 305 306 // Go to next subchunk. 307 while (subchunk_data_size > 0) { 308 unsigned int consume; 309 310 if (subchunk_data_size > sizeof(buf)) 311 consume = sizeof(buf); 312 else 313 consume = subchunk_data_size; 314 315 err = container_recursive_read(cntr, &buf, consume); 316 if (err < 0) 317 return err; 318 if (cntr->eof) 319 return 0; 320 subchunk_data_size -= consume; 321 } 322 } 323 324 return 0; 325} 326 327static int parse_riff_wave_format(struct container_context *cntr) 328{ 329 uint64_t byte_count; 330 int err; 331 332 err = parse_riff_chunk(cntr, &byte_count); 333 if (err < 0) 334 return err; 335 336 err = parse_wave_subchunk(cntr); 337 if (err < 0) 338 return err; 339 340 return 0; 341} 342 343static int wave_parser_pre_process(struct container_context *cntr, 344 snd_pcm_format_t *format, 345 unsigned int *samples_per_frame, 346 unsigned int *frames_per_second, 347 uint64_t *byte_count) 348{ 349 struct parser_state *state = cntr->private_data; 350 int phys_width; 351 const struct format_map *map; 352 unsigned int i; 353 int err; 354 355 err = parse_riff_wave_format(cntr); 356 if (err < 0) 357 return err; 358 359 phys_width = 8 * state->average_bytes_per_second / 360 state->samples_per_frame / state->frames_per_second; 361 362 for (i = 0; i < ARRAY_SIZE(format_maps); ++i) { 363 map = &format_maps[i]; 364 if (state->format != map->wformat) 365 continue; 366 if ((int)state->avail_bits_in_sample != 367 snd_pcm_format_width(map->format)) 368 continue; 369 if (phys_width != snd_pcm_format_physical_width(map->format)) 370 continue; 371 372 if (state->be && snd_pcm_format_big_endian(map->format) != 1) 373 continue; 374 375 break; 376 } 377 if (i == ARRAY_SIZE(format_maps)) 378 return -EINVAL; 379 380 // Set parameters. 381 *format = format_maps[i].format; 382 *samples_per_frame = state->samples_per_frame; 383 *frames_per_second = state->frames_per_second; 384 *byte_count = state->byte_count; 385 386 return 0; 387} 388 389struct builder_state { 390 bool be; 391 enum wave_format format; 392 unsigned int avail_bits_in_sample; 393 unsigned int bytes_per_sample; 394 unsigned int samples_per_frame; 395 unsigned int frames_per_second; 396}; 397 398static void build_riff_chunk_header(struct riff_chunk *chunk, 399 uint64_t byte_count, bool be) 400{ 401 uint64_t data_size = sizeof(struct riff_chunk_data) + 402 sizeof(struct wave_fmt_subchunk) + 403 sizeof(struct wave_data_subchunk) + byte_count; 404 405 if (be) { 406 memcpy(chunk->id, RIFF_CHUNK_ID_BE, sizeof(chunk->id)); 407 chunk->size = htobe32(data_size); 408 } else { 409 memcpy(chunk->id, RIFF_CHUNK_ID_LE, sizeof(chunk->id)); 410 chunk->size = htole32(data_size); 411 } 412} 413 414static void build_subchunk_header(struct riff_subchunk *subchunk, 415 const char *const form, uint64_t size, 416 bool be) 417{ 418 memcpy(subchunk->id, form, sizeof(subchunk->id)); 419 if (be) 420 subchunk->size = htobe32(size); 421 else 422 subchunk->size = htole32(size); 423} 424 425static void build_wave_format_subchunk(struct wave_fmt_subchunk *subchunk, 426 struct builder_state *state) 427{ 428 unsigned int bytes_per_frame = 429 state->bytes_per_sample * state->samples_per_frame; 430 unsigned int average_bytes_per_second = state->bytes_per_sample * 431 state->samples_per_frame * state->frames_per_second; 432 uint64_t size; 433 434 // No extensions. 435 size = sizeof(struct wave_fmt_subchunk) - sizeof(struct riff_subchunk); 436 build_subchunk_header((struct riff_subchunk *)subchunk, FMT_SUBCHUNK_ID, 437 size, state->be); 438 439 if (state->be) { 440 subchunk->format = htobe16(state->format); 441 subchunk->samples_per_frame = htobe16(state->samples_per_frame); 442 subchunk->frames_per_second = htobe32(state->frames_per_second); 443 subchunk->average_bytes_per_second = 444 htobe32(average_bytes_per_second); 445 subchunk->bytes_per_frame = htobe16(bytes_per_frame); 446 subchunk->bits_per_sample = 447 htobe16(state->avail_bits_in_sample); 448 } else { 449 subchunk->format = htole16(state->format); 450 subchunk->samples_per_frame = htole16(state->samples_per_frame); 451 subchunk->frames_per_second = htole32(state->frames_per_second); 452 subchunk->average_bytes_per_second = 453 htole32(average_bytes_per_second); 454 subchunk->bytes_per_frame = htole16(bytes_per_frame); 455 subchunk->bits_per_sample = 456 htole16(state->avail_bits_in_sample); 457 } 458} 459 460static void build_wave_data_subchunk(struct wave_data_subchunk *subchunk, 461 uint64_t byte_count, bool be) 462{ 463 build_subchunk_header((struct riff_subchunk *)subchunk, 464 DATA_SUBCHUNK_ID, byte_count, be); 465} 466 467static int write_riff_chunk_for_wave(struct container_context *cntr, 468 uint64_t byte_count) 469{ 470 struct builder_state *state = cntr->private_data; 471 union { 472 struct riff_chunk chunk; 473 struct riff_chunk_data chunk_data; 474 struct wave_fmt_subchunk fmt_subchunk; 475 struct wave_data_subchunk data_subchunk; 476 } buf = {0}; 477 uint64_t total_byte_count; 478 int err; 479 480 // Chunk header. 481 total_byte_count = sizeof(struct riff_chunk_data) + 482 sizeof(struct wave_fmt_subchunk) + 483 sizeof(struct wave_data_subchunk); 484 if (byte_count > cntr->max_size - total_byte_count) 485 total_byte_count = cntr->max_size; 486 else 487 total_byte_count += byte_count; 488 build_riff_chunk_header(&buf.chunk, total_byte_count, state->be); 489 err = container_recursive_write(cntr, &buf, sizeof(buf.chunk)); 490 if (err < 0) 491 return err; 492 493 // Chunk data header. 494 memcpy(buf.chunk_data.id, RIFF_FORM_WAVE, sizeof(buf.chunk_data.id)); 495 err = container_recursive_write(cntr, &buf, sizeof(buf.chunk_data)); 496 if (err < 0) 497 return err; 498 499 // A subchunk in the chunk data for WAVE format. 500 build_wave_format_subchunk(&buf.fmt_subchunk, state); 501 err = container_recursive_write(cntr, &buf, sizeof(buf.fmt_subchunk)); 502 if (err < 0) 503 return err; 504 505 // A subchunk in the chunk data for WAVE data. 506 build_wave_data_subchunk(&buf.data_subchunk, byte_count, state->be); 507 return container_recursive_write(cntr, &buf, sizeof(buf.data_subchunk)); 508} 509 510static int wave_builder_pre_process(struct container_context *cntr, 511 snd_pcm_format_t *format, 512 unsigned int *samples_per_frame, 513 unsigned int *frames_per_second, 514 uint64_t *byte_count) 515{ 516 struct builder_state *state = cntr->private_data; 517 unsigned int i; 518 519 // Validate parameters. 520 for (i = 0; i < ARRAY_SIZE(format_maps); ++i) { 521 if (format_maps[i].format == *format) 522 break; 523 } 524 if (i == ARRAY_SIZE(format_maps)) 525 return -EINVAL; 526 527 state->format = format_maps[i].wformat; 528 state->avail_bits_in_sample = snd_pcm_format_width(*format); 529 state->bytes_per_sample = snd_pcm_format_physical_width(*format) / 8; 530 state->samples_per_frame = *samples_per_frame; 531 state->frames_per_second = *frames_per_second; 532 533 state->be = (snd_pcm_format_big_endian(*format) == 1); 534 535 return write_riff_chunk_for_wave(cntr, *byte_count); 536} 537 538static int wave_builder_post_process(struct container_context *cntr, 539 uint64_t handled_byte_count) 540{ 541 int err; 542 543 err = container_seek_offset(cntr, 0); 544 if (err < 0) 545 return err; 546 547 return write_riff_chunk_for_wave(cntr, handled_byte_count); 548} 549 550const struct container_parser container_parser_riff_wave = { 551 .format = CONTAINER_FORMAT_RIFF_WAVE, 552 .magic = RIFF_MAGIC, 553 .max_size = UINT32_MAX - 554 sizeof(struct riff_chunk_data) - 555 sizeof(struct wave_fmt_subchunk) - 556 sizeof(struct wave_data_subchunk), 557 .ops = { 558 .pre_process = wave_parser_pre_process, 559 }, 560 .private_size = sizeof(struct parser_state), 561}; 562 563const struct container_builder container_builder_riff_wave = { 564 .format = CONTAINER_FORMAT_RIFF_WAVE, 565 .max_size = UINT32_MAX - 566 sizeof(struct riff_chunk_data) - 567 sizeof(struct wave_fmt_subchunk) - 568 sizeof(struct wave_data_subchunk), 569 .ops = { 570 .pre_process = wave_builder_pre_process, 571 .post_process = wave_builder_post_process, 572 }, 573 .private_size = sizeof(struct builder_state), 574}; 575