2013-07-20 11 views
5

Przeszukałem cały Internet i nie mogę znaleźć samouczka, jak korzystać z SoundTouch library do wykrywania rytmu.Struktura iOS SoundTouch Przykład BPM Detection

(Uwaga:... Nie mam doświadczenia z C++ Wcześniej wiem C, Objective-C i Java więc mogłem pomieszane trochę tego, ale kompiluje)

I dodaje framework do mojego projektu i udało się uzyskać następujące skompilować:

NSString *path = [[NSBundle mainBundle] pathForResource:@"song" ofType:@"wav"]; 

NSData *data = [NSData dataWithContentsOfFile:path]; 

player =[[AVAudioPlayer alloc] initWithData:data error:NULL]; 

player.volume = 1.0; 

player.delegate = self; 

[player prepareToPlay]; 
[player play]; 

NSUInteger len = [player.data length]; // Get the length of the data 

soundtouch::SAMPLETYPE sampleBuffer[len]; // Create buffer array 

[player.data getBytes:sampleBuffer length:len]; // Copy the bytes into the buffer 

soundtouch::BPMDetect *BPM = new soundtouch::BPMDetect(player.numberOfChannels, [[player.settings valueForKey:@"AVSampleRateKey"] longValue]); // This is working (tested) 

BPM->inputSamples(sampleBuffer, len); // Send the samples to the BPM class 

NSLog(@"Beats Per Minute = %f", BPM->getBpm()); // Print out the BPM - currently returns 0.00 for errors per documentation 

informacje bajt inputSamples(*samples, numSamples) piosenka myli mnie.

Jak uzyskać te informacje z pliku utworu?

Próbowałem użyć memcpy(), ale wydaje się, że nie działa.

Ktoś ma jakieś myśli?

Odpowiedz

1

Po wiele godzin debugowania i czytanie ograniczoną dokumentację w internecie, I zmodyfikowano kilka rzeczy przed natrafiają na to: Trzeba podzielić numSamples przez numberOfChannels w funkcji inputSamples().

Moja ostatnia kod jest tak:

NSString *path = [[NSBundle mainBundle] pathForResource:@"song" ofType:@"wav"]; 

NSData *data = [NSData dataWithContentsOfFile:path]; 

player =[[AVAudioPlayer alloc] initWithData:data error:NULL]; 

player.volume = 1.0; // optional to play music 

player.delegate = self; 

[player prepareToPlay]; // optional to play music 
[player play];   // optional to play music 

NSUInteger len = [player.data length]; 

soundtouch::SAMPLETYPE sampleBuffer[len]; 

[player.data getBytes:sampleBuffer length:len]; 

soundtouch::BPMDetect BPM(player.numberOfChannels, [[player.settings valueForKey:@"AVSampleRateKey"] longValue]); 

BPM.inputSamples(sampleBuffer, len/player.numberOfChannels); 

NSLog(@"Beats Per Minute = %f", BPM.getBpm()); 
+0

fajne czy możesz powiedzieć, w jaki sposób dodałeś bibliotekę SoundTouch do projektu xcode? – otakuProgrammer

+0

Wystarczy pobrać framework i zaimportować go do projektu. – MrHappyAsthma

+0

ok udało mi się dołączyć go do projektu xcode, powyższy kod nie będzie działał, czasami aplikacja się zawiesza, próbowałem zarówno plików wav i mp3, korzystałem nawet z oryginalnej próbki audio z witryny soundtouch, to spowodowało awarię issue, or nan result (przy użyciu oryginalnego dźwięku próbnego) – otakuProgrammer

0

Próbowałem to rozwiązanie do zapoznania się z BPM z plików mp3 (przy użyciu klasy TSLibraryImport przekonwertować do WAV) wewnątrz iOS Music Library:

       MPMediaItem *item = [collection representativeItem]; 

           NSURL *urlStr = [item valueForProperty:MPMediaItemPropertyAssetURL]; 

           TSLibraryImport* import = [[TSLibraryImport alloc] init]; 

           NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
           NSString *documentsDirectory = [paths objectAtIndex:0]; 

           NSURL* destinationURL = [NSURL fileURLWithPath:[documentsDirectory stringByAppendingPathComponent:@"temp_data"]]; 
           [[NSFileManager defaultManager] removeItemAtURL:destinationURL error:nil]; 

           [import importAsset:urlStr toURL:destinationURL completionBlock:^(TSLibraryImport* import) { 

            NSString *outPath = [documentsDirectory stringByAppendingPathComponent:@"temp_data"]; 


            NSData *data = [NSData dataWithContentsOfFile:outPath]; 
            AVAudioPlayer *player =[[AVAudioPlayer alloc] initWithData:data error:NULL]; 

            NSUInteger len = [player.data length]; 
            int numChannels = player.numberOfChannels; 

            soundtouch::SAMPLETYPE sampleBuffer[1024]; 

            soundtouch::BPMDetect *BPM = new soundtouch::BPMDetect(player.numberOfChannels, [[player.settings valueForKey:@"AVSampleRateKey"] longValue]); 


            for (NSUInteger i = 0; i <= len - 1024; i = i + 1024) { 

             NSRange r = NSMakeRange(i, 1024); 
             //NSData *temp = [player.data subdataWithRange:r]; 
             [player.data getBytes:sampleBuffer range:r]; 

             int samples = sizeof(sampleBuffer)/numChannels; 

             BPM->inputSamples(sampleBuffer, samples); // Send the samples to the BPM class 

            } 

            NSLog(@"Beats Per Minute = %f", BPM->getBpm()); 


           }]; 

dziwność jest, że obliczony BMP jest zawsze taka sama wartość:

2013-10-02 03:05:36.725 AppTestAudio[1464:1803] Beats Per Minute = 117.453835 

Nie zależnie od tego, która ścieżka była liczbą klatek lub wielkością bufora (tutaj użyłem rozmiaru bufora 2K, jak w przypadku przykładu SoundTouch w kodzie źródłowym biblioteki).

0

Dla Swift 3:

https://github.com/Luccifer/BPM-Analyser

i używać go lubię:

guard let filePath = Bundle.main.path(forResource: "TestMusic", ofType: "m4a"), 
let url = URL(string: filePath) else {return "error occured, check fileURL"} 

BPMAnalyzer.core.getBpmFrom(url, completion: nil) 

Zapraszam do komentowania!