<commit_before>#include "vm.hpp"
#include "shared_state.hpp"
#include "config_parser.hpp"
#include "config.h"
#include "objectmemory.hpp"
#include "environment.hpp"
#include "instruments/tooling.hpp"
#include "instruments/timing.hpp"
#include "global_cache.hpp"
#include "capi/handles.hpp"
#include "capi/tag.hpp"

#include "util/thread.hpp"
#include "inline_cache.hpp"
#include "configuration.hpp"

#include "agent.hpp"
#include "world_state.hpp"
#include "builtin/randomizer.hpp"
#include "builtin/array.hpp"
#include "builtin/thread.hpp"

#include <iostream>
#include <iomanip>

#ifdef ENABLE_LLVM
#include "llvm/state.hpp"
#endif

namespace rubinius {

  SharedState::SharedState(Environment* env, Configuration& config, ConfigParser& cp)
    : initialized_(false)
    , auxiliary_threads_(0)
    , signal_handler_(0)
    , global_handles_(new capi::Handles)
    , global_serial_(0)
    , world_(new WorldState)
    , ic_registry_(new InlineCacheRegistry)
    , class_count_(0)
    , thread_ids_(1)
    , kcode_page_(kcode::eAscii)
    , kcode_table_(kcode::null_table())
    , agent_(0)
    , root_vm_(0)
    , env_(env)
    , tool_broker_(new tooling::ToolBroker)
    , ruby_critical_set_(false)
    , use_capi_lock_(false)
    , check_gc_(false)
    , om(0)

    , global_cache(new GlobalCache)
    , config(config)
    , user_variables(cp)
    , llvm_state(0)
  {
    ref();

    auxiliary_threads_ = new AuxiliaryThreads();

    for(int i = 0; i < Primitives::cTotalPrimitives; i++) {
      primitive_hits_[i] = 0;
    }

    hash_seed = Randomizer::random_uint32();
  }

  SharedState::~SharedState() {
    if(!initialized_) return;

    if(config.gc_show) {
      std::cerr << "Time spent waiting for the world to stop: " << world_->time_waiting() << "ns\n";
    }

#ifdef ENABLE_LLVM
    if(llvm_state) {
      delete llvm_state;
    }
#endif

    if(agent_) {
      delete agent_;
    }

    delete global_handles_;
    delete tool_broker_;
    delete global_cache;
    delete ic_registry_;
    delete world_;
    delete om;
    delete auxiliary_threads_;
  }

  void SharedState::add_managed_thread(ManagedThread* thr) {
    SYNC_TL;
    threads_.push_back(thr);
  }

  void SharedState::remove_managed_thread(ManagedThread* thr) {
    SYNC_TL;
    threads_.remove(thr);
  }

  int SharedState::size() {
    return sizeof(SharedState) +
      sizeof(WorldState) +
      symbols.byte_size();
  }

  void SharedState::discard(SharedState* ss) {
    if(ss->deref()) delete ss;
  }

  uint32_t SharedState::new_thread_id() {
    return atomic::fetch_and_add(&thread_ids_, 1);
  }

  VM* SharedState::new_vm() {
    uint32_t id = new_thread_id();

    SYNC_TL;

    // TODO calculate the thread id by finding holes in the
    // field of ids, so we reuse ids.

    VM* vm = new VM(id, *this);
    threads_.push_back(vm);

    this->ref();

    // If there is no root vm, then the first one created becomes it.
    if(!root_vm_) root_vm_ = vm;
    return vm;
  }

  void SharedState::remove_vm(VM* vm) {
    SYNC_TL;
    threads_.remove(vm);
    this->deref();

    // Don't delete ourself here, it's too problematic.
  }

  Array* SharedState::vm_threads(STATE) {
    SYNC_TL;

    Array* threads = Array::create(state, 0);
    for(std::list<ManagedThread*>::iterator i = threads_.begin();
        i != threads_.end();
        ++i) {
      if(VM* vm = (*i)->as_vm()) {
        Thread *thread = vm->thread.get();
        if(!thread->system_thread() && CBOOL(thread->alive())) {
          threads->append(state, thread);
        }
      }
    }
    return threads;
  }

