annotate thread/AsynchronousTask.h @ 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 2aed32965291
children 701233f8ed41
rev   line source
c@292 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
c@292 2
c@292 3 /*
c@292 4 QM DSP Library
c@292 5
c@292 6 Centre for Digital Music, Queen Mary, University of London.
c@292 7 This file Copyright 2009 QMUL.
c@292 8 */
c@292 9
c@292 10 #ifndef _ASYNCHRONOUS_TASK_H_
c@292 11 #define _ASYNCHRONOUS_TASK_H_
c@292 12
c@292 13 #include "Thread.h"
c@292 14
c@294 15 #include <iostream>
c@294 16
c@292 17 /**
c@292 18 * AsynchronousTask provides a thread pattern implementation for
c@292 19 * threads which are used to perform a series of similar operations in
c@292 20 * parallel with other threads of the same type.
c@292 21 *
c@292 22 * For example, a thread used to calculate FFTs of a particular block
c@292 23 * size in the context of a class that needs to calculate many block
c@292 24 * sizes of FFT at once may be a candidate for an AsynchronousTask.
c@292 25 *
c@292 26 * The general use pattern is:
c@292 27 *
c@292 28 * caller -> request thread A calculate something
c@292 29 * caller -> request thread B calculate something
c@292 30 * caller -> request thread C calculate something
c@292 31 * caller -> wait for threads A, B, and C
c@292 32 *
c@292 33 * Here threads A, B, and C may be AsynchronousTasks. An important
c@292 34 * point is that the caller must be prepared to block when waiting for
c@292 35 * these threads to complete (i.e. they are started asynchronously,
c@292 36 * but testing for completion is synchronous).
c@292 37 */
c@292 38 class AsynchronousTask : public Thread
c@292 39 {
c@292 40 public:
c@292 41 AsynchronousTask() :
c@292 42 m_todo("AsynchronousTask: task to perform"),
c@292 43 m_done("AsynchronousTask: task complete"),
c@292 44 m_inTask(false),
c@292 45 m_finishing(false)
c@292 46 {
c@292 47 start();
c@292 48 }
c@292 49 virtual ~AsynchronousTask()
c@292 50 {
c@294 51 m_todo.lock();
c@292 52 m_finishing = true;
c@292 53 m_todo.signal();
c@294 54 m_todo.unlock();
c@292 55 wait();
c@292 56 }
c@292 57
c@292 58 // Subclass must provide methods to request task and obtain
c@292 59 // results, which the caller calls. The method that requests a
c@292 60 // new task should set up any internal state and call startTask(),
c@292 61 // which then calls back on the subclass implementation of
c@292 62 // performTask from within its work thread. The method that
c@292 63 // obtains results should call awaitTask() and then return any
c@292 64 // results from internal state.
c@292 65
c@292 66 protected:
c@292 67 void startTask() {
c@294 68 m_done.lock();
c@292 69 m_todo.lock();
c@292 70 m_inTask = true;
c@292 71 m_todo.signal();
c@292 72 m_todo.unlock();
c@292 73 }
c@292 74 void awaitTask() {
c@294 75 m_done.wait();
c@292 76 m_done.unlock();
c@292 77 }
c@292 78
c@292 79 virtual void performTask() = 0;
c@292 80
c@292 81 private:
c@292 82 virtual void run() {
c@292 83 m_todo.lock();
c@294 84 while (1) {
c@292 85 while (!m_inTask && !m_finishing) {
c@292 86 m_todo.wait();
c@292 87 }
c@292 88 if (m_finishing) {
c@294 89 m_done.lock();
c@293 90 m_inTask = false;
c@293 91 m_done.signal();
c@294 92 m_done.unlock();
c@292 93 break;
c@292 94 }
c@294 95 performTask();
c@294 96 m_done.lock();
c@294 97 m_inTask = false;
c@294 98 m_done.signal();
c@294 99 m_done.unlock();
c@292 100 }
c@292 101 m_todo.unlock();
c@292 102 }
c@292 103
c@292 104 Condition m_todo;
c@292 105 Condition m_done;
c@292 106 bool m_inTask;
c@292 107 bool m_finishing;
c@292 108 };
c@292 109
c@292 110 #endif