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