  capi::Handle* SharedState::add_global_handle(STATE, Object* obj) {
    if(!obj->reference_p()) {
      rubinius::bug("Trying to add a handle for a non reference");
    }
    uintptr_t handle_index = global_handles_->allocate_index(state, obj);
    obj->set_handle_index(state, handle_index);
    return obj->handle(state);
  }

  void SharedState::make_handle_cached(STATE, capi::Handle* handle) {
    SYNC(state);
    cached_handles_.push_back(handle);
  }

  void SharedState::add_global_handle_location(capi::Handle** loc,
                                               const char* file, int line)
  {
    SYNC_TL;
    if(*loc && REFERENCE_P(*loc)) {
      if(!global_handles_->validate(*loc)) {
        std::cerr << std::endl << "==================================== ERROR ====================================" << std::endl;
        std::cerr << "| An extension is trying to add an invalid handle at the following location:  |" << std::endl;
        std::ostringstream out;
        out << file << ":" << line;
        std::cerr << "| " << std::left << std::setw(75) << out.str() << " |" << std::endl;
        std::cerr << "|                                                                             |" << std::endl;
        std::cerr << "| An invalid handle means that it points to an invalid VALUE. This can happen |" << std::endl;
        std::cerr << "| when you haven't initialized the VALUE pointer yet, in which case we        |" << std::endl;
        std::cerr << "| suggest either initializing it properly or otherwise first initialize it to |" << std::endl;
        std::cerr << "| NULL if you can only set it to a proper VALUE pointer afterwards. Consider  |" << std::endl;
        std::cerr << "| the following example that could cause this problem:                        |" << std::endl;
        std::cerr << "|                                                                             |" << std::endl;
        std::cerr << "| VALUE ptr;                                                                  |" << std::endl;
        std::cerr << "| rb_gc_register_address(&ptr);                                               |" << std::endl;
        std::cerr << "| ptr = rb_str_new(\"test\");                                                   |" << std::endl;
        std::cerr << "|                                                                             |" << std::endl;
        std::cerr << "| Either change this register after initializing                              |" << std::endl;
        std::cerr << "|                                                                             |" << std::endl;
        std::cerr << "| VALUE ptr;                                                                  |" << std::endl;
        std::cerr << "| ptr = rb_str_new(\"test\");                                                   |" << std::endl;
        std::cerr << "| rb_gc_register_address(&ptr);                                               |" << std::endl;
        std::cerr << "|                                                                             |" << std::endl;
        std::cerr << "| Or initialize it with NULL:                                                 |" << std::endl;
        std::cerr << "|                                                                             |" << std::endl;
        std::cerr << "| VALUE ptr = NULL;                                                           |" << std::endl;
        std::cerr << "| rb_gc_register_address(&ptr);                                               |" << std::endl;
        std::cerr << "| ptr = rb_str_new(\"test\");                                                   |" << std::endl;
        std::cerr << "|                                                                             |" << std::endl;
        std::cerr << "================================== ERROR ======================================" << std::endl;
        rubinius::bug("Halting due to invalid handle");
      }
    }

    capi::GlobalHandle* global_handle = new capi::GlobalHandle(loc, file, line);
    global_handle_locations_.push_back(global_handle);
  }

  void SharedState::del_global_handle_location(capi::Handle** loc) {
    SYNC_TL;

    for(std::list<capi::GlobalHandle*>::iterator i = global_handle_locations_.begin();
        i != global_handle_locations_.end(); ++i) {
      if((*i)->handle() == loc) {
        delete *i;
        global_handle_locations_.erase(i);
        return;
      }
    }
    rubinius::bug("Removing handle not in the list");
  }

  QueryAgent* SharedState::start_agent(STATE) {
    SYNC(state);

    if(!agent_) {
      agent_ = new QueryAgent(state);
    }

    return agent_;
  }

