First off: I don't know much about audio processing. I know with Core Audio, you can get the info about a playing track.
My goal is to have a node in SpriteKit with the current amplitude/loudness of the current song from iTunes being its scale (say, scale should be at 1.0
at its loudest and 0.0
at its quietest).
I can do the node programming (setting xScale
and yScale
to a float
amp
). My problem is involved with getting amp
's value.
Here's my code:
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];
What I get is a constant output of -120 dB
and lag (this is in my update
method). Where it would normally be 60 fps, it is 10-11 on my iPhone 6. Any idea how to fix this? I've searched online for a solid hour but got nothing.
I'm not sure if I'm interpreting your code correctly, but it looks like you might be instantiating your player every frame with would explain the slowness. You need to set your player up ahead of time. Then on your timer, call updateMeters right before you get averagePowerForChannel. I'm not familiar with spiteKit, so I just used UIKit with viewDidLoad and a displayLink for my timer.