diff options
Diffstat (limited to 'src/lib/netlist/prg/nlwav.cpp')
-rw-r--r-- | src/lib/netlist/prg/nlwav.cpp | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/src/lib/netlist/prg/nlwav.cpp b/src/lib/netlist/prg/nlwav.cpp new file mode 100644 index 00000000000..681b0e6d79e --- /dev/null +++ b/src/lib/netlist/prg/nlwav.cpp @@ -0,0 +1,289 @@ +#include <cstdio> +#include <cstring> +#include "plib/poptions.h" +#include "plib/pstring.h" +#include "plib/plists.h" +#include "plib/pstream.h" +#include "nl_setup.h" + +class nlwav_options_t : public poptions +{ +public: + nlwav_options_t() : + poptions(), +#if 0 + opt_ttr ("t", "time_to_run", 1.0, "time to run the emulation (seconds)", this), + opt_name("n", "name", "", "netlist in file to run; default is first one", this), + opt_logs("l", "logs", "", "colon separated list of terminals to log", this), + opt_file("f", "file", "-", "file to process (default is stdin)", this), + opt_type("y", "type", "spice", "spice:eagle", "type of file to be converted: spice,eagle", this), + opt_cmd ("c", "cmd", "run", "run|convert|listdevices", this), + opt_inp( "i", "input", "", "input file to process (default is none)", this), +#endif + opt_inp( "i", "input", "", "input file", this), + opt_out( "o", "output", "", "output file", this), + opt_amp( "a", "amp", 10000.0, "amplification after mean correction", this), + opt_verb("v", "verbose", "be verbose - this produces lots of output", this), + opt_quiet("q", "quiet", "be quiet - no warnings", this), + opt_help("h", "help", "display help", this) + {} +#if 0 + poption_double opt_ttr; + poption_str opt_name; + poption_str opt_logs; + poption_str opt_file; + poption_str_limit opt_type; + poption_str opt_cmd; +#endif + poption_str opt_inp; + poption_str opt_out; + poption_double opt_amp; + poption_bool opt_verb; + poption_bool opt_quiet; + poption_bool opt_help; +}; + +/* http://de.wikipedia.org/wiki/RIFF_WAVE */ +class wav_t +{ +public: + wav_t(postream &strm, unsigned sr) : m_f(strm) + { +// m_f = strm; + initialize(sr); + m_f.write(&m_fh, sizeof(m_fh)); + m_f.write(&m_fmt, sizeof(m_fmt)); + m_f.write(&m_data, sizeof(m_data)); + } + ~wav_t() + { + close(); + } + + unsigned channels() { return m_fmt.channels; } + unsigned sample_rate() { return m_fmt.sample_rate; } + + void write_sample(int sample) + { + m_data.len += m_fmt.block_align; + short ps = sample; /* 16 bit sample, FIXME: powerpc? */ + m_f.write(&ps, sizeof(ps)); + } + + void close() + { + m_f.seek(0); + m_f.write(&m_fh, sizeof(m_fh)); + m_f.write(&m_fmt, sizeof(m_fmt)); + + //data.len = fmt.block_align * n; + m_f.write(&m_data, sizeof(m_data)); + } +private: + struct riff_chunk_t + { + char group_id[4]; + unsigned filelen; + char rifftype[4]; + }; + + struct riff_format_t + { + char signature[4]; + unsigned fmt_length; + short format_tag; + short channels; + unsigned sample_rate; + unsigned bytes_per_second; + short block_align; + short bits_sample; + }; + + struct riff_data_t + { + char signature[4]; + unsigned len; + // data follows + }; + + void initialize(unsigned sr) + { + std::strncpy(m_fh.group_id, "RIFF", 4); + m_fh.filelen = 0; // Fixme + std::strncpy(m_fh.rifftype, "WAVE", 4); + + std::strncpy(m_fmt.signature, "fmt ", 4); + m_fmt.fmt_length = 16; + m_fmt.format_tag = 0x0001; //PCM + m_fmt.channels = 1; + m_fmt.sample_rate = sr; + m_fmt.bits_sample = 16; + 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; + + std::strncpy(m_data.signature, "data", 4); + m_data.len = m_fmt.bytes_per_second * 2 * 0; + + } + + riff_chunk_t m_fh; + riff_format_t m_fmt; + riff_data_t m_data; + + postream &m_f; + +}; + +void convert(nlwav_options_t &opts) +{ + pofilestream fo(opts.opt_out()); + if (fo.bad()) + { + throw netlist::fatalerror_e("Error opening output file: " + opts.opt_out()); + } + wav_t wo(fo, 48000); + + pifilestream fin(opts.opt_inp()); + if (fin.bad()) + throw netlist::fatalerror_e("Error opening input file: " + opts.opt_inp()); + + double dt = 1.0 / (double) wo.sample_rate(); + double ct = dt; + //double mean = 2.4; + double amp = opts.opt_amp(); + double mean = 0.0; + double means = 0.0; + double cursam = 0.0; + double outsam = 0.0; + double lt = 0.0; + double maxsam = -1e9; + double minsam = 1e9; + int n = 0; + //short sample = 0; + pstring line; + + while(fin.readline(line)) + { +#if 1 + float t = 0.0; float v = 0.0; + sscanf(line.cstr(), "%f %f", &t, &v); + while (t >= ct) + { + outsam += (ct - lt) * cursam; + outsam = outsam / dt; + if (t>0.0) + { + means += outsam; + maxsam = std::max(maxsam, outsam); + minsam = std::min(minsam, outsam); + n++; + //mean = means / (double) n; + mean += 5.0 / (double) wo.sample_rate() * (outsam - mean); + } + outsam = (outsam - mean) * amp; + outsam = std::max(-32000.0, outsam); + outsam = std::min(32000.0, outsam); + wo.write_sample((int) outsam); + outsam = 0.0; + lt = ct; + ct += dt; + } + outsam += (t-lt)*cursam; + lt = t; + cursam = v; +#else + float t = 0.0; float v = 0.0; + fscanf(FIN, "%f %f", &t, &v); + while (ct <= t) + { + wo.write_sample(sample); + n++; + ct += dt; + } + means += v; + mean = means / (double) n; + v = v - mean; + v = v * amp; + if (v>32000.0) + v = 32000.0; + else if (v<-32000.0) + v = -32000.0; + sample = v; + //printf("%f %f\n", t, v); +#endif + } + printf("Mean (low freq filter): %f\n", mean); + printf("Mean (static): %f\n", means / (double) n); + printf("Amp + %f\n", 32000.0 / (maxsam- mean)); + printf("Amp - %f\n", -32000.0 / (minsam- mean)); + wo.close(); + fo.close(); + fin.close(); + +} + +void usage(nlwav_options_t &opts) +{ + fprintf(stderr, + "Usage:\n" + " nltool -help\n" + " nltool [options]\n" + "\n" + "Where:\n" + ); + fprintf(stderr, "%s\n", opts.help().cstr()); +} + + +int main(int argc, char *argv[]) +{ +#if (!PSTANDALONE) + track_memory(true); + { +#endif + nlwav_options_t opts; + int ret; + + if ((ret = opts.parse(argc, argv)) != argc) + { + fprintf(stderr, "Error parsing %s\n", argv[ret]); + usage(opts); + return 1; + } + + if (opts.opt_help()) + { + usage(opts); + return 1; + } + + convert(opts); +#if (!PSTANDALONE) + } + dump_unfreed_mem(); +#endif + + return 0; +} + +/* +Der Daten-Abschnitt enth??lt die Abtastwerte: +Offset L??nge Inhalt Beschreibung +36 (0x24) 4 'data' Header-Signatur +40 (0x28) 4 <length> L??nge des Datenblocks, max. <Dateigr????e>?????????44 + +0 (0x00) char 4 'RIFF' +4 (0x04) unsigned 4 <Dateigr????e>?????????8 +8 (0x08) char 4 'WAVE' + +Der fmt-Abschnitt (24 Byte) beschreibt das Format der einzelnen Abtastwerte: +Offset L??nge Inhalt Beschreibung +12 (0x0C) 4 'fmt ' Header-Signatur (folgendes Leerzeichen beachten) +16 (0x10) 4 <fmt length> L??nge des restlichen fmt-Headers (16 Bytes) +20 (0x14) 2 <format tag> Datenformat der Abtastwerte (siehe separate Tabelle weiter unten) +22 (0x16) 2 <channels> Anzahl der Kan??le: 1 = mono, 2 = stereo; mittlerweile sind auch mehr als 2 Kan??le (z. B. f??r Raumklang) m??glich.[2] +24 (0x18) 4 <sample rate> Samples pro Sekunde je Kanal (z. B. 44100) +28 (0x1C) 4 <bytes/second> Abtastrate????????Frame-Gr????e +32 (0x20) 2 <block align> Frame-Gr????e = <Anzahl der Kan??le>????????((<Bits/Sample (eines Kanals)>???+???7)???/???8) (Division ohne Rest) +34 (0x22) 2 <bits/sample> Anzahl der Datenbits pro Samplewert je Kanal (z. B. 12) +*/ |