syedhali / EZAudio

An iOS and macOS audio visualization framework built upon Core Audio useful for anyone doing real-time, low-latency audio processing and visualizations.
Other
4.93k stars 821 forks source link

`startFetchingAudio` doesn't work anymore after calling `stopFetchingAudio` #362

Open victorBaro opened 6 years ago

victorBaro commented 6 years ago

I have a very simple app with 4 buttons (record, stop recording, play and delete) and a plot (EZAudioPlotGL) showing the microphone input realtime.

Everything works very well until I try to delete the file and record again. For some reason, the following delegate methods are not called any more:

    func microphone(_ microphone: EZMicrophone!, hasAudioReceived buffer: UnsafeMutablePointer<UnsafeMutablePointer<Float>?>!, withBufferSize bufferSize: UInt32, withNumberOfChannels numberOfChannels: UInt32) { ... }

    func microphone(_ microphone: EZMicrophone!, hasBufferList bufferList: UnsafeMutablePointer<AudioBufferList>!, withBufferSize bufferSize: UInt32, withNumberOfChannels numberOfChannels: UInt32) { ... }

This is what my code looks like

class WaveRecorderView: UIView {
    fileprivate var recordingAudioPlot: EZAudioPlotGL!
    fileprivate var microphone: EZMicrophone!
    fileprivate var recorder: EZRecorder!
    private var backgroundImageView: UIImageView!

    fileprivate(set) var isRecording = false
    var shouldStopAutomatically = true
    var maximumRecordingTime = GlobalConstants.maxClipDuration

    init() {
        super.init(frame: .zero)
        setup()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func setup() {
        backgroundImageView = UIImageView(image: #imageLiteral(resourceName: "StaticWaveBackground"))
        addSubview(backgroundImageView)
        backgroundImageView.autoPinEdgesToSuperviewEdges()
        startPlot()
    }

    private func startPlot() {
        recordingAudioPlot = EZAudioPlotGL()
        recordingAudioPlot.backgroundColor = UIColor.white
        recordingAudioPlot.color = UIColor.customBlue
        recordingAudioPlot.gain = 5
        recordingAudioPlot.plotType = EZPlotType.rolling
        recordingAudioPlot.shouldFill = true
        recordingAudioPlot.shouldMirror = true
        addSubview(recordingAudioPlot)
        recordingAudioPlot.autoPinEdgesToSuperviewEdges()
    }

    func startRecording(at fileURL: URL) {
        print(fileURL)
        microphone = EZMicrophone(delegate: self, startsImmediately: true)
        recorder = EZRecorder(url: fileURL, clientFormat: microphone.audioStreamBasicDescription(), fileType: EZRecorderFileType.M4A, delegate: self)
        isRecording = true
    }

    func stopRecording() {
        isRecording = false
        microphone.stopFetchingAudio()
        recorder.closeAudioFile()
    }

    func removeAudio() {
        //There is another class in charge of removing the previously created m4a file and create a 
        //new URL for the next file
        recorder = nil
        microphone = nil
        recordingAudioPlot.clear()
    }
}

// THE FOLLOWING METHODS ARE CALLED CORRECTLY BUT ONCE I STOP RECORDING
// AND REMOVE THE AUDIO, THESE METHODS ARE NOT CALLED ANY MORE AFTER `STARTRECORDING`

extension WaveRecorderView: EZMicrophoneDelegate, EZRecorderDelegate {
    func microphone(_ microphone: EZMicrophone!, hasAudioReceived buffer: UnsafeMutablePointer<UnsafeMutablePointer<Float>?>!, withBufferSize bufferSize: UInt32, withNumberOfChannels numberOfChannels: UInt32) {
        DispatchQueue.main.async { [weak self] in
            self?.recordingAudioPlot.updateBuffer(buffer[0], withBufferSize: bufferSize)
        }
    }

    func microphone(_ microphone: EZMicrophone!, hasBufferList bufferList: UnsafeMutablePointer<AudioBufferList>!, withBufferSize bufferSize: UInt32, withNumberOfChannels numberOfChannels: UInt32) {
        guard recorder != nil else { return }
        recorder.appendData(from: bufferList, withBufferSize: bufferSize)
    }
}
tolik85 commented 6 years ago

Did you solve your problem?

nguyentrongbang commented 5 years ago

Have the same question

designerfuzzi commented 2 years ago

when you remove also the microphone via setting it to = nil you also remove its delegate with it, which leads to no call of the delegate methods of course.