尝试结合 2 个 Audiokit 示例:麦克风分析和录音机:当我点击录音时崩溃

2024-05-02

我正在尝试将麦克风分析和录音机示例结合起来。它总是在线路上崩溃try recorder.record.

2018-01-08 21:21:48.507019-0800 音乐练习[90266:18761122] [avae] AVAEInternal.h:70:_AVAE_Check: 所需条件为 false: [AVAEGraphNode.mm:804:CreateRecordingTap: (nullptr == Tap())] 2018-01-08 21:21:48.527443-0800 音乐练习[90266:18761122]* 由于未捕获的异常“com.apple.coreaudio.avfaudio”而终止应用程序,原因:“所需条件为假:nullptr == Tap()” *首先抛出调用堆栈:

// -----------

import AudioKit

import AudioKitUI

import UIKit

class SecondViewController: UIViewController {

    @IBOutlet private var inputPlot: AKNodeOutputPlot!
    @IBOutlet weak var tempViewForRecordingAndPlay: UIView!
    @IBOutlet weak var outputWavePlot: AKOutputWaveformPlot!

    // for microphone Analysis
    @IBOutlet weak var frequencyLabel: UILabel!
    @IBOutlet weak var amplitudeLabel: UILabel!
    @IBOutlet weak var noteNameWithSharpsLabel: UILabel!
    @IBOutlet weak var noteNameWithFlatsLabel: UILabel!
    @IBOutlet private var audioInputPlot: EZAudioPlot!


    var micMixer: AKMixer!
    var recorder: AKNodeRecorder!
    var player: AKAudioPlayer!
    var tape: AKAudioFile!
    var micBooster: AKBooster!
    var moogLadder: AKMoogLadder!
    var delay: AKDelay!
    var mainMixer: AKMixer!

    let mic = AKMicrophone()

    var state = State.readyToRecord


    @IBOutlet private weak var infoLabel: UILabel!
    @IBOutlet private weak var resetButton: UIButton!
    @IBOutlet private weak var RecordOrPlay_Btn: UIButton!
    @IBOutlet private weak var frequencySlider: AKSlider!
    @IBOutlet private weak var resonanceSlider: AKSlider!
    @IBOutlet private weak var loopButton: UIButton!
    @IBOutlet private weak var moogLadderTitle: UILabel!

    enum State {
        case readyToRecord
        case recording
        case readyToPlay
        case playing

    }
    var plot:  AKNodeOutputPlot!
    var micNew: AKMicrophone!
    var tracker: AKFrequencyTracker!
    var silence: AKBooster!

    let noteFrequencies = [16.35, 17.32, 18.35, 19.45, 20.6, 21.83, 23.12, 24.5, 25.96, 27.5, 29.14, 30.87]
    let noteNamesWithSharps = ["C", "C♯", "D", "D♯", "E", "F", "F♯", "G", "G♯", "A", "A♯", "B"]
    let noteNamesWithFlats = ["C", "D♭", "D", "E♭", "E", "F", "G♭", "G", "A♭", "A", "B♭", "B"]


    @objc func updateUI() {
        if tracker.amplitude > 0.1 {
            frequencyLabel.text = String(format: "%0.1f", tracker.frequency)

            var frequency = Float(tracker.frequency)
            while frequency > Float(noteFrequencies[noteFrequencies.count - 1]) {
                frequency /= 2.0
            }
            while frequency < Float(noteFrequencies[0]) {
                frequency *= 2.0
            }

            var minDistance: Float = 10_000.0
            var index = 0

            for i in 0..<noteFrequencies.count {
                let distance = fabsf(Float(noteFrequencies[i]) - frequency)
                if distance < minDistance {
                    index = i
                    minDistance = distance
                }
            }
            let octave = Int(log2f(Float(tracker.frequency) / frequency))
            noteNameWithSharpsLabel.text = "\(noteNamesWithSharps[index])\(octave)"
            noteNameWithFlatsLabel.text = "\(noteNamesWithFlats[index])\(octave)"
        }
        amplitudeLabel.text = String(format: "%0.2f", tracker.amplitude)
    }

