mirror of
https://github.com/holub/mame
synced 2025-07-04 17:38:08 +03:00
nlwav now accepts stdin and stdout. (nw)
cat log_RO.1.log | ./nlwav | play -
This commit is contained in:
parent
1765c5d9b4
commit
9e88fd79ea
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user