2013-07-20 29 views
5

我在網上搜索了所有內容,找不到關於如何使用SoundTouch library進行節拍檢測的教程。iOS SoundTouch框架BPM檢測示例

(注:。我必須在此之前沒有C++的經驗,我知道C,Objective-C的,和Java這樣我就可以搞砸了一些這件事,但它編譯)

我增加了framework到我的項目,並設法得到如下編譯:

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 

的​​歌曲字節的信息讓我困惑。

如何從歌曲文件中獲取這些信息?

我試過使用memcpy(),但它似乎沒有工作。

任何人有任何想法?

回答

1

小時後,調試的時間和讀取網絡上有限的文件,我在此之前絆腳石修改的幾件事情:你需要通過numberOfChannelsinputSamples()功能來劃分numSamples

我的最終代碼是像這樣:

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

很酷,你能告訴你如何將SoundTouch庫添加到xcode項目? – otakuProgrammer

+0

您只需下載框架並將其導入到您的項目中。 – MrHappyAsthma

+0

好吧,我已經設法將它包括到xcode項目中,上面的代碼不會工作,有時候應用程序崩潰,我嘗試了wav和mp3文件,我甚至使用了來自soundtouch網站的原始音頻樣本,它給了我一個崩潰問題或nan結果(使用原始樣本音頻時) – otakuProgrammer

0

我試過這個解決方案來讀取MP3文件的iOS音樂庫中的BPM(使用TSLibraryImport類轉換爲WAV):

       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()); 


           }]; 

的陌生感是計算的BMP始終是相同的值:

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

無問題是哪個軌道是幀的數量或緩衝區大小(這裏我使用了庫的源代碼中SoundTouch示例的2K緩衝區大小)。

0

對於斯威夫特3:

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

而且使用它像:

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) 

隨意發表評論!