  void SharedState::reinit(STATE) {
    // For now, we disable inline debugging here. This makes inspecting
    // it much less confusing.

    config.jit_inline_debug.set("no");

    env_->set_root_vm(state->vm());
    threads_.clear();
    threads_.push_back(state->vm());

    // Reinit the locks for this object
    lock_init(state->vm());
    global_cache->lock_init(state->vm());
    ic_registry_->lock_init(state->vm());
    onig_lock_.init();
    ruby_critical_lock_.init();
    capi_lock_.init();

    world_->reinit();
  }

  bool SharedState::should_stop() {
    return world_->should_stop();
  }

  bool SharedState::stop_the_world(THREAD) {
    return world_->wait_til_alone(state);
  }

  void SharedState::stop_threads_externally() {
    world_->stop_threads_externally();
  }

  void SharedState::restart_world(THREAD) {
    world_->wake_all_waiters(state);
  }

  void SharedState::restart_threads_externally() {
    world_->restart_threads_externally();
  }

  bool SharedState::checkpoint(THREAD) {
    return world_->checkpoint(state);
  }

  void SharedState::gc_dependent(STATE) {
    world_->become_dependent(state->vm());
  }

  void SharedState::gc_independent(STATE) {
    world_->become_independent(state->vm());
  }

  void SharedState::gc_dependent(THREAD) {
    world_->become_dependent(state);
  }

  void SharedState::gc_independent(THREAD) {
    world_->become_independent(state);
  }

  void SharedState::set_critical(STATE) {
    SYNC(state);

    if(!ruby_critical_set_ ||
         !pthread_equal(ruby_critical_thread_, pthread_self())) {

      UNSYNC;
      GCIndependent gc_guard(state);
      ruby_critical_lock_.lock();
      ruby_critical_thread_ = pthread_self();
      ruby_critical_set_ = true;
    }

    return;
  }

  void SharedState::clear_critical(STATE) {
    SYNC(state);

    if(ruby_critical_set_ && pthread_equal(ruby_critical_thread_, pthread_self())) {
      ruby_critical_set_ = false;
      ruby_critical_lock_.unlock();
    }
  }

  void SharedState::enter_capi(STATE, const char* file, int line) {
    if(use_capi_lock_) {
      capi_lock_.lock(state->vm(), file, line);
    }
  }

  void SharedState::leave_capi(STATE) {
    if(use_capi_lock_) {
      capi_lock_.unlock(state->vm());
    }
  }
}
<commit_msg>Ensure cleanup of global handle locations<commit_after>#include "vm.hpp"
#include "shared_state.hpp"
#include "config_parser.hpp"
#include "config.h"
#include "objectmemory.hpp"
#include "environment.hpp"
#include "instruments/tooling.hpp"
#include "instruments/timing.hpp"
#include "global_cache.hpp"
#include "capi/handles.hpp"
#include "capi/tag.hpp"

#include "util/thread.hpp"
#include "inline_cache.hpp"
#include "configuration.hpp"

#include "agent.hpp"
#include "world_state.hpp"
#include "builtin/randomizer.hpp"
#include "builtin/array.hpp"
#include "builtin/thread.hpp"

#include <iostream>
#include <iomanip>

#ifdef ENABLE_LLVM
#include "llvm/state.hpp"
#endif

namespace rubinius {

  SharedState::SharedState(Environment* env, Configuration& config, ConfigParser& cp)
    : initialized_(false)
    , auxiliary_threads_(0)
    , signal_handler_(0)
    , global_handles_(new capi::Handles)
    , global_serial_(0)
    , world_(new WorldState)
    , ic_registry_(new InlineCacheRegistry)
    , class_count_(0)
    , thread_ids_(1)
    , kcode_page_(kcode::eAscii)
    , kcode_table_(kcode::null_table())
    , agent_(0)
    , root_vm_(0)
    , env_(env)
    , tool_broker_(new tooling::ToolBroker)
    , ruby_critical_set_(false)
    , use_capi_lock_(false)
    , check_gc_(false)
    , om(0)

    , global_cache(new GlobalCache)
    , config(config)
    , user_variables(cp)
    , llvm_state(0)
  {
    ref();

    auxiliary_threads_ = new AuxiliaryThreads();

    for(int i = 0; i < Primitives::cTotalPrimitives; i++) {
      primitive_hits_[i] = 0;
    }

    hash_seed = Randomizer::random_uint32();
  }

