首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >iOS SoundTouch框架业务流程管理检测示例

iOS SoundTouch框架业务流程管理检测示例
EN

Stack Overflow用户
提问于 2013-07-20 10:08:31
回答 3查看 7.6K关注 0票数 5

我已经搜索了整个网络,但没有找到关于如何使用SoundTouch library进行节拍检测的教程。

(注意:在此之前,我没有C++经验。我知道C、Objective-C和Java。因此,我本可以把其中的一些内容搞乱,但它可以编译。)

我将framework添加到我的项目中,并设法获得以下代码以进行编译:

代码语言:javascript
复制
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

inputSamples(*samples, numSamples)歌曲字节信息把我搞糊涂了。

如何从歌曲文件中获取这些信息?

我试过使用memcpy(),但它似乎不起作用。

有人有什么想法吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-07-20 12:10:53

经过一小时又一小时的调试和阅读网上有限的文档,我修改了一些东西,然后偶然发现了这一点:你需要在inputSamples()函数中将numSamples除以numberOfChannels

我的最终代码是这样的:

代码语言:javascript
复制
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());
票数 1
EN

Stack Overflow用户

发布于 2013-10-02 09:12:11

我尝试了这个解决方案,从iOS音乐库中的mp3文件(使用TSLibraryImport类转换为wav)中读取BPM:

代码语言:javascript
复制
                                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总是相同的值:

代码语言:javascript
复制
2013-10-02 03:05:36.725 AppTestAudio[1464:1803]  Beats Per Minute = 117.453835

无论哪个轨道,即帧的数量或缓冲区大小(在这里,我使用2K缓冲区大小作为库的源代码中的SoundTouch示例)。

票数 0
EN

Stack Overflow用户

发布于 2017-04-12 17:47:42

对于Swift 3:

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

并像这样使用它:

代码语言:javascript
复制
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)

欢迎发表评论!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17757975

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档