How to Repeat Music in Swift

Play a sound file on repeat in Swift?

By default AVAudioPlayer plays its audio from start to finish then stops, but we can control how many times to make it loop by setting its numberOfLoops property. For example, to make your audio play three times in total, you’d write this:

 player.numberOfLoops = 3

if you want the infinite loop then use

 player.numberOfLoops =  -1  

for e.g

  func playSound(soundName: String) { //
let url = Bundle.main.url(forResource: soundName, withExtension: "wav")
player = try! AVAudioPlayer(contentsOf: url!)
player.numberOfLoops = -1 // set your count here
player.play()

} // End of Play Sound

How to Repeat Music in Swift

Set numberOfLoops property to a negative value.

backgroundMusic.numberOfLoops = -1
backgroundMusic.play() // To stop, call stop()

How can I repeat a song in iOS?

Use AVAudioPlayer's numberOfLoops property for getting the repeat feature.

From the Apple doc's Discussion section:

A value of 0, which is the default, means to play the sound once. Set a positive integer value to specify the number of times to return to the start and play again. For example, specifying a value of 1 results in a total of two plays of the sound. Set any negative integer value to loop the sound indefinitely until you call the
stop() method.

So use:

player.numberOfLoops = n - 1 // here n (positive integer) denotes how many times you want to play the sound

Or, to avail the infinite loop use:

player.numberOfLoops = -1
// But somewhere in your code, you need to stop this

To stop the playing:

player.stop()

Swift Sound on repeat

Just set the numberOfLoops property to a negative number.

ThemePlayer.numberOfLoops = -1

From the documentation:

numberOfLoops
The number of times a sound will return to the beginning, upon reaching the end, to repeat playback.

...

var numberOfLoops: Int

...

A value of 0, which is the default, means to play the sound once. Set a positive integer value to specify the number of times to return to the start and play again. For example, specifying a value of 1 results in a total of two plays of the sound. Set any negative integer value to loop the sound indefinitely until you call the stop method.

You may also need to make your AVAudioPlayer a property, rather than a local variable. As it stands, with automatic reference counting, I think your local ThemePlayer instance is likely to be deallocated by ARC. Someone who knows AVAudioPlayer better than me might be able to comment on that.

(As an aside, you might want to follow Apple's convention of naming object instances by starting with lowercase letters, e.g. themePlayer rather than ThemePlayer. It'll make your code easier for other people to read.)

How to loop background music without lag/delay when song repeats (seamless)

You can use AVPlayerLooper and AVQueuePlayer to do this.

import UIKit
import AVFoundation

class ViewController: UIViewController {

var queuePlayer = AVQueuePlayer()
var playerLooper: AVPlayerLooper?

override func viewDidLoad() {
super.viewDidLoad()

guard let url = Bundle.main.url(forResource: "Gamescene(new)", withExtension: "mp3") else { return }
let playerItem = AVPlayerItem(asset: AVAsset(url: url))
playerLooper = AVPlayerLooper(player: queuePlayer, templateItem: playerItem)
queuePlayer.play()
}
}

Play audio file in sequence in Swift, where the second sound gets played on repeat

You're starting 2 players at the same time. You can use one player property, and it's AVAudioPlayerDelegate can play the second sound when the audioPlayerDidFinishPlaying method is called at the end of the first sound. Basically something like this:

class Player: AVAudioPlayerDelegate {

var audioPlayer: AVAudioPlayer?

func startPlayingFirstSong() {
// your 1st do/catch code...
try audioPlayer = AVAudioPlayer(contentsOf: urlIntro)
audioPlayer?.delegate = self
}

// AVAudioPlayer will call this func when the first song ends:
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
// your 2nd do/catch code...
try audioPlayer = AVAudioPlayer(contentsOf: url)
audioPlayer?.delegate = self
}

}

let player = Player()
player.startPlayingFirstSong()

How to loop through background music at specific time in SwiftUI

Just play it first time and then loop with

'AudioPlayer.currentTime += 30'

How do I repeat a AVAudioPlayer?

Set the Property numberOfLoops to -1 and it would go into infinite loop.

