2016-03-26 17 views
0

名前をつけて教えてください!音楽ビジュアル用のAVAudioPlayerを使用したSKEmiterNode

私の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を使用していると、他のアイデアにも素晴らしい人に興味があるがある可能性があり!

答えて

0

警告:次のコードはテストされていません。それが動作すれば教えてください。

あなたがSpriteKitベースを使用しているように、まず、それゆえ、あなたが自動的にCADisplayLinkとして、事実上のように頻繁に呼び出されるSKScene方法update:にエミッタのスケールを変更するために必要なコードを置くことができ、見えます。

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方法。このメソッドは、この変換のためのアルゴリズムは、このStackOverflowの応答https://stackoverflow.com/a/16192481/3222419から取られたので...

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

ように宣言することができます。

関連する問題