bibscy
bibscy

Reputation: 2708

addPeriodicTimeObserver is not called every millisecond?

I know that player.currentItem.currentTime().seconds returns the current time in seconds of the audio file that is being played.

Can I add a callback function on player to be called every millisecond?
For example for second 1, this callBack function should be called 1000 times.

The problem is that using addPeriodicTimeObserver the callBack function is called only 1 time per second, rather than 1000 times per second.

Why do I need this?

1.
I am extracting the beat count of a Salsa song manually by tapping on a button in the UI while the audio file is being played and I record it as [Int:Int] // milisecondButtonTapped: beatCount.

My array is going to look like
var beatCounts = [982: 1, 2051: 2, 3006: 3, 5027: 5, 6011: 6, 7028: 7]

After the audio finishes playing I will end up with an array containing the beatCounts corresponding to certain milliseconds of player.currentItem.currentTime()

2.

Now, I want to play the song again and check if player currentTime in milliseconds is == to one of the values in var beatCounts

func checkCurrentTime(playerTimeMilliseconds: Int) {

  for (millisecond, beatCount) in beatCounts {
    if  playerTimeMilliseconds == millisecond {
       //show beatCount in label on UI 
     }
 }
}





func playSound(url: URL) {

    let playerItem: AVPlayerItem = AVPlayerItem(url: url)
    player = AVPlayer(playerItem: playerItem)


    try! AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
    try! AVAudioSession.sharedInstance().setActive(true)
    player?.play()

    player?.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1, 1000), queue: DispatchQueue.main, using: { [weak self] (CMTime) in

        print("cmtime is \(CMTime)")
      CMTime.value

        if self?.player?.currentItem?.status == .readyToPlay {

        }
    })

}//end playSound

Upvotes: 2

Views: 2117

Answers (1)

Z. Ziv
Z. Ziv

Reputation: 115

You just have to use forInterval differently, whereas time unit will be 0.001 and preferred time scaled should be used with NSEC_PER_SEC as quoted below

let interval: CMTime = CMTimeMakeWithSeconds(0.001, preferredTimescale: Int32(NSEC_PER_SEC))

player?.addPeriodicTimeObserver(forInterval: *interval*), queue:
.main) { [weak self] (CMTime) in

Upvotes: 3

Related Questions