    #if NOT_USED
    func setupPlot() {
        plot = AKNodeOutputPlot(micNew, frame: audioInputPlot.bounds)
        plot.plotType = .rolling
        plot.shouldFill = true
        plot.shouldMirror = true
        plot.color = UIColor.blue
        audioInputPlot.addSubview(plot)
    }
    #endif

    func setupPlot_forMic() {
        plot = AKNodeOutputPlot(micMixer, frame: audioInputPlot.bounds)
        plot.plotType = .rolling
        plot.shouldFill = true
        plot.shouldMirror = true
        plot.color = UIColor.red
        audioInputPlot.addSubview(plot)
    }


    func execute_viewDidAppear_micAnalysis() {
        //AudioKit.output = silence
        //AudioKit.start()
        setupPlot_forMic()
        Timer.scheduledTimer(timeInterval: 0.1,
                             target: self,
                             selector: #selector(SecondViewController.updateUI),
                             userInfo: nil,
                             repeats: true)
    }


    //view DID APPEAR
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        execute_viewDidAppear_micAnalysis()
    }

    // View DID DOWNLOAD
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.tempViewForRecordingAndPlay.addSubview(inputPlot);
        self.tempViewForRecordingAndPlay.addSubview(outputWavePlot);
        //parentView.bringSubview(toFront: childView)
        tempViewForRecordingAndPlay.bringSubview(toFront: inputPlot);
        tempViewForRecordingAndPlay.bringSubview(toFront: outputWavePlot);

        recorderPlayerSettings()

    #if TEMP

    #else
       micAnalysisSettings()
    #endif

    }


    func recorderPlayerSettings() {

        setupButtonNames()

        // Clean tempFiles!
        AKAudioFile.cleanTempDirectory()

        // Session settings
        AKSettings.bufferLength = .medium

        do {
            try AKSettings.setSession(category: .playAndRecord, with: .allowBluetoothA2DP)
        } catch {
            AKLog("Could not set session category.")
        }

        AKSettings.defaultToSpeaker = true

        // Patching
        inputPlot.node = mic
        micMixer = AKMixer(mic)
        micBooster = AKBooster(micMixer)

        //play(from: innerTime, to: endTime, when: 0)
       // passing 0 for endTime will use the duration.

        // Will set the level of microphone monitoring
        micBooster.gain = 0
        recorder = try? AKNodeRecorder(node: micMixer)
        if let file = recorder.audioFile {
            player = try? AKAudioPlayer(file: file)
        }
        player.looping = true
        player.completionHandler = playingEnded

        moogLadder = AKMoogLadder(player)

        mainMixer = AKMixer(moogLadder, micBooster)

        AudioKit.output = mainMixer
        AudioKit.start()
        setupUIForRecording()

    }

    func micAnalysisSettings() {
        AKSettings.audioInputEnabled = true
        //micNew = AKMicrophone()
        tracker = AKFrequencyTracker(micMixer)
        //tracker = AKFrequencyTracker(mic)
        silence = AKBooster(tracker, gain: 0)
    }

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

    // CallBack triggered when playing has ended
    // Must be seipatched on the main queue as completionHandler
    // will be triggered by a background thread
    func playingEnded() {
        DispatchQueue.main.async {
            self.setupUIForPlaying ()
        }
    }

    @IBAction func RecordOrPlay_BtnTouched(_ sender: UIButton) {

        switch state {
        case .readyToRecord :
            infoLabel.text = "Recording"
            RecordOrPlay_Btn.setTitle("Stop", for: .normal)
            state = .recording
            // microphone will be monitored while recording
            // only if headphones are plugged
            if AKSettings.headPhonesPlugged {
                micBooster.gain = 1
            }
            do {
                try recorder.record()
            } catch { print("Errored recording.") }

        case .recording :
            // Microphone monitoring is muted
            micBooster.gain = 0
            do {
                try player.reloadFile()
            } catch { print("Errored reloading.") }

            let recordedDuration = player != nil ? player.audioFile.duration  : 0
            if recordedDuration > 0.0 {
                recorder.stop()
                player.audioFile.exportAsynchronously(name: "TempTestFile.m4a",
                                                      baseDir: .documents,
                                                      exportFormat: .m4a) {_, exportError in
                                                        if let error = exportError {
                                                            print("Export Failed \(error)")
                                                        } else {
                                                            print("Export succeeded")
                                                        }
                }
                setupUIForPlaying ()
            }
        case .readyToPlay :
            player.play()
            infoLabel.text = "Playing..."
            RecordOrPlay_Btn.setTitle("Stop", for: .normal)
            state = .playing
        case .playing :
            player.stop()
            setupUIForPlaying()
        }
    }

    struct Constants {
        static let empty = ""
    }

    func setupButtonNames() {
        resetButton.setTitle(Constants.empty, for: UIControlState.disabled)
        RecordOrPlay_Btn.setTitle(Constants.empty, for: UIControlState.disabled)
        loopButton.setTitle(Constants.empty, for: UIControlState.disabled)
    }

    func setupUIForRecording () {
        state = .readyToRecord
        infoLabel.text = "Ready to record"
        RecordOrPlay_Btn.setTitle("Record", for: .normal)
        resetButton.isEnabled = false
        resetButton.isHidden = true
        micBooster.gain = 0
        setSliders(active: false)
    }

    func setupUIForPlaying () {
        let recordedDuration = player != nil ? player.audioFile.duration  : 0
        infoLabel.text = "Recorded: \(String(format: "%0.1f", recordedDuration)) seconds"
        RecordOrPlay_Btn.setTitle("Play", for: .normal)
        state = .readyToPlay
        resetButton.isHidden = false
        resetButton.isEnabled = true
        setSliders(active: true)
        frequencySlider.value = moogLadder.cutoffFrequency
        resonanceSlider.value = moogLadder.resonance
    }

    func setSliders(active: Bool) {
        loopButton.isEnabled = active
        moogLadderTitle.isEnabled = active
        frequencySlider.callback = updateFrequency
        frequencySlider.isHidden = !active
        resonanceSlider.callback = updateResonance
        resonanceSlider.isHidden = !active
        frequencySlider.range = 10 ... 2_000
        moogLadderTitle.text = active ? "Moog Ladder Filter" : Constants.empty
    }

    @IBAction func loopButtonTouched(_ sender: UIButton) {

        if player.looping {
            player.looping = false
            sender.setTitle("Loop is Off", for: .normal)
        } else {
            player.looping = true
            sender.setTitle("Loop is On", for: .normal)

        }

    }


    func updateFrequency(value: Double) {
        moogLadder.cutoffFrequency = value
        frequencySlider.property = "Frequency"
        frequencySlider.format = "%0.0f"
    }

    func updateResonance(value: Double) {
        moogLadder.resonance = value
        resonanceSlider.property = "Resonance"
        resonanceSlider.format = "%0.3f"
    }

    @IBAction func resetEverything(_ sender: Any) {
        player.stop()
        do {
            try recorder.reset()
        } catch { print("Errored resetting.") }

        //try? player.replaceFile((recorder.audioFile)!)
        setupUIForRecording()
    }



    // convert to a generic view animate function and dissociate from the button
    @IBAction func animateButton(_ sender: UIButton) {

        UIView.animate(withDuration: 0.5, delay: 0.0, options: UIViewAnimationOptions.curveEaseIn, animations: {
            //Frame Option 1:
            self.tempViewForRecordingAndPlay.frame = CGRect(x: self.tempViewForRecordingAndPlay.frame.origin.x, y: 20, width: self.tempViewForRecordingAndPlay.frame.width, height: self.tempViewForRecordingAndPlay.frame.height)

            //Frame Option 2:
            self.tempViewForRecordingAndPlay.center = CGPoint(x: self.view.frame.width / 2, y: self.view.frame.height / 4)
            //self.tempViewForRecordingAndPlay.backgroundColor = .blue

        },completion: { finish in
           /*
            UIView.animate(withDuration: 1, delay: 0.25,options: UIViewAnimationOptions.curveEaseOut,animations: {
                self.tempViewForRecordingAndPlay.backgroundColor = .orange
                self.tempViewForRecordingAndPlay.transform = CGAffineTransform(scaleX: 0.25, y: 0.25)

                //self.animationButton.isEnabled = false // If you want to restrict the button not to repeat animation..You can enable by setting into true

            },completion: nil)})
           */

            UIView.animate(withDuration: 1.0, delay: 0.25, usingSpringWithDamping:
            0.6, initialSpringVelocity: 0.3, options:
                UIViewAnimationOptions.allowAnimatedContent, animations: { () -> Void in
                //do actual move
                self.tempViewForRecordingAndPlay.center = self.tempViewForRecordingAndPlay.center
        }, completion:  nil)})

    }

