1

From the question in this If I assign a sound in Reality Composer, can I stop it programmatically in RealityKit?, I would like to use method to resume playback after Play Music.

Can I do that?

Now, I use this command in stopAudio function to stop the music.

func stopAudio() {
    if arView.scene.anchors.count > 0 {
        if arView.scene.anchors[0].isAnchored {
            arView.scene.anchors[0].children[0].stopAllAudio()
        }
    }
}

If I want arView.scene.anchors[0] to replay the music again, which command should I use?

Andy Jazz
  • 49,178
  • 17
  • 136
  • 220
kkk
  • 187
  • 8

1 Answers1

1

Audio Playback Controller

Since RealityKit 2.0 isn't able to control parameters of Reality Composer's behaviors, the best strategy for controlling audio is to create a programmatic AudioPlaybackController. To feed your audio file to the controller, export .rcproject scene to .usdz format and use unzipping trick to extract the .aiff, .caf or .mp3 sound file. When loading audio for playback, you can choose between spatial and non-spatial audio experience.

UIKit version

import UIKit
import RealityKit

extension ViewController {

    private func loadAudio() {
        do {
            let resource = try AudioFileResource.load(
                                                named: "planetarium07.caf",
                                                   in: nil,
                                            inputMode: .spatial,
                                      loadingStrategy: .preload,
                                           shouldLoop: true)

            self.controller = entity.prepareAudio(resource)
            self.controller?.speed = 0.9
            self.controller?.fade(to: .infinity, duration: 2)

        } catch {
            print(error.localizedDescription)
        }
    }
}

ViewController.

class ViewController : UIViewController {
    
    @IBOutlet var uiView: UIView!         // when using @IBAction buttons
    @IBOutlet var arView: ARView!
    private var entity = Entity()
    private var controller: AudioPlaybackController? = nil
    
    override func viewDidLoad() {
        super.viewDidLoad()
        uiView.backgroundColor = .systemCyan
        
        let boxScene = try! Experience.loadBox()
        arView.scene.anchors.append(boxScene)
        
        let anchor = boxScene.anchor
        anchor?.addChild(entity)
        
        self.loadAudio()
    }
    @IBAction func playMusic(_ sender: UIButton) {
        self.controller?.play()
    }
    @IBAction func stopMusic(_ sender: UIButton) {
        self.controller?.pause()
        // self.controller?.stop()
    }
}

SwiftUI version

import SwiftUI
import RealityKit

struct ContentView : View {       
    @State var arView = ARView(frame: .zero)
    @State var controller: AudioPlaybackController? = nil
    @State var entity = Entity()
    
    var body: some View {
        ZStack {
            ARViewContainer(arView: $arView, 
                            entity: $entity).ignoresSafeArea()
            VStack {
                Spacer()
                Button("Play") { loadSound(); controller?.play() }
                Button("Stop") { controller?.stop() }
            }
        }
    }
    func loadSound() {
        do {
            let resource = try AudioFileResource.load(
                                                named: "planetarium07.caf",
                                                   in: nil,
                                            inputMode: .spatial,
                                      loadingStrategy: .preload,
                                           shouldLoop: true)    
            self.controller = entity.prepareAudio(resource)
        } catch {
            print(error.localizedDescription)
        }
    }
}

ARViewContainer.

struct ARViewContainer: UIViewRepresentable {
    
    @Binding var arView: ARView
    @Binding var entity: Entity
    
    func makeUIView(context: Context) -> ARView {

        let boxScene = try! Experience.loadBox()
        arView.scene.anchors.append(boxScene)
        
        let anchor = boxScene.anchor
        anchor?.addChild(entity)
        return arView
    }
    func updateUIView(_ view: ARView, context: Context) { }
}
Andy Jazz
  • 49,178
  • 17
  • 136
  • 220