40 static const uint32_t snd_magic = 0x2e736e64;
42 static const std::size_t max_annotation_length = 1024;
49 template<
typename Binary_In_Stream, Audio_Encoding Encoding>
50 class Audio_Samples_Reader :
public audiofile_details::Audio_Samples_Reader_If
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);
57 vec read_channel(
int n,
int ch);
59 virtual std::streamoff tell()
const;
60 virtual bool seek(std::streamoff n);
61 virtual std::streamoff num_samples();
68 std::streamoff _start_pos;
70 std::streamoff _cur_pos;
72 Binary_In_Stream& _str;
75 template<
typename Binary_In_Stream, Audio_Encoding Encoding>
76 std::streamoff Audio_Samples_Reader<Binary_In_Stream,Encoding>::tell()
const
81 template<
typename Binary_In_Stream, Audio_Encoding Encoding>
82 bool Audio_Samples_Reader<Binary_In_Stream,Encoding>::seek(std::streamoff n)
84 _str.seekg(_start_pos + (_cur_pos * _num_channels *sample_size), std::ios_base::beg);
94 template<
typename Binary_In_Stream, Audio_Encoding Encoding>
95 std::streamoff Audio_Samples_Reader<Binary_In_Stream,Encoding>::num_samples()
97 _str.seekg(0, std::ios_base::end);
99 std::streamoff end_pos = _str.tellg();
100 return (end_pos - _start_pos)/(_num_channels * sample_size);
104 template<
typename Binary_In_Stream, Audio_Encoding Encoding>
105 bool Audio_Samples_Reader<Binary_In_Stream,Encoding>::read_sample(
double& s,
int ch)
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;
122 template<
typename Binary_In_Stream, Audio_Encoding Encoding>
123 vec Audio_Samples_Reader<Binary_In_Stream,Encoding>::read_channel(
int n,
int ch)
127 static const std::streamsize ignore_threshold = 64;
129 if((n <= 0) || (ch >= _num_channels))
return vec();
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;
138 if(stride > ignore_threshold)
139 _str.seekg(stride, std::ios_base::cur);
146 sample_type raw_sample; _str >> raw_sample;
161 template<
typename Binary_In_Stream, Audio_Encoding Encoding>
162 mat Audio_Samples_Reader<Binary_In_Stream,Encoding>::read(
int n)
164 if(n <= 0)
return mat();
165 mat ret(n,_num_channels);
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;
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)
192 int num_channels = d->get_num_channels();
195 return new Audio_Samples_Reader<Binary_In_Stream, enc_mulaw8>(str,start_pos,num_channels);
197 return new Audio_Samples_Reader<Binary_In_Stream, enc_alaw8>(str,start_pos,num_channels);
199 return new Audio_Samples_Reader<Binary_In_Stream, enc_linear8>(str,start_pos,num_channels);
201 return new Audio_Samples_Reader<Binary_In_Stream, enc_linear16>(str,start_pos,num_channels);
203 return new Audio_Samples_Reader<Binary_In_Stream, enc_linear24>(str,start_pos,num_channels);
205 return new Audio_Samples_Reader<Binary_In_Stream, enc_linear32>(str,start_pos,num_channels);
207 return new Audio_Samples_Reader<Binary_In_Stream, enc_float>(str,start_pos,num_channels);
209 return new Audio_Samples_Reader<Binary_In_Stream, enc_double>(str,start_pos,num_channels);
220 template<
typename Binary_Out_Stream, Audio_Encoding Encoding>
221 class Audio_Samples_Writer :
public audiofile_details::Audio_Samples_Writer_If
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),
227 virtual bool write_sample(
const double& s,
int ch);
228 virtual bool write_channel(
const vec& s,
int 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();
240 std::streamoff _start_pos;
242 std::streamoff _cur_pos;
244 Binary_Out_Stream& _str;
249 template<
typename Binary_Out_Stream, Audio_Encoding Encoding>
250 std::streamoff Audio_Samples_Writer<Binary_Out_Stream,Encoding>::tell()
const
255 template<
typename Binary_Out_Stream, Audio_Encoding Encoding>
256 bool Audio_Samples_Writer<Binary_Out_Stream,Encoding>::seek(std::streamoff n)
258 _str.seekp(_start_pos + (n * _num_channels *sample_size), std::ios_base::beg);
268 template<
typename Binary_Out_Stream, Audio_Encoding Encoding>
269 std::streamoff Audio_Samples_Writer<Binary_Out_Stream,Encoding>::num_samples()
271 _str.seekp(0, std::ios_base::end);
273 std::streamoff end_pos = _str.tellp();
274 return (end_pos - _start_pos)/(_num_channels * sample_size);
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)
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);
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)
297 if(ch >= _num_channels)
return false;
299 int len = s.length();
301 std::streamoff ns = num_samples();
302 if(ns < 0)
return false;
304 int to_overwrite = (int)
std::min(ns - _cur_pos, (std::streamoff)len);
306 const std::streamoff stride = sample_size*(_num_channels - 1);
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);
319 _str << Audio_Sample<Encoding>::encode(s(i)); ++i;
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){
330 _str << Audio_Sample<Encoding>::encode(s(i));
345 template<
typename Binary_Out_Stream, Audio_Encoding Encoding>
346 bool Audio_Samples_Writer<Binary_Out_Stream,Encoding>::write(
const mat& s)
348 if(s.cols() < _num_channels)
return false;
350 for(
int i = 0; (i < len) && _str; ++i){
351 for(
int j = 0; (j < _num_channels) && _str; ++j){
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)
369 int num_channels = d->get_num_channels();
372 return new Audio_Samples_Writer<Binary_Out_Stream, enc_mulaw8>(str,start_pos,num_channels);
374 return new Audio_Samples_Writer<Binary_Out_Stream, enc_alaw8>(str,start_pos,num_channels);
376 return new Audio_Samples_Writer<Binary_Out_Stream, enc_linear8>(str,start_pos,num_channels);
378 return new Audio_Samples_Writer<Binary_Out_Stream, enc_linear16>(str,start_pos,num_channels);
380 return new Audio_Samples_Writer<Binary_Out_Stream, enc_linear24>(str,start_pos,num_channels);
382 return new Audio_Samples_Writer<Binary_Out_Stream, enc_linear32>(str,start_pos,num_channels);
384 return new Audio_Samples_Writer<Binary_Out_Stream, enc_float>(str,start_pos,num_channels);
386 return new Audio_Samples_Writer<Binary_Out_Stream, enc_double>(str,start_pos,num_channels);
400 static const std::size_t snd_fixed_header_size = 24;
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)
412 uint32_t magic, hdr_size, data_size, encoding, sampling_rate, num_channels;
414 std::size_t sample_size;
416 std::string annotation;
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;
424 if(magic != snd_magic)
return false;
428 if(hdr_size < snd_fixed_header_size)
return false;
429 audio_offset = hdr_size;
433 if(!sample_size)
return false;
436 if(hdr_size > snd_fixed_header_size)
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){
447 if(!_str)
return false;
451 _str.seekg(0, std::ios_base::end);
452 if(!_str)
return false;
453 std::streamoff ns = ((std::streamoff)_str.tellg() - hdr_size)/(num_channels * sample_size);
456 if(data_size = 0xffffffff){
461 num_samples = std::min<long unsigned int>((
long unsigned int)ns,(std::streamoff)data_size/(num_channels * sample_size));
465 audio_offset = hdr_size;
469 d->set_num_channels(num_channels);
470 d->set_sampling_rate(sampling_rate);
471 d->set_description(annotation);
477 template<typename Binary_Out_Stream>
478 bool write_header(Binary_Out_Stream& _str, const Audio_Stream_Description* const d, std::streamoff& audio_offset)
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();
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;
489 hdr_size = (uint32_t)snd_fixed_header_size + ann_length + padding_length + 1;
492 _str.seekp(0,std::ios_base::beg);
493 if(!_str)
return false;
496 _str << snd_magic << hdr_size << data_size << encoding << sampling_rate << num_channels;
497 if(!_str)
return false;
500 _str.write(d->get_description().c_str(), ann_length);
501 for(uint32_t i = 0; (i < (padding_length + 1)) && _str; ++i) _str <<
'\0';
503 if(!_str)
return false;
504 audio_offset = hdr_size;
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)
513 uint32_t data_size = (uint32_t) std::min<long unsigned int>((
long unsigned int)(num_samples *
515 (
long unsigned int)0xffffffff);
516 _str.seekp(2*
sizeof(uint32_t),std::ios_base::beg);
517 if(!_str)
return false;
519 if(!_str)
return false;
531 _description(new Audio_Stream_Description), _num_samples(0)
535 SND_In_File::SND_In_File(
const char *fname):_samples_reader(0),
536 _description(new Audio_Stream_Description), _num_samples(0)
541 bool SND_In_File::open(
const char *fname)
544 if (_str.is_open()) close();
546 _str.open(fname, bfstream_base::b_endian);
547 if (!_str)
return false;
550 std::streamoff audio_offset;
551 if (!read_header(_str,_description, audio_offset,_num_samples)) {
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);
562 void SND_In_File::close()
565 if(_str.is_open()) _str.close();
568 delete _samples_reader;
573 *_description = Audio_Stream_Description();
576 SND_In_File::~SND_In_File()
589 SND_Out_File::SND_Out_File():_samples_writer(0),
590 _description(new Audio_Stream_Description), _num_samples(0)
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)
600 bool SND_Out_File::open(
const char *fname,
const Audio_Stream_Description& d)
605 if (_str.is_open()) close();
607 _str.open(fname,
true, bfstream_base::b_endian);
608 if (!_str)
return false;
611 std::streamoff audio_offset;
612 if (!write_header(_str, &d, audio_offset)){
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);
623 void SND_Out_File::close()
627 update_num_samples_in_header(_str,_description,_num_samples);
632 delete _samples_writer;
637 *_description = Audio_Stream_Description();
640 SND_Out_File::~SND_Out_File()
652 SND_IO_File::SND_IO_File():
653 _samples_reader(0), _samples_writer(0),
654 _description(new Audio_Stream_Description), _num_samples(0)
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)
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)
674 bool SND_IO_File::open(
const char *fname)
677 if (_str.is_open()) close();
679 _str.open(fname,
false, bfstream_base::b_endian);
680 if (!_str)
return false;
682 std::streamoff audio_offset;
683 if (!read_header(_str,_description, audio_offset,_num_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);
697 bool SND_IO_File::open(
const char *fname,
const Audio_Stream_Description& d)
703 if (_str.is_open()) close();
705 _str.open(fname,
true, bfstream_base::b_endian);
706 if (!_str)
return false;
710 std::streamoff audio_offset;
711 if (!write_header(_str, &d, audio_offset)){
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);
727 void SND_IO_File::close()
731 update_num_samples_in_header(_str,_description,_num_samples);
736 delete _samples_writer;
741 delete _samples_reader;
746 *_description = Audio_Stream_Description();
749 SND_IO_File::~SND_IO_File()