目前在我的应用程序中,我正在对来自内置麦克风的音频样本进行FFT分析。我让用户从ipod库播放歌曲,使用扬声器,麦克风捕获声音,我可以计算FFT。我对这个解决方案不满意。我想直接从音频文件(ipod库)获取样本并计算FFT。我知道这是可能的,因为我在AppStore中看到了可以分析来自ipod库的歌曲的应用程序。我怎样才能做到这一点?
答案 0 :(得分:0)
您可以使用AVAssetExportSession
将用户库中的歌曲导出到本地文件。然后使用ExtAudioRead
API打开文件并执行FFT操作。有这样的效果:
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset: asset
presetName: AVAssetExportPresetPassthrough];
NSString *ext = [url pathExtension];
if ([ext isEqual: @"mp3"])
{
exporter.outputFileType = AVFileTypeQuickTimeMovie;
ext = @"mov"; // this is create an mov with mp3 data hidden inside it.. huhuhhaha
}
else if ([ext isEqual: @"m4a"])
{
exporter.outputFileType = AVFileTypeAppleM4A;
}
else if ([ext isEqual: @"wav"])
{
exporter.outputFileType = AVFileTypeWAVE;
}
else if ([ext isEqual: @"aif"])
{
exporter.outputFileType = AVFileTypeAIFF;
}
exporter.outputURL = exportURL;
[exporter exportAsynchronouslyWithCompletionHandler: ^(void){
int exportStatus = exporter.status;
switch (exportStatus) {
case AVAssetExportSessionStatusCompleted: {
exportedURL = exporter.outputURL;
break;
}
}
}];
答案 1 :(得分:0)
我最终使用novocaine。用它计算FFT很简单:
self.audioManager = [Novocaine audioManager];
self.audioManager.forceOutputToSpeaker = YES;
self.fileReader= [[AudioFileReader alloc]
initWithAudioFileURL:inputFileURL
samplingRate:self.audioManager.samplingRate
numChannels:self.audioManager.numOutputChannels];
[self.fileReader play];
__block COMPLEX_SPLIT AA = A;
__block int nOver = nOver2;
FFTSetup fftSetup2 = fftSetup;
__block int log = log2n;
__block int n2 = n;
__weak MainViewController *listener2 = listener;
__weak AudioManager *wself = self;
__block float *window = (float *)malloc(sizeof(float) * n2);
vDSP_hamm_window(window, n2, 0);
__block BOOL songStarted = NO;
__block float *data = (float *)malloc(sizeof(float) * n2);
[self.audioManager setOutputBlock:^(float *data2, UInt32 numFrames, UInt32 numChannels)
{
[wself.fileReader retrieveFreshAudio:data2 numFrames:numFrames numChannels:numChannels];
if(!wself.fileReader.playing && songStarted)
{
[listener2 nextSong:nil];
[wself.audioManager setOutputBlock:nil];
return;
}
else if(wself.fileReader.playing && !songStarted)
songStarted = YES;
vDSP_vmul(data2, 1, window, 1, data, 1, n2);
vDSP_ctoz((COMPLEX*)data, 2, &AA, 1, nOver);
vDSP_fft_zrip(fftSetup2, &AA, 1, log, FFT_FORWARD);
// calculating square of magnitude for each value
vDSP_zvmags(&AA, 1, AA.realp, 1, nOver);
float *tab_results = (float *)malloc(32 * sizeof(float));
for(int i=0;i<32;i++)
tab_results[i]=AA.realp[i+5];//i+5
[listener2 sendResults:tab_results];
memset(data, 0, n2*sizeof(float));
}];
[self.audioManager play];
答案 2 :(得分:-3)
尝试 .H
#import <MediaPlayer/MediaPlayer.h>
#import <CoreAudio/CoreAudioTypes.h>
@interface ViewController : UIViewController {
MPMusicPlayerController *myPlayer;
}
在.m
- (void)viewDidLoad {
[super viewDidLoad];
myPlayer = [MPMusicPlayerController applicationMusicPlayer];
[myPlayer beginGeneratingPlaybackNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemUpdated) name:MPMusicPlayerControllerNowPlayingItemDidChangeNotification object:nil];
// Do any additional setup after loading the view, typically from a nib.
}
然后您可以使用[MPMediaQuery songsQuery]
要解析每首歌曲,请尝试使用此代码,其中[myPlayer nowPlayingItem]
是查询中的每个项目:
NSString *artist = [[myPlayer nowPlayingItem] valueForKey:MPMediaItemPropertyArtist];
NSString *title = [[myPlayer nowPlayingItem] valueForKey:MPMediaItemPropertyTitle];
NSString *genre = [[myPlayer nowPlayingItem] valueForKey:MPMediaItemPropertyGenre];
NSString *duration = [[myPlayer nowPlayingItem] valueForKey:MPMediaItemPropertyPlaybackDuration];
int minutes = floor([duration floatValue]/60);
int seconds = round([duration floatValue] - minutes * 60);
NSLog(@"%@ - %@ (%i:%02d) Genre:%@",artist,title, minutes,seconds,genre);