nlwav now accepts stdin and stdout. (nw)

cat log_RO.1.log | ./nlwav | play -
This commit is contained in:
couriersud 2017-01-08 22:59:45 +01:00
parent 1765c5d9b4
commit 9e88fd79ea

View File

@ -7,14 +7,15 @@
#include "plib/plists.h" #include "plib/plists.h"
#include "plib/pstream.h" #include "plib/pstream.h"
#include "nl_setup.h" #include "nl_setup.h"
#include <memory>
class nlwav_options_t : public plib::options class nlwav_options_t : public plib::options
{ {
public: public:
nlwav_options_t() : nlwav_options_t() :
plib::options(), plib::options(),
opt_inp(*this, "i", "input", "", "input file"), opt_inp(*this, "i", "input", "-", "input file"),
opt_out(*this, "o", "output", "", "output file"), opt_out(*this, "o", "output", "-", "output file"),
opt_amp(*this, "a", "amp", 10000.0, "amplification after mean correction"), opt_amp(*this, "a", "amp", 10000.0, "amplification after mean correction"),
opt_verb(*this, "v", "verbose", "be verbose - this produces lots of output"), opt_verb(*this, "v", "verbose", "be verbose - this produces lots of output"),
opt_quiet(*this,"q", "quiet", "be quiet - no warnings"), opt_quiet(*this,"q", "quiet", "be quiet - no warnings"),
@ -30,12 +31,24 @@ public:
plib::option_bool opt_help; plib::option_bool opt_help;
}; };
plib::pstdin pin_strm;
plib::pstdout pout_strm; plib::pstdout pout_strm;
plib::pstderr perr_strm; plib::pstderr perr_strm;
plib::pstream_fmt_writer_t pout(pout_strm); plib::pstream_fmt_writer_t pout(pout_strm);
plib::pstream_fmt_writer_t perr(perr_strm); plib::pstream_fmt_writer_t perr(perr_strm);
nlwav_options_t opts;
/* From: https://ffmpeg.org/pipermail/ffmpeg-devel/2007-October/038122.html
* The most compatible way to make a wav header for unknown length is to put
* 0xffffffff in the header. 0 as the RIFF length and 0 as the data chunk length
* is a common agreement in serious recording applications while
* still recording the file. So a playback application can determine that the
* given file is still being recorded. As soon as the recording application
* finishes the ongoing recording, it writes the correct values for RIFF lenth
* and data chunk length to the file.
*/
/* http://de.wikipedia.org/wiki/RIFF_WAVE */ /* http://de.wikipedia.org/wiki/RIFF_WAVE */
class wav_t class wav_t
{ {
@ -49,6 +62,9 @@ public:
} }
~wav_t() ~wav_t()
{ {
if (m_f.seekable())
{
m_fh.filelen = m_data.len + sizeof(m_data) + sizeof(m_fh) + sizeof(m_fmt) - 8;
m_f.seek(0); m_f.seek(0);
m_f.write(&m_fh, sizeof(m_fh)); m_f.write(&m_fh, sizeof(m_fh));
m_f.write(&m_fmt, sizeof(m_fmt)); m_f.write(&m_fmt, sizeof(m_fmt));
@ -56,6 +72,7 @@ public:
//data.len = fmt.block_align * n; //data.len = fmt.block_align * n;
m_f.write(&m_data, sizeof(m_data)); m_f.write(&m_data, sizeof(m_data));
} }
}
unsigned channels() { return m_fmt.channels; } unsigned channels() { return m_fmt.channels; }
unsigned sample_rate() { return m_fmt.sample_rate; } unsigned sample_rate() { return m_fmt.sample_rate; }
@ -63,44 +80,44 @@ public:
void write_sample(int sample) void write_sample(int sample)
{ {
m_data.len += m_fmt.block_align; m_data.len += m_fmt.block_align;
short ps = static_cast<short>(sample); /* 16 bit sample, FIXME: Endianess? */ int16_t ps = static_cast<int16_t>(sample); /* 16 bit sample, FIXME: Endianess? */
m_f.write(&ps, sizeof(ps)); m_f.write(&ps, sizeof(ps));
} }
private: private:
struct riff_chunk_t struct riff_chunk_t
{ {
char group_id[4]; uint8_t group_id[4];
unsigned filelen; uint32_t filelen;
char rifftype[4]; uint8_t rifftype[4];
}; };
struct riff_format_t struct riff_format_t
{ {
char signature[4]; uint8_t signature[4];
unsigned fmt_length; uint32_t fmt_length;
short format_tag; uint16_t format_tag;
unsigned short channels; uint16_t channels;
unsigned sample_rate; uint32_t sample_rate;
unsigned bytes_per_second; uint32_t bytes_per_second;
unsigned short block_align; uint16_t block_align;
unsigned short bits_sample; uint16_t bits_sample;
}; };
struct riff_data_t struct riff_data_t
{ {
char signature[4]; uint8_t signature[4];
unsigned len; uint32_t len;
// data follows // data follows
}; };
void initialize(unsigned sr) void initialize(unsigned sr)
{ {
std::strncpy(m_fh.group_id, "RIFF", 4); std::memcpy(m_fh.group_id, "RIFF", 4);
m_fh.filelen = 0; // Fixme m_fh.filelen = 0x0; // Fixme
std::strncpy(m_fh.rifftype, "WAVE", 4); std::memcpy(m_fh.rifftype, "WAVE", 4);
std::strncpy(m_fmt.signature, "fmt ", 4); std::memcpy(m_fmt.signature, "fmt ", 4);
m_fmt.fmt_length = 16; m_fmt.fmt_length = 16;
m_fmt.format_tag = 0x0001; //PCM m_fmt.format_tag = 0x0001; //PCM
m_fmt.channels = 1; m_fmt.channels = 1;
@ -109,8 +126,10 @@ private:
m_fmt.block_align = m_fmt.channels * ((m_fmt.bits_sample + 7) / 8); m_fmt.block_align = m_fmt.channels * ((m_fmt.bits_sample + 7) / 8);
m_fmt.bytes_per_second = m_fmt.sample_rate * m_fmt.block_align; m_fmt.bytes_per_second = m_fmt.sample_rate * m_fmt.block_align;
std::strncpy(m_data.signature, "data", 4); std::memcpy(m_data.signature, "data", 4);
m_data.len = m_fmt.bytes_per_second * 2 * 0; //m_data.len = m_fmt.bytes_per_second * 2 * 0;
/* force "play" to play and warn about eof instead of being silent */
m_data.len = (m_f.seekable() ? 0 : 0xffffffff);
} }
@ -124,12 +143,11 @@ private:
static void convert(nlwav_options_t &opts) static void convert(nlwav_options_t &opts)
{ {
plib::pofilestream fo(opts.opt_out()); plib::postream *fo = (opts.opt_out() == "-" ? &pout_strm : new plib::pofilestream(opts.opt_out()));
wav_t wo(fo, 48000); plib::pistream *fin = (opts.opt_inp() == "-" ? &pin_strm : new plib::pifilestream(opts.opt_inp()));
wav_t *wo = new wav_t(*fo, 48000);
plib::pifilestream fin(opts.opt_inp()); double dt = 1.0 / static_cast<double>(wo->sample_rate());
double dt = 1.0 / static_cast<double>(wo.sample_rate());
double ct = dt; double ct = dt;
//double mean = 2.4; //double mean = 2.4;
double amp = opts.opt_amp(); double amp = opts.opt_amp();
@ -144,7 +162,7 @@ static void convert(nlwav_options_t &opts)
//short sample = 0; //short sample = 0;
pstring line; pstring line;
while(fin.readline(line)) while(fin->readline(line))
{ {
#if 1 #if 1
double t = 0.0; double v = 0.0; double t = 0.0; double v = 0.0;
@ -160,12 +178,12 @@ static void convert(nlwav_options_t &opts)
minsam = std::min(minsam, outsam); minsam = std::min(minsam, outsam);
n++; n++;
//mean = means / (double) n; //mean = means / (double) n;
mean += 5.0 / static_cast<double>(wo.sample_rate()) * (outsam - mean); mean += 5.0 / static_cast<double>(wo->sample_rate()) * (outsam - mean);
} }
outsam = (outsam - mean) * amp; outsam = (outsam - mean) * amp;
outsam = std::max(-32000.0, outsam); outsam = std::max(-32000.0, outsam);
outsam = std::min(32000.0, outsam); outsam = std::min(32000.0, outsam);
wo.write_sample(static_cast<int>(outsam)); wo->write_sample(static_cast<int>(outsam));
outsam = 0.0; outsam = 0.0;
lt = ct; lt = ct;
ct += dt; ct += dt;
@ -194,10 +212,19 @@ static void convert(nlwav_options_t &opts)
//printf("%f %f\n", t, v); //printf("%f %f\n", t, v);
#endif #endif
} }
pout("Mean (low freq filter): {}\n", mean); delete wo;
pout("Mean (static): {}\n", means / static_cast<double>(n)); if (opts.opt_inp() != "-")
pout("Amp + {}\n", 32000.0 / (maxsam- mean)); delete fin;
pout("Amp - {}\n", -32000.0 / (minsam- mean)); if (opts.opt_out() != "-")
delete fo;
if (!opts.opt_quiet())
{
perr("Mean (low freq filter): {}\n", mean);
perr("Mean (static): {}\n", means / static_cast<double>(n));
perr("Amp + {}\n", 32000.0 / (maxsam- mean));
perr("Amp - {}\n", -32000.0 / (minsam- mean));
}
} }
static void usage(plib::pstream_fmt_writer_t &fw, nlwav_options_t &opts) static void usage(plib::pstream_fmt_writer_t &fw, nlwav_options_t &opts)
@ -209,7 +236,6 @@ static void usage(plib::pstream_fmt_writer_t &fw, nlwav_options_t &opts)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
nlwav_options_t opts;
int ret; int ret;
if ((ret = opts.parse(argc, argv)) != argc) if ((ret = opts.parse(argc, argv)) != argc)