10 #define WAVWRITER_HPP_
34 template<
class Container1d,
typename T>
50 :
base(),wave_(),outfile(),finished(0),total_nb_elem(0),initialized(false),output_audio_size_(0)
51 {outfile.exceptions(std::ofstream::failbit | std::ofstream::badbit);}
60 WavWriter(std::string output_filename,
const WAVE_HEADER & wave,
61 std::size_t output_audio_size);
72 WavWriter(std::string output_filename,
short sample_rate,
73 short byte_per_sample, std::size_t output_audio_size);
87 void initialize(
const WAVE_HEADER & wave, std::size_t output_audio_size);
95 void initialize(
short sample_rate,
short byte_per_sample, std::size_t output_audio_size);
138 std::ofstream outfile;
142 std::size_t total_nb_elem;
146 std::size_t output_audio_size_;
150 void init_wave(
short sample_rate,
short byte_per_sample);
158 template<
class Container1d,
typename T>
161 std::size_t output_audio_size)
162 :
base(output_filename),wave_(wave),outfile(),finished(0),total_nb_elem(0),initialized(false),
163 output_audio_size_(output_audio_size)
165 outfile.exceptions(std::ofstream::failbit | std::ofstream::badbit);
169 template<
class Container1d,
typename T>
172 short byte_per_sample, std::size_t output_audio_size)
173 :
base(output_filename),wave_(),outfile(),finished(0),total_nb_elem(0),initialized(false),
174 output_audio_size_(output_audio_size)
176 outfile.exceptions(std::ofstream::failbit | std::ofstream::badbit);
177 init_wave(sample_rate,byte_per_sample);
181 template<
class Container1d,
typename T>
184 wave_.format_header.sample_rate =
static_cast<int32
>(sample_rate);
185 wave_.format_header.bits_per_sample =
static_cast<int16
>(byte_per_sample);
186 wave_.format_header.format = 1;
187 wave_.format_header.num_channels = 1;
188 wave_.format_header.align = wave_.format_header.bits_per_sample / 8;
189 wave_.format_header.byte_rate = wave_.format_header.sample_rate
190 *
static_cast<int32
>(wave_.format_header.align);
192 wave_.riff_header.chunk_id[0] =
'R';
193 wave_.riff_header.chunk_id[1] =
'I';
194 wave_.riff_header.chunk_id[2] =
'F';
195 wave_.riff_header.chunk_id[3] =
'F';
196 wave_.riff_header.chunk_id[4] =
'\0';
197 wave_.riff_header.chunk_size = 36 +
static_cast<int32
>(output_audio_size_)
198 * static_cast<int32>(wave_.format_header.align);
199 wave_.riff_header.format[0] =
'W';
200 wave_.riff_header.format[1] =
'A';
201 wave_.riff_header.format[2] =
'V';
202 wave_.riff_header.format[3] =
'E';
203 wave_.riff_header.format[4] =
'\0';
205 wave_.format_header.chunk_id[0] =
'f';
206 wave_.format_header.chunk_id[1] =
'm';
207 wave_.format_header.chunk_id[2] =
't';
208 wave_.format_header.chunk_id[3] =
' ';
209 wave_.format_header.chunk_id[4] =
'\0';
210 wave_.format_header.chunk_size = 16;
212 wave_.data_header.chunk_id[0] =
'd';
213 wave_.data_header.chunk_id[1] =
'a';
214 wave_.data_header.chunk_id[2] =
't';
215 wave_.data_header.chunk_id[3] =
'a';
216 wave_.data_header.chunk_id[4] =
'\0';
217 wave_.data_header.chunk_size =
static_cast<int32
>(output_audio_size_) *
218 static_cast<int32>(wave_.format_header.align);
221 template<
class Container1d,
typename T>
224 short byte_per_sample, std::size_t output_audio_size){
225 init_wave(sample_rate,byte_per_sample);
226 output_audio_size_ = output_audio_size;
230 template<
class Container1d,
typename T>
234 output_audio_size_ = output_audio_size;
239 template<
class Container1d,
typename T>
244 outfile.open(this->output_filename_.c_str(), std::ofstream::binary);
247 std::ostringstream err;
249 slip::slip_exception exc(std::string(
"slip"), std::string(
"WavWriter::initialize()"), err.str());
254 outfile.write(
"RIFF",4);
256 int32 chunk_size = 36 +
static_cast<int32
>(output_audio_size_)
257 * static_cast<int32>(wave_.format_header.align);
258 #ifdef REVERSE_ENDIANISM
260 chunk_size = SWAP_32(chunk_size);
262 outfile.write(reinterpret_cast<char8*>(&chunk_size),4);
263 outfile.write(
"WAVE",4);
266 outfile.write(
"fmt ",4);
268 int16 audiofmt = wave_.format_header.format;
269 int16 numchannel = wave_.format_header.num_channels;
270 int32 freq = wave_.format_header.sample_rate;
271 int16 bytpersample = wave_.format_header.bits_per_sample;
272 int16 bytperbl = numchannel * bytpersample / 8;
273 int32 bytrate = freq *
static_cast<int32
>(bytperbl);
275 #ifdef REVERSE_ENDIANISM
276 chunk_size = SWAP_32(chunk_size);
277 audiofmt = SWAP_16(audiofmt);
278 numchannel = SWAP_16(numchannel);
279 freq = SWAP_32(freq);
280 bytrate = SWAP_32(bytrate);
281 bytperbl = SWAP_16(bytperbl);
282 bytpersample = SWAP_16(bytpersample);
284 outfile.write(reinterpret_cast<char8*>(&chunk_size),4);
285 outfile.write(reinterpret_cast<char8*>(&audiofmt),2);
286 outfile.write(reinterpret_cast<char8*>(&numchannel),2);
287 outfile.write(reinterpret_cast<char8*>(&freq),4);
288 outfile.write(reinterpret_cast<char8*>(&bytrate),4);
289 outfile.write(reinterpret_cast<char8*>(&bytperbl),2);
290 outfile.write(reinterpret_cast<char8*>(&bytpersample),2);
293 outfile.write(
"data",4);
294 chunk_size = output_audio_size_ *
static_cast<std::size_t
>(bytperbl);
295 #ifdef REVERSE_ENDIANISM
296 chunk_size = SWAP_32(chunk_size);
298 outfile.write(reinterpret_cast<char8*>(&chunk_size),4);
306 template<
class Container1d,
typename T>
310 std::ostringstream err;
311 err <<
FILE_WRITE_ERROR << this->output_filename_ <<
" | The writer to be initialized before writing.";
312 slip_exception exc(std::string(
"slip"), std::string(
"WavWriter::write()"), err.str());
319 total_nb_elem += data.size();
321 if(output_audio_size_ < total_nb_elem){
322 std::ostringstream err;
323 err <<
FILE_WRITE_ERROR << this->output_filename_ <<
" | Allocation problem during wav writing.";
324 slip_exception exc(std::string(
"slip"), std::string(
"WavWriter::write()"), err.str());
329 std::size_t bps =
static_cast<std::size_t
>(wave_.format_header.bits_per_sample);
330 std::size_t nbch =
static_cast<std::size_t
>(wave_.format_header.num_channels);
331 std::size_t size_d = data.size();
332 double max =
static_cast<double>(*std::max_element(data.begin(),data.end()));
333 double min =
static_cast<double>(*std::min_element(data.begin(),data.end()));
334 double delta = max -
min;
337 double delta32 = max32 - min32;
340 double delta16 = max16 - min16;
341 double max8 =
static_cast<double>(255);
345 if ((max <= max8) && (min >= 0)){
346 for(std::size_t j=0; j<size_d; j++){
347 for(std::size_t i=0;i<nbch;i++){
348 char d =
static_cast<char>(data[j]);
349 outfile.write(reinterpret_cast<char8*>(&d),1);
353 double alpha = max8/delta;
354 for(std::size_t j=0; j<size_d; j++){
355 char d =
static_cast<char>(max8 - alpha*(max -
static_cast<double>(data[j])));
356 for(std::size_t i=0;i<nbch;i++){
357 outfile.write(reinterpret_cast<char8*>(&d),1);
365 if ((max <= max16) && (min >= min16)){
366 for(std::size_t j=0; j<size_d; j++){
367 for(std::size_t i=0;i<nbch;i++){
368 int16 d =
static_cast<int16
>(data[j]);
369 #ifdef REVERSE_ENDIANISM
372 outfile.write(reinterpret_cast<char8*>(&d),2);
376 double alpha = delta16/delta;
377 for(std::size_t j=0; j<size_d; ++j){
378 int16 d =
static_cast<int16
>(max16 - alpha*(max -
static_cast<double>(data[j])));
379 #ifdef REVERSE_ENDIANISM
382 for(std::size_t i=0;i<nbch;i++){
383 outfile.write(reinterpret_cast<char8*>(&d),2);
391 if ((max <= max32) && (min >= min32)){
392 for(std::size_t j=0; j<size_d; j++){
393 for(std::size_t i=0;i<nbch;i++){
394 int32 d =
static_cast<int32
>(d);
395 #ifdef REVERSE_ENDIANISM
398 outfile.write(reinterpret_cast<char8*>(&d),4);
402 double alpha = delta32/delta;
403 for(std::size_t j=0; j<size_d; ++j){
404 int32 d =
static_cast<int32
>(max32 - alpha*(max -
static_cast<double>(data[j])));
405 #ifdef REVERSE_ENDIANISM
408 for(std::size_t i=0;i<nbch;i++){
409 outfile.write(reinterpret_cast<char8*>(&d),4);
416 std::ostringstream err;
417 err <<
FILE_WRITE_ERROR << this->output_filename_ <<
" | The specified bit per sample is not valid.";
418 slip_exception exc(std::string(
"slip"), std::string(
"WavWriter::write()"), err.str());
423 if (total_nb_elem == output_audio_size_)
429 template<
class Container1d,
typename T>
433 if (outfile.is_open())
435 wave_ = WAVE_HEADER();
438 output_audio_size_ = 0;
void release()
release the writing process. Has to be called when an audio file has been fully written.
T & min(const GrayscaleImage< T > &M1)
Returns the min element of a GrayscaleImage.
const std::string FILE_WRITE_ERROR
standard exception extension name have been changed to eliminate conflicts with QT ...
Contains the container writer base class.
const std::string FILE_OPEN_ERROR
Some definitions specific to wav files manipulations.
int write(const container_type &data)
write function. This function write the data within the output file after the previous one...
Container1d container_type
const WAVE_HEADER & get_header() const
Get the wav file header.
void set_header(const WAVE_HEADER &wave)
Set the wav header file.
ContainerWriter is the base class of the writer classes. All the writers are working the same way: ...
void initialize(const WAVE_HEADER &wave, std::size_t output_audio_size)
initialized the writing process. Has to be called before the first write() call of a given array...
ContainerWriter< Container1d, T > base
T & max(const GrayscaleImage< T > &M1)
Returns the max element of a GrayscaleImage.
WavWriter is the wave array writer.