1 // WAVWriter.cpp: .wav audio writer
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
4 // Free Software Foundation, Inc
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "WAVWriter.h"
23 #include <fstream> // for composition (file_stream)
26 #include "GnashException.h" // for SoundException
27 #include "log.h" // will import boost::format too
32 namespace { // anonymous
34 // Header of a wave file
35 // http://ftp.iptel.org/pub/sems/doc/full/current/wav__hdr_8c-source.html
37 char rID
[4]; // 'RIFF'
39 char wID
[4]; // 'WAVE'
40 char fId
[4]; // 'fmt '
41 std::uint32_t pcm_header_len
; // varies...
42 std::int16_t wFormatTag
;
43 std::int16_t nChannels
; // 1,2 for stereo data is (l,r) pairs
44 std::uint32_t nSamplesPerSec
;
45 std::uint32_t nAvgBytesPerSec
;
46 std::int16_t nBlockAlign
;
47 std::int16_t nBitsPerSample
;
51 // http://ftp.iptel.org/pub/sems/doc/full/current/wav__hdr_8c-source.html
53 char dId
[4]; // 'data' or 'fact'
57 } // end of anonymous namespace
60 WAVWriter::WAVWriter(const std::string
& wavefile
)
62 file_stream
.open(wavefile
.c_str());
63 if (file_stream
.fail()) {
64 boost::format fmt
= boost::format(_("Unable to write file %1%"))
66 throw SoundException(fmt
.str());
70 write_wave_header(file_stream
);
71 log_debug("Created 44100 Hz 16-bit stereo wave file: %s",
77 WAVWriter::~WAVWriter()
80 // Seeking back to the beginning, in order to rewrite the header with
81 // information accumulated during writing.
83 if (file_stream
.fail()) {
84 log_error("WAVWriter: Failed to flush audio dump metadata, resulting file would be incomplete");
87 write_wave_header(file_stream
);
97 WAVWriter::pushSamples(std::int16_t* from
, unsigned int nSamples
)
99 // NOTE: if muted, the samples will be silent already
100 std::uint8_t* stream
= reinterpret_cast<std::uint8_t*>(from
);
101 unsigned int len
= nSamples
*2;
102 file_stream
.write((char*) stream
, len
);
108 WAVWriter::write_wave_header(std::ofstream
& outfile
)
111 // allocate wav header
117 std::memcpy(wav
.rID
, "RIFF", 4);
118 std::memcpy(wav
.wID
, "WAVE", 4);
119 std::memcpy(wav
.fId
, "fmt ", 4);
122 wav
.nBitsPerSample
= 16;
123 wav
.nSamplesPerSec
= 44100;
124 wav
.nAvgBytesPerSec
= 44100;
125 wav
.nAvgBytesPerSec
*= wav
.nBitsPerSample
/ 8;
126 wav
.nAvgBytesPerSec
*= 2;
128 wav
.nBlockAlign
= 2 * wav
.nBitsPerSample
/ 8;
130 // setup data chunk header
131 std::memcpy(chk
.dId
, "data", 4);
132 chk
.dLen
= data_size
;
134 // setup wav header's size field
135 wav
.pcm_header_len
= 16;
136 wav
.rLen
= sizeof(WAV_HDR
) - 8 + sizeof(CHUNK_HDR
) + chk
.dLen
;
138 /* write riff/wav header */
139 outfile
.write(wav
.rID
, 4);
140 write_uint32(outfile
, wav
.rLen
);
141 outfile
.write(wav
.wID
, 4);
142 outfile
.write(wav
.fId
, 4);
143 write_uint32(outfile
, wav
.pcm_header_len
);
144 write_uint16(outfile
, wav
.wFormatTag
);
145 write_uint16(outfile
, wav
.nChannels
);
146 write_uint32(outfile
, wav
.nSamplesPerSec
);
147 write_uint32(outfile
, wav
.nAvgBytesPerSec
);
148 write_uint16(outfile
, wav
.nBlockAlign
);
149 write_uint16(outfile
, wav
.nBitsPerSample
);
151 /* write chunk header */
152 outfile
.write(chk
.dId
, 4);
153 write_uint32(outfile
, chk
.dLen
);
157 } // gnash.sound namespace