iPhone - 获取当前点的音频幅度
iPhone - get amplitude of audio at current point
首先:我对音频处理了解不多。我知道使用 Core Audio,您可以获得有关 正在播放 曲目的信息。
我的目标是在 SpriteKit 中有一个节点,当前来自 iTunes 的歌曲的 amplitude/loudness 是它的音阶(例如,音阶应该在 1.0
最大声和 0.0
在最安静的时候)。
我可以进行节点编程(将 xScale
和 yScale
设置为 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 上是 10-11 6。知道如何解决这个问题吗?我在网上搜索了整整一个小时,但一无所获。
我不确定我是否正确解释了您的代码,但看起来您可能在每一帧都实例化了您的播放器,这可以解释速度缓慢的原因。您需要提前设置播放器。然后在您的计时器上,在获得 averagePowerForChannel 之前立即调用 updateMeters。我不熟悉 spiteKit,所以我只是将 UIKit 与 viewDidLoad 和一个 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];
}
首先:我对音频处理了解不多。我知道使用 Core Audio,您可以获得有关 正在播放 曲目的信息。
我的目标是在 SpriteKit 中有一个节点,当前来自 iTunes 的歌曲的 amplitude/loudness 是它的音阶(例如,音阶应该在 1.0
最大声和 0.0
在最安静的时候)。
我可以进行节点编程(将 xScale
和 yScale
设置为 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 上是 10-11 6。知道如何解决这个问题吗?我在网上搜索了整整一个小时,但一无所获。
我不确定我是否正确解释了您的代码,但看起来您可能在每一帧都实例化了您的播放器,这可以解释速度缓慢的原因。您需要提前设置播放器。然后在您的计时器上,在获得 averagePowerForChannel 之前立即调用 updateMeters。我不熟悉 spiteKit,所以我只是将 UIKit 与 viewDidLoad 和一个 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];
}