Mercurial > hg > audiodb
comparison examples/iAudioDB/AppController.m @ 687:e2f4924130ef
* Query parameters added (multi, length, etc)
* Tweaks to status bar for more detailed info
author | mas01mj |
---|---|
date | Thu, 11 Mar 2010 17:19:15 +0000 |
parents | e78e5a80b73d |
children | 8bc10774e56b |
comparison
equal
deleted
inserted
replaced
686:d9bb0dba8e7a | 687:e2f4924130ef |
---|---|
3 // iAudioDB | 3 // iAudioDB |
4 // | 4 // |
5 // Created by Mike Jewell on 27/01/2010. | 5 // Created by Mike Jewell on 27/01/2010. |
6 // Copyright 2010 __MyCompanyName__. All rights reserved. | 6 // Copyright 2010 __MyCompanyName__. All rights reserved. |
7 // | 7 // |
8 | |
9 #import "AppController.h" | 8 #import "AppController.h" |
9 | |
10 | 10 |
11 | 11 |
12 @implementation AppController | 12 @implementation AppController |
13 | 13 |
14 -(id)init | 14 -(id)init |
93 // Calculate the max DB size | 93 // Calculate the max DB size |
94 int vectors = ceil(([maxLengthField doubleValue] * 60) / ([hopSizeField doubleValue] / 44100)); | 94 int vectors = ceil(([maxLengthField doubleValue] * 60) / ([hopSizeField doubleValue] / 44100)); |
95 int numtracks = [maxTracksField intValue]; | 95 int numtracks = [maxTracksField intValue]; |
96 int datasize = ceil((numtracks * vectors * dim * 8) / 1024 / 1024); // In MB | 96 int datasize = ceil((numtracks * vectors * dim * 8) / 1024 / 1024); // In MB |
97 | 97 |
98 // TODO: Refactor this into a 'tidy' method. | 98 [self reset]; |
99 // Tidy any existing references up. | |
100 if(db) | |
101 { | |
102 audiodb_close(db); | |
103 } | |
104 | |
105 if(dbFilename) | |
106 { | |
107 [dbFilename release]; | |
108 [dbName release]; | |
109 [plistFilename release]; | |
110 } | |
111 | 99 |
112 // Create new db, and set flags. | 100 // Create new db, and set flags. |
113 db = audiodb_create([[panel filename] cStringUsingEncoding:NSUTF8StringEncoding], datasize, numtracks, dim); | 101 db = audiodb_create([[panel filename] cStringUsingEncoding:NSUTF8StringEncoding], datasize, numtracks, dim); |
114 audiodb_l2norm(db); | 102 audiodb_l2norm(db); |
115 | 103 |
130 [queryKey setStringValue:@"None Selected"]; | 118 [queryKey setStringValue:@"None Selected"]; |
131 [self updateStatus]; | 119 [self updateStatus]; |
132 } | 120 } |
133 } | 121 } |
134 | 122 |
123 -(void)reset | |
124 { | |
125 // Tidy any existing references up. | |
126 if(db) | |
127 { | |
128 NSLog(@"Close db"); | |
129 audiodb_close(db); | |
130 } | |
131 | |
132 if(dbFilename) | |
133 { | |
134 NSLog(@"Tidy up filenames"); | |
135 [dbFilename release]; | |
136 [dbName release]; | |
137 [plistFilename release]; | |
138 [trackMap release]; | |
139 [dbState release]; | |
140 } | |
141 | |
142 // Reset query flags | |
143 [queryPath setStringValue: @"No file selected"]; | |
144 [queryLengthSeconds setDoubleValue:0]; | |
145 [queryLengthVectors setDoubleValue:0]; | |
146 [multipleCheckBox setState:NSOnState]; | |
147 } | |
148 | |
135 /** | 149 /** |
136 * Open an existing adb (which must have a plist) | 150 * Open an existing adb (which must have a plist) |
137 */ | 151 */ |
138 -(IBAction)openDatabase:(id)sender | 152 -(IBAction)openDatabase:(id)sender |
139 { | 153 { |
140 NSArray *fileTypes = [NSArray arrayWithObject:@"adb"]; | 154 NSArray *fileTypes = [NSArray arrayWithObject:@"adb"]; |
141 NSOpenPanel* panel = [NSOpenPanel openPanel]; | 155 NSOpenPanel* panel = [NSOpenPanel openPanel]; |
142 NSInteger response = [panel runModalForDirectory:NSHomeDirectory() file:@"" types:fileTypes]; | 156 NSInteger response = [panel runModalForDirectory:NSHomeDirectory() file:@"" types:fileTypes]; |
143 if(response == NSFileHandlingPanelOKButton) | 157 if(response == NSFileHandlingPanelOKButton) |
144 { | 158 { |
145 // Tidy any existing references up. | 159 [self reset]; |
146 if(db) | |
147 { | |
148 NSLog(@"Close db"); | |
149 audiodb_close(db); | |
150 } | |
151 | |
152 if(dbFilename) | |
153 { | |
154 NSLog(@"Tidy up filenames"); | |
155 [dbFilename release]; | |
156 [dbName release]; | |
157 [plistFilename release]; | |
158 [trackMap release]; | |
159 [dbState release]; | |
160 } | |
161 | 160 |
162 // Store useful paths. | 161 // Store useful paths. |
163 NSLog(@"Open"); | 162 NSLog(@"Open"); |
164 db = audiodb_open([[panel filename] cStringUsingEncoding:NSUTF8StringEncoding], O_RDONLY); | 163 db = audiodb_open([[panel filename] cStringUsingEncoding:NSUTF8StringEncoding], O_RDONLY); |
165 dbName = [[[panel URL] relativePath] retain]; | 164 dbName = [[[panel URL] relativePath] retain]; |
171 // Clear out any old results. | 170 // Clear out any old results. |
172 [results removeAllObjects]; | 171 [results removeAllObjects]; |
173 [tracksView reloadData]; | 172 [tracksView reloadData]; |
174 | 173 |
175 [queryKey setStringValue:@"None Selected"]; | 174 [queryKey setStringValue:@"None Selected"]; |
176 [self updateStatus]; | |
177 | 175 |
178 adb_liszt_results_t* liszt_results = audiodb_liszt(db); | 176 adb_liszt_results_t* liszt_results = audiodb_liszt(db); |
179 | 177 |
180 for(int k=0; k<liszt_results->nresults; k++) | 178 for(int k=0; k<liszt_results->nresults; k++) |
181 { | 179 { |
185 | 183 |
186 audiodb_liszt_free_results(db, liszt_results); | 184 audiodb_liszt_free_results(db, liszt_results); |
187 dbState = [[[NSMutableDictionary alloc] initWithContentsOfFile:plistFilename] retain]; | 185 dbState = [[[NSMutableDictionary alloc] initWithContentsOfFile:plistFilename] retain]; |
188 trackMap = [[dbState objectForKey:@"tracks"] retain]; | 186 trackMap = [[dbState objectForKey:@"tracks"] retain]; |
189 | 187 |
188 [self updateStatus]; | |
189 | |
190 NSLog(@"Size: %d", [trackMap count]); | 190 NSLog(@"Size: %d", [trackMap count]); |
191 } | 191 } |
192 } | |
193 | |
194 -(IBAction)pathAction:(id)sender | |
195 { | |
196 NSLog(@"Path action"); | |
192 } | 197 } |
193 | 198 |
194 /** | 199 /** |
195 * Update button states and status field based on current state. | 200 * Update button states and status field based on current state. |
196 */ | 201 */ |
201 { | 206 { |
202 NSLog(@"Got a db"); | 207 NSLog(@"Got a db"); |
203 adb_status_t *status = (adb_status_t *)malloc(sizeof(adb_status_t)); | 208 adb_status_t *status = (adb_status_t *)malloc(sizeof(adb_status_t)); |
204 int flags; | 209 int flags; |
205 flags = audiodb_status(db, status); | 210 flags = audiodb_status(db, status); |
206 [statusField setStringValue: [NSString stringWithFormat:@"Database: %@ Dimensions: %d Files: %d", dbName, status->dim, status->numFiles]]; | 211 [statusField setStringValue: [NSString stringWithFormat:@"%@ Dim: %d Files: %d Hop: %@ Win: %@ Ext: %@", |
207 [chooseButton setEnabled:YES]; | 212 dbName, |
213 status->dim, | |
214 status->numFiles, | |
215 [dbState objectForKey:@"hopsize"], | |
216 [dbState objectForKey:@"windowsize"], | |
217 [dbState objectForKey:@"extractor"]]]; | |
218 [performQueryButton setEnabled:YES]; | |
208 } | 219 } |
209 else | 220 else |
210 { | 221 { |
211 NSLog(@"No db"); | 222 NSLog(@"No db"); |
212 [chooseButton setEnabled:NO]; | 223 [performQueryButton setEnabled:NO]; |
213 [playBothButton setEnabled:FALSE]; | 224 [playBothButton setEnabled:FALSE]; |
214 [playResultButton setEnabled:FALSE]; | 225 [playResultButton setEnabled:FALSE]; |
215 } | 226 } |
216 } | 227 } |
217 | 228 |
238 NSArray *filesToOpen = [panel filenames]; | 249 NSArray *filesToOpen = [panel filenames]; |
239 | 250 |
240 NSString* extractor = [dbState objectForKey:@"extractor"]; | 251 NSString* extractor = [dbState objectForKey:@"extractor"]; |
241 NSString* extractorPath = [NSString stringWithFormat:@"/Users/mikej/Development/audioDB/examples/iAudioDB/rdf/%@.n3", extractor]; | 252 NSString* extractorPath = [NSString stringWithFormat:@"/Users/mikej/Development/audioDB/examples/iAudioDB/rdf/%@.n3", extractor]; |
242 | 253 |
254 // TODO Shift this process into a separate function. | |
243 // Create the customized extractor config | 255 // Create the customized extractor config |
244 NSString* extractorContent = [NSString stringWithContentsOfFile:extractorPath]; | 256 NSString* extractorContent = [NSString stringWithContentsOfFile:extractorPath]; |
245 NSString* hopStr = [dbState objectForKey:@"hopsize"]; | 257 NSString* hopStr = [dbState objectForKey:@"hopsize"]; |
246 NSString* winStr = [dbState objectForKey:@"windowsize"]; | 258 NSString* winStr = [dbState objectForKey:@"windowsize"]; |
247 NSString* newContent = [[extractorContent stringByReplacingOccurrencesOfString:@"HOP_SIZE" withString:hopStr] | 259 NSString* newContent = [[extractorContent stringByReplacingOccurrencesOfString:@"HOP_SIZE" withString:hopStr] |
497 /** | 509 /** |
498 * Select an audio file, determine the key, and fire off a query. | 510 * Select an audio file, determine the key, and fire off a query. |
499 */ | 511 */ |
500 -(IBAction)chooseQuery:(id)sender | 512 -(IBAction)chooseQuery:(id)sender |
501 { | 513 { |
514 [NSApp beginSheet:querySheet modalForWindow:mainWindow modalDelegate:self didEndSelector:NULL contextInfo:nil]; | |
515 session = [NSApp beginModalSessionForWindow:querySheet]; | |
516 [NSApp runModalSession:session]; | |
517 } | |
518 | |
519 | |
520 -(IBAction)selectQueryFile:(id)sender | |
521 { | |
502 NSArray* fileTypes = [NSArray arrayWithObject:@"wav"]; | 522 NSArray* fileTypes = [NSArray arrayWithObject:@"wav"]; |
503 NSOpenPanel* panel = [NSOpenPanel openPanel]; | 523 NSOpenPanel* panel = [NSOpenPanel openPanel]; |
504 NSInteger response = [panel runModalForDirectory:NSHomeDirectory() file:@"" types:fileTypes]; | 524 NSInteger response = [panel runModalForDirectory:NSHomeDirectory() file:@"" types:fileTypes]; |
505 if(response == NSFileHandlingPanelOKButton) | 525 if(response == NSFileHandlingPanelOKButton) |
506 { | 526 { |
507 NSLog(@"%@", [panel filename]); | |
508 // Grab key | |
509 NSArray* opts = [trackMap allKeysForObject:[panel filename]]; | 527 NSArray* opts = [trackMap allKeysForObject:[panel filename]]; |
510 if([opts count] != 1) | 528 if([opts count] != 1) |
511 { | 529 { |
530 // TODO : Needs fixing! | |
531 | |
512 NSAlert *alert = [[[NSAlert alloc] init] autorelease]; | 532 NSAlert *alert = [[[NSAlert alloc] init] autorelease]; |
513 [alert addButtonWithTitle:@"OK"]; | 533 [alert addButtonWithTitle:@"OK"]; |
514 [alert setMessageText:@"Track not found"]; | 534 [alert setMessageText:@"Track not found"]; |
515 [alert setInformativeText:@"Make sure you have specified a valid track identifier."]; | 535 [alert setInformativeText:@"Make sure you have specified a valid track identifier."]; |
516 [alert setAlertStyle:NSWarningAlertStyle]; | 536 [alert setAlertStyle:NSWarningAlertStyle]; |
518 } | 538 } |
519 else | 539 else |
520 { | 540 { |
521 selectedKey = [opts objectAtIndex:0]; | 541 selectedKey = [opts objectAtIndex:0]; |
522 [queryKey setStringValue:selectedKey]; | 542 [queryKey setStringValue:selectedKey]; |
543 [queryPath setStringValue:selectedKey]; | |
523 selectedFilename = [[panel filename] retain]; | 544 selectedFilename = [[panel filename] retain]; |
524 [self performQuery]; | 545 |
525 } | 546 [self resetLengths:self]; |
526 } | 547 } |
548 } | |
549 } | |
550 | |
551 -(IBAction)resetLengths:(id)sender | |
552 { | |
553 queryTrack = [[NSSound alloc] initWithContentsOfFile:selectedFilename byReference:YES]; | |
554 NSLog(@"%f", [queryTrack duration]); | |
555 double samples = ([queryTrack duration]*44100); | |
556 double hopSize = [[dbState objectForKey:@"hopsize"] doubleValue]; | |
557 double winSize = [[dbState objectForKey:@"windowsize"] doubleValue]; | |
558 | |
559 [queryLengthSeconds setDoubleValue:ceil([queryTrack duration])]; | |
560 [queryLengthVectors setDoubleValue:ceil((samples-winSize)/hopSize)]; | |
561 | |
562 } | |
563 | |
564 - (void)controlTextDidChange:(NSNotification *)nd | |
565 { | |
566 NSTextField *ed = [nd object]; | |
567 | |
568 double hopSize = [[dbState objectForKey:@"hopsize"] doubleValue]; | |
569 double winSize = [[dbState objectForKey:@"windowsize"] doubleValue]; | |
570 | |
571 if (ed == queryLengthSeconds) | |
572 { | |
573 double secs = [queryLengthSeconds doubleValue]; | |
574 if(secs > 0) | |
575 { | |
576 [queryLengthVectors setDoubleValue:ceil(((secs*44100)-winSize)/hopSize)]; | |
577 } | |
578 } | |
579 if (ed == queryLengthVectors) | |
580 { | |
581 double vectors = [queryLengthVectors doubleValue]; | |
582 if(vectors > 0) | |
583 { | |
584 [queryLengthSeconds setDoubleValue:ceil(((hopSize*vectors)+winSize)/44100)]; | |
585 } | |
586 } | |
587 }; | |
588 | |
589 -(IBAction)cancelQuery:(id)sender | |
590 { | |
591 [NSApp endModalSession:session]; | |
592 [querySheet orderOut:nil]; | |
593 [NSApp endSheet:querySheet]; | |
527 } | 594 } |
528 | 595 |
529 /** | 596 /** |
530 * Actually perform the query. TODO: Monolithic. | 597 * Actually perform the query. TODO: Monolithic. |
531 */ | 598 */ |
532 -(void)performQuery | 599 -(IBAction)performQuery:(id)sender |
533 { | 600 { |
601 [NSApp endModalSession:session]; | |
602 [querySheet orderOut:nil]; | |
603 [NSApp endSheet:querySheet]; | |
604 | |
534 NSLog(@"Perform query! %@, %@", selectedKey, selectedFilename); | 605 NSLog(@"Perform query! %@, %@", selectedKey, selectedFilename); |
535 | 606 |
536 adb_query_spec_t *spec = (adb_query_spec_t *)malloc(sizeof(adb_query_spec_t)); | 607 adb_query_spec_t *spec = (adb_query_spec_t *)malloc(sizeof(adb_query_spec_t)); |
537 spec->qid.datum = (adb_datum_t *)malloc(sizeof(adb_datum_t)); | 608 spec->qid.datum = (adb_datum_t *)malloc(sizeof(adb_datum_t)); |
538 | 609 |
539 spec->qid.sequence_length = 20; | 610 spec->qid.sequence_length = [queryLengthVectors doubleValue]; |
540 spec->qid.sequence_start = 0; | 611 spec->qid.sequence_start = 0; |
541 spec->qid.flags = 0; | 612 spec->qid.flags = 0; |
542 | |
543 // spec->qid.flags = spec->qid.flags | ADB_QID_FLAG_EXHAUSTIVE; | 613 // spec->qid.flags = spec->qid.flags | ADB_QID_FLAG_EXHAUSTIVE; |
614 | |
544 spec->params.accumulation = ADB_ACCUMULATION_PER_TRACK; | 615 spec->params.accumulation = ADB_ACCUMULATION_PER_TRACK; |
616 | |
617 if([multipleCheckBox state] == NSOnState) | |
618 { | |
619 spec->params.npoints = 10; | |
620 } | |
621 else | |
622 { | |
623 spec->params.npoints = 1; | |
624 } | |
625 | |
545 spec->params.distance = ADB_DISTANCE_EUCLIDEAN_NORMED; | 626 spec->params.distance = ADB_DISTANCE_EUCLIDEAN_NORMED; |
546 | 627 |
547 spec->params.npoints = 1; | |
548 spec->params.ntracks = 100; | 628 spec->params.ntracks = 100; |
549 //spec->refine.radius = 5.0; | 629 //spec->refine.radius = 5.0; |
550 // spec->refine.absolute_threshold = -6; | 630 // spec->refine.absolute_threshold = -6; |
551 // spec->refine.relative_threshold = 10; | 631 // spec->refine.relative_threshold = 10; |
552 // spec->refine.duration_ratio = 0; | 632 // spec->refine.duration_ratio = 0; |