IT++ Logo
audiofile.cpp
Go to the documentation of this file.
1 
29 #include <itpp/srccode/audiofile.h>
30 #include <itpp/base/converters.h>
31 #include <itpp/base/ittypes.h>
32 #include <itpp/base/itassert.h>
33 #include <iostream>
34 
36 namespace itpp
37 {
38 
39 //magic id of snd file header
40 static const uint32_t snd_magic = 0x2e736e64;
41 //maximum length of annotation to extract from snd file
42 static const std::size_t max_annotation_length = 1024;
43 
45 //
46 // Audio_Samples_Reader - templated implementation of Audio_Samples_Reader_If
47 //
49 template<typename Binary_In_Stream, Audio_Encoding Encoding>
50 class Audio_Samples_Reader : public audiofile_details::Audio_Samples_Reader_If
51 {
52 public:
53  Audio_Samples_Reader(Binary_In_Stream& str, std::streamoff start, int nc):
54  _str(str), _start_pos(start), _num_channels(nc), _cur_pos(0){}
55  bool read_sample(double& s, int ch);
56  //Read n samples from audio channel ch
57  vec read_channel(int n, int ch);
58  mat read(int n);
59  virtual std::streamoff tell() const;
60  virtual bool seek(std::streamoff n);
61  virtual std::streamoff num_samples();
62 private:
63  static const std::size_t sample_size = Audio_Sample<Encoding>::enc_sample_size;
64  typedef typename Audio_Sample<Encoding>::enc_sample_type sample_type;
65  //Number of audio channels
66  int _num_channels;
68  std::streamoff _start_pos;
70  std::streamoff _cur_pos;
72  Binary_In_Stream& _str;
73 };
74 
75 template<typename Binary_In_Stream, Audio_Encoding Encoding>
76 std::streamoff Audio_Samples_Reader<Binary_In_Stream,Encoding>::tell() const
77 {
78  return _cur_pos;
79 }
80 
81 template<typename Binary_In_Stream, Audio_Encoding Encoding>
82 bool Audio_Samples_Reader<Binary_In_Stream,Encoding>::seek(std::streamoff n)
83 {
84  _str.seekg(_start_pos + (_cur_pos * _num_channels *sample_size), std::ios_base::beg);
85  if(_str){
86  _cur_pos = n;
87  return true;
88  }
89  else{
90  return false;
91  }
92 }
93 
94 template<typename Binary_In_Stream, Audio_Encoding Encoding>
95 std::streamoff Audio_Samples_Reader<Binary_In_Stream,Encoding>::num_samples()
96 {
97  _str.seekg(0, std::ios_base::end);
98  if(!_str) return -1;
99  std::streamoff end_pos = _str.tellg();
100  return (end_pos - _start_pos)/(_num_channels * sample_size);
101 }
102 
103 //read single channel samples starting at current position
104 template<typename Binary_In_Stream, Audio_Encoding Encoding>
105 bool Audio_Samples_Reader<Binary_In_Stream,Encoding>::read_sample(double& s, int ch)
106 {
107  if(ch >= _num_channels) return false;
108  std::streamoff read_pos = _start_pos + (_cur_pos * _num_channels + ch )*sample_size;
109  _str.seekg(read_pos, std::ios_base::beg);
110  if(!_str) return false;
111  sample_type raw_sample;
112  _str >> raw_sample;
113  if(_str){
114  s = Audio_Sample<Encoding>::decode(raw_sample);
115  _cur_pos++;
116  return true;
117  }
118  return false;
119 }
120 
121 //read n samples from channel ch starting at current position
122 template<typename Binary_In_Stream, Audio_Encoding Encoding>
123 vec Audio_Samples_Reader<Binary_In_Stream,Encoding>::read_channel(int n, int ch)
124 {
125  //ignore threshold - ignore() is used instead of seekg()
126  //if stride between samples is smaller then this threshold
127  static const std::streamsize ignore_threshold = 64;
128 
129  if((n <= 0) || (ch >= _num_channels)) return vec();
130  vec ret(n);
131 
132  //read first n-1 samples
133  const std::streamsize stride = sample_size*(_num_channels - 1);
134  _str.seekg(_start_pos + (_cur_pos *_num_channels + ch) * sample_size, std::ios_base::beg);
135  for(int i = 0; (i < (n-1)) && _str; ++i) {
136  sample_type raw_sample; _str >> raw_sample;
137  ret(i) = Audio_Sample<Encoding>::decode(raw_sample);
138  if(stride > ignore_threshold)
139  _str.seekg(stride, std::ios_base::cur);
140  else
141  _str.ignore(stride);
142  }
143 
144  //read last sample
145  if(_str){
146  sample_type raw_sample; _str >> raw_sample;
147  ret(n-1) = Audio_Sample<Encoding>::decode(raw_sample);
148  }
149 
150  if(_str){
151  _cur_pos += n;
152  }
153  else{
154  ret.set_size(0);
155  }
156 
157  return ret;
158 }
159 
160 //read n samples from all channels starting at current position
161 template<typename Binary_In_Stream, Audio_Encoding Encoding>
162 mat Audio_Samples_Reader<Binary_In_Stream,Encoding>::read(int n)
163 {
164  if(n <= 0) return mat();
165  mat ret(n,_num_channels);
166 
167  //read samples
168  const std::streamsize stride = sample_size*(_num_channels - 1);
169  _str.seekg(_start_pos + _cur_pos * sample_size *_num_channels, std::ios_base::beg);
170  for(int i = 0; (i < n) && _str; ++i) {
171  for(int j = 0; j < _num_channels && _str; ++j) {
172  sample_type raw_sample; _str >> raw_sample;
173  ret(i,j) = Audio_Sample<Encoding>::decode(raw_sample);
174  }
175  }
176 
177  if(_str){
178  _cur_pos += n;
179  }
180  else{
181  ret.set_size(0,0);
182  }
183  return ret;
184 }
185 
186 //make audio samples reader to input data from stream
187 template<typename Binary_In_Stream>
188 audiofile_details::Audio_Samples_Reader_If* make_reader(Binary_In_Stream& str,
189  std::streamoff start_pos, Audio_Stream_Description* d)
190 {
191  Audio_Encoding encoding = d->get_encoding();
192  int num_channels = d->get_num_channels();
193  switch(encoding){
194  case enc_mulaw8:
195  return new Audio_Samples_Reader<Binary_In_Stream, enc_mulaw8>(str,start_pos,num_channels);
196  case enc_alaw8:
197  return new Audio_Samples_Reader<Binary_In_Stream, enc_alaw8>(str,start_pos,num_channels);
198  case enc_linear8:
199  return new Audio_Samples_Reader<Binary_In_Stream, enc_linear8>(str,start_pos,num_channels);
200  case enc_linear16:
201  return new Audio_Samples_Reader<Binary_In_Stream, enc_linear16>(str,start_pos,num_channels);
202  case enc_linear24:
203  return new Audio_Samples_Reader<Binary_In_Stream, enc_linear24>(str,start_pos,num_channels);
204  case enc_linear32:
205  return new Audio_Samples_Reader<Binary_In_Stream, enc_linear32>(str,start_pos,num_channels);
206  case enc_float:
207  return new Audio_Samples_Reader<Binary_In_Stream, enc_float>(str,start_pos,num_channels);
208  case enc_double:
209  return new Audio_Samples_Reader<Binary_In_Stream, enc_double>(str,start_pos,num_channels);
210  case enc_unknown:
211  default:
212  return 0;
213  }
214 }
216 //
217 // Audio_Samples_Writer - templated implementation of Audio_Samples_Writer_If
218 //
220 template<typename Binary_Out_Stream, Audio_Encoding Encoding>
221 class Audio_Samples_Writer : public audiofile_details::Audio_Samples_Writer_If
222 {
223 public:
224  Audio_Samples_Writer(Binary_Out_Stream& str, std::streamoff start, int nc):
225  _str(str), _start_pos(start), _num_channels(nc), _cur_pos(0),
226  _zero(Audio_Sample<Encoding>::encode(0.0)){}
227  virtual bool write_sample(const double& s, int ch);
228  virtual bool write_channel(const vec& s, int ch);
229  //Write n samples to audio channel ch
230  virtual bool write(const mat& s);
231  virtual std::streamoff tell() const;
232  virtual bool seek(std::streamoff n);
233  virtual std::streamoff num_samples();
234 private:
235  static const std::size_t sample_size = Audio_Sample<Encoding>::enc_sample_size;
236  typedef typename Audio_Sample<Encoding>::enc_sample_type sample_type;
237  //Number of audio channels
238  int _num_channels;
240  std::streamoff _start_pos;
242  std::streamoff _cur_pos;
244  Binary_Out_Stream& _str;
245  //Zero sample
246  sample_type _zero;
247 };
248 
249 template<typename Binary_Out_Stream, Audio_Encoding Encoding>
250 std::streamoff Audio_Samples_Writer<Binary_Out_Stream,Encoding>::tell() const
251 {
252  return _cur_pos;
253 }
254 
255 template<typename Binary_Out_Stream, Audio_Encoding Encoding>
256 bool Audio_Samples_Writer<Binary_Out_Stream,Encoding>::seek(std::streamoff n)
257 {
258  _str.seekp(_start_pos + (n * _num_channels *sample_size), std::ios_base::beg);
259  if(_str){
260  _cur_pos = n;
261  return true;
262  }
263  else{
264  return false;
265  }
266 }
267 
268 template<typename Binary_Out_Stream, Audio_Encoding Encoding>
269 std::streamoff Audio_Samples_Writer<Binary_Out_Stream,Encoding>::num_samples()
270 {
271  _str.seekp(0, std::ios_base::end);
272  if(!_str) return -1;
273  std::streamoff end_pos = _str.tellp();
274  return (end_pos - _start_pos)/(_num_channels * sample_size);
275 }
276 
277 //write single sample starting at current position
278 template<typename Binary_Out_Stream, Audio_Encoding Encoding>
279 bool Audio_Samples_Writer<Binary_Out_Stream,Encoding>::write_sample(const double& s, int ch)
280 {
281  if(ch >= _num_channels) return false;
282  std::streamoff write_pos = _start_pos + (_cur_pos * _num_channels + ch )*sample_size;
283  _str.seekp(write_pos, std::ios_base::beg);
284  if(!_str) return false;
285  _str << Audio_Sample<Encoding>::encode(s);
286  if(_str){
287  _cur_pos++;
288  return true;
289  }
290  return false;
291 }
292 
293 //write single channel samples starting at current position
294 template<typename Binary_Out_Stream, Audio_Encoding Encoding>
295 bool Audio_Samples_Writer<Binary_Out_Stream,Encoding>::write_channel(const vec& s, int ch)
296 {
297  if(ch >= _num_channels) return false;
298 
299  int len = s.length();
300  //overall number of already written samples
301  std::streamoff ns = num_samples();
302  if(ns < 0) return false;
303  //compute number of samples to overwrite and number of samples to add to the end of file
304  int to_overwrite = (int)std::min(ns - _cur_pos, (std::streamoff)len);
305 
306  const std::streamoff stride = sample_size*(_num_channels - 1);
307 
308  int i = 0;
309  //overwrite samples
310  if(to_overwrite)
311  {
312  //process first to_overwrite-1 samples
313  _str.seekp(_start_pos + (_cur_pos * _num_channels + ch )*sample_size, std::ios_base::beg);
314  for(i = 0; (i < (to_overwrite-1)) && _str; ++i) {
315  _str << Audio_Sample<Encoding>::encode(s(i));
316  if(stride) _str.seekp(stride,std::ios_base::cur);
317  }
318  if(_str){
319  _str << Audio_Sample<Encoding>::encode(s(i)); ++i;
320  }
321  }
322 
323  //add samples to the end of file
324  if(i < len)
325  {
326  _str.seekp(_start_pos + ns * _num_channels * sample_size, std::ios_base::beg);
327  for(; (i < len) && _str; ++i) {
328  for(int j = 0; (j < _num_channels) && _str; ++j){
329  if(j == ch)
330  _str << Audio_Sample<Encoding>::encode(s(i));
331  else
332  _str << _zero;
333  }
334  }
335  }
336 
337  if(_str){
338  _cur_pos += len;
339  return true;
340  }
341  return false;
342 }
343 
344 //write samples starting at current position
345 template<typename Binary_Out_Stream, Audio_Encoding Encoding>
346 bool Audio_Samples_Writer<Binary_Out_Stream,Encoding>::write(const mat& s)
347 {
348  if(s.cols() < _num_channels) return false;
349  int len = s.rows();
350  for(int i = 0; (i < len) && _str; ++i){
351  for(int j = 0; (j < _num_channels) && _str; ++j){
352  sample_type raw_sample = Audio_Sample<Encoding>::encode(s(i,j));
353  _str << raw_sample;
354  }
355  }
356  if(_str){
357  _cur_pos += len;
358  return true;
359  }
360  return false;
361 }
362 
363 //make audio samples writer for stream output
364 template<typename Binary_Out_Stream>
365 audiofile_details::Audio_Samples_Writer_If* make_writer(Binary_Out_Stream& str,
366  std::streamoff start_pos, Audio_Stream_Description* d)
367 {
368  Audio_Encoding encoding = d->get_encoding();
369  int num_channels = d->get_num_channels();
370  switch(encoding){
371  case enc_mulaw8:
372  return new Audio_Samples_Writer<Binary_Out_Stream, enc_mulaw8>(str,start_pos,num_channels);
373  case enc_alaw8:
374  return new Audio_Samples_Writer<Binary_Out_Stream, enc_alaw8>(str,start_pos,num_channels);
375  case enc_linear8:
376  return new Audio_Samples_Writer<Binary_Out_Stream, enc_linear8>(str,start_pos,num_channels);
377  case enc_linear16:
378  return new Audio_Samples_Writer<Binary_Out_Stream, enc_linear16>(str,start_pos,num_channels);
379  case enc_linear24:
380  return new Audio_Samples_Writer<Binary_Out_Stream, enc_linear24>(str,start_pos,num_channels);
381  case enc_linear32:
382  return new Audio_Samples_Writer<Binary_Out_Stream, enc_linear32>(str,start_pos,num_channels);
383  case enc_float:
384  return new Audio_Samples_Writer<Binary_Out_Stream, enc_float>(str,start_pos,num_channels);
385  case enc_double:
386  return new Audio_Samples_Writer<Binary_Out_Stream, enc_double>(str,start_pos,num_channels);
387  case enc_unknown:
388  default:
389  return 0;
390  }
391 }
392 
394 //
395 // SND Header helpers
396 //
398 //snd header consists of 6 uint32_t fixed fields possibly followed
399 //by the variable length annotation
400 static const std::size_t snd_fixed_header_size = 24;
401 
402 //read_header() reads audio stream information from snd file header.
403 //returns true if successfull.
404 //d - pointer to stream description to collect info from snd header
405 //audio_offset - byte offset of first audio sample inside snd file
406 //number of audio samples stored in snd file, num_samples
407 template<typename Binary_In_Stream>
408 bool read_header(Binary_In_Stream& _str, Audio_Stream_Description* d,
409  std::streamoff& audio_offset, std::streamoff& num_samples)
410 {
411  //SND header fields
412  uint32_t magic, hdr_size, data_size, encoding, sampling_rate, num_channels;
413  //encoded sample size
414  std::size_t sample_size;
415  //annotation
416  std::string annotation;
417 
418  //read fixed fields of snd file header
419  _str.seekg(0, std::ios_base::beg);
420  _str >> magic >> hdr_size>> data_size>> encoding >> sampling_rate>> num_channels;
421  if(!_str) return false;
422 
423  //check magic
424  if(magic != snd_magic) return false; //invalid magic
425 
426  //check header size (we do not verify divisibility of header size by 8 since we still able to
427  //read unaligned data samples)
428  if(hdr_size < snd_fixed_header_size) return false; //header is too short
429  audio_offset = hdr_size;
430 
431  //check encoding
432  sample_size = encoded_sample_size((Audio_Encoding)encoding);
433  if(!sample_size) return false; //unknown or invalid encoding
434 
435  //read annotation
436  if(hdr_size > snd_fixed_header_size)
437  {//annotation is present
438  //get annotation length
439  std::streamsize ann_length = (std::streamsize)std::min(hdr_size - snd_fixed_header_size, max_annotation_length);
440  for(int i = 0; i < ann_length; ++i){
441  char s; _str>>s;
442  if(_str && s)
443  annotation += s;
444  else
445  break;
446  }
447  if(!_str) return false; //failed to read annotation
448  }
449 
450  //compute number of audio samples based on the file length
451  _str.seekg(0, std::ios_base::end);
452  if(!_str) return false; //failed to seek to the end
453  std::streamoff ns = ((std::streamoff)_str.tellg() - hdr_size)/(num_channels * sample_size);
454 
455  //update number of samples just read from header
456  if(data_size = 0xffffffff){
457  //data size was set to unknown in file header, use number of smaples obtained from file length
458  num_samples = ns;
459  }
460  else{
461  num_samples = std::min<long unsigned int>((long unsigned int)ns,(std::streamoff)data_size/(num_channels * sample_size));
462  }
463 
464  //update start position of audio samples
465  audio_offset = hdr_size;
466 
467  //update stream description
468  d->set_encoding((Audio_Encoding) encoding);
469  d->set_num_channels(num_channels);
470  d->set_sampling_rate(sampling_rate);
471  d->set_description(annotation);
472  return true;
473 }
474 
475 //write_header() writes audio stream information to snd file header.
476 //it is assumed that stream description pointed by d is initialized with correct values
477 template<typename Binary_Out_Stream>
478 bool write_header(Binary_Out_Stream& _str, const Audio_Stream_Description* const d, std::streamoff& audio_offset)
479 {
480  uint32_t hdr_size, data_size, encoding, sampling_rate, num_channels;
481  data_size = 0xffffffff;
482  encoding = (uint32_t)d->get_encoding();
483  sampling_rate = (uint32_t)d->get_sampling_rate();
484  num_channels = (uint32_t)d->get_num_channels();
485 
486  //compute header size based on fixed fields length and length of the annotation
487  uint32_t ann_length = (uint32_t)std::min(d->get_description().length(), max_annotation_length);
488  uint32_t padding_length = (8 - ((ann_length+1) % 8)) % 8; //compute padding length
489  hdr_size = (uint32_t)snd_fixed_header_size + ann_length + padding_length + 1;
490 
491  //position stream pointer at the beginning of the file
492  _str.seekp(0,std::ios_base::beg);
493  if(!_str) return false;
494 
495  //write fixed-sized part of the header
496  _str << snd_magic << hdr_size << data_size << encoding << sampling_rate << num_channels;
497  if(!_str) return false;
498 
499  //write annotationn and padding
500  _str.write(d->get_description().c_str(), ann_length);
501  for(uint32_t i = 0; (i < (padding_length + 1)) && _str; ++i) _str << '\0';
502 
503  if(!_str) return false;
504  audio_offset = hdr_size;
505 
506  return true;
507 }
508 
509 //update_num_samples_in_header() updates numder of samples in snd file header
510 template<typename Binary_Out_Stream>
511 bool update_num_samples_in_header(Binary_Out_Stream& _str, const Audio_Stream_Description* const d, std::streamoff num_samples)
512 {
513  uint32_t data_size = (uint32_t) std::min<long unsigned int>((long unsigned int)(num_samples *
514  d->get_num_channels() * encoded_sample_size(d->get_encoding())),
515  (long unsigned int)0xffffffff);
516  _str.seekp(2*sizeof(uint32_t),std::ios_base::beg);
517  if(!_str) return false;
518  _str << data_size;
519  if(!_str) return false;
520  return true;
521 }
522 
523 
525 //
526 // SND_In_File
527 //
529 
530 SND_In_File::SND_In_File():_samples_reader(0),
531  _description(new Audio_Stream_Description), _num_samples(0)
532 {
533 }
534 
535 SND_In_File::SND_In_File(const char *fname):_samples_reader(0),
536  _description(new Audio_Stream_Description), _num_samples(0)
537 {
538  open(fname);
539 }
540 
541 bool SND_In_File::open(const char *fname)
542 {
543  //try to reopen the stream
544  if (_str.is_open()) close();
545  _str.clear();
546  _str.open(fname, bfstream_base::b_endian);
547  if (!_str) return false;
548 
549  //read header and update description
550  std::streamoff audio_offset;
551  if (!read_header(_str,_description, audio_offset,_num_samples)) {
552  _str.close();
553  return false;
554  }
555 
556  //create samples reader
557  it_assert(_samples_reader == 0, "SND_In_File::open: samples reader was not deallocated properly.");
558  _samples_reader = make_reader(_str,audio_offset,_description);
559  return true;
560 }
561 
562 void SND_In_File::close()
563 {
564  //close stream
565  if(_str.is_open()) _str.close();
566  //dispose reader
567  if(_samples_reader){
568  delete _samples_reader;
569  _samples_reader = 0;
570  }
571  //reset description
572  _num_samples = 0;
573  *_description = Audio_Stream_Description();
574 }
575 
576 SND_In_File::~SND_In_File()
577 {
578  //close file and dispose description
579  close();
580  delete _description;
581 }
582 
583 
585 //
586 // SND_Out_File
587 //
589 SND_Out_File::SND_Out_File():_samples_writer(0),
590  _description(new Audio_Stream_Description), _num_samples(0)
591 {
592 }
593 
594 SND_Out_File::SND_Out_File(const char *fname, const Audio_Stream_Description& d):
595  _samples_writer(0), _description(new Audio_Stream_Description), _num_samples(0)
596 {
597  open(fname, d);
598 }
599 
600 bool SND_Out_File::open(const char *fname, const Audio_Stream_Description& d)
601 {
602  //check if we have a valid description
603  if(!is_valid(d)) return false;
604  //try to reopen the stream
605  if (_str.is_open()) close();
606  _str.clear();
607  _str.open(fname, true, bfstream_base::b_endian);
608  if (!_str) return false;
609  //init description and write header
610  *_description = d;
611  std::streamoff audio_offset;
612  if (!write_header(_str, &d, audio_offset)){
613  _str.close();
614  return false;
615  }
616  //create samples writer
617  it_assert(_samples_writer == 0, "SND_Out_File::open: samples writer was not deallocated properly.");
618  _samples_writer = make_writer(_str,audio_offset,_description);
619  _num_samples = 0;
620  return true;
621 }
622 
623 void SND_Out_File::close()
624 {
625  //update file header with written samples counter and close the stream
626  if(_str.is_open()){
627  update_num_samples_in_header(_str,_description,_num_samples);
628  _str.close();
629  }
630  //dispose samples writer
631  if(_samples_writer){
632  delete _samples_writer;
633  _samples_writer = 0;
634  }
635  //reset description
636  _num_samples = 0;
637  *_description = Audio_Stream_Description();
638 }
639 
640 SND_Out_File::~SND_Out_File()
641 {
642  //close file and dispose description
643  close();
644  delete _description;
645 }
647 //
648 // SND_IO_File
649 //
651 
652 SND_IO_File::SND_IO_File():
653  _samples_reader(0), _samples_writer(0),
654  _description(new Audio_Stream_Description), _num_samples(0)
655 {
656 
657 }
658 
659 SND_IO_File::SND_IO_File(const char *fname):
660  _samples_reader(0), _samples_writer(0),
661  _description(new Audio_Stream_Description), _num_samples(0)
662 {
663  open(fname);
664 }
665 
666 SND_IO_File::SND_IO_File(const char *fname, const Audio_Stream_Description& d):
667  _samples_reader(0), _samples_writer(0),
668  _description(new Audio_Stream_Description), _num_samples(0)
669 {
670  open(fname, d);
671 }
672 
673 //open IO file. Pick up information about audio stream from file header
674 bool SND_IO_File::open(const char *fname)
675 {
676  //try to reopen the stream
677  if (_str.is_open()) close();
678  _str.clear();
679  _str.open(fname, false, bfstream_base::b_endian);
680  if (!_str) return false;
681  //reader header and update description
682  std::streamoff audio_offset;
683  if (!read_header(_str,_description, audio_offset,_num_samples)) {
684  _str.close();
685  return false;
686  }
687  //create reader and writer for audio samples
688  it_assert(_samples_reader == 0, "SND_IO_File::open: samples reader was not deallocated properly.");
689  _samples_reader = make_reader(_str,audio_offset,_description);
690  it_assert(_samples_writer == 0, "SND_IO_File::open: samples writer was not deallocated properly.");
691  _samples_writer = make_writer(_str,audio_offset,_description);
692  return true;
693 
694 }
695 
696 //open file for IO with new descrition - truncates file contents
697 bool SND_IO_File::open(const char *fname, const Audio_Stream_Description& d)
698 {
699  //check if provided decription is valid
700  if(!is_valid(d)) return false;
701 
702  //try reopen the stream
703  if (_str.is_open()) close();
704  _str.clear();
705  _str.open(fname, true, bfstream_base::b_endian);
706  if (!_str) return false;
707 
708  //init description and write file header
709  *_description = d;
710  std::streamoff audio_offset;
711  if (!write_header(_str, &d, audio_offset)){
712  _str.close();
713  return false;
714  }
715  //create reader and writer for audio samples
716  it_assert(_samples_reader == 0, "SND_IO_File::open: samples reader was not deallocated properly.");
717  _samples_reader = make_reader(_str,audio_offset,_description);
718  it_assert(_samples_writer == 0, "SND_IO_File::open: samples writer was not deallocated properly.");
719  _samples_writer = make_writer(_str,audio_offset,_description);
720 
721  _num_samples = 0;
722  return true;
723 
724 }
725 
726 
727 void SND_IO_File::close()
728 {
729  //close the stream and update number of written samples
730  if(_str.is_open()){
731  update_num_samples_in_header(_str,_description,_num_samples);
732  _str.close();
733  }
734  //dispose reader and writer of audio samples
735  if(_samples_writer){
736  delete _samples_writer;
737  _samples_writer = 0;
738  }
739 
740  if(_samples_reader){
741  delete _samples_reader;
742  _samples_reader = 0;
743  }
744  //reset description
745  _num_samples = 0;
746  *_description = Audio_Stream_Description();
747 }
748 
749 SND_IO_File::~SND_IO_File()
750 {
751  //close audio file and dispose description
752  close();
753  delete _description;
754 }
755 
756 } // namespace itpp
757 
SourceForge Logo

Generated on Sat May 25 2013 16:32:23 for IT++ by Doxygen 1.8.2