0

Hi I am making an iOS game in SpriteKit and decided to use an AvAudioPlayerNode and engine instead off the regular AvAudioPlayer so I could change the pitch and playbackspeed but I have come across a problem in which the AvAudioPlayerNode doesn't repeat after being played

I have already used many answers from stack overflow but they are very out dated if you do happen to solve this can u make sure it works with my code otherwise its useless

//

let engine = AVAudioEngine()
let speedControl = AVAudioUnitVarispeed()
let pitchControl = AVAudioUnitTimePitch()
let audioplayer = AVAudioPlayerNode()
let audioPath = Bundle.main.path(forResource: "loop", ofType: "wav")


func play(_ url: URL) throws {

 let file = try AVAudioFile(forReading: url)



 engine.attach(audioplayer)
 engine.attach(pitchControl)
 engine.attach(speedControl)

 engine.connect(audioplayer, to: speedControl, format: nil)
 engine.connect(speedControl, to: pitchControl, format: nil)
 engine.connect(pitchControl, to: engine.mainMixerNode, format: nil)

 audioplayer.scheduleFile(file, at: nil)

 try engine.start()
 audioplayer.play()


}

'

//This simply gets run in the game view controller by doing this

let audioPath = Bundle.main.path(forResource: "loop", ofType: "wav") ?? ""

    do
    {

        try? play(URL(fileURLWithPath: audioPath))
    }
    catch {
}

I actually have no idea where to start I am fairly new to Xcode so any help would be useful, please don't over complicate things I am 15

Sam1212
  • 3
  • 2
  • I recommend using SKAudioNode. It has avAudioNode attached to it, which is cast-able to an AVAudioPlayerNode, giving you the features you want. – Knight0fDragon Sep 05 '19 at 19:40

1 Answers1

3

You want to read your file into a buffer, then schedule the player to loop

let file = try AVAudioFile(forReading: url)
let audioFileBuffer = AVAudioPCMBuffer(PCMFormat: file.fileFormat, frameCapacity: file.length)
try? read(into buffer: audioFileBuffer )
audioFilePlayer.scheduleBuffer(audioFileBuffer, atTime: nil, options:.Loops, completionHandler: nil)
audioFilePlayer.play()
Knight0fDragon
  • 16,609
  • 2
  • 23
  • 44
  • This would take too much of memory, isn't there a way to loop with small buffer – cs guy Apr 04 '21 at 13:58
  • @csguy maybe back in 1982 – Knight0fDragon Apr 04 '21 at 16:27
  • not really, imagine 82 sound files sitting in memory each of them having 30 seconds. This takes around 700MB of memory on my mac because all of them are loaded into memory with buffers size of whole sound file, this approach would cause troubles on IOS apps... so I am looking for a way to loop with setting a buffer size, is ther a way? – cs guy Apr 04 '21 at 16:32
  • Imagine 82 files sound files in memory.... why would I need to imagine 82 sound files that require looping. Don’t have 82 files in memory, you better manage your resources a lot better and only have what you need in memory. – Knight0fDragon Apr 04 '21 at 16:34
  • 1
    because I am making an audio looper app and there are 82 buttons on the screen – cs guy Apr 04 '21 at 16:35
  • So? You start with a 82 samples each composed of one second, then you use that time to load in your 30 second looping sample that starts 1 second later. The loop plays immediately after the sample. – Knight0fDragon Apr 04 '21 at 16:40