Изменение звукового тона "эхолота" - PullRequest
0 голосов
/ 03 июня 2018

Edit: добавлен новый код внизу.

Я довольно новичок в кодировании, поэтому я начал с создания приложения для деки.Мне удалось использовать команду «rate» для замедления или ускорения звука, но теперь я тоже хочу изменить высоту звука.В идеале я хотел бы иметь два переключателя.Тот, который ускоряет звук и увеличивает высоту тона, тот, который замедляет и понижает, и если они оба выключены, он играет нормально.Ниже мой код, который работает для всего, кроме изменения высоты тона.Любой вклад с благодарностью.Для справки, sass медленный, чип быстрый.

import UIKit
import AVFoundation

var Sounder1 = AVAudioPlayer()
var Sounder2 = AVAudioPlayer()

let sassFloat: Float = 0.5
let myInt = Int(sassFloat)

let chipFloat: Float = 3.0
let myInt2 = Int(chipFloat)

class ViewController: UIViewController {

@IBOutlet weak var sassSwitch: UISwitch!

@IBOutlet weak var chipSwitch: UISwitch!

override func viewDidLoad() {
    super.viewDidLoad()

    do {
        Sounder1 = try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: "Sound1", ofType: "mp3")!))
        Sounder1.prepareToPlay()
        Sounder1.enableRate = true
    }catch{

    }

    do {
        Sounder2 = try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: "Sound2", ofType: "wav")!))
        Sounder2.prepareToPlay()
        Sounder2.enableRate = true
    }catch{

    }
    // Do any additional setup after loading the view, typically from a nib.
}

@IBAction func sassAction(_ sender: UISwitch) {
    chipSwitch.setOn(false, animated: true)
}

@IBAction func chipAction(_ sender: UISwitch) {
    sassSwitch.setOn(false, animated: true)
}

@IBAction func play(_ sender: Any) {
    if sassSwitch.isOn {
        Sounder1.rate = sassFloat
        Sounder1.play()
    } else if chipSwitch.isOn {
        Sounder1.rate = chipFloat
        Sounder1.play()
    } else {
        Sounder1.rate = 1.0
        Sounder1.play()
    }

}

@IBAction func play2(_ sender: Any) {
    if sassSwitch.isOn {
        Sounder2.rate = sassFloat
        Sounder2.play()
    } else if chipSwitch.isOn {
        Sounder2.rate = chipFloat
        Sounder2.play()
    } else {
        Sounder2.rate = 1.0
        Sounder2.play()
    }
}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


}

Это новый код, который я придумал на основе предложений @ericl.Мне все еще нужно reset() audioEngine, но у меня также было несколько вопросов.1) Будет ли оператор if else if else действительно работать в этой ситуации?2) Где я могу добавить оператор reset().3) Нужно ли отсоединять узел после каждого звука?Или просто сбросить?

class ViewController: UIViewController {

@IBOutlet weak var sassSwitch: UISwitch!
@IBOutlet weak var chipSwitch: UISwitch!

@IBAction func sassAction(_ sender: UISwitch) {
    chipSwitch.setOn(false, animated: true)
}
@IBAction func chipSwitch(_ sender: UISwitch) {
    sassSwitch.setOn(false, animated: true)
}


///Playback Engine
private let audioEngine = AVAudioEngine()

///Player's Nodes
private let pitchPlayer = AVAudioPlayerNode()
private let timePitch = AVAudioUnitTimePitch()

///Audio Files to be played
private var audioFile1 = AVAudioFile()
private var audioFile2 = AVAudioFile()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    if let filePath = Bundle.main.path(forResource: "PeteNope", ofType:
        "mp3") {
        let filePathURL = URL(fileURLWithPath: filePath)

        setPlayerFile(filePathURL)

    }

    if let filePath2 = Bundle.main.path(forResource: "Law_WOW", ofType:
        "mp3") {
        let filePath2URL = URL(fileURLWithPath: filePath2)

        setPlayerFile2(filePath2URL)

    }
}

private func setPlayerFile(_ fileURL: URL) {
    do {
        let file = try AVAudioFile(forReading: fileURL)

        self.audioFile1 = file


    } catch {
        fatalError("Could not create AVAudioFile instance. error: \(error).")
    }
}

