diff options
| -rw-r--r-- | src/audiofile.cc | 279 | ||||
| -rw-r--r-- | src/audiofile.h | 74 | ||||
| -rw-r--r-- | src/drumgizmo.cc | 1264 | ||||
| -rw-r--r-- | src/drumgizmo.h | 62 | ||||
| -rw-r--r-- | src/drumkitloader.cc | 231 | ||||
| -rw-r--r-- | src/drumkitloader.h | 87 | ||||
| -rw-r--r-- | vst/drumgizmo_vst.cc | 129 | 
7 files changed, 958 insertions, 1168 deletions
| diff --git a/src/audiofile.cc b/src/audiofile.cc index 5ceff59..e9b5976 100644 --- a/src/audiofile.cc +++ b/src/audiofile.cc @@ -38,225 +38,116 @@  #include "configuration.h" -AudioFile::AudioFile(std::string filename, int filechannel) +AudioFile::AudioFile(const std::string& filename, int filechannel)  { -  is_loaded = false; -  this->filename = filename; -  this->filechannel = filechannel; +	is_loaded = false; +	this->filename = filename; +	this->filechannel = filechannel; -  data = NULL; -  size = 0; +	data = nullptr; +	size = 0; -#ifdef LAZYLOAD -  preloaded_data = NULL; -#endif/*LAZYLOAD*/ - -  magic = this; +	magic = this;  }  AudioFile::~AudioFile()  { -  magic = NULL; -  unload(); +	magic = nullptr; +	unload();  }  bool AudioFile::isValid()  { -  return this == magic; +	return this == magic;  }  void AudioFile::unload()  { -  // Make sure we don't unload the object while loading it... -  MutexAutolock l(mutex); +	// Make sure we don't unload the object while loading it... +	MutexAutolock l(mutex); -  is_loaded = false; +	is_loaded = false; -#ifdef LAZYLOAD -  if(data == preloaded_data) { -    delete[] data; -    data = NULL; -    size = 0; -  } else { -    size = 0; -    delete[] data; -    data = NULL; -    delete preloaded_data; -    preloaded_data = NULL; -  } -#else -  delete[] data; -  data = NULL; -  size = 0; -#endif/*LAZYLOAD*/ +	delete[] data; +	data = nullptr; +	size = 0;  }  #define	BUFFER_SIZE	4092  void AudioFile::load(int num_samples)  { -  // Make sure we don't unload the object while loading it... -  MutexAutolock l(mutex); - - /* -  Lazy load of drum kits -  init(); -  return; -  */ - -  if(data) return; - -  SF_INFO sf_info; -  SNDFILE *fh = sf_open(filename.c_str(), SFM_READ, &sf_info); -  if(!fh) { -    ERR(audiofile,"SNDFILE Error (%s): %s\n", -        filename.c_str(), sf_strerror(fh)); -    return; -  } -  -  if(num_samples == ALL_SAMPLES) { -    num_samples = sf_info.frames; -  } - -  size = sf_info.frames; -  preloadedsize = sf_info.frames; - -  if(preloadedsize > (size_t)num_samples) { -    preloadedsize = num_samples; -  } - -  sample_t* data = new sample_t[preloadedsize]; -  if(sf_info.channels == 1) { -    preloadedsize = sf_read_float(fh, data, preloadedsize); -  } else { -    // check filechannel exists -    if(filechannel >= sf_info.channels) { -        filechannel = sf_info.channels - 1; -    } -    sample_t buffer[BUFFER_SIZE]; -    int readsize = BUFFER_SIZE / sf_info.channels; -    int totalread = 0; -    int read; -    do { -      read = sf_readf_float(fh, buffer, readsize); -      for (int i = 0; (i < read) && (totalread < num_samples); i++) { -        data[totalread++] = buffer[i * sf_info.channels + filechannel]; -      } -    } while( (read > 0) && -             (totalread < (int)preloadedsize) && -             (totalread < num_samples) ); -    // set data size to total bytes read -    preloadedsize = totalread; -  } - -  DEBUG(audiofile,"Loaded %d samples %p\n", (int)preloadedsize, this); -   -  sf_close(fh); - -  this->data = data; -  is_loaded = true; - -  //DEBUG(audiofile, "Loading of %s completed.\n", filename.c_str()); +	// Make sure we don't unload the object while loading it... +	MutexAutolock l(mutex); + +	if(data) +	{ +		return; +	} + +	SF_INFO sf_info; +	SNDFILE *fh = sf_open(filename.c_str(), SFM_READ, &sf_info); +	if(!fh) +	{ +		ERR(audiofile,"SNDFILE Error (%s): %s\n", +		    filename.c_str(), sf_strerror(fh)); +		return; +	} + +	if(num_samples == ALL_SAMPLES) +	{ +		num_samples = sf_info.frames; +	} + +	size = sf_info.frames; +	preloadedsize = sf_info.frames; + +	if(preloadedsize > (size_t)num_samples) +	{ +		preloadedsize = num_samples; +	} + +	sample_t* data = new sample_t[preloadedsize]; +	if(sf_info.channels == 1) +	{ +		preloadedsize = sf_read_float(fh, data, preloadedsize); +	} +	else +	{ +		// check filechannel exists +		if(filechannel >= sf_info.channels) +		{ +			filechannel = sf_info.channels - 1; +		} + +		sample_t buffer[BUFFER_SIZE]; +		int readsize = BUFFER_SIZE / sf_info.channels; +		int totalread = 0; +		int read; + +		do +		{ +	    read = sf_readf_float(fh, buffer, readsize); +	    for(int i = 0; (i < read) && (totalread < num_samples); ++i) +	    { +		    data[totalread++] = buffer[i * sf_info.channels + filechannel]; +	    } +		} +		while( (read > 0) && +		       (totalread < (int)preloadedsize) && +		       (totalread < num_samples) ); + +		// set data size to total bytes read +		preloadedsize = totalread; +	} + +	sf_close(fh); + +	this->data = data; +	is_loaded = true;  }  bool AudioFile::isLoaded()  { -  return is_loaded; -} - -#ifdef LAZYLOAD -#define SIZE 512*4  -void AudioFile::init() -{ -  //DEBUG(audiofile,"Initializing %p\n", this); -  if(data) {  -    //DEBUG(audiofile,"\t already initialized\n"); -    return; -  } - -  SF_INFO sf_info; -  SNDFILE *fh = sf_open(filename.c_str(), SFM_READ, &sf_info); -  if(!fh) { -    ERR(audiofile,"SNDFILE Error (%s): %s\n", -        filename.c_str(), sf_strerror(fh)); -    return; -  } -  -  int size = SIZE; - -  sample_t* data = new sample_t[size]; -   -  size = sf_read_float(fh, data, size);  - -  //DEBUG(audiofile,"Lazy loaded %d samples\n", size); -  sf_close(fh); - -  mutex.lock(); -  this->data = data; -  this->size = size; -  this->preloaded_data = data; -  this->is_loaded = true; -  mutex.unlock(); -} - -void AudioFile::loadNext() -{ -  if(this->data != this->preloaded_data) { -    //DEBUG(audiofile,"Already completely loaded %p\n", this); -    return; -  } - -  SF_INFO sf_info; -  SNDFILE *fh = sf_open(filename.c_str(), SFM_READ, &sf_info); -  if(!fh) { -    ERR(audiofile,"SNDFILE Error (%s): %s\n", -        filename.c_str(), sf_strerror(fh)); -    return; -  } - -  int r; -//  int size_accum = 0; -  sample_t* data = new sample_t[sf_info.frames]; -  memcpy(data, this->preloaded_data, this->size * sizeof(sample_t)); -  this->data = data; -  sf_seek(fh, this->size, SEEK_SET); -//  sample_t* data_buf = new sample_t[SIZE]; -  while(this->size < sf_info.frames) { -    //DEBUG(audiofile,"Accumulated %d of %llu\n", size_accum, sf_info.frames); -    //if( (r = sf_read_float(fh, data_buf, SIZE)) < 0) { -    if( (r = sf_read_float(fh, &data[this->size], SIZE)) < 0) { -      ERR(audiofile,"Error reading sound file\n"); -      break; -    } -    //size_accum += r; -    //memcpy(data+size_accum, data_buf, sizeof(sample_t) * r); -    this->size += r; -  } -  //delete data_buf; -   -  //DEBUG(audiofile,"Finished loading %d samples %p\n", size, this); -  sf_close(fh); - -  //mutex.lock(); -  //this->data = data; -  //this->size = size; -  //mutex.unlock(); -} - -void AudioFile::reset() -{ -  //DEBUG(audiofile,"Resetting audio file %p\n", this); -  if(this->data == this->preloaded_data) { -    //DEBUG(audiofile,"\tNot completely loaded - skipping %p\n", this); -    return; -  } - -  mutex.lock(); -  volatile sample_t* old_data = data; -  this->size = SIZE; -  this->data = this->preloaded_data; -  //DEBUG(audiofile,"Deleting data %p\n", this); -  delete old_data;  -  mutex.unlock(); +	return is_loaded;  } -#endif diff --git a/src/audiofile.h b/src/audiofile.h index aefb8d6..3ca8b97 100644 --- a/src/audiofile.h +++ b/src/audiofile.h @@ -24,8 +24,7 @@   *  along with DrumGizmo; if not, write to the Free Software   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.   */ -#ifndef __DRUMGIZMO_AUDIOFILE_H__ -#define __DRUMGIZMO_AUDIOFILE_H__ +#pragma once  #include <string>  #include <map> @@ -36,74 +35,31 @@  #include "mutex.h"  #include "audio.h" -/* -  Plan for lazy loading of audio (Brainstorming) -    * Encapsulate data array? -      - Speed issues? -      - Other suggestion -        * Trigger on read begin and read done -          - readnext(instrument)? -        * size_t current latest loaded sample -        * run in own thread? threads in drumgizmo?? -          - Add soundfile-loader-class which run in its own thread -    * Add pre-loading constant -    * Pointer to pos in audio stream (maybe just last position read) -    * Strategy for how to handle pre-loading of remaining file -      - Is it acceptable only to handle sequential reading of data (no random access)? - -   Thread A                                                  Thread B - -   :preload constant (user defined) -   :speed modifier constant (in which time must  -    sample n be loaded relative to trigger time)  -  ----------                                                           ------ -  | Loader |   <------- Trigger load of InstrumentSample n  --------- | DG   |  -  ----------                                                           ------ -    Load                  (int- right most loaded sample --> If current sample pos loaded -      |            --------- |                                   | -    Wave Into --> | SndFile | <----- Read data (directly from array) -                   ---------   -*/ - -//#define LAZYLOAD -  #define ALL_SAMPLES -1  class AudioFile {  public: -  AudioFile(std::string filename, int filechannel); -  ~AudioFile(); - -  void load(int num_samples = ALL_SAMPLES); -  void unload(); +	AudioFile(const std::string& filename, int filechannel); +	~AudioFile(); -  bool isLoaded(); +	void load(int num_samples = ALL_SAMPLES); +	void unload(); -  volatile size_t size; // Full size of the file -  volatile size_t preloadedsize; // Number of samples preloaded (in data) -  sample_t *data; +	bool isLoaded(); -  std::string filename; +	volatile size_t size{0}; // Full size of the file +	volatile size_t preloadedsize{0}; // Number of samples preloaded (in data) +	sample_t *data{nullptr}; -#ifdef LAZYLOAD -//  SF_INFO sf_info; -//  SNDFILE *fh; -//  bool completely_loaded; -  void init(); -  void reset(); -  void loadNext(); -  sample_t* preloaded_data;  -#endif/*LAZYLOAD*/ +	std::string filename; -  bool isValid(); +	bool isValid(); -  Mutex mutex; +	Mutex mutex; -  int filechannel; +	int filechannel;  private: -  void *magic; -  volatile bool is_loaded; +	void *magic; +	volatile bool is_loaded;  }; - -#endif/*__DRUMGIZMO_AUDIOFILE_H__*/ diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index 3dc1306..26b8e65 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -46,346 +46,403 @@  #include "nolocale.h"  DrumGizmo::DrumGizmo(AudioOutputEngine *o, AudioInputEngine *i) -  : MessageReceiver(MSGRCV_ENGINE) -  , loader() -  , oe(o) -  , ie(i) -  , framesize(0) -  , freewheel(false) +	: MessageReceiver(MSGRCV_ENGINE) +	, loader() +	, oe(o) +	, ie(i) +	, framesize(0) +	, freewheel(false)  { -  is_stopping = false; -  audioCache.init(1000); // start thread +	is_stopping = false; +	audioCache.init(1000); // start thread  }  DrumGizmo::~DrumGizmo()  { -  audioCache.deinit(); // stop thread +	audioCache.deinit(); // stop thread  }  bool DrumGizmo::loadkit(std::string file)  { -  if(file == "") return 1; +	if(file == "") +	{ +		return 1; +	} -  DEBUG(drumgizmo, "loadkit(%s)\n", file.c_str()); +	DEBUG(drumgizmo, "loadkit(%s)\n", file.c_str()); -  // Remove all queue AudioFiles from loader before we actually delete them. -  loader.skip(); +	// Remove all queue AudioFiles from loader before we actually delete them. +	loader.skip(); -  // Delete all Channels, Instruments, Samples and AudioFiles. -  kit.clear(); +	// Delete all Channels, Instruments, Samples and AudioFiles. +	kit.clear(); -  DrumKitParser parser(file, kit); -  if(parser.parse()) { -    ERR(drumgizmo, "Drumkit parser failed: %s\n", file.c_str()); -    return false; -  } +	DrumKitParser parser(file, kit); +	if(parser.parse()) +	{ +		ERR(drumgizmo, "Drumkit parser failed: %s\n", file.c_str()); +		return false; +	} -  loader.loadKit(&kit); +	loader.loadKit(&kit);  #ifdef WITH_RESAMPLER -  for(int i = 0; i < MAX_NUM_CHANNELS; i++) { -    resampler[i].setup(kit.samplerate(), Conf::samplerate); -  } +	for(int i = 0; i < MAX_NUM_CHANNELS; ++i) +	{ +		resampler[i].setup(kit.samplerate(), Conf::samplerate); +	}  #endif/*WITH_RESAMPLER*/ -  DEBUG(loadkit, "loadkit: Success\n"); +	DEBUG(loadkit, "loadkit: Success\n"); -  return true; +	return true;  }  bool DrumGizmo::init()  { -  if(!ie->init(kit.instruments)) return false; -  if(!oe->init(kit.channels)) return false; +	if(!ie->init(kit.instruments)) +	{ +		return false; +	} -  return true; +	if(!oe->init(kit.channels)) +	{ +		return false; +	} + +	return true;  }  void DrumGizmo::handleMessage(Message *msg)  { -  DEBUG(msg, "got message."); -  switch(msg->type()) { -  case Message::LoadDrumKit: -    { -      DEBUG(msg, "got LoadDrumKitMessage message."); -      LoadDrumKitMessage *m = (LoadDrumKitMessage*)msg; -      loadkit(m->drumkitfile); -      //init(true); -    } -    break; -  case Message::LoadMidimap: -    DEBUG(msg, "got LoadMidimapMessage message."); -    if(!ie->isMidiEngine()) break; -    { -      AudioInputEngineMidi *aim = (AudioInputEngineMidi*)ie; -      LoadMidimapMessage *m = (LoadMidimapMessage*)msg; -      bool ret = aim->loadMidiMap(m->midimapfile, kit.instruments); -       -      LoadStatusMessageMidimap *ls = new LoadStatusMessageMidimap(); -      ls->success = ret; -      msghandler.sendMessage(MSGRCV_UI, ls); -    } -    break; -  case Message::EngineSettingsMessage: -    { -      bool mmap_loaded = false; -      std::string mmapfile; -      if(ie->isMidiEngine()) { -        AudioInputEngineMidi *aim = (AudioInputEngineMidi*)ie; -        mmapfile = aim->midimapFile(); -        mmap_loaded = aim->isValid(); -      } -       -      EngineSettingsMessage *msg = new EngineSettingsMessage(); -      msg->midimapfile = mmapfile; -      msg->midimap_loaded = mmap_loaded; -      msg->drumkitfile = kit.file(); -      msg->drumkit_loaded = loader.isDone(); -      msg->enable_velocity_modifier = Conf::enable_velocity_modifier; -      msg->velocity_modifier_falloff = Conf::velocity_modifier_falloff; -      msg->velocity_modifier_weight = Conf::velocity_modifier_weight; -      msg->enable_velocity_randomiser = Conf::enable_velocity_randomiser; -      msg->velocity_randomiser_weight = Conf::velocity_randomiser_weight; -      msghandler.sendMessage(MSGRCV_UI, msg); -    } -    break; -  case Message::ChangeSettingMessage: -    { -      ChangeSettingMessage *ch = (ChangeSettingMessage*)msg; -      switch(ch->name) { -      case ChangeSettingMessage::enable_velocity_modifier: -        Conf::enable_velocity_modifier = ch->value; -        break; -      case ChangeSettingMessage::velocity_modifier_weight: -        Conf::velocity_modifier_weight = ch->value; -        break; -      case ChangeSettingMessage::velocity_modifier_falloff: -        Conf::velocity_modifier_falloff = ch->value; -        break; -      } -    } -    break; -  default: -    break; -  } +	DEBUG(msg, "got message."); +	switch(msg->type()) { +	case Message::LoadDrumKit: +		{ +			DEBUG(msg, "got LoadDrumKitMessage message."); +			LoadDrumKitMessage *m = (LoadDrumKitMessage*)msg; +			loadkit(m->drumkitfile); +			//init(true); +		} +		break; +	case Message::LoadMidimap: +		DEBUG(msg, "got LoadMidimapMessage message."); +		if(!ie->isMidiEngine()) +		{ +			break; +		} +		{ +			AudioInputEngineMidi *aim = (AudioInputEngineMidi*)ie; +			LoadMidimapMessage *m = (LoadMidimapMessage*)msg; +			bool ret = aim->loadMidiMap(m->midimapfile, kit.instruments); + +			LoadStatusMessageMidimap *ls = new LoadStatusMessageMidimap(); +			ls->success = ret; +			msghandler.sendMessage(MSGRCV_UI, ls); +		} +		break; +	case Message::EngineSettingsMessage: +		{ +			bool mmap_loaded = false; +			std::string mmapfile; +			if(ie->isMidiEngine()) +			{ +				AudioInputEngineMidi *aim = (AudioInputEngineMidi*)ie; +				mmapfile = aim->midimapFile(); +				mmap_loaded = aim->isValid(); +			} + +			EngineSettingsMessage *msg = new EngineSettingsMessage(); +			msg->midimapfile = mmapfile; +			msg->midimap_loaded = mmap_loaded; +			msg->drumkitfile = kit.file(); +			msg->drumkit_loaded = loader.isDone(); +			msg->enable_velocity_modifier = Conf::enable_velocity_modifier; +			msg->velocity_modifier_falloff = Conf::velocity_modifier_falloff; +			msg->velocity_modifier_weight = Conf::velocity_modifier_weight; +			msg->enable_velocity_randomiser = Conf::enable_velocity_randomiser; +			msg->velocity_randomiser_weight = Conf::velocity_randomiser_weight; +			msghandler.sendMessage(MSGRCV_UI, msg); +		} +		break; +	case Message::ChangeSettingMessage: +		{ +			ChangeSettingMessage *ch = (ChangeSettingMessage*)msg; +			switch(ch->name) { +			case ChangeSettingMessage::enable_velocity_modifier: +				Conf::enable_velocity_modifier = ch->value; +				break; +			case ChangeSettingMessage::velocity_modifier_weight: +				Conf::velocity_modifier_weight = ch->value; +				break; +			case ChangeSettingMessage::velocity_modifier_falloff: +				Conf::velocity_modifier_falloff = ch->value; +				break; +			} +		} +		break; +	default: +		break; +	}  }  void DrumGizmo::setFrameSize(size_t framesize)  { -  // If we are resampling override the frame size. -  if(resampler[0].ratio() != 1) { -    framesize = RESAMPLER_INPUT_BUFFER; -  } - -  if(this->framesize != framesize) { -	  DEBUG(drumgizmo, "New framesize: %d\n", (int)framesize); - -    this->framesize = framesize; - -    // Update framesize in drumkitloader and cachemanager: -    loader.setFrameSize(framesize); -    audioCache.setFrameSize(framesize); -  } +	// If we are resampling override the frame size. +	if(resampler[0].ratio() != 1) +	{ +		framesize = RESAMPLER_INPUT_BUFFER; +	} + +	if(this->framesize != framesize) +	{ +		DEBUG(drumgizmo, "New framesize: %d\n", (int)framesize); + +		this->framesize = framesize; + +		// Update framesize in drumkitloader and cachemanager: +		loader.setFrameSize(framesize); +		audioCache.setFrameSize(framesize); +	}  }  void DrumGizmo::setFreeWheel(bool freewheel)  { -  // Freewheel = true means that we are bouncing and therefore running faster -  // than realtime. -  if(freewheel != this->freewheel) { -    this->freewheel = freewheel; -    audioCache.setAsyncMode(!freewheel); -  } +	// Freewheel = true means that we are bouncing and therefore running faster +	// than realtime. +	if(freewheel != this->freewheel) +	{ +		this->freewheel = freewheel; +		audioCache.setAsyncMode(!freewheel); +	}  }  bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples)  { -  setFrameSize(nsamples); - -  // Handle engine messages, at most one in each iteration: -  handleMessages(1); - -  ie->pre(); -  oe->pre(nsamples); - -  // -  // Read new events -  // - -  //DEBUG(engine, "Number of active events: %d\n", activeevents[0].size()); - -  size_t nev; -  event_t *evs = ie->run(pos, nsamples, &nev); - -  for(size_t e = 0; e < nev; e++) { -    if(evs[e].type == TYPE_ONSET) { -      Instrument *i = NULL; -      int d = evs[e].instrument; -      /* -        Instruments::iterator it = kit.instruments.begin(); -        while(d-- && it != kit.instruments.end()) { -        i = &(it->second); -        it++; -        } -      */ -       -      if(!kit.isValid()) continue; - -      if(d < (int)kit.instruments.size()) { -        i = kit.instruments[d]; -      } - -      if(i == NULL || !i->isValid()) { -        ERR(drumgizmo, "Missing Instrument %d.\n", evs[e].instrument); -        continue; -      } - -      if(i->group() != "") { -        // Add event to ramp down all existing events with the same groupname. -        Channels::iterator j = kit.channels.begin(); -        while(j != kit.channels.end()) { -          Channel &ch = *j; -          std::list< Event* >::iterator evs = activeevents[ch.num].begin(); -          while(evs != activeevents[ch.num].end()) { -            Event *ev = *evs; -            if(ev->type() == Event::sample) { -              EventSample *sev = (EventSample*)ev; -              if(sev->group == i->group() && sev->instrument != i) { -                sev->rampdown = 3000; // Ramp down 3000 samples -                // TODO: This must be configurable at some point... -                // ... perhaps even by instrument (ie. in the xml file) -                sev->ramp_start = sev->rampdown; -              } -            } -            evs++; -          } -          j++; -        } -      } - -      Sample *s = i->sample(evs[e].velocity, evs[e].offset + pos); -       -      if(s == NULL) { -        ERR(drumgizmo, "Missing Sample.\n"); -        continue; -      } -       -      Channels::iterator j = kit.channels.begin(); -      while(j != kit.channels.end()) { -        Channel &ch = *j; -        AudioFile *af = s->getAudioFile(&ch); -        if(af) { -          // LAZYLOAD: -          // DEBUG(drumgizmo,"Requesting preparing of audio file\n"); -          // loader.prepare(af); -        } -        if(af == NULL || !af->isValid()) { -          //DEBUG(drumgizmo,"Missing AudioFile.\n"); -        } else { -          //DEBUG(drumgizmo, "Adding event %d.\n", evs[e].offset); -          Event *evt = new EventSample(ch.num, 1.0, af, i->group(), i); -          evt->offset = (evs[e].offset + pos) * resampler[0].ratio(); -          activeevents[ch.num].push_back(evt); -        } -        j++; -      } -    } -     -    if(evs[e].type == TYPE_STOP) { -      is_stopping = true; -    } - -    if(is_stopping) { -      // Count the number of active events. -      int num_active_events = 0; -      Channels::iterator j = kit.channels.begin(); -      while(j != kit.channels.end()) { -        Channel &ch = *j; -        num_active_events += activeevents[ch.num].size(); -        j++; -      } - -      if(num_active_events == 0) { -        // No more active events - now we can stop the engine. -        return false; -      } -    } -     -  } -     -  free(evs); - -  // -  // Write audio -  // +	setFrameSize(nsamples); + +	// Handle engine messages, at most one in each iteration: +	handleMessages(1); + +	ie->pre(); +	oe->pre(nsamples); + +	// +	// Read new events +	// + +	//DEBUG(engine, "Number of active events: %d\n", activeevents[0].size()); + +	size_t nev; +	event_t *evs = ie->run(pos, nsamples, &nev); + +	for(size_t e = 0; e < nev; ++e) +	{ +		if(evs[e].type == TYPE_ONSET) +		{ +			Instrument *i = nullptr; +			int d = evs[e].instrument; +			/* +			  Instruments::iterator it = kit.instruments.begin(); +			  while(d-- && it != kit.instruments.end()) +			  { +			  i = &(it->second); +			  ++it; +			  } +			*/ + +			if(!kit.isValid()) +			{ +				continue; +			} + +			if(d < (int)kit.instruments.size()) +			{ +				i = kit.instruments[d]; +			} + +			if(i == nullptr || !i->isValid()) +			{ +				ERR(drumgizmo, "Missing Instrument %d.\n", evs[e].instrument); +				continue; +			} + +			if(i->group() != "") +			{ +				// Add event to ramp down all existing events with the same groupname. +				Channels::iterator j = kit.channels.begin(); +				while(j != kit.channels.end()) +				{ +					Channel &ch = *j; +					std::list< Event* >::iterator evs = activeevents[ch.num].begin(); +					while(evs != activeevents[ch.num].end()) +					{ +						Event *ev = *evs; +						if(ev->type() == Event::sample) +						{ +							EventSample *sev = (EventSample*)ev; +							if(sev->group == i->group() && sev->instrument != i) +							{ +								sev->rampdown = 3000; // Ramp down 3000 samples +								// TODO: This must be configurable at some point... +								// ... perhaps even by instrument (ie. in the xml file) +								sev->ramp_start = sev->rampdown; +							} +						} +						++evs; +					} +					++j; +				} +			} + +			Sample *s = i->sample(evs[e].velocity, evs[e].offset + pos); + +			if(s == nullptr) +			{ +				ERR(drumgizmo, "Missing Sample.\n"); +				continue; +			} + +			Channels::iterator j = kit.channels.begin(); +			while(j != kit.channels.end()) +			{ +				Channel &ch = *j; +				AudioFile *af = s->getAudioFile(&ch); +				if(af) +				{ +					// LAZYLOAD: +					// DEBUG(drumgizmo,"Requesting preparing of audio file\n"); +					// loader.prepare(af); +				} +				if(af == nullptr || !af->isValid()) +				{ +					//DEBUG(drumgizmo,"Missing AudioFile.\n"); +				} +				else +				{ +					//DEBUG(drumgizmo, "Adding event %d.\n", evs[e].offset); +					Event *evt = new EventSample(ch.num, 1.0, af, i->group(), i); +					evt->offset = (evs[e].offset + pos) * resampler[0].ratio(); +					activeevents[ch.num].push_back(evt); +				} +				++j; +			} +		} + +		if(evs[e].type == TYPE_STOP) +		{ +			is_stopping = true; +		} + +		if(is_stopping) +		{ +			// Count the number of active events. +			int num_active_events = 0; +			Channels::iterator j = kit.channels.begin(); +			while(j != kit.channels.end()) +			{ +				Channel &ch = *j; +				num_active_events += activeevents[ch.num].size(); +				++j; +			} + +			if(num_active_events == 0) +			{ +				// No more active events - now we can stop the engine. +				return false; +			} +		} + +	} + +	free(evs); + +	// +	// Write audio +	//  #ifdef WITH_RESAMPLER -  if(Conf::enable_resampling == false || -     resampler[0].ratio() == 1.0) { // No resampling needed +	if((Conf::enable_resampling == false) || +	   (resampler[0].ratio() == 1.0)) // No resampling needed +	{  #endif -    for(size_t c = 0; c < kit.channels.size(); c++) { -      sample_t *buf = samples; -      bool internal = false; -      if(oe->getBuffer(c)) { -        buf = oe->getBuffer(c); -        internal = true; -      } -      if(buf) { -        memset(buf, 0, nsamples * sizeof(sample_t)); - -        getSamples(c, pos, buf, nsamples); - -        if(!internal) oe->run(c, samples, nsamples); -      } -    } +		for(size_t c = 0; c < kit.channels.size(); ++c) +		{ +			sample_t *buf = samples; +			bool internal = false; +			if(oe->getBuffer(c)) +			{ +				buf = oe->getBuffer(c); +				internal = true; +			} + +			if(buf) +			{ +				memset(buf, 0, nsamples * sizeof(sample_t)); + +				getSamples(c, pos, buf, nsamples); + +				if(!internal) +				{ +					oe->run(c, samples, nsamples); +				} +			} +		}  #ifdef WITH_RESAMPLER -  } else { -  // Resampling needed - -  // -  // NOTE: Channels must be processed one buffer at a time on all channels in -  // parallel - NOT all buffers on one channel and then all buffer on the next -  // one since this would mess up the event queue (it would jump back and forth -  // in time) -  // - -  // Prepare output buffer -  for(size_t c = 0; c < kit.channels.size(); c++) { -    resampler[c].setOutputSamples(resampler_output_buffer[c], nsamples); -  } - -  // Process channel data -  size_t kitpos = pos * resampler[0].ratio(); -  size_t insize = sizeof(resampler_input_buffer[0]) / sizeof(sample_t); - -  while(resampler[0].getOutputSampleCount() > 0) { -    for(size_t c = 0; c < kit.channels.size(); c++) { -      if(resampler[c].getInputSampleCount() == 0) { -        sample_t *sin = resampler_input_buffer[c]; -        memset(resampler_input_buffer[c], 0, -               sizeof(resampler_input_buffer[c])); -        getSamples(c, kitpos, sin, insize); - -        resampler[c].setInputSamples(sin, insize); -      } -      resampler[c].process(); -    } -    kitpos += insize; -  } - -  // Write output data to output engine. -  for(size_t c = 0; c < kit.channels.size(); c++) { -    oe->run(c, resampler_output_buffer[c], nsamples); -  } - -  } +	} +	else +	{ +		// Resampling needed + +		// +		// NOTE: Channels must be processed one buffer at a time on all channels in +		// parallel - NOT all buffers on one channel and then all buffer on the next +		// one since this would mess up the event queue (it would jump back and +		// forth in time) +		// + +		// Prepare output buffer +		for(size_t c = 0; c < kit.channels.size(); ++c) +		{ +			resampler[c].setOutputSamples(resampler_output_buffer[c], nsamples); +		} + +		// Process channel data +		size_t kitpos = pos * resampler[0].ratio(); +		size_t insize = sizeof(resampler_input_buffer[0]) / sizeof(sample_t); + +		while(resampler[0].getOutputSampleCount() > 0) +		{ +			for(size_t c = 0; c < kit.channels.size(); ++c) +			{ +				if(resampler[c].getInputSampleCount() == 0) +				{ +					sample_t *sin = resampler_input_buffer[c]; +					memset(resampler_input_buffer[c], 0, +					       sizeof(resampler_input_buffer[c])); +					getSamples(c, kitpos, sin, insize); + +					resampler[c].setInputSamples(sin, insize); +				} +				resampler[c].process(); +			} +			kitpos += insize; +		} + +		// Write output data to output engine. +		for(size_t c = 0; c < kit.channels.size(); ++c) +		{ +			oe->run(c, resampler_output_buffer[c], nsamples); +		} + +	}  #endif/*WITH_RESAMPLER*/ -   -  ie->post(); -  oe->post(nsamples); -   -  pos += nsamples; -  return true; +	ie->post(); +	oe->post(nsamples); + +	pos += nsamples; + +	return true;  }  #undef SSE // SSE broken for now ... so disable it. @@ -396,423 +453,278 @@ typedef float vNsf __attribute__ ((vector_size(sizeof(sample_t)*N)));  void DrumGizmo::getSamples(int ch, int pos, sample_t *s, size_t sz)  { -  std::list< Event* >::iterator i = activeevents[ch].begin(); -  for(; i != activeevents[ch].end(); ++i) { -    bool removeevent = false; - -    Event *event = *i; - -    Event::type_t type = event->type(); -    switch(type) { -    case Event::sample: -      { -        EventSample *evt = (EventSample *)event; -        AudioFile *af = evt->file; - -        if(!af->isLoaded() || !af->isValid() || s == NULL) { -          removeevent = true; -          break; -        } - -        // Don't handle event now is is scheduled for a future iteration? -        if(evt->offset > (pos + sz)) { -          continue; -        } - -        if(evt->cache_id == CACHE_NOID) { -          size_t initial_chunksize = (pos + sz) - evt->offset; -          evt->buffer = audioCache.open(af, initial_chunksize, -                                          af->filechannel, evt->cache_id); -          evt->buffer_size = initial_chunksize; -        } - -        { -        MutexAutolock l(af->mutex); - -        size_t n = 0; // default start point is 0. - -        // If we are not at offset 0 in current buffer: -        if(evt->offset > (size_t)pos) { -          n = evt->offset - pos; -        } - -        size_t end = sz; // default end point is the end of the buffer. - -        // Find the end point intra-buffer -        if((evt->t + end - n) > af->size) { -          end = af->size - evt->t + n; -        } - -        // This should not be necessary but make absolutely sure that we do -        // not write over the end of the buffer. -        if(end > sz) { -          end = sz; -        } - -        size_t t = 0; // Internal buffer counter -        if(evt->rampdown == NO_RAMPDOWN) { +	std::list< Event* >::iterator i = activeevents[ch].begin(); +	for(; i != activeevents[ch].end(); ++i) +	{ +		bool removeevent = false; + +		Event *event = *i; + +		Event::type_t type = event->type(); +		switch(type) { +		case Event::sample: +			{ +				EventSample *evt = (EventSample *)event; +				AudioFile *af = evt->file; + +				if(!af->isLoaded() || !af->isValid() || (s == nullptr)) +				{ +					removeevent = true; +					break; +				} + +				// Don't handle event now is is scheduled for a future iteration? +				if(evt->offset > (pos + sz)) +				{ +					continue; +				} + +				if(evt->cache_id == CACHE_NOID) +				{ +					size_t initial_chunksize = (pos + sz) - evt->offset; +					evt->buffer = audioCache.open(af, initial_chunksize, +					                              af->filechannel, evt->cache_id); +					evt->buffer_size = initial_chunksize; +				} + +				{ +					MutexAutolock l(af->mutex); + +					size_t n = 0; // default start point is 0. + +					// If we are not at offset 0 in current buffer: +					if(evt->offset > (size_t)pos) +					{ +						n = evt->offset - pos; +					} + +					size_t end = sz; // default end point is the end of the buffer. + +					// Find the end point intra-buffer +					if((evt->t + end - n) > af->size) +					{ +						end = af->size - evt->t + n; +					} + +					// This should not be necessary but make absolutely sure that we do +					// not write over the end of the buffer. +					if(end > sz) +					{ +						end = sz; +					} + +					size_t t = 0; // Internal buffer counter +					if(evt->rampdown == NO_RAMPDOWN) +					{  #ifdef SSE -          size_t optend = ((end - n) / N) * N + n; - -          // Force source addr to be 16 byte aligned... (might skip 1 or 2 samples) -          while((size_t)&evt->buffer[t] % 16) { -            ++t; -          } - -          for(; (n < optend) && (t < evt->buffer_size); n += N) { -            *(vNsf*)&(s[n]) += *(vNsf*)&(evt->buffer[t]); -            t += N; -          } +						size_t optend = ((end - n) / N) * N + n; + +						// Force source addr to be 16 byte aligned... +						// (might skip 1 or 2 samples) +						while((size_t)&evt->buffer[t] % 16) +						{ +							++t; +						} + +						for(; (n < optend) && (t < evt->buffer_size); n += N) +						{ +							*(vNsf*)&(s[n]) += *(vNsf*)&(evt->buffer[t]); +							t += N; +						}  #endif -          for(; (n < end) && (t < evt->buffer_size); n++) { -            s[n] += evt->buffer[t]; -            t++; -          } -        } else { // Ramp down in progress. -          for(; (n < end) && (t < evt->buffer_size) && evt->rampdown; n++) { -            float scale = (float)evt->rampdown/(float)evt->ramp_start; -            s[n] += evt->buffer[t] * scale; -            t++; -            evt->rampdown--; -          } -        } - -        evt->t += evt->buffer_size; // Add internal buffer counter to "global" event counter. - -        if((evt->t < af->size) && (evt->rampdown != 0)) { -          evt->buffer = audioCache.next(evt->cache_id, evt->buffer_size); -        } else { -          removeevent = true; -        } - -        if(removeevent) { -          audioCache.close(evt->cache_id); -        } -        } -      } -      break; -    } - -    if(removeevent) { -      delete event; -      i = activeevents[ch].erase(i); -      continue; -    } -  } +						for(; (n < end) && (t < evt->buffer_size); ++n) +						{ +							s[n] += evt->buffer[t]; +							++t; +						} +					} +					else +					{ // Ramp down in progress. +						for(; (n < end) && (t < evt->buffer_size) && evt->rampdown; ++n) +						{ +							float scale = (float)evt->rampdown/(float)evt->ramp_start; +							s[n] += evt->buffer[t] * scale; +							++t; +							evt->rampdown--; +						} +					} + +					// Add internal buffer counter to "global" event counter. +					evt->t += evt->buffer_size; + +					if((evt->t < af->size) && (evt->rampdown != 0)) +					{ +						evt->buffer = audioCache.next(evt->cache_id, evt->buffer_size); +					} +					else +					{ +						removeevent = true; +					} + +					if(removeevent) +					{ +						audioCache.close(evt->cache_id); +					} +				} +			} +			break; +		} + +		if(removeevent) +		{ +			delete event; +			i = activeevents[ch].erase(i); +			continue; +		} +	}  }  void DrumGizmo::stop()  { -  // engine.stop(); +	// engine.stop();  }  int DrumGizmo::samplerate()  { -  return Conf::samplerate; +	return Conf::samplerate;  }  void DrumGizmo::setSamplerate(int samplerate)  {  	DEBUG(dgeditor, "%s samplerate: %d\n", __PRETTY_FUNCTION__, samplerate); -  Conf::samplerate = samplerate; +	Conf::samplerate = samplerate;  #ifdef WITH_RESAMPLER -  for(int i = 0; i < MAX_NUM_CHANNELS; i++) { -    resampler[i].setup(kit.samplerate(), Conf::samplerate); -  } -  if(resampler[0].ratio() != 1) { -    setFrameSize(RESAMPLER_INPUT_BUFFER); -  } +	for(int i = 0; i < MAX_NUM_CHANNELS; ++i) +	{ +		resampler[i].setup(kit.samplerate(), Conf::samplerate); +	} +	if(resampler[0].ratio() != 1) +	{ +		setFrameSize(RESAMPLER_INPUT_BUFFER); +	}  #endif/*WITH_RESAMPLER*/ -  }  std::string float2str(float a)  { -  char buf[256]; -  snprintf_nol(buf, sizeof(buf) - 1, "%f", a); -  return buf; +	char buf[256]; +	snprintf_nol(buf, sizeof(buf) - 1, "%f", a); +	return buf;  }  std::string bool2str(bool a)  { -  return a?"true":"false"; +	return a?"true":"false";  }  float str2float(std::string a)  { -  if(a == "") return 0.0; -  return atof_nol(a.c_str()); +	if(a == "") +	{ +		return 0.0; +	} + +	return atof_nol(a.c_str());  }  std::string DrumGizmo::configString()  { -  std::string mmapfile; -  if(ie->isMidiEngine()) { -    AudioInputEngineMidi *aim = (AudioInputEngineMidi*)ie; -    mmapfile = aim->midimapFile(); -  } - -  return -    "<config>\n" -    "  <value name=\"drumkitfile\">" + kit.file() + "</value>\n" -    "  <value name=\"midimapfile\">" + mmapfile + "</value>\n" -    "  <value name=\"enable_velocity_modifier\">" + -    bool2str(Conf::enable_velocity_modifier) + "</value>\n" -    "  <value name=\"velocity_modifier_falloff\">" + -    float2str(Conf::velocity_modifier_falloff) + "</value>\n" -    "  <value name=\"velocity_modifier_weight\">" + -    float2str(Conf::velocity_modifier_weight) + "</value>\n" -    "  <value name=\"enable_velocity_randomiser\">" + -    bool2str(Conf::enable_velocity_randomiser) + "</value>\n" -    "  <value name=\"velocity_randomiser_weight\">" + -    float2str(Conf::velocity_randomiser_weight) + "</value>\n" -    "</config>"; +	std::string mmapfile; +	if(ie->isMidiEngine()) +	{ +		AudioInputEngineMidi *aim = (AudioInputEngineMidi*)ie; +		mmapfile = aim->midimapFile(); +	} + +	return +		"<config>\n" +		"  <value name=\"drumkitfile\">" + kit.file() + "</value>\n" +		"  <value name=\"midimapfile\">" + mmapfile + "</value>\n" +		"  <value name=\"enable_velocity_modifier\">" + +		bool2str(Conf::enable_velocity_modifier) + "</value>\n" +		"  <value name=\"velocity_modifier_falloff\">" + +		float2str(Conf::velocity_modifier_falloff) + "</value>\n" +		"  <value name=\"velocity_modifier_weight\">" + +		float2str(Conf::velocity_modifier_weight) + "</value>\n" +		"  <value name=\"enable_velocity_randomiser\">" + +		bool2str(Conf::enable_velocity_randomiser) + "</value>\n" +		"  <value name=\"velocity_randomiser_weight\">" + +		float2str(Conf::velocity_randomiser_weight) + "</value>\n" +		"</config>";  } -  bool DrumGizmo::setConfigString(std::string cfg)  { -  DEBUG(config, "Load config: %s\n", cfg.c_str()); - -  std::string dkf; -  ConfigParser p; -  if(p.parse(cfg)) { -    ERR(drumgizmo, "Config parse error.\n"); -    return false; -  } - -  if(p.value("enable_velocity_modifier") != "") { -    Conf::enable_velocity_modifier = -      p.value("enable_velocity_modifier") == "true"; -  } - -  if(p.value("velocity_modifier_falloff") != "") { -    Conf::velocity_modifier_falloff = -      str2float(p.value("velocity_modifier_falloff")); -  } - -  if(p.value("velocity_modifier_weight") != "") { -    Conf::velocity_modifier_weight = -      str2float(p.value("velocity_modifier_weight")); -  } - -  if(p.value("enable_velocity_randomiser") != "") { -    Conf::enable_velocity_randomiser = -      p.value("enable_velocity_randomiser") == "true"; -  } - -  if(p.value("velocity_randomiser_weight") != "") { -    Conf::velocity_randomiser_weight = -      str2float(p.value("velocity_randomiser_weight")); -  } - -  if(p.value("enable_resampling") != "") { -    Conf::enable_resampling = -      p.value("enable_resampling") == "true"; -  } - -  std::string newkit = p.value("drumkitfile"); -  if(newkit != "" && kit.file() != newkit) { -    /* -    if(!loadkit(p.values["drumkitfile"])) return false; -    init(true); -    */ -    LoadDrumKitMessage *msg = new LoadDrumKitMessage(); -    msg->drumkitfile = newkit; -    msghandler.sendMessage(MSGRCV_ENGINE, msg); -  } - -  std::string newmidimap = p.value("midimapfile"); -  if(newmidimap != "") { -    //midimapfile = newmidimap; -    LoadMidimapMessage *msg = new LoadMidimapMessage(); -    msg->midimapfile = newmidimap; -    msghandler.sendMessage(MSGRCV_ENGINE, msg); -  } - -  return true; -} - -#ifdef TEST_DRUMGIZMO -//deps: instrument.cc sample.cc channel.cc audiofile.cc drumkit.cc drumkitparser.cc configuration.cc saxparser.cc instrumentparser.cc path.cc -//cflags: $(SNDFILE_CFLAGS) $(EXPAT_CFLAGS) -I../include -DSSE -msse -msse2 -msse3 -//libs: $(SNDFILE_LIBS) $(EXPAT_LIBS) -#include "test.h" - -static float f(size_t x) -{ -  return x + 1.0; +	DEBUG(config, "Load config: %s\n", cfg.c_str()); + +	std::string dkf; +	ConfigParser p; +	if(p.parse(cfg)) +	{ +	 ERR(drumgizmo, "Config parse error.\n"); +	 return false; +	} + +	if(p.value("enable_velocity_modifier") != "") +	{ +		Conf::enable_velocity_modifier = +			p.value("enable_velocity_modifier") == "true"; +	} + +	if(p.value("velocity_modifier_falloff") != "") +	{ +		Conf::velocity_modifier_falloff = +			str2float(p.value("velocity_modifier_falloff")); +	} + +	if(p.value("velocity_modifier_weight") != "") +	{ +		Conf::velocity_modifier_weight = +			str2float(p.value("velocity_modifier_weight")); +	} + +	if(p.value("enable_velocity_randomiser") != "") +	{ +		Conf::enable_velocity_randomiser = +			p.value("enable_velocity_randomiser") == "true"; +	} + +	if(p.value("velocity_randomiser_weight") != "") +	{ +		Conf::velocity_randomiser_weight = +			str2float(p.value("velocity_randomiser_weight")); +	} + +	if(p.value("enable_resampling") != "") +	{ +		Conf::enable_resampling = +			p.value("enable_resampling") == "true"; +	} + +	std::string newkit = p.value("drumkitfile"); +	if(newkit != "" && kit.file() != newkit) +	{ +		/* +		  if(!loadkit(p.values["drumkitfile"])) +		  { +		  return false; +		  } +		  init(true); +		*/ +		LoadDrumKitMessage *msg = new LoadDrumKitMessage(); +		msg->drumkitfile = newkit; +		msghandler.sendMessage(MSGRCV_ENGINE, msg); +	} + +	std::string newmidimap = p.value("midimapfile"); +	if(newmidimap != "") +	{ +		//midimapfile = newmidimap; +		LoadMidimapMessage *msg = new LoadMidimapMessage(); +		msg->midimapfile = newmidimap; +		msghandler.sendMessage(MSGRCV_ENGINE, msg); +	} + +	return true;  } - -class AITest : public AudioInputEngine { -public: -  bool init(Instruments &instruments) { return true; } -  void setParm(std::string parm, std::string value) {} -  bool start() { return true; } -  void stop() {} -  void pre() {} -  event_t *run(size_t pos, size_t len, size_t *nevents) -  { -    event_t *e = NULL; -    *nevents = 0; - -    if(pos <= offset && offset < pos + len) { -      e = new event_t; - -      e->type = TYPE_ONSET; -      e->instrument = 0; -      e->velocity = 1.0; -      e->offset = offset - pos; - -      *nevents = 1; -    } -    return e; -  } -  void post() {} -  size_t offset; -}; - -class AOTest : public AudioOutputEngine { -public: -  bool init(Channels channels) { return true; } -  void setParm(std::string parm, std::string value) {} -  bool start() { return true; } -  void stop() {} -  void pre(size_t nsamples) {} -  void run(int ch, sample_t *samples, size_t nsamples) -  { -  } -  void post(size_t nsamples) {} -}; - -const char xml_kit[] = -  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" -  "<drumkit name=\"test\" description=\"\">\n" -  "  <channels>\n" -  "    <channel name=\"ch1\"/>\n" -  "  </channels>\n" -  "  <instruments>\n" -  "    <instrument name=\"instr1\" file=\"instr1.xml\">\n" -  "      <channelmap in=\"ch1\" out=\"ch1\"/>\n" -  "		</instrument>\n" -  "	</instruments>\n" -  "</drumkit>"; - -const char xml_instr[] = -  "<?xml version='1.0' encoding='UTF-8'?>\n" -  "<instrument name=\"instr1\">\n" -  " <samples>\n" -  "  <sample name=\"sample1\">\n" -  "   <audiofile channel=\"ch1\" file=\"instr1.wav\"/>\n" -  "  </sample>\n" -  " </samples>\n" -  " <velocities>\n" -  "  <velocity lower=\"0\" upper=\"1.0\">\n" -  "   <sampleref name=\"sample1\"/>\n" -  "  </velocity>\n" -  " </velocities>\n" -  "</instrument>"; - -#define PCM_SIZE 100 - -void createTestKit() -{ -  FILE *fp; -  fp = fopen("/tmp/kit.xml", "w"); -  fwrite(xml_kit, strlen(xml_kit), 1, fp); -  fclose(fp); - -  fp = fopen("/tmp/instr1.xml", "w"); -  fwrite(xml_instr, strlen(xml_instr), 1, fp); -  fclose(fp); - -  SF_INFO sf_info; -  sf_info.format = SF_FORMAT_WAV | SF_FORMAT_FLOAT; -  sf_info.samplerate = 44100; -  sf_info.channels = 1; - -  SNDFILE *fh = sf_open("/tmp/instr1.wav", SFM_WRITE, &sf_info); -  if(!fh) { -    printf("Error: %s\n", sf_strerror(fh)); -  } - -  size_t size = PCM_SIZE; -  sample_t samples[size]; - -  for(size_t i = 0; i < size; i++) { -    samples[i] = f(i);//(float)i / (float)size; -  } - -  sf_write_float(fh, samples, size);  -  sf_close(fh); -} - -void deleteTestKit() -{ -  unlink("/tmp/kit.xml"); -  unlink("/tmp/instr1.xml"); -  unlink("/tmp/instr1.wav"); -} - -TEST_BEGIN; - -createTestKit(); - -size_t size = PCM_SIZE; -//for(size_t chunksz = 1; chunksz < size + 1; chunksz++) { -size_t chunksz = 16; { -  sample_t samples[chunksz]; - -  for(size_t offset = 0; offset < chunksz + size + 1; offset++) { -    //size_t offset = 5; { -    for(size_t padding = 0; padding < chunksz + size + offset + 1; padding++) { -      //size_t padding = 2; { -      TEST_MSG("Values (offset %d, padding %d, chunksz %d)", -               offset, padding, chunksz); -       -      AOTest ao; -      AITest ai; ai.offset = offset; -      DrumGizmo dg(&ao, &ai); -      dg.loadkit("/tmp/kit.xml"); -       -      size_t pos = 0; -      //      sample_t samples[chunksz]; -      while(pos < offset + size + padding) { -        dg.run(pos, samples, chunksz); -         -        float err = 0; -        size_t errcnt = 0; -        for(size_t i = 0; i < chunksz && pos < offset + size + padding; i++) { -          float val = 0.0; -          if(pos >= offset && pos < (offset + size)) val = f(pos - offset); -          float diff = samples[i] - val; -          /* -          if(diff != 0.0) { -            TEST_EQUAL_FLOAT(samples[i], val, -                           "samples[%d] ?= val, pos %d", i, pos); -          } -          */ -          if(diff != 0.0) errcnt++; - -          err += fabs(diff); -          pos++; -        } - -        TEST_EQUAL_FLOAT(err, 0.0, -                         "Compare error (offset %d, padding %d, chunksz %d)", -                         offset, padding, chunksz); -        TEST_EQUAL_INT(errcnt, 0, -                       "Compare count (offset %d, padding %d, chunksz %d)", -                       offset, padding, chunksz); -      } - -    } -  } -} - -deleteTestKit(); - -TEST_END; - -#endif/*TEST_DRUMGIZMO*/ diff --git a/src/drumgizmo.h b/src/drumgizmo.h index 1e38e08..98cd287 100644 --- a/src/drumgizmo.h +++ b/src/drumgizmo.h @@ -53,52 +53,54 @@  #define REFSFILE "refs.conf"  #define RESAMPLER_INPUT_BUFFER 64 -class DrumGizmo : public MessageReceiver { +class DrumGizmo +	: public MessageReceiver +{  public: -  DrumGizmo(AudioOutputEngine *outputengine, AudioInputEngine *inputengine); -  virtual ~DrumGizmo(); +	DrumGizmo(AudioOutputEngine *outputengine, AudioInputEngine *inputengine); +	virtual ~DrumGizmo(); -  bool loadkit(std::string kitfile); +	bool loadkit(std::string kitfile); -  bool init(); +	bool init(); -  bool run(size_t pos, sample_t *samples, size_t nsamples); -  void stop(); +	bool run(size_t pos, sample_t *samples, size_t nsamples); +	void stop(); -  void getSamples(int ch, int pos, sample_t *s, size_t sz); +	void getSamples(int ch, int pos, sample_t *s, size_t sz); -  std::string configString(); -  bool setConfigString(std::string cfg); +	std::string configString(); +	bool setConfigString(std::string cfg); -  void handleMessage(Message *msg); +	void handleMessage(Message *msg); -  int samplerate(); -  void setSamplerate(int samplerate); +	int samplerate(); +	void setSamplerate(int samplerate); -  void setFrameSize(size_t framesize); +	void setFrameSize(size_t framesize); -  void setFreeWheel(bool freewheel); +	void setFreeWheel(bool freewheel); -private: -  DrumKitLoader loader; +protected: +	DrumKitLoader loader; -  Mutex mutex; -  bool is_stopping; ///< Is set to true when a TYPE_STOP event has been seen. +	Mutex mutex; +	bool is_stopping; ///< Is set to true when a TYPE_STOP event has been seen. -  AudioOutputEngine *oe; -  AudioInputEngine *ie; +	AudioOutputEngine *oe; +	AudioInputEngine *ie; -  std::list< Event* > activeevents[MAX_NUM_CHANNELS]; +	std::list< Event* > activeevents[MAX_NUM_CHANNELS]; -  CHResampler resampler[MAX_NUM_CHANNELS]; -  sample_t resampler_output_buffer[MAX_NUM_CHANNELS][4096]; -  sample_t resampler_input_buffer[MAX_NUM_CHANNELS][RESAMPLER_INPUT_BUFFER]; +	CHResampler resampler[MAX_NUM_CHANNELS]; +	sample_t resampler_output_buffer[MAX_NUM_CHANNELS][4096]; +	sample_t resampler_input_buffer[MAX_NUM_CHANNELS][RESAMPLER_INPUT_BUFFER]; -  std::map<std::string, AudioFile *> audiofiles; +	std::map<std::string, AudioFile *> audiofiles; -  AudioCache audioCache; -  DrumKit kit; +	AudioCache audioCache; +	DrumKit kit; -  size_t framesize; -  bool freewheel; +	size_t framesize; +	bool freewheel;  }; diff --git a/src/drumkitloader.cc b/src/drumkitloader.cc index 0a44db0..64d6710 100644 --- a/src/drumkitloader.cc +++ b/src/drumkitloader.cc @@ -32,146 +32,165 @@  #include "drumgizmo.h"  DrumKitLoader::DrumKitLoader() -  : semaphore("drumkitloader") -  , framesize(0) +	: semaphore("drumkitloader") +	, framesize(0)  { -  run(); -  run_semaphore.wait(); // Wait for the thread to actually start. +	run(); +	run_semaphore.wait(); // Wait for the thread to actually start.  }  DrumKitLoader::~DrumKitLoader()  {  	DEBUG(loader, "~DrumKitLoader() pre\n"); -  if(running) { -	  framesize_semaphore.post(); -    stop(); -  } + +	if(running) +	{ +		framesize_semaphore.post(); +		stop(); +	} +  	DEBUG(loader, "~DrumKitLoader() post\n");  }  void DrumKitLoader::stop()  { -  { -    MutexAutolock l(mutex); -    load_queue.clear(); -  } - -  running = false; -  semaphore.post(); -  wait_stop(); +	{ +		MutexAutolock l(mutex); +		load_queue.clear(); +	} + +	running = false; +	semaphore.post(); +	wait_stop();  }  void DrumKitLoader::skip()  { -  MutexAutolock l(mutex);   -  load_queue.clear(); +	MutexAutolock l(mutex); +	load_queue.clear();  }  void DrumKitLoader::setFrameSize(size_t framesize)  {  	DEBUG(loader, "%s pre\n", __PRETTY_FUNCTION__); +  	{ -  MutexAutolock l(mutex); -  this->framesize = framesize; -  framesize_semaphore.post(); // Signal that the framesize has been set. +		MutexAutolock l(mutex); +		this->framesize = framesize; +		framesize_semaphore.post(); // Signal that the framesize has been set.  	} +  	DEBUG(loader, "%s post\n", __PRETTY_FUNCTION__);  }  bool DrumKitLoader::isDone()  { -  MutexAutolock l(mutex); -  return load_queue.size() == 0; +	MutexAutolock l(mutex); +	return load_queue.size() == 0;  }  void DrumKitLoader::loadKit(DrumKit *kit)  { -  MutexAutolock l(mutex); - -  DEBUG(loader, "Create AudioFile queue from DrumKit\n"); - -  total_num_audiofiles = 0;// For UI Progress Messages - -  { // Count total number of files that need loading: -    Instruments::iterator i = kit->instruments.begin(); -    while(i != kit->instruments.end()) { -      Instrument *instr = *i; -      total_num_audiofiles += instr->audiofiles.size(); -      i++; -    } -  } - -  fraction = total_num_audiofiles / 200; -  if(fraction == 0) fraction = 1; - -  { // Now actually queue them for loading: -    Instruments::iterator i = kit->instruments.begin(); -    while(i != kit->instruments.end()) { -      Instrument *instr = *i; -       -      std::vector<AudioFile*>::iterator af = instr->audiofiles.begin(); -      while(af != instr->audiofiles.end()) { -        AudioFile *audiofile = *af; -        load_queue.push_back(audiofile); -        af++; -      } -   -      i++; -    } -  } - -  loaded = 0; // For UI Progress Messages - -  DEBUG(loader, "Queued %d (size: %d) AudioFiles for loading.\n", -        (int)total_num_audiofiles, (int)load_queue.size()); - -  semaphore.post(); // Start loader loop. +	MutexAutolock l(mutex); + +	DEBUG(loader, "Create AudioFile queue from DrumKit\n"); + +	total_num_audiofiles = 0;// For UI Progress Messages + +	{ // Count total number of files that need loading: +		Instruments::iterator i = kit->instruments.begin(); +		while(i != kit->instruments.end()) +		{ +			Instrument *instr = *i; +			total_num_audiofiles += instr->audiofiles.size(); +			++i; +		} +	} + +	fraction = total_num_audiofiles / 200; +	if(fraction == 0) +	{ +		fraction = 1; +	} + +	{ // Now actually queue them for loading: +		Instruments::iterator i = kit->instruments.begin(); +		while(i != kit->instruments.end()) +		{ +			Instrument *instr = *i; + +			std::vector<AudioFile*>::iterator af = instr->audiofiles.begin(); +			while(af != instr->audiofiles.end()) +			{ +				AudioFile *audiofile = *af; +				load_queue.push_back(audiofile); +				af++; +			} + +			++i; +		} +	} + +	loaded = 0; // For UI Progress Messages + +	DEBUG(loader, "Queued %d (size: %d) AudioFiles for loading.\n", +	      (int)total_num_audiofiles, (int)load_queue.size()); + +	semaphore.post(); // Start loader loop.  }  void DrumKitLoader::thread_main()  { -  running = true; - -  run_semaphore.post(); // Signal that the thread has been started. - -  framesize_semaphore.wait(); // Wait until the framesize has been set. - -  while(running) { -    size_t size; -    { -      MutexAutolock l(mutex); -      size = load_queue.size(); -    } - -    // Only sleep if queue is empty. -    if(size == 0) semaphore.wait(); - -    std::string filename; -    { -      MutexAutolock l(mutex); -      if(load_queue.size() == 0) continue; -      AudioFile *audiofile = load_queue.front(); -      load_queue.pop_front(); -      filename = audiofile->filename; -      size_t preload_size = framesize * CHUNK_MULTIPLIER + framesize; -      if(preload_size < 1024) -      { +	running = true; + +	run_semaphore.post(); // Signal that the thread has been started. + +	framesize_semaphore.wait(); // Wait until the framesize has been set. + +	while(running) +	{ +		size_t size; +		{ +			MutexAutolock l(mutex); +			size = load_queue.size(); +		} + +		// Only sleep if queue is empty. +		if(size == 0) +		{ +			semaphore.wait(); +		} + +		std::string filename; +		{ +			MutexAutolock l(mutex); +			if(load_queue.size() == 0) +			{ +				continue; +			} +			AudioFile *audiofile = load_queue.front(); +			load_queue.pop_front(); +			filename = audiofile->filename; +			size_t preload_size = framesize * CHUNK_MULTIPLIER + framesize; +			if(preload_size < 1024) +			{  	      preload_size = 1024; -      } -      (void)preload_size; -      audiofile->load(ALL_SAMPLES); // Note: Change this to enable diskstreaming -    } - -    loaded++; - -    if(loaded % fraction == 0 || loaded == total_num_audiofiles) { -      LoadStatusMessage *ls = new LoadStatusMessage(); -      ls->number_of_files = total_num_audiofiles; -      ls->numer_of_files_loaded = loaded; -      ls->current_file = filename; -      msghandler.sendMessage(MSGRCV_UI, ls); -    } -  } - -  DEBUG(loader, "Loader thread finished."); +			} +			(void)preload_size; +			audiofile->load(ALL_SAMPLES); // Note: Change this to enable diskstreaming +		} + +		loaded++; + +		if(loaded % fraction == 0 || loaded == total_num_audiofiles) +		{ +			LoadStatusMessage *ls = new LoadStatusMessage(); +			ls->number_of_files = total_num_audiofiles; +			ls->numer_of_files_loaded = loaded; +			ls->current_file = filename; +			msghandler.sendMessage(MSGRCV_UI, ls); +		} +	} + +	DEBUG(loader, "Loader thread finished.");  } diff --git a/src/drumkitloader.h b/src/drumkitloader.h index 22859a0..0532691 100644 --- a/src/drumkitloader.h +++ b/src/drumkitloader.h @@ -24,8 +24,7 @@   *  along with DrumGizmo; if not, write to the Free Software   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.   */ -#ifndef __DRUMGIZMO_DRUMKITLOADER_H__ -#define __DRUMGIZMO_DRUMKITLOADER_H__ +#pragma once  #include <string>  #include <list> @@ -36,69 +35,51 @@  #include "drumkit.h" -/** - * This class is responsible for loading the drumkits in its own thread. - * All interaction calls are simply modifying queues and not doing any - * work in-sync with the caller. - * This means that if loadKit(...) is called, one cannot assume that the - * drumkit has actually been loaded when the call returns. - */ -class DrumKitLoader : public Thread { +//! This class is responsible for loading the drumkits in its own thread. +//! All interaction calls are simply modifying queues and not doing any +//! work in-sync with the caller. +//! This means that if loadKit(...) is called, one cannot assume that the +//! drumkit has actually been loaded when the call returns. +class DrumKitLoader +	: public Thread +{  public: -  /** -   * The constrcutor starts the loader thread. -   */ -  DrumKitLoader(); +	//! The constrcutor starts the loader thread. +	DrumKitLoader(); -  /** -   * The destructor signals the thread to stop and waits to merge before -   * returning (ie. deleting the object will garantuee that the thread has -   * been stopped). -   */ -  ~DrumKitLoader(); +	//! The destructor signals the thread to stop and waits to merge before +	//! returning (ie. deleting the object will garantuee that the thread has +	//! been stopped). +	~DrumKitLoader(); -  /** -   * Signal the loader to start loading all audio files contained in kit. -   * All other AudioFiles in queue will be removed before the new ones are -   * scheduled. -   */ -  void loadKit(DrumKit *kit); -   -  // I have no idea what this does.. -  //void reset(AudioFile* af); +	//! Signal the loader to start loading all audio files contained in kit. +	//! All other AudioFiles in queue will be removed before the new ones are +	//! scheduled. +	void loadKit(DrumKit *kit); -  void thread_main(); +	void thread_main(); -  /** -   * Simply reports if the load queue is empty (i.e. all AudioFiles has been -   * loaded). -   */ -  bool isDone(); +	//! Simply reports if the load queue is empty (i.e. all AudioFiles has been +	//! loaded). +	bool isDone(); -  /** -   * Signal the loader to stop and wait until it has. -   */ -  void stop(); +	//! Signal the loader to stop and wait until it has. +	void stop(); -  /** -   * Skip all queued AudioFiles. -   */ -  void skip(); +	//! Skip all queued AudioFiles. +	void skip(); -  void setFrameSize(size_t framesize); +	void setFrameSize(size_t framesize); -private: -  Semaphore run_semaphore; -  Semaphore semaphore; -  Semaphore framesize_semaphore; -  Mutex mutex; +protected: +	Semaphore run_semaphore; +	Semaphore semaphore; +	Semaphore framesize_semaphore; +	Mutex mutex;  	volatile bool running{false}; -  std::list<AudioFile*> load_queue; +	std::list<AudioFile*> load_queue;  	size_t total_num_audiofiles{0};  	size_t fraction{1};  	size_t loaded{0}; -  	size_t framesize{0};  }; - -#endif/*__DRUMGIZMO_DRUMKITLOADER_H__*/ diff --git a/vst/drumgizmo_vst.cc b/vst/drumgizmo_vst.cc index 8c40b2f..c974a2a 100644 --- a/vst/drumgizmo_vst.cc +++ b/vst/drumgizmo_vst.cc @@ -85,7 +85,7 @@ void DGEditor::idle()  AudioEffect* createEffectInstance(audioMasterCallback audioMaster)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	return new DrumGizmoVst(audioMaster);  } @@ -123,9 +123,9 @@ DrumGizmoVst::DrumGizmoVst(audioMasterCallback audioMaster)  		printf("Error: %d\n", status);  	} -	INFO(example, "We are up and running"); +	INFO(vst, "We are up and running"); -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	pos = 0;  	buffer = nullptr; @@ -181,17 +181,26 @@ DrumGizmoVst::DrumGizmoVst(audioMasterCallback audioMaster)  DrumGizmoVst::~DrumGizmoVst()  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	DEBUG(vst, "~DrumGizmoVst(1)\n");  	if(drumgizmo) +	{  		delete drumgizmo; +	} +  	DEBUG(vst, "~DrumGizmoVst(2)\n");  	if(input) +	{  		delete input; +	} +  	DEBUG(vst, "~DrumGizmoVst(3)\n");  	if(output) +	{  		delete output; +	} +  	DEBUG(vst, "~DrumGizmoVst(4)\n");  	hug_close(); @@ -199,7 +208,7 @@ DrumGizmoVst::~DrumGizmoVst()  VstInt32 DrumGizmoVst::getChunk(void** data, bool isPreset)  { -	DEBUG(dgeditor, "%s - data: %p isPreset: %d\n", +	DEBUG(vst, "%s - data: %p isPreset: %d\n",  	      __PRETTY_FUNCTION__, *data, isPreset ? 1 : 0);  	std::string cfg = drumgizmo->configString();  	DEBUG(vst, "drumgizmo->config := %s\n", cfg.c_str()); @@ -210,7 +219,7 @@ VstInt32 DrumGizmoVst::getChunk(void** data, bool isPreset)  VstInt32 DrumGizmoVst::setChunk(void* data, VstInt32 byteSize, bool isPreset)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	std::string config;  	config.append((const char*)data, (size_t)byteSize); @@ -228,21 +237,21 @@ VstInt32 DrumGizmoVst::setChunk(void* data, VstInt32 byteSize, bool isPreset)  void DrumGizmoVst::setProgram(VstInt32 program)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  }  void DrumGizmoVst::setProgramName(char* name)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  }  void DrumGizmoVst::getProgramName(char* name)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	name[0] = '\0';  }  void DrumGizmoVst::getParameterLabel(VstInt32 index, char* label)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	label[0] = '\0';  	/*  	switch(index) @@ -268,7 +277,7 @@ void DrumGizmoVst::getParameterLabel(VstInt32 index, char* label)  void DrumGizmoVst::getParameterDisplay(VstInt32 index, char* text)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	text[0] = 0;  	/*  	switch(index) @@ -304,7 +313,7 @@ void DrumGizmoVst::getParameterDisplay(VstInt32 index, char* text)  void DrumGizmoVst::getParameterName(VstInt32 index, char* label)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	/*  	switch(index)  	{ @@ -328,13 +337,13 @@ void DrumGizmoVst::getParameterName(VstInt32 index, char* label)  void DrumGizmoVst::setParameter(VstInt32 index, float value)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	/*  	DrumGizmoVstProgram *ap = &programs[curProgram];  	switch(index)  	{  	    case kWaveform1:	fWaveform1	= ap->fWaveform1	= value;	break; -	    case kFreq1:		fFreq1 		= ap->fFreq1		= value;	break; +	    case kFreq1:		fFreq1		= ap->fFreq1		= value;	break;  	    case kVolume1:		fVolume1	= ap->fVolume1		= value;	break;  	    case kWaveform2:	fWaveform2	= ap->fWaveform2	= value;	break;  	    case kFreq2:		fFreq2		= ap->fFreq2		= value;	break; @@ -346,7 +355,7 @@ void DrumGizmoVst::setParameter(VstInt32 index, float value)  float DrumGizmoVst::getParameter(VstInt32 index)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	float value = 0;  	/*  	switch(index) @@ -363,10 +372,10 @@ float DrumGizmoVst::getParameter(VstInt32 index)  	return value;  } -bool DrumGizmoVst::getOutputProperties( -    VstInt32 index, VstPinProperties* properties) +bool DrumGizmoVst::getOutputProperties(VstInt32 index, +                                       VstPinProperties* properties)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	if(index < NUM_OUTPUTS)  	{  		vst_strncpy(properties->label, "Channel ", 63); @@ -381,92 +390,108 @@ bool DrumGizmoVst::getOutputProperties(  	return false;  } -bool DrumGizmoVst::getProgramNameIndexed( -    VstInt32 category, VstInt32 index, char* text) +bool DrumGizmoVst::getProgramNameIndexed(VstInt32 category, VstInt32 index, +                                         char* text)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	return false;  }  bool DrumGizmoVst::getEffectName(char* name)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	vst_strncpy(name, "DrumGizmo4", kVstMaxEffectNameLen);  	return true;  }  bool DrumGizmoVst::getVendorString(char* text)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	vst_strncpy(text, "Aasimon.org", kVstMaxVendorStrLen);  	return true;  }  bool DrumGizmoVst::getProductString(char* text)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	vst_strncpy(text, "Vst Synth", kVstMaxProductStrLen);  	return true;  }  VstInt32 DrumGizmoVst::getVendorVersion()  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	return 1000;  }  VstInt32 DrumGizmoVst::canDo(char* text)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	if(!strcmp(text, "receiveVstEvents")) +	{  		return 1; +	} +  	if(!strcmp(text, "receiveVstMidiEvent")) +	{  		return 1; +	} +  	// if(!strcmp(text, "midiProgramNames")) return 1;  	return -1; // explicitly can't do; 0 => don't know  }  VstInt32 DrumGizmoVst::getNumMidiInputChannels()  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	return 1; // we are monophonic  }  VstInt32 DrumGizmoVst::getNumMidiOutputChannels()  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	return 0; // no MIDI output back to Host app  } -VstInt32 DrumGizmoVst::getMidiProgramName( -    VstInt32 channel, MidiProgramName* mpn) +VstInt32 DrumGizmoVst::getMidiProgramName(VstInt32 channel, +                                          MidiProgramName* mpn)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	VstInt32 prg = mpn->thisProgramIndex; -	if(prg < 0 || prg >= 128) +	if((prg < 0) || (prg >= 128)) +	{  		return 0; +	} +  	fillProgram(channel, prg, mpn);  	if(channel == 9) +	{  		return 1; +	} +  	return 128L;  } -VstInt32 DrumGizmoVst::getCurrentMidiProgram( -    VstInt32 channel, MidiProgramName* mpn) +VstInt32 DrumGizmoVst::getCurrentMidiProgram(VstInt32 channel, +                                             MidiProgramName* mpn)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); -	if(channel < 0 || channel >= 16 || !mpn) +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__); +	if((channel < 0) || (channel >= 16) || !mpn) +	{  		return -1; +	} +  	VstInt32 prg = 0;  	mpn->thisProgramIndex = prg;  	fillProgram(channel, prg, mpn); +  	return prg;  } -void DrumGizmoVst::fillProgram( -    VstInt32 channel, VstInt32 prg, MidiProgramName* mpn) +void DrumGizmoVst::fillProgram(VstInt32 channel, VstInt32 prg, +                               MidiProgramName* mpn)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	mpn->midiBankMsb = mpn->midiBankLsb = -1;  	mpn->reserved = 0;  	mpn->flags = 0; @@ -476,10 +501,10 @@ void DrumGizmoVst::fillProgram(  	mpn->parentCategoryIndex = 0;  } -VstInt32 DrumGizmoVst::getMidiProgramCategory( -    VstInt32 channel, MidiProgramCategory* cat) +VstInt32 DrumGizmoVst::getMidiProgramCategory(VstInt32 channel, +                                              MidiProgramCategory* cat)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	cat->parentCategoryIndex = -1; // -1:no parent category  	cat->flags = 0;                // reserved, none defined yet, zero.  	//	VstInt32 category = cat->thisCategoryIndex; @@ -498,7 +523,7 @@ bool DrumGizmoVst::getMidiKeyName(VstInt32 channel, MidiKeyName* key)  // if keyName is "" the standard name of the key will be displayed.  // if false is returned, no MidiKeyNames defined for 'thisProgramIndex'.  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	// key->thisProgramIndex;		// >= 0. fill struct for this program index.  	// key->thisKeyNumber;			// 0 - 127. fill struct for this key number.  	key->keyName[0] = 0; @@ -509,28 +534,28 @@ bool DrumGizmoVst::getMidiKeyName(VstInt32 channel, MidiKeyName* key)  void DrumGizmoVst::setSampleRate(float sampleRate)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	AudioEffectX::setSampleRate(sampleRate);  	drumgizmo->setSamplerate(sampleRate);  }  void DrumGizmoVst::setBlockSize(VstInt32 blockSize)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	AudioEffectX::setBlockSize(blockSize);  }  void DrumGizmoVst::initProcess()  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	//  drumgizmo->loadkit(getenv("DRUMGIZMO_DRUMKIT"));  	drumgizmo->init();  } -void DrumGizmoVst::processReplacing( -    float** inputs, float** outputs, VstInt32 sampleFrames) +void DrumGizmoVst::processReplacing(float** inputs, float** outputs, +                                    VstInt32 sampleFrames)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	long lvl = getCurrentProcessLevel();  	// 0 = realtime/normal  	// 1 = non-realtime/rendering @@ -542,9 +567,13 @@ void DrumGizmoVst::processReplacing(  	if(buffer_size != (size_t)sampleFrames)  	{  		if(buffer) +		{  			free(buffer); +		} +  		buffer_size = sampleFrames;  		buffer = (sample_t*)malloc(sizeof(sample_t) * buffer_size); +  		drumgizmo->setFrameSize(buffer_size);  	} @@ -555,7 +584,7 @@ void DrumGizmoVst::processReplacing(  VstInt32 DrumGizmoVst::processEvents(VstEvents* ev)  { -	DEBUG(dgeditor, "%s\n", __PRETTY_FUNCTION__); +	DEBUG(vst, "%s\n", __PRETTY_FUNCTION__);  	input->processEvents(ev);  	return 1;  } | 
