Definitely-A-Person
Definitely-A-Person

Reputation: 11

How to resolve FlushPendingInput error with AVFoundation?

I'm a relatively inexperienced programmer using Swift 5.9 and Xcode. I'm trying to set up an audio recorder using AVFoundation and create tableView cells corresponding to each recording.
However, no new cells appear when the recording is finished (when run in the simulator; not tested on physical device).
This code was made by following this tutorial for recording: https://www.youtube.com/watch?v=CrLbuzM9IDs and a London App Brewery tutorial on tableViews.

Here is the code:

import UIKit
import AVFoundation

class SoundSetViewController: UIViewController, AVAudioRecorderDelegate {
    //need to add table view, recording. add recoding url to list of recordings. Can use button on side to delete. Add button to delete set, and alert before doing this.
    var soundSet = SoundSet(name: "New Sound", files: [], sounds: [], recordsNumber: 0)

    var recordingSession: AVAudioSession!
    var audioRecorder: AVAudioRecorder!

    @IBOutlet var recordingButton: UIButton!
    @IBOutlet var tableView: UITableView!

    @IBAction func toggleListeningSession(_ sender: Any) {
        if  audioRecorder == nil {
            soundSet.recordsNumber += 1
            let fileName = getRecordingPath().appendingPathComponent("\(soundSet.recordsNumber).m4a") //add soundsetname once class defined
            print(fileName.absoluteString)
            soundSet.files.append(fileName)
            //do research into what settings work well
            let settings = [AVFormatIDKey: Int(kAudioFormatMPEG4AAC), AVSampleRateKey: 12000, AVNumberOfChannelsKey: 1, AVEncoderAudioQualityKey: AVAudioQuality.low.rawValue]
            //start recording
            do {
                audioRecorder = try AVAudioRecorder(url: fileName, settings: settings)
                audioRecorder.delegate = self
                audioRecorder.record()
                recordingButton.setTitle("Stop Recording", for: .normal)
            } catch {
                displayAlert(title: "Error:", message: "recording failed to start")
            } 
        }
        else {
            audioRecorder.stop()
            audioRecorder = nil
            recordingButton.setTitle("Start Recording", for: .normal)
            updateView()
        }
    }
    
    func updateView(){
        for file in soundSet.files {
            let fileName = file.lastPathComponent
            let recording = Recording(recordName: fileName, fileName: file)
            self.soundSet.sounds.append(recording)
            DispatchQueue.main.async {
                self.tableView.reloadData()
            }  
        }
    }
    
    func getRecordingPath()->URL{
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        let documentDirectory = paths[0]
        return documentDirectory
    }
    
    //alerts user if problem
    func displayAlert(title: String, message: String){
        let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "Dismiss", style: .default))
        alert.present(alert, animated: true)
    }
    
    override func viewDidLoad(){
        super.viewDidLoad()
        tableView.register(UINib(nibName: K.SoundSetConstants.cellName, bundle: nil), forCellReuseIdentifier: K.SoundSetConstants.cellIdentifier)
        recordingSession = AVAudioSession.sharedInstance()


        AVAudioApplication.requestRecordPermission { hasPermission in
            if hasPermission {
                print("has permission")
            }
        }
        updateView()
    }
}

extension SoundSetViewController: UITableViewDataSource{
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: K.SoundSetConstants.cellIdentifier, for: indexPath) as! RecordSampleCell
        cell.recordingName.text = "\(soundSet.recordsNumber)"
        print(soundSet.recordsNumber)
        return cell
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return soundSet.recordsNumber
    }
}

When I start recording, this is the output in the console:

file:///Users/myName/Library/Developer/CoreSimulator/Devices/2CA498B1-270C-4F83-8B25-D18C7E096D53/data/Containers/Data/Application/84C1909A-0632-4E06-AB03-20B09EA0B323/Documents/2.m4a 2024-02-23 13:16:51.367417-0500 FeedBack[34081:22683094] [AQ] AudioQueueObject.cpp:1580 BuildConverter: AudioConverterNew returned -50 from: 0 ch, 12000 Hz, .... (0x00000000) 0 bits/channel, 0 bytes/packet, 0 frames/packet, 0 bytes/frame to: 1 ch, 12000 Hz, aac (0x00000000) 0 bits/channel, 0 bytes/packet, 1024 frames/packet, 0 bytes/frame

When I end the recording, this is the output in the console:

2024-02-23 13:17:42.726800-0500 FeedBack[34081:22683094] [AQ] AudioQueueObject.cpp:6643 ConvertInput: aq@0x107820000: AudioConverterFillComplexBuffer returned -50, packetCount 5 2024-02-23 13:17:42.727141-0500 FeedBack[34081:22683094] [AQ] AudioQueueObject.h:2353 GetAnchorIOSampleTimeWarnIfInvalid: aq@0x107820000: ConvertInput using invalid anchor time 2024-02-23 13:17:42.727319-0500 FeedBack[34081:22683094] [AQ] AudioQueueObject.cpp:3060 FlushPendingInput: flushing pending input terminated - error -50

I have tried running this code without the tableView and the console shows the same thing.
In searching, I have not found anything helpful to me about BuildConverter, AudioConverter, or FlushPendingInput error -50.

Upvotes: 1

Views: 78

Answers (0)

Related Questions