Mercurial > hg > svcore
comparison data/fft/FFTDataServer.cpp @ 742:c10cb8782576 coreaudio_tests
Merge from branch "default"
author | Chris Cannam |
---|---|
date | Sun, 01 Jul 2012 11:53:00 +0100 |
parents | 1424aa29ae95 |
children | 97c53dfaf798 e802e550a1f2 |
comparison
equal
deleted
inserted
replaced
666:4efa7429cd85 | 742:c10cb8782576 |
---|---|
189 distance += ((server->getFFTSize() / fftSize) - 1) * 10; | 189 distance += ((server->getFFTSize() / fftSize) - 1) * 10; |
190 | 190 |
191 if (server->getFillCompletion() < 50) distance += 100; | 191 if (server->getFillCompletion() < 50) distance += 100; |
192 | 192 |
193 #ifdef DEBUG_FFT_SERVER | 193 #ifdef DEBUG_FFT_SERVER |
194 std::cerr << "FFTDataServer::getFuzzyInstance: Distance for server " << server << " is " << distance << ", best is " << bestdist << std::endl; | 194 SVDEBUG << "FFTDataServer::getFuzzyInstance: Distance for server " << server << " is " << distance << ", best is " << bestdist << endl; |
195 #endif | 195 #endif |
196 | 196 |
197 if (bestdist == -1 || distance < bestdist) { | 197 if (bestdist == -1 || distance < bestdist) { |
198 bestdist = distance; | 198 bestdist = distance; |
199 best = i; | 199 best = i; |
202 } | 202 } |
203 | 203 |
204 if (bestdist >= 0) { | 204 if (bestdist >= 0) { |
205 FFTDataServer *server = best->second.first; | 205 FFTDataServer *server = best->second.first; |
206 #ifdef DEBUG_FFT_SERVER | 206 #ifdef DEBUG_FFT_SERVER |
207 std::cerr << "FFTDataServer::getFuzzyInstance: We like server " << server << " (with distance " << bestdist << ")" << std::endl; | 207 SVDEBUG << "FFTDataServer::getFuzzyInstance: We like server " << server << " (with distance " << bestdist << ")" << endl; |
208 #endif | 208 #endif |
209 claimInstance(server, false); | 209 claimInstance(server, false); |
210 return server; | 210 return server; |
211 } | 211 } |
212 } | 212 } |
226 | 226 |
227 FFTDataServer * | 227 FFTDataServer * |
228 FFTDataServer::findServer(QString n) | 228 FFTDataServer::findServer(QString n) |
229 { | 229 { |
230 #ifdef DEBUG_FFT_SERVER | 230 #ifdef DEBUG_FFT_SERVER |
231 std::cerr << "FFTDataServer::findServer(\"" << n.toStdString() << "\")" << std::endl; | 231 SVDEBUG << "FFTDataServer::findServer(\"" << n << "\")" << endl; |
232 #endif | 232 #endif |
233 | 233 |
234 if (m_servers.find(n) != m_servers.end()) { | 234 if (m_servers.find(n) != m_servers.end()) { |
235 | 235 |
236 FFTDataServer *server = m_servers[n].first; | 236 FFTDataServer *server = m_servers[n].first; |
237 | 237 |
238 #ifdef DEBUG_FFT_SERVER | 238 #ifdef DEBUG_FFT_SERVER |
239 std::cerr << "FFTDataServer::findServer(\"" << n.toStdString() << "\"): found " << server << std::endl; | 239 SVDEBUG << "FFTDataServer::findServer(\"" << n << "\"): found " << server << endl; |
240 #endif | 240 #endif |
241 | 241 |
242 claimInstance(server, false); | 242 claimInstance(server, false); |
243 | 243 |
244 return server; | 244 return server; |
245 } | 245 } |
246 | 246 |
247 #ifdef DEBUG_FFT_SERVER | 247 #ifdef DEBUG_FFT_SERVER |
248 std::cerr << "FFTDataServer::findServer(\"" << n.toStdString() << "\"): not found" << std::endl; | 248 SVDEBUG << "FFTDataServer::findServer(\"" << n << "\"): not found" << endl; |
249 #endif | 249 #endif |
250 | 250 |
251 return 0; | 251 return 0; |
252 } | 252 } |
253 | 253 |
262 { | 262 { |
263 MutexLocker locker(needLock ? &m_serverMapMutex : 0, | 263 MutexLocker locker(needLock ? &m_serverMapMutex : 0, |
264 "FFTDataServer::claimInstance::m_serverMapMutex"); | 264 "FFTDataServer::claimInstance::m_serverMapMutex"); |
265 | 265 |
266 #ifdef DEBUG_FFT_SERVER | 266 #ifdef DEBUG_FFT_SERVER |
267 std::cerr << "FFTDataServer::claimInstance(" << server << ")" << std::endl; | 267 SVDEBUG << "FFTDataServer::claimInstance(" << server << ")" << endl; |
268 #endif | 268 #endif |
269 | 269 |
270 for (ServerMap::iterator i = m_servers.begin(); i != m_servers.end(); ++i) { | 270 for (ServerMap::iterator i = m_servers.begin(); i != m_servers.end(); ++i) { |
271 if (i->second.first == server) { | 271 if (i->second.first == server) { |
272 | 272 |
273 for (ServerQueue::iterator j = m_releasedServers.begin(); | 273 for (ServerQueue::iterator j = m_releasedServers.begin(); |
274 j != m_releasedServers.end(); ++j) { | 274 j != m_releasedServers.end(); ++j) { |
275 | 275 |
276 if (*j == server) { | 276 if (*j == server) { |
277 #ifdef DEBUG_FFT_SERVER | 277 #ifdef DEBUG_FFT_SERVER |
278 std::cerr << "FFTDataServer::claimInstance: found in released server list, removing from it" << std::endl; | 278 SVDEBUG << "FFTDataServer::claimInstance: found in released server list, removing from it" << endl; |
279 #endif | 279 #endif |
280 m_releasedServers.erase(j); | 280 m_releasedServers.erase(j); |
281 break; | 281 break; |
282 } | 282 } |
283 } | 283 } |
284 | 284 |
285 ++i->second.second; | 285 ++i->second.second; |
286 | 286 |
287 #ifdef DEBUG_FFT_SERVER | 287 #ifdef DEBUG_FFT_SERVER |
288 std::cerr << "FFTDataServer::claimInstance: new refcount is " << i->second.second << std::endl; | 288 SVDEBUG << "FFTDataServer::claimInstance: new refcount is " << i->second.second << endl; |
289 #endif | 289 #endif |
290 | 290 |
291 return; | 291 return; |
292 } | 292 } |
293 } | 293 } |
307 { | 307 { |
308 MutexLocker locker(needLock ? &m_serverMapMutex : 0, | 308 MutexLocker locker(needLock ? &m_serverMapMutex : 0, |
309 "FFTDataServer::releaseInstance::m_serverMapMutex"); | 309 "FFTDataServer::releaseInstance::m_serverMapMutex"); |
310 | 310 |
311 #ifdef DEBUG_FFT_SERVER | 311 #ifdef DEBUG_FFT_SERVER |
312 std::cerr << "FFTDataServer::releaseInstance(" << server << ")" << std::endl; | 312 SVDEBUG << "FFTDataServer::releaseInstance(" << server << ")" << endl; |
313 #endif | 313 #endif |
314 | 314 |
315 // -- if ref count > 0, decrement and return | 315 // -- if ref count > 0, decrement and return |
316 // -- if the instance hasn't been used at all, delete it immediately | 316 // -- if the instance hasn't been used at all, delete it immediately |
317 // -- if fewer than N instances (N = e.g. 3) remain with zero refcounts, | 317 // -- if fewer than N instances (N = e.g. 3) remain with zero refcounts, |
330 << server << "): instance not allocated" << std::endl; | 330 << server << "): instance not allocated" << std::endl; |
331 } else if (--i->second.second == 0) { | 331 } else if (--i->second.second == 0) { |
332 /*!!! | 332 /*!!! |
333 if (server->m_lastUsedCache == -1) { // never used | 333 if (server->m_lastUsedCache == -1) { // never used |
334 #ifdef DEBUG_FFT_SERVER | 334 #ifdef DEBUG_FFT_SERVER |
335 std::cerr << "FFTDataServer::releaseInstance: instance " | 335 SVDEBUG << "FFTDataServer::releaseInstance: instance " |
336 << server << " has never been used, erasing" | 336 << server << " has never been used, erasing" |
337 << std::endl; | 337 << endl; |
338 #endif | 338 #endif |
339 delete server; | 339 delete server; |
340 m_servers.erase(i); | 340 m_servers.erase(i); |
341 } else { | 341 } else { |
342 */ | 342 */ |
343 #ifdef DEBUG_FFT_SERVER | 343 #ifdef DEBUG_FFT_SERVER |
344 std::cerr << "FFTDataServer::releaseInstance: instance " | 344 SVDEBUG << "FFTDataServer::releaseInstance: instance " |
345 << server << " no longer in use, marking for possible collection" | 345 << server << " no longer in use, marking for possible collection" |
346 << std::endl; | 346 << endl; |
347 #endif | 347 #endif |
348 bool found = false; | 348 bool found = false; |
349 for (ServerQueue::iterator j = m_releasedServers.begin(); | 349 for (ServerQueue::iterator j = m_releasedServers.begin(); |
350 j != m_releasedServers.end(); ++j) { | 350 j != m_releasedServers.end(); ++j) { |
351 if (*j == server) { | 351 if (*j == server) { |
359 server->suspend(); | 359 server->suspend(); |
360 purgeLimbo(); | 360 purgeLimbo(); |
361 //!!! } | 361 //!!! } |
362 } else { | 362 } else { |
363 #ifdef DEBUG_FFT_SERVER | 363 #ifdef DEBUG_FFT_SERVER |
364 std::cerr << "FFTDataServer::releaseInstance: instance " | 364 SVDEBUG << "FFTDataServer::releaseInstance: instance " |
365 << server << " now has refcount " << i->second.second | 365 << server << " now has refcount " << i->second.second |
366 << std::endl; | 366 << endl; |
367 #endif | 367 #endif |
368 } | 368 } |
369 return; | 369 return; |
370 } | 370 } |
371 } | 371 } |
376 | 376 |
377 void | 377 void |
378 FFTDataServer::purgeLimbo(int maxSize) | 378 FFTDataServer::purgeLimbo(int maxSize) |
379 { | 379 { |
380 #ifdef DEBUG_FFT_SERVER | 380 #ifdef DEBUG_FFT_SERVER |
381 std::cerr << "FFTDataServer::purgeLimbo(" << maxSize << "): " | 381 SVDEBUG << "FFTDataServer::purgeLimbo(" << maxSize << "): " |
382 << m_releasedServers.size() << " candidates" << std::endl; | 382 << m_releasedServers.size() << " candidates" << endl; |
383 #endif | 383 #endif |
384 | 384 |
385 while (int(m_releasedServers.size()) > maxSize) { | 385 while (int(m_releasedServers.size()) > maxSize) { |
386 | 386 |
387 FFTDataServer *server = *m_releasedServers.begin(); | 387 FFTDataServer *server = *m_releasedServers.begin(); |
388 | 388 |
389 bool found = false; | 389 bool found = false; |
390 | 390 |
391 #ifdef DEBUG_FFT_SERVER | 391 #ifdef DEBUG_FFT_SERVER |
392 std::cerr << "FFTDataServer::purgeLimbo: considering candidate " | 392 SVDEBUG << "FFTDataServer::purgeLimbo: considering candidate " |
393 << server << std::endl; | 393 << server << endl; |
394 #endif | 394 #endif |
395 | 395 |
396 for (ServerMap::iterator i = m_servers.begin(); i != m_servers.end(); ++i) { | 396 for (ServerMap::iterator i = m_servers.begin(); i != m_servers.end(); ++i) { |
397 | 397 |
398 if (i->second.first == server) { | 398 if (i->second.first == server) { |
403 << i->second.second << std::endl; | 403 << i->second.second << std::endl; |
404 // ... so don't delete it | 404 // ... so don't delete it |
405 break; | 405 break; |
406 } | 406 } |
407 #ifdef DEBUG_FFT_SERVER | 407 #ifdef DEBUG_FFT_SERVER |
408 std::cerr << "FFTDataServer::purgeLimbo: looks OK, erasing it" | 408 SVDEBUG << "FFTDataServer::purgeLimbo: looks OK, erasing it" |
409 << std::endl; | 409 << endl; |
410 #endif | 410 #endif |
411 | 411 |
412 m_servers.erase(i); | 412 m_servers.erase(i); |
413 delete server; | 413 delete server; |
414 break; | 414 break; |
424 | 424 |
425 m_releasedServers.pop_front(); | 425 m_releasedServers.pop_front(); |
426 } | 426 } |
427 | 427 |
428 #ifdef DEBUG_FFT_SERVER | 428 #ifdef DEBUG_FFT_SERVER |
429 std::cerr << "FFTDataServer::purgeLimbo(" << maxSize << "): " | 429 SVDEBUG << "FFTDataServer::purgeLimbo(" << maxSize << "): " |
430 << m_releasedServers.size() << " remain" << std::endl; | 430 << m_releasedServers.size() << " remain" << endl; |
431 #endif | 431 #endif |
432 | 432 |
433 } | 433 } |
434 | 434 |
435 void | 435 void |
437 { | 437 { |
438 MutexLocker locker(&m_serverMapMutex, | 438 MutexLocker locker(&m_serverMapMutex, |
439 "FFTDataServer::modelAboutToBeDeleted::m_serverMapMutex"); | 439 "FFTDataServer::modelAboutToBeDeleted::m_serverMapMutex"); |
440 | 440 |
441 #ifdef DEBUG_FFT_SERVER | 441 #ifdef DEBUG_FFT_SERVER |
442 std::cerr << "FFTDataServer::modelAboutToBeDeleted(" << model << ")" | 442 SVDEBUG << "FFTDataServer::modelAboutToBeDeleted(" << model << ")" |
443 << std::endl; | 443 << endl; |
444 #endif | 444 #endif |
445 | 445 |
446 for (ServerMap::iterator i = m_servers.begin(); i != m_servers.end(); ++i) { | 446 for (ServerMap::iterator i = m_servers.begin(); i != m_servers.end(); ++i) { |
447 | 447 |
448 FFTDataServer *server = i->second.first; | 448 FFTDataServer *server = i->second.first; |
449 | 449 |
450 if (server->getModel() == model) { | 450 if (server->getModel() == model) { |
451 | 451 |
452 #ifdef DEBUG_FFT_SERVER | 452 #ifdef DEBUG_FFT_SERVER |
453 std::cerr << "FFTDataServer::modelAboutToBeDeleted: server is " | 453 SVDEBUG << "FFTDataServer::modelAboutToBeDeleted: server is " |
454 << server << std::endl; | 454 << server << endl; |
455 #endif | 455 #endif |
456 | 456 |
457 if (i->second.second > 0) { | 457 if (i->second.second > 0) { |
458 std::cerr << "WARNING: FFTDataServer::modelAboutToBeDeleted: Model " << model << " (\"" << model->objectName().toStdString() << "\") is about to be deleted, but is still being referred to by FFT server " << server << " with non-zero refcount " << i->second.second << std::endl; | 458 std::cerr << "WARNING: FFTDataServer::modelAboutToBeDeleted: Model " << model << " (\"" << model->objectName() << "\") is about to be deleted, but is still being referred to by FFT server " << server << " with non-zero refcount " << i->second.second << std::endl; |
459 server->suspendWrites(); | 459 server->suspendWrites(); |
460 return; | 460 return; |
461 } | 461 } |
462 for (ServerQueue::iterator j = m_releasedServers.begin(); | 462 for (ServerQueue::iterator j = m_releasedServers.begin(); |
463 j != m_releasedServers.end(); ++j) { | 463 j != m_releasedServers.end(); ++j) { |
464 if (*j == server) { | 464 if (*j == server) { |
465 #ifdef DEBUG_FFT_SERVER | 465 #ifdef DEBUG_FFT_SERVER |
466 std::cerr << "FFTDataServer::modelAboutToBeDeleted: erasing from released servers" << std::endl; | 466 SVDEBUG << "FFTDataServer::modelAboutToBeDeleted: erasing from released servers" << endl; |
467 #endif | 467 #endif |
468 m_releasedServers.erase(j); | 468 m_releasedServers.erase(j); |
469 break; | 469 break; |
470 } | 470 } |
471 } | 471 } |
472 #ifdef DEBUG_FFT_SERVER | 472 #ifdef DEBUG_FFT_SERVER |
473 std::cerr << "FFTDataServer::modelAboutToBeDeleted: erasing server" << std::endl; | 473 SVDEBUG << "FFTDataServer::modelAboutToBeDeleted: erasing server" << endl; |
474 #endif | 474 #endif |
475 m_servers.erase(i); | 475 m_servers.erase(i); |
476 delete server; | 476 delete server; |
477 return; | 477 return; |
478 } | 478 } |
812 FFTCache::Rectangular, | 812 FFTCache::Rectangular, |
813 width, m_height); | 813 width, m_height); |
814 | 814 |
815 success = true; | 815 success = true; |
816 | 816 |
817 } catch (std::exception e) { | 817 } catch (std::exception &e) { |
818 | 818 |
819 delete cb->fileCacheWriter; | 819 delete cb->fileCacheWriter; |
820 cb->fileCacheWriter = 0; | 820 cb->fileCacheWriter = 0; |
821 | 821 |
822 std::cerr << "ERROR: Failed to construct disc cache for FFT data: " | 822 std::cerr << "ERROR: Failed to construct disc cache for FFT data: " |
823 << e.what() << std::endl; | 823 << e.what() << std::endl; |
824 | |
825 throw; | |
824 } | 826 } |
825 } | 827 } |
826 | 828 |
827 m_cacheVectorLock.lockForWrite(); | 829 m_cacheVectorLock.lockForWrite(); |
828 | 830 |
837 FFTDataServer::makeCacheReader(int c) | 839 FFTDataServer::makeCacheReader(int c) |
838 { | 840 { |
839 // preconditions: m_caches[c] exists and contains a file writer; | 841 // preconditions: m_caches[c] exists and contains a file writer; |
840 // m_cacheVectorLock is not locked by this thread | 842 // m_cacheVectorLock is not locked by this thread |
841 #ifdef DEBUG_FFT_SERVER | 843 #ifdef DEBUG_FFT_SERVER |
842 std::cerr << "FFTDataServer::makeCacheReader(" << c << ")" << std::endl; | 844 SVDEBUG << "FFTDataServer::makeCacheReader(" << c << ")" << endl; |
843 #endif | 845 #endif |
844 | 846 |
845 QThread *me = QThread::currentThread(); | 847 QThread *me = QThread::currentThread(); |
846 QWriteLocker locker(&m_cacheVectorLock); | 848 QWriteLocker locker(&m_cacheVectorLock); |
847 CacheBlock *cb(m_caches.at(c)); | 849 CacheBlock *cb(m_caches.at(c)); |
849 | 851 |
850 try { | 852 try { |
851 | 853 |
852 cb->fileCacheReader[me] = new FFTFileCacheReader(cb->fileCacheWriter); | 854 cb->fileCacheReader[me] = new FFTFileCacheReader(cb->fileCacheWriter); |
853 | 855 |
854 } catch (std::exception e) { | 856 } catch (std::exception &e) { |
855 | 857 |
856 delete cb->fileCacheReader[me]; | 858 delete cb->fileCacheReader[me]; |
857 cb->fileCacheReader.erase(me); | 859 cb->fileCacheReader.erase(me); |
858 | 860 |
859 std::cerr << "ERROR: Failed to construct disc cache reader for FFT data: " | 861 std::cerr << "ERROR: Failed to construct disc cache reader for FFT data: " |
871 } | 873 } |
872 | 874 |
873 cb = m_caches.at(deleteCandidate); | 875 cb = m_caches.at(deleteCandidate); |
874 if (cb && cb->fileCacheReader.find(me) != cb->fileCacheReader.end()) { | 876 if (cb && cb->fileCacheReader.find(me) != cb->fileCacheReader.end()) { |
875 #ifdef DEBUG_FFT_SERVER | 877 #ifdef DEBUG_FFT_SERVER |
876 std::cerr << "FFTDataServer::makeCacheReader: Deleting probably unpopular reader " << deleteCandidate << " for this thread (as I create reader " << c << ")" << std::endl; | 878 SVDEBUG << "FFTDataServer::makeCacheReader: Deleting probably unpopular reader " << deleteCandidate << " for this thread (as I create reader " << c << ")" << endl; |
877 #endif | 879 #endif |
878 delete cb->fileCacheReader[me]; | 880 delete cb->fileCacheReader[me]; |
879 cb->fileCacheReader.erase(me); | 881 cb->fileCacheReader.erase(me); |
880 } | 882 } |
881 | 883 |
887 { | 889 { |
888 Profiler profiler("FFTDataServer::getMagnitudeAt", false); | 890 Profiler profiler("FFTDataServer::getMagnitudeAt", false); |
889 | 891 |
890 if (x >= m_width || y >= m_height) return 0; | 892 if (x >= m_width || y >= m_height) return 0; |
891 | 893 |
892 size_t col; | 894 float val = 0; |
893 FFTCacheReader *cache = getCacheReader(x, col); | 895 |
894 if (!cache) return 0; | 896 try { |
895 | 897 size_t col; |
896 //!!! n.b. can throw | 898 FFTCacheReader *cache = getCacheReader(x, col); |
897 if (!cache->haveSetColumnAt(col)) { | 899 if (!cache) return 0; |
898 Profiler profiler("FFTDataServer::getMagnitudeAt: filling"); | 900 |
899 #ifdef DEBUG_FFT_SERVER | 901 if (!cache->haveSetColumnAt(col)) { |
900 std::cerr << "FFTDataServer::getMagnitudeAt: calling fillColumn(" | 902 Profiler profiler("FFTDataServer::getMagnitudeAt: filling"); |
901 << x << ")" << std::endl; | 903 #ifdef DEBUG_FFT_SERVER |
902 #endif | 904 SVDEBUG << "FFTDataServer::getMagnitudeAt: calling fillColumn(" |
903 fillColumn(x); | 905 << x << ")" << endl; |
904 } | 906 #endif |
905 return cache->getMagnitudeAt(col, y); | 907 fillColumn(x); |
908 } | |
909 | |
910 val = cache->getMagnitudeAt(col, y); | |
911 | |
912 } catch (std::exception &e) { | |
913 m_error = e.what(); | |
914 } | |
915 | |
916 return val; | |
906 } | 917 } |
907 | 918 |
908 bool | 919 bool |
909 FFTDataServer::getMagnitudesAt(size_t x, float *values, size_t minbin, size_t count, size_t step) | 920 FFTDataServer::getMagnitudesAt(size_t x, float *values, size_t minbin, size_t count, size_t step) |
910 { | 921 { |
916 if (count == 0) count = (m_height - minbin) / step; | 927 if (count == 0) count = (m_height - minbin) / step; |
917 else if (minbin + count * step > m_height) { | 928 else if (minbin + count * step > m_height) { |
918 count = (m_height - minbin) / step; | 929 count = (m_height - minbin) / step; |
919 } | 930 } |
920 | 931 |
921 size_t col; | 932 try { |
922 FFTCacheReader *cache = getCacheReader(x, col); | 933 size_t col; |
923 if (!cache) return false; | 934 FFTCacheReader *cache = getCacheReader(x, col); |
924 | 935 if (!cache) return false; |
925 //!!! n.b. can throw | 936 |
926 if (!cache->haveSetColumnAt(col)) { | 937 if (!cache->haveSetColumnAt(col)) { |
927 Profiler profiler("FFTDataServer::getMagnitudesAt: filling"); | 938 Profiler profiler("FFTDataServer::getMagnitudesAt: filling"); |
928 fillColumn(x); | 939 fillColumn(x); |
929 } | 940 } |
930 | 941 |
931 cache->getMagnitudesAt(col, values, minbin, count, step); | 942 cache->getMagnitudesAt(col, values, minbin, count, step); |
943 | |
944 } catch (std::exception &e) { | |
945 m_error = e.what(); | |
946 return false; | |
947 } | |
932 | 948 |
933 return true; | 949 return true; |
934 } | 950 } |
935 | 951 |
936 float | 952 float |
938 { | 954 { |
939 Profiler profiler("FFTDataServer::getNormalizedMagnitudeAt", false); | 955 Profiler profiler("FFTDataServer::getNormalizedMagnitudeAt", false); |
940 | 956 |
941 if (x >= m_width || y >= m_height) return 0; | 957 if (x >= m_width || y >= m_height) return 0; |
942 | 958 |
943 size_t col; | 959 float val = 0; |
944 FFTCacheReader *cache = getCacheReader(x, col); | 960 |
945 if (!cache) return 0; | 961 try { |
946 | 962 |
947 //!!! n.b. can throw | 963 size_t col; |
948 if (!cache->haveSetColumnAt(col)) { | 964 FFTCacheReader *cache = getCacheReader(x, col); |
949 Profiler profiler("FFTDataServer::getNormalizedMagnitudeAt: filling"); | 965 if (!cache) return 0; |
950 fillColumn(x); | 966 |
951 } | 967 if (!cache->haveSetColumnAt(col)) { |
952 return cache->getNormalizedMagnitudeAt(col, y); | 968 Profiler profiler("FFTDataServer::getNormalizedMagnitudeAt: filling"); |
969 fillColumn(x); | |
970 } | |
971 val = cache->getNormalizedMagnitudeAt(col, y); | |
972 | |
973 } catch (std::exception &e) { | |
974 m_error = e.what(); | |
975 } | |
976 | |
977 return val; | |
953 } | 978 } |
954 | 979 |
955 bool | 980 bool |
956 FFTDataServer::getNormalizedMagnitudesAt(size_t x, float *values, size_t minbin, size_t count, size_t step) | 981 FFTDataServer::getNormalizedMagnitudesAt(size_t x, float *values, size_t minbin, size_t count, size_t step) |
957 { | 982 { |
963 if (count == 0) count = (m_height - minbin) / step; | 988 if (count == 0) count = (m_height - minbin) / step; |
964 else if (minbin + count * step > m_height) { | 989 else if (minbin + count * step > m_height) { |
965 count = (m_height - minbin) / step; | 990 count = (m_height - minbin) / step; |
966 } | 991 } |
967 | 992 |
968 size_t col; | 993 try { |
969 FFTCacheReader *cache = getCacheReader(x, col); | 994 |
970 if (!cache) return false; | 995 size_t col; |
971 | 996 FFTCacheReader *cache = getCacheReader(x, col); |
972 //!!! n.b. can throw | 997 if (!cache) return false; |
973 if (!cache->haveSetColumnAt(col)) { | 998 |
974 Profiler profiler("FFTDataServer::getNormalizedMagnitudesAt: filling"); | 999 if (!cache->haveSetColumnAt(col)) { |
975 fillColumn(x); | 1000 Profiler profiler("FFTDataServer::getNormalizedMagnitudesAt: filling"); |
976 } | 1001 fillColumn(x); |
977 | 1002 } |
978 for (size_t i = 0; i < count; ++i) { | 1003 |
979 values[i] = cache->getNormalizedMagnitudeAt(col, i * step + minbin); | 1004 for (size_t i = 0; i < count; ++i) { |
1005 values[i] = cache->getNormalizedMagnitudeAt(col, i * step + minbin); | |
1006 } | |
1007 | |
1008 } catch (std::exception &e) { | |
1009 m_error = e.what(); | |
1010 return false; | |
980 } | 1011 } |
981 | 1012 |
982 return true; | 1013 return true; |
983 } | 1014 } |
984 | 1015 |
987 { | 1018 { |
988 Profiler profiler("FFTDataServer::getMaximumMagnitudeAt", false); | 1019 Profiler profiler("FFTDataServer::getMaximumMagnitudeAt", false); |
989 | 1020 |
990 if (x >= m_width) return 0; | 1021 if (x >= m_width) return 0; |
991 | 1022 |
992 size_t col; | 1023 float val = 0; |
993 FFTCacheReader *cache = getCacheReader(x, col); | 1024 |
994 if (!cache) return 0; | 1025 try { |
995 | 1026 |
996 //!!! n.b. can throw | 1027 size_t col; |
997 if (!cache->haveSetColumnAt(col)) { | 1028 FFTCacheReader *cache = getCacheReader(x, col); |
998 Profiler profiler("FFTDataServer::getMaximumMagnitudeAt: filling"); | 1029 if (!cache) return 0; |
999 fillColumn(x); | 1030 |
1000 } | 1031 if (!cache->haveSetColumnAt(col)) { |
1001 return cache->getMaximumMagnitudeAt(col); | 1032 Profiler profiler("FFTDataServer::getMaximumMagnitudeAt: filling"); |
1033 fillColumn(x); | |
1034 } | |
1035 val = cache->getMaximumMagnitudeAt(col); | |
1036 | |
1037 } catch (std::exception &e) { | |
1038 m_error = e.what(); | |
1039 } | |
1040 | |
1041 return val; | |
1002 } | 1042 } |
1003 | 1043 |
1004 float | 1044 float |
1005 FFTDataServer::getPhaseAt(size_t x, size_t y) | 1045 FFTDataServer::getPhaseAt(size_t x, size_t y) |
1006 { | 1046 { |
1007 Profiler profiler("FFTDataServer::getPhaseAt", false); | 1047 Profiler profiler("FFTDataServer::getPhaseAt", false); |
1008 | 1048 |
1009 if (x >= m_width || y >= m_height) return 0; | 1049 if (x >= m_width || y >= m_height) return 0; |
1010 | 1050 |
1011 size_t col; | 1051 float val = 0; |
1012 FFTCacheReader *cache = getCacheReader(x, col); | 1052 |
1013 if (!cache) return 0; | 1053 try { |
1014 | 1054 |
1015 //!!! n.b. can throw | 1055 size_t col; |
1016 if (!cache->haveSetColumnAt(col)) { | 1056 FFTCacheReader *cache = getCacheReader(x, col); |
1017 Profiler profiler("FFTDataServer::getPhaseAt: filling"); | 1057 if (!cache) return 0; |
1018 fillColumn(x); | 1058 |
1019 } | 1059 if (!cache->haveSetColumnAt(col)) { |
1020 return cache->getPhaseAt(col, y); | 1060 Profiler profiler("FFTDataServer::getPhaseAt: filling"); |
1061 fillColumn(x); | |
1062 } | |
1063 val = cache->getPhaseAt(col, y); | |
1064 | |
1065 } catch (std::exception &e) { | |
1066 m_error = e.what(); | |
1067 } | |
1068 | |
1069 return val; | |
1021 } | 1070 } |
1022 | 1071 |
1023 bool | 1072 bool |
1024 FFTDataServer::getPhasesAt(size_t x, float *values, size_t minbin, size_t count, size_t step) | 1073 FFTDataServer::getPhasesAt(size_t x, float *values, size_t minbin, size_t count, size_t step) |
1025 { | 1074 { |
1031 if (count == 0) count = (m_height - minbin) / step; | 1080 if (count == 0) count = (m_height - minbin) / step; |
1032 else if (minbin + count * step > m_height) { | 1081 else if (minbin + count * step > m_height) { |
1033 count = (m_height - minbin) / step; | 1082 count = (m_height - minbin) / step; |
1034 } | 1083 } |
1035 | 1084 |
1036 size_t col; | 1085 try { |
1037 FFTCacheReader *cache = getCacheReader(x, col); | 1086 |
1038 if (!cache) return false; | 1087 size_t col; |
1039 | 1088 FFTCacheReader *cache = getCacheReader(x, col); |
1040 //!!! n.b. can throw | 1089 if (!cache) return false; |
1041 if (!cache->haveSetColumnAt(col)) { | 1090 |
1042 Profiler profiler("FFTDataServer::getPhasesAt: filling"); | 1091 if (!cache->haveSetColumnAt(col)) { |
1043 fillColumn(x); | 1092 Profiler profiler("FFTDataServer::getPhasesAt: filling"); |
1044 } | 1093 fillColumn(x); |
1045 | 1094 } |
1046 for (size_t i = 0; i < count; ++i) { | 1095 |
1047 values[i] = cache->getPhaseAt(col, i * step + minbin); | 1096 for (size_t i = 0; i < count; ++i) { |
1097 values[i] = cache->getPhaseAt(col, i * step + minbin); | |
1098 } | |
1099 | |
1100 } catch (std::exception &e) { | |
1101 m_error = e.what(); | |
1102 return false; | |
1048 } | 1103 } |
1049 | 1104 |
1050 return true; | 1105 return true; |
1051 } | 1106 } |
1052 | 1107 |
1059 real = 0; | 1114 real = 0; |
1060 imaginary = 0; | 1115 imaginary = 0; |
1061 return; | 1116 return; |
1062 } | 1117 } |
1063 | 1118 |
1064 size_t col; | 1119 try { |
1065 FFTCacheReader *cache = getCacheReader(x, col); | 1120 |
1066 | 1121 size_t col; |
1067 if (!cache) { | 1122 FFTCacheReader *cache = getCacheReader(x, col); |
1068 real = 0; | 1123 |
1069 imaginary = 0; | 1124 if (!cache) { |
1070 return; | 1125 real = 0; |
1071 } | 1126 imaginary = 0; |
1072 | 1127 return; |
1073 //!!! n.b. can throw | 1128 } |
1074 if (!cache->haveSetColumnAt(col)) { | 1129 |
1075 Profiler profiler("FFTDataServer::getValuesAt: filling"); | 1130 if (!cache->haveSetColumnAt(col)) { |
1076 #ifdef DEBUG_FFT_SERVER | 1131 Profiler profiler("FFTDataServer::getValuesAt: filling"); |
1077 std::cerr << "FFTDataServer::getValuesAt(" << x << ", " << y << "): filling" << std::endl; | 1132 #ifdef DEBUG_FFT_SERVER |
1078 #endif | 1133 SVDEBUG << "FFTDataServer::getValuesAt(" << x << ", " << y << "): filling" << endl; |
1079 fillColumn(x); | 1134 #endif |
1080 } | 1135 fillColumn(x); |
1081 | 1136 } |
1082 cache->getValuesAt(col, y, real, imaginary); | 1137 |
1138 cache->getValuesAt(col, y, real, imaginary); | |
1139 | |
1140 } catch (std::exception &e) { | |
1141 m_error = e.what(); | |
1142 } | |
1083 } | 1143 } |
1084 | 1144 |
1085 bool | 1145 bool |
1086 FFTDataServer::getValuesAt(size_t x, float *reals, float *imaginaries, size_t minbin, size_t count, size_t step) | 1146 FFTDataServer::getValuesAt(size_t x, float *reals, float *imaginaries, size_t minbin, size_t count, size_t step) |
1087 { | 1147 { |
1093 if (count == 0) count = (m_height - minbin) / step; | 1153 if (count == 0) count = (m_height - minbin) / step; |
1094 else if (minbin + count * step > m_height) { | 1154 else if (minbin + count * step > m_height) { |
1095 count = (m_height - minbin) / step; | 1155 count = (m_height - minbin) / step; |
1096 } | 1156 } |
1097 | 1157 |
1098 size_t col; | 1158 try { |
1099 FFTCacheReader *cache = getCacheReader(x, col); | 1159 |
1100 if (!cache) return false; | 1160 size_t col; |
1101 | 1161 FFTCacheReader *cache = getCacheReader(x, col); |
1102 //!!! n.b. can throw | 1162 if (!cache) return false; |
1103 if (!cache->haveSetColumnAt(col)) { | 1163 |
1104 Profiler profiler("FFTDataServer::getValuesAt: filling"); | 1164 if (!cache->haveSetColumnAt(col)) { |
1105 fillColumn(x); | 1165 Profiler profiler("FFTDataServer::getValuesAt: filling"); |
1106 } | 1166 fillColumn(x); |
1107 | 1167 } |
1108 for (size_t i = 0; i < count; ++i) { | 1168 |
1109 cache->getValuesAt(col, i * step + minbin, reals[i], imaginaries[i]); | 1169 for (size_t i = 0; i < count; ++i) { |
1170 cache->getValuesAt(col, i * step + minbin, reals[i], imaginaries[i]); | |
1171 } | |
1172 | |
1173 } catch (std::exception &e) { | |
1174 m_error = e.what(); | |
1175 return false; | |
1110 } | 1176 } |
1111 | 1177 |
1112 return true; | 1178 return true; |
1113 } | 1179 } |
1114 | 1180 |
1121 | 1187 |
1122 if (!haveCache(x)) { | 1188 if (!haveCache(x)) { |
1123 /*!!! | 1189 /*!!! |
1124 if (m_lastUsedCache == -1) { | 1190 if (m_lastUsedCache == -1) { |
1125 if (m_suspended) { | 1191 if (m_suspended) { |
1126 std::cerr << "FFTDataServer::isColumnReady(" << x << "): no cache, calling resume" << std::endl; | 1192 SVDEBUG << "FFTDataServer::isColumnReady(" << x << "): no cache, calling resume" << endl; |
1127 resume(); | 1193 resume(); |
1128 } | 1194 } |
1129 m_fillThread->start(); | 1195 m_fillThread->start(); |
1130 } | 1196 } |
1131 */ | 1197 */ |
1132 return false; | 1198 return false; |
1133 } | 1199 } |
1134 | 1200 |
1135 size_t col; | 1201 try { |
1136 FFTCacheReader *cache = getCacheReader(x, col); | 1202 |
1137 if (!cache) return true; | 1203 size_t col; |
1138 | 1204 FFTCacheReader *cache = getCacheReader(x, col); |
1139 //!!! n.b. can throw | 1205 if (!cache) return true; |
1140 return cache->haveSetColumnAt(col); | 1206 |
1207 return cache->haveSetColumnAt(col); | |
1208 | |
1209 } catch (std::exception &e) { | |
1210 m_error = e.what(); | |
1211 return false; | |
1212 } | |
1141 } | 1213 } |
1142 | 1214 |
1143 void | 1215 void |
1144 FFTDataServer::fillColumn(size_t x) | 1216 FFTDataServer::fillColumn(size_t x) |
1145 { | 1217 { |
1184 | 1256 |
1185 startFrame -= winsize / 2; | 1257 startFrame -= winsize / 2; |
1186 endFrame -= winsize / 2; | 1258 endFrame -= winsize / 2; |
1187 | 1259 |
1188 #ifdef DEBUG_FFT_SERVER_FILL | 1260 #ifdef DEBUG_FFT_SERVER_FILL |
1189 std::cerr << "FFTDataServer::fillColumn: requesting frames " | 1261 SVDEBUG << "FFTDataServer::fillColumn: requesting frames " |
1190 << startFrame + pfx << " -> " << endFrame << " ( = " | 1262 << startFrame + pfx << " -> " << endFrame << " ( = " |
1191 << endFrame - (startFrame + pfx) << ") at index " | 1263 << endFrame - (startFrame + pfx) << ") at index " |
1192 << off + pfx << " in buffer of size " << m_fftSize | 1264 << off + pfx << " in buffer of size " << m_fftSize |
1193 << " with window size " << m_windowSize | 1265 << " with window size " << m_windowSize |
1194 << " from channel " << m_channel << std::endl; | 1266 << " from channel " << m_channel << endl; |
1195 #endif | 1267 #endif |
1196 | 1268 |
1197 QMutexLocker locker(&m_fftBuffersLock); | 1269 QMutexLocker locker(&m_fftBuffersLock); |
1198 | 1270 |
1199 // We may have been called from a function that wanted to obtain a | 1271 // We may have been called from a function that wanted to obtain a |
1296 m_workbuffer, | 1368 m_workbuffer, |
1297 m_workbuffer + hs + 1); | 1369 m_workbuffer + hs + 1); |
1298 } | 1370 } |
1299 | 1371 |
1300 if (m_suspended) { | 1372 if (m_suspended) { |
1301 // std::cerr << "FFTDataServer::fillColumn(" << x << "): calling resume" << std::endl; | 1373 // SVDEBUG << "FFTDataServer::fillColumn(" << x << "): calling resume" << endl; |
1302 // resume(); | 1374 // resume(); |
1303 } | 1375 } |
1304 } | 1376 } |
1305 | 1377 |
1306 void | 1378 void |
1307 FFTDataServer::fillComplete() | 1379 FFTDataServer::fillComplete() |
1308 { | 1380 { |
1309 for (int i = 0; i < int(m_caches.size()); ++i) { | 1381 for (int i = 0; i < int(m_caches.size()); ++i) { |
1382 if (!m_caches[i]) continue; | |
1310 if (m_caches[i]->memoryCache) { | 1383 if (m_caches[i]->memoryCache) { |
1311 m_caches[i]->memoryCache->allColumnsWritten(); | 1384 m_caches[i]->memoryCache->allColumnsWritten(); |
1312 } | 1385 } |
1313 if (m_caches[i]->fileCacheWriter) { | 1386 if (m_caches[i]->fileCacheWriter) { |
1314 m_caches[i]->fileCacheWriter->allColumnsWritten(); | 1387 m_caches[i]->fileCacheWriter->allColumnsWritten(); |
1315 } | 1388 } |
1316 } | 1389 } |
1390 } | |
1391 | |
1392 QString | |
1393 FFTDataServer::getError() const | |
1394 { | |
1395 if (m_error != "") return m_error; | |
1396 else if (m_fillThread) return m_fillThread->getError(); | |
1397 else return ""; | |
1317 } | 1398 } |
1318 | 1399 |
1319 size_t | 1400 size_t |
1320 FFTDataServer::getFillCompletion() const | 1401 FFTDataServer::getFillCompletion() const |
1321 { | 1402 { |
1363 | 1444 |
1364 void | 1445 void |
1365 FFTDataServer::FillThread::run() | 1446 FFTDataServer::FillThread::run() |
1366 { | 1447 { |
1367 #ifdef DEBUG_FFT_SERVER_FILL | 1448 #ifdef DEBUG_FFT_SERVER_FILL |
1368 std::cerr << "FFTDataServer::FillThread::run()" << std::endl; | 1449 SVDEBUG << "FFTDataServer::FillThread::run()" << endl; |
1369 #endif | 1450 #endif |
1370 | 1451 |
1371 m_extent = 0; | 1452 m_extent = 0; |
1372 m_completion = 0; | 1453 m_completion = 0; |
1373 | 1454 |
1374 while (!m_server.m_model->isReady() && !m_server.m_exiting) { | 1455 while (!m_server.m_model->isReady() && !m_server.m_exiting) { |
1375 #ifdef DEBUG_FFT_SERVER_FILL | 1456 #ifdef DEBUG_FFT_SERVER_FILL |
1376 std::cerr << "FFTDataServer::FillThread::run(): waiting for model " << m_server.m_model << " to be ready" << std::endl; | 1457 SVDEBUG << "FFTDataServer::FillThread::run(): waiting for model " << m_server.m_model << " to be ready" << endl; |
1377 #endif | 1458 #endif |
1378 sleep(1); | 1459 sleep(1); |
1379 } | 1460 } |
1380 if (m_server.m_exiting) return; | 1461 if (m_server.m_exiting) return; |
1381 | 1462 |
1390 | 1471 |
1391 if (m_fillFrom > start) { | 1472 if (m_fillFrom > start) { |
1392 | 1473 |
1393 for (size_t f = m_fillFrom; f < end; f += m_server.m_windowIncrement) { | 1474 for (size_t f = m_fillFrom; f < end; f += m_server.m_windowIncrement) { |
1394 | 1475 |
1395 m_server.fillColumn(int((f - start) / m_server.m_windowIncrement)); | 1476 try { |
1477 m_server.fillColumn(int((f - start) / m_server.m_windowIncrement)); | |
1478 } catch (std::exception &e) { | |
1479 SVDEBUG << "FFTDataServer::FillThread::run: exception: " << e.what() << endl; | |
1480 m_error = e.what(); | |
1481 m_server.fillComplete(); | |
1482 m_completion = 100; | |
1483 m_extent = end; | |
1484 return; | |
1485 } | |
1396 | 1486 |
1397 if (m_server.m_exiting) return; | 1487 if (m_server.m_exiting) return; |
1398 | 1488 |
1399 while (m_server.m_suspended) { | 1489 while (m_server.m_suspended) { |
1400 #ifdef DEBUG_FFT_SERVER | 1490 #ifdef DEBUG_FFT_SERVER |
1430 | 1520 |
1431 size_t baseCompletion = m_completion; | 1521 size_t baseCompletion = m_completion; |
1432 | 1522 |
1433 for (size_t f = start; f < remainingEnd; f += m_server.m_windowIncrement) { | 1523 for (size_t f = start; f < remainingEnd; f += m_server.m_windowIncrement) { |
1434 | 1524 |
1435 m_server.fillColumn(int((f - start) / m_server.m_windowIncrement)); | 1525 try { |
1526 m_server.fillColumn(int((f - start) / m_server.m_windowIncrement)); | |
1527 } catch (std::exception &e) { | |
1528 SVDEBUG << "FFTDataServer::FillThread::run: exception: " << e.what() << endl; | |
1529 m_error = e.what(); | |
1530 m_server.fillComplete(); | |
1531 m_completion = 100; | |
1532 m_extent = end; | |
1533 return; | |
1534 } | |
1436 | 1535 |
1437 if (m_server.m_exiting) return; | 1536 if (m_server.m_exiting) return; |
1438 | 1537 |
1439 while (m_server.m_suspended) { | 1538 while (m_server.m_suspended) { |
1440 #ifdef DEBUG_FFT_SERVER | 1539 #ifdef DEBUG_FFT_SERVER |
1466 m_server.fillComplete(); | 1565 m_server.fillComplete(); |
1467 m_completion = 100; | 1566 m_completion = 100; |
1468 m_extent = end; | 1567 m_extent = end; |
1469 | 1568 |
1470 #ifdef DEBUG_FFT_SERVER | 1569 #ifdef DEBUG_FFT_SERVER |
1471 std::cerr << "FFTDataServer::FillThread::run exiting" << std::endl; | 1570 SVDEBUG << "FFTDataServer::FillThread::run exiting" << endl; |
1472 #endif | 1571 #endif |
1473 } | 1572 } |
1474 | 1573 |