Как реализовать прослушиватель или while(true), чтобы остановить прокрутку графика сигнала после завершения записи в Swift с использованием AudioKit

У меня есть система, которая использует различные классы из AudioKit для записи входного сигнала с микрофона и сохранения его в файл, с максимальной продолжительностью 30 с, и одновременно во время записи выходной сигнал отображается на графике сигнала с использованием EZAudioPlot.

Моя проблема в том, что я использую кнопку записи в стиле Snapchat, которая начинает запись / черчение для события касания и прекращает запись / черчение для события касания (внутри и снаружи) - это означает, что когда пользователь продолжает удерживать кнопку записи дольше, чем максимальная длительность (как это иногда бывает), форма сигнала на выходе микрофона продолжает отображаться, несмотря на завершение записи. Я спрашиваю, есть ли способ в Swift/AudioKit постоянно "слушать" рекордер, чтобы остановить запись, сродни чему-то вроде

while true
{
    if recorder.isRecording() == false
    {
        plot.pause()
    }
}  

после нажатия кнопки, но до ее отпускания? Если бы существовал какой-то способ прослушивать бесконечно, чтобы рекордер закончил запись между нажатой кнопкой и отпущенной кнопкой, это очень легко решило бы мою проблему. Существует ли такая функциональность в той или иной форме в Swift или AudioKit?

Мой код выглядит следующим образом (нерелевантный код опущен):

import UIKit
import AudioKit
import AudioKitUI

// Define maximum recording time in seconds

let maxRecordingTime = 30.0

class ViewController: UIViewController
{
    var microphone : AKMicrophone!
    var mixer : AKMixer!
    var waveformBooster: AKBooster!
    var outputBooster : AKBooster!
    var exportTape : AKAudioFile!
    var recorder : AKNodeRecorder!
    var player : AKClipPlayer!
    var circleView : CircleView!
    var plot : AKNodeOutputPlot!

    @IBOutlet var startRecordingButton: CircularButton!
    @IBOutlet var playRecordingButton: UIButton!
    @IBOutlet var waveformPlot: EZAudioPlot!

    override func viewDidLoad()
    {
        super.viewDidLoad()

        microphone = AKMicrophone()
        mixer = AKMixer(microphone)

        // Initialise booster to set monitoring level to zero - this ensures that
        // microphone output is recorded but not sent to main audio output

        outputBooster = AKBooster(mixer)
        outputBooster.gain = 0

        // Initialise booster to set waveform display gain so that waveform can be set to display
        // only when the app is recording

        waveformBooster = AKBooster(microphone)
        waveformBooster.gain = 0

        AudioKit.output = outputBooster
        try!AudioKit.start()

        // Initialise file to store recorder output and set recorder to route mixer
        // output to file

        exportTape = try! AKAudioFile(name: "ExportTape")
        recorder = try! AKNodeRecorder(node: mixer, file: exportTape)

        recorder.durationToRecord = maxRecordingTime

        plot = AKNodeOutputPlot(waveformBooster, frame: waveformPlot.bounds)
        setupWaveformPlot()
    }

    @IBAction func startRecording(_ sender: UIButton)
    {
        // Delete contents of output file so it can be rewritten

        try! recorder.reset()

        // Perform various tasks related to getting the plot ready
        // to be rewritten to in the event of several recordings being made

        updateWaveformPlot()

        // Start the microphone and

        microphone.start()
        waveformBooster.gain = 1

        animateRecordingButton()

        do
        {
            try recorder?.record()
        } catch
        {
            AKLog("Couldn't record")
        }
    }

    @IBAction func stopRecording(_ sender: UIButton)
    {
        microphone.stop()
        waveformBooster.gain = 0
        recorder.stop()

        plot.pause()
    }

    @IBAction func playRecording(_ sender: UIButton)
    {
        let player = try! AKAudioPlayer(file: exportTape)

        if player.isStarted == false
        {
            AudioKit.output = player
            player.play()
        }
    }

    func setupWaveformPlot()
    {
        plot.plotType = .rolling
        plot.clipsToBounds = true
        plot.shouldFill = true
        plot.shouldMirror = true
        plot.color = UIColor.white
        plot.backgroundColor = UIColor.black

        // Set the gain of the plot to control range of values displayed on the waveform plot

        plot.gain = 25
        waveformPlot.addSubview(plot)
    }

    func updateWaveformPlot()
    {
        plot.clear()
        plot.resume()

        // Set rolling history length to correct value for 30s
        // such that waveform fills whole plot with no scrolling

        plot.setRollingHistoryLength(Int32(Float(1284)))
    }
}

1 ответ

Решение

Я закончил тем, что реализовал поведение, которое я преследовал с помощью Таймера, что-то вроде:

var recordingTimer = Timer!
let maxRecordingTime = 30.0    

if recordingTimer == nil
                {
                    recordingTimer = Timer.scheduledTimer(withTimeInterval: maxRecordingTime, repeats: false)
                    {
                        timer in
                        self.plot.pause()
                    }
Другие вопросы по тегам