diff options
| -rw-r--r-- | plugingui/plugingui.cc | 2 | ||||
| -rw-r--r-- | src/audiofile.cc | 174 | ||||
| -rw-r--r-- | src/audiofile.h | 9 | ||||
| -rw-r--r-- | src/drumgizmo.cc | 25 | ||||
| -rw-r--r-- | src/drumkitloader.cc | 208 | ||||
| -rw-r--r-- | src/drumkitloader.h | 51 | ||||
| -rw-r--r-- | src/messagehandler.cc | 7 | ||||
| -rw-r--r-- | src/messagereceiver.cc | 3 | ||||
| -rw-r--r-- | src/messagereceiver.h | 1 | ||||
| -rw-r--r-- | src/semaphore.cc | 11 | ||||
| -rw-r--r-- | src/semaphore.h | 3 | 
11 files changed, 228 insertions, 266 deletions
| diff --git a/plugingui/plugingui.cc b/plugingui/plugingui.cc index 4f16b34..e452965 100644 --- a/plugingui/plugingui.cc +++ b/plugingui/plugingui.cc @@ -153,7 +153,7 @@ void closeClick(void *ptr)  */  PluginGUI::PluginGUI() -  : MessageReceiver(MSGRCV_UI) +  : MessageReceiver(MSGRCV_UI), sem("plugingui")  {    windowClosedHandler = NULL;    changeMidimapHandler = NULL; diff --git a/src/audiofile.cc b/src/audiofile.cc index 4ac1f94..858edd7 100644 --- a/src/audiofile.cc +++ b/src/audiofile.cc @@ -37,8 +37,6 @@  #include "configuration.h" -#define LAZYLOAD -  AudioFile::AudioFile(std::string filename)  {    is_loaded = false; @@ -46,8 +44,11 @@ AudioFile::AudioFile(std::string filename)    data = NULL;    size = 0; + +#ifdef LAZYLOAD    preloaded_data = NULL; -  ref_count = 0; +#endif/*LAZYLOAD*/ +    magic = this;  } @@ -64,21 +65,104 @@ bool AudioFile::isValid()  void AudioFile::unload()  { +  // Make sure we don't unload the object while loading it...    MutexAutolock l(mutex); + +  is_loaded = false; + +#ifdef LAZYLOAD    if(data == preloaded_data) {      delete[] data;      data = NULL;      size = 0; -  } -  else { +  } else {      size = 0;      delete[] data;      data = NULL;      delete preloaded_data;      preloaded_data = NULL;    } +#else +  delete[] data; +  data = NULL; +  size = 0; +#endif/*LAZYLOAD*/ +} + +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; +  } +  +  size = sf_info.frames; + +  double ratio = (double)Conf::samplerate / (double)sf_info.samplerate; + +  if(num_samples != ALL_SAMPLES) { +    // Make sure we read enough samples, even after conversion. +    num_samples /= ratio; +    if((int)size > num_samples) size = num_samples; +  } + +  sample_t* data = new sample_t[size];  +  size = sf_read_float(fh, data, size);  +   +  DEBUG(audiofile,"Loaded %d samples %p\n", size, this); +   +  sf_close(fh); + +  if(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", size, this); +  } +   +  this->data = data; +  is_loaded = true; + +  //DEBUG(audiofile, "Loading of %s completed.\n", filename.c_str()); +} + +bool AudioFile::isLoaded() +{ +  return is_loaded;  } +#ifdef LAZYLOAD  #define SIZE 512*4   void AudioFile::init()  { @@ -173,82 +257,4 @@ void AudioFile::reset()    delete old_data;     mutex.unlock();  } - -void AudioFile::load(int num_samples) -{ -  /* -  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; -  } -  -  size = sf_info.frames; - -  double ratio = (double)Conf::samplerate / (double)sf_info.samplerate; - -  if(num_samples != ALL_SAMPLES) { -    // Make sure we read enough samples, even after conversion. -    num_samples /= ratio; -    if((int)size > num_samples) size = num_samples; -  } - -  sample_t* data = new sample_t[size];  -  size = sf_read_float(fh, data, size);  -   -  DEBUG(audiofile,"Loaded %d samples %p\n", size, this); -   -  sf_close(fh); - -  if(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", size, this); -  } - - -  mutex.lock(); -  this->data = data; -  is_loaded = true; -  mutex.unlock(); - -  //DEBUG(audiofile, "Loading of %s completed.\n", filename.c_str()); -} - -bool AudioFile::isLoaded() -{ -  bool l; - -  mutex.lock(); -  l = is_loaded; -  mutex.unlock(); - -  return l; -} +#endif diff --git a/src/audiofile.h b/src/audiofile.h index 20ffdf3..8a190c1 100644 --- a/src/audiofile.h +++ b/src/audiofile.h @@ -36,7 +36,7 @@  #include "mutex.h"  #include "audio.h" -#if 0 +/*    Plan for lazy loading of audio (Brainstorming)      * Encapsulate data array?        - Speed issues? @@ -63,9 +63,9 @@        |            --------- |                                   |      Wave Into --> | SndFile | <----- Read data (directly from array)                     ---------   -#endif/*0*/ +*/ -#define LAZYLOAD +//#define LAZYLOAD  #define ALL_SAMPLES -1 @@ -95,13 +95,12 @@ public:  #endif/*LAZYLOAD*/    bool isValid(); -  int ref_count;    Mutex mutex;  private:    void *magic; -  bool is_loaded; +  volatile bool is_loaded;  };  #endif/*__DRUMGIZMO_AUDIOFILE_H__*/ diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index b99687d..c4ef194 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -43,21 +43,13 @@  DrumGizmo::DrumGizmo(AudioOutputEngine *o, AudioInputEngine *i)    : MessageReceiver(MSGRCV_ENGINE), -    loader(this), oe(o), ie(i) +    loader(), oe(o), ie(i)  { -  loader.run(); // Start drumkit loader thread.  }  DrumGizmo::~DrumGizmo()  { -  /* -  AudioFiles::iterator i = audiofiles.begin(); -  while(i != audiofiles.end()) { -    AudioFile *audiofile = i->second; -    delete audiofile; -    i++; -  } -  */ +  DEBUG(drumgizmo, "!");    loader.stop();  } @@ -75,8 +67,10 @@ bool DrumGizmo::loadkit(std::string file)    DEBUG(drumgizmo, "loadkit(%s)\n", kitfile.c_str()); +  // Remove all queue AudioFiles from loader before we actually delete them.    loader.skip(); +  // Delete all Channels, Instruments, Samples and AudioFiles.    kit.clear();    DrumKitParser parser(kitfile, kit); @@ -94,16 +88,7 @@ bool DrumGizmo::loadkit(std::string file)  bool DrumGizmo::init(bool preload)  { -  if(preload) { -    /* -    AudioFiles::iterator i = audiofiles.begin(); -    while(i != audiofiles.end()) { -      AudioFile *audiofile = i->second; -      audiofile->load(); -      i++; -    } -    */ -  } +  (void)preload;    if(!ie->init(kit.instruments)) return false;    if(!oe->init(kit.channels)) return false; diff --git a/src/drumkitloader.cc b/src/drumkitloader.cc index a7a8989..69f656b 100644 --- a/src/drumkitloader.cc +++ b/src/drumkitloader.cc @@ -31,185 +31,129 @@  #include "drumkitparser.h"  #include "drumgizmo.h" -DrumKitLoader::DrumKitLoader(DrumGizmo *dg) +DrumKitLoader::DrumKitLoader() +  : semaphore("drumkitloader")  { -  drumgizmo = dg; -  is_done = false; -  quitit = false; -  skipit = false; +  running = true; +  run();  }  DrumKitLoader::~DrumKitLoader()  { -  if(!quitit) { +  if(running) {      stop();    }  }  void DrumKitLoader::stop()  { -  quitit = true; +  { +    MutexAutolock l(mutex); +    load_queue.clear(); +  } + +  running = false;    semaphore.post();    wait_stop();  }  void DrumKitLoader::skip()  { -  skipit = true; -  semaphore.post(); -  skip_semaphore.wait(); +  MutexAutolock l(mutex);   +  load_queue.clear();  }  bool DrumKitLoader::isDone()  { -  bool done; - -  mutex.lock(); -  done = is_done; -  mutex.unlock(); - -  return done; +  MutexAutolock l(mutex); +  return load_queue.size() == 0;  }  void DrumKitLoader::loadKit(DrumKit *kit)  { -  this->kit = kit; - -  mutex.lock(); -  is_done = false; -  mutex.unlock(); - -  semaphore.post(); -} +  MutexAutolock l(mutex); -void DrumKitLoader::prepare(AudioFile* af) -{ -  DEBUG(loader, "Preparing audiofile %p (%d in queue)\n", -        af, load_queue.size()); -  mutex.lock(); -  af->ref_count++; -  load_queue.push_back(af); -//  if(ref_count.find(af) == ref_count.end()) { -//    ref_count[af]++; -//  } -//  else { -//    ref_count[af] = 0; -//  } -  mutex.unlock();  -  semaphore.post(); -} +  DEBUG(loader, "Create AudioFile queue from DrumKit\n"); -void DrumKitLoader::reset(AudioFile* af) -{ -  mutex.lock(); -  af->ref_count--; -  reset_queue.push_back(af); -  mutex.unlock(); -  semaphore.post(); -} +  total_num_audiofiles = 0;// For UI Progress Messages -void DrumKitLoader::thread_main() -{ -  while(1) { -    DEBUG(loader, "before sem\n"); +  { // 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++; +    } +  } -    semaphore.wait(); +  { // 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++; +    } +  } -    DEBUG(loader, "after sem\n"); -    fflush(stdout); +  loaded = 0; // For UI Progress Messages +  DEBUG(loader, "Queued %d (size: %d) AudioFiles for loading.\n", +        total_num_audiofiles, load_queue.size()); -    if(quitit) return; +  semaphore.post(); // Start loader loop. +} -    if(skipit) { -      skip_semaphore.post(); -      skipit = false; -      continue; +void DrumKitLoader::thread_main() +{ +  while(running) { +    size_t size; +    { +      MutexAutolock l(mutex); +      size = load_queue.size();      } -    if(!load_queue.empty()) { -      DEBUG(loader, "Loading remaining of audio file\n");  -      AudioFile* af = load_queue.front(); -      mutex.lock(); -      load_queue.pop_front(); -      mutex.unlock(); -      af->loadNext(); -    } -    else if(!reset_queue.empty()) { -      AudioFile* af = reset_queue.front(); -      mutex.lock(); -      if(af->ref_count <= 0) { -        af->reset(); -        af->ref_count = 0; -      } -      reset_queue.pop_front(); -      mutex.unlock(); +    // Only sleep if queue is empty. +    if(size == 0) { +      //DEBUG(loader, "Wait for sem"); +      semaphore.wait(); +      //DEBUG(loader, "Sem enter");      } -    else { // Initialize drum kit -      DEBUG(loader, "Initializing drum kit\n"); -      unsigned int count = 0; - -      if(kit && !kit->isValid()) goto finish; -      { // Count total number of files that need loading: -        Instruments::iterator i = kit->instruments.begin(); -        while(i != kit->instruments.end()) { -          Instrument *instr = *i; -          if(instr && !instr->isValid()) goto finish; +    AudioFile *audiofile = NULL; -          count += instr->audiofiles.size(); -          i++; -        } -      } - -      { // Now actually load them: -        unsigned int loaded = 0; -        Instruments::iterator i = kit->instruments.begin(); -        while(i != kit->instruments.end()) { -          Instrument *instr = *i; -         -          if(instr && !instr->isValid()) goto finish; +    { +      MutexAutolock l(mutex); +      if(load_queue.size() == 0) continue; +      audiofile = load_queue.front(); +      load_queue.pop_front(); +    } -          std::vector<AudioFile*>::iterator a = instr->audiofiles.begin(); -          while(a != instr->audiofiles.end()) {  #if 0  #ifdef WIN32 -            SleepEx(5000, FALSE); +    SleepEx(5000, FALSE);  #else -            usleep(5000); +    usleep(5000);  #endif/*WIN32*/  #endif -            AudioFile *af = *a; - -            if(af && !af->isValid()) goto finish; - -            af->load(); -           -            loaded++; - -            LoadStatusMessage *ls = new LoadStatusMessage(); -            ls->number_of_files = count; -            ls->numer_of_files_loaded = loaded; -            ls->current_file = af->filename; -            msghandler.sendMessage(MSGRCV_UI, ls); -           -            a++; - -            if(skipit) goto finish; -          } -         -          i++; -        } -      } -      mutex.lock(); -      is_done = true; -      mutex.unlock(); +    audiofile->load(); +    loaded++; -    finish: -      continue; -    } +    LoadStatusMessage *ls = new LoadStatusMessage(); +    ls->number_of_files = total_num_audiofiles; +    ls->numer_of_files_loaded = loaded; +    ls->current_file = audiofile->filename; +    msghandler.sendMessage(MSGRCV_UI, ls);    } + +  DEBUG(loader, "Loader thread finished.");  }  #ifdef TEST_DRUMKITLOADER diff --git a/src/drumkitloader.h b/src/drumkitloader.h index 9d14638..be24812 100644 --- a/src/drumkitloader.h +++ b/src/drumkitloader.h @@ -36,37 +36,62 @@  #include "drumkit.h" -class DrumGizmo; - +/** + * 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: -  DrumKitLoader(DrumGizmo *drumgizmo); +  /** +   * 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(); +  /** +   * 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 prepare(AudioFile* af); -  void reset(AudioFile* af); +  // I have no idea what this does.. +  //void reset(AudioFile* af);    void thread_main(); +  /** +   * 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(); + +  /** +   * Skip all queued AudioFiles. +   */    void skip();  private: -  DrumGizmo *drumgizmo;    Semaphore semaphore; -  Semaphore skip_semaphore; -  DrumKit *kit; -  bool is_done;    Mutex mutex; -  volatile bool quitit; -  volatile bool skipit; +  volatile bool running;    std::list<AudioFile*> load_queue; -  std::list<AudioFile*> reset_queue; -  std::map<AudioFile*, int> ref_count; +  size_t total_num_audiofiles; +  size_t loaded;  };  #endif/*__DRUMGIZMO_DRUMKITLOADER_H__*/ diff --git a/src/messagehandler.cc b/src/messagehandler.cc index dcaf5f1..52a89a5 100644 --- a/src/messagehandler.cc +++ b/src/messagehandler.cc @@ -73,16 +73,17 @@ bool MessageHandler::sendMessage(message_receiver_id_t id, Message* msg)    //DEBUG(msghandler, "Sending message to id %d\n", id);    MessageReceiver *receiver = receivers[id]; - +  /* // This code causes sporadic segfaults on windows.    if(msg->processing_mode() == Message::FilterMultiple) {      Message *pmsg; +    MutexAutolock lock(receiver->message_mutex); // Make peek/receive atomic.      while( (pmsg = receiver->peekMessage()) != NULL) { -      if(pmsg->type() != Message::LoadStatus) break; +      if(pmsg->type() != msg->type()) break;        // Remove all old messages with same type.        delete receiver->receiveMessage();      }    } - +  */    receiver->sendMessage(msg);    return true;  } diff --git a/src/messagereceiver.cc b/src/messagereceiver.cc index f391aad..a24482b 100644 --- a/src/messagereceiver.cc +++ b/src/messagereceiver.cc @@ -47,7 +47,6 @@ void MessageReceiver::sendMessage(Message *msg)  Message *MessageReceiver::receiveMessage()  { -  MutexAutolock l(message_mutex);    Message *msg = NULL;    if(message_queue.size()) {      msg = message_queue.front(); @@ -58,7 +57,6 @@ Message *MessageReceiver::receiveMessage()  Message *MessageReceiver::peekMessage()  { -  MutexAutolock l(message_mutex);    Message *msg = NULL;    if(message_queue.size()) {      msg = message_queue.front(); @@ -68,6 +66,7 @@ Message *MessageReceiver::peekMessage()  void MessageReceiver::handleMessages(size_t max)  { +  MutexAutolock l(message_mutex);    bool process_all = false;    if(max == 0) process_all = true; diff --git a/src/messagereceiver.h b/src/messagereceiver.h index 4185f29..2794091 100644 --- a/src/messagereceiver.h +++ b/src/messagereceiver.h @@ -34,6 +34,7 @@  #include "messagehandler.h"  class MessageReceiver { +  friend class MessageHandler;  public:    MessageReceiver(message_receiver_id_t id);    ~MessageReceiver(); diff --git a/src/semaphore.cc b/src/semaphore.cc index d43835a..5d90c55 100644 --- a/src/semaphore.cc +++ b/src/semaphore.cc @@ -42,9 +42,10 @@ struct semaphore_private_t {  #endif  }; -Semaphore::Semaphore() +Semaphore::Semaphore(const char *name)  { -  DEBUG(semaphore, "Create\n"); +  this->name = name; +  DEBUG(semaphore, "Create [%s]\n", name);    prv = new struct semaphore_private_t(); @@ -60,7 +61,7 @@ Semaphore::Semaphore()  Semaphore::~Semaphore()  { -  DEBUG(semaphore, "Delete\n"); +  DEBUG(semaphore, "Delete [%s]\n", name);  #ifdef WIN32    CloseHandle(prv->semaphore); @@ -73,7 +74,7 @@ Semaphore::~Semaphore()  void Semaphore::post()  { -  DEBUG(semaphore, "Post\n"); +  DEBUG(semaphore, "Post [%s]\n", name);  #ifdef WIN32    ReleaseSemaphore(prv->semaphore, 1, NULL); @@ -84,7 +85,7 @@ void Semaphore::post()  void Semaphore::wait()  { -  DEBUG(semaphore, "Wait\n"); +  DEBUG(semaphore, "Wait [%s]\n", name);  #ifdef WIN32    WaitForSingleObject(prv->semaphore, INFINITE); diff --git a/src/semaphore.h b/src/semaphore.h index 7f8a6ff..7e39f5a 100644 --- a/src/semaphore.h +++ b/src/semaphore.h @@ -31,7 +31,7 @@ struct semaphore_private_t;  class Semaphore {  public: -  Semaphore(); +  Semaphore(const char *name = "");    ~Semaphore();    void post(); @@ -39,6 +39,7 @@ public:  private:    struct semaphore_private_t *prv; +  const char *name;  };  #endif/*__PRACRO_SEMAPHORE_H__*/ | 
