1aac2e99bcdc9c209e50605258d591c232023281
[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 <stdlib.h>
15 #include <stdint.h>
16 #include <string.h>
17
18 #include <endian.h>
19
20 /* This is the logical arrangement of the struct but we are splitting it
21  * because it is easier to handle the variable length extradata that way.
22  *
23  * strongly inspired by http://www.mpg123.de/mpg123/mpg123/wav.c
24  */
25 #if 0
26 struct _RIFF {
27         char riffheader[4];
28         uint32_t WAVElen;
29         struct _WAVE {
30                 char fmtheader[8];
31                 uint32_t fmtlen;
32                 struct _fmt {
33                         uint16_t wFormatTag;
34                         uint16_t nChannels;
35                         uint32_t nSamplesPerSec;
36                         uint32_t nAvgBytesPerSec;
37                         uint16_t nBlockAlign;
38                         uint16_t wBitsPerSample;
39                         uint16_t cbSize; /* cbSize = sizeof(extradata) */
40                         uint8_t extradata[];
41                 } fmt;
42                 struct _data
43                 {
44                         char dataheader[4];
45                         uint32_t datalen;
46                 } data;
47                 /* from here you insert your PCM data */
48         } WAVE;
49 };
50 #endif
51
52 struct fmt {
53         uint16_t wFormatTag;
54         uint16_t nChannels;
55         uint32_t nSamplesPerSec;
56         uint32_t nAvgBytesPerSec;
57         uint16_t nBlockAlign;
58         uint16_t wBitsPerSample;
59         uint16_t cbSize;
60         uint8_t extradata[];
61 }  __attribute__((__packed__));
62
63 struct WAVE {
64         char fmtheader[8];
65         uint32_t fmtlen;
66 } __attribute__((__packed__));
67
68 struct RIFF {
69         char riffheader[4];
70         uint32_t WAVElen;
71 };
72
73 struct data {
74         char dataheader[4];
75         uint32_t datalen;
76 };
77
78 struct extradata {
79         uint16_t len; /* same storage size as fmt.cbSize */
80         uint8_t data[];
81 };
82
83
84 void write_wav_header(FILE *file, struct fmt *format,
85                 struct extradata *extradata, unsigned data_len)
86 {
87         struct RIFF r = {
88                 { 'R','I','F','F' } ,
89                 0
90         };
91
92         struct WAVE w = {
93                 { 'W','A','V','E','f','m','t',' ' },
94                 0
95         };
96
97         struct data d = {
98                 { 'd','a','t','a' },
99                 0
100         };
101
102         format->cbSize = extradata->len;
103         w.fmtlen = sizeof(*format) + format->cbSize;
104         r.WAVElen = sizeof(w) + w.fmtlen + sizeof(d);
105         d.datalen = data_len;
106
107         /* RIFF */
108         fwrite(&r.riffheader, 1, 4, file);
109         fwrite(&htole32(r.WAVElen), 4, 1, file);
110
111         /* WAVE */
112         fwrite(&w.fmtheader, 1, 8, file);
113         fwrite(&htole32(w.fmtlen), 4, 1, file);
114
115         /* fmt */
116         fwrite(&htole16(format->wFormatTag), 2, 1, file);
117         fwrite(&htole16(format->nChannels), 2, 1, file);
118         fwrite(&htole32(format->nSamplesPerSec), 4, 1, file);
119         fwrite(&htole32(format->nAvgBytesPerSec), 4, 1, file);
120         fwrite(&htole16(format->nBlockAlign), 2, 1, file);
121         fwrite(&htole16(format->wBitsPerSample), 2, 1, file);
122         fwrite(&htole16(format->cbSize), 2, 1, file);
123
124         /* extradata */
125         fwrite(extradata->data, 1, extradata->len, file);
126
127         /* data */
128         fwrite(&d.dataheader, 1, 4, file);
129         fwrite(&htole32(d.datalen), 4, 1, file);
130 }
131
132 int main(void)
133 {
134         struct fmt format = {
135                 .wFormatTag = 0x161,
136                 .nChannels = 2,
137                 .nSamplesPerSec = 48000,
138                 .nAvgBytesPerSec = 192000 / 8,
139                 .wBitsPerSample = 16,
140                 .nBlockAlign = 8192,
141                 .cbSize = 0,
142         };
143
144         static struct extradata codec_private_data = {
145                 .len = 10,
146                 .data = "\x00\x88\x00\x00\x0f\x00\x00\x00\x00\x00",
147         };
148
149         unsigned data_len;
150
151         data_len = 70680576;
152
153         write_wav_header(stdout, &format, &codec_private_data, data_len);
154
155         return 0;
156 }