Loop audio for certain duration on iOS

You were on the right track with AVPlayerLooper.

This is how you setup AVPlayerLooper

var playerLooper: AVPlayerLooper!
var player: AVQueuePlayer!

func play(_ url: URL) {
let asset = AVAsset(url: url)
let playerItem = AVPlayerItem(asset: asset)

player = AVQueuePlayer(playerItem: playerItem)
playerLooper = AVPlayerLooper(player: player, templateItem: playerItem)

player.play()
}

To stop the loop after a set amount of time you can use addBoundaryTimeObserver(forTimes:queue:using:)
For example:

let assetDuration = CMTimeGetSeconds(asset.duration)
let maxDuration = 60.0 // Define max duration
let maxLoops = floor(maxDuration / assetDuration)
let lastLoopDuration = maxDuration - (assetDuration * maxLoops)
let boundaryTime = CMTimeMakeWithSeconds(lastLoopDuration, preferredTimescale: 1)
let boundaryTimeValue = NSValue(time: boundaryTime)

player.addBoundaryTimeObserver(forTimes: [boundaryTimeValue], queue: DispatchQueue.main) { [weak self] in
if self?.playerLooper.loopCount == Int(maxLoops) {
self?.player.pause()
}
}

For fading in/out you have to set the audioMix property to your AVPlayerItem instance before using it.

let introRange = CMTimeRangeMake(start: CMTimeMakeWithSeconds(0, preferredTimescale: 1), duration: CMTimeMakeWithSeconds(1, preferredTimescale: 1))
let endingSecond = CMTimeRangeMake(start: CMTimeMakeWithSeconds(assetDuration - 1, preferredTimescale: 1), duration: CMTimeMakeWithSeconds(1, preferredTimescale: 1))

let inputParams = AVMutableAudioMixInputParameters(track: asset.tracks.first! as AVAssetTrack)
inputParams.setVolumeRamp(fromStartVolume: 0, toEndVolume: 1, timeRange: introRange)
inputParams.setVolumeRamp(fromStartVolume: 1, toEndVolume: 0, timeRange: endingSecond)

let audioMix = AVMutableAudioMix()
audioMix.inputParameters = [inputParams]
playerItem.audioMix = audioMix

Complete function:

func play(_ url: URL) {
let asset = AVAsset(url: url)
let playerItem = AVPlayerItem(asset: asset)

let assetDuration = CMTimeGetSeconds(asset.duration)

let introRange = CMTimeRangeMake(start: CMTimeMakeWithSeconds(0, preferredTimescale: 1), duration: CMTimeMakeWithSeconds(1, preferredTimescale: 1))
let endingSecond = CMTimeRangeMake(start: CMTimeMakeWithSeconds(assetDuration - 1, preferredTimescale: 1), duration: CMTimeMakeWithSeconds(1, preferredTimescale: 1))

let inputParams = AVMutableAudioMixInputParameters(track: asset.tracks.first! as AVAssetTrack)
inputParams.setVolumeRamp(fromStartVolume: 0, toEndVolume: 1, timeRange: introRange)
inputParams.setVolumeRamp(fromStartVolume: 1, toEndVolume: 0, timeRange: endingSecond)

let audioMix = AVMutableAudioMix()
audioMix.inputParameters = [inputParams]
playerItem.audioMix = audioMix

player = AVQueuePlayer(playerItem: playerItem)
playerLooper = AVPlayerLooper(player: player, templateItem: playerItem)
player.play()

let maxDuration = 60.0 // Define max duration
let maxLoops = floor(maxDuration / assetDuration)
let lastLoopDuration = maxDuration - (assetDuration * maxLoops)
let boundaryTime = CMTimeMakeWithSeconds(lastLoopDuration, preferredTimescale: 1)
let boundaryTimeValue = NSValue(time: boundaryTime)

player.addBoundaryTimeObserver(forTimes: [boundaryTimeValue], queue: DispatchQueue.main) { [weak self] in
if self?.playerLooper.loopCount == Int(maxLoops) {
self?.player.pause()
}
}
}


Related Topics



Leave a reply



Submit