comparison examples/iAudioDB/AppController.m @ 702:6d8539709d9c

Switching over to use sample rate where possible - poss bug in query start specification.
author mas01mj
date Fri, 30 Apr 2010 14:57:30 +0000
parents e21abbac820e
children 14b48e1b9ca4
comparison
equal deleted inserted replaced
701:e21abbac820e 702:6d8539709d9c
91 dim = 12; 91 dim = 12;
92 break; 92 break;
93 } 93 }
94 94
95 // Calculate the max DB size 95 // Calculate the max DB size
96 int vectors = ceil(([maxLengthField doubleValue] * 60.0f) / ([hopSizeField doubleValue] / 44100.0f)); 96 int vectors = ceil(([maxLengthField doubleValue] * 60.0f) / (([hopSizeField doubleValue] / 1000) * 44100.0f));
97 NSLog(@"Vectors: %d", vectors);
97 int numtracks = [maxTracksField intValue]; 98 int numtracks = [maxTracksField intValue];
98 int datasize = ceil((numtracks * vectors * dim * 8.0f) / 1024.0f / 1024.0f); // In MB 99 int datasize = ceil((numtracks * vectors * dim * 8.0f) / 1024.0f / 1024.0f); // In MB
99 100
100 [self reset]; 101 [self reset];
101 102
259 AudioFileClose(audioFile); 260 AudioFileClose(audioFile);
260 261
261 return sampleRate; 262 return sampleRate;
262 } 263 }
263 264
265 -(UInt64)getHopSizeInSamples:(NSString *)filename
266 {
267 NSString* hopStr = [dbState objectForKey:@"hopsize"];
268 return round([self getSampleRate:filename] * ([hopStr doubleValue] / 1000));
269 }
270
271 -(int)nearestPow2:(int)x
272 {
273 if (x < 0)
274 return 0;
275 --x;
276 x |= x >> 1;
277 x |= x >> 2;
278 x |= x >> 4;
279 x |= x >> 8;
280 x |= x >> 16;
281 return x+1;
282 }
283
264 -(void)importFile:(NSString *)filename withExtractorConfig:(NSString *)extractorPath 284 -(void)importFile:(NSString *)filename withExtractorConfig:(NSString *)extractorPath
265 { 285 {
266 // Create the extractor configuration 286 // Create the extractor configuration
267 UInt64 sampleRate = [self getSampleRate:filename]; 287 int hopSizeSamples = [self getHopSizeInSamples:filename];
288 int windowSizeSamples = [self nearestPow2:(hopSizeSamples*8)];
268 289
269 NSString* extractorContent = [NSString stringWithContentsOfFile:extractorPath]; 290 NSString* extractorContent = [NSString stringWithContentsOfFile:extractorPath];
270 NSString* hopStr = [dbState objectForKey:@"hopsize"]; 291 NSString* newContent = [[extractorContent stringByReplacingOccurrencesOfString:@"HOP_SIZE" withString:[NSString stringWithFormat:@"%d", hopSizeSamples]]
271 NSString* newContent = [[extractorContent stringByReplacingOccurrencesOfString:@"HOP_SIZE" withString:hopStr] 292 stringByReplacingOccurrencesOfString:@"WINDOW_SIZE" withString:[NSString stringWithFormat:@"%d", windowSizeSamples]];
272 stringByReplacingOccurrencesOfString:@"WINDOW_SIZE" withString:[NSString stringWithFormat:@"%d", [hopStr intValue] * 8]];
273 NSString* n3FileName = [NSTemporaryDirectory() stringByAppendingPathComponent:@"extractor_config.n3"]; 293 NSString* n3FileName = [NSTemporaryDirectory() stringByAppendingPathComponent:@"extractor_config.n3"];
274 294 NSLog(newContent);
275 NSError* error; 295 NSError* error;
276 [newContent writeToFile:n3FileName atomically:YES encoding:NSASCIIStringEncoding error:&error]; 296 [newContent writeToFile:n3FileName atomically:YES encoding:NSASCIIStringEncoding error:&error];
277 297
278 // Create the temp file for the extracted features 298 // Create the temp file for the extracted features
279 NSString* tempFileTemplate = [NSTemporaryDirectory() stringByAppendingPathComponent:@"features.XXXXXX"]; 299 NSString* tempFileTemplate = [NSTemporaryDirectory() stringByAppendingPathComponent:@"features.XXXXXX"];
313 333
314 } 334 }
315 335
316 /** 336 /**
317 * Choose the file(s) to be imported. 337 * Choose the file(s) to be imported.
318 * TODO: Currently handles the import process too - split this off.
319 */ 338 */
320 -(IBAction)importAudio:(id)sender 339 -(IBAction)importAudio:(id)sender
321 { 340 {
322 [tracksView reloadData]; 341 [tracksView reloadData];
323 342
336 NSArray *filesToOpen = [panel filenames]; 355 NSArray *filesToOpen = [panel filenames];
337 356
338 NSString* extractor = [dbState objectForKey:@"extractor"]; 357 NSString* extractor = [dbState objectForKey:@"extractor"];
339 NSString* extractorPath = [NSString stringWithFormat:@"/Applications/iAudioDB.app/rdf/%@.n3", extractor]; 358 NSString* extractorPath = [NSString stringWithFormat:@"/Applications/iAudioDB.app/rdf/%@.n3", extractor];
340 359
341 // TODO Shift this process into a separate function.
342 // Create the customized extractor config
343 /* NSString* extractorContent = [NSString stringWithContentsOfFile:extractorPath];
344 NSString* hopStr = [dbState objectForKey:@"hopsize"];
345 NSString* winStr = [dbState objectForKey:@"windowsize"];
346 NSString* newContent = [[extractorContent stringByReplacingOccurrencesOfString:@"HOP_SIZE" withString:hopStr]
347 stringByReplacingOccurrencesOfString:@"WINDOW_SIZE" withString:winStr];
348 NSString* n3FileName = [NSTemporaryDirectory() stringByAppendingPathComponent:@"extractor_config.n3"];
349
350 NSError* error;
351 [newContent writeToFile:n3FileName atomically:YES encoding:NSASCIIStringEncoding error:&error];
352 */
353 for(int i=0; i<[filesToOpen count]; i++) 360 for(int i=0; i<[filesToOpen count]; i++)
354 { 361 {
355 audiodb_close(db); 362 audiodb_close(db);
356 363
357 // Get the sample rate for the audio file 364 // Get the sample rate for the audio file
358 365
359 [self importFile:[filesToOpen objectAtIndex:i] withExtractorConfig:extractorPath]; 366 [self importFile:[filesToOpen objectAtIndex:i] withExtractorConfig:extractorPath];
360
361 /* NSString* tempFileTemplate = [NSTemporaryDirectory() stringByAppendingPathComponent:@"features.XXXXXX"];
362 const char* tempFileTemplateCString = [tempFileTemplate fileSystemRepresentation];
363 char* tempFileNameCString = (char *)malloc(strlen(tempFileTemplateCString) + 1);
364 strcpy(tempFileNameCString, tempFileTemplateCString);
365 mktemp(tempFileNameCString);
366
367 NSString* featuresFileName = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:tempFileNameCString length:strlen(tempFileNameCString)];
368 free(tempFileNameCString);
369
370 NSTask* task = [[NSTask alloc] init];
371
372 [task setLaunchPath:@"/usr/local/bin/sonic-annotator"];
373 NSArray* args;
374 args = [NSArray arrayWithObjects:@"-t", n3FileName, @"-w", @"rdf", @"-r", @"--rdf-network", @"--rdf-one-file", featuresFileName, @"--rdf-force", [filesToOpen objectAtIndex:i], nil];
375 [task setArguments:args];
376 [task launch];
377 [task waitUntilExit];
378 [task release];
379
380 NSTask* importTask = [[NSTask alloc] init];
381 [importTask setLaunchPath:@"/usr/local/bin/populate"];
382 args = [NSArray arrayWithObjects:featuresFileName, dbFilename, nil];
383 [importTask setArguments:args];
384 [importTask launch];
385 [importTask waitUntilExit];
386 [importTask release];
387
388 NSString* val = [[filesToOpen objectAtIndex:i] retain];
389 NSString* key = [[[filesToOpen objectAtIndex:i] lastPathComponent] retain];
390
391 // Update the plist store.
392 [trackMap setValue:val forKey:key];
393 [dbState writeToFile:plistFilename atomically: YES];
394 */
395
396 db = audiodb_open([dbFilename cStringUsingEncoding:NSUTF8StringEncoding], O_RDONLY); 367 db = audiodb_open([dbFilename cStringUsingEncoding:NSUTF8StringEncoding], O_RDONLY);
397 [self updateStatus]; 368 [self updateStatus];
398 } 369 }
399 370
400 [NSApp endModalSession:session]; 371 [NSApp endModalSession:session];
646 617
647 -(IBAction)resetLengths:(id)sender 618 -(IBAction)resetLengths:(id)sender
648 { 619 {
649 queryTrack = [[NSSound alloc] initWithContentsOfFile:selectedFilename byReference:YES]; 620 queryTrack = [[NSSound alloc] initWithContentsOfFile:selectedFilename byReference:YES];
650 621
651 double samples = ([queryTrack duration]*44100.0f); 622 int sampleRate = [self getSampleRate:selectedFilename];
652 double hopSize = [[dbState objectForKey:@"hopsize"] doubleValue]; 623 int hopSize = [self getHopSizeInSamples:selectedFilename];
653 double winSize = [[dbState objectForKey:@"windowsize"] doubleValue]; 624 int winSize = [self nearestPow2:(hopSize*8)];
625
626 double samples = ([queryTrack duration]*sampleRate);
654 627
655 [queryLengthSeconds setDoubleValue:[queryTrack duration]]; 628 [queryLengthSeconds setDoubleValue:[queryTrack duration]];
656 [queryLengthVectors setDoubleValue:ceil((samples-winSize)/hopSize)]; 629 [queryLengthVectors setDoubleValue:ceil((samples-winSize)/hopSize)];
657 630
658 // For now, go with 0 631 // For now, go with 0
663 [queryLengthVectors setEnabled:YES]; 636 [queryLengthVectors setEnabled:YES];
664 [queryStartSeconds setEnabled:YES]; 637 [queryStartSeconds setEnabled:YES];
665 [queryStartVectors setEnabled:YES]; 638 [queryStartVectors setEnabled:YES];
666 [resetButton setEnabled:YES]; 639 [resetButton setEnabled:YES];
667 [multipleCheckBox setEnabled:YES]; 640 [multipleCheckBox setEnabled:YES];
641 [queryButton setEnabled:YES];
668 642
669 } 643 }
670 644
671 - (void)controlTextDidChange:(NSNotification *)nd 645 - (void)controlTextDidChange:(NSNotification *)nd
672 { 646 {
673 NSTextField *ed = [nd object]; 647 NSTextField *ed = [nd object];
674 648
675 double hopSize = [[dbState objectForKey:@"hopsize"] doubleValue]; 649 int sampleRate = [self getSampleRate:selectedFilename];
676 double winSize = [[dbState objectForKey:@"windowsize"] doubleValue]; 650 int hopSize = [self getHopSizeInSamples:selectedFilename];
651 int winSize = [self nearestPow2:(hopSize*8)];
677 652
678 if(!queryTrack) 653 if(!queryTrack)
679 { 654 {
680 queryTrack = [[NSSound alloc] initWithContentsOfFile:selectedFilename byReference:YES]; 655 queryTrack = [[NSSound alloc] initWithContentsOfFile:selectedFilename byReference:YES];
681 } 656 }
682 657
683 double totalDuration = [queryTrack duration]; 658 double totalDuration = [queryTrack duration];
684 double samples = totalDuration * 44100.0f; 659 double samples = totalDuration * sampleRate;
685 double totalVectors = ceil((samples-winSize)/hopSize); 660 double totalVectors = ceil((samples-winSize)/hopSize);
686 661
662
687 double lengthSecs = [queryLengthSeconds doubleValue]; 663 double lengthSecs = [queryLengthSeconds doubleValue];
688 double startSecs = [queryStartSeconds doubleValue]; 664 double startSecs = [queryStartSeconds doubleValue];
689 double lengthVectors = [queryLengthVectors doubleValue]; 665 double lengthVectors = [queryLengthVectors doubleValue];
690 double startVectors = [queryStartVectors doubleValue]; 666 double startVectors = [queryStartVectors doubleValue];
691 667
692 // Query Length 668 // Query Length
693 if (ed == queryLengthSeconds) 669 if (ed == queryLengthSeconds)
694 { 670 {
695 if(lengthSecs >= 0) 671 if(lengthSecs >= 0)
696 { 672 {
697 lengthVectors = ceil(((lengthSecs*44100.0f)-winSize)/hopSize); 673 lengthVectors = ceil(((lengthSecs*sampleRate)-winSize)/hopSize);
698 if(lengthVectors < 0) {lengthVectors = 0; } 674 if(lengthVectors < 0) {lengthVectors = 0; }
699 [queryLengthVectors setDoubleValue:lengthVectors]; 675 [queryLengthVectors setDoubleValue:lengthVectors];
700
701 } 676 }
702 } 677 }
703 678
704 if (ed == queryLengthVectors) 679 if (ed == queryLengthVectors)
705 { 680 {
706 if(lengthVectors >= 0) 681 if(lengthVectors >= 0)
707 { 682 {
708 lengthSecs = ((hopSize*lengthVectors)+winSize)/44100.0f; 683 lengthSecs = ((hopSize*lengthVectors)+winSize)/sampleRate;
709 if(lengthSecs < 0) { lengthSecs = 0; } 684 if(lengthSecs < 0) { lengthSecs = 0; }
710 [queryLengthSeconds setDoubleValue:lengthSecs]; 685 [queryLengthSeconds setDoubleValue:lengthSecs];
711 } 686 }
712 } 687 }
713 688
714 // Query start 689 // Query start
715 if (ed == queryStartSeconds) 690 if (ed == queryStartSeconds)
716 { 691 {
717 if(startSecs >= 0) 692 if(startSecs >= 0)
718 { 693 {
719 startVectors = ceil(((startSecs*44100.0f)-winSize)/hopSize); 694 startVectors = ceil(((startSecs*sampleRate)-winSize)/hopSize);
720 if(startVectors < 0) { startVectors = 0; } 695 if(startVectors < 0) { startVectors = 0; }
721 [queryStartVectors setDoubleValue:startVectors]; 696 [queryStartVectors setDoubleValue:startVectors];
722 } 697 }
723 } 698 }
724 if (ed == queryStartVectors) 699 if (ed == queryStartVectors)
725 { 700 {
726 if(startVectors >= 0) 701 if(startVectors >= 0)
727 { 702 {
728 startSecs = ((hopSize*startVectors)+winSize)/44100.0f; 703 startSecs = ((hopSize*startVectors)+winSize)/sampleRate;
729 if(startSecs < 0) { startSecs = 0; } 704 if(startSecs < 0) { startSecs = 0; }
730 [queryStartSeconds setDoubleValue:startSecs]; 705 [queryStartSeconds setDoubleValue:startSecs];
731 } 706 }
732 } 707 }
733 708
811 786
812 NSLog(@"No results"); 787 NSLog(@"No results");
813 } 788 }
814 else 789 else
815 { 790 {
791
816 NSLog(@"Populate table: %d", result->nresults); 792 NSLog(@"Populate table: %d", result->nresults);
817 float divisor = (44100.0f/hopSize);
818 for(int i=0; i<result->nresults; i++) 793 for(int i=0; i<result->nresults; i++)
819 { 794 {
795
796 NSString* filename = [trackMap objectForKey:[NSString stringWithFormat:@"%s", result->results[i].ikey]];
797 int sampleRate = [self getSampleRate:filename];
798 int hopSize = [self getHopSizeInSamples:filename];
799 float divisor = (sampleRate/hopSize);
820 800
821 NSMutableDictionary* dict = [[NSMutableDictionary alloc] initWithCapacity:4]; 801 NSMutableDictionary* dict = [[NSMutableDictionary alloc] initWithCapacity:4];
822 [dict setValue:[NSString stringWithFormat:@"%s", result->results[i].ikey] forKey:@"key"]; 802 [dict setValue:[NSString stringWithFormat:@"%s", result->results[i].ikey] forKey:@"key"];
823 [dict setValue:[NSNumber numberWithFloat:result->results[i].dist] forKey:@"distance"]; 803 [dict setValue:[NSNumber numberWithFloat:result->results[i].dist] forKey:@"distance"];
824 [dict setValue:[NSNumber numberWithFloat:result->results[i].dist] forKey:@"meter"]; 804 [dict setValue:[NSNumber numberWithFloat:result->results[i].dist] forKey:@"meter"];