Hi, Here's a WAV file sink and source I wrote because I frequently work with WAV recordings of baseband or IF signals, plus I like using WAV manipulation software to analyze signals or do some quick-and-dirty processing. It's also useful as an audio source for testing audio transmission without having to use a microphone.
Of course I could use gr_file_sink and gr_file_source, but my blocks save me a conversion step and I use them a lot. If anyone feels like this is something worth having in GNU Radio, I'd be glad to submit my code [attached]. I can also provide a qa-script, but it requires a small test-file to work. Martin -- Martin Braun Institut fuer Nachrichtentechnik Universitaet Karlsruhe http://www.int.uni-karlsruhe.de
/* -*- c++ -*- */
/*
* Copyright 2004 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gri_wavfile_header.h>
#include <cstring>
bool
gri_wavheader_parse(FILE *fp,
unsigned int &sample_rate,
unsigned short &nchans,
int &bytes_per_sample,
int &first_sample_pos,
int &samples_per_chan,
int &normalize_fac,
int &normalize_shift)
{
char str_buf[8] = {0};
unsigned int file_size;
unsigned int fmt_hdr_skip;
unsigned short compression_type;
unsigned int avg_bytes_per_sec;
unsigned short block_align;
unsigned short bits_per_sample;
unsigned int chunk_size;
size_t fresult;
fresult = fread(str_buf, 1, 4, fp);
if (fresult != 4 || strncmp(str_buf, "RIFF", 4) || feof(fp)) {
return false;
}
fread(&file_size, 1, 4, fp); // file size
fresult = fread(str_buf, 1, 8, fp);
if (fresult != 8 || strncmp(str_buf, "WAVEfmt ", 8) || feof(fp)) {
return false;
}
fread(&fmt_hdr_skip, 1, 4, fp);
fmt_hdr_skip -= 16;
fread(&compression_type, 1, 2, fp);
if (compression_type != 0x0001) { // Invalid compression type
return false;
}
fread(&nchans, 1, 2, fp);
fread(&sample_rate, 1, 4, fp);
fread(&avg_bytes_per_sec, 1, 4, fp);
fread(&block_align, 1, 2, fp);
fread(&bits_per_sample, 1, 2, fp);
if (ferror(fp)) {
return false;
}
if (bits_per_sample != 8 && bits_per_sample != 16) {
return false;
}
bytes_per_sample = bits_per_sample / 8;
if (fmt_hdr_skip) {
fseek(fp, fmt_hdr_skip, SEEK_CUR);
}
// data chunk
fresult = fread(str_buf, 1, 4, fp);
if (strncmp(str_buf, "data", 4)) {
return false;
}
fread(&chunk_size, 1, 4, fp);
if (ferror(fp)) {
return false;
}
samples_per_chan = chunk_size / (bytes_per_sample * nchans);
if (bytes_per_sample == 1) {
normalize_fac = 128;
normalize_shift = 1;
} else {
normalize_fac = 0x7FFF;
}
return true;
}
bool
gri_wavheader_write(FILE *fp,
unsigned int &sample_rate,
unsigned short &nchans,
int &bytes_per_sample)
{
const int header_len = 44;
char wav_hdr[header_len] = "RIFF\0\0\0\0WAVEfmt \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0data\0\0\0";
unsigned short int block_align = bytes_per_sample * nchans;
unsigned int avg_bytes = sample_rate * block_align;
unsigned short int bits_per_sample = bytes_per_sample * 8;
wav_hdr[16] = 0x10; // no extra bytes
wav_hdr[20] = 0x01; // no compression
memcpy((void *) (wav_hdr + 22), (void *) &nchans, sizeof(short));
memcpy((void *) (wav_hdr + 24), (void *) &sample_rate, sizeof(unsigned));
memcpy((void *) (wav_hdr + 28), (void *) &avg_bytes, sizeof(unsigned));
memcpy((void *) (wav_hdr + 32), (void *) &block_align, sizeof(short));
memcpy((void *) (wav_hdr + 34), (void *) &bits_per_sample, sizeof(short));
fwrite(&wav_hdr, 1, header_len, fp);
if (ferror(fp)) {
return false;
}
return true;
}
bool
gri_wavheader_complete(FILE *fp, unsigned int byte_count)
{
fseek(fp, 40, SEEK_SET);
fwrite(&byte_count, 1, sizeof(unsigned), fp);
byte_count += 36; // fmt chunk and data header
fseek(fp, 4, SEEK_SET);
fwrite(&byte_count, 1, sizeof(unsigned), fp);
if (ferror(fp)) {
return false;
}
return true;
}
/* -*- c++ -*- */
/*
* Copyright 2004 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_WAVFILE_SINK_H
#define INCLUDED_GR_WAVFILE_SINK_H
#include <gr_sync_block.h>
#include <gr_file_sink_base.h>
#include <omnithread.h>
class gr_wavfile_sink;
typedef boost::shared_ptr<gr_wavfile_sink> gr_wavfile_sink_sptr;
/*
* \p filename The .wav file to be opened
* \p repeat If this is set to true, the samples are repeated infinitely
* \p normalize If set to false, sample values aren't within [-1;1] but are
* exactly the (integer) values of what the .wav-files contain.
* Remember 8-bit .wav-files are represented with unsigned integers.
*/
gr_wavfile_sink_sptr
gr_make_wavfile_sink (const char *filename,
unsigned int n_channels,
unsigned int sample_rate,
unsigned int bits_per_sample = 16);
/*!
* \brief Read stream from a Microsoft PCM (.wav) file, output floats
*
* Unless otherwise called, values are within [-1;1].
* Check gr_make_wavfile_source() for extra info.
*
* \ingroup sink
*/
class gr_wavfile_sink : public gr_sync_block
{
friend gr_wavfile_sink_sptr gr_make_wavfile_sink (const char *filename,
unsigned int n_channels,
unsigned int sample_rate,
unsigned int bits_per_sample);
private:
bool d_normalize;
unsigned int d_sample_rate;
unsigned int d_sample_count;
unsigned short d_nchans;
int d_bytes_per_sample;
int d_bytes_per_sample_new;
int d_normalize_fac;
int d_normalize_shift;
int d_max_sample_val;
int d_min_sample_val;
FILE *d_fp;
FILE *d_new_fp;
bool d_updated;
omni_mutex d_mutex;
/*!
* \brief Convert a sample value within [-1;+1] to a corresponding
* short integer value
*/
short int convert_to_short(float sample);
/*!
* \brief Writes information to the WAV header which is not available
* a-priori (chunk size etc.) and closes the file. Not thread-safe and
* assumes d_fp is a valid file pointer, should thus only be called by other methods.
*/
void close_wav();
protected:
gr_wavfile_sink(const char *filename,
unsigned int n_channels,
unsigned int sample_rate,
unsigned int bits_per_sample);
public:
~gr_wavfile_sink ();
/*!
* \brief Opens a new file and writes a WAV header. Thread-safe.
*/
bool open(const char* filename);
/*!
* \brief Closes the currently active file and completes the WAV
* header. Thread-safe.
*/
void close();
/*!
* \brief If any file changes have occurred, update now. This is called
* internally by work() and thus doesn't usually need to be called by
* hand.
*/
void do_update();
/*!
* \brief Set the sample rate. This will not affect the WAV file
* currently opened. Any following open() calls will use this new
* sample rate.
*/
void set_sample_rate(unsigned int sample_rate);
/*!
* \brief Set bits per sample. This will not affect the WAV file
* currently opened (see set_sample_rate()). If the value is neither
* 8 nor 16, the call is ignored and the current value is kept.
*/
void set_bits_per_sample(unsigned int bits_per_sample);
int work (int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
};
#endif /* INCLUDED_GR_WAVFILE_SINK_H */
/* -*- c++ -*- */
/*
* Copyright 2004 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gr_wavfile_source.h>
#include <gr_io_signature.h>
#include <gri_wavfile_header.h>
#include <cstdio>
#include <sys/types.h>
#include <fcntl.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
gr_wavfile_source::gr_wavfile_source (const char *filename,
bool repeat, bool normalize)
: gr_sync_block ("wavfile_source",
gr_make_io_signature (0, 0, 0),
gr_make_io_signature (1, 2, sizeof(float))),
d_fp (NULL), d_repeat (repeat), d_normalize(normalize),
d_sample_rate(1), d_nchans(1), d_bytes_per_sample(2), d_first_sample_pos(0),
d_samples_per_chan(0), d_normalize_fac(1), d_normalize_shift(0), 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) {
perror (filename);
throw std::runtime_error ("can't open file");
}
if ((d_fp = fdopen (fd, "rb")) == NULL) {
perror (filename);
throw std::runtime_error ("can't open file");
}
// Scan headers, check file validity
if (!gri_wavheader_parse(d_fp,
d_sample_rate,
d_nchans,
d_bytes_per_sample,
d_first_sample_pos,
d_samples_per_chan,
d_normalize_fac,
d_normalize_shift)) {
throw std::runtime_error("is not a valid wav file");
}
if (d_samples_per_chan == 0) {
throw std::runtime_error("WAV file does not contain any samples");
}
// Re-set the output signature
set_output_signature(gr_make_io_signature(1, d_nchans, sizeof(float)));
}
gr_wavfile_source_sptr
gr_make_wavfile_source (const char *filename, bool repeat, bool normalize)
{
return gr_wavfile_source_sptr (new gr_wavfile_source (filename, repeat, normalize));
}
gr_wavfile_source::~gr_wavfile_source ()
{
fclose ((FILE *) d_fp);
}
int
gr_wavfile_source::work (int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
float **out = (float **) &output_items[0];
int n_out_chans = output_items.size();
int i;
short int samp_buf;
float samp_buf_f;
for (i = 0; i < noutput_items; i++) {
if (d_sample_idx >= d_samples_per_chan) {
if (!d_repeat) {
// if nothing was read at all, say we're done.
return i ? i : -1;
}
if (fseek (d_fp, d_first_sample_pos, SEEK_SET) == -1) {
fprintf(stderr, "[%s] fseek failed\n", __FILE__);
exit(-1);
}
d_sample_idx = 0;
}
for (int chan = 0; chan < d_nchans; chan++) {
samp_buf = 0;
fread(&samp_buf, d_bytes_per_sample, 1, d_fp);
samp_buf_f = ((float) samp_buf);
if (d_normalize) {
samp_buf_f /= d_normalize_fac;
samp_buf_f -= d_normalize_shift;
}
if (chan < n_out_chans) {
out[chan][i] = samp_buf_f;
}
}
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)) {
if (i == 0) {
fprintf(stderr, "[%s] WAV file has corrupted header or i/o error\n", __FILE__);
return -1;
}
return i;
}
}
return noutput_items;
}
/* -*- c++ -*- */
/*
* Copyright 2004 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_WAVFILE_SOURCE_H
#define INCLUDED_GR_WAVFILE_SOURCE_H
#include <gr_sync_block.h>
class gr_wavfile_source;
typedef boost::shared_ptr<gr_wavfile_source> gr_wavfile_source_sptr;
gr_wavfile_source_sptr
gr_make_wavfile_source (const char *filename, bool repeat = false, bool normalize = true);
/*!
* \brief Read stream from a Microsoft PCM (.wav) file, output floats
*
* Unless otherwise called, values are within [-1;1].
* Check gr_make_wavfile_source() for extra info.
*
* \ingroup source
*/
class gr_wavfile_source : public gr_sync_block
{
friend gr_wavfile_source_sptr gr_make_wavfile_source (const char *filename,
bool repeat,
bool normalize);
private:
FILE *d_fp;
bool d_repeat;
bool d_normalize;
unsigned int d_sample_rate;
unsigned short d_nchans;
int d_bytes_per_sample;
int d_first_sample_pos;
int d_samples_per_chan;
int d_normalize_fac;
int d_normalize_shift;
int d_sample_idx;
protected:
gr_wavfile_source(const char *filename, bool repeat, bool normalize);
/*!
* \brief Go through wav header, read info, check validity
*/
bool parse_wav_header(FILE *fp);
public:
~gr_wavfile_source ();
int work (int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
/*!
* \brief Read the sample rate as specified in the wav file header
*/
unsigned int get_sample_rate() { return d_sample_rate; };
/*!
* \brief Return the number of bits per sample as specified in the wav
* file header. Only 8 or 16 bit are supported here.
*/
unsigned int get_bits_per_sample() { return d_bytes_per_sample * 8; };
/*!
* \brief Return the number of channels in the wav file as specified in
* the wav file header. This is also the max number of outputs you can
* have.
*/
unsigned int get_n_channels() { return d_nchans; };
};
#endif /* INCLUDED_GR_WAVFILE_SOURCE_H */
/* -*- c++ -*- */ /* * Copyright 2004 Free Software Foundation, Inc. * * This file is part of GNU Radio * * GNU Radio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * GNU Radio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Radio; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ // This file stores all the RIFF file type knowledge for the gr_wavfile_* // blocks. #include <cstdio> /*! * \brief Read signal information from a given WAV file. * * \p fp File pointer to an opened, empty file. * \p sample_rate Stores the sample rate [S/s] * \p nchans Number of channels * \p bytes_per_sample Bytes per sample, can either be 1 or 2 (corresponding to * 8 or 16 bit samples, respectively) * \p first_sample_pos Number of the first byte containing a sample. Use this * with fseek() to jump from the end of the file to the first sample * when in repeat mode. * \p samples_per_chan Number of samples per channel * \p normalize_fac The normalization factor with which you need to divide the * integer values of the samples to get them within [-1;1] * \p normalize_shift The value by which the sample values need to be shifted * after normalization (reason being, 8-bit WAV files store samples as * unsigned char and 16-bit as signed short int) * \return True on a successful read, false if the file could not be read or is * not a valid WAV file. */ bool gri_wavheader_parse(FILE *fp, unsigned int &sample_rate, unsigned short &nchans, int &bytes_per_sample, int &first_sample_pos, int &samples_per_chan, int &normalize_fac, int &normalize_shift); /*! * \brief Write a valid RIFF file header * * Note: Some header values are kept blank because they're usually not known * a-priori (file and chunk lengths). Use gri_wavheader_complete() to fill * these in. */ bool gri_wavheader_write(FILE *fp, unsigned int &sample_rate, unsigned short &nchans, int &bytes_per_sample); /*! * \brief Complete a WAV header * * Note: The stream position is changed during this function. If anything * needs to be written to the WAV file after calling this function (which * shouldn't happen), you need to fseek() to the end of the file (or * whereever). * * \p fp File pointer to an open WAV file with a blank header * \p byte_count Length of all samples written to the file in bytes. */ bool gri_wavheader_complete(FILE *fp, unsigned int byte_count);
/* -*- c++ -*- */
/*
* Copyright 2004,2006,2007 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gr_wavfile_sink.h>
#include <gr_io_signature.h>
#include <gri_wavfile_header.h>
#include <stdexcept>
#include <climits>
#include <cstring>
#include <cmath>
#include <fcntl.h>
// 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
gr_wavfile_sink_sptr
gr_make_wavfile_sink (const char *filename,
unsigned int n_channels,
unsigned int sample_rate,
unsigned int bits_per_sample)
{
return gr_wavfile_sink_sptr (new gr_wavfile_sink (filename,
n_channels,
sample_rate,
bits_per_sample));
}
gr_wavfile_sink::gr_wavfile_sink(const char *filename,
unsigned int n_channels,
unsigned int sample_rate,
unsigned int bits_per_sample)
: gr_sync_block ("wavfile_sink",
gr_make_io_signature(1, n_channels, sizeof(float)),
gr_make_io_signature(0, 0, 0)),
d_sample_rate(sample_rate), d_nchans(n_channels), d_normalize_shift(0),
d_fp(0), d_new_fp(0), 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;
if (!open(filename)) {
throw std::runtime_error ("can't open file");
}
if (bits_per_sample == 8) {
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 (bits_per_sample == 16) {
d_max_sample_val = SHRT_MAX;
d_min_sample_val = SHRT_MIN;
d_normalize_fac = d_max_sample_val;
}
}
bool
gr_wavfile_sink::open(const char* filename)
{
omni_mutex_lock l(d_mutex);
// we use the open system call to get access to the O_LARGEFILE flag.
int fd;
if ((fd = ::open (filename,
O_WRONLY|O_CREAT|O_TRUNC|OUR_O_LARGEFILE|OUR_O_BINARY,
0664)) < 0){
perror (filename);
return false;
}
if (d_new_fp) { // if we've already got a new one open, close it
fclose(d_new_fp);
d_new_fp = 0;
}
if ((d_new_fp = fdopen (fd, "wb")) == NULL) {
perror (filename);
::close(fd); // don't leak file descriptor if fdopen fails.
return false;
}
d_updated = true;
if (!gri_wavheader_write(d_new_fp,
d_sample_rate,
d_nchans,
d_bytes_per_sample_new)) {
fprintf(stderr, "[%s] could not write to WAV file\n", __FILE__);
exit(-1);
}
return true;
}
void
gr_wavfile_sink::close()
{
omni_mutex_lock l(d_mutex);
if (!d_fp)
return;
close_wav();
}
void gr_wavfile_sink::close_wav()
{
unsigned int byte_count = d_sample_count * d_bytes_per_sample;
gri_wavheader_complete(d_fp, byte_count);
fclose(d_fp);
d_fp = NULL;
}
gr_wavfile_sink::~gr_wavfile_sink ()
{
if (d_new_fp) {
fclose(d_new_fp);
}
close();
}
int
gr_wavfile_sink::work (int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
float **in = (float **) &input_items[0];
int n_in_chans = input_items.size();
short int sample_buf_s;
int nwritten;
do_update(); // update: d_fp is reqd
if (!d_fp) // drop output on the floor
return noutput_items;
for (nwritten = 0; nwritten < noutput_items; nwritten++) {
for (int chan = 0; chan < d_nchans; chan++) {
// Write zeros to channels which are in the WAV file
// but don't have any inputs here
if (chan < n_in_chans) {
sample_buf_s =
convert_to_short(in[chan][nwritten]);
} else {
sample_buf_s = 0;
}
fwrite(&sample_buf_s, 1, d_bytes_per_sample, d_fp);
if (feof(d_fp) || ferror(d_fp)) {
fprintf(stderr, "[%s] file i/o error\n", __FILE__);
close();
exit(-1);
}
d_sample_count++;
}
}
return nwritten;
}
short int
gr_wavfile_sink::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;
}
return (short int) roundf(sample);
}
void
gr_wavfile_sink::set_bits_per_sample(unsigned int bits_per_sample)
{
omni_mutex_lock l(d_mutex);
if (bits_per_sample == 8 || bits_per_sample == 16) {
d_bytes_per_sample_new = bits_per_sample / 8;
}
}
void
gr_wavfile_sink::set_sample_rate(unsigned int sample_rate)
{
omni_mutex_lock l(d_mutex);
d_sample_rate = sample_rate;
}
void
gr_wavfile_sink::do_update()
{
if (!d_updated) {
return;
}
omni_mutex_lock l(d_mutex); // hold mutex for duration of this block
if (d_fp) {
close_wav();
}
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_updated = false;
}
gr_wavfile_i.DEFANGED-10
Description: application/defanged-10
_______________________________________________ Patch-gnuradio mailing list [email protected] http://lists.gnu.org/mailman/listinfo/patch-gnuradio