  SharedState::~SharedState() {
    if(!initialized_) return;

    if(config.gc_show) {
      std::cerr << "Time spent waiting for the world to stop: " << world_->time_waiting() << "ns\n";
    }

#ifdef ENABLE_LLVM
    if(llvm_state) {
      delete llvm_state;
    }
#endif

    if(agent_) {
      delete agent_;
    }

    for(std::list<capi::GlobalHandle*>::iterator i = global_handle_locations_.begin();
          i != global_handle_locations_.end();
          ++i) {
      capi::GlobalHandle* global_handle = *i;
      delete global_handle;
    }

    delete global_handles_;
    delete tool_broker_;
    delete global_cache;
    delete ic_registry_;
    delete world_;
    delete om;
    delete auxiliary_threads_;
  }

  void SharedState::add_managed_thread(ManagedThread* thr) {
    SYNC_TL;
    threads_.push_back(thr);
  }

  void SharedState::remove_managed_thread(ManagedThread* thr) {
    SYNC_TL;
    threads_.remove(thr);
  }

  int SharedState::size() {
    return sizeof(SharedState) +
      sizeof(WorldState) +
      symbols.byte_size();
  }

  void SharedState::discard(SharedState* ss) {
    if(ss->deref()) delete ss;
  }

  uint32_t SharedState::new_thread_id() {
    return atomic::fetch_and_add(&thread_ids_, 1);
  }

  VM* SharedState::new_vm() {
    uint32_t id = new_thread_id();

    SYNC_TL;

    // TODO calculate the thread id by finding holes in the
    // field of ids, so we reuse ids.

    VM* vm = new VM(id, *this);
    threads_.push_back(vm);

    this->ref();

    // If there is no root vm, then the first one created becomes it.
    if(!root_vm_) root_vm_ = vm;
    return vm;
  }

  void SharedState::remove_vm(VM* vm) {
    SYNC_TL;
    threads_.remove(vm);
    this->deref();

    // Don't delete ourself here, it's too problematic.
  }

  Array* SharedState::vm_threads(STATE) {
    SYNC_TL;

    Array* threads = Array::create(state, 0);
    for(std::list<ManagedThread*>::iterator i = threads_.begin();
        i != threads_.end();
        ++i) {
      if(VM* vm = (*i)->as_vm()) {
        Thread *thread = vm->thread.get();
        if(!thread->system_thread() && CBOOL(thread->alive())) {
          threads->append(state, thread);
        }
      }
    }
    return threads;
  }

  capi::Handle* SharedState::add_global_handle(STATE, Object* obj) {
    if(!obj->reference_p()) {
      rubinius::bug("Trying to add a handle for a non reference");
    }
    uintptr_t handle_index = global_handles_->allocate_index(state, obj);
    obj->set_handle_index(state, handle_index);
    return obj->handle(state);
  }

  void SharedState::make_handle_cached(STATE, capi::Handle* handle) {
    SYNC(state);
    cached_handles_.push_back(handle);
  }

