summaryrefslogtreecommitdiff
path: root/gr-blocks/lib/wavfile_source_impl.cc
diff options
context:
space:
mode:
authorRon Economos <w6rz@comcast.net>2020-06-23 14:40:40 -0700
committerMarcus Müller <marcus@hostalia.de>2020-09-01 23:26:30 +0200
commit18f64ba685cfc2533e2d7726aa43c524b007d97b (patch)
treeba7f4420cce2728ab9ccbd2c2471b851d41138fb /gr-blocks/lib/wavfile_source_impl.cc
parent028b2167d7c1a6e7c4eb428b1c6cdd5225add264 (diff)
gr-blocks: Transition the WAV sink and source blocks to libsndfile.
Compressed input and output with FLAC and Ogg Vorbis now supported.
Diffstat (limited to 'gr-blocks/lib/wavfile_source_impl.cc')
-rw-r--r--gr-blocks/lib/wavfile_source_impl.cc117
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;