Mick McCarthy
Mick McCarthy

Reputation: 437

AudioKit: AKPlayer not loading AKAudioFile at all

I have been trying to replace the AKAudioPlayer in my code with an AKPlayer due to a separate issue whereby the playhead of the AKAudioPlayer gives a negative number after pausing and does not update. However after this switch I have been running into a separate issue where the AKPlayer doesn't load my AKAudioFIle at all. Here is a simple version of my code:

import UIKit
import AudioKit
import AudioKitUI

class ViewController: UIViewController
{
    var microphone : AKMicrophone!
    var mixer : AKMixer!
    var waveformBooster: AKBooster!
    var outputBooster : AKBooster!
    var exportTape : AKAudioFile!
    var recorder : AKNodeRecorder!
    var player : AKPlayer!
    var recordingTimer : Timer!
    var playTimer : Timer!

    @IBOutlet var startRecordingButton: CircularButton!
    @IBOutlet var playAndPauseRecordingButton: UIButton!

    override func viewDidLoad()
    {
        super.viewDidLoad()

        microphone = AKMicrophone()
        mixer = AKMixer(microphone)

        AudioKit.output = mixer
        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)

        // Create player with blank tape so that we have a reference player object

        player = AKPlayer(audioFile: exportTape)
    }

    @IBAction func startRecording(_ sender: UIButton)
    {
        if player.isPlaying == false
        {
            // Delete contents of output file so it can be rewritten

            try! recorder.reset()

            microphone.start()

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

    @IBAction func stopRecording(_ sender: UIButton)
    {
        microphone.stop()
        recorder.stop()
    }

    @IBAction func playAndPauseRecording(_ sender: UIButton)
    {
        // Replace the empty or previous tape with the newly recorded one

        //player.load(audioFile: exportTape) <-- This doesn't work either
        var player = AKPlayer(audioFile: exportTape)

        // TEST

        print("CurrentTime \(player.currentTime)")
        print("StartTime \(player.startTime)")
        print("EndTime \(player.endTime)")
        print("Duration \(player.duration)")
        print("isPlaying \(player.isPlaying)")

        // END TEST

        // If something has been recorded...

        if player.duration > 0
        {
            // If the player is currently playing...

            if player.isPlaying == true
            {   
                // ...and pause the tape

                player.pause()
            } else
            {
                AudioKit.output = player
                player.play()
                print("Playing...")

                //player.resume()
            }
        }
    }
}

Neither the using the .load() method nor creating a new player instance are working for me - the output is as follows:

CurrentTime nan
StartTime 0.0
EndTime 0.0
Duration 0.0
isPlaying false

Strangely followed by

AKPlayer.swift:deinit:918:* deinit AKPlayer

Does this mean that the AKPlayer is deinitialising after the test print statements?

To be clear, the file would load properly into the player when it was an AKAudioPlayer, it is only now that I have changed it over to an AKPlayer that the file won't load. Does anyone know why this is? Any help would be much appreciated.

EDIT:

Here is a much shorter and simpler piece of code that still exhibits the error:

import UIKit
import AudioKit

class ViewController: UIViewController
{
    var file : AKAudioFile!
    var player : AKPlayer!
    var audioPlayer : AKAudioPlayer!
    var microphone : AKMicrophone!
    var mixer : AKMixer!
    var recorder : AKNodeRecorder!
    var booster : AKBooster!

    @IBOutlet var startRecordingButton: UIButton!
    @IBOutlet var stopRecordingButton: UIButton!
    @IBOutlet var playRecordingButton: UIButton!

    override func viewDidLoad()
    {
        super.viewDidLoad()

        microphone = AKMicrophone()
        mixer = AKMixer(microphone)

        booster = AKBooster(mixer)
        booster.gain = 0

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

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

    @IBAction func startRecording(_ sender: UIButton)
    {
        microphone.start()
        print("Recording...")

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

    @IBAction func stopRecording(_ sender: UIButton)
    {
        microphone.stop()
        recorder.stop()
        print("Recording Stopped")
    }

    @IBAction func playRecording(_ sender: UIButton)
    {
        audioPlayer = try! AKAudioPlayer(file: file)
        player = AKPlayer(audioFile: file)

        AudioKit.output = player
        player.play()

//        v this works! v

//        AudioKit.output = audioPlayer 
//        audioPlayer.play()
    }
}

Upvotes: 1

Views: 480

Answers (1)

Ryan Francesconi
Ryan Francesconi

Reputation: 1006

This has been addressed in an upcoming bug fix. The problem was that AKPlayer was assuming the passed in AKAudioFile was opened forReading, whereas the AKMicrophone's associated file was forWriting.

AKAudioPlayer created a duplicated file object which is why it worked there. Should be updated very soon!

Upvotes: 1

Related Questions