  void SharedState::add_global_handle_location(capi::Handle** loc,
                                               const char* file, int line)
  {
    SYNC_TL;
    if(*loc && REFERENCE_P(*loc)) {
      if(!global_handles_->validate(*loc)) {
        std::cerr << std::endl << "==================================== ERROR ====================================" << std::endl;
        std::cerr << "| An extension is trying to add an invalid handle at the following location:  |" << std::endl;
        std::ostringstream out;
        out << file << ":" << line;
        std::cerr << "| " << std::left << std::setw(75) << out.str() << " |" << std::endl;
        std::cerr << "|                                                                             |" << std::endl;
        std::cerr << "| An invalid handle means that it points to an invalid VALUE. This can happen |" << std::endl;
        std::cerr << "| when you haven't initialized the VALUE pointer yet, in which case we        |" << std::endl;
        std::cerr << "| suggest either initializing it properly or otherwise first initialize it to |" << std::endl;
        std::cerr << "| NULL if you can only set it to a proper VALUE pointer afterwards. Consider  |" << std::endl;
        std::cerr << "| the following example that could cause this problem:                        |" << std::endl;
        std::cerr << "|                                                                             |" << std::endl;
        std::cerr << "| VALUE ptr;                                                                  |" << std::endl;
        std::cerr << "| rb_gc_register_address(&ptr);                                               |" << std::endl;
        std::cerr << "| ptr = rb_str_new(\"test\");                                                   |" << std::endl;
        std::cerr << "|                                                                             |" << std::endl;
        std::cerr << "| Either change this register after initializing                              |" << std::endl;
        std::cerr << "|                                                                             |" << std::endl;
        std::cerr << "| VALUE ptr;                                                                  |" << std::endl;
        std::cerr << "| ptr = rb_str_new(\"test\");                                                   |" << std::endl;
        std::cerr << "| rb_gc_register_address(&ptr);                                               |" << std::endl;
        std::cerr << "|                                                                             |" << std::endl;
        std::cerr << "| Or initialize it with NULL:                                                 |" << std::endl;
        std::cerr << "|                                                                             |" << std::endl;
        std::cerr << "| VALUE ptr = NULL;                                                           |" << std::endl;
        std::cerr << "| rb_gc_register_address(&ptr);                                               |" << std::endl;
        std::cerr << "| ptr = rb_str_new(\"test\");                                                   |" << std::endl;
        std::cerr << "|                                                                             |" << std::endl;
        std::cerr << "================================== ERROR ======================================" << std::endl;
        rubinius::bug("Halting due to invalid handle");
      }
    }

    capi::GlobalHandle* global_handle = new capi::GlobalHandle(loc, file, line);
    global_handle_locations_.push_back(global_handle);
  }

  void SharedState::del_global_handle_location(capi::Handle** loc) {
    SYNC_TL;

    for(std::list<capi::GlobalHandle*>::iterator i = global_handle_locations_.begin();
        i != global_handle_locations_.end(); ++i) {
      if((*i)->handle() == loc) {
        delete *i;
        global_handle_locations_.erase(i);
        return;
      }
    }
    rubinius::bug("Removing handle not in the list");
  }

  QueryAgent* SharedState::start_agent(STATE) {
    SYNC(state);

    if(!agent_) {
      agent_ = new QueryAgent(state);
    }

    return agent_;
  }

  void SharedState::reinit(STATE) {
    // For now, we disable inline debugging here. This makes inspecting
    // it much less confusing.

    config.jit_inline_debug.set("no");

    env_->set_root_vm(state->vm());
    threads_.clear();
    threads_.push_back(state->vm());

    // Reinit the locks for this object
    lock_init(state->vm());
    global_cache->lock_init(state->vm());
    ic_registry_->lock_init(state->vm());
    onig_lock_.init();
    ruby_critical_lock_.init();
    capi_lock_.init();

    world_->reinit();
  }

  bool SharedState::should_stop() {
    return world_->should_stop();
  }

  bool SharedState::stop_the_world(THREAD) {
    return world_->wait_til_alone(state);
  }

  void SharedState::stop_threads_externally() {
    world_->stop_threads_externally();
  }

  void SharedState::restart_world(THREAD) {
    world_->wake_all_waiters(state);
  }

  void SharedState::restart_threads_externally() {
    world_->restart_threads_externally();
  }

  bool SharedState::checkpoint(THREAD) {
    return world_->checkpoint(state);
  }

  void SharedState::gc_dependent(STATE) {
    world_->become_dependent(state->vm());
  }

  void SharedState::gc_independent(STATE) {
    world_->become_independent(state->vm());
  }

  void SharedState::gc_dependent(THREAD) {
    world_->become_dependent(state);
  }

  void SharedState::gc_independent(THREAD) {
    world_->become_independent(state);
  }

  void SharedState::set_critical(STATE) {
    SYNC(state);

    if(!ruby_critical_set_ ||
         !pthread_equal(ruby_critical_thread_, pthread_self())) {

      UNSYNC;
      GCIndependent gc_guard(state);
      ruby_critical_lock_.lock();
      ruby_critical_thread_ = pthread_self();
      ruby_critical_set_ = true;
    }

    return;
  }

