AudioKit 音频播放器 - 不同步播放每个曲目

问题描述 投票:0回答:1

我正在开发一个应用程序来练习与 16 个不同曲目的混音。我在一个函数中加载每个文件,然后按一个按钮即可播放所有文件,但它们在不同的时间开始播放,导致音频不同步。您知道如何确保一切同步吗?当这些文件在 DAW 中播放时,它们都完全同步,所以这不是问题,而是代码中的问题。

主应用程序文件

import swiftUI
import UIKit

@main
struct MixLabApp: App {
    @StateObject var conductor = MixerClass()
    
    var body: some Scene {
        WindowGroup {
            FreePlayMain()
                .environmentObject(conductor)
        }
    }
}

Mixer 类(精简以便更容易理解)

import Foundation
import AudioKit
import AVFoundation

final class MixerClass: ObservableObject {
    let engine = AudioEngine()
    var mixer = Mixer()
    
    @Published var track1 = AudioPlayer()
    @Published var track2 = AudioPlayer()
    @Published var track3 = AudioPlayer()

    @Published var isTrack1Playing: Bool = false
    @Published var isTrack2Playing: Bool = false
    @Published var isTrack3Playing: Bool = false

    init() {
        do {
            Settings.bufferLength = .medium
            try AVAudioSession.sharedInstance().setPreferredIOBufferDuration((Settings.bufferLength.duration))
            
            try AVAudioSession.sharedInstance().setCategory(.playAndRecord, options: [.defaultToSpeaker, .mixWithOthers, .allowBluetoothA2DP])
            
            try AVAudioSession.sharedInstance().setActive(true)
        } catch let err {
            print(err)
        }

        do {
            if let track1FileURL = Bundle.main.url(forResource: "DQ_Kick", withExtension: "mp3") {
                try track1.load(url: track1FileURL)
            } else {
                Log("Could not find Track 1 file")
            }
            
            if let track2FileURL = Bundle.main.url(forResource: "DQ_Snare", withExtension: "mp3") {
                try track2.load(url: track2FileURL)
            } else {
                Log("Could not find Track 2 file")
            }
            
            if let track3FileURL = Bundle.main.url(forResource: "DQ_Tom1", withExtension: "mp3") {
                try track3.load(url: track3FileURL)
            } else {
                Log("Could not find Track 3 file")
            }

        track1.isLooping = true
        track2.isLooping = true
        track3.isLooping = true
    }

 func playStopToggle() {
        
        isTrack1Playing ? track1.stop() : track1.start()
        isTrack1Playing.toggle()
        
        isTrack2Playing ? track2.stop() : track2.start()
        isTrack2Playing.toggle()
        
        isTrack3Playing ? track3.stop() : track3.start()
        isTrack3Playing.toggle()
    }
}

FreePlay主要

import SwiftUI

struct FreePlayMain: View {
    @EnvironmentObject var conductor: MixerClass
    
    var body: some View {
        NavigationStack {
            VStack {
                VStack {
                    Slider(value: $conductor.track1.volume, in: 0...1)
                        .padding()
                    Slider(value: $conductor.track2.volume, in: 0...1)
                        .padding()
                    Slider(value: $conductor.track3.volume, in: 0...1)
                        .padding()
                }
                playStopButton
            }
        }
    }
    
    private var playStopButton: some View {
        Button(action: {
            conductor.playStopToggle()
        }) {
            VStack {
                Text("\(Image(systemName: conductor.isTrack1Playing ? "stop.fill" : "play.fill")) \(conductor.isTrack1Playing ? "Stop" : "Start") Track 1")
            }
        }
    }
}
swiftui audiokit
1个回答
0
投票

不确定您是否已经找到了解决方案,但几个月前我遇到了类似的问题,技巧是使用 .play(at:) 方法为所有曲目提供统一的开始时间。这就是该行在我的playbackChannels中的样子,它是一个对象数组,每个对象都包含一个audioKit播放器

self.playbackChannels.forEach{
        $0.getAudioPlayer().play(from: 0, at: startTime)
}
© www.soinside.com 2019 - 2024. All rights reserved.