iOS SoundTouch framework BPM Detection example

前端 未结 3 1461
盖世英雄少女心
盖世英雄少女心 2020-12-14 04:59

I have searched all over the web and cannot find a tutorial on how to use the SoundTouch library for beat detection.

(Note: I have no C++ experience prior to this

相关标签:
3条回答
  • 2020-12-14 05:23

    After hours and hours of debugging and reading the limited documentation on the web, I modified a few things before stumbling upon this: You need to divide numSamples by numberOfChannels in the inputSamples() function.

    My final code is like so:

    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 讨论(0)
  • 2020-12-14 05:28

    I've tried this solution to read the BPM from mp3 files (using the TSLibraryImport class to convert to wav) inside the 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());
    
    
                                     }];
    

    The strangeness is that the calculated BMP is always the same value:

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

    No matter which track was i.e. number of frames or the buffer size (here I used 2K buffer size as for the SoundTouch example in the source code of the library).

    0 讨论(0)
  • 2020-12-14 05:46

    For Swift 3:

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

    And use it like:

    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)
    

    Feel free to comment!

    0 讨论(0)
提交回复
热议问题