summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordeva <deva>2011-03-01 19:19:02 +0000
committerdeva <deva>2011-03-01 19:19:02 +0000
commite190d38057892b69246391841b234a368bc2b4ad (patch)
tree34f946bc1c3b86997d4cd45e63c433ef07b36486
parentc393edc920f8ee126d1bced3500b6bc1ecf86f83 (diff)
MAJOR rewrite of the internals. New input/output 'plugin' system. Still a lot missing.
-rw-r--r--src/Makefile.am47
-rw-r--r--src/audio.h40
-rw-r--r--src/audiofile.cc61
-rw-r--r--src/audiofile.h9
-rw-r--r--src/audioinputengine.cc57
-rw-r--r--src/audioinputengine.h46
-rw-r--r--src/audioinputenginejackmidi.cc116
-rw-r--r--src/audioinputenginejackmidi.h55
-rw-r--r--src/audioinputenginemidifile.cc44
-rw-r--r--src/audioinputenginemidifile.h41
-rw-r--r--src/audiooutputengine.cc42
-rw-r--r--src/audiooutputengine.h51
-rw-r--r--src/audiooutputenginealsa.cc194
-rw-r--r--src/audiooutputenginealsa.h51
-rw-r--r--src/audiooutputenginejack.cc106
-rw-r--r--src/audiooutputenginejack.h59
-rw-r--r--src/audiooutputenginesndfile.cc84
-rw-r--r--src/audiooutputenginesndfile.h51
-rw-r--r--src/beatmapper.cc2
-rw-r--r--src/channel.cc26
-rw-r--r--src/channel.h12
-rw-r--r--src/channelmixer.cc110
-rw-r--r--src/channelmixer.h58
-rw-r--r--src/cli.cc189
-rw-r--r--src/cli.h29
-rw-r--r--src/drumgizmo.cc295
-rw-r--r--src/drumgizmo.h85
-rw-r--r--src/drumkit.h13
-rw-r--r--src/drumkitparser.cc78
-rw-r--r--src/drumkitparser.h16
-rw-r--r--src/event.cc28
-rw-r--r--src/event.h99
-rw-r--r--src/instrument.cc59
-rw-r--r--src/instrument.h59
-rw-r--r--src/midi.h33
-rw-r--r--src/midimap.h43
-rw-r--r--src/midimapper.cc11
-rw-r--r--src/midiplayer.cc2
-rw-r--r--src/mutex.cc125
-rw-r--r--src/mutex.h55
-rw-r--r--src/rangemap.h91
-rw-r--r--src/sample.cc32
-rw-r--r--src/sample.h20
-rw-r--r--src/saxparser.cc11
-rw-r--r--src/saxparser.h3
-rw-r--r--src/thread.cc53
-rw-r--r--src/thread.h48
47 files changed, 2541 insertions, 298 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 5ec0802..df904db 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,35 +1,70 @@
bin_PROGRAMS = drumgizmo
-drumgizmo_LDADD = $(JACK_LIBS) $(SNDFILE_LIBS) $(SMF_LIBS)
+drumgizmo_LDADD = $(ALSA_LIBS) $(JACK_LIBS) $(SNDFILE_LIBS) $(SMF_LIBS) \
+ $(PTHREAD_CFLAGS)
-drumgizmo_CXXFLAGS = $(JACK_CXXFLAGS) $(SNDFILE_CXXFLAGS) $(SMF_CFLAGS)
+drumgizmo_CXXFLAGS = $(ALSA_CFLAGS) $(JACK_CXXFLAGS) $(SNDFILE_CXXFLAGS) \
+ $(SMF_CFLAGS) $(PTHREAD_LIBS)
drumgizmo_SOURCES = \
+ audioinputengine.cc \
+ audioinputenginejackmidi.cc \
+ audiooutputengine.cc \
+ audiooutputenginealsa.cc \
+ audiooutputenginejack.cc \
+ audiooutputenginesndfile.cc \
audiofile.cc \
- beatmapper.cc \
+ cli.cc \
channel.cc \
+ channelmixer.cc \
drumgizmo.cc \
drumkitparser.cc \
event.cc \
instrument.cc \
- jackclient.cc \
midimapper.cc \
midiplayer.cc \
+ mutex.cc \
sample.cc \
saxparser.cc \
+ thread.cc \
velocity.cc
+# beatmapper.cc
+
EXTRA_DIST = \
+ audio.h \
+ audioinputengine.h \
+ audioinputenginejackmidi.h \
+ audiooutputengine.h \
+ audiooutputenginealsa.h \
+ audiooutputenginejack.h \
+ audiooutputenginesndfile.h \
audiofile.h \
- beatmapper.h \
channel.h \
+ channelmixer.h \
+ drumgizmo.h \
drumkit.h \
drumkitparser.h \
event.h \
instrument.h \
- jackclient.h \
midimapper.h \
midiplayer.h \
+ mutex.h \
+ rangemap.h \
sample.h \
saxparser.h \
+ thread.h \
velocity.h
+
+# beatmapper.h
+
+################
+# Test Section #
+################
+
+TEST_SOURCE_DEPS = ${drumgizmo_SOURCES} ${EXTRA_DIST}
+TEST_SCRIPT_DIR = $(top_srcdir)/tools
+
+include ${TEST_SCRIPT_DIR}/Makefile.am.test
+
+include Makefile.am.test \ No newline at end of file
diff --git a/src/audio.h b/src/audio.h
new file mode 100644
index 0000000..85a84a0
--- /dev/null
+++ b/src/audio.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * audio.h
+ *
+ * Thu Sep 16 20:15:45 CEST 2010
+ * Copyright 2010 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 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.
+ */
+#ifndef __DRUMGIZMO_AUDIO_H__
+#define __DRUMGIZMO_AUDIO_H__
+
+typedef unsigned int channels_t;
+typedef unsigned int channel_t;
+
+#define ALL_CHANNELS ((channel_t)0xffffffff)
+#define NO_CHANNEL ((channel_t)0xfffffffe)
+
+typedef float sample_t;
+
+typedef float level_t;
+
+#endif/*__DRUMGIZMO_AUDIO_H__*/
diff --git a/src/audiofile.cc b/src/audiofile.cc
index 9c00bed..2533b33 100644
--- a/src/audiofile.cc
+++ b/src/audiofile.cc
@@ -31,22 +31,12 @@
#include <sndfile.h>
-AudioFile::AudioFile(std::string filename, bool preload, int min_velocity)
+AudioFile::AudioFile(std::string filename)
{
this->filename = filename;
+
data = NULL;
size = 0;
-
- char *p = (char*)filename.c_str() + filename.length() - 6;
- int num = atoi(p);
- if(num < 0) num *= -1;
-
- //printf("%s", filename.c_str());
- if(preload && num >= min_velocity) {
- //printf(" ... loading");
- load();
- }
- printf("."); fflush(stdout);
}
AudioFile::~AudioFile()
@@ -56,40 +46,29 @@ AudioFile::~AudioFile()
void AudioFile::unload()
{
- if(!data) return;
-
- free(data);
- data = NULL;
- size = 0;
+ if(data) {
+ delete data;
+ data = NULL;
+ size = 0;
+ }
}
-#define THRESHOLD 0.0001
void AudioFile::load()
{
if(data) return;
- SF_INFO sf_info;
- SNDFILE *fh = sf_open(filename.c_str(), SFM_READ, &sf_info);
-
- size = sf_seek(fh, 0, SEEK_END);
- jack_default_audio_sample_t* tmp_data = (jack_default_audio_sample_t*)malloc(sizeof(jack_default_audio_sample_t)*size);
-
- // printf("Loading %s, %d samples\n", filename.c_str(), size);
-
- sf_seek(fh, 0, SEEK_SET);
- sf_read_float(fh, tmp_data, size);
-
- // for(size_t i = 0; i < size; i++) data[i] *= 0.1;
-
- sf_close(fh);
-
- // Find real size (crop 'silence')
- while(size > 0 && tmp_data[size--] < THRESHOLD) {}
- data = (jack_default_audio_sample_t*)malloc(sizeof(jack_default_audio_sample_t)*size);
- for(size_t i = 0; i < size; i++) data[i] = tmp_data[i];
- // ramp down
- // if(size > 1024) for(size_t i = 1024; i >= 0; i--) data[size - i] *= (float)i/1024.0;
- free(tmp_data);
-
+ SF_INFO sf_info;
+ SNDFILE *fh = sf_open(filename.c_str(), SFM_READ, &sf_info);
+ if(!fh) {
+ printf("Load error...\n");
+ return;
+ }
+
+ size = sf_info.frames;
+ data = new sample_t[size];
+
+ sf_read_float(fh, data, size);
+
+ sf_close(fh);
}
diff --git a/src/audiofile.h b/src/audiofile.h
index 879cc95..a3d607d 100644
--- a/src/audiofile.h
+++ b/src/audiofile.h
@@ -27,20 +27,21 @@
#ifndef __DRUMGIZMO_AUDIOFILE_H__
#define __DRUMGIZMO_AUDIOFILE_H__
-#include <jack/jack.h>
#include <string>
+#include <map>
+
+#include "audio.h"
class AudioFile {
public:
- AudioFile(std::string filename, bool preload = false, int min_velocity = 0);
+ AudioFile(std::string filename);
~AudioFile();
void load();
void unload();
- jack_default_audio_sample_t *data;
+ sample_t *data;
size_t size;
- std::string channel;
private:
std::string filename;
diff --git a/src/audioinputengine.cc b/src/audioinputengine.cc
new file mode 100644
index 0000000..201d851
--- /dev/null
+++ b/src/audioinputengine.cc
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * audioinputengine.cc
+ *
+ * Sun Feb 27 11:33:20 CET 2011
+ * Copyright 2011 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 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 "audioinputengine.h"
+
+#include "audioinputenginejackmidi.h"
+#include "audioinputenginemidifile.h"
+
+AudioInputEngine *createAudioInputEngine(std::string engine)
+{
+ AudioInputEngine *e = NULL;
+
+ if(engine == "jackmidi") e = new AudioInputEngineJackMidi();
+ if(engine == "midifile") e = new AudioInputEngineMidiFile();
+
+ return e;
+}
+
+#ifdef TEST_AUDIOINPUTENGINE
+//Additional dependency files
+//deps:
+//Required cflags (autoconf vars may be used)
+//cflags:
+//Required link options (autoconf vars may be used)
+//libs:
+#include "test.h"
+
+TEST_BEGIN;
+
+// TODO: Put some testcode here (see test.h for usable macros).
+
+TEST_END;
+
+#endif/*TEST_AUDIOINPUTENGINE*/
diff --git a/src/audioinputengine.h b/src/audioinputengine.h
new file mode 100644
index 0000000..d10a31c
--- /dev/null
+++ b/src/audioinputengine.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * audioinputengine.h
+ *
+ * Sun Feb 27 11:33:19 CET 2011
+ * Copyright 2011 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 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.
+ */
+#ifndef __DRUMGIZMO_AUDIOINPUTENGINE_H__
+#define __DRUMGIZMO_AUDIOINPUTENGINE_H__
+
+#include <string>
+
+#include "event.h"
+
+class AudioInputEngine {
+public:
+ AudioInputEngine() {}
+ virtual ~AudioInputEngine() {}
+
+ virtual bool init(EventQueue *e) = 0;
+
+ virtual void run(size_t pos, size_t len) = 0;
+};
+
+AudioInputEngine *createAudioInputEngine(std::string engine);
+
+#endif/*__DRUMGIZMO_AUDIOINPUTENGINE_H__*/
diff --git a/src/audioinputenginejackmidi.cc b/src/audioinputenginejackmidi.cc
new file mode 100644
index 0000000..49bfde4
--- /dev/null
+++ b/src/audioinputenginejackmidi.cc
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * audioinputenginejackmidi.cc
+ *
+ * Sun Feb 27 11:33:31 CET 2011
+ * Copyright 2011 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 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 "audioinputenginejackmidi.h"
+
+#define NOTE_ON 0x90
+
+extern "C" {
+ static int _wrap_jack_process(jack_nframes_t nframes, void *arg){
+ return ((AudioInputEngineJackMidi*)arg)->process(nframes);}
+}
+
+AudioInputEngineJackMidi::AudioInputEngineJackMidi()
+{
+ pos = 0;
+}
+
+AudioInputEngineJackMidi::~AudioInputEngineJackMidi()
+{
+ // wait_stop();
+ jack_client_close(jack_client);
+}
+
+int AudioInputEngineJackMidi::process(jack_nframes_t nframes)
+{
+ // printf(" jk: %d\n", pos);
+
+ void *midibuffer = jack_port_get_buffer(midi_port, nframes);
+
+ jack_nframes_t midievents = jack_midi_get_event_count(midibuffer);
+ // if(midievents) printf("#%d\n", midievents);
+ for(jack_nframes_t i = 0; i < midievents; i++) {
+ jack_midi_event_t event;
+ jack_midi_event_get(&event, midibuffer, i);
+
+
+ if(event.size != 3) continue;
+ if((event.buffer[0] & NOTE_ON) != NOTE_ON) continue;
+
+ int key = event.buffer[1];
+ int velocity = event.buffer[2];
+
+ //if(velocity == 0) continue;
+
+ printf("Event key:%d vel:%d\n", key, velocity);
+ Event *evt = new EventSine(0, key * 10, (float)velocity / 127.0, 1000);
+ eventqueue->post(evt, pos + event.time);
+ }
+
+ jack_midi_clear_buffer(midibuffer);
+
+ pos += nframes;
+
+ return 0;
+}
+
+bool AudioInputEngineJackMidi::init(EventQueue *e)
+{
+ eventqueue = e;
+
+ jack_status_t status;
+
+ jack_client = jack_client_open("DrumGizmo", JackNullOption, &status);
+
+ midi_port = jack_port_register(jack_client,
+ "drumgizmo_midiin",
+ JACK_DEFAULT_MIDI_TYPE,
+ JackPortIsInput,// | JackPortIsTerminal,
+ 0);
+
+ jack_set_process_callback(jack_client, _wrap_jack_process, this);
+
+ jack_activate(jack_client);
+
+ return true;
+}
+
+#ifdef TEST_AUDIOINPUTENGINEJACKMIDI
+//Additional dependency files
+//deps:
+//Required cflags (autoconf vars may be used)
+//cflags:
+//Required link options (autoconf vars may be used)
+//libs:
+#include "test.h"
+
+TEST_BEGIN;
+
+// TODO: Put some testcode here (see test.h for usable macros).
+
+TEST_END;
+
+#endif/*TEST_AUDIOINPUTENGINEJACKMIDI*/
diff --git a/src/audioinputenginejackmidi.h b/src/audioinputenginejackmidi.h
new file mode 100644
index 0000000..9807a40
--- /dev/null
+++ b/src/audioinputenginejackmidi.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * audioinputenginejackmidi.h
+ *
+ * Sun Feb 27 11:33:31 CET 2011
+ * Copyright 2011 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 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.
+ */
+#ifndef __DRUMGIZMO_AUDIOINPUTENGINEJACKMIDI_H__
+#define __DRUMGIZMO_AUDIOINPUTENGINEJACKMIDI_H__
+
+#include <jack/jack.h>
+#include <jack/midiport.h>
+
+#include "audioinputengine.h"
+#include "event.h"
+
+class AudioInputEngineJackMidi : public AudioInputEngine {
+public:
+ AudioInputEngineJackMidi();
+ ~AudioInputEngineJackMidi();
+
+ bool init(EventQueue *e);
+ void run(size_t pos, size_t len) {}
+
+ void thread_main();
+
+ int process(jack_nframes_t nframes);
+
+private:
+ size_t pos;
+ EventQueue *eventqueue;
+ jack_client_t *jack_client;
+ jack_port_t *midi_port;
+};
+
+#endif/*__DRUMGIZMO_AUDIOINPUTENGINEJACKMIDI_H__*/
diff --git a/src/audioinputenginemidifile.cc b/src/audioinputenginemidifile.cc
new file mode 100644
index 0000000..878ca1b
--- /dev/null
+++ b/src/audioinputenginemidifile.cc
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * audioinputenginemidifile.cc
+ *
+ * Sun Feb 27 11:43:32 CET 2011
+ * Copyright 2011 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 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 "audioinputenginemidifile.h"
+
+#ifdef TEST_AUDIOINPUTENGINEMIDIFILE
+//Additional dependency files
+//deps:
+//Required cflags (autoconf vars may be used)
+//cflags:
+//Required link options (autoconf vars may be used)
+//libs:
+#include "test.h"
+
+TEST_BEGIN;
+
+// TODO: Put some testcode here (see test.h for usable macros).
+
+TEST_END;
+
+#endif/*TEST_AUDIOINPUTENGINEMIDIFILE*/
diff --git a/src/audioinputenginemidifile.h b/src/audioinputenginemidifile.h
new file mode 100644
index 0000000..fbdeffa
--- /dev/null
+++ b/src/audioinputenginemidifile.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * audioinputenginemidifile.h
+ *
+ * Sun Feb 27 11:43:32 CET 2011
+ * Copyright 2011 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 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.
+ */
+#ifndef __DRUMGIZMO_AUDIOINPUTENGINEMIDIFILE_H__
+#define __DRUMGIZMO_AUDIOINPUTENGINEMIDIFILE_H__
+
+#include "audioinputengine.h"
+
+class AudioInputEngineMidiFile : public AudioInputEngine {
+public:
+ AudioInputEngineMidiFile() {}
+ ~AudioInputEngineMidiFile() {}
+
+ bool init(EventQueue *eventqueue) { return true; }
+ void run(size_t pos, size_t len) {}
+};
+
+#endif/*__DRUMGIZMO_AUDIOINPUTENGINEMIDIFILE_H__*/
diff --git a/src/audiooutputengine.cc b/src/audiooutputengine.cc
new file mode 100644
index 0000000..73ef355
--- /dev/null
+++ b/src/audiooutputengine.cc
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * audioooutputengine.cc
+ *
+ * Thu Sep 16 10:27:01 CEST 2010
+ * Copyright 2010 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 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 "audiooutputengine.h"
+
+#include "audiooutputenginealsa.h"
+#include "audiooutputenginejack.h"
+#include "audiooutputenginesndfile.h"
+
+AudioOutputEngine *createAudioOutputEngine(std::string engine)
+{
+ AudioOutputEngine *e = NULL;
+
+ if(engine == "alsa") e = new AudioOutputEngineAlsa();
+ if(engine == "jack") e = new AudioOutputEngineJack();
+ if(engine == "sndfile") e = new AudioOutputEngineSndFile("out.wav");
+
+ return e;
+}
diff --git a/src/audiooutputengine.h b/src/audiooutputengine.h
new file mode 100644
index 0000000..09dcbd7
--- /dev/null
+++ b/src/audiooutputengine.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * audiooutputengine.h
+ *
+ * Thu Sep 16 10:27:01 CEST 2010
+ * Copyright 2010 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 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.
+ */
+#ifndef __DRUMGIZMO_AUDIOOUTPUTENGINE_H__
+#define __DRUMGIZMO_AUDIOOUTPUTENGINE_H__
+
+#include <string>
+
+#include "channel.h"
+
+class DrumGizmo;
+
+class AudioOutputEngine {
+public:
+ AudioOutputEngine() {}
+ virtual ~AudioOutputEngine() {}
+
+ virtual bool init(Channels *channels) = 0;
+
+ virtual void run(DrumGizmo *drumgizmo) = 0;
+
+protected:
+ Channels *channels;
+};
+
+AudioOutputEngine *createAudioOutputEngine(std::string engine);
+
+#endif/*__DRUMGIZMO_AUDIOOUTPUTENGINE_H__*/
diff --git a/src/audiooutputenginealsa.cc b/src/audiooutputenginealsa.cc
new file mode 100644
index 0000000..635cf70
--- /dev/null
+++ b/src/audiooutputenginealsa.cc
@@ -0,0 +1,194 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * audiooutputenginealsa.cc
+ *
+ * Thu Sep 16 11:22:52 CEST 2010
+ * Copyright 2010 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 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 "audiooutputenginealsa.h"
+
+#include "drumgizmo.h"
+
+#include <string>
+#include <math.h>
+#include <sys/time.h>
+
+#define T(x, msg) if(x < 0) { printf("%s failed: %s\n", msg, snd_strerror(x)); fflush(stdout); return false; }
+#define T_(x, msg) if(x < 0) { printf("%s failed: %s\n", msg, snd_strerror(x)); fflush(stdout); return; }
+
+AudioOutputEngineAlsa::AudioOutputEngineAlsa()
+{
+ printf("AudioOutputEngineAlsa\n");
+ int rc;
+
+ std::string pcmname = "default";
+
+ rc = snd_pcm_open(&handle, pcmname.c_str(),
+ SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
+ T_(rc, "snd_pcm_open");
+}
+
+AudioOutputEngineAlsa::~AudioOutputEngineAlsa()
+{
+ printf("~AudioOutputEngineAlsa\n");
+ if(handle) snd_pcm_close(handle);
+}
+
+bool AudioOutputEngineAlsa::init(Channels *channels)
+{
+ this->channels = channels;
+
+ if(!handle) {
+ printf("No handle!\n");
+ return false;
+ }
+
+ int rc;
+ unsigned int srate = 44100;
+ snd_pcm_uframes_t frames = 32;
+
+ // Allocate a hardware parameters object.
+ snd_pcm_hw_params_alloca(&params);
+ // if(rc < 0) return false;
+
+ // Fill it in with default values.
+ rc = snd_pcm_hw_params_any(handle, params);
+ T(rc, "snd_pcm_hw_params_any");
+
+ rc = snd_pcm_hw_params_set_access(handle, params,
+ SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
+ T(rc, "snd_pcm_hw_params_set_access");
+
+ rc = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_FLOAT);
+ T(rc, "snd_pcm_hw_params_set_format");
+
+ rc = snd_pcm_hw_params_set_channels(handle, params, channels->size());
+ T(rc, "snd_pcm_hw_params_set_channels");
+
+ rc = snd_pcm_hw_params_set_rate_near(handle, params, &srate, 0);
+ T(rc, "snd_pcm_hw_params_set_rate_near");
+
+ rc = snd_pcm_hw_params_set_period_size_near(handle, params, &frames, 0);
+ T(rc, "snd_pcm_hw_params_set_period_size_near");
+
+ rc = snd_pcm_hw_params(handle, params);
+ T(rc, "snd_pcm_hw_params");
+
+ // SW Params:
+ /*
+ rc = snd_pcm_sw_params_current(pcm, sw);
+ rc = snd_pcm_sw_params_set_start_threshold(pcm, sw, ~0U);
+ rc = snd_pcm_sw_params_set_stop_threshold(pcm, sw, ~0U);
+ rc = snd_pcm_sw_params(pcm, sw);
+ rc = snd_pcm_hw_params_get_buffer_size(hw, &buffer_size);
+ */
+
+ channels_t nchannels;
+ rc = snd_pcm_hw_params_get_channels(params, &nchannels);
+ printf("channels: %d rc: %d\n", nchannels, rc);
+ T(rc, "snd_pcm_hw_params_get_channels");
+ if(nchannels != channels->size()) return false;
+
+ channel_t c = 0;
+ Channels::iterator i = channels->begin();
+ while(i != channels->end()) {
+ i->num = c;
+
+ i++;
+ c++;
+ }
+
+ return true;
+}
+
+#define MICRO 1000000
+void AudioOutputEngineAlsa::run(DrumGizmo *drumgizmo)
+{
+ int rc;
+
+ snd_pcm_uframes_t nframes;
+
+ while(drumgizmo->isRunning()) {
+ timeval tim;
+ gettimeofday(&tim, NULL);
+ useconds_t t1 = tim.tv_sec * MICRO + tim.tv_usec;
+
+ snd_pcm_uframes_t offset = 0;
+
+ // unsigned int nchannels = 2;
+ // rc = snd_pcm_hw_params_get_channels(params, &nchannels);
+ // printf("channels: %d rc: %d\n", nchannels, rc);
+ // T_(rc, "snd_pcm_hw_params_get_channels");
+ nframes = snd_pcm_avail_update(handle);
+ // printf("%d\n", rc);
+ // T_(rc, "snd_pcm_avail_update");
+
+ // rc = snd_pcm_hw_params_get_buffer_size(params, &nframes);
+ // T_(rc, "nd_pcm_hw_params_get_buffer_size");
+
+ // nframes = 960;
+
+ const snd_pcm_channel_area_t *areas;
+ rc = snd_pcm_mmap_begin(handle, &areas, &offset, &nframes);
+ T_(rc, "snd_pcm_mmap_begin");
+
+ drumgizmo->pre((size_t)nframes);
+
+ Channels::iterator i = channels->begin();
+ while(i != channels->end()) {
+ const snd_pcm_channel_area_t *a = &areas[i->num];
+ sample_t *p = (sample_t*)a->addr + offset;
+ memset(p, 0, nframes * sizeof(sample_t));
+ drumgizmo->getSamples(&(*i), p, (size_t)nframes);
+
+ i++;
+ }
+ drumgizmo->post((size_t)nframes);
+
+ switch(snd_pcm_state(handle)) {
+ case SND_PCM_STATE_PREPARED:
+ rc = snd_pcm_mmap_commit(handle, offset, nframes);
+ T_(rc, "snd_pcm_mmap_commit");
+ rc = snd_pcm_start(handle);
+ T_(rc, "snd_pcm_start");
+ break;
+ case SND_PCM_STATE_RUNNING:
+ rc = snd_pcm_mmap_commit(handle, offset, nframes);
+ T_(rc, "snd_pcm_mmap_commit");
+ break;
+ default:
+ break;
+ }
+
+ useconds_t msec = ((useconds_t)nframes * MICRO)/44100;
+
+ gettimeofday(&tim, NULL);
+ useconds_t t2 = tim.tv_sec * MICRO + tim.tv_usec;
+
+ struct timespec slp;
+ slp.tv_sec = 0;
+ slp.tv_nsec = (msec - (t2 - t1)) * 1000;
+
+ nanosleep(&slp, NULL);
+
+ }
+}
diff --git a/src/audiooutputenginealsa.h b/src/audiooutputenginealsa.h
new file mode 100644
index 0000000..8aef940
--- /dev/null
+++ b/src/audiooutputenginealsa.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * audiooutputenginealsa.h
+ *
+ * Thu Sep 16 11:22:52 CEST 2010
+ * Copyright 2010 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 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.
+ */
+#ifndef __DRUMGIZMO_AUDIOOUTPUTENGINEALSA_H__
+#define __DRUMGIZMO_AUDIOOUTPUTENGINEALSA_H__
+
+// Use the newer ALSA API
+#define ALSA_PCM_NEW_HW_PARAMS_API
+
+#include <asoundlib.h>
+
+#include "audiooutputengine.h"
+
+class AudioOutputEngineAlsa : public AudioOutputEngine {
+public:
+ AudioOutputEngineAlsa();
+ ~AudioOutputEngineAlsa();
+
+ bool init(Channels *channels);
+
+ void run(DrumGizmo *drumgizmo);
+
+private:
+ snd_pcm_t *handle;
+ snd_pcm_hw_params_t *params;
+};
+
+#endif/*__DRUMGIZMO_AUDIOOUTPUTENGINEALSA_H__*/
diff --git a/src/audiooutputenginejack.cc b/src/audiooutputenginejack.cc
new file mode 100644
index 0000000..f29404d
--- /dev/null
+++ b/src/audiooutputenginejack.cc
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * audiooutputenginejack.cc
+ *
+ * Thu Sep 16 10:28:37 CEST 2010
+ * Copyright 2010 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 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 "audiooutputenginejack.h"
+
+#include <string.h>
+#include "drumgizmo.h"
+
+extern "C" {
+ static int _wrap_jack_process(jack_nframes_t nframes, void *arg){
+ return ((AudioOutputEngineJack*)arg)->process(nframes);}
+}
+
+AudioOutputEngineJack::AudioOutputEngineJack()
+{
+ jack_status_t status;
+
+ jack_client = jack_client_open("DrumGizmo", JackNullOption, &status);
+ jack_set_process_callback(jack_client, _wrap_jack_process, this);
+}
+
+AudioOutputEngineJack::~AudioOutputEngineJack()
+{
+ jack_client_close(jack_client);
+}
+
+bool AudioOutputEngineJack::init(Channels *channels)
+{
+ this->channels = channels;
+
+ Channels::iterator i = channels->begin();
+ while(i != channels->end()) {
+
+ jack_port_t *port =
+ jack_port_register(jack_client,
+ i->name.c_str(),
+ JACK_DEFAULT_AUDIO_TYPE,
+ JackPortIsOutput | JackPortIsTerminal,
+ 0);
+
+ output_ports.push_back(port);
+ i->num = output_ports.size() - 1;
+
+ i++;
+ }
+
+ return true;
+}
+
+void AudioOutputEngineJack::run(DrumGizmo *drumgizmo)
+{
+ gizmo = drumgizmo;
+
+ jack_activate(jack_client);
+
+ jack_connect(jack_client, "DrumGizmo:port0", "system:playback_1");
+ jack_connect(jack_client, "DrumGizmo:port1", "system:playback_2");
+
+ while(drumgizmo->isRunning()) {
+ sleep(1);
+ }
+}
+
+int AudioOutputEngineJack::process(jack_nframes_t nframes)
+{
+ gizmo->pre(nframes);
+
+ Channels::iterator i = channels->begin();
+ while(i != channels->end()) {
+ jack_port_t *port = output_ports[i->num];
+ jack_default_audio_sample_t *buffer;
+ buffer = (jack_default_audio_sample_t *)jack_port_get_buffer(port, nframes);
+
+ memset(buffer, 0, nframes * sizeof(sample_t));
+ gizmo->getSamples(&(*i), buffer, nframes);
+
+ i++;
+ }
+
+ gizmo->post(nframes);
+
+ return 0;
+}
diff --git a/src/audiooutputenginejack.h b/src/audiooutputenginejack.h
new file mode 100644
index 0000000..41d9964
--- /dev/null
+++ b/src/audiooutputenginejack.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * audiooutputenginejack.h
+ *
+ * Thu Sep 16 10:28:37 CEST 2010
+ * Copyright 2010 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 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.
+ */
+#ifndef __DRUMGIZMO_AUDIOOUTPUTENGINEJACK_H__
+#define __DRUMGIZMO_AUDIOOUTPUTENGINEJACK_H__
+
+#include <vector>
+
+#include <jack/jack.h>
+
+#include "audiooutputengine.h"
+
+class AudioOutputEngineJack : public AudioOutputEngine {
+public:
+ AudioOutputEngineJack();
+ ~AudioOutputEngineJack();
+
+ bool init(Channels *channels);
+
+ void run(DrumGizmo *drumgizmo);
+
+ // Internal callback method. *must* be public.
+ int process(jack_nframes_t nframes);
+
+private:
+ jack_client_t *jack_client;
+ std::vector< jack_port_t *> output_ports;
+
+ jack_port_t *port0;
+ jack_port_t *port1;
+
+ DrumGizmo *gizmo;
+};
+
+
+#endif/*__DRUMGIZMO_AUDIOOUTPUTENGINEJACK_H__*/
diff --git a/src/audiooutputenginesndfile.cc b/src/audiooutputenginesndfile.cc
new file mode 100644
index 0000000..f311180
--- /dev/null
+++ b/src/audiooutputenginesndfile.cc
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * audiooutputenginesndfile.cc
+ *
+ * Tue Sep 21 09:31:30 CEST 2010
+ * Copyright 2010 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 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 "audiooutputenginesndfile.h"
+
+#include "drumgizmo.h"
+
+AudioOutputEngineSndFile::AudioOutputEngineSndFile(std::string file)
+{
+ filename = file;
+}
+
+AudioOutputEngineSndFile::~AudioOutputEngineSndFile()
+{
+ if(fh) sf_close(fh);
+}
+
+bool AudioOutputEngineSndFile::init(Channels *channels)
+{
+ this->channels = channels;
+
+ sf_info.channels = channels->size();
+ sf_info.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT;
+ sf_info.samplerate = 44100;
+
+ fh = sf_open(filename.c_str(), SFM_WRITE, &sf_info);
+ if(!fh) {
+ printf("Load error...\n");
+ return false;
+ }
+
+ channel_t c = 0;
+ Channels::iterator i = channels->begin();
+ while(i != channels->end()) {
+ i->num = c;
+ i++;
+ c++;
+ }
+
+ return true;
+}
+
+void AudioOutputEngineSndFile::run(DrumGizmo *gizmo)
+{
+ sample_t s[channels->size()];
+
+ while(gizmo->isRunning()) {
+
+ gizmo->pre(1);
+ Channels::iterator i = channels->begin();
+ while(i != channels->end()) {
+ s[i->num] = 0.0;
+ gizmo->getSamples(&(*i), &(s[i->num]), 1);
+ i++;
+ }
+
+ gizmo->post(1);
+
+ sf_writef_float(fh, s, 1);
+ }
+}
diff --git a/src/audiooutputenginesndfile.h b/src/audiooutputenginesndfile.h
new file mode 100644
index 0000000..adfbe96
--- /dev/null
+++ b/src/audiooutputenginesndfile.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * audiooutputenginesndfile.h
+ *
+ * Tue Sep 21 09:31:29 CEST 2010
+ * Copyright 2010 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 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.
+ */
+#ifndef __DRUMGIZMO_AUDIOOUTPUTENGINESNDFILE_H__
+#define __DRUMGIZMO_AUDIOOUTPUTENGINESNDFILE_H__
+
+#include <string>
+
+#include <sndfile.h>
+
+#include "audiooutputengine.h"
+
+class AudioOutputEngineSndFile : public AudioOutputEngine {
+public:
+ AudioOutputEngineSndFile(std::string filename);
+ ~AudioOutputEngineSndFile();
+
+ bool init(Channels *channels);
+
+ void run(DrumGizmo *drumgizmo);
+
+private:
+ std::string filename;
+ SF_INFO sf_info;
+ SNDFILE *fh;
+};
+
+#endif/*__DRUMGIZMO_AUDIOOUTPUTENGINESNDFILE_H__*/
diff --git a/src/beatmapper.cc b/src/beatmapper.cc
index 2600499..1b25d07 100644
--- a/src/beatmapper.cc
+++ b/src/beatmapper.cc
@@ -26,6 +26,8 @@
*/
#include "beatmapper.h"
+#include <stdio.h>
+
#define DEF 2.0
BeatMapper::BeatMapper(Instrument *instrument)
diff --git a/src/channel.cc b/src/channel.cc
index 93a0715..941847a 100644
--- a/src/channel.cc
+++ b/src/channel.cc
@@ -29,5 +29,29 @@
Channel::Channel(std::string name)
{
this->name = name;
- this->port = NULL;
+ num = NO_CHANNEL;
}
+
+#ifdef TEST_CHANNEL
+//deps:
+//cflags:
+//libs:
+#include "test.h"
+
+TEST_BEGIN;
+
+Channel c1;
+TEST_EQUAL_STR(c1.name, "", "Empty name?");
+TEST_EQUAL_INT(c1.num, NO_CHANNEL, "No physical channel assigned?");
+
+Channel c2("ch2");
+TEST_EQUAL_STR(c2.name, "ch2", "Nonempty name?");
+TEST_EQUAL_INT(c2.num, NO_CHANNEL, "No physical channel assigned?");
+
+Channels channels;
+channels.push_back(c1);
+channels.push_back(c2);
+
+TEST_END;
+
+#endif/*TEST_CHANNEL*/
diff --git a/src/channel.h b/src/channel.h
index 4c512d5..7aadc3c 100644
--- a/src/channel.h
+++ b/src/channel.h
@@ -27,15 +27,21 @@
#ifndef __DRUMGIZMO_CHANNEL_H__
#define __DRUMGIZMO_CHANNEL_H__
+#include <vector>
#include <string>
-#include <jack/jack.h>
+
+#include "audio.h"
class Channel {
public:
- Channel(std::string name);
+ Channel(std::string name = "");
std::string name;
- jack_port_t *port;
+ channel_t num;
};
+typedef Channel InstrumentChannel;
+
+typedef std::vector< Channel > Channels;
+
#endif/*__DRUMGIZMO_CHANNEL_H__*/
diff --git a/src/channelmixer.cc b/src/channelmixer.cc
new file mode 100644
index 0000000..c8ee71a
--- /dev/null
+++ b/src/channelmixer.cc
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * channelmixer.cc
+ *
+ * Sun Oct 17 10:14:34 CEST 2010
+ * Copyright 2010 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 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 "channelmixer.h"
+
+ChannelMixer::ChannelMixer(Channels &c, Channel *defc, float defg)
+ : channels(c)
+{
+ setDefaults(defc, defg);
+}
+
+void ChannelMixer::setDefaults(Channel *defc, float defg)
+{
+ defaultchannel = defc;
+ if(defc == NULL && channels.size() > 0) defaultchannel = &channels[0];
+
+ defaultgain = defg;
+}
+
+MixerSettings &ChannelMixer::lookup(InstrumentChannel *c)
+{
+ std::map<InstrumentChannel *, MixerSettings>::iterator mi = mix.find(c);
+
+ if(mi == mix.end()) {
+ MixerSettings m;
+ m.gain = defaultgain;
+ m.output = defaultchannel;
+ mix[c] = m;
+ return mix[c];
+ }
+
+ return mi->second;
+}
+
+
+#ifdef TEST_CHANNELMIXER
+//deps: channel.cc
+//cflags:
+//libs:
+#include "test.h"
+
+TEST_BEGIN;
+
+Channel ch1;
+Channel ch2;
+Channels channels;
+channels.push_back(ch1);
+channels.push_back(ch2);
+
+{
+ ChannelMixer mixer(channels, NULL, 1.0);
+
+ InstrumentChannel ich;
+ MixerSettings &m = mixer.lookup(&ich);
+ TEST_EQUAL(m.output, &channels[0], "Default channel?");
+ TEST_EQUAL_FLOAT(m.gain, 1.0, "Default gain?");
+}
+
+{
+ ChannelMixer mixer(channels, &channels[1]);
+
+ InstrumentChannel ich;
+ MixerSettings &m = mixer.lookup(&ich);
+ TEST_EQUAL(m.output, &channels[1], "Default channel?");
+ TEST_EQUAL_FLOAT(m.gain, 1.0, "Default gain?");
+}
+
+{
+ ChannelMixer mixer(channels, &channels[1]);
+
+ InstrumentChannel ich;
+ MixerSettings &m = mixer.lookup(&ich);
+ TEST_EQUAL(m.output, &channels[1], "Default channel?");
+ TEST_EQUAL_FLOAT(m.gain, 1.0, "Default gain?");
+
+ m.output = &channels[0];
+ m.gain = 0.5;
+
+ MixerSettings &m2 = mixer.lookup(&ich);
+ TEST_EQUAL(m2.output, &channels[0], "Changed channel?");
+ TEST_EQUAL_FLOAT(m2.gain, 0.5, "Changed gain?");
+}
+
+
+TEST_END;
+
+#endif/*TEST_CHANNELMIXER*/
diff --git a/src/channelmixer.h b/src/channelmixer.h
new file mode 100644
index 0000000..06cef2f
--- /dev/null
+++ b/src/channelmixer.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * channelmixer.h
+ *
+ * Sun Oct 17 10:14:34 CEST 2010
+ * Copyright 2010 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 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.
+ */
+#ifndef __DRUMGIZMO_CHANNELMIXER_H__
+#define __DRUMGIZMO_CHANNELMIXER_H__
+
+#include <map>
+
+#include "channel.h"
+
+class MixerSettings {
+public:
+ float gain;
+ Channel *output;
+};
+
+class ChannelMixer {
+public:
+ ChannelMixer(Channels &channels,
+ Channel *defaultchannel = NULL, float defaultgain = 1.0);
+
+ MixerSettings &lookup(InstrumentChannel *channel);
+
+ void setDefaults(Channel *defaultchannel, float defaultgain);
+
+private:
+ std::map<InstrumentChannel *, MixerSettings> mix;
+
+ Channel *defaultchannel;
+ float defaultgain;
+
+ Channels &channels;
+};
+
+#endif/*__DRUMGIZMO_CHANNELMIXER_H__*/
diff --git a/src/cli.cc b/src/cli.cc
new file mode 100644
index 0000000..bb0eae2
--- /dev/null
+++ b/src/cli.cc
@@ -0,0 +1,189 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * cli.cc
+ *
+ * Thu Sep 16 10:23:22 CEST 2010
+ * Copyright 2010 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 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 <config.h>
+#include <getopt.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "drumgizmo.h"
+
+#include "audiooutputengine.h"
+#include "audioinputengine.h"
+
+#include "event.h"
+
+static const char version_str[] =
+"DrumGizmo v" VERSION "\n"
+;
+
+static const char copyright_str[] =
+"Copyright (C) 2008-2009 Bent Bisballe Nyeng - Aasimon.org.\n"
+"This is free software. You may redistribute copies of it under the terms of\n"
+"the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.\n"
+"There is NO WARRANTY, to the extent permitted by law.\n"
+"\n"
+"Written by Bent Bisballe Nyeng (deva@aasimon.org)\n"
+;
+
+static const char usage_str[] =
+"Usage: %s [options] drumkitfile\n"
+"Options:\n"
+" -p, --preload Load entire kit audio files into memory (uses ALOT of memory).\n"
+" -o, --outputengine alsa|jack|sndfile Use said audio engine.\n"
+" -i, --inputengine jackmidi|midifile Use said audio engine.\n"
+" -v, --version Print version information and exit.\n"
+" -h, --help Print this message and exit.\n"
+;
+
+int main(int argc, char *argv[])
+{
+ int c;
+
+ std::string outputengine;
+ std::string inputengine;
+ bool preload = false;
+
+ int option_index = 0;
+ while(1) {
+ static struct option long_options[] = {
+ {"preload", no_argument, 0, 'p'},
+ {"outputengine", required_argument, 0, 'o'},
+ {"inputengine", required_argument, 0, 'i'},
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'v'},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long (argc, argv, "hvpo:i:", long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch(c) {
+ case 'o':
+ outputengine = optarg;
+ break;
+
+ case 'i':
+ inputengine = optarg;
+ break;
+
+ case 'p':
+ preload = true;
+ break;
+
+ case '?':
+ case 'h':
+ printf("%s", version_str);
+ printf(usage_str, argv[0]);
+ return 0;
+
+ case 'v':
+ printf("%s", version_str);
+ printf("%s", copyright_str);
+ return 0;
+
+ default:
+ break;
+ }
+ }
+
+ if(outputengine == "") {
+ printf("Missing output engine\n");
+ return 1;
+ }
+
+ AudioOutputEngine *oe = createAudioOutputEngine(outputengine);
+
+ if(oe == NULL) {
+ printf("Invalid output engine: %s\n", outputengine.c_str());
+ return 1;
+ }
+
+
+ if(inputengine == "") {
+ printf("Missing input engine\n");
+ return 1;
+ }
+
+ AudioInputEngine *ie = createAudioInputEngine(inputengine);
+
+ if(ie == NULL) {
+ printf("Invalid input engine: %s\n", outputengine.c_str());
+ return 1;
+ }
+
+ std::string kitfile;
+
+ if(option_index < argc) {
+ printf("non-option ARGV-elements: ");
+ while (optind < argc) {
+ if(kitfile != "") {
+ fprintf(stderr, "Can only handle a single kitfile.\n");
+ printf(usage_str, argv[0]);
+ return 1;
+ }
+ kitfile = argv[optind++];
+ }
+ printf("\n");
+ } else {
+ fprintf(stderr, "Missing kitfile.\n");
+ printf(usage_str, argv[0]);
+ return 1;
+ }
+
+ printf("Using kitfile: %s\n", kitfile.c_str());
+
+ Channels channels;
+ Channel c1; c1.num = 0;
+ Channel c2; c2.num = 1;
+ channels.push_back(c1);
+ channels.push_back(c2);
+ ChannelMixer m(channels, &channels[0]);
+
+ DrumGizmo gizmo(*oe, *ie, m);
+ if(/*kitfile == "" ||*/ !gizmo.loadkit(kitfile)) {
+ printf("Failed to load \"%s\".\n", kitfile.c_str());
+ return 1;
+ }
+
+ if(!gizmo.init(preload)) {
+ printf("Failed init drumkit.\n");
+ return 1;
+ }
+
+ gizmo.run();
+
+ printf("Quit.\n"); fflush(stdout);
+
+ delete oe;
+ delete ie;
+
+ return 0;
+}
diff --git a/src/cli.h b/src/cli.h
new file mode 100644
index 0000000..a5c42be
--- /dev/null
+++ b/src/cli.h
@@ -0,0 +1,29 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * cli.h
+ *
+ * Thu Sep 16 10:23:22 CEST 2010
+ * Copyright 2010 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 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.
+ */
+#ifndef __DRUMGIZMO_CLI_H__
+#define __DRUMGIZMO_CLI_H__
+#endif/*__DRUMGIZMO_CLI_H__*/
diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc
index 3941f17..161517e 100644
--- a/src/drumgizmo.cc
+++ b/src/drumgizmo.cc
@@ -2,8 +2,8 @@
/***************************************************************************
* drumgizmo.cc
*
- * Sun Jul 20 19:25:01 CEST 2008
- * Copyright 2008 Bent Bisballe Nyeng
+ * Thu Sep 16 10:24:40 CEST 2010
+ * Copyright 2010 Bent Bisballe Nyeng
* deva@aasimon.org
****************************************************************************/
@@ -24,125 +24,214 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#include <config.h>
-#include <getopt.h>
-#include "jackclient.h"
+#include "drumgizmo.h"
+
+#include <math.h>
+#include <stdio.h>
+
#include "drumkitparser.h"
-#include "midiplayer.h"
-#include <string.h>
-
-static const char version_str[] =
-"DrumGizmo v" VERSION "\n"
-;
-
-static const char copyright_str[] =
-"Copyright (C) 2008-2009 Bent Bisballe Nyeng - Aasimon.org.\n"
-"This is free software. You may redistribute copies of it under the terms of\n"
-"the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.\n"
-"There is NO WARRANTY, to the extent permitted by law.\n"
-"\n"
-"Written by Bent Bisballe Nyeng (deva@aasimon.org)\n"
-;
-
-static const char usage_str[] =
-"Usage: %s [options] drumkitfile\n"
-"Options:\n"
-" -p, --preload Load entire kit audio files into memory (uses ALOT of memory).\n"
-" -P, --preload_vel vel Load all files with velocity above vel into memory (uses a little less memory).\n"
-" -m, --midi midifile Load midifile, and play it.\n"
-" -v, --version Print version information and exit.\n"
-" -h, --help Print this message and exit.\n"
-;
-
-int main(int argc, char *argv[])
+#include "audiooutputengine.h"
+#include "audioinputengine.h"
+#include "event.h"
+
+DrumGizmo::DrumGizmo(AudioOutputEngine &o,
+ AudioInputEngine &i,
+ ChannelMixer &m)
+ : mixer(m), oe(o), ie(i)
{
- int c;
-
- char *midifile = NULL;
- bool preload = true;
- int min_velocity = 0;//18;
-
- int option_index = 0;
- while(1) {
- static struct option long_options[] = {
- {"preload_vel", required_argument, 0, 'P'},
- {"preload", no_argument, 0, 'p'},
- {"midi", required_argument, 0, 'm'},
- {"help", no_argument, 0, 'h'},
- {"version", no_argument, 0, 'v'},
- {0, 0, 0, 0}
- };
-
- c = getopt_long (argc, argv, "hvpP:m:", long_options, &option_index);
-
- if (c == -1)
- break;
-
- switch(c) {
- case 'm':
- midifile = strdup(optarg);
- break;
+ time = 0;
+ Channel c1; c1.num = 0; c1.name="left";
+ Channel c2; c2.num = 1; c2.name="right";
+ channels.push_back(c1);
+ channels.push_back(c2);
+}
- case 'p':
- preload = true;
- break;
-
- case 'P':
- preload = true;
- min_velocity = atoi(optarg);
- break;
+DrumGizmo::~DrumGizmo()
+{
+ AudioFiles::iterator i = audiofiles.begin();
+ while(i != audiofiles.end()) {
+ AudioFile *audiofile = i->second;
+ delete audiofile;
+ i++;
+ }
+}
- case '?':
- case 'h':
- printf(version_str);
- printf(usage_str, argv[0]);
- return 0;
+bool DrumGizmo::loadkit(const std::string &kitfile)
+{
+ /*
+ DrumKitParser parser(kitfile, kit);
+ if(parser.parse()) return false;
+ */
- case 'v':
- printf(version_str);
- printf(copyright_str);
- return 0;
+ return true;
+}
- default:
- break;
+bool DrumGizmo::init(bool preload)
+{
+ if(preload) {
+ AudioFiles::iterator i = audiofiles.begin();
+ while(i != audiofiles.end()) {
+ AudioFile *audiofile = i->second;
+ audiofile->load();
+ i++;
}
}
- std::string kitfile;
+ if(!oe.init(&channels)) return false;
- if(option_index < argc) {
- printf("non-option ARGV-elements: ");
- while (optind < argc) {
- if(kitfile != "") {
- fprintf(stderr, "Can only handle a single kitfile.\n");
- printf(usage_str, argv[0]);
- return 1;
- }
- kitfile = argv[optind++];
+ if(!ie.init(&eventqueue)) return false;
+
+ return true;
+}
+
+void DrumGizmo::run()
+{
+ is_running = true;
+ oe.run(this);
+}
+
+void DrumGizmo::pre(size_t sz)
+{
+ ie.run(time, sz);
+
+ for(size_t n = 0; n < sz; n++) {
+ while(eventqueue.hasEvent(time + n)) {
+ Event *event = eventqueue.take(time + n);
+ activeevents[event->channel].push_back(event);
}
- printf("\n");
- } else {
- fprintf(stderr, "Missing kitfile.\n");
- printf(usage_str, argv[0]);
- return 1;
}
-
- printf("Using kitfile: %s\n", kitfile.c_str());
+}
- DrumKitParser parser(kitfile, preload, min_velocity);
- if(parser.parse()) return 1;
+void DrumGizmo::getSamples(Channel *c, sample_t *s, size_t sz)
+{
+ for(std::list< Event* >::iterator i = activeevents[c->num].begin();
+ i != activeevents[c->num].end();
+ i++) {
+ bool removeevent = false;
+
+ Event *event = *i;
+
+ Event::type_t type = event->type();
+ switch(type) {
+ case Event::sine:
+ {
+ EventSine *evt = (EventSine *)event;
+ for(size_t n = 0; n < sz; n++) {
+
+ if(evt->offset > (time + n)) continue;
+
+ if(evt->t > evt->len) {
+ removeevent = true;
+ break;
+ }
+
+ float x = (float)evt->t / 44100.0;
+ float gain = evt->gain;
+ gain *= 1.0 - ((float)evt->t / (float)evt->len);
+ sample_t val = gain * sin(2.0 * M_PI * evt->freq * x);
+ s[n] += val;
+
+ evt->t++;
+ }
+ }
+ break;
- JackClient client(parser.getDrumkit());
+ case Event::noise:
+ {
+ EventNoise *evt = (EventNoise *)event;
+ for(size_t n = 0; n < sz; n++) {
- client.activate();
+ if(evt->offset > (time + n)) continue;
- if(midifile) {
- MidiPlayer player(midifile);
+ if(evt->t > evt->len) {
+ removeevent = true;
+ break;
+ }
+
+ float gain = evt->gain;
+ gain *= 1.0 - ((float)evt->t / (float)evt->len);
+ sample_t val = (float)rand() / (float)RAND_MAX;
+ s[n] += val * gain;
+ evt->t++;
+ }
+ }
+ break;
+
+ case Event::sample:
+ {
+ /*
+ EventSample *evt = (EventSample *)event;
+ AudioFile *af = audiofiles[evt->file];
+ af->load(); // Make sure it is loaded.
+ for(size_t n = 0; n < sz; n++) {
+
+ if(evt->offset > (time + n)) continue;
+
+ if(evt->t > af->size) {
+ removeevent = true;
+ break;
+ }
+
+ float gain = evt->gain;
+ gain *= 1.0 - ((float)evt->t / (float)af->size);
+ sample_t val = af->data[evt->t];
+ s[n] += val * gain;
+ evt->t++;
+ }
+ */
+ }
+ break;
+ }
- while(1) sleep(1);
+ if(removeevent) {
+ delete event;
+ i = activeevents[c->num].erase(i);
+ if(activeevents[0].size() +
+ activeevents[1].size() +
+ eventqueue.size() == 0) {/*is_running = false;*/}
+ }
}
+}
- while(1) sleep(1);
+void DrumGizmo::post(size_t sz)
+{
+ time += sz;
+}
- return 0;
+void DrumGizmo::stop()
+{
+ // engine.stop();
}
+
+#ifdef TEST_DRUMGIZMO
+//deps: instrument.cc sample.cc channel.cc audiofile.cc event.cc
+//cflags: $(SNDFILE_CFLAGS)
+//libs: $(SNDFILE_LIBS)
+#include "test.h"
+
+class AudioOutputEngineDummy : public AudioOutputEngine {
+public:
+ bool init(Channels *channels) { return true; }
+ void run(DrumGizmo *drumgizmo) {}
+};
+
+TEST_BEGIN;
+
+AudioOutputEngineDummy a;
+DrumGizmo g(a);
+
+Channel ch0("ch0"); g.channels.push_back(ch0);
+Channel ch1("ch1"); g.channels.push_back(ch1);
+
+Instrument i("test");
+Sample s1; i.addSample(0.0, 1.0, &s1);
+Sample s2; i.addSample(0.0, 1.0, &s2);
+Sample s3; i.addSample(0.0, 1.0, &s3);
+
+//g.kit.instruments["instr"] = i;
+
+g.run();
+
+TEST_END;
+
+#endif/*TEST_DRUMGIZMO*/
diff --git a/src/drumgizmo.h b/src/drumgizmo.h
new file mode 100644
index 0000000..4c6683b
--- /dev/null
+++ b/src/drumgizmo.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * drumgizmo.h
+ *
+ * Thu Sep 16 10:24:40 CEST 2010
+ * Copyright 2010 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 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.
+ */
+#ifndef __DRUMGIZMO_DRUMGIZMO_H__
+#define __DRUMGIZMO_DRUMGIZMO_H__
+
+#include <string>
+#include <list>
+
+#include "drumkit.h"
+#include "audio.h"
+#include "event.h"
+
+#include "channelmixer.h"
+
+class AudioOutputEngine;
+class AudioInputEngine;
+
+class DrumGizmo {
+public:
+ DrumGizmo(AudioOutputEngine &outputengine,
+ AudioInputEngine &inputengine,
+ ChannelMixer &mixer);
+ ~DrumGizmo();
+
+ bool loadkit(const std::string &kitfile);
+
+ bool init(bool preload = true);
+
+ void run();
+ void stop();
+
+ void pre(size_t sz);
+ void getSamples(Channel *c, sample_t *s, size_t sz);
+ void post(size_t sz);
+
+ bool isRunning() { return is_running; }
+
+ Channels channels;
+ ChannelMixer mixer;
+
+ EventQueue eventqueue;
+
+private:
+ bool is_running;
+
+ AudioOutputEngine &oe;
+ AudioInputEngine &ie;
+
+ std::list< Event* > activeevents[100];
+ timepos_t time;
+
+ AudioFiles audiofiles;
+
+#ifdef TEST_DRUMGIZMO
+public:
+#endif
+ DrumKit kit;
+};
+
+
+#endif/*__DRUMGIZMO_DRUMGIZMO_H__*/
diff --git a/src/drumkit.h b/src/drumkit.h
index caf1dc2..d79a3e4 100644
--- a/src/drumkit.h
+++ b/src/drumkit.h
@@ -30,23 +30,14 @@
#include <map>
#include <string>
-#include "sample.h"
-#include "instrument.h"
#include "channel.h"
-
-typedef std::map< std::string, Channel* > Channels;
-typedef std::map< std::string, Sample* > Samples;
-
-typedef unsigned int midi_note_t;
-typedef std::map< midi_note_t, Instrument* > Instruments;
+#include "instrument.h"
+#include "midimap.h"
class DrumKit {
public:
std::string name;
std::string description;
-
- Channels channels;
- Samples samples;
Instruments instruments;
};
diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc
index e18d262..499b78c 100644
--- a/src/drumkitparser.cc
+++ b/src/drumkitparser.cc
@@ -25,85 +25,52 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
#include "drumkitparser.h"
+
#include <string.h>
+#include <stdio.h>
+
#define DIR_SEPERATOR '/'
-DrumKitParser::DrumKitParser(std::string kitfile, bool preload, int min_velocity)
+DrumKitParser::DrumKitParser(const std::string &kitfile, DrumKit &k)
+ : kit(k)
{
- std::string file;
- std::string path;
-
- char *split = strrchr(kitfile.c_str(), DIR_SEPERATOR);
- if(split) {
- file = split + 1;
- path = kitfile.substr(0, kitfile.length() - file.length());
- // All drum samples are relative to the kitfile, so we must chdir there to be able to open them.
- chdir(path.c_str());
- } else {
- file = kitfile;
- }
-
- this->preload = preload;
- this->min_velocity = min_velocity;
-
- dk = NULL;
- fd = fopen(file.c_str(), "r");
+ fd = fopen(kitfile.c_str(), "r");
if(!fd) return;
- dk = new DrumKit();
}
DrumKitParser::~DrumKitParser()
{
- if(dk) fclose(fd);
+ if(fd) fclose(fd);
}
-void DrumKitParser::startTag(std::string name, std::map< std::string, std::string> attributes)
+void DrumKitParser::startTag(std::string name,
+ std::map< std::string, std::string> attributes)
{
if(name == "drumkit") {
- dk->name = attributes["name"];
- dk->description = attributes["description"];
+ kit.name = attributes["name"];
+ kit.description = attributes["description"];
}
if(name == "channels") {}
if(name == "channel") {
- Channel *c = new Channel(attributes["name"]);
- dk->channels[attributes["name"]] = c;
+ // Channel *c = new Channel(attributes["name"]);
+ // dk->channels[attributes["name"]] = c;
}
- if(name == "samples") {}
-
- if(name == "sample") {
- Sample *s = new Sample(attributes["name"]);
- dk->samples[attributes["name"]] = s;
- lastsample = s;
+ if(name == "instruments") {
}
- if(name == "audiofile") {
- AudioFile *af = new AudioFile(attributes["name"], preload, min_velocity);
- af->channel = attributes["channel"];
- lastsample->audiofiles[attributes["name"]] = af;
+ if(name == "instrument") {
}
- if(name == "instruments") {}
-
- if(name == "instrument") {
- midi_note_t m = atoi(attributes["midimap"].c_str());
- Instrument *i = new Instrument(attributes["name"], m);
- dk->instruments[m] = i;
- lastinstrument = i;
+ if(name == "channelmap") {
}
-
- if(name == "velocity") {
- Velocity *v = new Velocity(atoi(attributes["lower"].c_str()),
- atoi(attributes["upper"].c_str()));
- lastinstrument->addVelocity(v);
- lastvelocity = v;
+
+ if(name == "midimaps") {
}
- if(name == "sampleref") {
- lastvelocity->addSample(dk->samples[attributes["name"]],
- atof(attributes["probability"].c_str()));
+ if(name == "midimap") {
}
}
@@ -111,14 +78,9 @@ void DrumKitParser::endTag(std::string name)
{
}
-DrumKit *DrumKitParser::getDrumkit()
-{
- return dk;
-}
-
int DrumKitParser::readData(char *data, size_t size)
{
- if(!fd) return 0;
+ if(!fd) return -1;
return fread(data, 1, size, fd);
}
diff --git a/src/drumkitparser.h b/src/drumkitparser.h
index 22fe83e..783ed5f 100644
--- a/src/drumkitparser.h
+++ b/src/drumkitparser.h
@@ -32,27 +32,19 @@
class DrumKitParser : public SAXParser {
public:
- DrumKitParser(std::string kitfile, bool preload = false, int min_velocity = -1);
+ DrumKitParser(const std::string &kitfile, DrumKit &kit);
~DrumKitParser();
- void startTag(std::string name, std::map< std::string, std::string> attributes);
+ void startTag(std::string name,
+ std::map< std::string, std::string> attributes);
void endTag(std::string name);
- DrumKit *getDrumkit();
-
protected:
int readData(char *data, size_t size);
private:
FILE *fd;
- DrumKit *dk;
-
- Sample *lastsample;
- Instrument *lastinstrument;
- Velocity *lastvelocity;
-
- bool preload;
- int min_velocity;
+ DrumKit &kit;
};
#endif/*__DRUMGIZMO_DRUMKITPARSER_H__*/
diff --git a/src/event.cc b/src/event.cc
index 5a78746..717fa12 100644
--- a/src/event.cc
+++ b/src/event.cc
@@ -2,8 +2,8 @@
/***************************************************************************
* event.cc
*
- * Mon Jul 21 10:56:02 CEST 2008
- * Copyright 2008 Bent Bisballe Nyeng
+ * Sat Sep 18 22:02:16 CEST 2010
+ * Copyright 2010 Bent Bisballe Nyeng
* deva@aasimon.org
****************************************************************************/
@@ -26,21 +26,25 @@
*/
#include "event.h"
-Event::Event(jack_port_t *port, AudioFile *sample, size_t time, size_t duration)
+void EventQueue::post(Event *event, timepos_t time)
{
- this->port = port;
- this->sample = sample;
- sample->load();
- this->time = time;
- this->duration = duration;
+ MutexAutolock lock(mutex);
+ event->offset = time;
+ queue.insert(std::pair<timepos_t, Event*>(time, event));
}
-Event::~Event()
+Event *EventQueue::take(timepos_t time)
{
+ MutexAutolock lock(mutex);
+ std::multimap<timepos_t, Event*>::iterator i = queue.find(time);
+ if(i == queue.end()) return NULL;
+ Event *event = i->second;
+ queue.erase(i);
+ return event;
}
-bool Event::operator<(const Event& event) const
+bool EventQueue::hasEvent(timepos_t time)
{
- if(time == event.time) return this < &event;
- return time < event.time;
+ MutexAutolock lock(mutex);
+ return queue.find(time) != queue.end();
}
diff --git a/src/event.h b/src/event.h
index b721df0..2128386 100644
--- a/src/event.h
+++ b/src/event.h
@@ -2,8 +2,8 @@
/***************************************************************************
* event.h
*
- * Mon Jul 21 10:56:01 CEST 2008
- * Copyright 2008 Bent Bisballe Nyeng
+ * Sat Sep 18 22:02:16 CEST 2010
+ * Copyright 2010 Bent Bisballe Nyeng
* deva@aasimon.org
****************************************************************************/
@@ -27,24 +27,97 @@
#ifndef __DRUMGIZMO_EVENT_H__
#define __DRUMGIZMO_EVENT_H__
-#include <jack/jack.h>
+#include <map>
+#include <stdio.h>
+#include <string>
+#include <sndfile.h>
-#include <set>
-#include "audiofile.h"
+#include "audio.h"
+#include "mutex.h"
+
+typedef unsigned int timepos_t;
class Event {
public:
- Event(jack_port_t *port, AudioFile *sample, size_t time, size_t duration = 0);
- ~Event();
+ typedef enum {
+ sine,
+ noise,
+ sample
+ } type_t;
+
+ virtual type_t type() = 0;
+
+ channel_t channel;
+ timepos_t offset;
+};
+
+class EventSine : public Event {
+public:
+ EventSine(channel_t c, float f, float g, timepos_t l)
+ {
+ channel = c;
+ freq = f;
+ gain = g;
+ len = l;
+ t = 0;
+ }
+ Event::type_t type() { return Event::sine; }
+
+ float freq;
+ float gain;
+ timepos_t len;
+
+ unsigned int t;
+};
+
+class EventNoise : public Event {
+public:
+ EventNoise(channel_t c, float g, timepos_t l)
+ {
+ channel = c;
+ gain = g;
+ len = l;
+ t = 0;
+ }
+ Event::type_t type() { return Event::noise; }
+
+ float gain;
+ timepos_t len;
+
+ unsigned int t;
+};
+
+class EventSample : public Event {
+public:
+ EventSample(channel_t c, float g, std::string f)
+ {
+ channel = c;
+ gain = g;
+ t = 0;
+ file = f;
+ }
+
+ Event::type_t type() { return Event::sample; }
+
+ float gain;
- bool operator<(const Event& event) const;
+ unsigned int t;
- jack_port_t *port;
- AudioFile *sample;
- size_t duration;
- size_t time;
+ std::string file;
};
-typedef std::set< Event > Events;
+
+
+class EventQueue {
+public:
+ void post(Event *event, timepos_t time);
+ Event *take(timepos_t time);
+ bool hasEvent(timepos_t time);
+ size_t size() { return queue.size(); }
+
+private:
+ std::multimap< timepos_t, Event* > queue;
+ Mutex mutex;
+};
#endif/*__DRUMGIZMO_EVENT_H__*/
diff --git a/src/instrument.cc b/src/instrument.cc
index 0aa38ac..b710757 100644
--- a/src/instrument.cc
+++ b/src/instrument.cc
@@ -26,23 +26,60 @@
*/
#include "instrument.h"
-Instrument::Instrument(std::string name, unsigned int midimap)
+#include <stdlib.h>
+
+Instrument::Instrument(std::string name)
{
this->name = name;
- this->midimap = midimap;
}
-void Instrument::addVelocity(Velocity *velocity)
+Sample *Instrument::sample(level_t level)
{
- velocities.push_back(velocity);
+ std::vector<Sample*> s = samples.get(level);
+ if(s.size() == 0) return NULL;
+ size_t idx = rand()%(s.size());
+ return s[idx];
}
-Velocity *Instrument::getVelocity(unsigned int v)
+void Instrument::addSample(level_t a, level_t b, Sample *s)
{
- Velocities::iterator i = velocities.begin();
- while(i != velocities.end()) {
- if(v >= (*i)->lower && v <= (*i)->upper) return *i;
- i++;
- }
- return NULL;
+ samples.insert(a, b, s);
}
+
+#ifdef TEST_INSTRUMENT
+//deps: channel.cc sample.cc audiofile.cc
+//cflags: $(SNDFILE_CFLAGS)
+//libs: $(SNDFILE_LIBS)
+#include "test.h"
+
+TEST_BEGIN;
+
+Instrument i("test");
+
+Sample *a = new Sample();
+i.addSample(0.0, 1.0, a);
+
+Sample *b = new Sample();
+i.addSample(0.0, 1.0, b);
+
+Sample *c = new Sample();
+i.addSample(1.5, 1.7, c);
+
+TEST_EQUAL(i.sample(0.0), b, "?");
+TEST_EQUAL(i.sample(0.0), a, "?");
+TEST_EQUAL(i.sample(0.0), b, "?");
+TEST_EQUAL(i.sample(0.0), b, "?");
+TEST_EQUAL(i.sample(0.0), b, "?");
+TEST_EQUAL(i.sample(0.0), b, "?");
+TEST_EQUAL(i.sample(0.0), a, "?");
+TEST_EQUAL(i.sample(0.0), a, "?");
+
+TEST_EQUAL(i.sample(2.0), NULL, "?");
+
+TEST_EQUAL(i.sample(1.6), c, "?");
+TEST_EQUAL(i.sample(1.6), c, "?");
+TEST_EQUAL(i.sample(1.6), c, "?");
+
+TEST_END;
+
+#endif/*TEST_INSTRUMENT*/
diff --git a/src/instrument.h b/src/instrument.h
index 96fc6ba..b01379f 100644
--- a/src/instrument.h
+++ b/src/instrument.h
@@ -30,25 +30,60 @@
#include <string>
#include <vector>
-#include <jack/jack.h>
-
-#include "velocity.h"
+#include "rangemap.h"
+#include "sample.h"
class Instrument {
public:
- Instrument(std::string name, unsigned int midimap);
-
- void addVelocity(Velocity *velocity);
- Velocity *getVelocity(unsigned int velocity);
+ Instrument(std::string name);
- std::string name;
- unsigned int midimap;
+ Sample *sample(level_t level);
- jack_port_t *port;
+ void addSample(level_t a, level_t b, Sample *s);
private:
- typedef std::vector< Velocity * > Velocities;
- Velocities velocities;
+ std::string name;
+ RangeMap<level_t, Sample*> samples;
};
+typedef std::map< std::string, Instrument > Instruments;
+
+/*
+ * <?xml version='1.0' encoding='UTF-8'?>
+ * <instrument name="kick-r">
+ * <samples>
+ * <sample name="kick-r-1">
+ * <audiofile channel="Alesis-3" file="samples/1-kick-r-Alesis-3.wav"/>
+ * <audiofile channel="Amb L-3" file="samples/1-kick-r-Amb L-3.wav"/>
+ * <audiofile channel="Amb R-3" file="samples/1-kick-r-Amb R-3.wav"/>
+ * <audiofile channel="Kick L-3" file="samples/1-kick-r-Kick L-3.wav"/>
+ * <audiofile channel="Kick R-3" file="samples/1-kick-r-Kick R-3.wav"/>
+ * </sample>
+ * <sample name="kick-r-2">
+ * <audiofile channel="Alesis-3" file="samples/2-kick-r-Alesis-3.wav"/>
+ * <audiofile channel="Amb L-3" file="samples/2-kick-r-Amb L-3.wav"/>
+ * <audiofile channel="Amb R-3" file="samples/2-kick-r-Amb R-3.wav"/>
+ * <audiofile channel="Kick L-3" file="samples/2-kick-r-Kick L-3.wav"/>
+ * <audiofile channel="Kick R-3" file="samples/2-kick-r-Kick R-3.wav"/>
+ * </sample>
+ * <sample name="kick-r-3">
+ * <audiofile channel="Alesis-3" file="samples/3-kick-r-Alesis-3.wav"/>
+ * <audiofile channel="Amb L-3" file="samples/3-kick-r-Amb L-3.wav"/>
+ * <audiofile channel="Amb R-3" file="samples/3-kick-r-Amb R-3.wav"/>
+ * <audiofile channel="Kick L-3" file="samples/3-kick-r-Kick L-3.wav"/>
+ * <audiofile channel="Kick R-3" file="samples/3-kick-r-Kick R-3.wav"/>
+ * </sample>
+ * </samples>
+ * <velocities>
+ * <velocity lower="0" upper="99">
+ * <sampleref name="kick-r-1"/>
+ * <sampleref name="kick-r-2"/>
+ * </velocity>
+ * <velocity lower="100" upper="127">
+ * <sampleref name="kick-r-3"/>
+ * </velocity>
+ * </velocities>
+ * </instrument>
+ */
+
#endif/*__DRUMGIZMO_INSTRUMENT_H__*/
diff --git a/src/midi.h b/src/midi.h
new file mode 100644
index 0000000..5d1515e
--- /dev/null
+++ b/src/midi.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * midi.h
+ *
+ * Wed Sep 15 15:43:53 CEST 2010
+ * Copyright 2010 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 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.
+ */
+#ifndef __DRUMGIZMO_MIDI_H__
+#define __DRUMGIZMO_MIDI_H__
+
+typedef unsigned int midi_note_t;
+typedef unsigned int midi_velocity_t;
+
+#endif/*__DRUMGIZMO_MIDI_H__*/
diff --git a/src/midimap.h b/src/midimap.h
new file mode 100644
index 0000000..6679d98
--- /dev/null
+++ b/src/midimap.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * midimap.h
+ *
+ * Wed Sep 15 15:44:48 CEST 2010
+ * Copyright 2010 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 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.
+ */
+#ifndef __DRUMGIZMO_MIDIMAP_H__
+#define __DRUMGIZMO_MIDIMAP_H__
+
+#include "midi.h"
+
+class MidiMap {
+public:
+ midi_note_t note;
+ midi_velocity_t from;
+ midi_velocity_t to;
+ std::string instrument;
+ // float gain; // TODO: Add this to gain the entire instrument.
+};
+
+//typedef std::vector< MidiMap > MidiMaps;
+
+#endif/*__DRUMGIZMO_MIDIMAP_H__*/
diff --git a/src/midimapper.cc b/src/midimapper.cc
index 6bf38c7..243c22e 100644
--- a/src/midimapper.cc
+++ b/src/midimapper.cc
@@ -26,6 +26,8 @@
*/
#include "midimapper.h"
+#include <stdio.h>
+
#define NOTE_ON 0x9
MidiMapper::MidiMapper(DrumKit *drumkit)
@@ -63,11 +65,11 @@ MidiMapper::MidiMapper(DrumKit *drumkit)
Sample *MidiMapper::map(jack_midi_event_t event)
{
Sample *sample = NULL;
-
+#if 0
// printf("m"); fflush(stdout);
if(event.size != 3) return NULL;
- if(event.buffer[0] & NOTE_ON != NOTE_ON) return NULL;
+ if((event.buffer[0] & NOTE_ON) != NOTE_ON) return NULL;
int key = event.buffer[1];
int velocity = event.buffer[2];
@@ -82,15 +84,16 @@ Sample *MidiMapper::map(jack_midi_event_t event)
}
printf("]\n");
*/
+
if(drumkit->instruments.find(key) == drumkit->instruments.end()) {
printf("Unknown instrument %d\n", key);
return NULL;
}
-
+
Velocity *v = drumkit->instruments[key]->getVelocity(velocity);
if(!v) return NULL;
sample = v->getSample();
-
+#endif
return sample;
}
diff --git a/src/midiplayer.cc b/src/midiplayer.cc
index b55b225..9864d1c 100644
--- a/src/midiplayer.cc
+++ b/src/midiplayer.cc
@@ -108,7 +108,7 @@ static int inst[] = { 35, 36, 38, 46, 41, 43, 45, 47, 49, 57, 51 };
static int inst[] = { 51, 49, 57 };
#endif
-#if 1 // Toms
+#if 0 // Toms
#define NUM_INST 4
static int inst[] = { 41, 43, 45, 47 };
#endif
diff --git a/src/mutex.cc b/src/mutex.cc
new file mode 100644
index 0000000..ec0d0e8
--- /dev/null
+++ b/src/mutex.cc
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * mutex.cc
+ *
+ * Thu Nov 12 10:51:32 CET 2009
+ * Copyright 2009 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Pracro.
+ *
+ * Pracro 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.
+ *
+ * Pracro 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 Pracro; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "mutex.h"
+
+Mutex::Mutex()
+{
+ pthread_mutex_init (&mutex, NULL);
+}
+
+Mutex::~Mutex()
+{
+ pthread_mutex_destroy(&mutex);
+}
+
+bool Mutex::trylock()
+{
+ return pthread_mutex_trylock(&mutex) == 0;
+}
+
+void Mutex::lock()
+{
+ pthread_mutex_lock(&mutex);
+}
+
+void Mutex::unlock()
+{
+ pthread_mutex_unlock(&mutex);
+}
+
+
+MutexAutolock::MutexAutolock(Mutex &m)
+ : mutex(m)
+{
+ mutex.lock();
+}
+
+MutexAutolock::~MutexAutolock()
+{
+ mutex.unlock();
+}
+
+#ifdef TEST_MUTEX
+//deps:
+//cflags: $(PTHREAD_CFLAGS)
+//libs: $(PTHREAD_LIBS)
+#include <test.h>
+
+#include <unistd.h>
+
+volatile int cnt = 0;
+
+static void* thread_run(void *data)
+{
+ Mutex *mutex = (Mutex*)data;
+ mutex->lock();
+ cnt++;
+ mutex->unlock();
+ return NULL;
+}
+
+TEST_BEGIN;
+
+Mutex mutex;
+
+mutex.lock();
+TEST_FALSE(mutex.trylock(), "Testing if trylock works negative.");
+mutex.unlock();
+TEST_TRUE(mutex.trylock(), "Testing if trylock works positive.");
+mutex.unlock();
+
+mutex.lock();
+
+pthread_attr_t attr;
+pthread_t tid;
+pthread_attr_init(&attr);
+pthread_create(&tid, &attr, thread_run, &mutex);
+
+sleep(1);
+TEST_EQUAL_INT(cnt, 0, "Testing if lock prevent cnt from increasing.");
+mutex.unlock();
+
+sleep(1);
+TEST_EQUAL_INT(cnt, 1, "Testing if unlock makes cnt increase.");
+
+pthread_join(tid, NULL);
+pthread_attr_destroy(&attr);
+
+{
+ TEST_TRUE(mutex.trylock(), "Testing if autolock has not yet locked the mutex.");
+ mutex.unlock();
+ MutexAutolock mlock(mutex);
+ TEST_FALSE(mutex.trylock(), "Testing if autolock worked.");
+}
+
+TEST_TRUE(mutex.trylock(), "Testing if autolock has released the lock on the mutex.");
+mutex.unlock();
+
+TEST_END;
+
+#endif/*TEST_MUTEX*/
diff --git a/src/mutex.h b/src/mutex.h
new file mode 100644
index 0000000..cf052ad
--- /dev/null
+++ b/src/mutex.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * mutex.h
+ *
+ * Thu Nov 12 10:51:32 CET 2009
+ * Copyright 2009 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Pracro.
+ *
+ * Pracro 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.
+ *
+ * Pracro 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 Pracro; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __PRACRO_MUTEX_H__
+#define __PRACRO_MUTEX_H__
+
+#include <pthread.h>
+
+class Mutex {
+public:
+ Mutex();
+ ~Mutex();
+
+ bool trylock();
+ void lock();
+ void unlock();
+
+private:
+ pthread_mutex_t mutex;
+};
+
+class MutexAutolock {
+public:
+ MutexAutolock(Mutex &mutex);
+ ~MutexAutolock();
+
+private:
+ Mutex &mutex;
+};
+
+#endif/*__PRACRO_MUTEX_H__*/
diff --git a/src/rangemap.h b/src/rangemap.h
new file mode 100644
index 0000000..d863052
--- /dev/null
+++ b/src/rangemap.h
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * rangemap.h
+ *
+ * Wed Sep 22 19:17:49 CEST 2010
+ * Copyright 2010 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 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.
+ */
+#ifndef __DRUMGIZMO_RANGEMAP_H__
+#define __DRUMGIZMO_RANGEMAP_H__
+
+#include <vector>
+#include <map>
+
+template<typename T1, typename T2>
+class RangeMap {
+public:
+ void insert(T1 from, T1 to, T2 value);
+ std::vector<T2> get(T1 from, T1 to);
+ std::vector<T2> get(T1 at);
+
+private:
+ std::multimap<std::pair<T1, T1>, T2> values;
+};
+
+template<typename T1, typename T2>
+void RangeMap<T1, T2>::insert(T1 from, T1 to, T2 value)
+{
+ if(from < to) values.insert(std::make_pair(std::make_pair(from, to), value));
+ else values.insert(std::make_pair(std::make_pair(to, from), value));
+}
+
+template<typename T1, typename T2>
+std::vector<T2> RangeMap<T1, T2>::get(T1 from, T1 to)
+{
+ std::vector<T2> res;
+
+ typename std::multimap<std::pair<T1, T1>, T2>::iterator i = values.begin();
+ while(i != values.end()) {
+ T1 a = i->first.first;
+ T1 b = i->first.second;
+ if(
+ (from >= a && to <= b) || // inside
+ (from <= a && to >= b) || // containing
+ (from <= a && to >= a && to <= b) || // overlapping lower
+ (from >= a && from <= b && to >= b) // overlapping upper
+ )
+ res.push_back(i->second);
+ i++;
+ }
+
+ return res;
+}
+
+template<typename T1, typename T2>
+std::vector<T2> RangeMap<T1, T2>::get(T1 at)
+{
+ std::vector<T2> res;
+
+ typename std::multimap<std::pair<T1, T1>, T2>::iterator i = values.begin();
+ while(i != values.end()) {
+ T1 a = i->first.first;
+ T1 b = i->first.second;
+ if(at >= a && at <= b)
+ res.push_back(i->second);
+ i++;
+ }
+
+ return res;
+}
+
+
+#endif/*__DRUMGIZMO_RANGEMAP_H__*/
diff --git a/src/sample.cc b/src/sample.cc
index 5a06331..f0bb099 100644
--- a/src/sample.cc
+++ b/src/sample.cc
@@ -39,3 +39,35 @@ Sample::Sample(std::string name)
Sample::~Sample()
{
}
+
+void Sample::addAudioFile(Channel *c, AudioFile *a)
+{
+ audiofiles[c] = a;
+}
+
+AudioFile *Sample::getAudioFile(Channel *c)
+{
+ if(audiofiles.find(c) == audiofiles.end()) return NULL;
+ return audiofiles[c];
+}
+
+#ifdef TEST_SAMPLE
+//deps: channel.cc audiofile.cc
+//cflags: $(SNDFILE_CFLAGS)
+//libs: $(SNDFILE_LIBS)
+#include "test.h"
+
+TEST_BEGIN;
+
+Sample s;
+InstrumentChannel c;
+InstrumentChannel c2;
+AudioFile a("test");
+
+s.addAudioFile(&c, &a);
+TEST_EQUAL(s.getAudioFile(&c), &a, "?");
+TEST_EQUAL(s.getAudioFile(&c2), NULL, "?");
+
+TEST_END;
+
+#endif/*TEST_SAMPLE*/
diff --git a/src/sample.h b/src/sample.h
index e3acff1..c4d82f8 100644
--- a/src/sample.h
+++ b/src/sample.h
@@ -29,18 +29,32 @@
#include <map>
#include <string>
+
+#include "channel.h"
#include "audiofile.h"
-typedef std::map< std::string, AudioFile* > AudioFiles;
+typedef std::map< Channel*, AudioFile* > AudioFiles;
class Sample {
public:
- Sample(std::string name);
+ Sample(std::string name = "");
~Sample();
- AudioFiles audiofiles;
+ void addAudioFile(InstrumentChannel *c, AudioFile *a);
+ AudioFile *getAudioFile(InstrumentChannel *c);
+private:
std::string name;
+ AudioFiles audiofiles;
};
+/*
+ * <sample name="kick-r-1">
+ * <audiofile channel="Alesis-3" file="samples/1-kick-r-Alesis-3.wav"/>
+ * <audiofile channel="Amb L-3" file="samples/1-kick-r-Amb L-3.wav"/>
+ * <audiofile channel="Amb R-3" file="samples/1-kick-r-Amb R-3.wav"/>
+ * <audiofile channel="Kick L-3" file="samples/1-kick-r-Kick L-3.wav"/>
+ * <audiofile channel="Kick R-3" file="samples/1-kick-r-Kick R-3.wav"/>
+ * </sample>
+ */
#endif/*__DRUMGIZMO_SAMPLE_H__*/
diff --git a/src/saxparser.cc b/src/saxparser.cc
index 19c6142..1090ef3 100644
--- a/src/saxparser.cc
+++ b/src/saxparser.cc
@@ -25,6 +25,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
#include "saxparser.h"
+
+#include <stdio.h>
#include <string.h>
static void character_hndl(void *p, const XML_Char *s, int len)
@@ -90,8 +92,13 @@ int SAXParser::parse()
do {
len = readData(buf, sizeof(buf) - 1);
- if (! XML_Parse(p, buf, len, len == 0)) {
- parseError(buf, len, XML_ErrorString(XML_GetErrorCode(p)), (int)XML_GetCurrentLineNumber(p));
+ if(len == -1) {
+ parseError((char*)"", 0, "Could not read data", 0);
+ return 1;
+ }
+ if(!XML_Parse(p, buf, len, len == 0)) {
+ parseError(buf, len, XML_ErrorString(XML_GetErrorCode(p)),
+ (int)XML_GetCurrentLineNumber(p));
return 1;
}
diff --git a/src/saxparser.h b/src/saxparser.h
index 48109f6..8415b6b 100644
--- a/src/saxparser.h
+++ b/src/saxparser.h
@@ -39,7 +39,8 @@ public:
int parse();
virtual void characterData(std::string &data) {}
- virtual void startTag(std::string name, std::map< std::string, std::string> attributes) {}
+ virtual void startTag(std::string name,
+ std::map< std::string, std::string> attributes) {}
virtual void endTag(std::string name) {}
virtual void parseError(char *buf, size_t len, std::string error, int lineno);
diff --git a/src/thread.cc b/src/thread.cc
new file mode 100644
index 0000000..605cf54
--- /dev/null
+++ b/src/thread.cc
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * thread.cc
+ *
+ * Sun Oct 31 12:12:20 CET 2004
+ * Copyright 2004 Bent Bisballe
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of MIaV.
+ *
+ * MIaV 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.
+ *
+ * MIaV 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 MIaV; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "thread.h"
+
+static void* thread_run(void *data) {
+ Thread *t = (Thread*)data;
+ t->thread_main();
+ return NULL;
+}
+
+Thread::Thread()
+{
+}
+
+Thread::~Thread()
+{
+}
+
+void Thread::exec()
+{
+ pthread_attr_init(&attr);
+
+ pthread_create(&tid, &attr, thread_run, this);
+}
+
+void Thread::wait_stop()
+{
+ pthread_join(tid, NULL);
+}
diff --git a/src/thread.h b/src/thread.h
new file mode 100644
index 0000000..ebce385
--- /dev/null
+++ b/src/thread.h
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * thread.h
+ *
+ * Sun Oct 31 12:12:20 CET 2004
+ * Copyright 2004 Bent Bisballe
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of MIaV.
+ *
+ * MIaV 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.
+ *
+ * MIaV 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 MIaV; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __THREAD_H__
+#define __THREAD_H__
+
+#include <pthread.h>
+#include <semaphore.h>
+
+class Thread {
+public:
+ Thread();
+ virtual ~Thread();
+
+ void exec();
+ void wait_stop();
+
+ virtual void thread_main() = 0;
+
+private:
+ pthread_attr_t attr;
+ pthread_t tid;
+};
+
+#endif/*__THREAD_H__*/