3 * @author Shinichiro Nakamura
4 * @brief libcベースのWAVファイルモジュール。
8 * ===============================================================
11 * ===============================================================
12 * Copyright (c) 2011-2012 Shinichiro Nakamura
14 * Permission is hereby granted, free of charge, to any person
15 * obtaining a copy of this software and associated documentation
16 * files (the "Software"), to deal in the Software without
17 * restriction, including without limitation the rights to use,
18 * copy, modify, merge, publish, distribute, sublicense, and/or
19 * sell copies of the Software, and to permit persons to whom the
20 * Software is furnished to do so, subject to the following
23 * The above copyright notice and this permission notice shall be
24 * included in all copies or substantial portions of the Software.
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
28 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
30 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
31 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33 * OTHER DEALINGS IN THE SOFTWARE.
34 * ===============================================================
44 #define CHUNK_ID_RIFF (('R' << 24) | ('I' << 16) | ('F' << 8) | ('F' << 0))
45 #define CHUNK_ID_FMT (('f' << 24) | ('m' << 16) | ('t' << 8) | (' ' << 0))
46 #define CHUNK_ID_DATA (('d' << 24) | ('a' << 16) | ('t' << 8) | ('a' << 0))
48 #define RIFF_CHUNK_FORMAT_WAVE (('W' << 24) | ('A' << 16) | ('V' << 8) | ('E' << 0))
50 #define BITS_PER_SAMPLE_8 (8)
51 #define BITS_PER_SAMPLE_16 (16)
52 #define BITS_PER_SAMPLE_24 (24)
54 #define CHUNK_SIZE_FMT_PCM (16)
55 #define CHUNK_SIZE_FMT_EXTENSIBLE (40)
57 #define CHANNEL_MASK_SPEAKER_FRONT_LEFT (0x00000001)
58 #define CHANNEL_MASK_SPEAKER_FRONT_RIGHT (0x00000002)
59 #define CHANNEL_MASK_SPEAKER_FRONT_CENTER (0x00000004)
60 #define CHANNEL_MASK_SPEAKER_LOW_FREQUENCY (0x00000008)
61 #define CHANNEL_MASK_SPEAKER_BACK_LEFT (0x00000010)
62 #define CHANNEL_MASK_SPEAKER_BACK_RIGHT (0x00000020)
63 #define CHANNEL_MASK_SPEAKER_FRONT_LEFT_OF_CENTER (0x00000040)
64 #define CHANNEL_MASK_SPEAKER_FRONT_RIGHT_OF_CENTER (0x00000080)
65 #define CHANNEL_MASK_SPEAKER_BACK_CENTER (0x00000100)
66 #define CHANNEL_MASK_SPEAKER_SIDE_LEFT (0x00000200)
67 #define CHANNEL_MASK_SPEAKER_SIDE_RIGHT (0x00000400)
68 #define CHANNEL_MASK_SPEAKER_TOP_CENTER (0x00000800)
69 #define CHANNEL_MASK_SPEAKER_TOP_FRONT_LEFT (0x00001000)
70 #define CHANNEL_MASK_SPEAKER_TOP_FRONT_CENTER (0x00002000)
71 #define CHANNEL_MASK_SPEAKER_TOP_FRONT_RIGHT (0x00004000)
72 #define CHANNEL_MASK_SPEAKER_TOP_BACK_LEFT (0x00008000)
73 #define CHANNEL_MASK_SPEAKER_TOP_BACK_CENTER (0x00010000)
74 #define CHANNEL_MASK_SPEAKER_TOP_BACK_RIGHT (0x00020000)
75 #define CHANNEL_MASK_SPEAKER_RESERVED (0x80000000)
78 FILE *fp; /**< ファイルハンドラ。 */
79 char filename[BUFSIZ]; /**< ファイル名。 */
80 WavFileMode mode; /**< ファイルモード。 */
81 bool info_checked; /**< infoを確認したら真になるフラグ。 */
82 bool data_checked; /**< dataを確認したら真になるフラグ。 */
83 uint32_t data_byte_count; /**< データバイトカウント。 */
84 wavfile_info_t info; /**< 対象ファイルのinfo情報。制御の確認用に用いる。 */
87 static int WRITE_U32_BE(FILE *fp, const uint32_t value)
89 for (int i = 0; i < 4; i++) {
90 if (fputc((value >> (8 * (3 - i))), fp) == EOF) {
97 static int WRITE_U32_LE(FILE *fp, const uint32_t value)
99 for (int i = 0; i < 4; i++) {
100 if (fputc((value >> (8 * i)), fp) == EOF) {
107 static int WRITE_U16_LE(FILE *fp, const uint16_t value)
109 for (int i = 0; i < 2; i++) {
110 if (fputc((value >> (8 * i)), fp) == EOF) {
117 static int READ_U32_BE(FILE *fp, uint32_t *value)
120 for (int i = 0; i < (int)(sizeof(raw) / sizeof(raw[0])); i++) {
128 ((uint32_t)raw[0] << 24) |
129 ((uint32_t)raw[1] << 16) |
130 ((uint32_t)raw[2] << 8) |
131 ((uint32_t)raw[3] << 0);
135 static int READ_U32_LE(FILE *fp, uint32_t *value)
138 for (int i = 0; i < (int)(sizeof(raw) / sizeof(raw[0])); i++) {
146 ((uint32_t)raw[3] << 24) |
147 ((uint32_t)raw[2] << 16) |
148 ((uint32_t)raw[1] << 8) |
149 ((uint32_t)raw[0] << 0);
153 static int READ_U16_LE(FILE *fp, uint16_t *value)
156 for (int i = 0; i < (int)(sizeof(raw) / sizeof(raw[0])); i++) {
164 ((uint16_t)raw[1] << 8) |
165 ((uint16_t)raw[0] << 0);
169 static WavFileResult chunk_reader_unknown(
170 const uint32_t chunk_id,
171 const uint32_t chunk_size,
174 for (int i = 0; i < (int)chunk_size; i++) {
177 return WavFileResultErrorBrokenChunkData;
180 return WavFileResultOK;
183 static WavFileResult chunk_reader_riff(
184 const uint32_t chunk_id,
185 const uint32_t chunk_size,
189 if (READ_U32_BE(fp, format_id) != 0) {
190 return WavFileResultErrorBrokenFormatId;
192 return WavFileResultOK;
195 static WavFileResult chunk_reader_fmt(
196 const uint32_t chunk_id,
197 const uint32_t chunk_size,
199 uint16_t *audio_format,
200 uint16_t *num_channels,
201 uint32_t *sample_rate,
203 uint16_t *block_align,
204 uint16_t *bits_per_sample)
206 uint32_t read_byte_count = 0;
211 if (read_byte_count < chunk_size) {
212 if (READ_U16_LE(fp, audio_format) != 0) {
213 return WavFileResultErrorBrokenAudioFormat;
221 if (read_byte_count < chunk_size) {
222 if (READ_U16_LE(fp, num_channels) != 0) {
223 return WavFileResultErrorBrokenNumChannels;
231 if (read_byte_count < chunk_size) {
232 if (READ_U32_LE(fp, sample_rate) != 0) {
233 return WavFileResultErrorBrokenSampleRate;
241 if (read_byte_count < chunk_size) {
242 if (READ_U32_LE(fp, byte_rate) != 0) {
243 return WavFileResultErrorBrokenByteRate;
251 if (read_byte_count < chunk_size) {
252 if (READ_U16_LE(fp, block_align) != 0) {
253 return WavFileResultErrorBrokenBlockAlign;
259 * 2 + 2 + 4 + 4 + 2 + 2
261 if (read_byte_count < chunk_size) {
262 if (READ_U16_LE(fp, bits_per_sample) != 0) {
263 return WavFileResultErrorBrokenBitsPerSample;
269 * 2 + 2 + 4 + 4 + 2 + 2
271 while (read_byte_count < chunk_size) {
272 if (fgetc(fp) == EOF) {
273 return WavFileResultErrorBrokenChunkData;
278 return WavFileResultOK;
281 WAVFILE *wavfile_open(const char *filename, WavFileMode mode, WavFileResult *result)
286 if (filename == NULL) {
287 *result = WavFileResultErrorInvalidFileName;
296 case WavFileModeRead:
297 fp = fopen(filename, "rb");
299 case WavFileModeWrite:
300 fp = fopen(filename, "wb");
307 *result = WavFileResultErrorFileOpen;
314 WAVFILE *p = (WAVFILE *)malloc(sizeof(WAVFILE));
316 *result = WavFileResultErrorMemoryAllocation;
324 strcpy(p->filename, filename);
326 p->info_checked = false;
327 p->data_checked = false;
328 p->data_byte_count = 0;
329 WAVFILE_INFO_AUDIO_FORMAT(&(p->info)) = 0;
330 WAVFILE_INFO_NUM_CHANNELS(&(p->info)) = 0;
331 WAVFILE_INFO_SAMPLE_RATE(&(p->info)) = 0;
332 WAVFILE_INFO_BYTE_RATE(&(p->info)) = 0;
333 WAVFILE_INFO_BLOCK_ALIGN(&(p->info)) = 0;
334 WAVFILE_INFO_BITS_PER_SAMPLE(&(p->info)) = 0;
336 *result = WavFileResultOK;
340 WavFileResult wavfile_read_info(WAVFILE *p, wavfile_info_t *info)
342 WavFileResult result = WavFileResultOK;
345 result = WavFileResultErrorInvalidHandler;
349 if (p->info_checked) {
350 result = WavFileResultErrorAlreadyInfoChecked;
353 if (p->data_checked) {
354 result = WavFileResultErrorAlreadyDataChecked;
357 if (p->mode != WavFileModeRead) {
358 result = WavFileResultErrorInvalidMode;
369 if (READ_U32_BE(p->fp, &chunk_id) != 0) {
372 * このループはデータチャンクのデータ先頭に到達して離脱する仕掛け。
373 * チャンクIDを確認するところでEOFになるのは所望のデータに到達できなかった証拠である。
375 result = WavFileResultErrorNoDataChunk;
378 result = WavFileResultErrorBrokenChunkId;
386 if (READ_U32_LE(p->fp, &chunk_size) != 0) {
387 result = WavFileResultErrorBrokenChunkSize;
391 #if WAVFILE_DEBUG_ENABLED
393 * チャンクIDとチャンクサイズのデバッグ用出力。
395 DEBUG("chunk_id(0x%04X-%c%c%c%c), chunk_size(%d bytes)\n",
397 (chunk_id >> (8 * 3)),
398 (chunk_id >> (8 * 2)),
399 (chunk_id >> (8 * 1)),
400 (chunk_id >> (8 * 0)),
405 * チャンクIDに従って読み込みを実行する。
411 result = chunk_reader_riff(
417 #if WAVFILE_DEBUG_ENABLED
421 DEBUG("\tformat_id(%d)\n", format_id);
424 if (format_id != RIFF_CHUNK_FORMAT_WAVE) {
425 return WavFileResultErrorInvalidFormatId;
427 if (result != WavFileResultOK) {
434 result = chunk_reader_fmt(
438 &(p->info.audio_format),
439 &(p->info.num_channels),
440 &(p->info.sample_rate),
441 &(p->info.byte_rate),
442 &(p->info.block_align),
443 &(p->info.bits_per_sample));
445 info->audio_format = p->info.audio_format;
446 info->num_channels = p->info.num_channels;
447 info->sample_rate = p->info.sample_rate;
448 info->byte_rate = p->info.byte_rate;
449 info->block_align = p->info.block_align;
450 info->bits_per_sample = p->info.bits_per_sample;
452 #if WAVFILE_DEBUG_ENABLED
456 DEBUG("\taudio_format(%d)\n", p->info.audio_format);
457 DEBUG("\tnum_channels(%d)\n", p->info.num_channels);
458 DEBUG("\tsample_rate(%d)\n", p->info.sample_rate);
459 DEBUG("\tbyte_rate(%d)\n", p->info.byte_rate);
460 DEBUG("\tblock_align(%d)\n", p->info.block_align);
461 DEBUG("\tbits_per_sample(%d)\n", p->info.bits_per_sample);
464 if ((p->info.audio_format != WAVFILE_AUDIO_FORMAT_PCM) && (info->audio_format != WAVFILE_AUDIO_FORMAT_EXTENSIBLE)) {
465 return WavFileResultErrorInvalidAudioFormat;
467 if (result != WavFileResultOK) {
474 p->info_checked = true;
475 p->data_byte_count = chunk_size;
481 result = chunk_reader_unknown(chunk_id, chunk_size, p->fp);
482 if (result != WavFileResultOK) {
495 * @details 音声データは、どんな形式でも常に0.0から1.0の範囲で正規化して出力される。
497 WavFileResult wavfile_read_data(WAVFILE *p, wavfile_data_t *data)
500 return WavFileResultErrorInvalidHandler;
503 if (!p->info_checked) {
504 return WavFileResultErrorNeedInfoChecked;
507 if (p->mode != WavFileModeRead) {
508 return WavFileResultErrorInvalidMode;
511 if (p->data_byte_count == 0) {
512 data->num_channels = 0;
513 for (int i = 0; i < p->info.num_channels; i++) {
514 data->channel_data[i] = 0.5;
516 return WavFileResultOK;
519 data->num_channels = p->info.num_channels;
520 for (int i = 0; i < p->info.num_channels; i++) {
521 switch (p->info.bits_per_sample) {
522 case BITS_PER_SAMPLE_8:
524 int c = fgetc(p->fp);
526 return WavFileResultErrorBrokenChunkData;
528 data->channel_data[i] = (double)c / 0xFF;
530 p->data_byte_count-=1;
532 case BITS_PER_SAMPLE_16:
534 int c1 = fgetc(p->fp);
536 return WavFileResultErrorBrokenChunkData;
538 int c2 = fgetc(p->fp);
540 return WavFileResultErrorBrokenChunkData;
542 uint16_t n = (((uint16_t)c2 << 8) | ((uint16_t)c1 << 0)) ^ (1 << 15);
543 data->channel_data[i] = (double)n / 0xFFFF;
545 p->data_byte_count-=2;
547 case BITS_PER_SAMPLE_24:
549 int c1 = fgetc(p->fp);
551 return WavFileResultErrorBrokenChunkData;
553 int c2 = fgetc(p->fp);
555 return WavFileResultErrorBrokenChunkData;
557 int c3 = fgetc(p->fp);
559 return WavFileResultErrorBrokenChunkData;
561 uint32_t n = (((uint32_t)c3 << 16) | ((uint32_t)c2 << 8) | ((uint32_t)c1 << 0)) ^ (1 << 23);
562 data->channel_data[i] = (double)n / 0xFFFFFF;
564 p->data_byte_count-=3;
567 return WavFileResultErrorUnsupportedBitsPerSample;
570 return WavFileResultOK;
573 WavFileResult wavfile_write_info(WAVFILE *p, const wavfile_info_t *info)
575 WavFileResult result = WavFileResultOK;
578 result = WavFileResultErrorInvalidHandler;
582 if (p->info_checked) {
583 result = WavFileResultErrorAlreadyInfoChecked;
587 if (p->mode != WavFileModeWrite) {
588 result = WavFileResultErrorInvalidMode;
592 p->info.audio_format = info->audio_format;
593 p->info.num_channels = info->num_channels;
594 p->info.sample_rate = info->sample_rate;
595 p->info.byte_rate = info->byte_rate;
596 p->info.block_align = info->block_align;
597 p->info.bits_per_sample = info->bits_per_sample;
603 if ((info->audio_format != WAVFILE_AUDIO_FORMAT_PCM) && (info->audio_format != WAVFILE_AUDIO_FORMAT_EXTENSIBLE)) {
604 result = WavFileResultErrorInvalidAudioFormat;
608 if ((info->bits_per_sample != BITS_PER_SAMPLE_8)
609 && (info->bits_per_sample != BITS_PER_SAMPLE_16)
610 && (info->bits_per_sample != BITS_PER_SAMPLE_24)) {
611 result = WavFileResultErrorUnsupportedBitsPerSample;
615 if ((info->num_channels * info->sample_rate * (info->bits_per_sample / 8)) != info->byte_rate) {
616 result = WavFileResultErrorInvalidByteRate;
622 * ------------------------------------------
623 * Big endian 4 bytes : Chunk ID
624 * Little endian 4 bytes : Chunk size
625 * Big endian 4 bytes : Format
626 * ------------------------------------------
628 if (WRITE_U32_BE(p->fp, CHUNK_ID_RIFF) != 0) {
629 result = WavFileResultErrorFileWrite;
632 if (WRITE_U32_LE(p->fp, 0x00000000) != 0) {
633 result = WavFileResultErrorFileWrite;
636 if (WRITE_U32_BE(p->fp, RIFF_CHUNK_FORMAT_WAVE) != 0) {
637 result = WavFileResultErrorFileWrite;
643 * ------------------------------------------
644 * Big endian 4 bytes : Sub chunk ID
645 * Little endian 4 bytes : Sub chunk size
646 * Little endian 2 bytes : Audio format
647 * Little endian 2 bytes : Number of channels
648 * Little endian 4 bytes : Sample rate
649 * Little endian 4 bytes : Byte rate
650 * Little endian 2 bytes : Block align
651 * Little endian 2 bytes : Bits per sample
653 * . Additional bytes here (extensible) .
655 * ------------------------------------------
657 switch (info->audio_format) {
658 case WAVFILE_AUDIO_FORMAT_PCM:
660 if (WRITE_U32_BE(p->fp, CHUNK_ID_FMT) != 0) {
661 result = WavFileResultErrorFileWrite;
664 if (WRITE_U32_LE(p->fp, CHUNK_SIZE_FMT_PCM) != 0) {
665 result = WavFileResultErrorFileWrite;
668 if (WRITE_U16_LE(p->fp, info->audio_format) != 0) {
669 result = WavFileResultErrorFileWrite;
672 if (WRITE_U16_LE(p->fp, info->num_channels) != 0) {
673 result = WavFileResultErrorFileWrite;
676 if (WRITE_U32_LE(p->fp, info->sample_rate) != 0) {
677 result = WavFileResultErrorFileWrite;
680 if (WRITE_U32_LE(p->fp, info->byte_rate) != 0) {
681 result = WavFileResultErrorFileWrite;
684 if (WRITE_U16_LE(p->fp, info->block_align) != 0) {
685 result = WavFileResultErrorFileWrite;
688 if (WRITE_U16_LE(p->fp, info->bits_per_sample) != 0) {
689 result = WavFileResultErrorFileWrite;
694 case WAVFILE_AUDIO_FORMAT_EXTENSIBLE:
696 if (WRITE_U32_BE(p->fp, CHUNK_ID_FMT) != 0) {
697 result = WavFileResultErrorFileWrite;
700 if (WRITE_U32_LE(p->fp, CHUNK_SIZE_FMT_EXTENSIBLE) != 0) {
701 result = WavFileResultErrorFileWrite;
704 if (WRITE_U16_LE(p->fp, info->audio_format) != 0) {
705 result = WavFileResultErrorFileWrite;
708 if (WRITE_U16_LE(p->fp, info->num_channels) != 0) {
709 result = WavFileResultErrorFileWrite;
712 if (WRITE_U32_LE(p->fp, info->sample_rate) != 0) {
713 result = WavFileResultErrorFileWrite;
716 if (WRITE_U32_LE(p->fp, info->byte_rate) != 0) {
717 result = WavFileResultErrorFileWrite;
720 if (WRITE_U16_LE(p->fp, info->block_align) != 0) {
721 result = WavFileResultErrorFileWrite;
724 if (WRITE_U16_LE(p->fp, info->bits_per_sample) != 0) {
725 result = WavFileResultErrorFileWrite;
729 * Additional bytes for the extensible format.
731 * 2 bytes : Size of the extension (0 or 22)
732 * 2 bytes : Number of valid bits
733 * 4 bytes : Speaker position mask
734 * 16 bytes : GUID, including the data format code
736 if (WRITE_U16_LE(p->fp, 22) != 0) {
737 result = WavFileResultErrorFileWrite;
740 if (WRITE_U16_LE(p->fp, info->bits_per_sample) != 0) {
741 result = WavFileResultErrorFileWrite;
744 if (WRITE_U32_LE(p->fp, 0x00000000) != 0) {
745 result = WavFileResultErrorFileWrite;
748 static const unsigned char sub_format[16] = {
749 0x01, 0x00, 0x00, 0x00,
750 0x00, 0x00, 0x10, 0x00,
751 0x80, 0x00, 0x00, 0xAA,
752 0x00, 0x38, 0x9B, 0x71
754 for (int i = 0; i < sizeof(sub_format); i++) {
755 fputc((char)sub_format[i], p->fp);
760 result = WavFileResultErrorInvalidAudioFormat;
766 * ------------------------------------------
767 * Big endian 4 bytes : Sub chunk ID
768 * Little endian 4 bytes : Sub chunk size
769 * ------------------------------------------
770 * Little endian 2 bytes : Sample 1 (Ch.1)
771 * Little endian 2 bytes : Sample 1 (Ch.2)
775 * Little endian 2 bytes : Sample 1 (Ch.N)
776 * ------------------------------------------
777 * Little endian 2 bytes : Sample 2 (Ch.1)
778 * Little endian 2 bytes : Sample 2 (Ch.2)
782 * Little endian 2 bytes : Sample 2 (Ch.N)
783 * ------------------------------------------
785 if (WRITE_U32_BE(p->fp, CHUNK_ID_DATA) != 0) {
786 result = WavFileResultErrorFileWrite;
789 if (WRITE_U32_LE(p->fp, 0x00000000) != 0) {
790 result = WavFileResultErrorFileWrite;
795 if (WavFileResultOK == result) {
796 p->info_checked = true;
802 * @details 音声データは、どんな形式でも常に0.0から1.0の範囲で正規化して入力される。
804 WavFileResult wavfile_write_data(WAVFILE *p, const wavfile_data_t *data)
806 WavFileResult result = WavFileResultOK;
809 result = WavFileResultErrorInvalidHandler;
813 if (!p->info_checked) {
814 result = WavFileResultErrorNeedInfoChecked;
818 if (p->mode != WavFileModeWrite) {
819 result = WavFileResultErrorInvalidMode;
823 if (p->info.num_channels != data->num_channels) {
824 result = WavFileResultErrorInvalidNumChannels;
828 for (int i = 0; i < p->info.num_channels; i++) {
829 switch (p->info.bits_per_sample) {
830 case BITS_PER_SAMPLE_8:
832 int n = (int)((double)data->channel_data[i] * 0xFF);
839 fputc((char)n, p->fp);
841 p->data_byte_count+=1;
843 case BITS_PER_SAMPLE_16:
845 int n = (int)((double)(data->channel_data[i] * 0xFFFF) - 0x8000);
852 fputc(((uint16_t)n >> 0) & 0xff, p->fp);
853 fputc(((uint16_t)n >> 8) & 0xff, p->fp);
855 p->data_byte_count+=2;
857 case BITS_PER_SAMPLE_24:
859 int n = (int)((double)(data->channel_data[i] * 0xFFFFFF) - 0x800000);
866 fputc(((uint32_t)n >> 0) & 0xff, p->fp);
867 fputc(((uint32_t)n >> 8) & 0xff, p->fp);
868 fputc(((uint32_t)n >> 16) & 0xff, p->fp);
870 p->data_byte_count+=3;
874 p->data_checked = true;
880 WavFileResult wavfile_close(WAVFILE *p)
882 WavFileResult result = WavFileResultOK;
885 case WavFileModeRead:
887 case WavFileModeWrite:
888 if (p->info_checked && p->data_checked) {
889 switch (p->info.audio_format) {
890 case WAVFILE_AUDIO_FORMAT_PCM:
893 * Fill the RIFF chunk size.
895 if (fseek(p->fp, 4L, SEEK_SET) == -1) {
896 result = WavFileResultErrorFileWrite;
899 if (WRITE_U32_LE(p->fp, 4 + (8 + CHUNK_SIZE_FMT_PCM) + (8 + p->data_byte_count)) != 0) {
900 result = WavFileResultErrorFileWrite;
905 * Fill the data sub chunk size.
907 if (fseek(p->fp, 12 + (8 + CHUNK_SIZE_FMT_PCM) + 4, SEEK_SET) == -1) {
908 result = WavFileResultErrorFileWrite;
911 if (WRITE_U32_LE(p->fp, p->data_byte_count) != 0) {
912 result = WavFileResultErrorFileWrite;
917 case WAVFILE_AUDIO_FORMAT_EXTENSIBLE:
920 * Fill the RIFF chunk size.
922 if (fseek(p->fp, 4L, SEEK_SET) == -1) {
923 result = WavFileResultErrorFileWrite;
926 if (WRITE_U32_LE(p->fp, 4 + (8 + CHUNK_SIZE_FMT_EXTENSIBLE) + (8 + p->data_byte_count)) != 0) {
927 result = WavFileResultErrorFileWrite;
932 * Fill the data sub chunk size.
934 if (fseek(p->fp, 12 + (8 + CHUNK_SIZE_FMT_EXTENSIBLE) + 4, SEEK_SET) == -1) {
935 result = WavFileResultErrorFileWrite;
938 if (WRITE_U32_LE(p->fp, p->data_byte_count) != 0) {
939 result = WavFileResultErrorFileWrite;
955 void wavfile_result_string(const WavFileResult result, char *buf, size_t siz)
958 case WavFileResultOK:
961 case WavFileResultErrorInvalidFileName:
962 strcpy(buf, "Invalid file name found.");
964 case WavFileResultErrorMemoryAllocation:
965 strcpy(buf, "Memory allocation error.");
967 case WavFileResultErrorFileOpen:
968 strcpy(buf, "File open error found.");
970 case WavFileResultErrorFileWrite:
971 strcpy(buf, "File write error found.");
973 case WavFileResultErrorBrokenChunkId:
974 strcpy(buf, "Broken chunk ID found.");
976 case WavFileResultErrorBrokenChunkSize:
977 strcpy(buf, "Borken chunk size found.");
979 case WavFileResultErrorBrokenChunkData:
980 strcpy(buf, "Borken chunk data found.");
982 case WavFileResultErrorBrokenFormatId:
983 strcpy(buf, "Broken format ID found.");
985 case WavFileResultErrorInvalidFormatId:
986 strcpy(buf, "Invalid format ID found.");
988 case WavFileResultErrorBrokenAudioFormat:
989 strcpy(buf, "Broken audio format found.");
991 case WavFileResultErrorInvalidAudioFormat:
992 strcpy(buf, "Invalid audio format found.");
994 case WavFileResultErrorInvalidNumChannels:
995 strcpy(buf, "Invalid number of channels found.");
997 case WavFileResultErrorBrokenNumChannels:
998 strcpy(buf, "Broken number of channels found.");
1000 case WavFileResultErrorBrokenSampleRate:
1001 strcpy(buf, "Broken sample rate found.");
1003 case WavFileResultErrorBrokenByteRate:
1004 strcpy(buf, "Broken byte rate found.");
1006 case WavFileResultErrorInvalidByteRate:
1007 strcpy(buf, "Invalid byte rate found.");
1009 case WavFileResultErrorBrokenBlockAlign:
1010 strcpy(buf, "Broken block alignment found.");
1012 case WavFileResultErrorBrokenBitsPerSample:
1013 strcpy(buf, "Broken bits per sample found.");
1015 case WavFileResultErrorUnsupportedBitsPerSample:
1016 strcpy(buf, "Unsupported bits per sample found.");
1018 case WavFileResultErrorAlreadyInfoChecked:
1019 strcpy(buf, "Already checked info.");
1021 case WavFileResultErrorAlreadyDataChecked:
1022 strcpy(buf, "Already checked data.");
1024 case WavFileResultErrorNoDataChunk:
1025 strcpy(buf, "No data chunk.");
1027 case WavFileResultErrorInvalidMode:
1028 strcpy(buf, "Invalid mode.");
1030 case WavFileResultErrorNeedInfoChecked:
1031 strcpy(buf, "Need check info.");
1033 case WavFileResultErrorNeedDataChecked:
1034 strcpy(buf, "Need check data.");
1036 case WavFileResultErrorInvalidHandler:
1037 strcpy(buf, "Invalid handler.");
1040 strcpy(buf, "Unkonwn error found.");