Mercurial > hg > qm-dsp
view thread/Thread.cpp @ 298:255e431ae3d4
* Key detector: when returning key strengths, use the peak value of the
three underlying chromagram correlations (from 36-bin chromagram)
corresponding to each key, instead of the mean.
Rationale: This is the same method as used when returning the key value,
and it's nice to have the same results in both returned value and plot.
The peak performed better than the sum with a simple test set of triads,
so it seems reasonable to change the plot to match the key output rather
than the other way around.
* FFT: kiss_fftr returns only the non-conjugate bins, synthesise the rest
rather than leaving them (perhaps dangerously) undefined. Fixes an
uninitialised data error in chromagram that could cause garbage results
from key detector.
* Constant Q: remove precalculated values again, I reckon they're not
proving such a good tradeoff.
author | Chris Cannam <c.cannam@qmul.ac.uk> |
---|---|
date | Fri, 05 Jun 2009 15:12:39 +0000 |
parents | f6fb85073d64 |
children | e4a57215ddee |
line wrap: on
line source
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* QM DSP Library Centre for Digital Music, Queen Mary, University of London. This file copyright Chris Cannam, used with permission. */ #include "Thread.h" #include <iostream> #include <cstdlib> #ifdef USE_PTHREADS #include <sys/time.h> #include <time.h> #endif using std::cerr; using std::endl; using std::string; #ifdef _WIN32 Thread::Thread() : m_id(0), m_extant(false) { #ifdef DEBUG_THREAD cerr << "THREAD DEBUG: Created thread object " << this << endl; #endif } Thread::~Thread() { #ifdef DEBUG_THREAD cerr << "THREAD DEBUG: Destroying thread object " << this << ", id " << m_id << endl; #endif if (m_extant) { WaitForSingleObject(m_id, INFINITE); } #ifdef DEBUG_THREAD cerr << "THREAD DEBUG: Destroyed thread object " << this << endl; #endif } void Thread::start() { m_id = CreateThread(NULL, 0, staticRun, this, 0, 0); if (!m_id) { cerr << "ERROR: thread creation failed" << endl; exit(1); } else { #ifdef DEBUG_THREAD cerr << "THREAD DEBUG: Created thread " << m_id << " for thread object " << this << endl; #endif m_extant = true; } } void Thread::wait() { if (m_extant) { #ifdef DEBUG_THREAD cerr << "THREAD DEBUG: Waiting on thread " << m_id << " for thread object " << this << endl; #endif WaitForSingleObject(m_id, INFINITE); #ifdef DEBUG_THREAD cerr << "THREAD DEBUG: Waited on thread " << m_id << " for thread object " << this << endl; #endif m_extant = false; } } Thread::Id Thread::id() { return m_id; } bool Thread::threadingAvailable() { return true; } DWORD Thread::staticRun(LPVOID arg) { Thread *thread = static_cast<Thread *>(arg); #ifdef DEBUG_THREAD cerr << "THREAD DEBUG: " << (void *)GetCurrentThreadId() << ": Running thread " << thread->m_id << " for thread object " << thread << endl; #endif thread->run(); return 0; } Mutex::Mutex() #ifndef NO_THREAD_CHECKS : m_lockedBy(-1) #endif { m_mutex = CreateMutex(NULL, FALSE, NULL); #ifdef DEBUG_MUTEX cerr << "MUTEX DEBUG: " << (void *)GetCurrentThreadId() << ": Initialised mutex " << &m_mutex << endl; #endif } Mutex::~Mutex() { #ifdef DEBUG_MUTEX cerr << "MUTEX DEBUG: " << (void *)GetCurrentThreadId() << ": Destroying mutex " << &m_mutex << endl; #endif CloseHandle(m_mutex); } void Mutex::lock() { #ifndef NO_THREAD_CHECKS DWORD tid = GetCurrentThreadId(); if (m_lockedBy == tid) { cerr << "ERROR: Deadlock on mutex " << &m_mutex << endl; } #endif #ifdef DEBUG_MUTEX cerr << "MUTEX DEBUG: " << (void *)tid << ": Want to lock mutex " << &m_mutex << endl; #endif WaitForSingleObject(m_mutex, INFINITE); #ifndef NO_THREAD_CHECKS m_lockedBy = tid; #endif #ifdef DEBUG_MUTEX cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << endl; #endif } void Mutex::unlock() { #ifndef NO_THREAD_CHECKS DWORD tid = GetCurrentThreadId(); if (m_lockedBy != tid) { cerr << "ERROR: Mutex " << &m_mutex << " not owned by unlocking thread" << endl; return; } #endif #ifdef DEBUG_MUTEX cerr << "MUTEX DEBUG: " << (void *)tid << ": Unlocking mutex " << &m_mutex << endl; #endif #ifndef NO_THREAD_CHECKS m_lockedBy = -1; #endif ReleaseMutex(m_mutex); } bool Mutex::trylock() { #ifndef NO_THREAD_CHECKS DWORD tid = GetCurrentThreadId(); #endif DWORD result = WaitForSingleObject(m_mutex, 0); if (result == WAIT_TIMEOUT || result == WAIT_FAILED) { #ifdef DEBUG_MUTEX cerr << "MUTEX DEBUG: " << (void *)tid << ": Mutex " << &m_mutex << " unavailable" << endl; #endif return false; } else { #ifndef NO_THREAD_CHECKS m_lockedBy = tid; #endif #ifdef DEBUG_MUTEX cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << " (from trylock)" << endl; #endif return true; } } Condition::Condition(string name) : m_locked(false) #ifdef DEBUG_CONDITION , m_name(name) #endif { m_mutex = CreateMutex(NULL, FALSE, NULL); m_condition = CreateEvent(NULL, FALSE, FALSE, NULL); #ifdef DEBUG_CONDITION cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Initialised condition " << &m_condition << " \"" << m_name << "\"" << endl; #endif } Condition::~Condition() { #ifdef DEBUG_CONDITION cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Destroying condition " << &m_condition << " \"" << m_name << "\"" << endl; #endif if (m_locked) ReleaseMutex(m_mutex); CloseHandle(m_condition); CloseHandle(m_mutex); } void Condition::lock() { #ifdef DEBUG_CONDITION cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Want to lock " << &m_condition << " \"" << m_name << "\"" << endl; #endif WaitForSingleObject(m_mutex, INFINITE); m_locked = true; #ifdef DEBUG_CONDITION cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Locked " << &m_condition << " \"" << m_name << "\"" << endl; #endif } void Condition::unlock() { if (!m_locked) { #ifdef DEBUG_CONDITION cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Not locked " << &m_condition << " \"" << m_name << "\"" << endl; #endif return; } #ifdef DEBUG_CONDITION cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Unlocking " << &m_condition << " \"" << m_name << "\"" << endl; #endif m_locked = false; ReleaseMutex(m_mutex); } void Condition::wait(int us) { if (us == 0) { #ifdef DEBUG_CONDITION cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Waiting on " << &m_condition << " \"" << m_name << "\"" << endl; #endif SignalObjectAndWait(m_mutex, m_condition, INFINITE, FALSE); WaitForSingleObject(m_mutex, INFINITE); } else { DWORD ms = us / 1000; if (us > 0 && ms == 0) ms = 1; #ifdef DEBUG_CONDITION cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Timed waiting on " << &m_condition << " \"" << m_name << "\"" << endl; #endif SignalObjectAndWait(m_mutex, m_condition, ms, FALSE); WaitForSingleObject(m_mutex, INFINITE); } #ifdef DEBUG_CONDITION cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Wait done on " << &m_condition << " \"" << m_name << "\"" << endl; #endif m_locked = true; } void Condition::signal() { #ifdef DEBUG_CONDITION cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Signalling " << &m_condition << " \"" << m_name << "\"" << endl; #endif SetEvent(m_condition); } #else /* !_WIN32 */ #ifdef USE_PTHREADS Thread::Thread() : m_id(0), m_extant(false) { #ifdef DEBUG_THREAD cerr << "THREAD DEBUG: Created thread object " << this << endl; #endif } Thread::~Thread() { #ifdef DEBUG_THREAD cerr << "THREAD DEBUG: Destroying thread object " << this << ", id " << m_id << endl; #endif if (m_extant) { pthread_join(m_id, 0); } #ifdef DEBUG_THREAD cerr << "THREAD DEBUG: Destroyed thread object " << this << endl; #endif } void Thread::start() { if (pthread_create(&m_id, 0, staticRun, this)) { cerr << "ERROR: thread creation failed" << endl; exit(1); } else { #ifdef DEBUG_THREAD cerr << "THREAD DEBUG: Created thread " << m_id << " for thread object " << this << endl; #endif m_extant = true; } } void Thread::wait() { if (m_extant) { #ifdef DEBUG_THREAD cerr << "THREAD DEBUG: Waiting on thread " << m_id << " for thread object " << this << endl; #endif pthread_join(m_id, 0); #ifdef DEBUG_THREAD cerr << "THREAD DEBUG: Waited on thread " << m_id << " for thread object " << this << endl; #endif m_extant = false; } } Thread::Id Thread::id() { return m_id; } bool Thread::threadingAvailable() { return true; } void * Thread::staticRun(void *arg) { Thread *thread = static_cast<Thread *>(arg); #ifdef DEBUG_THREAD cerr << "THREAD DEBUG: " << (void *)pthread_self() << ": Running thread " << thread->m_id << " for thread object " << thread << endl; #endif thread->run(); return 0; } Mutex::Mutex() #ifndef NO_THREAD_CHECKS : m_lockedBy(0), m_locked(false) #endif { pthread_mutex_init(&m_mutex, 0); #ifdef DEBUG_MUTEX cerr << "MUTEX DEBUG: " << (void *)pthread_self() << ": Initialised mutex " << &m_mutex << endl; #endif } Mutex::~Mutex() { #ifdef DEBUG_MUTEX cerr << "MUTEX DEBUG: " << (void *)pthread_self() << ": Destroying mutex " << &m_mutex << endl; #endif pthread_mutex_destroy(&m_mutex); } void Mutex::lock() { #ifndef NO_THREAD_CHECKS pthread_t tid = pthread_self(); if (m_locked && m_lockedBy == tid) { cerr << "ERROR: Deadlock on mutex " << &m_mutex << endl; } #endif #ifdef DEBUG_MUTEX cerr << "MUTEX DEBUG: " << (void *)tid << ": Want to lock mutex " << &m_mutex << endl; #endif pthread_mutex_lock(&m_mutex); #ifndef NO_THREAD_CHECKS m_lockedBy = tid; m_locked = true; #endif #ifdef DEBUG_MUTEX cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << endl; #endif } void Mutex::unlock() { #ifndef NO_THREAD_CHECKS pthread_t tid = pthread_self(); if (!m_locked) { cerr << "ERROR: Mutex " << &m_mutex << " not locked in unlock" << endl; return; } else if (m_lockedBy != tid) { cerr << "ERROR: Mutex " << &m_mutex << " not owned by unlocking thread" << endl; return; } #endif #ifdef DEBUG_MUTEX cerr << "MUTEX DEBUG: " << (void *)tid << ": Unlocking mutex " << &m_mutex << endl; #endif #ifndef NO_THREAD_CHECKS m_locked = false; #endif pthread_mutex_unlock(&m_mutex); } bool Mutex::trylock() { #ifndef NO_THREAD_CHECKS pthread_t tid = pthread_self(); #endif if (pthread_mutex_trylock(&m_mutex)) { #ifdef DEBUG_MUTEX cerr << "MUTEX DEBUG: " << (void *)tid << ": Mutex " << &m_mutex << " unavailable" << endl; #endif return false; } else { #ifndef NO_THREAD_CHECKS m_lockedBy = tid; m_locked = true; #endif #ifdef DEBUG_MUTEX cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << " (from trylock)" << endl; #endif return true; } } Condition::Condition(string name) : m_locked(false) #ifdef DEBUG_CONDITION , m_name(name) #endif { pthread_mutex_init(&m_mutex, 0); pthread_cond_init(&m_condition, 0); #ifdef DEBUG_CONDITION cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Initialised condition " << &m_condition << " \"" << m_name << "\"" << endl; #endif } Condition::~Condition() { #ifdef DEBUG_CONDITION cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Destroying condition " << &m_condition << " \"" << m_name << "\"" << endl; #endif if (m_locked) pthread_mutex_unlock(&m_mutex); pthread_cond_destroy(&m_condition); pthread_mutex_destroy(&m_mutex); } void Condition::lock() { #ifdef DEBUG_CONDITION cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Want to lock " << &m_condition << " \"" << m_name << "\"" << endl; #endif pthread_mutex_lock(&m_mutex); m_locked = true; #ifdef DEBUG_CONDITION cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Locked " << &m_condition << " \"" << m_name << "\"" << endl; #endif } void Condition::unlock() { if (!m_locked) { #ifdef DEBUG_CONDITION cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Not locked " << &m_condition << " \"" << m_name << "\"" << endl; #endif return; } #ifdef DEBUG_CONDITION cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Unlocking " << &m_condition << " \"" << m_name << "\"" << endl; #endif m_locked = false; pthread_mutex_unlock(&m_mutex); } void Condition::wait(int us) { if (us == 0) { #ifdef DEBUG_CONDITION cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Waiting on " << &m_condition << " \"" << m_name << "\"" << endl; #endif pthread_cond_wait(&m_condition, &m_mutex); } else { struct timeval now; gettimeofday(&now, 0); now.tv_usec += us; while (now.tv_usec > 1000000) { now.tv_usec -= 1000000; ++now.tv_sec; } struct timespec timeout; timeout.tv_sec = now.tv_sec; timeout.tv_nsec = now.tv_usec * 1000; #ifdef DEBUG_CONDITION cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Timed waiting on " << &m_condition << " \"" << m_name << "\"" << endl; #endif pthread_cond_timedwait(&m_condition, &m_mutex, &timeout); } #ifdef DEBUG_CONDITION cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Wait done on " << &m_condition << " \"" << m_name << "\"" << endl; #endif m_locked = true; } void Condition::signal() { #ifdef DEBUG_CONDITION cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Signalling " << &m_condition << " \"" << m_name << "\"" << endl; #endif pthread_cond_signal(&m_condition); } #else /* !USE_PTHREADS */ Thread::Thread() { } Thread::~Thread() { } void Thread::start() { abort(); } void Thread::wait() { abort(); } Thread::Id Thread::id() { abort(); } bool Thread::threadingAvailable() { return false; } Mutex::Mutex() { } Mutex::~Mutex() { } void Mutex::lock() { abort(); } void Mutex::unlock() { abort(); } bool Mutex::trylock() { abort(); } Condition::Condition(const char *) { } Condition::~Condition() { } void Condition::lock() { abort(); } void Condition::wait(int us) { abort(); } void Condition::signal() { abort(); } #endif /* !USE_PTHREADS */ #endif /* !_WIN32 */ MutexLocker::MutexLocker(Mutex *mutex) : m_mutex(mutex) { if (m_mutex) { m_mutex->lock(); } } MutexLocker::~MutexLocker() { if (m_mutex) { m_mutex->unlock(); } }