iPhone - 获取当前音频的振幅

时间:2015-06-16 04:31:22

标签: ios objective-c iphone avaudioplayer

首先:我对音频处理知之甚少。我知道使用Core Audio,您可以获得有关播放曲目的信息。

我的目标是在SpriteKit中创建一个节点,当前iTunes中当前歌曲的当前幅度/响度是它的音阶(比如,音阶应该在1.0最大,0.0在其最大最安静)。

我可以进行节点编程(将xScaleyScale设置为float amp)。我的问题涉及获得amp的价值。

这是我的代码:

AVAudioPlayer *somePlayer = [AVAudioPlayer new];
__autoreleasing NSError* error;
somePlayer = [somePlayer initWithContentsOfURL:[[[MPMusicPlayerController systemMusicPlayer] nowPlayingItem] valueForProperty:MPMediaItemPropertyAssetURL] error:&error];
somePlayer.currentTime = [[MPMusicPlayerController systemMusicPlayer] currentPlaybackTime];
somePlayer.volume = 0;
[somePlayer play];
[somePlayer setMeteringEnabled:YES];
[somePlayer updateMeters];
NSMutableArray* amps = [NSMutableArray array];
if (error != nil) {
    NSLog(@"error: %@", error.debugDescription);
}
for (int i = 0; i < somePlayer.numberOfChannels; i++) {
    [amps addObject:@([somePlayer averagePowerForChannel:i]);
    NSLog(@"Amplitude: %f db for channel %i", [somePlayer averagePowerForChannel:i], i);
}
float amp = 0;
for (NSNumber *x in amps) {
    amp += [x floatValue];
}
amp /= amps.count;
NSLog(@"amp: %f", amp);
// set xScale and yScale to "amp"
[somePlayer stop];

我得到的是-120 dB和滞后的恒定输出(这是我的update方法)。它通常是60 fps,在我的iPhone 6上是10-11。任何想法如何解决这个问题?我在网上搜索了一个小时但却一无所获。

1 个答案:

答案 0 :(得分:0)

我不确定我是否正确地解释了您的代码,但看起来您可能会在每一帧中实例化您的播放器并解释它的缓慢程度。您需要提前设置播放器。然后在您的计时器上,在获得averagePowerForChannel之前调用updateMeters。我不熟悉spiteKit,所以我只使用了带有viewDidLoad的UIKit和一个用于我的计时器的displayLink。

@interface ViewController (){
    AVAudioPlayer *somePlayer;
    UIView *redView;
    UIView *blueView;
}

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    NSURL *eggman = [[NSBundle mainBundle]URLForResource:@"Eggman" withExtension:@"mp3"];
    somePlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:eggman error:NULL];
    [somePlayer setMeteringEnabled:YES];
    [somePlayer play];


    [self addViews];
    CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(animateViews)];
    [displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}


-(void)animateViews{

    [somePlayer updateMeters];
    float left_db = [somePlayer averagePowerForChannel:0];
    float right_db;
    if (somePlayer.numberOfChannels > 1) {
        right_db = [somePlayer averagePowerForChannel:1];
    }
    else{
        right_db = left_db;
    }


    float blueScale = db_to_scale(left_db);
    float redScale = db_to_scale(right_db);
    float vert = self.view.bounds.size.height - 80;

    blueView.center = CGPointMake(blueView.center.x, vert - (vert * blueScale));
    redView.center = CGPointMake(redView.center.x, vert - (vert * redScale));

}
float db_to_scale(float decibles){
    return powf(10, (0.05 * decibles));
}
-(void)addViews{
    blueView = [[UIView alloc]initWithFrame:CGRectMake(80, 80, 80, 80)];
    blueView.backgroundColor = [UIColor blueColor];
    [self.view addSubview:blueView];

    redView = [[UIView alloc]initWithFrame:CGRectMake(160, 80, 80, 80)];
    redView.backgroundColor = [UIColor redColor];
    [self.view addSubview:redView];
}