2016-10-06 3 views
2

Так, I asked this question before on the Apple Developer Forums но не получили правильный ответ, поэтому я думал, что спросить его здесь:Xcode 8 Swift 3 Pitch изменяющих звуки

Итак, я пытаюсь сделать простую игру с хитовым звуком который имеет различную высоту, когда вы что-то нажимаете. Я думал, что это будет просто, но в конечном итоге с завалил (большинство из которых я полностью скопированный с кем-то еще):

func hitSound(value: Float) { 

    let audioPlayerNode = AVAudioPlayerNode() 

    audioPlayerNode.stop() 
    engine.stop() // This is an AVAudioEngine defined previously 
    engine.reset() 

    engine.attach(audioPlayerNode) 

    let changeAudioUnitTime = AVAudioUnitTimePitch() 
    changeAudioUnitTime.pitch = value 

    engine.attach(changeAudioUnitTime) 
    engine.connect(audioPlayerNode, to: changeAudioUnitTime, format: nil) 
    engine.connect(changeAudioUnitTime, to: engine.outputNode, format: nil) 
    audioPlayerNode.scheduleFile(file, at: nil, completionHandler: nil) // File is an AVAudioFile defined previously 
    try? engine.start() 

    audioPlayerNode.play() 
} 

мой вопрос, так как этот код кажется, чтобы остановить воспроизведение любых звуков в настоящее время играется, чтобы воспроизвести новый звук, есть ли способ изменить это поведение, чтобы он не прекратил ничего играть? Я попытался удалить бит engine.stop и engine.reset, но это просто сбой приложения. Кроме того, этот код невероятно медленный, когда его часто называют. Я могу что-то сделать, чтобы ускорить его? Это обращение необходимо очень часто.

+0

Извините, кто читает это если я похожу на хуй, который ничего не знает о коде и просто требует, чтобы другие делали что-то в этом роде, я очень к этому не знаком, и я даже не коснулся каких-либо аудиофункций, но я просто пытаюсь понять, что какие. Swift кажется довольно похожим на Lua до сих пор, и я сделал некоторые другие рабочие вещи, я просто застрял в этой аудио-проблеме. – MysteryPancake

ответ

0

Вы каждый раз перезагружаете двигатель каждый раз, когда играете звук! И вы создаете дополнительные узлы игрока - это на самом деле гораздо проще, чем, если вы хотите только один экземпляр поля сдвинуты звук играть сразу:

// instance variables 
let engine = AVAudioEngine() 
let audioPlayerNode = AVAudioPlayerNode() 
let changeAudioUnitTime = AVAudioUnitTimePitch() 

вызов setupAudioEngine() раз:

func setupAudioEngine() { 
    engine.attach(self.audioPlayerNode) 

    engine.attach(changeAudioUnitTime) 
    engine.connect(audioPlayerNode, to: changeAudioUnitTime, format: nil) 
    engine.connect(changeAudioUnitTime, to: engine.outputNode, format: nil) 
    try? engine.start() 
    audioPlayerNode.play() 
} 

и вызов hitSound() столько раз, сколько пожелаете:

func hitSound(value: Float) { 
    changeAudioUnitTime.pitch = value 

    audioPlayerNode.scheduleFile(file, at: nil, completionHandler: nil) // File is an AVAudioFile defined previously 
} 

ps шаг может быть сдвинут на две октавы вверх или вниз, для диапазона 4 октавы, и находится в числовом диапазоне [-2400, 2400], имея единицу «цента».

p.p.s AVAudioUnitTimePitch очень крутая технология. Когда я был ребенком, у нас точно не было ничего подобного.

UPDATE

Если вы хотите мульти канал, вы можете легко настроить несколько игроков и тангажа узлов, однако вы должны выбрать количество каналов, прежде чем запустить двигатель. Вот как вы могли бы сделать два (это легко расширить до п экземпляров, и вы, вероятно, хотите, чтобы выбрать свой собственный метод выбора, какой канал прерывания, когда все играют):

// instance variables 
let engine = AVAudioEngine() 
var nextPlayerIndex = 0 
let audioPlayers = [AVAudioPlayerNode(), AVAudioPlayerNode()] 
let pitchUnits = [AVAudioUnitTimePitch(), AVAudioUnitTimePitch()] 

func setupAudioEngine() { 
    var i = 0 
    for playerNode in audioPlayers { 
     let pitchUnit = pitchUnits[i] 

     engine.attach(playerNode) 
     engine.attach(pitchUnit) 
     engine.connect(playerNode, to: pitchUnit, format: nil) 
     engine.connect(pitchUnit, to:engine.mainMixerNode, format: nil) 

     i += 1 
    } 

    try? engine.start() 

    for playerNode in audioPlayers { 
     playerNode.play() 
    } 
} 

func hitSound(value: Float) { 
    let playerNode = audioPlayers[nextPlayerIndex] 
    let pitchUnit = pitchUnits[nextPlayerIndex] 

    pitchUnit.pitch = value 

    // interrupt playing sound if you have to 
    if playerNode.isPlaying { 
     playerNode.stop() 
     playerNode.play() 
    } 

    playerNode.scheduleFile(file, at: nil, completionHandler: nil) // File is an AVAudioFile defined previously 

    nextPlayerIndex = (nextPlayerIndex + 1) % audioPlayers.count 
} 
+0

Спасибо, что ответили, что имеет смысл! Я попробую это, я был очень смущен, почему он так лаконичен, что многие игры способны делать гораздо более сложные вещи. – MysteryPancake

+0

Хорошо, я попробовал вашу версию, и это, безусловно, работает намного быстрее, но я ищу способ воспроизвести более одного экземпляра звука сразу на другом шаге, если это возможно. Извините, что раздражает вас снова, но в настоящее время звуки играют в разное время, так как они все играют после eachother. – MysteryPancake

+0

. А, вот, см. Обновленный ответ. –

Смежные вопросы