  void SharedState::clear_critical(STATE) {
    SYNC(state);

    if(ruby_critical_set_ && pthread_equal(ruby_critical_thread_, pthread_self())) {
      ruby_critical_set_ = false;
      ruby_critical_lock_.unlock();
    }
  }

  void SharedState::enter_capi(STATE, const char* file, int line) {
    if(use_capi_lock_) {
      capi_lock_.lock(state->vm(), file, line);
    }
  }

  void SharedState::leave_capi(STATE) {
    if(use_capi_lock_) {
      capi_lock_.unlock(state->vm());
    }
  }
}
<|endoftext|>


<commit_before>#include "VoiceDB.h"

using namespace std;

VoiceDB::VoiceDB():path_singer(L"") {}

VoiceDB::VoiceDB(const wstring& path_singer)
{
  setSingerPath(path_singer);
}

VoiceDB::~VoiceDB() {}

bool VoiceDB::initVoiceMap()
{
  namespace fs = boost::filesystem;
  const fs::path path(path_singer);

  if (fs::is_directory(path)) {
    BOOST_FOREACH(const fs::path& p, std::make_pair(fs::recursive_directory_iterator(path), fs::recursive_directory_iterator())) {
      if (p.leaf().wstring() == L"oto.ini") {
        wcout << L"loading " << p.wstring() << endl;
        initVoiceMap(p.wstring());
      }
    }
    if (voice_map.size() > 0)
      return true;
  }

  cerr << "[VoiceDB::initVoiceMap] path_singer is invalid" << endl;
  return false;
}

bool VoiceDB::initVoiceMap(const wstring& path_oto_ini)
{
  boost::filesystem::wifstream ifs(path_oto_ini);
  boost::filesystem::path path_ini(path_oto_ini);
  wstring buf, wav_ext=L".wav";
  while (ifs && getline(ifs, buf)) {
    // read oto.ini
    Voice tmp_voice(this);
    vector<wstring> v1, v2;
    boost::algorithm::split(v1, buf, boost::is_any_of("="));
    boost::algorithm::split(v2, v1[1], boost::is_any_of(","));
    short tmp;
    tmp_voice.setWavPath((path_ini.parent_path()/v1[0]).wstring());
    tmp_voice.offs = (((tmp=boost::lexical_cast<double>(v2[1]))>0))?tmp:0;
    tmp_voice.cons = (((tmp=boost::lexical_cast<double>(v2[2]))>0))?tmp:0;
    tmp_voice.blnk = boost::lexical_cast<double>(v2[3]);
    tmp_voice.prec = boost::lexical_cast<double>(v2[4]);
    tmp_voice.ovrl = boost::lexical_cast<double>(v2[5]);
    tmp_voice.is_vcv = false;
    // sanitize
    if (tmp_voice.ovrl > tmp_voice.prec) {
      tmp_voice.prec = tmp_voice.ovrl;
    }
    if (tmp_voice.prec > tmp_voice.cons) {
      tmp_voice.cons = tmp_voice.prec;
    }
    if (tmp_voice.blnk<0 && tmp_voice.cons > -tmp_voice.blnk) {
      tmp_voice.blnk = -tmp_voice.cons;
    }
    if (tmp_voice.offs < 0) {
      short tmp = -tmp_voice.offs;
      tmp_voice.offs = 0;
      tmp_voice.ovrl += tmp;
      tmp_voice.cons += tmp;
      tmp_voice.prec += tmp;
      if (tmp_voice.blnk < 0) {
        tmp_voice.blnk -= tmp;
      }
    }
    // get Voice pron
    tmp_voice.setAlias((v2[0]==L"")?tmp_voice.path_wav.stem().wstring():v2[0]);
    tmp_voice.is_vcv = (tmp_voice.alias.prefix!=L"- " && tmp_voice.alias.prefix!=L"* " && !tmp_voice.alias.prefix.empty());
    // set vowel_map
    if (!tmp_voice.is_vcv) {
      map<wstring, wstring>::const_iterator it = nak::getVow2PronIt(tmp_voice.getPron());
      if (it!=nak::vow2pron.end() && (tmp_voice.alias.prefix==L"- "||tmp_voice.alias.prefix.empty())) {
        WavParser wav_parser(tmp_voice.path_wav.wstring());
        wav_parser.addTargetTrack(0);
        if (wav_parser.parse()) {
          vector<double> tmp_wav = (*(wav_parser.getDataChunks().begin())).getData();
          vector<double>::iterator it_tmp_wav_cons = tmp_wav.begin()+((tmp_voice.offs+tmp_voice.cons)/1000.0*wav_parser.getFormat().dwSamplesPerSec);
          vector<double>::iterator it_tmp_wav_min = it_tmp_wav_cons;
          short win_size = wav_parser.getFormat().dwSamplesPerSec / tmp_voice.getFrq();
          double tmp_min_rms = -1.0;
          for (size_t i=0; i<win_size*2; i++) {
            vector<double> tmp_wav(it_tmp_wav_cons+i-win_size, it_tmp_wav_cons+i+win_size);
            double tmp_rms = nak::getRMS(tmp_wav);
            if (tmp_rms<tmp_min_rms || tmp_min_rms<0) {
              tmp_min_rms = tmp_rms;
              it_tmp_wav_min = it_tmp_wav_cons+i;
            }
          }
          vowel_map[nak::pron2vow[it->second]+tmp_voice.alias.suffix].assign(it_tmp_wav_min-win_size, it_tmp_wav_min+win_size);
        }
      }
    }
    voice_map[tmp_voice.getAliasString()] = tmp_voice;
  }
  return true;
}

