diff options
Diffstat (limited to 'gr-blocks/lib/wavfile_source_impl.cc')
-rw-r--r-- | gr-blocks/lib/wavfile_source_impl.cc | 117 |
1 files changed, 53 insertions, 64 deletions
diff --git a/gr-blocks/lib/wavfile_source_impl.cc b/gr-blocks/lib/wavfile_source_impl.cc index b6bb559a5d..06db72c7e5 100644 --- a/gr-blocks/lib/wavfile_source_impl.cc +++ b/gr-blocks/lib/wavfile_source_impl.cc @@ -13,28 +13,10 @@ #endif #include "wavfile_source_impl.h" -#include <gnuradio/blocks/wavfile.h> #include <gnuradio/io_signature.h> -#include <fcntl.h> #include <sys/types.h> #include <stdexcept> -// win32 (mingw/msvc) specific -#ifdef HAVE_IO_H -#include <io.h> -#endif -#ifdef O_BINARY -#define OUR_O_BINARY O_BINARY -#else -#define OUR_O_BINARY 0 -#endif -// should be handled via configure -#ifdef O_LARGEFILE -#define OUR_O_LARGEFILE O_LARGEFILE -#else -#define OUR_O_LARGEFILE 0 -#endif - namespace gr { namespace blocks { @@ -52,51 +34,56 @@ wavfile_source_impl::wavfile_source_impl(const char* filename, bool repeat) d_h{}, // Init with zeros d_sample_idx(0) { - // we use "open" to use to the O_LARGEFILE flag - int fd; - if ((fd = ::open(filename, O_RDONLY | OUR_O_LARGEFILE | OUR_O_BINARY)) < 0) { - GR_LOG_ERROR(d_logger, - boost::format("::open: %s: %s") % filename % strerror(errno)); - throw std::runtime_error("can't open file"); - } + SF_INFO sfinfo; - if ((d_fp = fdopen(fd, "rb")) == NULL) { + sfinfo.format = 0; + if (!(d_fp = sf_open(filename, SFM_READ, &sfinfo))) { GR_LOG_ERROR(d_logger, - boost::format("fdopen: %s: %s") % filename % strerror(errno)); - throw std::runtime_error("can't open file"); + boost::format("sf_open failed: %s: %s") % filename % + strerror(errno)); + throw std::runtime_error("Can't open WAV file."); } - // Scan headers, check file validity - if (!wavheader_parse(d_fp, d_h)) { - throw std::runtime_error("is not a valid wav file"); + d_h.sample_rate = (unsigned)sfinfo.samplerate; + d_h.nchans = sfinfo.channels; + if (sfinfo.channels > 24) { + throw std::runtime_error("Number of channels greater than 24 not supported."); } - - if (d_h.samples_per_chan == 0) { - throw std::runtime_error("WAV file does not contain any samples"); + switch (sfinfo.format & SF_FORMAT_SUBMASK) { + case SF_FORMAT_PCM_S8: + d_h.bytes_per_sample = 1; + break; + case SF_FORMAT_PCM_16: + d_h.bytes_per_sample = 2; + break; + case SF_FORMAT_PCM_24: + d_h.bytes_per_sample = 3; + break; + case SF_FORMAT_PCM_32: + d_h.bytes_per_sample = 4; + break; + case SF_FORMAT_PCM_U8: + d_h.bytes_per_sample = 1; + break; + case SF_FORMAT_FLOAT: + d_h.bytes_per_sample = 4; + break; + case SF_FORMAT_DOUBLE: + d_h.bytes_per_sample = 8; + break; } + d_h.samples_per_chan = sfinfo.frames; - if (d_h.bytes_per_sample == 1) { - d_normalize_fac = UINT8_MAX / 2; - d_normalize_shift = 1; - } else { - d_normalize_fac = INT16_MAX; - d_normalize_shift = 0; + if (d_h.samples_per_chan == 0) { + throw std::runtime_error("WAV file does not contain any samples."); } // Re-set the output signature set_output_signature(io_signature::make(1, d_h.nchans, sizeof(float))); } -wavfile_source_impl::~wavfile_source_impl() { fclose(d_fp); } - -float wavfile_source_impl::convert_to_float(short int sample) -{ - float sample_out = (float)sample; - sample_out /= d_normalize_fac; - sample_out -= d_normalize_shift; - return sample_out; -} +wavfile_source_impl::~wavfile_source_impl() { sf_close(d_fp); } int wavfile_source_impl::work(int noutput_items, gr_vector_const_void_star& input_items, @@ -104,9 +91,9 @@ int wavfile_source_impl::work(int noutput_items, { auto out = (float**)&output_items[0]; int n_out_chans = output_items.size(); - int i; - short sample; + int errnum; + float sample[24]; for (i = 0; i < noutput_items; i++) { if (d_sample_idx >= d_h.samples_per_chan) { @@ -115,33 +102,35 @@ int wavfile_source_impl::work(int noutput_items, return i ? i : -1; } - if (fseek(d_fp, d_h.first_sample_pos, SEEK_SET) == -1) { + if (sf_seek(d_fp, 0, SEEK_SET) == -1) { GR_LOG_ERROR(d_logger, - boost::format("fseek failed %s") % strerror(errno)); - exit(-1); + boost::format("sf_seek failed: %s") % strerror(errno)); + throw std::runtime_error("Seek error."); } d_sample_idx = 0; } + sf_read_float(d_fp, &sample[0], d_h.nchans); for (int chan = 0; chan < d_h.nchans; chan++) { - sample = wav_read_sample(d_fp, d_h.bytes_per_sample); - if (chan < n_out_chans) { - out[chan][i] = convert_to_float(sample); + out[chan][i] = sample[chan]; } } d_sample_idx++; - // OK, EOF is not necessarily an error. But we're not going to - // deal with handling corrupt wav files, so if they give us any - // trouble they won't be processed. Serves them bloody right. - if (feof(d_fp) || ferror(d_fp)) { + // We're not going to deal with handling corrupt wav files, + // so if they give us any trouble they won't be processed. + // Serves them bloody right. + + errnum = sf_error(d_fp); + if (errnum) { if (i == 0) { - GR_LOG_ERROR(d_logger, - boost::format("WAV file has corrupted header or i/o error") % - strerror(errno)); + GR_LOG_ERROR( + d_logger, + boost::format("WAV file has corrupted header or I/O error, %s") % + sf_error_number(errnum)); return -1; } return i; |