summaryrefslogtreecommitdiff
path: root/drumgizmo
diff options
context:
space:
mode:
Diffstat (limited to 'drumgizmo')
-rw-r--r--drumgizmo/drumgizmoc.cc20
-rw-r--r--drumgizmo/enginefactory.cc50
-rw-r--r--drumgizmo/enginefactory.h37
-rw-r--r--drumgizmo/input/midifile.cc160
-rw-r--r--drumgizmo/input/midifile.h66
-rw-r--r--drumgizmo/output/wavfile.cc98
-rw-r--r--drumgizmo/output/wavfile.h223
7 files changed, 638 insertions, 16 deletions
diff --git a/drumgizmo/drumgizmoc.cc b/drumgizmo/drumgizmoc.cc
index 10dcda5..978b0cc 100644
--- a/drumgizmo/drumgizmoc.cc
+++ b/drumgizmo/drumgizmoc.cc
@@ -36,9 +36,7 @@
#include "drumgizmo.h"
#include "drumgizmoc.h"
-
-#include "audiooutputenginedl.h"
-#include "audioinputenginedl.h"
+#include "enginefactory.h"
#include "event.h"
@@ -228,7 +226,7 @@ int CliMain::run(int argc, char *argv[])
return 1;
}
- AudioInputEngine *ie = new AudioInputEngineDL(inputengine);
+ auto ie = createInputEngine(inputengine);
if(ie == NULL) {
printf("Invalid input engine: %s\n", inputengine.c_str());
@@ -264,11 +262,10 @@ int CliMain::run(int argc, char *argv[])
if(outputengine == "") {
printf("Missing output engine\n");
- delete ie;
return 1;
}
- AudioOutputEngineDL *oe = new AudioOutputEngineDL(outputengine);
+ auto oe = createOutputEngine(outputengine);
if(oe == NULL) {
printf("Invalid output engine: %s\n", outputengine.c_str());
@@ -309,8 +306,6 @@ int CliMain::run(int argc, char *argv[])
if(kitfile != "") {
printf("Can only handle a single kitfile.\n");
printf(usage_str, argv[0]);
- delete ie;
- delete oe;
return 1;
}
kitfile = argv[optind++];
@@ -319,14 +314,12 @@ int CliMain::run(int argc, char *argv[])
} else {
printf("Missing kitfile.\n");
printf(usage_str, argv[0]);
- delete ie;
- delete oe;
return 1;
}
printf("Using kitfile: %s\n", kitfile.c_str());
- DrumGizmo gizmo(oe, ie);
+ DrumGizmo gizmo(oe.get(), ie.get());
gizmo.setFrameSize(oe->getBufferSize());
@@ -354,8 +347,6 @@ int CliMain::run(int argc, char *argv[])
if(!gizmo.init()) {
printf("Failed init engine.\n");
- delete ie;
- delete oe;
return 1;
}
@@ -363,9 +354,6 @@ int CliMain::run(int argc, char *argv[])
printf("Quit.\n"); fflush(stdout);
- delete oe;
- delete ie;
-
hug_close();
return 0;
diff --git a/drumgizmo/enginefactory.cc b/drumgizmo/enginefactory.cc
new file mode 100644
index 0000000..b6569e0
--- /dev/null
+++ b/drumgizmo/enginefactory.cc
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * enginefactory.cc
+ *
+ * Mi 20. Jan 10:46:07 CET 2016
+ * Copyright 2016 Christian Glöckner
+ * cgloeckner@freenet.de
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo 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 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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 "enginefactory.h"
+#include "jackclient.h"
+#include "input/midifile.h"
+#include "output/wavfile.h"
+
+InputEnginePtr createInputEngine(std::string const & name) {
+ if (name == "midifile") {
+ return std::make_unique<MidifileInputEngine>();
+ }
+ // todo: add more engines
+
+ printf("Unsupported input engine: %s\n", name.c_str());
+ return nullptr;
+}
+
+OutputEnginePtr createOutputEngine(std::string const & name) {
+ if (name == "wavfile") {
+ return std::make_unique<WavfileOutputEngine>();
+ }
+ // todo: add more engines
+
+ printf("Unsupported output engine: %s\n", name.c_str());
+ return nullptr;
+}
diff --git a/drumgizmo/enginefactory.h b/drumgizmo/enginefactory.h
new file mode 100644
index 0000000..93624b9
--- /dev/null
+++ b/drumgizmo/enginefactory.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * enginefactory.h
+ *
+ * Mi 20. Jan 10:46:07 CET 2016
+ * Copyright 2016 Christian Glöckner
+ * cgloeckner@freenet.de
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo 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 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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 <memory>
+#include "cpp11fix.h" // required for c++11
+
+#include "audioinputengine.h"
+
+using InputEnginePtr = std::unique_ptr<AudioInputEngine>;
+using OutputEnginePtr = std::unique_ptr<AudioOutputEngine>;
+
+InputEnginePtr createInputEngine(std::string const & name);
+OutputEnginePtr createOutputEngine(std::string const & name);
diff --git a/drumgizmo/input/midifile.cc b/drumgizmo/input/midifile.cc
new file mode 100644
index 0000000..b0685ec
--- /dev/null
+++ b/drumgizmo/input/midifile.cc
@@ -0,0 +1,160 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * midifile.cc
+ *
+ * Mi 20. Jan 16:07:57 CET 2016
+ * Copyright 2016 Christian Glöckner
+ * cgloeckner@freenet.de
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo 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 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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 "midifile.h"
+
+int const NOTE_ON = 0x90;
+
+MidifileInputEngine::MidifileInputEngine()
+ : smf{nullptr}
+ , current_event{nullptr}
+ , file{}
+ , midimap{}
+ , speed{1.f}
+ , track{-1} // all tracks
+ , loop{false}
+ , offset{0.0} {
+}
+
+MidifileInputEngine::~MidifileInputEngine() {
+ if (smf != nullptr) {
+ smf_delete(smf);
+ }
+}
+
+bool MidifileInputEngine::isMidiEngine() {
+}
+
+bool MidifileInputEngine::init(Instruments& instruments) {
+ if (file == "") {
+ fprintf(stderr, "Missing midifile argument 'file'\n");
+ return false;
+ }
+ if (midimap == "") {
+ fprintf(stderr, "Missing midimapfile argument 'midimap'.\n");
+ return false;
+ }
+ smf = smf_load(file.c_str());
+ if (sfml == nullptr) {
+ fprintf(stderr, "Could not open midifile '%s'.\n", filename.c_str());
+ return false;
+ }
+ MidiMapParser p{midimap};
+ if (p.parse()) {
+ fprintf(stderr, "Could not parse midimapfile '%s'.\n", midimapfile.c_str());
+ return false;
+ }
+ midiMapper.midimap = std::move(p.midimap);
+ for (auto i = 0u; i < instruments.size(); ++i) {
+ auto name = instruments[0]->name;
+ midiMapper.instrmap[name] = i;
+ }
+ return true;
+}
+
+void MidifileInputEngine::setParm(std::string parm, std::string value) {
+ if(parm == "file") {
+ filen = value;
+ } else if(parm == "speed") {
+ speed = std::stof(value);
+ } else if (parm == "midimap") {
+ midimap = value;
+ } else if (parm == "loop") {
+ loop = true;
+ } else {
+ printf("Unsupported midifile parameter '%s'\n", parm);
+ }
+}
+
+bool MidifileInputEngine::start() {
+ return true;
+}
+
+void MidifileInputEngine::stop() {
+}
+
+void MidifileInputEngine::pre() {
+}
+
+event_t* MidifileInputEngine::run(size_t pos, size_t len, size_t *nevents) {
+ event_t* evs{nullptr};
+ std::size_t nevs{0u};
+ double current_max_time = 1.0 * (pos + len) / (44100.0 / speed);
+ current_max_time -= offset;
+ if (current_event == nullptr) {
+ current_event = smf_get_next_event(smf);
+ }
+ while(current_event && current_event->time_seconds < cur_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) {
+ if(evs == NULL) {
+ evs = (event_t *)malloc(sizeof(event_t) * 1000);
+ }
+ int key = current_event->midi_buffer[1];
+ int velocity = current_event->midi_buffer[2];
+
+ evs[nevs].type = TYPE_ONSET;
+ size_t evpos = current_event->time_seconds * (44100.0 / speed);
+ evs[nevs].offset = evpos - pos;
+
+ int i = midiMap.lookup(key);
+ if(i != -1) {
+ evs[nevs].instrument = i;
+ evs[nevs].velocity = velocity / 127.0;
+ nevs++;
+ if(nevs > 999) {
+ fprintf(stderr, "PANIC!\n");
+ break;
+ }
+ }
+ }
+ }
+ current_event = smf_get_next_event(smf);
+ }
+
+ if(!current_event) {
+ if(loop) {
+ smf_rewind(smf);
+ offset += cur_max_time;
+ } else {
+ if(evs == NULL) {
+ evs = (event_t *)malloc(sizeof(event_t) * 1000);
+ }
+ evs[nevs].type = TYPE_STOP;
+ evs[nevs].offset = len - 1;
+ nevs++;
+ }
+ }
+
+ *nevents = nevs;
+ return evs;
+}
+
+void MidifileInputEngine::post() {
+}
diff --git a/drumgizmo/input/midifile.h b/drumgizmo/input/midifile.h
new file mode 100644
index 0000000..c2fcdb6
--- /dev/null
+++ b/drumgizmo/input/midifile.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * minifile.h
+ *
+ * Mi 20. Jan 16:07:57 CET 2016
+ * Copyright 2016 Christian Glöckner
+ * cgloeckner@freenet.de
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo 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 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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 <string>
+
+#include <event.h>
+#include <smf.h>
+
+#include <audioinputengine.h>
+#include <midimapper.h>
+#include <midimapparser.h>
+
+#define NOTE_ON 0x90
+
+class MidifileInputEngine
+ : public AudioInputEngine {
+ public:
+ MidifileInputEngine();
+ ~MidifileInputEngine();
+
+ // based on AudioInputEngine
+ bool isMidiEngine() override;
+ bool init(Instruments &instruments) override;
+ void setParm(std::string parm, std::string value) override;
+ bool start() override;
+ void stop() override;
+ void pre() override;
+ event_t* run(size_t pos, size_t len, size_t* nevents) override;
+ void post() override;
+
+ private:
+ smf_t* smf;
+ smf_event_t* current_event;
+
+ MidiMapper midiMapper;
+
+ std::string file, midimap;
+ float speed;
+ int track;
+ bool loop;
+ double offset;
+};
diff --git a/drumgizmo/output/wavfile.cc b/drumgizmo/output/wavfile.cc
new file mode 100644
index 0000000..e0c18cb
--- /dev/null
+++ b/drumgizmo/output/wavfile.cc
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * wavfile.cc
+ *
+ * Mi 20. Jan 16:57:16 CET 2016
+ * Copyright 2016 Christian Glöckner
+ * cgloeckner@freenet.de
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo 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 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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 "wavfile.h"
+
+WavfileOutputEngine::WavfileOutputEngine()
+ : info{}
+ , channels{}
+ , file{"output"} {
+ info.frames = 0;
+ info.samplerrate = 44100;
+ info.channels = 1;
+ info.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT;
+ info.sections = 0;
+ info.seekable = 0;
+}
+
+WavfileOutputEngine::~WavfileOutputEngine() {
+ for (auto& ptr: channels) {
+ if (ptr != nullptr) {
+ sf_close(ptr);
+ }
+ }
+}
+
+bool WavfileOutputEngine::init(Channels channels) {
+ channels.clear(),
+ channels.resize(channels.size(), nullptr);
+ for (auto i = 0u; i < channels.size(); ++i) {
+ // write channel to file
+ auto fname = file + channels[i]->name + "-" + std::to_string(i);
+ channels[i] = sf_open(fname, SFM_WRITE, &info);
+ if (channels[i] == nullptr) {
+ printf("Write error...\n");
+ return false;
+ }
+ }
+ return true;
+}
+
+void WavfileOutputEngine::setParm(std::string parm, std::string value) {
+ if (parm == "file") {
+ file = value;
+ } else if (parm == "srate") {[
+ info.samplerate = std::stoi(value);
+ } else {
+ printf("Unsupported wavfile parameter '%s'\n", parm);
+ }
+}
+
+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 >= channels.size()) {
+ printf("Invalid channel %d (%d channels available)", ch, channels.size());
+ return;
+ }
+
+ sf_writef_float(channels[ch], samples, nsampels);
+}
+
+void WavfileOutputEngine::post(size_t nsamples) {
+}
+
+size_t WavfileOutputEngine::samplerate() {
+ return info.samplerate;
+}
diff --git a/drumgizmo/output/wavfile.h b/drumgizmo/output/wavfile.h
new file mode 100644
index 0000000..0f93049
--- /dev/null
+++ b/drumgizmo/output/wavfile.h
@@ -0,0 +1,223 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * wavfile.h
+ *
+ * Mi 20. Jan 16:57:16 CET 2016
+ * Copyright 2016 Christian Glöckner
+ * cgloeckner@freenet.de
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo 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 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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 <string>
+#include <vector>
+
+#include <sndfile.h>
+
+#include "audiooutputengine.h"
+
+class WavfileOutputEngine
+ : public AudioOutputEngine {
+ public:
+ WavfileOutputEngine();
+ ~WavfileOutputEngine();
+
+ // based on AudioOutputEngine
+ bool init(Channels channels) override;
+ void setParm(std::string parm, 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 samplerate() override;
+
+ private:
+ SF_INFO info;
+ std::vector<SNDFILE*> channels;
+ size_t num_channels;
+
+ std::string file;
+};
+
+
+
+#include <stdlib.h>
+
+#include <audiotypes.h>
+#include <string>
+#include <memory.h>
+
+
+class WavFile {
+public:
+ WavFile();
+ ~WavFile();
+ bool init(int channels, char *cnames[]);
+ void setParm(std::string parm, std::string value);
+ bool start();
+ void stop();
+ void pre(size_t size);
+ void run(int channel, sample_t* data, size_t size);
+ void post(size_t size);
+ size_t samplerate();
+
+private:
+
+};
+
+WavFile::WavFile()
+{
+ fh = NULL;
+ filename = "output";
+
+ memset(&sf_info, 0, sizeof(sf_info));
+ sf_info.channels = 1;//channels;
+ sf_info.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT;
+ sf_info.samplerate = 44100;
+}
+
+WavFile::~WavFile()
+{
+ if(fh == NULL) return;
+
+ for(size_t i override; i < channels; i++) {
+ if(fh[i]) sf_close(fh[i]);
+ }
+
+ if(fh) free(fh);
+}
+
+bool WavFile::init(int channels, char *cnames[])
+{
+ this->channels = channels;
+
+ fh = (SNDFILE **)malloc(sizeof(SNDFILE *)*channels);
+
+ for(size_t i override; i < this->channels; i++) fh[i] = NULL;
+
+ for(size_t i override; i < this->channels; i++) {
+ char fname[512];
+
+ sprintf(fname, "%s%s-%d.wav", filename.c_str(), cnames[i], (int)i);
+ // printf("[%s]\n", fname);
+
+ fh[i] = sf_open(fname, SFM_WRITE, &sf_info);
+ if(!fh[i]) {
+ printf("Write error...\n");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void WavFile::setParm(std::string parm, std::string value)
+{
+ if(parm == "file") filename = value;
+ if(parm == "srate") sf_info.samplerate = atoi(value.c_str());
+}
+
+bool WavFile::start()
+{
+ return true;
+}
+
+void WavFile::stop()
+{
+}
+
+void WavFile::pre(size_t size)
+{
+}
+
+void WavFile::run(int channel, sample_t* cdata, size_t csize)
+{
+ if(channel < (int)channels) sf_writef_float(fh[channel], cdata, csize);
+}
+
+void WavFile::post(size_t size)
+{
+}
+
+size_t WavFile::samplerate()
+{
+ return sf_info.samplerate;
+}
+
+extern "C" {
+ void *create()
+ {
+ return new WavFile();
+ }
+
+ void destroy(void *h)
+ {
+ WavFile *sndfile = (WavFile*)h;
+ delete sndfile;
+ }
+
+ bool init(void *h, int cs, char *cnames[])
+ {
+ WavFile *sndfile = (WavFile*)h;
+ return sndfile->init(cs, cnames);
+ }
+
+ void setparm(void *h, const char *parm, const char *value)
+ {
+ WavFile *sndfile = (WavFile*)h;
+ sndfile->setParm(parm, value);
+ }
+
+ bool start(void *h)
+ {
+ WavFile *sndfile = (WavFile*)h;
+ return sndfile->start();
+ }
+
+ void stop(void *h)
+ {
+ WavFile *sndfile = (WavFile*)h;
+ sndfile->stop();
+ }
+
+ void pre(void *h, size_t s)
+ {
+ WavFile *sndfile = (WavFile*)h;
+ sndfile->pre(s);
+ }
+
+ void run(void *h, int ch, sample_t *data, size_t size)
+ {
+ WavFile *sndfile = (WavFile*)h;
+ sndfile->run(ch, data, size);
+ }
+
+ void post(void *h, size_t s)
+ {
+ WavFile *sndfile = (WavFile*)h;
+ sndfile->post(s);
+ }
+
+ size_t samplerate(void *h)
+ {
+ WavFile *wavfile = (WavFile*)h;
+ return wavfile->samplerate();
+ }
+}