e21841a709ddcee6072700cff2cee2e71f829a9b
[wav_header.git] / wav_header.c
1 /*
2  * wav_header - write the header of a wav file
3  *
4  * Copyright (C) 2010  Antonio Ospite <ospite@studenti.unina.it>
5  *
6  * This program is free software. It comes without any warranty, to
7  * the extent permitted by applicable law. You can redistribute it
8  * and/or modify it under the terms of the Do What The Fuck You Want
9  * To Public License, Version 2, as published by Sam Hocevar. See
10  * http://sam.zoy.org/wtfpl/COPYING for more details.
11  */
12
13 #include <stdio.h>
14 #include <stdint.h>
15
16 #include <endian.h>
17
18 /* This is the logical arrangement of the struct but we are splitting it
19  * because it is easier to handle the variable length extradata that way.
20  *
21  * strongly inspired by http://www.mpg123.de/mpg123/mpg123/wav.c
22  */
23 #if 0
24 struct _RIFF {
25         char riffheader[4];
26         uint32_t WAVElen;
27         struct _WAVE {
28                 char fmtheader[8];
29                 uint32_t fmtlen;
30                 struct _fmt {
31                         uint16_t wFormatTag;
32                         uint16_t nChannels;
33                         uint32_t nSamplesPerSec;
34                         uint32_t nAvgBytesPerSec;
35                         uint16_t nBlockAlign;
36                         uint16_t wBitsPerSample;
37                         uint16_t cbSize; /* cbSize = sizeof(extradata) */
38                         uint8_t extradata[];
39                 } fmt;
40                 struct _data
41                 {
42                         char dataheader[4];
43                         uint32_t datalen;
44                 } data;
45                 /* from here you insert your PCM data */
46         } WAVE;
47 };
48 #endif
49
50 struct fmt {
51         uint16_t wFormatTag;
52         uint16_t nChannels;
53         uint32_t nSamplesPerSec;
54         uint32_t nAvgBytesPerSec;
55         uint16_t nBlockAlign;
56         uint16_t wBitsPerSample;
57         uint16_t cbSize;
58         uint8_t extradata[];
59 }  __attribute__((__packed__));
60
61 struct WAVE {
62         char fmtheader[8];
63         uint32_t fmtlen;
64 } __attribute__((__packed__));
65
66 struct RIFF {
67         char riffheader[4];
68         uint32_t WAVElen;
69 };
70
71 struct data {
72         char dataheader[4];
73         uint32_t datalen;
74 };
75
76 struct extradata {
77         uint16_t len; /* same storage size as fmt.cbSize */
78         uint8_t data[];
79 };
80
81
82 void write_wav_header(FILE *file, struct fmt *format,
83                 struct extradata *extradata, unsigned data_len)
84 {
85         struct RIFF r = {
86                 { 'R','I','F','F' } ,
87                 0
88         };
89
90         struct WAVE w = {
91                 { 'W','A','V','E','f','m','t',' ' },
92                 0
93         };
94
95         struct data d = {
96                 { 'd','a','t','a' },
97                 0
98         };
99
100         format->cbSize = extradata->len;
101         w.fmtlen = sizeof(*format) + format->cbSize;
102         r.WAVElen = sizeof(w) + w.fmtlen + sizeof(d);
103         d.datalen = data_len;
104
105         /* RIFF */
106         fwrite(&r.riffheader, 1, 4, file);
107         fwrite(&htole32(r.WAVElen), 4, 1, file);
108
109         /* WAVE */
110         fwrite(&w.fmtheader, 1, 8, file);
111         fwrite(&htole32(w.fmtlen), 4, 1, file);
112
113         /* fmt */
114         fwrite(&htole16(format->wFormatTag), 2, 1, file);
115         fwrite(&htole16(format->nChannels), 2, 1, file);
116         fwrite(&htole32(format->nSamplesPerSec), 4, 1, file);
117         fwrite(&htole32(format->nAvgBytesPerSec), 4, 1, file);
118         fwrite(&htole16(format->nBlockAlign), 2, 1, file);
119         fwrite(&htole16(format->wBitsPerSample), 2, 1, file);
120         fwrite(&htole16(format->cbSize), 2, 1, file);
121
122         /* extradata */
123         fwrite(extradata->data, 1, extradata->len, file);
124
125         /* data */
126         fwrite(&d.dataheader, 1, 4, file);
127         fwrite(&htole32(d.datalen), 4, 1, file);
128 }
129
130 int main(void)
131 {
132         struct fmt format = {
133                 .wFormatTag = 0x161,
134                 .nChannels = 2,
135                 .nSamplesPerSec = 48000,
136                 .nAvgBytesPerSec = 192000 / 8,
137                 .wBitsPerSample = 16,
138                 .nBlockAlign = 8192,
139                 .cbSize = 0,
140         };
141
142         static struct extradata codec_private_data = {
143                 .len = 10,
144                 .data = "\x00\x88\x00\x00\x0f\x00\x00\x00\x00\x00",
145         };
146
147         unsigned data_len;
148
149         data_len = 70680576;
150
151         write_wav_header(stdout, &format, &codec_private_data, data_len);
152
153         return 0;
154 }