diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.am.drumgizmo | 3 | ||||
| -rw-r--r-- | src/audiofile.cc | 36 | ||||
| -rw-r--r-- | src/chresampler.cc | 170 | ||||
| -rw-r--r-- | src/chresampler.h | 65 | ||||
| -rw-r--r-- | src/drumgizmo.cc | 63 | ||||
| -rw-r--r-- | src/drumgizmo.h | 8 | ||||
| -rw-r--r-- | src/drumkit.cc | 6 | ||||
| -rw-r--r-- | src/drumkit.h | 3 | ||||
| -rw-r--r-- | src/drumkitparser.cc | 8 | 
9 files changed, 320 insertions, 42 deletions
| diff --git a/src/Makefile.am.drumgizmo b/src/Makefile.am.drumgizmo index c48c478..26e2a30 100644 --- a/src/Makefile.am.drumgizmo +++ b/src/Makefile.am.drumgizmo @@ -3,6 +3,7 @@ DRUMGIZMO_SOURCES = \  	$(top_srcdir)/src/audiofile.cc \  	$(top_srcdir)/src/channel.cc \  	$(top_srcdir)/src/channelmixer.cc \ +	$(top_srcdir)/src/chresampler.cc \  	$(top_srcdir)/src/configuration.cc \  	$(top_srcdir)/src/configparser.cc \  	$(top_srcdir)/src/drumgizmo.cc \ @@ -26,4 +27,4 @@ DRUMGIZMO_SOURCES = \  	$(top_srcdir)/src/velocity.cc \  	$(top_srcdir)/src/versionstr.cc -DRUMGIZMO_LIBS = $(SNDFILE_LIBS) $(EXPAT_LIBS) $(SAMPLERATE_LIBS)
\ No newline at end of file +DRUMGIZMO_LIBS = $(ZITA_LIBS) $(SNDFILE_LIBS) $(EXPAT_LIBS) $(SAMPLERATE_LIBS)
\ No newline at end of file diff --git a/src/audiofile.cc b/src/audiofile.cc index 874b9c5..59e0c14 100644 --- a/src/audiofile.cc +++ b/src/audiofile.cc @@ -34,9 +34,6 @@  #include <stdlib.h>  #include <unistd.h>  #include <sndfile.h> -#ifdef WITH_RESAMPLE -#include <samplerate.h> -#endif/*WITH_RESAMPLE*/  #include <hugin.hpp>  #include "configuration.h" @@ -154,39 +151,6 @@ void AudioFile::load(int num_samples)    sf_close(fh); -#ifdef WITH_RESAMPLE - -  // Check environment to see if resample should be disabled. -  // Defaults to "1" which is 'enable'. All other values are 'disabled'. -  const char *env_res = getenv("DRUMGIZMO_RESAMPLE"); -  if(env_res == NULL) env_res = "1"; - -  if( (strcmp(env_res, "1") == 0) && -      Conf::samplerate != sf_info.samplerate) { -    // Resample data... -    size_t osize = size * ratio; -    sample_t *odata = new sample_t[osize]; - -    SRC_DATA src; -    src.data_in = data; -    src.input_frames = size; - -    src.data_out = odata; -    src.output_frames = osize; - -    src.src_ratio = ratio; - -    // Do the conversion -    src_simple(&src, SRC_SINC_BEST_QUALITY, 1); - -    delete[] data; -    data = odata; -    size = src.output_frames; - -    DEBUG(audiofile,"Converted into %d samples %p\n", (int)size, this); -  } -#endif/*WITH_RESAMPLE*/ -    this->data = data;    is_loaded = true; diff --git a/src/chresampler.cc b/src/chresampler.cc new file mode 100644 index 0000000..301e650 --- /dev/null +++ b/src/chresampler.cc @@ -0,0 +1,170 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            chresampler.cc + * + *  Tue Sep 23 20:42:14 CEST 2014 + *  Copyright 2014 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 "chresampler.h" + +#include <config.h> +#include <hugin.hpp> +#include <stdio.h> + +#ifdef WITH_RESAMPLER + +#if defined(USE_ZITA) +  #include <zita-resampler/resampler.h> +#elif defined(USE_SRC) +  #include <samplerate.h> +#else +  #error "No resampler selected" +#endif + +class CHResampler::Prv { +public: +#if defined(USE_ZITA) +  Resampler zita; +#elif defined(USE_SRC) +  SRC_STATE *state; +  SRC_DATA data; +#endif +}; + +CHResampler::CHResampler() +{ +  input_fs = 44100; +  output_fs = 44100; + +  prv = new Prv(); +#if defined(SRC) +  prv->state = NULL; +#endif +} + +void CHResampler::setup(double input_fs, double output_fs) +{ +  int nchan = 1; // always mono + +  this->input_fs = input_fs; +  this->output_fs = output_fs; + +#if defined(USE_ZITA) +  DEBUG(resampler, "Using zita-resampler (%d -> %d)", (int)input_fs, (int)output_fs); + +  int hlen = 72; // 16 ≤ hlen ≤ 96 +  // delay is 2 * hlen, 72 corresponds to delay introduced by SRC. +  prv->zita.setup(input_fs, output_fs, nchan, hlen); +#elif defined(USE_SRC) +  DEBUG(resampler, "Using libsamplerate (%d -> %d)", (int)input_fs, (int)output_fs); + +  int err; +  prv->state = src_new(SRC_SINC_BEST_QUALITY, nchan, &err); +  (void)err; +  //  printf("err: %d\n", err); +  src_set_ratio(prv->state, output_fs / input_fs); +  prv->data.src_ratio = output_fs / input_fs; +  prv->data.end_of_input = 0; +#endif +} + +CHResampler::~CHResampler() +{ +#if defined(USE_ZITA) +#elif defined(USE_SRC) +  if(prv->state) src_delete(prv->state); +#endif +  delete prv; +} + +void CHResampler::setInputSamples(float *samples, size_t count) +{ +#if defined(USE_ZITA) +  prv->zita.inp_data = samples; +  prv->zita.inp_count = count; +#elif defined(USE_SRC) +  prv->data.data_in = samples; +  prv->data.input_frames = count; +#endif +} + +void CHResampler::setOutputSamples(float *samples, size_t count) +{ +#if defined(USE_ZITA) +  prv->zita.out_data = samples; +  prv->zita.out_count = count; +#elif defined(USE_SRC) +  prv->data.data_out = samples; +  prv->data.output_frames = count; +#endif +} + +void CHResampler::process() +{ +#if defined(USE_ZITA) +  prv->zita.process(); +#elif defined(USE_SRC) +  src_process(prv->state, &prv->data); +  prv->data.output_frames -= prv->data.output_frames_gen; +  prv->data.data_out +=  prv->data.output_frames_gen; +  prv->data.input_frames -= prv->data.input_frames_used; +  prv->data.data_in += prv->data.input_frames_used; +#endif +} + +size_t CHResampler::getInputSampleCount() +{ +#if defined(USE_ZITA) +  return prv->zita.inp_count; +#elif defined(USE_SRC) +  return prv->data.input_frames; +#endif +} + +size_t CHResampler::getOutputSampleCount() +{ +#if defined(USE_ZITA) +  return prv->zita.out_count; +#elif defined(USE_SRC) +  return prv->data.output_frames; +#endif +} + +double CHResampler::ratio() +{ +  return input_fs / output_fs; +} + +#else + +// Dummy implementation +CHResampler::CHResampler() {} +CHResampler::~CHResampler() {} +void CHResampler::setup(double, double) {} +void CHResampler::setInputSamples(float *, size_t) {} +void CHResampler::setOutputSamples(float *, size_t) {} +void CHResampler::process() {} +size_t CHResampler::getInputSampleCount() { return 0; } +size_t CHResampler::getOutputSampleCount() { return 0; } +double CHResampler::ratio() { return 1; } + +#endif/*WITH_RESAMPLER*/ diff --git a/src/chresampler.h b/src/chresampler.h new file mode 100644 index 0000000..5943627 --- /dev/null +++ b/src/chresampler.h @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            chresampler.h + * + *  Tue Sep 23 20:42:14 CEST 2014 + *  Copyright 2014 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_CHRESAMPLER_H__ +#define __DRUMGIZMO_CHRESAMPLER_H__ + +#include <stdlib.h> + +/** + * Channel resampler class using either zita-resampler or secret rabbit code + * (really!!) depending on the value of the WITH_RESAMPLER macro. + * If WITH_RESAMPLER is unset the resampler is disabled entirely. + * If WITH_RESAMPLER=="zita" zita-resampler will be used. + * If WITH_RESAMPLER=="src" Secret Rabbit Code will be used. + */ +class CHResampler { +public: +  CHResampler(); +  ~CHResampler(); + +  void setup(double input_fs, double output_fs); + +  void setInputSamples(float *samples, size_t count); +  void setOutputSamples(float *samples, size_t count); + +  void process(); + +  size_t getInputSampleCount(); +  size_t getOutputSampleCount(); + +  double ratio(); + +private: +  class Prv; +  Prv *prv; + +  double input_fs; +  double output_fs; +}; + + +#endif/*__DRUMGIZMO_CHRESAMPLER_H__*/ diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index 0337fae..6b48cda 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -36,6 +36,8 @@  #include <hugin.hpp> +#include <config.h> +  #include "drumkitparser.h"  #include "audioinputenginemidi.h"  #include "configuration.h" @@ -71,6 +73,12 @@ bool DrumGizmo::loadkit(std::string file)    loader.loadKit(&kit); +#ifdef WITH_RESAMPLER +  for(int i = 0; i < MAX_NUM_CHANNELS; i++) { +    resampler[i].setup(kit.samplerate(), Conf::samplerate); +  } +#endif/*WITH_RESAMPLER*/ +    DEBUG(loadkit, "loadkit: Success\n");    return true; @@ -239,7 +247,7 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples)          } 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; +          evt->offset = (evs[e].offset + pos) * resampler[0].ratio();            activeevents[ch.num].push_back(evt);          }          j++; @@ -253,11 +261,12 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples)    }    free(evs); -   -   +    //    // Write audio    // +#ifndef WITH_RESAMPLER +  // No resampling needed    for(size_t c = 0; c < kit.channels.size(); c++) {      sample_t *buf = samples;      bool internal = false; @@ -269,9 +278,49 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples)        memset(buf, 0, nsamples * sizeof(sample_t));        getSamples(c, pos, buf, nsamples); +        if(!internal) oe->run(c, samples, nsamples);      }    } +#else/*WITH_RESAMPLER*/ +  // 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(); +  //printf("ratio: %f\n", resampler[c].ratio()); +  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]; +        size_t insize = sizeof(resampler_input_buffer[c]) / sizeof(sample_t); +        memset(resampler_input_buffer[c], 0, +               sizeof(resampler_input_buffer[c])); +        getSamples(c, kitpos, sin, insize); +        kitpos += insize; + +        resampler[c].setInputSamples(sin, insize); +      } +      resampler[c].process(); +    } +  } + +  // 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); @@ -332,7 +381,7 @@ void DrumGizmo::getSamples(int ch, int pos, sample_t *s, size_t sz)          size_t n = 0;          if(evt->offset > (size_t)pos) n = evt->offset - pos;          size_t end = sz; -        if(evt->t + end - n > af->size) end = af->size - evt->t + n; +        if((evt->t + end - n) > af->size) end = af->size - evt->t + n;          if(end > sz) end = sz;          if(evt->rampdown == NO_RAMPDOWN) { @@ -391,6 +440,12 @@ int DrumGizmo::samplerate()  void DrumGizmo::setSamplerate(int samplerate)  {    Conf::samplerate = samplerate; +#ifdef WITH_RESAMPLER +  for(int i = 0; i < MAX_NUM_CHANNELS; i++) { +    resampler[i].setup(kit.samplerate(), Conf::samplerate); +  } +#endif/*WITH_RESAMPLER*/ +  }  std::string float2str(float a) diff --git a/src/drumgizmo.h b/src/drumgizmo.h index 37b26e5..138e61c 100644 --- a/src/drumgizmo.h +++ b/src/drumgizmo.h @@ -45,7 +45,9 @@  #include "messagereceiver.h" -#define MAX_NUM_CHANNELS 512 +#include "chresampler.h" + +#define MAX_NUM_CHANNELS 64  class DrumGizmo : public MessageReceiver {  public: @@ -87,6 +89,10 @@ private:    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][64]; +    std::map<std::string, AudioFile *> audiofiles;  #ifdef TEST_DRUMGIZMO diff --git a/src/drumkit.cc b/src/drumkit.cc index c2aa221..4d75f3b 100644 --- a/src/drumkit.cc +++ b/src/drumkit.cc @@ -50,6 +50,7 @@ void DrumKit::clear()    _name = "";    _description = ""; +  _samplerate = 44100;  }  bool DrumKit::isValid() @@ -72,6 +73,11 @@ std::string DrumKit::description()    return _description;  } +size_t DrumKit::samplerate() +{ +  return _samplerate; +} +  #ifdef TEST_DRUMKIT  //Additional dependency files  //deps: diff --git a/src/drumkit.h b/src/drumkit.h index 82fe69b..04b2c56 100644 --- a/src/drumkit.h +++ b/src/drumkit.h @@ -53,6 +53,8 @@ public:    bool isValid(); +  size_t samplerate(); +  private:    void *magic; @@ -60,6 +62,7 @@ private:    std::string _name;    std::string _description; +  size_t _samplerate;    VersionStr _version;  }; diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index 1b7ecaf..2c21c52 100644 --- a/src/drumkitparser.cc +++ b/src/drumkitparser.cc @@ -60,6 +60,14 @@ void DrumKitParser::startTag(std::string name,      if(attr.find("name") != attr.end())        kit._name = attr["name"]; +    if(attr.find("samplerate") != attr.end()) { +      kit._samplerate = atoi(attr["samplerate"].c_str()); +    } else { +      // If 'samplerate' attribute is missing, assume 44k1Hz +      // TODO: Ask instrument what samplerate is in the audiofiles... +      kit._samplerate = 44100; +    } +      if(attr.find("description") != attr.end())        kit._description = attr["description"]; | 
