OSDN Git Service

Updated the documents.
[bluetank/bluetank.git] / soft / utils / common / tinywavio / wavfile.cpp
1 /**
2  * @file wavfile.cpp
3  * @author Shinichiro Nakamura
4  * @brief libcベースのWAVファイルモジュール。
5  */
6
7 /*
8  * ===============================================================
9  *  Tiny WAV I/O Module
10  *  Version 0.0.1
11  * ===============================================================
12  * Copyright (c) 2011-2012 Shinichiro Nakamura
13  *
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
21  * conditions:
22  *
23  * The above copyright notice and this permission notice shall be
24  * included in all copies or substantial portions of the Software.
25  *
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  * ===============================================================
35  */
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include "wavfile.h"
41
42 #define DEBUG printf
43
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))
47
48 #define RIFF_CHUNK_FORMAT_WAVE  (('W' << 24) | ('A' << 16) | ('V' << 8) | ('E' << 0))
49
50 #define BITS_PER_SAMPLE_8           (8)
51 #define BITS_PER_SAMPLE_16          (16)
52 #define BITS_PER_SAMPLE_24          (24)
53
54 #define CHUNK_SIZE_FMT_PCM          (16)
55 #define CHUNK_SIZE_FMT_EXTENSIBLE   (40)
56
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)
76
77 struct WAVFILE {
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情報。制御の確認用に用いる。 */
85 };
86
87 static int WRITE_U32_BE(FILE *fp, const uint32_t value)
88 {
89     for (int i = 0; i < 4; i++) {
90         if (fputc((value >> (8 * (3 - i))), fp) == EOF) {
91             return -1;
92         }
93     }
94     return 0;
95 }
96
97 static int WRITE_U32_LE(FILE *fp, const uint32_t value)
98 {
99     for (int i = 0; i < 4; i++) {
100         if (fputc((value >> (8 * i)), fp) == EOF) {
101             return -1;
102         }
103     }
104     return 0;
105 }
106
107 static int WRITE_U16_LE(FILE *fp, const uint16_t value)
108 {
109     for (int i = 0; i < 2; i++) {
110         if (fputc((value >> (8 * i)), fp) == EOF) {
111             return -1;
112         }
113     }
114     return 0;
115 }
116
117 static int READ_U32_BE(FILE *fp, uint32_t *value)
118 {
119     int raw[4];
120     for (int i = 0; i < (int)(sizeof(raw) / sizeof(raw[0])); i++) {
121         raw[i] = fgetc(fp);
122         if (raw[i] == EOF) {
123             *value = 0x00000000;
124             return -1;
125         }
126     }
127     *value =
128         ((uint32_t)raw[0] << 24) |
129         ((uint32_t)raw[1] << 16) |
130         ((uint32_t)raw[2] <<  8) |
131         ((uint32_t)raw[3] <<  0);
132     return 0;
133 }
134
135 static int READ_U32_LE(FILE *fp, uint32_t *value)
136 {
137     int raw[4];
138     for (int i = 0; i < (int)(sizeof(raw) / sizeof(raw[0])); i++) {
139         raw[i] = fgetc(fp);
140         if (raw[i] == EOF) {
141             *value = 0x00000000;
142             return -1;
143         }
144     }
145     *value =
146         ((uint32_t)raw[3] << 24) |
147         ((uint32_t)raw[2] << 16) |
148         ((uint32_t)raw[1] <<  8) |
149         ((uint32_t)raw[0] <<  0);
150     return 0;
151 }
152
153 static int READ_U16_LE(FILE *fp, uint16_t *value)
154 {
155     int raw[2];
156     for (int i = 0; i < (int)(sizeof(raw) / sizeof(raw[0])); i++) {
157         raw[i] = fgetc(fp);
158         if (raw[i] == EOF) {
159             *value = 0x00000000;
160             return -1;
161         }
162     }
163     *value =
164         ((uint16_t)raw[1] <<  8) |
165         ((uint16_t)raw[0] <<  0);
166     return 0;
167 }
168
169 static WavFileResult chunk_reader_unknown(
170         const uint32_t chunk_id,
171         const uint32_t chunk_size,
172         FILE *fp)
173 {
174     for (int i = 0; i < (int)chunk_size; i++) {
175         int c = fgetc(fp);
176         if (c == EOF) {
177             return WavFileResultErrorBrokenChunkData;
178         }
179     }
180     return WavFileResultOK;
181 }
182
183 static WavFileResult chunk_reader_riff(
184         const uint32_t chunk_id,
185         const uint32_t chunk_size,
186         FILE *fp,
187         uint32_t *format_id)
188 {
189     if (READ_U32_BE(fp, format_id) != 0) {
190         return WavFileResultErrorBrokenFormatId;
191     }
192     return WavFileResultOK;
193 }
194
195 static WavFileResult chunk_reader_fmt(
196         const uint32_t chunk_id,
197         const uint32_t chunk_size,
198         FILE *fp,
199         uint16_t *audio_format,
200         uint16_t *num_channels,
201         uint32_t *sample_rate,
202         uint32_t *byte_rate,
203         uint16_t *block_align,
204         uint16_t *bits_per_sample)
205 {
206     uint32_t read_byte_count = 0;
207
208     /*
209      * 2
210      */
211     if (read_byte_count < chunk_size) {
212         if (READ_U16_LE(fp, audio_format) != 0) {
213             return WavFileResultErrorBrokenAudioFormat;
214         }
215     }
216     read_byte_count+=2;
217
218     /*
219      * 2 + 2
220      */
221     if (read_byte_count < chunk_size) {
222         if (READ_U16_LE(fp, num_channels) != 0) {
223             return WavFileResultErrorBrokenNumChannels;
224         }
225     }
226     read_byte_count+=2;
227
228     /*
229      * 2 + 2 + 4
230      */
231     if (read_byte_count < chunk_size) {
232         if (READ_U32_LE(fp, sample_rate) != 0) {
233             return WavFileResultErrorBrokenSampleRate;
234         }
235     }
236     read_byte_count+=4;
237
238     /*
239      * 2 + 2 + 4 + 4
240      */
241     if (read_byte_count < chunk_size) {
242         if (READ_U32_LE(fp, byte_rate) != 0) {
243             return WavFileResultErrorBrokenByteRate;
244         }
245     }
246     read_byte_count+=4;
247
248     /*
249      * 2 + 2 + 4 + 4 + 2
250      */
251     if (read_byte_count < chunk_size) {
252         if (READ_U16_LE(fp, block_align) != 0) {
253             return WavFileResultErrorBrokenBlockAlign;
254         }
255     }
256     read_byte_count+=2;
257
258     /*
259      * 2 + 2 + 4 + 4 + 2 + 2
260      */
261     if (read_byte_count < chunk_size) {
262         if (READ_U16_LE(fp, bits_per_sample) != 0) {
263             return WavFileResultErrorBrokenBitsPerSample;
264         }
265     }
266     read_byte_count+=2;
267
268     /*
269      * 2 + 2 + 4 + 4 + 2 + 2
270      */
271     while (read_byte_count < chunk_size) {
272         if (fgetc(fp) == EOF) {
273             return WavFileResultErrorBrokenChunkData;
274         }
275         read_byte_count++;
276     }
277
278     return WavFileResultOK;
279 }
280
281 WAVFILE *wavfile_open(const char *filename, WavFileMode mode, WavFileResult *result)
282 {
283     /*
284      * ファイル名を検証する。
285      */
286     if (filename == NULL) {
287         *result = WavFileResultErrorInvalidFileName;
288         return NULL;
289     }
290
291     /*
292      * ファイルを開く。
293      */
294     FILE *fp = NULL;
295     switch (mode) {
296         case WavFileModeRead:
297             fp = fopen(filename, "rb");
298             break;
299         case WavFileModeWrite:
300             fp = fopen(filename, "wb");
301             break;
302         default:
303             fp = NULL;
304             break;
305     }
306     if (fp == NULL) {
307         *result = WavFileResultErrorFileOpen;
308         return NULL;
309     }
310
311     /*
312      * ハンドラ領域を確保する。
313      */
314     WAVFILE *p = (WAVFILE *)malloc(sizeof(WAVFILE));
315     if (p == NULL) {
316         *result = WavFileResultErrorMemoryAllocation;
317         return NULL;
318     }
319
320     /*
321      * ハンドラ内部フィールドを設定する。
322      */
323     p->fp = fp;
324     strcpy(p->filename, filename);
325     p->mode = mode;
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;
335
336     *result = WavFileResultOK;
337     return p;
338 }
339
340 WavFileResult wavfile_read_info(WAVFILE *p, wavfile_info_t *info)
341 {
342     WavFileResult result = WavFileResultOK;
343
344     if (p == NULL) {
345         result = WavFileResultErrorInvalidHandler;
346         goto finalize;
347     }
348
349     if (p->info_checked) {
350         result = WavFileResultErrorAlreadyInfoChecked;
351         goto finalize;
352     }
353     if (p->data_checked) {
354         result = WavFileResultErrorAlreadyDataChecked;
355         goto finalize;
356     }
357     if (p->mode != WavFileModeRead) {
358         result = WavFileResultErrorInvalidMode;
359         goto finalize;
360     }
361
362     while (1) {
363         uint32_t chunk_id;
364         uint32_t chunk_size;
365
366         /*
367          * チャンクIDを取得する。
368          */
369         if (READ_U32_BE(p->fp, &chunk_id) != 0) {
370             if (feof(p->fp)) {
371                 /*
372                  * このループはデータチャンクのデータ先頭に到達して離脱する仕掛け。
373                  * チャンクIDを確認するところでEOFになるのは所望のデータに到達できなかった証拠である。
374                  */
375                 result = WavFileResultErrorNoDataChunk;
376                 goto finalize;
377             } else {
378                 result = WavFileResultErrorBrokenChunkId;
379                 goto finalize;
380             }
381         }
382
383         /*
384          * チャンクサイズを取得する。
385          */
386         if (READ_U32_LE(p->fp, &chunk_size) != 0) {
387             result = WavFileResultErrorBrokenChunkSize;
388             goto finalize;
389         }
390
391 #if WAVFILE_DEBUG_ENABLED
392         /*
393          * チャンクIDとチャンクサイズのデバッグ用出力。
394          */
395         DEBUG("chunk_id(0x%04X-%c%c%c%c), chunk_size(%d bytes)\n",
396                 chunk_id,
397                 (chunk_id >> (8 * 3)),
398                 (chunk_id >> (8 * 2)),
399                 (chunk_id >> (8 * 1)),
400                 (chunk_id >> (8 * 0)),
401                 chunk_size);
402 #endif
403
404         /*
405          * チャンクIDに従って読み込みを実行する。
406          */
407         switch (chunk_id) {
408             case CHUNK_ID_RIFF:
409                 {
410                     uint32_t format_id;
411                     result = chunk_reader_riff(
412                             chunk_id,
413                             chunk_size,
414                             p->fp,
415                             &format_id);
416
417 #if WAVFILE_DEBUG_ENABLED
418                     /*
419                      * フォーマットIDのデバッグ用出力。
420                      */
421                     DEBUG("\tformat_id(%d)\n", format_id);
422 #endif
423
424                     if (format_id != RIFF_CHUNK_FORMAT_WAVE) {
425                         return WavFileResultErrorInvalidFormatId;
426                     }
427                     if (result != WavFileResultOK) {
428                         goto finalize;
429                     }
430                 }
431                 break;
432             case CHUNK_ID_FMT:
433                 {
434                     result = chunk_reader_fmt(
435                             chunk_id,
436                             chunk_size,
437                             p->fp,
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));
444
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;
451
452 #if WAVFILE_DEBUG_ENABLED
453                     /*
454                      * フォーマット情報のデバッグ用出力。
455                      */
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);
462 #endif
463
464                     if ((p->info.audio_format != WAVFILE_AUDIO_FORMAT_PCM) && (info->audio_format != WAVFILE_AUDIO_FORMAT_EXTENSIBLE)) {
465                         return WavFileResultErrorInvalidAudioFormat;
466                     }
467                     if (result != WavFileResultOK) {
468                         goto finalize;
469                     }
470                 }
471                 break;
472             case CHUNK_ID_DATA:
473                 {
474                     p->info_checked = true;
475                     p->data_byte_count = chunk_size;
476                     goto finalize;
477                 }
478                 break;
479             default:
480                 {
481                     result = chunk_reader_unknown(chunk_id, chunk_size, p->fp);
482                     if (result != WavFileResultOK) {
483                         goto finalize;
484                     }
485                 }
486                 break;
487         }
488     }
489
490 finalize:
491     return result;
492 }
493
494 /**
495  * @details 音声データは、どんな形式でも常に0.0から1.0の範囲で正規化して出力される。
496  */
497 WavFileResult wavfile_read_data(WAVFILE *p, wavfile_data_t *data)
498 {
499     if (p == NULL) {
500         return WavFileResultErrorInvalidHandler;
501     }
502
503     if (!p->info_checked) {
504         return WavFileResultErrorNeedInfoChecked;
505     }
506
507     if (p->mode != WavFileModeRead) {
508         return WavFileResultErrorInvalidMode;
509     }
510
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;
515         }
516         return WavFileResultOK;
517     }
518
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:
523                 {
524                     int c = fgetc(p->fp);
525                     if (c == EOF) {
526                         return WavFileResultErrorBrokenChunkData;
527                     }
528                     data->channel_data[i] = (double)c / 0xFF;
529                 }
530                 p->data_byte_count-=1;
531                 break;
532             case BITS_PER_SAMPLE_16:
533                 {
534                     int c1 = fgetc(p->fp);
535                     if (c1 == EOF) {
536                         return WavFileResultErrorBrokenChunkData;
537                     }
538                     int c2 = fgetc(p->fp);
539                     if (c2 == EOF) {
540                         return WavFileResultErrorBrokenChunkData;
541                     }
542                     uint16_t n = (((uint16_t)c2 << 8) | ((uint16_t)c1 << 0)) ^ (1 << 15);
543                     data->channel_data[i] = (double)n / 0xFFFF;
544                 }
545                 p->data_byte_count-=2;
546                 break;
547             case BITS_PER_SAMPLE_24:
548                 {
549                     int c1 = fgetc(p->fp);
550                     if (c1 == EOF) {
551                         return WavFileResultErrorBrokenChunkData;
552                     }
553                     int c2 = fgetc(p->fp);
554                     if (c2 == EOF) {
555                         return WavFileResultErrorBrokenChunkData;
556                     }
557                     int c3 = fgetc(p->fp);
558                     if (c3 == EOF) {
559                         return WavFileResultErrorBrokenChunkData;
560                     }
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;
563                 }
564                 p->data_byte_count-=3;
565                 break;
566             default:
567                 return WavFileResultErrorUnsupportedBitsPerSample;
568         }
569     }
570     return WavFileResultOK;
571 }
572
573 WavFileResult wavfile_write_info(WAVFILE *p, const wavfile_info_t *info)
574 {
575     WavFileResult result = WavFileResultOK;
576
577     if (p == NULL) {
578         result = WavFileResultErrorInvalidHandler;
579         goto finalize;
580     }
581
582     if (p->info_checked) {
583         result = WavFileResultErrorAlreadyInfoChecked;
584         goto finalize;
585     }
586
587     if (p->mode != WavFileModeWrite) {
588         result = WavFileResultErrorInvalidMode;
589         goto finalize;
590     }
591
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;
598
599     /*
600      *
601      */
602
603     if ((info->audio_format != WAVFILE_AUDIO_FORMAT_PCM) && (info->audio_format != WAVFILE_AUDIO_FORMAT_EXTENSIBLE)) {
604         result = WavFileResultErrorInvalidAudioFormat;
605         goto finalize;
606     }
607
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;
612         goto finalize;
613     }
614
615     if ((info->num_channels * info->sample_rate * (info->bits_per_sample / 8)) != info->byte_rate) {
616         result = WavFileResultErrorInvalidByteRate;
617         goto finalize;
618     }
619
620     /*
621      * [RIFF]
622      * ------------------------------------------
623      * Big endian    4 bytes : Chunk ID
624      * Little endian 4 bytes : Chunk size
625      * Big endian    4 bytes : Format
626      * ------------------------------------------
627      */
628     if (WRITE_U32_BE(p->fp, CHUNK_ID_RIFF) != 0) {
629         result = WavFileResultErrorFileWrite;
630         goto finalize;
631     }
632     if (WRITE_U32_LE(p->fp, 0x00000000) != 0) {
633         result = WavFileResultErrorFileWrite;
634         goto finalize;
635     }
636     if (WRITE_U32_BE(p->fp, RIFF_CHUNK_FORMAT_WAVE) != 0) {
637         result = WavFileResultErrorFileWrite;
638         goto finalize;
639     }
640
641     /*
642      * [fmt]
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
652      *  .                                      .
653      *  .  Additional bytes here (extensible)  .
654      *  .                                      .
655      * ------------------------------------------
656      */
657     switch (info->audio_format) {
658         case WAVFILE_AUDIO_FORMAT_PCM:
659             {
660                 if (WRITE_U32_BE(p->fp, CHUNK_ID_FMT) != 0) {
661                     result = WavFileResultErrorFileWrite;
662                     goto finalize;
663                 }
664                 if (WRITE_U32_LE(p->fp, CHUNK_SIZE_FMT_PCM) != 0) {
665                     result = WavFileResultErrorFileWrite;
666                     goto finalize;
667                 }
668                 if (WRITE_U16_LE(p->fp, info->audio_format) != 0) {
669                     result = WavFileResultErrorFileWrite;
670                     goto finalize;
671                 }
672                 if (WRITE_U16_LE(p->fp, info->num_channels) != 0) {
673                     result = WavFileResultErrorFileWrite;
674                     goto finalize;
675                 }
676                 if (WRITE_U32_LE(p->fp, info->sample_rate) != 0) {
677                     result = WavFileResultErrorFileWrite;
678                     goto finalize;
679                 }
680                 if (WRITE_U32_LE(p->fp, info->byte_rate) != 0) {
681                     result = WavFileResultErrorFileWrite;
682                     goto finalize;
683                 }
684                 if (WRITE_U16_LE(p->fp, info->block_align) != 0) {
685                     result = WavFileResultErrorFileWrite;
686                     goto finalize;
687                 }
688                 if (WRITE_U16_LE(p->fp, info->bits_per_sample) != 0) {
689                     result = WavFileResultErrorFileWrite;
690                     goto finalize;
691                 }
692             }
693             break;
694         case WAVFILE_AUDIO_FORMAT_EXTENSIBLE:
695             {
696                 if (WRITE_U32_BE(p->fp, CHUNK_ID_FMT) != 0) {
697                     result = WavFileResultErrorFileWrite;
698                     goto finalize;
699                 }
700                 if (WRITE_U32_LE(p->fp, CHUNK_SIZE_FMT_EXTENSIBLE) != 0) {
701                     result = WavFileResultErrorFileWrite;
702                     goto finalize;
703                 }
704                 if (WRITE_U16_LE(p->fp, info->audio_format) != 0) {
705                     result = WavFileResultErrorFileWrite;
706                     goto finalize;
707                 }
708                 if (WRITE_U16_LE(p->fp, info->num_channels) != 0) {
709                     result = WavFileResultErrorFileWrite;
710                     goto finalize;
711                 }
712                 if (WRITE_U32_LE(p->fp, info->sample_rate) != 0) {
713                     result = WavFileResultErrorFileWrite;
714                     goto finalize;
715                 }
716                 if (WRITE_U32_LE(p->fp, info->byte_rate) != 0) {
717                     result = WavFileResultErrorFileWrite;
718                     goto finalize;
719                 }
720                 if (WRITE_U16_LE(p->fp, info->block_align) != 0) {
721                     result = WavFileResultErrorFileWrite;
722                     goto finalize;
723                 }
724                 if (WRITE_U16_LE(p->fp, info->bits_per_sample) != 0) {
725                     result = WavFileResultErrorFileWrite;
726                     goto finalize;
727                 }
728                 /*
729                  * Additional bytes for the extensible format.
730                  *
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
735                  */
736                 if (WRITE_U16_LE(p->fp, 22) != 0) {
737                     result = WavFileResultErrorFileWrite;
738                     goto finalize;
739                 }
740                 if (WRITE_U16_LE(p->fp, info->bits_per_sample) != 0) {
741                     result = WavFileResultErrorFileWrite;
742                     goto finalize;
743                 }
744                 if (WRITE_U32_LE(p->fp, 0x00000000) != 0) {
745                     result = WavFileResultErrorFileWrite;
746                     goto finalize;
747                 }
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
753                 };
754                 for (int i = 0; i < sizeof(sub_format); i++) {
755                     fputc((char)sub_format[i], p->fp);
756                 }
757             }
758             break;
759         default:
760             result = WavFileResultErrorInvalidAudioFormat;
761             goto finalize;
762     }
763
764     /*
765      * [data]
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)
772      *                    .
773      *                    .
774      *                    .
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)
779      *                    .
780      *                    .
781      *                    .
782      * Little endian 2 bytes : Sample 2 (Ch.N)
783      * ------------------------------------------
784      */
785     if (WRITE_U32_BE(p->fp, CHUNK_ID_DATA) != 0) {
786         result = WavFileResultErrorFileWrite;
787         goto finalize;
788     }
789     if (WRITE_U32_LE(p->fp, 0x00000000) != 0) {
790         result = WavFileResultErrorFileWrite;
791         goto finalize;
792     }
793
794 finalize:
795     if (WavFileResultOK == result) {
796         p->info_checked = true;
797     }
798     return result;
799 }
800
801 /**
802  * @details 音声データは、どんな形式でも常に0.0から1.0の範囲で正規化して入力される。
803  */
804 WavFileResult wavfile_write_data(WAVFILE *p, const wavfile_data_t *data)
805 {
806     WavFileResult result = WavFileResultOK;
807
808     if (p == NULL) {
809         result = WavFileResultErrorInvalidHandler;
810         goto finalize;
811     }
812
813     if (!p->info_checked) {
814         result = WavFileResultErrorNeedInfoChecked;
815         goto finalize;
816     }
817
818     if (p->mode != WavFileModeWrite) {
819         result = WavFileResultErrorInvalidMode;
820         goto finalize;
821     }
822
823     if (p->info.num_channels != data->num_channels) {
824         result = WavFileResultErrorInvalidNumChannels;
825         goto finalize;
826     }
827
828     for (int i = 0; i < p->info.num_channels; i++) {
829         switch (p->info.bits_per_sample) {
830             case BITS_PER_SAMPLE_8:
831                 {
832                     int n = (int)((double)data->channel_data[i] * 0xFF);
833                     if (n < 0x00) {
834                         n = 0x00;
835                     }
836                     if (0xFF < n) {
837                         n = 0xFF;
838                     }
839                     fputc((char)n, p->fp);
840                 }
841                 p->data_byte_count+=1;
842                 break;
843             case BITS_PER_SAMPLE_16:
844                 {
845                     int n = (int)((double)(data->channel_data[i] * 0xFFFF) - 0x8000);
846                     if (0x7FFF < n) {
847                         n = 0x7FFF;
848                     }
849                     if (n < -0x8000) {
850                         n = -0x8000;
851                     }
852                     fputc(((uint16_t)n >> 0) & 0xff, p->fp);
853                     fputc(((uint16_t)n >> 8) & 0xff, p->fp);
854                 }
855                 p->data_byte_count+=2;
856                 break;
857             case BITS_PER_SAMPLE_24:
858                 {
859                     int n = (int)((double)(data->channel_data[i] * 0xFFFFFF) - 0x800000);
860                     if (0x7FFFFF < n) {
861                         n = 0x7FFFFF;
862                     }
863                     if (n < -0x800000) {
864                         n = -0x800000;
865                     }
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);
869                 }
870                 p->data_byte_count+=3;
871                 break;
872         }
873     }
874     p->data_checked = true;
875
876 finalize:
877     return result;
878 }
879
880 WavFileResult wavfile_close(WAVFILE *p)
881 {
882     WavFileResult result = WavFileResultOK;
883
884     switch (p->mode) {
885         case WavFileModeRead:
886             break;
887         case WavFileModeWrite:
888             if (p->info_checked && p->data_checked) {
889                 switch (p->info.audio_format) {
890                     case WAVFILE_AUDIO_FORMAT_PCM:
891                         {
892                             /*
893                              * Fill the RIFF chunk size.
894                              */
895                             if (fseek(p->fp, 4L, SEEK_SET) == -1) {
896                                 result = WavFileResultErrorFileWrite;
897                                 goto finalize;
898                             }
899                             if (WRITE_U32_LE(p->fp, 4 + (8 + CHUNK_SIZE_FMT_PCM) + (8 + p->data_byte_count)) != 0) {
900                                 result = WavFileResultErrorFileWrite;
901                                 goto finalize;
902                             }
903
904                             /*
905                              * Fill the data sub chunk size.
906                              */
907                             if (fseek(p->fp, 12 + (8 + CHUNK_SIZE_FMT_PCM) + 4, SEEK_SET) == -1) {
908                                 result = WavFileResultErrorFileWrite;
909                                 goto finalize;
910                             }
911                             if (WRITE_U32_LE(p->fp, p->data_byte_count) != 0) {
912                                 result = WavFileResultErrorFileWrite;
913                                 goto finalize;
914                             }
915                         }
916                         break;
917                     case WAVFILE_AUDIO_FORMAT_EXTENSIBLE:
918                         {
919                             /*
920                              * Fill the RIFF chunk size.
921                              */
922                             if (fseek(p->fp, 4L, SEEK_SET) == -1) {
923                                 result = WavFileResultErrorFileWrite;
924                                 goto finalize;
925                             }
926                             if (WRITE_U32_LE(p->fp, 4 + (8 + CHUNK_SIZE_FMT_EXTENSIBLE) + (8 + p->data_byte_count)) != 0) {
927                                 result = WavFileResultErrorFileWrite;
928                                 goto finalize;
929                             }
930
931                             /*
932                              * Fill the data sub chunk size.
933                              */
934                             if (fseek(p->fp, 12 + (8 + CHUNK_SIZE_FMT_EXTENSIBLE) + 4, SEEK_SET) == -1) {
935                                 result = WavFileResultErrorFileWrite;
936                                 goto finalize;
937                             }
938                             if (WRITE_U32_LE(p->fp, p->data_byte_count) != 0) {
939                                 result = WavFileResultErrorFileWrite;
940                                 goto finalize;
941                             }
942                         }
943                         break;
944                 }
945             }
946             break;
947     }
948
949 finalize:
950     fclose(p->fp);
951     free(p);
952     return result;
953 }
954
955 void wavfile_result_string(const WavFileResult result, char *buf, size_t siz)
956 {
957     switch (result) {
958         case WavFileResultOK:
959             strcpy(buf, "OK.");
960             break;
961         case WavFileResultErrorInvalidFileName:
962             strcpy(buf, "Invalid file name found.");
963             break;
964         case WavFileResultErrorMemoryAllocation:
965             strcpy(buf, "Memory allocation error.");
966             break;
967         case WavFileResultErrorFileOpen:
968             strcpy(buf, "File open error found.");
969             break;
970         case WavFileResultErrorFileWrite:
971             strcpy(buf, "File write error found.");
972             break;
973         case WavFileResultErrorBrokenChunkId:
974             strcpy(buf, "Broken chunk ID found.");
975             break;
976         case WavFileResultErrorBrokenChunkSize:
977             strcpy(buf, "Borken chunk size found.");
978             break;
979         case WavFileResultErrorBrokenChunkData:
980             strcpy(buf, "Borken chunk data found.");
981             break;
982         case WavFileResultErrorBrokenFormatId:
983             strcpy(buf, "Broken format ID found.");
984             break;
985         case WavFileResultErrorInvalidFormatId:
986             strcpy(buf, "Invalid format ID found.");
987             break;
988         case WavFileResultErrorBrokenAudioFormat:
989             strcpy(buf, "Broken audio format found.");
990             break;
991         case WavFileResultErrorInvalidAudioFormat:
992             strcpy(buf, "Invalid audio format found.");
993             break;
994         case WavFileResultErrorInvalidNumChannels:
995             strcpy(buf, "Invalid number of channels found.");
996             break;
997         case WavFileResultErrorBrokenNumChannels:
998             strcpy(buf, "Broken number of channels found.");
999             break;
1000         case WavFileResultErrorBrokenSampleRate:
1001             strcpy(buf, "Broken sample rate found.");
1002             break;
1003         case WavFileResultErrorBrokenByteRate:
1004             strcpy(buf, "Broken byte rate found.");
1005             break;
1006         case WavFileResultErrorInvalidByteRate:
1007             strcpy(buf, "Invalid byte rate found.");
1008             break;
1009         case WavFileResultErrorBrokenBlockAlign:
1010             strcpy(buf, "Broken block alignment found.");
1011             break;
1012         case WavFileResultErrorBrokenBitsPerSample:
1013             strcpy(buf, "Broken bits per sample found.");
1014             break;
1015         case WavFileResultErrorUnsupportedBitsPerSample:
1016             strcpy(buf, "Unsupported bits per sample found.");
1017             break;
1018         case WavFileResultErrorAlreadyInfoChecked:
1019             strcpy(buf, "Already checked info.");
1020             break;
1021         case WavFileResultErrorAlreadyDataChecked:
1022             strcpy(buf, "Already checked data.");
1023             break;
1024         case WavFileResultErrorNoDataChunk:
1025             strcpy(buf, "No data chunk.");
1026             break;
1027         case WavFileResultErrorInvalidMode:
1028             strcpy(buf, "Invalid mode.");
1029             break;
1030         case WavFileResultErrorNeedInfoChecked:
1031             strcpy(buf, "Need check info.");
1032             break;
1033         case WavFileResultErrorNeedDataChecked:
1034             strcpy(buf, "Need check data.");
1035             break;
1036         case WavFileResultErrorInvalidHandler:
1037             strcpy(buf, "Invalid handler.");
1038             break;
1039         default:
1040             strcpy(buf, "Unkonwn error found.");
1041             break;
1042     }
1043 }
1044