Make automated FSCommand invocation tests show player-side output.
[gnash.git] / libsound / WAVWriter.cpp
blob62ec9caed1a8c6f4ffb21ea80ef17ccac222c72c
1 // WAVWriter.cpp: .wav audio writer
2 //
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
4 // Free Software Foundation, Inc
5 //
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.
15 //
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"
22 #include <cstdint>
23 #include <fstream> // for composition (file_stream)
24 #include <iostream>
26 #include "GnashException.h" // for SoundException
27 #include "log.h" // will import boost::format too
29 namespace gnash {
30 namespace sound {
32 namespace { // anonymous
34 // Header of a wave file
35 // http://ftp.iptel.org/pub/sems/doc/full/current/wav__hdr_8c-source.html
36 struct WAV_HDR {
37 char rID[4]; // 'RIFF'
38 std::uint32_t rLen;
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;
50 // Chunk of wave file
51 // http://ftp.iptel.org/pub/sems/doc/full/current/wav__hdr_8c-source.html
52 struct CHUNK_HDR{
53 char dId[4]; // 'data' or 'fact'
54 std::uint32_t dLen;
57 } // end of anonymous namespace
59 /* public */
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%"))
65 % wavefile;
66 throw SoundException(fmt.str());
68 else {
69 data_size = 0;
70 write_wave_header(file_stream);
71 log_debug("Created 44100 Hz 16-bit stereo wave file: %s",
72 wavefile);
76 /* public */
77 WAVWriter::~WAVWriter()
79 if (file_stream) {
80 // Seeking back to the beginning, in order to rewrite the header with
81 // information accumulated during writing.
82 file_stream.seekp(0);
83 if (file_stream.fail()) {
84 log_error("WAVWriter: Failed to flush audio dump metadata, resulting file would be incomplete");
86 else {
87 write_wave_header(file_stream);
90 // close the stream
91 file_stream.close();
95 /* public */
96 void
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);
103 data_size += len;
106 /* private */
107 void
108 WAVWriter::write_wave_header(std::ofstream& outfile)
111 // allocate wav header
112 WAV_HDR wav;
113 CHUNK_HDR chk;
115 // setup wav header
116 // CID 1149094
117 std::memcpy(wav.rID, "RIFF", 4);
118 std::memcpy(wav.wID, "WAVE", 4);
119 std::memcpy(wav.fId, "fmt ", 4);
121 wav.wFormatTag = 1;
122 wav.nBitsPerSample = 16;
123 wav.nSamplesPerSec = 44100;
124 wav.nAvgBytesPerSec = 44100;
125 wav.nAvgBytesPerSec *= wav.nBitsPerSample / 8;
126 wav.nAvgBytesPerSec *= 2;
127 wav.nChannels = 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
158 } // namespace gnash