From e190d38057892b69246391841b234a368bc2b4ad Mon Sep 17 00:00:00 2001 From: deva Date: Tue, 1 Mar 2011 19:19:02 +0000 Subject: MAJOR rewrite of the internals. New input/output 'plugin' system. Still a lot missing. --- src/Makefile.am | 47 ++++++- src/audio.h | 40 ++++++ src/audiofile.cc | 61 +++------ src/audiofile.h | 9 +- src/audioinputengine.cc | 57 ++++++++ src/audioinputengine.h | 46 +++++++ src/audioinputenginejackmidi.cc | 116 ++++++++++++++++ src/audioinputenginejackmidi.h | 55 ++++++++ src/audioinputenginemidifile.cc | 44 ++++++ src/audioinputenginemidifile.h | 41 ++++++ src/audiooutputengine.cc | 42 ++++++ src/audiooutputengine.h | 51 +++++++ src/audiooutputenginealsa.cc | 194 ++++++++++++++++++++++++++ src/audiooutputenginealsa.h | 51 +++++++ src/audiooutputenginejack.cc | 106 +++++++++++++++ src/audiooutputenginejack.h | 59 ++++++++ src/audiooutputenginesndfile.cc | 84 ++++++++++++ src/audiooutputenginesndfile.h | 51 +++++++ src/beatmapper.cc | 2 + src/channel.cc | 26 +++- src/channel.h | 12 +- src/channelmixer.cc | 110 +++++++++++++++ src/channelmixer.h | 58 ++++++++ src/cli.cc | 189 +++++++++++++++++++++++++ src/cli.h | 29 ++++ src/drumgizmo.cc | 295 ++++++++++++++++++++++++++-------------- src/drumgizmo.h | 85 ++++++++++++ src/drumkit.h | 13 +- src/drumkitparser.cc | 78 +++-------- src/drumkitparser.h | 16 +-- src/event.cc | 28 ++-- src/event.h | 99 ++++++++++++-- src/instrument.cc | 59 ++++++-- src/instrument.h | 59 ++++++-- src/midi.h | 33 +++++ src/midimap.h | 43 ++++++ src/midimapper.cc | 11 +- src/midiplayer.cc | 2 +- src/mutex.cc | 125 +++++++++++++++++ src/mutex.h | 55 ++++++++ src/rangemap.h | 91 +++++++++++++ src/sample.cc | 32 +++++ src/sample.h | 20 ++- src/saxparser.cc | 11 +- src/saxparser.h | 3 +- src/thread.cc | 53 ++++++++ src/thread.h | 48 +++++++ 47 files changed, 2541 insertions(+), 298 deletions(-) create mode 100644 src/audio.h create mode 100644 src/audioinputengine.cc create mode 100644 src/audioinputengine.h create mode 100644 src/audioinputenginejackmidi.cc create mode 100644 src/audioinputenginejackmidi.h create mode 100644 src/audioinputenginemidifile.cc create mode 100644 src/audioinputenginemidifile.h create mode 100644 src/audiooutputengine.cc create mode 100644 src/audiooutputengine.h create mode 100644 src/audiooutputenginealsa.cc create mode 100644 src/audiooutputenginealsa.h create mode 100644 src/audiooutputenginejack.cc create mode 100644 src/audiooutputenginejack.h create mode 100644 src/audiooutputenginesndfile.cc create mode 100644 src/audiooutputenginesndfile.h create mode 100644 src/channelmixer.cc create mode 100644 src/channelmixer.h create mode 100644 src/cli.cc create mode 100644 src/cli.h create mode 100644 src/drumgizmo.h create mode 100644 src/midi.h create mode 100644 src/midimap.h create mode 100644 src/mutex.cc create mode 100644 src/mutex.h create mode 100644 src/rangemap.h create mode 100644 src/thread.cc create mode 100644 src/thread.h (limited to 'src') 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 -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 #include +#include + +#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 + +#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 +#include + +#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 + +#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 +#include +#include + +#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(¶ms); + // 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 + +#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 +#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 + +#include + +#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 + +#include + +#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 + #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 #include -#include + +#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::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 + +#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 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 +#include + +#include +#include +#include + +#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 .\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 -#include -#include "jackclient.h" +#include "drumgizmo.h" + +#include +#include + #include "drumkitparser.h" -#include "midiplayer.h" -#include - -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 .\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 +#include + +#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 #include -#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 +#include + #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(time, event)); } -Event::~Event() +Event *EventQueue::take(timepos_t time) { + MutexAutolock lock(mutex); + std::multimap::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 +#include +#include +#include +#include -#include -#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 + +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 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 #include -#include - -#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 samples; }; +typedef std::map< std::string, Instrument > Instruments; + +/* + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + #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 + #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 + +#include + +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 + +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 +#include + +template +class RangeMap { +public: + void insert(T1 from, T1 to, T2 value); + std::vector get(T1 from, T1 to); + std::vector get(T1 at); + +private: + std::multimap, T2> values; +}; + +template +void RangeMap::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 +std::vector RangeMap::get(T1 from, T1 to) +{ + std::vector res; + + typename std::multimap, 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 +std::vector RangeMap::get(T1 at) +{ + std::vector res; + + typename std::multimap, 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 #include + +#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; }; +/* + * + * + * + * + * + * + * + */ #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 #include 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 +#include + +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__*/ -- cgit v1.2.3