Skip to content

Commit

Permalink
add AudioUnitPlayer #607
Browse files Browse the repository at this point in the history
  • Loading branch information
kingslay committed Nov 4, 2023
1 parent acf62d5 commit 24f065d
Show file tree
Hide file tree
Showing 11 changed files with 402 additions and 82 deletions.
56 changes: 36 additions & 20 deletions Demo/SwiftUI/Shared/Defaults.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@ import SwiftUI

public class Defaults: ObservableObject {
@AppStorage("showRecentPlayList") public var showRecentPlayList = false
@AppStorage("isUseAudioRenderer") public var isUseAudioRenderer = KSOptions.isUseAudioRenderer {
didSet {
KSOptions.isUseAudioRenderer = isUseAudioRenderer
}
}

@AppStorage("hardwareDecode")
public var hardwareDecode = KSOptions.hardwareDecode {
Expand All @@ -31,85 +26,99 @@ public class Defaults: ObservableObject {
}
}

@AppStorage("isUseDisplayLayer") public var isUseDisplayLayer = MEOptions.isUseDisplayLayer {
@AppStorage("isUseDisplayLayer")
public var isUseDisplayLayer = MEOptions.isUseDisplayLayer {
didSet {
MEOptions.isUseDisplayLayer = isUseDisplayLayer
}
}

@AppStorage("preferredForwardBufferDuration") public var preferredForwardBufferDuration = KSOptions.preferredForwardBufferDuration {
@AppStorage("preferredForwardBufferDuration")
public var preferredForwardBufferDuration = KSOptions.preferredForwardBufferDuration {
didSet {
KSOptions.preferredForwardBufferDuration = preferredForwardBufferDuration
}
}

@AppStorage("maxBufferDuration") public var maxBufferDuration = KSOptions.maxBufferDuration {
@AppStorage("maxBufferDuration")
public var maxBufferDuration = KSOptions.maxBufferDuration {
didSet {
KSOptions.maxBufferDuration = maxBufferDuration
}
}

@AppStorage("isLoopPlay") public var isLoopPlay = KSOptions.isLoopPlay {
@AppStorage("isLoopPlay")
public var isLoopPlay = KSOptions.isLoopPlay {
didSet {
KSOptions.isLoopPlay = isLoopPlay
}
}

@AppStorage("canBackgroundPlay") public var canBackgroundPlay = true {
@AppStorage("canBackgroundPlay")
public var canBackgroundPlay = true {
didSet {
KSOptions.canBackgroundPlay = canBackgroundPlay
}
}

@AppStorage("isAutoPlay") public var isAutoPlay = true {
@AppStorage("isAutoPlay")
public var isAutoPlay = true {
didSet {
KSOptions.isAutoPlay = isAutoPlay
}
}

@AppStorage("isSecondOpen") public var isSecondOpen = true {
@AppStorage("isSecondOpen")
public var isSecondOpen = true {
didSet {
KSOptions.isSecondOpen = isSecondOpen
}
}

@AppStorage("isAccurateSeek") public var isAccurateSeek = true {
@AppStorage("isAccurateSeek")
public var isAccurateSeek = true {
didSet {
KSOptions.isAccurateSeek = isAccurateSeek
}
}

@AppStorage("isPipPopViewController") public var isPipPopViewController = true {
@AppStorage("isPipPopViewController")
public var isPipPopViewController = true {
didSet {
KSOptions.isPipPopViewController = isPipPopViewController
}
}

@AppStorage("textFontSize") public var textFontSize = SubtitleModel.textFontSize {
@AppStorage("textFontSize")
public var textFontSize = SubtitleModel.textFontSize {
didSet {
SubtitleModel.textFontSize = textFontSize
}
}

@AppStorage("textBold") public var textBold = SubtitleModel.textBold {
@AppStorage("textBold")
public var textBold = SubtitleModel.textBold {
didSet {
SubtitleModel.textBold = textBold
}
}

@AppStorage("textItalic") public var textItalic = SubtitleModel.textItalic {
@AppStorage("textItalic")
public var textItalic = SubtitleModel.textItalic {
didSet {
SubtitleModel.textItalic = textItalic
}
}

@AppStorage("textColor") public var textColor = SubtitleModel.textColor {
@AppStorage("textColor")
public var textColor = SubtitleModel.textColor {
didSet {
SubtitleModel.textColor = textColor
}
}

@AppStorage("textBackgroundColor") public var textBackgroundColor = SubtitleModel.textBackgroundColor {
@AppStorage("textBackgroundColor")
public var textBackgroundColor = SubtitleModel.textBackgroundColor {
didSet {
SubtitleModel.textBackgroundColor = textBackgroundColor
}
Expand Down Expand Up @@ -164,9 +173,15 @@ public class Defaults: ObservableObject {
}
}

@AppStorage("audioPlayerType")
public var audioPlayerType = NSStringFromClass(KSOptions.audioPlayerType) {
didSet {
KSOptions.audioPlayerType = NSClassFromString(audioPlayerType) as! any AudioOutput.Type
}
}

public static let shared = Defaults()
private init() {
KSOptions.isUseAudioRenderer = isUseAudioRenderer
KSOptions.hardwareDecode = hardwareDecode
MEOptions.isUseDisplayLayer = isUseDisplayLayer
SubtitleModel.textFontSize = textFontSize
Expand All @@ -188,6 +203,7 @@ public class Defaults: ObservableObject {
KSOptions.isAccurateSeek = isAccurateSeek
KSOptions.isPipPopViewController = isPipPopViewController
MEOptions.yadifMode = yadifMode
KSOptions.audioPlayerType = NSClassFromString(audioPlayerType) as! any AudioOutput.Type
}
}

Expand Down
11 changes: 8 additions & 3 deletions Demo/SwiftUI/Shared/SettingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,17 @@ struct SettingGeneralView: View {
}

struct SettingAudioView: View {
@Default(\.isUseAudioRenderer)
private var isUseAudioRenderer
@Default(\.audioPlayerType)
private var audioPlayerType
init() {}
var body: some View {
Form {
Toggle("Use Audio Renderer", isOn: $isUseAudioRenderer)
Picker("audio Player Type", selection: $audioPlayerType) {
Text("AUGraph").tag(NSStringFromClass(AudioGraphPlayer.self))
Text("AudioUnit").tag(NSStringFromClass(AudioUnitPlayer.self))
Text("AVAudioEngine").tag(NSStringFromClass(AudioEnginePlayer.self))
Text("AVSampleBufferAudioRenderer").tag(NSStringFromClass(AudioRendererPlayer.self))
}
}
}
}
Expand Down
5 changes: 2 additions & 3 deletions Sources/KSPlayer/AVPlayer/KSOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@ open class KSOptions {
// audio
public var audioFilters = [String]()
public var syncDecodeAudio = false
/// true: AVSampleBufferAudioRenderer false: AVAudioEngine
public var isUseAudioRenderer = KSOptions.isUseAudioRenderer
// Locale(identifier: "en-US") Locale(identifier: "zh-CN")
public var audioLocale: Locale?
// sutile
Expand Down Expand Up @@ -496,14 +494,15 @@ public extension KSOptions {
}
}

static func outputNumberOfChannels(channelCount: AVAudioChannelCount, isUseAudioRenderer: Bool) -> AVAudioChannelCount {
static func outputNumberOfChannels(channelCount: AVAudioChannelCount) -> AVAudioChannelCount {
let maximumOutputNumberOfChannels = AVAudioChannelCount(AVAudioSession.sharedInstance().maximumOutputNumberOfChannels)
let preferredOutputNumberOfChannels = AVAudioChannelCount(AVAudioSession.sharedInstance().preferredOutputNumberOfChannels)
KSLog("[audio] maximumOutputNumberOfChannels: \(maximumOutputNumberOfChannels)")
KSLog("[audio] preferredOutputNumberOfChannels: \(preferredOutputNumberOfChannels)")
setAudioSession()
let isSpatialAudioEnabled = isSpatialAudioEnabled()
KSLog("[audio] isSpatialAudioEnabled: \(isSpatialAudioEnabled)")
let isUseAudioRenderer = KSOptions.audioPlayerType == AudioRendererPlayer.self
KSLog("[audio] isUseAudioRenderer: \(isUseAudioRenderer)")
var channelCount = channelCount
if channelCount > 2 {
Expand Down
4 changes: 4 additions & 0 deletions Sources/KSPlayer/MEPlayer/AVFoundationExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ extension AVAudioChannelLayout {
KSLog("[audio] out mask: \(outChannel.u.mask) nb_channels: \(outChannel.nb_channels)")
return outChannel
}

public var channelDescriptions: String {
"tag: \(layoutTag), channelDescriptions: \(layout.channelDescriptions)"
}
}

extension AVAudioFormat {
Expand Down
3 changes: 1 addition & 2 deletions Sources/KSPlayer/MEPlayer/AudioEnginePlayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,7 @@ public final class AudioEnginePlayer: AudioOutput {
sourceNodeAudioFormat = audioFormat
KSLog("[audio] outputFormat AudioFormat: \(audioFormat)")
if let channelLayout = audioFormat.channelLayout {
KSLog("[audio] outputFormat tag: \(channelLayout.layoutTag)")
KSLog("[audio] outputFormat channelDescriptions: \(channelLayout.layout.channelDescriptions)")
KSLog("[audio] outputFormat channelLayout \(channelLayout.channelDescriptions)")
}
let isRunning = engine.isRunning
engine.stop()
Expand Down
29 changes: 20 additions & 9 deletions Sources/KSPlayer/MEPlayer/AudioGraphPlayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,13 @@ public final class AudioGraphPlayer: AudioOutput {
AUGraphNodeInfo(graph, nodeForDynamicsProcessor, &descriptionForDynamicsProcessor, &audioUnitForDynamicsProcessor)
AUGraphNodeInfo(graph, nodeForMixer, &descriptionForMixer, &audioUnitForMixer)
AUGraphNodeInfo(graph, nodeForOutput, &descriptionForOutput, &audioUnitForOutput)
var inputCallbackStruct = renderCallbackStruct()
AUGraphSetNodeInputCallback(graph, nodeForTimePitch, 0, &inputCallbackStruct)
addRenderNotify(audioUnit: audioUnitForOutput)
var value = UInt32(1)
AudioUnitSetProperty(audioUnitForTimePitch,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Output, 0,
&value,
UInt32(MemoryLayout<UInt32>.size))
}

public func prepare(audioFormat: AVAudioFormat) {
Expand All @@ -205,27 +209,34 @@ public final class AudioGraphPlayer: AudioOutput {
sampleSize = audioFormat.sampleSize
var audioStreamBasicDescription = audioFormat.formatDescription.audioStreamBasicDescription
let audioStreamBasicDescriptionSize = UInt32(MemoryLayout<AudioStreamBasicDescription>.size)
var audioPlayerMaximumFramesPerSlice = AVAudioFrameCount(4096)
let inDataSize = UInt32(MemoryLayout.size(ofValue: audioPlayerMaximumFramesPerSlice))
let channelLayout = audioFormat.channelLayout?.layout
[audioUnitForTimePitch, audioUnitForDynamicsProcessor, audioUnitForMixer, audioUnitForOutput].forEach { unit in
guard let unit else { return }
AudioUnitSetProperty(unit,
kAudioUnitProperty_MaximumFramesPerSlice,
kAudioUnitScope_Global, 0,
&audioPlayerMaximumFramesPerSlice,
inDataSize)
AudioUnitSetProperty(unit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input, 0,
&audioStreamBasicDescription,
audioStreamBasicDescriptionSize)
AudioUnitSetProperty(unit,
kAudioUnitProperty_AudioChannelLayout,
kAudioUnitScope_Input, 0,
channelLayout,
UInt32(MemoryLayout<AudioChannelLayout>.size))
if unit != audioUnitForOutput {
AudioUnitSetProperty(unit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output, 0,
&audioStreamBasicDescription,
audioStreamBasicDescriptionSize)
}
if unit == audioUnitForTimePitch {
var inputCallbackStruct = renderCallbackStruct()
AudioUnitSetProperty(unit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input, 0,
&inputCallbackStruct,
UInt32(MemoryLayout<AURenderCallbackStruct>.size))
}
}
AUGraphInitialize(graph)
}
Expand Down
Loading

0 comments on commit 24f065d

Please sign in to comment.