bug fixes
This commit is contained in:
parent
caea96547a
commit
7d448e79de
2 changed files with 34 additions and 11 deletions
|
|
@ -1173,7 +1173,7 @@ class AudioPlayer: NSObject, ObservableObject {
|
|||
isUsingOfflineVis = false
|
||||
offlineVisProgress = 0
|
||||
offlineVisFPS = VisualizerSettings.shared.effectiveFPS
|
||||
let points = VisualizerSettings.shared.numberOfPoints
|
||||
let points = VisualizerSettings.shared.nowPlaying.numberOfPoints
|
||||
let cutoff = VisualizerSettings.shared.frequencyCutoff
|
||||
|
||||
Task {
|
||||
|
|
|
|||
|
|
@ -1610,12 +1610,32 @@ class ShazamRecognizer: NSObject, ObservableObject, SHSessionDelegate {
|
|||
// MARK: - MTAudioProcessingTap
|
||||
|
||||
private func installTap(on playerItem: AVPlayerItem) -> Bool {
|
||||
guard let audioTrack = playerItem.asset.tracks(withMediaType: .audio).first else {
|
||||
// loadTracks is async (tracks(withMediaType:) deprecated iOS 16)
|
||||
// We load synchronously from the asset's already-loaded track list if available,
|
||||
// falling back to a blocking load. Since this is called off the main thread in
|
||||
// a Task, a brief synchronous wait is acceptable.
|
||||
let asset = playerItem.asset
|
||||
var audioTrack: AVAssetTrack?
|
||||
|
||||
// Fast path: tracks already in memory (common for items that are playing)
|
||||
let loadedTracks = asset.tracks(withMediaType: .audio)
|
||||
if let first = loadedTracks.first {
|
||||
audioTrack = first
|
||||
} else {
|
||||
// Async load — bridge with a semaphore so we stay synchronous from the caller's view
|
||||
let sema = DispatchSemaphore(value: 0)
|
||||
Task {
|
||||
audioTrack = try? await asset.loadTracks(withMediaType: .audio).first
|
||||
sema.signal()
|
||||
}
|
||||
sema.wait()
|
||||
}
|
||||
|
||||
guard let audioTrack else {
|
||||
DebugLogger.shared.log("Shazam: no audio track on playerItem", category: "Audio")
|
||||
return false
|
||||
}
|
||||
|
||||
// Store self as opaque pointer in tap storage
|
||||
var callbacks = MTAudioProcessingTapCallbacks(
|
||||
version: kMTAudioProcessingTapCallbacksVersion_0,
|
||||
clientInfo: UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()),
|
||||
|
|
@ -1624,15 +1644,15 @@ class ShazamRecognizer: NSObject, ObservableObject, SHSessionDelegate {
|
|||
},
|
||||
finalize: nil,
|
||||
prepare: { tap, maxFrames, processingFormat in
|
||||
// Capture the source format so we can build the converter on first buffer
|
||||
let storage = Unmanaged<ShazamRecognizer>
|
||||
.fromOpaque(MTAudioProcessingTapGetStorage(tap))
|
||||
.takeUnretainedValue()
|
||||
let format = AVAudioFormat(streamDescription: processingFormat)
|
||||
storage.analysisQueue.async {
|
||||
storage.sourceFormat = format
|
||||
if let src = format, let dst = storage.targetFormat as AVAudioFormat? {
|
||||
storage.converter = try? AVAudioConverter(from: src, to: dst)
|
||||
// AVAudioConverter.init does not throw — no try? needed
|
||||
if let src = format {
|
||||
storage.converter = AVAudioConverter(from: src, to: storage.targetFormat)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -1640,19 +1660,22 @@ class ShazamRecognizer: NSObject, ObservableObject, SHSessionDelegate {
|
|||
process: shazamTapProcess
|
||||
)
|
||||
|
||||
var newTap: Unmanaged<MTAudioProcessingTap>?
|
||||
var rawTap: Unmanaged<MTAudioProcessingTap>?
|
||||
let status = MTAudioProcessingTapCreate(
|
||||
kCFAllocatorDefault, &callbacks,
|
||||
kMTAudioProcessingTapCreationFlag_PostEffects, &newTap
|
||||
kMTAudioProcessingTapCreationFlag_PostEffects, &rawTap
|
||||
)
|
||||
guard status == noErr, let newTap else {
|
||||
guard status == noErr, let rawTap else {
|
||||
DebugLogger.shared.log("Shazam: MTAudioProcessingTapCreate failed \(status)", category: "Audio")
|
||||
return false
|
||||
}
|
||||
tap = newTap
|
||||
|
||||
// takeRetainedValue transfers ownership (ARC takes over) — assign to our ivar
|
||||
let tapValue = rawTap.takeRetainedValue()
|
||||
tap = Unmanaged.passRetained(tapValue) // re-wrap for cleanup later
|
||||
|
||||
let inputParams = AVMutableAudioMixInputParameters(track: audioTrack)
|
||||
inputParams.audioTapProcessor = newTap.takeRetainedValue()
|
||||
inputParams.audioTapProcessor = tapValue // passes the already-retained value
|
||||
|
||||
let mix = AVMutableAudioMix()
|
||||
mix.inputParameters = [inputParams]
|
||||
|
|
|
|||
Loading…
Reference in a new issue