/*
 * accessor
 */
const Voice* VoiceDB::getVoice(const wstring& alias) const
{
  if (!isAlias(alias))
    return 0;

  return &(voice_map.at(alias));
}

bool VoiceDB::isAlias(const wstring& alias) const
{
  return !(voice_map.empty() || voice_map.count(alias)==0);
}

bool VoiceDB::isVowel(const wstring& subject) const
{
  return vowel_map.count(subject)>0;
}

const vector<double>& VoiceDB::getVowel(const wstring& subject) const
{
  return vowel_map.at(subject);
}

void VoiceDB::setSingerPath(const wstring& path_singer)
{
  this->path_singer = path_singer;
}

const wstring& VoiceDB::getSingerPath() const
{
  return this->path_singer;
}
<commit_msg>change pitchmark start point<commit_after>#include "VoiceDB.h"

using namespace std;

VoiceDB::VoiceDB():path_singer(L"") {}

VoiceDB::VoiceDB(const wstring& path_singer)
{
  setSingerPath(path_singer);
}

VoiceDB::~VoiceDB() {}

bool VoiceDB::initVoiceMap()
{
  namespace fs = boost::filesystem;
  const fs::path path(path_singer);

  if (fs::is_directory(path)) {
    BOOST_FOREACH(const fs::path& p, std::make_pair(fs::recursive_directory_iterator(path), fs::recursive_directory_iterator())) {
      if (p.leaf().wstring() == L"oto.ini") {
        wcout << L"loading " << p.wstring() << endl;
        initVoiceMap(p.wstring());
      }
    }
    if (voice_map.size() > 0)
      return true;
  }

  cerr << "[VoiceDB::initVoiceMap] path_singer is invalid" << endl;
  return false;
}

