【问题标题】:SKEmiterNode with AVAudioPlayer for music visuals带有 AVAudioPlayer 的 SKEmiterNode 用于音乐视觉效果
【发布时间】:2016-03-26 11:54:53
【问题描述】:

请人帮忙!

我想让我的 SKEmiterNode 的比例(意思是大小)随着我使用 AVAudioPlayer 内置到应用程序中的音乐变得越来越小。现在,这几乎是我为 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

但是,我无法完全理解它,因为他们在 Obj-C 中使用了一个emitterLayer 和它,而且我还对你们这些优秀的人可能有的任何其他想法感兴趣!

【问题讨论】:

    标签: ios swift animation avaudioplayer skemitternode


    【解决方案1】:

    警告:以下代码未经测试。请让我知道它是否有效。

    首先,您似乎正在使用 SpriteKit,因此您可以将更改发射器比例所需的代码放入 SKScene 方法 update: 中,该方法几乎与 CADisplayLink 一样频繁地自动调用。

    基本上您需要做的就是根据AVAudioPlayer 的通道音量在update: 方法中更新发射器比例。请注意,音频播放器可能有多个通道在运行,因此您需要平均每个通道的平均功率。

    首先...

    player.meteringEnabled = true 
    

    在你初始化你的音频播放器后设置它,这样它就会监控通道的电平。

    接下来,在更新方法中添加类似的内容。

    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)
    }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-12
      • 2023-03-03
      • 2010-12-12
      • 2011-11-29
      相关资源
      最近更新 更多