Mercurial > hg > audiodb
comparison accumulator.h @ 416:6e6f4c1cc14d api-inversion
Initial implementation of accumulators for forthcoming audiodb_query().
Minimally tested using a temporary test harness; do not use as food.
As well as the necessary C++ magic, doodle in API header files aiming
vaguely for a sane API.
author | mas01cr |
---|---|
date | Wed, 24 Dec 2008 10:54:40 +0000 |
parents | |
children | 580f696c817c |
comparison
equal
deleted
inserted
replaced
415:447f1cf2c276 | 416:6e6f4c1cc14d |
---|---|
1 #include <string> | |
2 #include <set> | |
3 #include <queue> | |
4 #include <map> | |
5 #include <functional> | |
6 #include "audioDB.h" | |
7 extern "C" { | |
8 #include "audioDB_API.h" | |
9 } | |
10 #include "audioDB-internals.h" | |
11 | |
12 #ifndef ACCUMULATOR_H | |
13 #define ACCUMULATOR_H | |
14 | |
15 class Accumulator { | |
16 public: | |
17 virtual ~Accumulator() {}; | |
18 virtual void add_point(adb_result_t *r) = 0; | |
19 virtual adb_query_results_t *get_points() = 0; | |
20 }; | |
21 | |
22 template <class T> class DBAccumulator : public Accumulator { | |
23 public: | |
24 DBAccumulator(unsigned int pointNN); | |
25 ~DBAccumulator(); | |
26 void add_point(adb_result_t *r); | |
27 adb_query_results_t *get_points(); | |
28 private: | |
29 unsigned int pointNN; | |
30 std::priority_queue< adb_result_t, std::vector<adb_result_t>, T > *queue; | |
31 std::set< adb_result_t, adb_result_triple_lt > *set; | |
32 }; | |
33 | |
34 template <class T> DBAccumulator<T>::DBAccumulator(unsigned int pointNN) | |
35 : pointNN(pointNN), queue(0), set(0) { | |
36 queue = new std::priority_queue< adb_result_t, std::vector<adb_result_t>, T>; | |
37 set = new std::set<adb_result_t, adb_result_triple_lt>; | |
38 } | |
39 | |
40 template <class T> DBAccumulator<T>::~DBAccumulator() { | |
41 if(queue) { | |
42 delete queue; | |
43 } | |
44 if(set) { | |
45 delete set; | |
46 } | |
47 } | |
48 | |
49 template <class T> void DBAccumulator<T>::add_point(adb_result_t *r) { | |
50 if(!isnan(r->dist)) { | |
51 if(set->find(*r) == set->end()) { | |
52 set->insert(*r); | |
53 queue->push(*r); | |
54 if(queue->size() > pointNN) { | |
55 queue->pop(); | |
56 } | |
57 } | |
58 } | |
59 } | |
60 | |
61 template <class T> adb_query_results_t *DBAccumulator<T>::get_points() { | |
62 unsigned int size = queue->size(); | |
63 adb_query_results_t *r = (adb_query_results_t *) malloc(sizeof(adb_query_results_t)); | |
64 adb_result_t *rs = (adb_result_t *) calloc(size, sizeof(adb_result_t)); | |
65 r->nresults = size; | |
66 r->results = rs; | |
67 | |
68 for(unsigned int k = 0; k < size; k++) { | |
69 rs[k] = queue->top(); | |
70 queue->pop(); | |
71 } | |
72 return r; | |
73 } | |
74 | |
75 template <class T> class PerTrackAccumulator : public Accumulator { | |
76 public: | |
77 PerTrackAccumulator(unsigned int pointNN, unsigned int trackNN); | |
78 ~PerTrackAccumulator(); | |
79 void add_point(adb_result_t *r); | |
80 adb_query_results_t *get_points(); | |
81 private: | |
82 unsigned int pointNN; | |
83 unsigned int trackNN; | |
84 std::map<adb_result_t, std::priority_queue< adb_result_t, std::vector<adb_result_t>, T > *, adb_result_key_lt> *queues; | |
85 std::set< adb_result_t, adb_result_triple_lt > *set; | |
86 }; | |
87 | |
88 template <class T> PerTrackAccumulator<T>::PerTrackAccumulator(unsigned int pointNN, unsigned int trackNN) | |
89 : pointNN(pointNN), trackNN(trackNN), queues(0), set(0) { | |
90 queues = new std::map<adb_result_t, std::priority_queue< adb_result_t, std::vector<adb_result_t>, T > *, adb_result_key_lt>; | |
91 set = new std::set< adb_result_t, adb_result_triple_lt >; | |
92 } | |
93 | |
94 template <class T> PerTrackAccumulator<T>::~PerTrackAccumulator() { | |
95 if(queues) { | |
96 typename std::map< adb_result_t, std::priority_queue< adb_result_t, std::vector< adb_result_t >, T > *, adb_result_key_lt>::iterator it; | |
97 for(it = queues->begin(); it != queues->end(); it++) { | |
98 delete (*it).second; | |
99 } | |
100 delete queues; | |
101 } | |
102 if(set) { | |
103 delete set; | |
104 } | |
105 } | |
106 | |
107 template <class T> void PerTrackAccumulator<T>::add_point(adb_result_t *r) { | |
108 if(!isnan(r->dist)) { | |
109 if(set->find(*r) == set->end()) { | |
110 set->insert(*r); | |
111 | |
112 typename std::map< adb_result_t, std::priority_queue< adb_result_t, std::vector< adb_result_t >, T > *, adb_result_key_lt>::iterator it; | |
113 std::priority_queue< adb_result_t, std::vector< adb_result_t >, T > *queue; | |
114 it = queues->find(*r); | |
115 if(it == queues->end()) { | |
116 queue = new std::priority_queue< adb_result_t, std::vector< adb_result_t >, T >; | |
117 (*queues)[*r] = queue; | |
118 } else { | |
119 queue = (*it).second; | |
120 } | |
121 | |
122 queue->push(*r); | |
123 if(queue->size() > pointNN) { | |
124 queue->pop(); | |
125 } | |
126 } | |
127 } | |
128 } | |
129 | |
130 template <class T> adb_query_results_t *PerTrackAccumulator<T>::get_points() { | |
131 typename std::map< adb_result_t, std::vector< adb_result_t >, adb_result_key_lt> points; | |
132 typename std::priority_queue< adb_result_t, std::vector< adb_result_t >, T> queue; | |
133 typename std::map< adb_result_t, std::priority_queue< adb_result_t, std::vector< adb_result_t >, T > *, adb_result_key_lt>::iterator it; | |
134 | |
135 unsigned int size = 0; | |
136 for(it = queues->begin(); it != queues->end(); it++) { | |
137 unsigned int n = ((*it).second)->size(); | |
138 std::vector<adb_result_t> v; | |
139 adb_result_t r; | |
140 double dist = 0; | |
141 for(unsigned int k = 0; k < n; k++) { | |
142 r = ((*it).second)->top(); | |
143 dist += r.dist; | |
144 v.push_back(r); | |
145 ((*it).second)->pop(); | |
146 } | |
147 points[r] = v; | |
148 dist /= n; | |
149 size += n; | |
150 r.dist = dist; | |
151 /* I will burn in hell */ | |
152 r.ipos = n; | |
153 queue.push(r); | |
154 if(queue.size() > trackNN) { | |
155 size -= queue.top().ipos; | |
156 queue.pop(); | |
157 } | |
158 } | |
159 | |
160 adb_query_results_t *r = (adb_query_results_t *) malloc(sizeof(adb_query_results_t)); | |
161 adb_result_t *rs = (adb_result_t *) calloc(size, sizeof(adb_result_t)); | |
162 r->nresults = size; | |
163 r->results = rs; | |
164 | |
165 unsigned int k = 0; | |
166 while(queue.size() > 0) { | |
167 std::vector<adb_result_t> v = points[queue.top()]; | |
168 queue.pop(); | |
169 while(v.size() > 0) { | |
170 rs[k++] = v.back(); | |
171 v.pop_back(); | |
172 } | |
173 } | |
174 return r; | |
175 } | |
176 | |
177 template <class T> class NearestAccumulator : public Accumulator { | |
178 public: | |
179 NearestAccumulator(); | |
180 ~NearestAccumulator(); | |
181 void add_point(adb_result_t *r); | |
182 adb_query_results_t *get_points(); | |
183 private: | |
184 std::set< adb_result_t, adb_result_triple_lt > *set; | |
185 std::set< adb_result_t, adb_result_qpos_lt > *points; | |
186 }; | |
187 | |
188 template <class T> NearestAccumulator<T>::NearestAccumulator() | |
189 : set(0), points(0) { | |
190 set = new std::set< adb_result_t, adb_result_triple_lt >; | |
191 points = new std::set< adb_result_t, adb_result_qpos_lt >; | |
192 } | |
193 | |
194 template <class T> NearestAccumulator<T>::~NearestAccumulator() { | |
195 if(set) { | |
196 delete set; | |
197 } | |
198 if(points) { | |
199 delete points; | |
200 } | |
201 } | |
202 | |
203 template <class T> void NearestAccumulator<T>::add_point(adb_result_t *r) { | |
204 if(!isnan(r->dist)) { | |
205 if(set->find(*r) == set->end()) { | |
206 set->insert(*r); | |
207 | |
208 std::set< adb_result_t, adb_result_qpos_lt >::iterator it; | |
209 it = points->find(*r); | |
210 if(it == points->end()) { | |
211 points->insert(*r); | |
212 } else if(T()(*(const adb_result_t *)r,(*it))) { | |
213 points->erase(it); | |
214 points->insert(*r); | |
215 } | |
216 } | |
217 } | |
218 } | |
219 | |
220 template <class T> adb_query_results_t *NearestAccumulator<T>::get_points() { | |
221 unsigned int nresults = points->size(); | |
222 adb_query_results_t *r = (adb_query_results_t *) malloc(sizeof(adb_query_results_t)); | |
223 adb_result_t *rs = (adb_result_t *) calloc(nresults, sizeof(adb_result_t)); | |
224 r->nresults = nresults; | |
225 r->results = rs; | |
226 std::set< adb_result_t, adb_result_qpos_lt >::iterator it; | |
227 unsigned int k = 0; | |
228 for(it = points->begin(); it != points->end(); it++) { | |
229 rs[k++] = *it; | |
230 } | |
231 return r; | |
232 } | |
233 | |
234 #endif |