您可能已经在公交车上使用了一个水龙头,并且您不能在同一辆公交车上再使用另一个水龙头。

Try to micMixer.outputNode.removeTap(onBus: 0)在你打电话之前recorder.record().

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

尝试结合 2 个 Audiokit 示例:麦克风分析和录音机:当我点击录音时崩溃 的相关文章

  • iOS7及以上版本中如何在接收器和扬声器之间切换音频输出?

    我有一个音频播放器 可以选择在接近传感器通知 1 时将音频输出从扬声器切换到接收器 耳机 无论是否连接耳机 以下是我执行此操作的代码 void switchAudioOutput NSString output AVAudioSession
  • 应用程序在第二次运行 nsnull 计数的循环时崩溃

    我有一个循环 第一次运行正常 但第二次循环时我得到 NSNull count unrecognized selector sent to instance 0x3a094a70 Terminating app due to uncaught
  • UITextField 字体大小在开始或停止输入字符时发生变化

    我见过很多线程 但没有找到解决这个问题的任何具体解决方案 我使用 XIB 创建了 UITextfield 尚未以编程方式对该字段执行任何操作 一旦我开始打字 文本字段的字体就会改变 一旦我将焦点移出文本字段 并且随着键盘消失 字体大小就会减
  • 使用prefersLargeTitles 和 UITableView 平滑滚动

    我在使用时遇到了滚动问题prefersLargeTitles并添加了UITableView 如果我设置prefersLargeTitles在导航控制器中 其根是UITableViewController一切都很好 导航大标题的滚动方式与我们
  • iOS UITableViewCell 配件在左侧?

    对于我的应用程序 我想要一些可以同时具有复选标记和详细信息披露按钮的单元格 也就是说 我希望它们看起来与 iOS 设置中的 Wi Fi 网络选择一模一样 左侧的复选标记 中间的内容 右侧的详细信息披露按钮 有没有正确的方法来做到这一点 或者
  • 找不到导航对象。您的组件是否位于导航器屏幕内?

    在我下面的代码中 当我使用 useNavigation 时 它会给出像我的问题一样的错误 如何使用useNavigation 请任何人都可以解决此错误 错误 找不到导航对象 您的组件是否位于导航器屏幕内 我从这里跟踪了代码https rnf
  • 编写支持 iOS 3.1.3 和 iOS 4.x 的 iOS 应用程序时的陷阱

    我想编写一个可以在 iOS 3 1 3 到 iOS 4 1 上运行的应用程序 我知道如何设置部署目标和基础 SDK 阅读 Apple 文档后 它很大程度上依赖于检查类是否可用和 或实例是否响应特定选择器 现在我的问题是 如果 Apple 从
  • cordova-plugin-whitelist 适用于 Android,但不适用于 iOS (Phonegap Build)

    我正在开发一个用 Cordova 封装并使用 Phonegap Build 构建的 JavaScript 应用程序 我们包括cordova plugin whitelist来自我们构建中的 npm 并添加了
  • 应用程序图标未刷新

    我更改了新版本应用程序中的图标图像 并且我在设备中安装了旧版本应用程序 然后我安装了新版本 它在 iOS 5 中运行良好 但在 iOS 6 中 图标没有刷新 它仍然显示旧版本图标 徽标 如果没有安装旧版本应用程序 该设备在 iOS 5 和
  • iOS Swift 检测键盘事件

    我能以某种方式检测来自 iOS 键盘的事件吗 我想检测此类事件UIViewController哪个没有UITextField或任何此类物体 我只有四个圆圈UIView我想在按下键盘上的按钮时将它们涂成不同的颜色 您没有任何对象可以从键盘获取
  • 使用 UIImagePickerController 的应用程序在拍照后选择“使用照片”时冻结

    我现在正在开发一个简单的照片和视频捕获应用程序 该应用程序成功地允许用户按下按钮即可拍摄照片或视频 但是 一旦您完成拍摄照片或视频 它就会提供 2 个选项 重新拍摄 和 使用照片 或 使用视频 具体取决于您使用的选项 如果用户点击 重新拍摄
  • 如何在我的 iOS 项目中添加和执行 .sql 文件?

    我找到了很多关于在 iOS 中使用 SQLite 数据库的教程 但没有找到任何直接引用 sql 文件的内容 谁能告诉我如何将现有的 SQL 数据库链接到我的应用程序 编辑 这是一个 MySQL 转储 我们有一个基于浏览器的抽认卡程序 现在我
  • 尝试从独立的 Apple Watch 应用发出网络请求

    当应用程序是独立应用程序时 Apple Watch 是否无法进行网络通话 即使手表已连接到 iPhone 我正在使用新的独立应用程序目标 它没有附带可以发出 WatchConnectivity 请求的配对 iOS 应用程序 我十有八九收到
  • 从 RemoteIO 保存音频的示例?

    我进行了搜索 但没有找到任何从 RemoteIO 音频单元保存音频的好示例或教程 我的设置 使用 MusicPlayer API 我有几个 AUSamplers gt MixerUnit gt RemoteIO 音频播放效果很好 我想添加将
  • 如何在 Xcode 4 中通过一个操作归档多个目标

    我有一个包含多个目标的项目 这些目标都适用于不同的 iOS 应用程序 例如 一个用于精简版的目标 另一个用于专业版的目标 我想立即构建并归档我的所有应用程序 目前 我对每个目标都有一个方案 我用它来独立归档每个应用程序 但现在我必须开始归档
  • UIImage:如何获取网站选项卡图标

    我正在开发一个 RSS 阅读器 我需要获取每个提要的图标 例如 如果我的提要是 google com 我想获取 G 图标并将其放入 UIImage 或其他内容中 关于如何实现这一目标有什么想法吗 最简单的方法是使用 Google NSStr
  • Cognito/IAM 策略和 S3 获取对象

    我正在尝试将 S3 和 Cognito 集成到我的 iOS 应用程序中 但到目前为止尚未成功 我相信该错误与我针对 Auth 和 Unauth 用户的 IAM 策略有关 所以这是我的政策 Version 2012 10 17 Stateme
  • 如何在 EKRecurrenceRule 中设置一周中某一天的数组?

    我想在用户选择的特定日期每周添加事件 可以是一个或多个 也可以是一整天 我将用户选择的日期值存储在模型类变量中 但是 当我添加事件并选择日期时 假设今天是星期一 我选择星期二和星期三并保存 然后我查看周一和周三添加的 iPhone 日历 我
  • Swift 中 UIImages 的淡入淡出动画

    我有一组图像 我希望它们在登录屏幕的背景中淡出 我无法在 swift 中找到任何可以做到这一点的东西 有什么办法我可以做到吗 这是我当前的代码 override func viewDidLoad super viewDidLoad star
  • 应用未能及时恢复

    我在一个非常具体的场景中遇到 未能及时恢复 崩溃 我认为与看门狗相关 仅在从后台恢复时 并且仅在进入后台后在很短的时间内执行此操作 a最多几秒钟 这似乎是相关的崩溃日志 Incident Identifier E30F2238 5B15 4

随机推荐