mas01cr@416: #include mas01cr@416: #include mas01cr@416: #include mas01cr@416: #include mas01cr@416: #include mas01cr@416: #include "audioDB.h" mas01cr@416: extern "C" { mas01cr@416: #include "audioDB_API.h" mas01cr@416: } mas01cr@416: #include "audioDB-internals.h" mas01cr@416: mas01cr@416: #ifndef ACCUMULATOR_H mas01cr@416: #define ACCUMULATOR_H mas01cr@416: mas01cr@416: class Accumulator { mas01cr@416: public: mas01cr@416: virtual ~Accumulator() {}; mas01cr@416: virtual void add_point(adb_result_t *r) = 0; mas01cr@416: virtual adb_query_results_t *get_points() = 0; mas01cr@416: }; mas01cr@416: mas01cr@416: template class DBAccumulator : public Accumulator { mas01cr@416: public: mas01cr@416: DBAccumulator(unsigned int pointNN); mas01cr@416: ~DBAccumulator(); mas01cr@416: void add_point(adb_result_t *r); mas01cr@416: adb_query_results_t *get_points(); mas01cr@416: private: mas01cr@416: unsigned int pointNN; mas01cr@416: std::priority_queue< adb_result_t, std::vector, T > *queue; mas01cr@416: std::set< adb_result_t, adb_result_triple_lt > *set; mas01cr@416: }; mas01cr@416: mas01cr@416: template DBAccumulator::DBAccumulator(unsigned int pointNN) mas01cr@416: : pointNN(pointNN), queue(0), set(0) { mas01cr@416: queue = new std::priority_queue< adb_result_t, std::vector, T>; mas01cr@416: set = new std::set; mas01cr@416: } mas01cr@416: mas01cr@416: template DBAccumulator::~DBAccumulator() { mas01cr@416: if(queue) { mas01cr@416: delete queue; mas01cr@416: } mas01cr@416: if(set) { mas01cr@416: delete set; mas01cr@416: } mas01cr@416: } mas01cr@416: mas01cr@416: template void DBAccumulator::add_point(adb_result_t *r) { mas01cr@416: if(!isnan(r->dist)) { mas01cr@416: if(set->find(*r) == set->end()) { mas01cr@416: set->insert(*r); mas01cr@416: queue->push(*r); mas01cr@416: if(queue->size() > pointNN) { mas01cr@416: queue->pop(); mas01cr@416: } mas01cr@416: } mas01cr@416: } mas01cr@416: } mas01cr@416: mas01cr@416: template adb_query_results_t *DBAccumulator::get_points() { mas01cr@416: unsigned int size = queue->size(); mas01cr@416: adb_query_results_t *r = (adb_query_results_t *) malloc(sizeof(adb_query_results_t)); mas01cr@416: adb_result_t *rs = (adb_result_t *) calloc(size, sizeof(adb_result_t)); mas01cr@416: r->nresults = size; mas01cr@416: r->results = rs; mas01cr@416: mas01cr@416: for(unsigned int k = 0; k < size; k++) { mas01cr@416: rs[k] = queue->top(); mas01cr@416: queue->pop(); mas01cr@416: } mas01cr@416: return r; mas01cr@416: } mas01cr@416: mas01cr@416: template class PerTrackAccumulator : public Accumulator { mas01cr@416: public: mas01cr@416: PerTrackAccumulator(unsigned int pointNN, unsigned int trackNN); mas01cr@416: ~PerTrackAccumulator(); mas01cr@416: void add_point(adb_result_t *r); mas01cr@416: adb_query_results_t *get_points(); mas01cr@416: private: mas01cr@416: unsigned int pointNN; mas01cr@416: unsigned int trackNN; mas01cr@416: std::map, T > *, adb_result_key_lt> *queues; mas01cr@416: std::set< adb_result_t, adb_result_triple_lt > *set; mas01cr@416: }; mas01cr@416: mas01cr@416: template PerTrackAccumulator::PerTrackAccumulator(unsigned int pointNN, unsigned int trackNN) mas01cr@416: : pointNN(pointNN), trackNN(trackNN), queues(0), set(0) { mas01cr@416: queues = new std::map, T > *, adb_result_key_lt>; mas01cr@416: set = new std::set< adb_result_t, adb_result_triple_lt >; mas01cr@416: } mas01cr@416: mas01cr@416: template PerTrackAccumulator::~PerTrackAccumulator() { mas01cr@416: if(queues) { mas01cr@416: typename std::map< adb_result_t, std::priority_queue< adb_result_t, std::vector< adb_result_t >, T > *, adb_result_key_lt>::iterator it; mas01cr@416: for(it = queues->begin(); it != queues->end(); it++) { mas01cr@416: delete (*it).second; mas01cr@416: } mas01cr@416: delete queues; mas01cr@416: } mas01cr@416: if(set) { mas01cr@416: delete set; mas01cr@416: } mas01cr@416: } mas01cr@416: mas01cr@416: template void PerTrackAccumulator::add_point(adb_result_t *r) { mas01cr@416: if(!isnan(r->dist)) { mas01cr@416: if(set->find(*r) == set->end()) { mas01cr@416: set->insert(*r); mas01cr@416: mas01cr@416: typename std::map< adb_result_t, std::priority_queue< adb_result_t, std::vector< adb_result_t >, T > *, adb_result_key_lt>::iterator it; mas01cr@416: std::priority_queue< adb_result_t, std::vector< adb_result_t >, T > *queue; mas01cr@416: it = queues->find(*r); mas01cr@416: if(it == queues->end()) { mas01cr@416: queue = new std::priority_queue< adb_result_t, std::vector< adb_result_t >, T >; mas01cr@416: (*queues)[*r] = queue; mas01cr@416: } else { mas01cr@416: queue = (*it).second; mas01cr@416: } mas01cr@416: mas01cr@416: queue->push(*r); mas01cr@416: if(queue->size() > pointNN) { mas01cr@416: queue->pop(); mas01cr@416: } mas01cr@416: } mas01cr@416: } mas01cr@416: } mas01cr@416: mas01cr@416: template adb_query_results_t *PerTrackAccumulator::get_points() { mas01cr@416: typename std::map< adb_result_t, std::vector< adb_result_t >, adb_result_key_lt> points; mas01cr@416: typename std::priority_queue< adb_result_t, std::vector< adb_result_t >, T> queue; mas01cr@416: typename std::map< adb_result_t, std::priority_queue< adb_result_t, std::vector< adb_result_t >, T > *, adb_result_key_lt>::iterator it; mas01cr@416: mas01cr@416: unsigned int size = 0; mas01cr@416: for(it = queues->begin(); it != queues->end(); it++) { mas01cr@416: unsigned int n = ((*it).second)->size(); mas01cr@416: std::vector v; mas01cr@416: adb_result_t r; mas01cr@416: double dist = 0; mas01cr@416: for(unsigned int k = 0; k < n; k++) { mas01cr@416: r = ((*it).second)->top(); mas01cr@416: dist += r.dist; mas01cr@416: v.push_back(r); mas01cr@416: ((*it).second)->pop(); mas01cr@416: } mas01cr@416: points[r] = v; mas01cr@416: dist /= n; mas01cr@416: size += n; mas01cr@416: r.dist = dist; mas01cr@416: /* I will burn in hell */ mas01cr@416: r.ipos = n; mas01cr@416: queue.push(r); mas01cr@416: if(queue.size() > trackNN) { mas01cr@416: size -= queue.top().ipos; mas01cr@416: queue.pop(); mas01cr@416: } mas01cr@416: } mas01cr@416: mas01cr@416: adb_query_results_t *r = (adb_query_results_t *) malloc(sizeof(adb_query_results_t)); mas01cr@416: adb_result_t *rs = (adb_result_t *) calloc(size, sizeof(adb_result_t)); mas01cr@416: r->nresults = size; mas01cr@416: r->results = rs; mas01cr@416: mas01cr@416: unsigned int k = 0; mas01cr@416: while(queue.size() > 0) { mas01cr@416: std::vector v = points[queue.top()]; mas01cr@416: queue.pop(); mas01cr@416: while(v.size() > 0) { mas01cr@416: rs[k++] = v.back(); mas01cr@416: v.pop_back(); mas01cr@416: } mas01cr@416: } mas01cr@416: return r; mas01cr@416: } mas01cr@416: mas01cr@416: template class NearestAccumulator : public Accumulator { mas01cr@416: public: mas01cr@416: NearestAccumulator(); mas01cr@416: ~NearestAccumulator(); mas01cr@416: void add_point(adb_result_t *r); mas01cr@416: adb_query_results_t *get_points(); mas01cr@416: private: mas01cr@416: std::set< adb_result_t, adb_result_triple_lt > *set; mas01cr@416: std::set< adb_result_t, adb_result_qpos_lt > *points; mas01cr@416: }; mas01cr@416: mas01cr@416: template NearestAccumulator::NearestAccumulator() mas01cr@416: : set(0), points(0) { mas01cr@416: set = new std::set< adb_result_t, adb_result_triple_lt >; mas01cr@416: points = new std::set< adb_result_t, adb_result_qpos_lt >; mas01cr@416: } mas01cr@416: mas01cr@416: template NearestAccumulator::~NearestAccumulator() { mas01cr@416: if(set) { mas01cr@416: delete set; mas01cr@416: } mas01cr@416: if(points) { mas01cr@416: delete points; mas01cr@416: } mas01cr@416: } mas01cr@416: mas01cr@416: template void NearestAccumulator::add_point(adb_result_t *r) { mas01cr@416: if(!isnan(r->dist)) { mas01cr@416: if(set->find(*r) == set->end()) { mas01cr@416: set->insert(*r); mas01cr@416: mas01cr@416: std::set< adb_result_t, adb_result_qpos_lt >::iterator it; mas01cr@416: it = points->find(*r); mas01cr@416: if(it == points->end()) { mas01cr@416: points->insert(*r); mas01cr@416: } else if(T()(*(const adb_result_t *)r,(*it))) { mas01cr@416: points->erase(it); mas01cr@416: points->insert(*r); mas01cr@416: } mas01cr@416: } mas01cr@416: } mas01cr@416: } mas01cr@416: mas01cr@416: template adb_query_results_t *NearestAccumulator::get_points() { mas01cr@416: unsigned int nresults = points->size(); mas01cr@416: adb_query_results_t *r = (adb_query_results_t *) malloc(sizeof(adb_query_results_t)); mas01cr@416: adb_result_t *rs = (adb_result_t *) calloc(nresults, sizeof(adb_result_t)); mas01cr@416: r->nresults = nresults; mas01cr@416: r->results = rs; mas01cr@416: std::set< adb_result_t, adb_result_qpos_lt >::iterator it; mas01cr@416: unsigned int k = 0; mas01cr@416: for(it = points->begin(); it != points->end(); it++) { mas01cr@416: rs[k++] = *it; mas01cr@416: } mas01cr@416: return r; mas01cr@416: } mas01cr@416: mas01cr@416: #endif