/* * wav_header - write the header of a wav file * * Copyright (C) 2010 Antonio Ospite * * This program is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What The Fuck You Want * To Public License, Version 2, as published by Sam Hocevar. See * http://sam.zoy.org/wtfpl/COPYING for more details. */ #include #include #include /* This is the logical arrangement of the struct but we are splitting it * because it is easier to handle the variable length extradata that way. * * strongly inspired by http://www.mpg123.de/mpg123/mpg123/wav.c */ #if 0 struct _RIFF { char riffheader[4]; uint32_t WAVElen; struct _WAVE { char fmtheader[8]; uint32_t fmtlen; struct _fmt { uint16_t wFormatTag; uint16_t nChannels; uint32_t nSamplesPerSec; uint32_t nAvgBytesPerSec; uint16_t nBlockAlign; uint16_t wBitsPerSample; uint16_t cbSize; /* cbSize = sizeof(extradata) */ uint8_t extradata[]; } fmt; struct _data { char dataheader[4]; uint32_t datalen; } data; /* from here you insert your PCM data */ } WAVE; }; #endif struct fmt { uint16_t wFormatTag; uint16_t nChannels; uint32_t nSamplesPerSec; uint32_t nAvgBytesPerSec; uint16_t nBlockAlign; uint16_t wBitsPerSample; uint16_t cbSize; uint8_t extradata[]; } __attribute__((__packed__)); struct WAVE { char fmtheader[8]; uint32_t fmtlen; } __attribute__((__packed__)); struct RIFF { char riffheader[4]; uint32_t WAVElen; }; struct data { char dataheader[4]; uint32_t datalen; }; struct extradata { uint16_t len; /* same storage size as fmt.cbSize */ uint8_t data[]; }; static inline void fwrite_le16(uint16_t x, FILE *file) { uint16_t tmp = htole16(x); fwrite(&tmp, sizeof(tmp), 1, file); } static inline void fwrite_le32(uint32_t x, FILE *file) { uint32_t tmp = htole32(x); fwrite(&tmp, sizeof(tmp), 1, file); } void write_wav_header(FILE *file, struct fmt *format, struct extradata *extradata, unsigned data_len) { struct RIFF r = { { 'R','I','F','F' } , 0 }; struct WAVE w = { { 'W','A','V','E','f','m','t',' ' }, 0 }; struct data d = { { 'd','a','t','a' }, 0 }; format->cbSize = extradata->len; w.fmtlen = sizeof(*format) + format->cbSize; r.WAVElen = sizeof(w) + w.fmtlen + sizeof(d); d.datalen = data_len; /* RIFF */ fwrite(&r.riffheader, 1, 4, file); fwrite_le32(r.WAVElen, file); /* WAVE */ fwrite(&w.fmtheader, 1, 8, file); fwrite_le32(w.fmtlen, file); /* fmt */ fwrite_le16(format->wFormatTag, file); fwrite_le16(format->nChannels, file); fwrite_le32(format->nSamplesPerSec, file); fwrite_le32(format->nAvgBytesPerSec, file); fwrite_le16(format->nBlockAlign, file); fwrite_le16(format->wBitsPerSample, file); fwrite_le16(format->cbSize, file); /* extradata */ fwrite(extradata->data, 1, extradata->len, file); /* data */ fwrite(&d.dataheader, 1, 4, file); fwrite_le32(d.datalen, file); } int main(void) { struct fmt format = { .wFormatTag = 0x161, .nChannels = 2, .nSamplesPerSec = 48000, .nAvgBytesPerSec = 192000 / 8, .wBitsPerSample = 16, .nBlockAlign = 8192, .cbSize = 0, }; static struct extradata codec_private_data = { .len = 10, .data = "\x00\x88\x00\x00\x0f\x00\x00\x00\x00\x00", }; unsigned data_len; data_len = 70680576; write_wav_header(stdout, &format, &codec_private_data, data_len); return 0; }