diff options
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(¶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 <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__*/ | 
