10 #define WAVREADER_HPP_
36 template<
class Container1d,
typename T, std::
size_t Nb_block>
53 wave(),header_size(0),output_size(0),infile(),indblock(1),block_size(0),last_block_size(0),
54 last_it(0),finished(0),initialized(0)
55 {infile.exceptions(std::ifstream::failbit | std::ifstream::badbit);}
64 wave(),header_size(0),output_size(0),infile(),indblock(1),block_size(0),last_block_size(0),
65 last_it(0),finished(0),initialized(0)
66 {infile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
initialize();}
129 std::size_t header_size;
130 std::size_t output_size;
133 std::ifstream infile;
134 std::size_t indblock;
135 std::size_t block_size;
136 std::size_t last_block_size;
149 template<
class Container1d,
typename T, std::
size_t Nb_block>
154 infile.open(this->data_filename_.c_str(), std::ifstream::binary);
157 std::ostringstream err;
159 slip::slip_exception exc(std::string(
"slip"), std::string(
"WavReader::initialize()"), err.str());
163 infile.read(wave.riff_header.chunk_id,4);
164 wave.riff_header.chunk_id[4] =
'\0';
166 if (wave.riff_header.chunk_id[0] !=
'R' || wave.riff_header.chunk_id[1] !=
'I'
167 || wave.riff_header.chunk_id[2] !=
'F' || wave.riff_header.chunk_id[3] !=
'F'){
168 std::ostringstream err;
169 err <<
FILE_READ_ERROR << this->data_filename_ <<
" | unable to find the RIFF chunk.";
170 slip::slip_exception exc(std::string(
"slip"), std::string(
"WavReader::initialize()"), err.str());
171 if (infile.is_open())
175 infile.read(reinterpret_cast<char8*>(&wave.riff_header.chunk_size),4);
177 #ifdef REVERSE_ENDIANISM
179 wave.riff_header.chunk_size = SWAP_32(wave.riff_header.chunk_size);
181 infile.read(wave.riff_header.format,4);
182 wave.riff_header.format[4] =
'\0';
184 if (wave.riff_header.format[0] !=
'W' || wave.riff_header.format[1] !=
'A'
185 || wave.riff_header.format[2] !=
'V' || wave.riff_header.format[3] !=
'E'){
186 std::ostringstream err;
187 err <<
FILE_READ_ERROR << this->data_filename_ <<
" | not a WAVE file.";
188 slip::slip_exception exc(std::string(
"slip"), std::string(
"WavReader::initialize()"), err.str());
189 if (infile.is_open())
195 infile.read(wave.format_header.chunk_id,4);
196 wave.format_header.chunk_id[4] =
'\0';
198 if (wave.format_header.chunk_id[0] !=
'f' || wave.format_header.chunk_id[1] !=
'm'
199 || wave.format_header.chunk_id[2] !=
't' || wave.format_header.chunk_id[3] !=
' '){
200 std::ostringstream err;
201 err <<
FILE_READ_ERROR << this->data_filename_ <<
" | unable to find the fmt chunk.";
202 slip::slip_exception exc(std::string(
"slip"), std::string(
"WavReader::initialize()"), err.str());
203 if (infile.is_open())
207 infile.read(reinterpret_cast<char8*>(&wave.format_header.chunk_size),4);
208 infile.read(reinterpret_cast<char8*>(&wave.format_header.format),2);
209 infile.read(reinterpret_cast<char8*>(&wave.format_header.num_channels),2);
210 infile.read(reinterpret_cast<char8*>(&wave.format_header.sample_rate),4);
211 infile.read(reinterpret_cast<char8*>(&wave.format_header.byte_rate),4);
212 infile.read(reinterpret_cast<char8*>(&wave.format_header.align),2);
213 infile.read(reinterpret_cast<char8*>(&wave.format_header.bits_per_sample),2);
215 #ifdef REVERSE_ENDIANISM
216 wave.format_header.chunk_size = SWAP_32(wave.format_header.chunk_size);
217 wave.format_header.format = SWAP_16(wave.format_header.format);
218 wave.format_header.num_channels = SWAP_16(wave.format_header.num_channels);
219 wave.format_header.sample_rate = SWAP_32(wave.format_header.sample_rate);
220 wave.format_header.byte_rate = SWAP_32(wave.format_header.byte_rate);
221 wave.format_header.align = SWAP_16(wave.format_header.align);
222 wave.format_header.bits_per_sample = SWAP_16(wave.format_header.bits_per_sample);
226 if (wave.format_header.bits_per_sample > 32){
227 std::ostringstream err;
228 err <<
FILE_READ_ERROR << this->data_filename_ <<
" | Too much bit per sample.";
230 if (infile.is_open())
237 std::size_t pos = infile.tellg();
238 std::size_t length = wave.riff_header.chunk_size + 4;
239 infile.read(wave.data_header.chunk_id,4);
240 wave.data_header.chunk_id[4] =
'\0';
242 while ((wave.data_header.chunk_id[0] !=
'd' || wave.data_header.chunk_id[1] !=
'a' ||
243 wave.data_header.chunk_id[2] !=
't' || wave.data_header.chunk_id[3] !=
'a')
248 infile.read(wave.data_header.chunk_id,4);
249 wave.data_header.chunk_id[4] =
'\0';
254 std::ostringstream err;
255 err <<
FILE_READ_ERROR << this->data_filename_ <<
" | unable to find the data chunk.";
256 slip::slip_exception exc(std::string(
"slip"), std::string(
"WavReader::initialize()"), err.str());
257 if (infile.is_open())
262 infile.read(reinterpret_cast<char8*>(&wave.data_header.chunk_size),4);
264 #ifdef REVERSE_ENDIANISM
265 wave.data_header.chunk_size = SWAP_32(wave.data_header.chunk_size);
267 output_size = (wave.data_header.chunk_size) / static_cast<std::size_t>(wave.format_header.align);
268 block_size = output_size / Nb_block;
269 last_block_size = output_size % Nb_block;
270 last_block_size = (last_block_size == 0 ? block_size : block_size+last_block_size);
271 last_it = (Nb_block == 1);
272 finished = (last_it && last_block_size == 0);
277 template<
class Container1d,
typename T, std::
size_t Nb_block>
280 std::ostringstream err;
281 err <<
FILE_READ_ERROR << this->data_filename_ <<
" | The reader needs to be initialized before reading.";
289 in.resize(last_block_size,T());
291 in.resize(block_size,T());
294 std::size_t pos = (
static_cast<std::size_t
>(infile.tellg()) - header_size) /
static_cast<std::size_t
>(wave.format_header.align);
295 if(output_size - pos < in.size()){
296 std::ostringstream err;
297 err <<
FILE_READ_ERROR << this->data_filename_ <<
" | Bad audio dimensions.";
305 std::size_t bps =
static_cast<std::size_t
>(wave.format_header.bits_per_sample);
311 for(std::size_t i=0; i<in.size(); i++){
313 infile.read(reinterpret_cast<char8*>(&d),1);
314 in[i] =
static_cast<T
>(d);
315 if (wave.format_header.num_channels > 1){
316 std::size_t newpos =
static_cast<std::size_t
>(infile.tellg()) +
317 static_cast<std::size_t>(wave.format_header.num_channels - 1);
318 infile.seekg(newpos);
325 for(std::size_t i=0; i<in.size(); ++i){
327 infile.read(reinterpret_cast<char8*>(&d),2);
328 #ifdef REVERSE_ENDIANISM
331 in[i] =
static_cast<T
>(d);
332 if (wave.format_header.num_channels > 1){
333 std::size_t newpos =
static_cast<std::size_t
>(infile.tellg()) +
334 2* static_cast<std::size_t>(wave.format_header.num_channels - 1);
335 infile.seekg(newpos);
342 for(std::size_t i=0; i<in.size(); ++i){
344 infile.read(reinterpret_cast<char8*>(&d),4);
345 #ifdef REVERSE_ENDIANISM
348 in[i] =
static_cast<T
>(d);
349 if (wave.format_header.num_channels > 1){
350 std::size_t newpos =
static_cast<std::size_t
>(infile.tellg()) +
351 4* static_cast<std::size_t>(wave.format_header.num_channels - 1);
352 infile.seekg(newpos);
359 std::ostringstream err;
360 err <<
FILE_WRITE_ERROR << this->data_filename_ <<
" | The specified bit per sample is not valid.";
383 last_it = (indblock == Nb_block);
387 template<
class Container1d,
typename T, std::
size_t Nb_block>
391 if (infile.is_open())
393 wave = WAVE_HEADER();
Contains the container reader base class.
const std::string FILE_WRITE_ERROR
standard exception extension name have been changed to eliminate conflicts with QT ...
Container1d container_type
std::size_t get_output_size() const
Get the output signal size.
WavReader, inherited from ContainerReader, is a reader for wav audio files.
const WAVE_HEADER & get_header() const
Get the wav file header.
const std::string FILE_OPEN_ERROR
Some definitions specific to wav files manipulations.
ContainerReader is the base class of the readers classes. All readers are working the same way: ...
void initialize()
initialized the reading process.
void release()
release the reading process.
int read(container_type &in)
virtual read function. If Nb_block is more than one, it reads only one container, and returns 0...
ContainerReader< Container1d, T, Nb_block > base
WavReader(std::string data_filename)
const std::string FILE_READ_ERROR