summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2016-05-14 20:27:56 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2016-05-14 20:27:56 +0200
commit36a62ae3403f7cfb02bd8dde43b6b2fa96fe867b (patch)
treec4ea5f2f97e94688bd0ac96dbb198a8f1eb67491 /test
parent7bbc7520ecb2ff4fc020189c1fdfebd7d3bb8e42 (diff)
Make all components use the same Random instance and add seed method on DrumGizmo class. Added dgreftest application for doing reference midifile rendering tests.
Diffstat (limited to 'test')
-rw-r--r--test/Makefile.am2
-rw-r--r--test/dgreftest/Makefile.am36
-rw-r--r--test/dgreftest/compareoutputengine.cc138
-rw-r--r--test/dgreftest/compareoutputengine.h55
-rw-r--r--test/dgreftest/dgreftest.cc136
-rw-r--r--test/dgreftest/midiinputengine.cc192
-rw-r--r--test/dgreftest/midiinputengine.h64
-rw-r--r--test/dgreftest/wavfileoutputengine.cc125
-rw-r--r--test/dgreftest/wavfileoutputengine.h54
9 files changed, 802 insertions, 0 deletions
diff --git a/test/Makefile.am b/test/Makefile.am
index a3a6294..594aa0d 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,4 +1,6 @@
# Rules for the test code (use `make check` to execute)
+SUBDIRS = dgreftest
+
include $(top_srcdir)/src/Makefile.am.drumgizmo
TESTS = resource engine gui resampler lv2 configfile audiocache \
diff --git a/test/dgreftest/Makefile.am b/test/dgreftest/Makefile.am
new file mode 100644
index 0000000..cacf26a
--- /dev/null
+++ b/test/dgreftest/Makefile.am
@@ -0,0 +1,36 @@
+if ENABLE_CLI
+if HAVE_INPUT_MIDIFILE
+
+include $(top_srcdir)/src/Makefile.am.drumgizmo
+
+bin_PROGRAMS = dgreftest
+
+dgreftest_LDADD = $(DRUMGIZMO_LIBS) $(PTHREAD_LIBS) -ldl $(JACK_LIBS) \
+ $(SMF_LIBS)
+
+dgreftest_LDFLAGS =
+
+dgreftest_CXXFLAGS = $(SNDFILE_CXXFLAGS) $(PTHREAD_CFLAGS) $(EXPAT_CFLAGS) \
+ -I$(top_srcdir)/include -I$(top_srcdir)/src \
+ -I$(top_srcdir)/hugin -DWITH_HUG_MUTEX -DWITH_HUG_FILTER \
+ $(JACK_CFLAGS) $(SSEFLAGS) $(SMF_CFLAGS)
+
+dgreftest_CFLAGS = -DWITH_HUG_MUTEX -DWITH_HUG_FILTER
+
+dgreftest_SOURCES = \
+ dgreftest.cc \
+ midiinputengine.cc \
+ wavfileoutputengine.cc \
+ compareoutputengine.cc \
+ $(DRUMGIZMO_SOURCES) \
+ $(top_srcdir)/hugin/hugin.c \
+ $(top_srcdir)/hugin/hugin_filter.c
+
+endif # HAVE_INPUT_MIDIFILE
+
+EXTRA_DIST = \
+ midiinputengine.h \
+ wavfileoutputengine.h \
+ compareoutputengine.h
+
+endif # ENABLE_CLI
diff --git a/test/dgreftest/compareoutputengine.cc b/test/dgreftest/compareoutputengine.cc
new file mode 100644
index 0000000..4b13566
--- /dev/null
+++ b/test/dgreftest/compareoutputengine.cc
@@ -0,0 +1,138 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * compareoutputengine.cc
+ *
+ * Sat May 14 13:27:04 CEST 2016
+ * Copyright 2016 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "compareoutputengine.h"
+
+#include <iostream>
+
+CompareOutputEngine::CompareOutputEngine()
+ : AudioOutputEngine{}
+ , info{}
+ , file{"output"}
+{
+ info.samplerate = 44100;
+ info.channels = 1;
+ info.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT;
+}
+
+CompareOutputEngine::~CompareOutputEngine()
+{
+ std::cout << "diff_samples: " << diff_samples << std::endl;
+ sf_close(handle);
+}
+
+bool CompareOutputEngine::init(const Channels& data)
+{
+ info.channels = data.size();
+
+ handle = sf_open(file.c_str(), SFM_READ, &info);
+ if(handle == nullptr)
+ {
+ std::cerr << "[CompareOutputEngine] Failed to open "
+ << file << " for writing.\n";
+ return false;
+ }
+
+ return true;
+}
+
+void CompareOutputEngine::setParm(const std::string& parm, const std::string& value)
+{
+ if(parm == "file")
+ {
+ // apply output filename prefix
+ file = value;
+ }
+ else if(parm == "srate")
+ {
+ // try to apply samplerate
+ try
+ {
+ info.samplerate = std::stoi(value);
+ }
+ catch(...)
+ {
+ std::cerr << "[CompareOutputEngine] Invalid samplerate " << value
+ << "\n";
+ }
+ }
+ else
+ {
+ std::cerr << "[CompareOutputEngine] Unsupported parameter '" << parm
+ << "'\n";
+ }
+}
+
+bool CompareOutputEngine::start()
+{
+ return true;
+}
+
+void CompareOutputEngine::stop()
+{
+}
+
+void CompareOutputEngine::pre(size_t nsamples)
+{
+}
+
+void CompareOutputEngine::run(int ch, sample_t* samples, size_t nsamples)
+{
+ if(ch >= info.channels)
+ {
+ std::cerr << "[CompareOutputEngine] cannot access channel #" << ch
+ << " (" << info.channels << " channels available)\n";
+ return;
+ }
+
+ for(std::size_t i = 0; i < nsamples; ++i)
+ {
+ buffer[i * info.channels + ch] = samples[i];
+ }
+}
+
+void CompareOutputEngine::post(size_t nsamples)
+{
+ sample_t ref_buffer[sizeof(buffer) / sizeof(sample_t)];
+ sf_readf_float(handle, ref_buffer, nsamples);
+
+ for(std::size_t i = 0; i < nsamples; ++i)
+ {
+ for(std::size_t ch = 0; ch < (std::size_t)info.channels; ++ch)
+ {
+ if(buffer[i * info.channels + ch] != ref_buffer[i * info.channels + ch])
+ {
+ ++diff_samples;
+ }
+ }
+ }
+
+}
+
+size_t CompareOutputEngine::getSamplerate() const
+{
+ return info.samplerate;
+}
diff --git a/test/dgreftest/compareoutputengine.h b/test/dgreftest/compareoutputengine.h
new file mode 100644
index 0000000..fb610d6
--- /dev/null
+++ b/test/dgreftest/compareoutputengine.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * compareoutputengine.h
+ *
+ * Sat May 14 13:27:04 CEST 2016
+ * Copyright 2016 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#pragma once
+
+#include <sndfile.h>
+#include <audiooutputengine.h>
+
+class CompareOutputEngine
+ : public AudioOutputEngine
+{
+public:
+ CompareOutputEngine();
+ ~CompareOutputEngine();
+
+ // based on AudioOutputEngine
+ bool init(const Channels& data) override;
+ void setParm(const std::string& parm, const std::string& value) override;
+ bool start() override;
+ void stop() override;
+ void pre(size_t nsamples) override;
+ void run(int ch, sample_t* samples, size_t nsamples) override;
+ void post(size_t nsamples) override;
+ size_t getSamplerate() const override;
+
+private:
+ SF_INFO info;
+ SNDFILE* handle;
+ std::string file;
+ sample_t buffer[4096 * 16];
+ std::size_t diff_samples{0};
+};
diff --git a/test/dgreftest/dgreftest.cc b/test/dgreftest/dgreftest.cc
new file mode 100644
index 0000000..072dcdc
--- /dev/null
+++ b/test/dgreftest/dgreftest.cc
@@ -0,0 +1,136 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * dgreftest.cc
+ *
+ * Thu May 12 17:50:08 CEST 2016
+ * Copyright 2016 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include <drumgizmo.h>
+
+#include <string>
+#include <iostream>
+#include <cassert>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "compareoutputengine.h"
+#include "midiinputengine.h"
+#include "wavfileoutputengine.h"
+
+#include <cpp11fix.h> // required for c++11
+
+std::unique_ptr<AudioOutputEngine> createOutput(const std::string& name)
+{
+ struct stat sb;
+ if((stat(name.c_str(), &sb) == -1) && (errno == ENOENT))
+ {
+ // Ref file doesn't exist - create it.
+ return std::make_unique<WavfileOutputEngine>();
+ }
+ else
+ {
+ // Ref file exists, do compare.
+ return std::make_unique<CompareOutputEngine>();
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ if(argc < 4)
+ {
+ std::cerr << "Usage: " << argv[0] << " testname drumkit midimap [seed]" << std::endl;
+ return 1;
+ }
+
+ Settings settings;
+
+ std::string test = argv[1];
+ std::string kitfile = argv[2];
+ std::string midimap = argv[3];
+
+ unsigned int seed = 0;
+ if(argc == 5)
+ {
+ seed = atoi(argv[4]);
+ }
+
+ std::string midifile = test + ".mid";
+ std::string reffile = test + ".wav";
+
+ MidifileInputEngine ie;
+ ie.setParm("file", midifile.c_str());
+
+ auto oe = createOutput(reffile);
+
+ oe->setParm("file", reffile.c_str());
+ oe->setParm("srate", "44100");
+
+ DrumGizmo drumgizmo(settings, oe.get(), &ie);
+ drumgizmo.setRandomSeed(seed);
+ drumgizmo.setFreeWheel(true); // Run in-sync with disk-cache
+ drumgizmo.setFrameSize(oe->getBufferSize());
+
+// settings.enable_resampling.store(false); // Bypass resampler - BROKEN
+
+ settings.drumkit_file.store(kitfile);
+ settings.midimap_file.store(midimap);
+
+ printf("Loading drumkit, this may take a while:\n");
+
+ while(settings.drumkit_load_status.load() != LoadStatus::Done)
+ {
+ usleep(10000);
+
+ int total = settings.number_of_files.load();
+ int loaded = settings.number_of_files_loaded.load();
+
+ printf("\r%d of %d ", loaded, total);
+ fflush(stdout);
+
+ if(settings.drumkit_load_status.load() == LoadStatus::Error)
+ {
+ printf("\nFailed to load \"%s\".\n", kitfile.c_str());
+ return 1;
+ }
+
+ if(loaded == total)
+ {
+ //break;
+ }
+ }
+ printf("\ndone\n");
+
+ drumgizmo.setSamplerate(oe->getSamplerate());
+
+
+ if(!drumgizmo.init())
+ {
+ printf("Failed init engine.\n");
+ return 1;
+ }
+
+ drumgizmo.run(-1);
+
+ return 0;
+}
diff --git a/test/dgreftest/midiinputengine.cc b/test/dgreftest/midiinputengine.cc
new file mode 100644
index 0000000..bc0fa87
--- /dev/null
+++ b/test/dgreftest/midiinputengine.cc
@@ -0,0 +1,192 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * midiinputengine.cc
+ *
+ * Sat May 14 13:26:23 CEST 2016
+ * Copyright 2016 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "midiinputengine.h"
+
+#include <iostream>
+
+static int const NOTE_ON = 0x90;
+
+MidifileInputEngine::MidifileInputEngine()
+ : AudioInputEngineMidi{}
+ , smf{nullptr}
+ , current_event{nullptr}
+ , file{}
+ , speed{1.f}
+ , track{-1} // all tracks
+ , loop{false}
+ , offset{0.0}
+ , samplerate{44100.0} // todo: via ctor arg
+{
+}
+
+MidifileInputEngine::~MidifileInputEngine()
+{
+ if(smf != nullptr)
+ {
+ smf_delete(smf);
+ }
+}
+
+bool MidifileInputEngine::init(const Instruments& instruments)
+{
+ if(file == "")
+ {
+ std::cerr << "[MidifileInputEngine] Missing midi filename\n";
+ return false;
+ }
+ //if(midimap_filename == "")
+ //{
+ // std::cerr << "[MidifileInputEngine] Missing midimap filename\n";
+ // return false;
+ //}
+ smf = smf_load(file.c_str());
+ if(smf == nullptr)
+ {
+ std::cerr << "[MidifileInputEngine] Failed to load midifile '" << file
+ << "'\n";
+ return false;
+ }
+ //if(!loadMidiMap(midimap_filename, instruments))
+ //{
+ // std::cerr << "[MidifileInputEngine] Failed to parse midimap '"
+ // << midimap_filename << "'\n";
+ // return false;
+ //}
+
+ return true;
+}
+
+void MidifileInputEngine::setParm(const std::string& parm, const std::string& value)
+{
+ if(parm == "file")
+ {
+ // apply midi input filename
+ file = value;
+ }
+ else if(parm == "speed")
+ {
+ // try to apply speed
+ try
+ {
+ speed = std::stof(value);
+ }
+ catch(...)
+ {
+ std::cerr << "[MidifileInputEngine] Invalid speed " << value
+ << "\n";
+ }
+ }
+ //else if(parm == "midimap")
+ //{
+ // // apply midimap filename
+ // midimap_filename = value;
+ //}
+ else if(parm == "loop")
+ {
+ // apply looping
+ loop = true;
+ }
+ else
+ {
+ std::cerr << "[MidifileInputEngine] Unsupported parameter '" << parm
+ << "'\n";
+ }
+}
+
+bool MidifileInputEngine::start()
+{
+ return true;
+}
+
+void MidifileInputEngine::stop()
+{
+}
+
+void MidifileInputEngine::pre()
+{
+}
+
+void MidifileInputEngine::run(size_t pos, size_t len, std::vector<event_t>& events)
+{
+ assert(events.empty());
+
+ double current_max_time = (1.0 + pos + len) / (samplerate / speed);
+ current_max_time -= offset;
+
+ if(!current_event)
+ {
+ current_event = smf_get_next_event(smf);
+ }
+
+ while(current_event && current_event->time_seconds < current_max_time)
+ {
+ if(!smf_event_is_metadata(current_event))
+ {
+ if((current_event->midi_buffer_length == 3) &&
+ ((current_event->midi_buffer[0] & NOTE_ON) == NOTE_ON) &&
+ (track == -1 || current_event->track_number == track) &&
+ current_event->midi_buffer[2] > 0)
+ {
+ int key = current_event->midi_buffer[1];
+ int velocity = current_event->midi_buffer[2];
+
+ events.emplace_back();
+ auto& event = events.back();
+ event.type = TYPE_ONSET;
+ size_t evpos = current_event->time_seconds * (samplerate / speed);
+ event.offset = evpos - pos;
+
+ int i = mmap.lookup(key);
+ if(i != -1)
+ {
+ event.instrument = i;
+ event.velocity = velocity / 127.0;
+ }
+ }
+ }
+
+ current_event = smf_get_next_event(smf);
+ }
+
+ if(!current_event)
+ {
+ if(loop)
+ {
+ smf_rewind(smf);
+ offset += current_max_time;
+ }
+ else
+ {
+ assert(len >= 1);
+ events.push_back({TYPE_STOP, 0, len-1, 0.f});
+ }
+ }
+}
+
+void MidifileInputEngine::post()
+{
+}
diff --git a/test/dgreftest/midiinputengine.h b/test/dgreftest/midiinputengine.h
new file mode 100644
index 0000000..3740d44
--- /dev/null
+++ b/test/dgreftest/midiinputengine.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * midiinputengine.h
+ *
+ * Sat May 14 13:26:22 CEST 2016
+ * Copyright 2016 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#pragma once
+
+#include <audioinputenginemidi.h>
+#include <midimapper.h>
+#include <midimapparser.h>
+#include <string>
+#include <vector>
+
+#include <event.h>
+#include <smf.h>
+
+class MidifileInputEngine
+ : public AudioInputEngineMidi
+{
+public:
+ MidifileInputEngine();
+ ~MidifileInputEngine();
+
+ // based on AudioInputEngineMidi
+ bool init(const Instruments& instruments) override;
+ void setParm(const std::string& parm, const std::string& value) override;
+ bool start() override;
+ void stop() override;
+ void pre() override;
+ void run(size_t pos, size_t len, std::vector<event_t>& events) override;
+ void post() override;
+
+private:
+ smf_t* smf;
+ smf_event_t* current_event;
+
+ std::string midimap_filename;
+ std::string file;
+ float speed;
+ int track;
+ bool loop;
+ double offset, samplerate;
+};
diff --git a/test/dgreftest/wavfileoutputengine.cc b/test/dgreftest/wavfileoutputengine.cc
new file mode 100644
index 0000000..6f971ad
--- /dev/null
+++ b/test/dgreftest/wavfileoutputengine.cc
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * wavfileoutputengine.cc
+ *
+ * Sat May 14 13:26:51 CEST 2016
+ * Copyright 2016 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "wavfileoutputengine.h"
+
+#include <iostream>
+
+WavfileOutputEngine::WavfileOutputEngine()
+ : AudioOutputEngine{}
+ , info{}
+ , file{"output"}
+{
+ info.samplerate = 44100;
+ info.channels = 1;
+ info.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT;
+}
+
+WavfileOutputEngine::~WavfileOutputEngine()
+{
+ sf_close(handle);
+}
+
+bool WavfileOutputEngine::init(const Channels& data)
+{
+ info.channels = data.size();
+
+ handle = sf_open(file.c_str(), SFM_WRITE, &info);
+ if(handle == nullptr)
+ {
+ std::cerr << "[WavfileOutputEngine] Failed to open "
+ << file << " for writing.\n";
+ return false;
+ }
+
+ return true;
+}
+
+void WavfileOutputEngine::setParm(const std::string& parm, const std::string& value)
+{
+ if(parm == "file")
+ {
+ // apply output filename prefix
+ file = value;
+ }
+ else if(parm == "srate")
+ {
+ // try to apply samplerate
+ try
+ {
+ info.samplerate = std::stoi(value);
+ }
+ catch(...)
+ {
+ std::cerr << "[WavfileOutputEngine] Invalid samplerate " << value
+ << "\n";
+ }
+ }
+ else
+ {
+ std::cerr << "[WavfileOutputEngine] Unsupported parameter '" << parm
+ << "'\n";
+ }
+}
+
+bool WavfileOutputEngine::start()
+{
+ return true;
+}
+
+void WavfileOutputEngine::stop()
+{
+}
+
+void WavfileOutputEngine::pre(size_t nsamples)
+{
+}
+
+void WavfileOutputEngine::run(int ch, sample_t* samples, size_t nsamples)
+{
+ if(ch >= info.channels)
+ {
+ std::cerr << "[WavfileOutputEngine] cannot access channel #" << ch
+ << " (" << info.channels << " channels available)\n";
+ return;
+ }
+
+ for(std::size_t i = 0; i < nsamples; ++i)
+ {
+ buffer[i * info.channels + ch] = samples[i];
+ }
+}
+
+void WavfileOutputEngine::post(size_t nsamples)
+{
+
+ sf_writef_float(handle, buffer, nsamples);
+}
+
+size_t WavfileOutputEngine::getSamplerate() const
+{
+ return info.samplerate;
+}
diff --git a/test/dgreftest/wavfileoutputengine.h b/test/dgreftest/wavfileoutputengine.h
new file mode 100644
index 0000000..6937ed2
--- /dev/null
+++ b/test/dgreftest/wavfileoutputengine.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * wavfileoutputengine.h
+ *
+ * Sat May 14 13:26:51 CEST 2016
+ * Copyright 2016 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#pragma once
+
+#include <sndfile.h>
+#include <audiooutputengine.h>
+
+class WavfileOutputEngine
+ : public AudioOutputEngine
+{
+public:
+ WavfileOutputEngine();
+ ~WavfileOutputEngine();
+
+ // based on AudioOutputEngine
+ bool init(const Channels& data) override;
+ void setParm(const std::string& parm, const std::string& value) override;
+ bool start() override;
+ void stop() override;
+ void pre(size_t nsamples) override;
+ void run(int ch, sample_t* samples, size_t nsamples) override;
+ void post(size_t nsamples) override;
+ size_t getSamplerate() const override;
+
+private:
+ SF_INFO info;
+ SNDFILE* handle;
+ std::string file;
+ sample_t buffer[4096 * 16];
+};