带有AVAudioPlayer的SKEmiterNode用于音乐视觉效果

请有人帮助!

我希望使用AVAudioPlayer将我的SKEmiterNode的音阶(意义上的大小)变得越来越小。 现在这几乎是我所有的SKEmiterNode,它看起来很棒:

beatParticle?.position = CGPoint(x: self.size.width * 0.5, y: self.size.height * 0.5) var beatParticleEffectNode = SKEffectNode() beatParticleEffectNode.addChild(beatParticle!) self.addChild(beatParticleEffectNode) 

所有的外观都在.sks文件中完成。

这里是我在一个连续循环中称之为“updateBeatParticle”函数的地方,这样它就可以把我的代码放在音乐上,使得粒子的尺度(意思是尺寸)越来越小。

 var dpLink : CADisplayLink? dpLink = CADisplayLink(target: self, selector: "updateBeatParticle") dpLink?.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSRunLoopCommonModes) func updateBeatParticle(){ //Put code here } 

任何想法我可以做到这一点? 我看了一些这样的教程: https : //www.raywenderlich.com/36475/how-to-make-a-music-visualizer-in-ios

但是,我不能很好的理解它,因为他们使用的是一个emitterLayer,它在Obj-C中,并且对于其他的精彩人物也有兴趣。

警告:以下代码尚未经过testing。 请让我知道,如果它的工作。

首先,看起来你正在使用SpriteKit,因此你可以把需要的代码改变为SKScene方法update: SKScene它自动被调用的CADisplayLink

基本上所有你需要做的是根据AVAudioPlayer的通道音量update:方法中的发射器刻度。 请注意,audio播放器可能有多个通道运行,所以您需要平均每个通道的平均功率。

首先…

 player.meteringEnabled = true 

在初始化audio播放器后进行设置,以便监听通道的电平。

接下来,在你的更新方法中添加这样的东西。

 override func update(currentTime: CFTimeInterval) { var scale: CGFloat = 0.5 if audioPlayer.playing { // Only do this if the audio is actually playing audioPlayer.updateMeters() // Tell the audio player to update and fetch the latest readings let channels = audioPlayer.numberOfChannels var power: Float = 0 // Loop over each channel and add its average power for i in 0..<channels { power += audioPlayer.averagePowerForChannel(i) } power /= Float(channels) // This will give the average power across all the channels in decibels // Convert power in decibels to a more appropriate percentage representation scale = CGFloat(getIntensityFromPower(power)) } // Set the particle scale to match emitterNode.particleScale = scale } 

getIntensityFromPower方法用于将分贝的功率转换为更合适的百分比表示。 这个方法可以像这样声明…

 // Will return a value between 0.0 ... 1.0, based on the decibels func getIntensityFromPower(decibels: Float) -> Float { // The minimum possible decibel returned from an AVAudioPlayer channel let minDecibels: Float = -160 // The maximum possible decibel returned from an AVAudioPlayer channel let maxDecibels: Float = 0 // Clamp the decibels value if decibels < minDecibels { return 0 } if decibels >= maxDecibels { return 1 } // This value can be adjusted to affect the curve of the intensity let root: Float = 2 let minAmp = powf(10, 0.05 * minDecibels) let inverseAmpRange: Float = 1.0 / (1.0 - minAmp) let amp: Float = powf(10, 0.05 * decibels) let adjAmp = (amp - minAmp) * inverseAmpRange return powf(adjAmp, 1.0 / root) } 

此转换的algorithm取自此StackOverflow响应https://stackoverflow.com/a/16192481/3222419