summaryrefslogtreecommitdiff
path: root/gr-blocks/lib/wavfile_sink_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gr-blocks/lib/wavfile_sink_impl.cc')
-rw-r--r--gr-blocks/lib/wavfile_sink_impl.cc135
1 files changed, 67 insertions, 68 deletions
diff --git a/gr-blocks/lib/wavfile_sink_impl.cc b/gr-blocks/lib/wavfile_sink_impl.cc
index 69fb8d826d..431919e7ed 100644
--- a/gr-blocks/lib/wavfile_sink_impl.cc
+++ b/gr-blocks/lib/wavfile_sink_impl.cc
@@ -48,8 +48,8 @@ wavfile_sink::sptr wavfile_sink::make(const char* filename,
unsigned int sample_rate,
int bits_per_sample)
{
- return gnuradio::get_initial_sptr(
- new wavfile_sink_impl(filename, n_channels, sample_rate, bits_per_sample));
+ return gnuradio::get_initial_sptr(new wavfile_sink_impl(
+ filename, n_channels, sample_rate, bits_per_sample));
}
wavfile_sink_impl::wavfile_sink_impl(const char* filename,
@@ -59,32 +59,20 @@ wavfile_sink_impl::wavfile_sink_impl(const char* filename,
: sync_block("wavfile_sink",
io_signature::make(1, n_channels, sizeof(float)),
io_signature::make(0, 0, 0)),
- d_sample_rate(sample_rate),
- d_nchans(n_channels),
- d_fp(0),
- d_new_fp(0),
+ d_h{}, // Init with zeros
+ d_fp(nullptr),
+ d_new_fp(nullptr),
d_updated(false)
{
- if (bits_per_sample != 8 && bits_per_sample != 16) {
- throw std::runtime_error("Invalid bits per sample (supports 8 and 16)");
- }
- d_bytes_per_sample = bits_per_sample / 8;
- d_bytes_per_sample_new = d_bytes_per_sample;
+ d_h.sample_rate = sample_rate;
+ d_h.nchans = n_channels;
- if (!open(filename)) {
- throw std::runtime_error("can't open file");
- }
+ set_bits_per_sample_unlocked(bits_per_sample);
- if (bits_per_sample == 8) {
- d_max_sample_val = 0xFF;
- d_min_sample_val = 0;
- d_normalize_fac = d_max_sample_val / 2;
- d_normalize_shift = 1;
- } else {
- d_max_sample_val = 0x7FFF;
- d_min_sample_val = -0x7FFF;
- d_normalize_fac = d_max_sample_val;
- d_normalize_shift = 0;
+ d_h.bytes_per_sample = d_bytes_per_sample_new;
+
+ if (!open(filename)) {
+ throw std::runtime_error("can't open WAV file");
}
}
@@ -93,10 +81,10 @@ bool wavfile_sink_impl::open(const char* filename)
gr::thread::scoped_lock guard(d_mutex);
// we use the open system call to get access to the O_LARGEFILE flag.
+ int flags = OUR_O_LARGEFILE | OUR_O_BINARY | O_CREAT | O_WRONLY | O_TRUNC;
int fd;
- if ((fd = ::open(filename,
- O_WRONLY | O_CREAT | O_TRUNC | OUR_O_LARGEFILE | OUR_O_BINARY,
- 0664)) < 0) {
+
+ if ((fd = ::open(filename, flags, 0664)) < 0) {
GR_LOG_ERROR(d_logger,
boost::format("::open: %s: %s") % filename % strerror(errno));
return false;
@@ -104,23 +92,27 @@ bool wavfile_sink_impl::open(const char* filename)
if (d_new_fp) { // if we've already got a new one open, close it
fclose(d_new_fp);
- d_new_fp = 0;
+ d_new_fp = nullptr;
}
- if ((d_new_fp = fdopen(fd, "wb")) == NULL) {
+ if (!(d_new_fp = fdopen(fd, "wb"))) {
GR_LOG_ERROR(d_logger,
boost::format("fdopen: %s: %s") % filename % strerror(errno));
+
::close(fd); // don't leak file descriptor if fdopen fails.
return false;
}
- d_updated = true;
- if (!wavheader_write(d_new_fp, d_sample_rate, d_nchans, d_bytes_per_sample_new)) {
- GR_LOG_ERROR(d_logger,
- boost::format("could not write to WAV file: %s") % strerror(errno))
- exit(-1);
+ d_h.first_sample_pos = 44;
+ if (!wavheader_write(
+ d_new_fp, d_h.sample_rate, d_h.nchans, d_bytes_per_sample_new)) {
+ GR_LOG_ERROR(d_logger, boost::format("could not save WAV header"));
+ fclose(d_new_fp);
+ return false;
}
+ d_updated = true;
+
return true;
}
@@ -136,12 +128,12 @@ void wavfile_sink_impl::close()
void wavfile_sink_impl::close_wav()
{
- unsigned int byte_count = d_sample_count * d_bytes_per_sample;
-
- wavheader_complete(d_fp, byte_count);
+ if (!wavheader_complete(d_fp, d_h.first_sample_pos)) {
+ GR_LOG_ERROR(d_logger, boost::format("could not save WAV header"));
+ }
fclose(d_fp);
- d_fp = NULL;
+ d_fp = nullptr;
}
wavfile_sink_impl::~wavfile_sink_impl() { stop(); }
@@ -150,7 +142,7 @@ bool wavfile_sink_impl::stop()
{
if (d_new_fp) {
fclose(d_new_fp);
- d_new_fp = NULL;
+ d_new_fp = nullptr;
}
close();
@@ -162,7 +154,7 @@ int wavfile_sink_impl::work(int noutput_items,
gr_vector_const_void_star& input_items,
gr_vector_void_star& output_items)
{
- float** in = (float**)&input_items[0];
+ auto in = (float**)&input_items[0];
int n_in_chans = input_items.size();
short int sample_buf_s;
@@ -170,12 +162,14 @@ int wavfile_sink_impl::work(int noutput_items,
int nwritten;
gr::thread::scoped_lock guard(d_mutex); // hold mutex for duration of this block
- do_update(); // update: d_fp is reqd
+ do_update(); // update: d_fp is read
if (!d_fp) // drop output on the floor
return noutput_items;
+ int nchans = d_h.nchans;
+ int bytes_per_sample = d_h.bytes_per_sample;
for (nwritten = 0; nwritten < noutput_items; nwritten++) {
- for (int chan = 0; chan < d_nchans; chan++) {
+ for (int chan = 0; chan < nchans; chan++) {
// Write zeros to channels which are in the WAV file
// but don't have any inputs here
if (chan < n_in_chans) {
@@ -184,7 +178,7 @@ int wavfile_sink_impl::work(int noutput_items,
sample_buf_s = 0;
}
- wav_write_sample(d_fp, sample_buf_s, d_bytes_per_sample);
+ wav_write_sample(d_fp, sample_buf_s, bytes_per_sample);
if (feof(d_fp) || ferror(d_fp)) {
GR_LOG_ERROR(d_logger,
@@ -192,7 +186,6 @@ int wavfile_sink_impl::work(int noutput_items,
close();
exit(-1);
}
- d_sample_count++;
}
}
@@ -203,11 +196,9 @@ short int wavfile_sink_impl::convert_to_short(float sample)
{
sample += d_normalize_shift;
sample *= d_normalize_fac;
- if (sample > d_max_sample_val) {
- sample = d_max_sample_val;
- } else if (sample < d_min_sample_val) {
- sample = d_min_sample_val;
- }
+
+ // In C++17, use std::clamp.
+ sample = std::max(std::min(sample, d_max_sample_val), d_min_sample_val);
return (short int)boost::math::iround(sample);
}
@@ -215,20 +206,39 @@ short int wavfile_sink_impl::convert_to_short(float sample)
void wavfile_sink_impl::set_bits_per_sample(int bits_per_sample)
{
gr::thread::scoped_lock guard(d_mutex);
- if (bits_per_sample == 8 || bits_per_sample == 16) {
- d_bytes_per_sample_new = bits_per_sample / 8;
+ set_bits_per_sample_unlocked(bits_per_sample);
+}
+
+void wavfile_sink_impl::set_bits_per_sample_unlocked(int bits_per_sample)
+{
+ switch (bits_per_sample) {
+ case 8:
+ d_max_sample_val = float(UINT8_MAX);
+ d_min_sample_val = float(0);
+ d_normalize_fac = d_max_sample_val / 2;
+ d_normalize_shift = 1;
+ break;
+ case 16:
+ d_max_sample_val = float(INT16_MAX);
+ d_min_sample_val = float(INT16_MIN);
+ d_normalize_fac = d_max_sample_val;
+ d_normalize_shift = 0;
+ break;
+ default:
+ throw std::runtime_error("Invalid bits per sample (only 8 and 16 are supported)");
}
+ d_bytes_per_sample_new = bits_per_sample / 8;
}
void wavfile_sink_impl::set_sample_rate(unsigned int sample_rate)
{
gr::thread::scoped_lock guard(d_mutex);
- d_sample_rate = sample_rate;
+ d_h.sample_rate = sample_rate;
}
int wavfile_sink_impl::bits_per_sample() { return d_bytes_per_sample_new; }
-unsigned int wavfile_sink_impl::sample_rate() { return d_sample_rate; }
+unsigned int wavfile_sink_impl::sample_rate() { return d_h.sample_rate; }
void wavfile_sink_impl::do_update()
{
@@ -241,22 +251,11 @@ void wavfile_sink_impl::do_update()
}
d_fp = d_new_fp; // install new file pointer
- d_new_fp = 0;
- d_sample_count = 0;
- d_bytes_per_sample = d_bytes_per_sample_new;
-
- if (d_bytes_per_sample == 1) {
- d_max_sample_val = UCHAR_MAX;
- d_min_sample_val = 0;
- d_normalize_fac = d_max_sample_val / 2;
- d_normalize_shift = 1;
- } else if (d_bytes_per_sample == 2) {
- d_max_sample_val = SHRT_MAX;
- d_min_sample_val = SHRT_MIN;
- d_normalize_fac = d_max_sample_val;
- d_normalize_shift = 0;
- }
+ d_new_fp = nullptr;
+ d_h.bytes_per_sample = d_bytes_per_sample_new;
+ // Avoid deadlock.
+ set_bits_per_sample_unlocked(8 * d_bytes_per_sample_new);
d_updated = false;
}