bool VoiceDB::initVoiceMap(const wstring& path_oto_ini)
{
  boost::filesystem::wifstream ifs(path_oto_ini);
  boost::filesystem::path path_ini(path_oto_ini);
  wstring buf, wav_ext=L".wav";
  while (ifs && getline(ifs, buf)) {
    // read oto.ini
    Voice tmp_voice(this);
    vector<wstring> v1, v2;
    boost::algorithm::split(v1, buf, boost::is_any_of("="));
    boost::algorithm::split(v2, v1[1], boost::is_any_of(","));
    short tmp;
    tmp_voice.setWavPath((path_ini.parent_path()/v1[0]).wstring());
    tmp_voice.offs = (((tmp=boost::lexical_cast<double>(v2[1]))>0))?tmp:0;
    tmp_voice.cons = (((tmp=boost::lexical_cast<double>(v2[2]))>0))?tmp:0;
    tmp_voice.blnk = boost::lexical_cast<double>(v2[3]);
    tmp_voice.prec = boost::lexical_cast<double>(v2[4]);
    tmp_voice.ovrl = boost::lexical_cast<double>(v2[5]);
    tmp_voice.is_vcv = false;
    // sanitize
    if (tmp_voice.ovrl > tmp_voice.prec) {
      tmp_voice.prec = tmp_voice.ovrl;
    }
    if (tmp_voice.prec > tmp_voice.cons) {
      tmp_voice.cons = tmp_voice.prec;
    }
    if (tmp_voice.blnk<0 && tmp_voice.cons > -tmp_voice.blnk) {
      tmp_voice.blnk = -tmp_voice.cons;
    }
    if (tmp_voice.offs < 0) {
      short tmp = -tmp_voice.offs;
      tmp_voice.offs = 0;
      tmp_voice.ovrl += tmp;
      tmp_voice.cons += tmp;
      tmp_voice.prec += tmp;
      if (tmp_voice.blnk < 0) {
        tmp_voice.blnk -= tmp;
      }
    }
    // get Voice pron
    tmp_voice.setAlias((v2[0]==L"")?tmp_voice.path_wav.stem().wstring():v2[0]);
    tmp_voice.is_vcv = (tmp_voice.alias.prefix!=L"- " && tmp_voice.alias.prefix!=L"* " && !tmp_voice.alias.prefix.empty());
    // set vowel_map
    if (!tmp_voice.is_vcv) {
      map<wstring, wstring>::const_iterator it = nak::getVow2PronIt(tmp_voice.getPron());
      if (it!=nak::vow2pron.end() && (tmp_voice.alias.prefix==L"- "||tmp_voice.alias.prefix.empty())) {
        WavParser wav_parser(tmp_voice.path_wav.wstring());
        wav_parser.addTargetTrack(0);
        if (wav_parser.parse()) {
          short win_size = wav_parser.getFormat().dwSamplesPerSec / tmp_voice.getFrq();
          double tmp_max_rms = -1.0;
          vector<double> tmp_win = nak::getLanczos(win_size*2, nak::unit_waveform_lobe);
          vector<double> tmp_wav = (*(wav_parser.getDataChunks().begin())).getData();
          vector<double>::iterator it_tmp_wav_cons = tmp_wav.begin()+((tmp_voice.offs+tmp_voice.cons)/1000.0*wav_parser.getFormat().dwSamplesPerSec);
          vector<double>::iterator it_tmp_wav_max = it_tmp_wav_cons;
          for (size_t i=0; i<win_size*2; i++) {
            vector<double> tmp_wav(it_tmp_wav_cons+i-win_size, it_tmp_wav_cons+i+win_size);
            for (size_t j=0; j<tmp_wav.size(); j++) {
              tmp_wav[j] *= tmp_win[j];
            }
            double tmp_rms = nak::getRMS(tmp_wav);
            if (tmp_rms>tmp_max_rms) {
              tmp_max_rms = tmp_rms;
              it_tmp_wav_max = it_tmp_wav_cons+i;
            }
          }
          vowel_map[nak::pron2vow[it->second]+tmp_voice.alias.suffix].assign(it_tmp_wav_max-win_size, it_tmp_wav_max+win_size);
        }
      }
    }
    voice_map[tmp_voice.getAliasString()] = tmp_voice;
  }
  return true;
}

/*
 * accessor
 */
const Voice* VoiceDB::getVoice(const wstring& alias) const
{
  if (!isAlias(alias))
    return 0;

  return &(voice_map.at(alias));
}

bool VoiceDB::isAlias(const wstring& alias) const
{
  return !(voice_map.empty() || voice_map.count(alias)==0);
}

bool VoiceDB::isVowel(const wstring& subject) const
{
  return vowel_map.count(subject)>0;
}

const vector<double>& VoiceDB::getVowel(const wstring& subject) const
{
  return vowel_map.at(subject);
}

void VoiceDB::setSingerPath(const wstring& path_singer)
{
  this->path_singer = path_singer;
}

const wstring& VoiceDB::getSingerPath() const
{
  return this->path_singer;
}
<|endoftext|>