private func setPlayerFile2(_ fileURL: URL) {
    do {
        let file = try AVAudioFile(forReading: fileURL)

        self.audioFile2 = file


    } catch {
        fatalError("Could not create AVAudioFile instance. error: \(error).")
    }
}


@IBAction func sound1Play(_ sender: UIButton) {
    if sassSwitch.isOn {
        timePitch.pitch = -300
        timePitch.rate = 0.5
        audioEngine.attach(pitchPlayer)
        audioEngine.attach(timePitch)

        audioEngine.connect(pitchPlayer, to: timePitch, format: audioFile1.processingFormat)
        audioEngine.connect(timePitch, to: audioEngine.outputNode, format: audioFile1.processingFormat)
        pitchPlayer.scheduleFile(audioFile1, at: nil, completionHandler: nil)

        // Start the engine.
        do {
            try audioEngine.start()
        } catch {
            fatalError("Could not start engine. error: \(error).")
        }

        pitchPlayer.play()

    } else if chipSwitch.isOn {
        timePitch.pitch = +500
        timePitch.rate = 2.0
        audioEngine.attach(pitchPlayer)
        audioEngine.attach(timePitch)

        audioEngine.connect(pitchPlayer, to: timePitch, format: audioFile1.processingFormat)
        audioEngine.connect(timePitch, to: audioEngine.outputNode, format: audioFile1.processingFormat)
        pitchPlayer.scheduleFile(audioFile1, at: nil, completionHandler: nil)

        // Start the engine.
        do {
            try audioEngine.start()
        } catch {
            fatalError("Could not start engine. error: \(error).")
        }

        pitchPlayer.play()

    } else {
        timePitch.pitch = +0
        timePitch.rate = 1.0
        audioEngine.attach(pitchPlayer)
        audioEngine.attach(timePitch)

        audioEngine.connect(pitchPlayer, to: timePitch, format: audioFile1.processingFormat)
        audioEngine.connect(timePitch, to: audioEngine.outputNode, format: audioFile1.processingFormat)
        pitchPlayer.scheduleFile(audioFile1, at: nil, completionHandler: nil)

        // Start the engine.
        do {
            try audioEngine.start()
        } catch {
            fatalError("Could not start engine. error: \(error).")
        }
        pitchPlayer.play()
    }

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


}

1 Ответ

0 голосов
/ 03 июня 2018

Вы будете использовать AVAudioEngine, чтобы прикрепить AVAudioPlayerNode к эффекту AVAudioUnitTimePitch.Я проверил образец кода Apple *1004* AudioUnitV3Example и собрал рабочий пример из него.Вы захотите реализовать больше состояний и обработки ошибок, которые вы можете найти там.В любом случае, вот что:

Определите некоторые личные переменные в верхней части вашего класса:

   /// Playback engine.
    private let audioEngine = AVAudioEngine()

    /// Engine's player node.
    private let pitchPlayer = AVAudioPlayerNode()
    private let timePitch = AVAudioUnitTimePitch()

    /// File to play.
    private var audioFile: AVAudioFile?

Проверьте правильность аудиофайла:

     override func viewDidLoad() {
         super.viewDidLoad()

     if let filePath = Bundle.main.path(forResource: "Sound1", ofType: 
 "mp3") {
         let filePathURL = URL(fileURLWithPath: filePath)

         setPlayerFile(filePathURL)

         }
     }

     private func setPlayerFile(_ fileURL: URL) {
         do {
             let file = try AVAudioFile(forReading: fileURL)

             self.audioFile = file


         } catch {
             fatalError("Could not create AVAudioFile instance. error: \(error).")
         }
     }

     @IBAction func verySlowPlayback(sender: UIButton) {


    timePitch.pitch = -300
    timePitch.rate = 0.5
    audioEngine.attach(pitchPlayer)
    audioEngine.attach(timePitch)

    audioEngine.connect(pitchPlayer, to: timePitch, format: audioFile?.processingFormat)
    audioEngine.connect(timePitch, to: audioEngine.outputNode, format: audioFile?.processingFormat)
    pitchPlayer.scheduleFile(audioFile!, at: nil, completionHandler: nil)

    // Start the engine.
    do {
        try audioEngine.start()
    } catch {
        fatalError("Could not start engine. error: \(error).")
    }

    pitchPlayer.play()

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...