11import Accelerate
22import AVFoundation
33
4- private let kIOAudioMixerTrack_frameCapacity : AVAudioFrameCount = 1024
4+ private let kAudioMixerTrack_frameCapacity : AVAudioFrameCount = 1024
55
66protocol AudioMixerTrackDelegate : AnyObject {
77 func track( _ track: AudioMixerTrack < Self > , didOutput audioPCMBuffer: AVAudioPCMBuffer , when: AVAudioTime )
88 func track( _ track: AudioMixerTrack < Self > , errorOccurred error: AudioMixerError )
99}
1010
11- /// Constraints on the audio mixier track's settings.
12- public struct AudioMixerTrackSettings : Codable , Sendable {
13- /// The default value.
14- public static let `default` = AudioMixerTrackSettings ( )
15-
16- /// Specifies the volume for output.
17- public var volume : Float
18-
19- /// Specifies the muted that indicates whether the audio output is muted.
20- public var isMuted = false
21-
22- /// Specifies the mixes the channels or not. Currently, it supports input sources with 4, 5, 6, and 8 channels.
23- public var downmix = true
24-
25- /// Specifies the map of the output to input channels.
26- /// ## Example code:
27- /// ```
28- /// // If you want to use the 3rd and 4th channels from a 4-channel input source for a 2-channel output, you would specify it like this.
29- /// channelMap = [2, 3]
30- /// ```
31- public var channelMap : [ Int ] ?
32-
33- /// Creates a new instance.
34- public init ( volume: Float = 1.0 , isMuted: Bool = false , downmix: Bool = true , channelMap: [ Int ] ? = nil ) {
35- self . volume = volume
36- self . isMuted = isMuted
37- self . downmix = downmix
38- self . channelMap = channelMap
39- }
40-
41- func apply( _ converter: AVAudioConverter ? , oldValue: AudioMixerTrackSettings ? ) {
42- guard let converter else {
43- return
44- }
45- if converter. downmix != downmix {
46- converter. downmix = downmix
47- }
48- if let channelMap = validatedChannelMap ( converter) {
49- converter. channelMap = channelMap. map { NSNumber ( value: $0) }
50- } else {
51- switch converter. outputFormat. channelCount {
52- case 1 :
53- converter. channelMap = [ 0 ]
54- case 2 :
55- converter. channelMap = ( converter. inputFormat. channelCount == 1 ) ? [ 0 , 0 ] : [ 0 , 1 ]
56- default :
57- break
58- }
59- }
60- }
61-
62- private func validatedChannelMap( _ converter: AVAudioConverter ) -> [ Int ] ? {
63- guard let channelMap, channelMap. count == converter. outputFormat. channelCount else {
64- return nil
65- }
66- for inputChannel in channelMap where converter. inputFormat. channelCount <= inputChannel {
67- return nil
68- }
69- return channelMap
70- }
71- }
72-
7311final class AudioMixerTrack < T: AudioMixerTrackDelegate > {
7412 let id : UInt8
7513 let outputFormat : AVAudioFormat
76-
14+ weak var delegate : T ?
7715 var settings : AudioMixerTrackSettings = . init( ) {
7816 didSet {
7917 settings. apply ( audioConverter, oldValue: oldValue)
8018 }
8119 }
82- weak var delegate : T ?
83-
8420 var inputFormat : AVAudioFormat ? {
8521 return audioConverter? . inputFormat
8622 }
@@ -101,7 +37,19 @@ final class AudioMixerTrack<T: AudioMixerTrackDelegate> {
10137 guard let audioConverter else {
10238 return
10339 }
104- settings. apply ( audioConverter, oldValue: nil )
40+ audioConverter. downmix = settings. downmix
41+ if let channelMap = settings. validatedChannelMap ( audioConverter) {
42+ audioConverter. channelMap = channelMap. map { NSNumber ( value: $0) }
43+ } else {
44+ switch audioConverter. outputFormat. channelCount {
45+ case 1 :
46+ audioConverter. channelMap = [ 0 ]
47+ case 2 :
48+ audioConverter. channelMap = ( audioConverter. inputFormat. channelCount == 1 ) ? [ 0 , 0 ] : [ 0 , 1 ]
49+ default :
50+ break
51+ }
52+ }
10553 audioConverter. primeMethod = . normal
10654 }
10755 }
@@ -167,9 +115,9 @@ final class AudioMixerTrack<T: AudioMixerTrackDelegate> {
167115 delegate? . track ( self , errorOccurred: . failedToCreate( from: inputFormat, to: outputFormat) )
168116 return
169117 }
170- inputBuffer = . init( pcmFormat: inputFormat, frameCapacity: 1024 * 4 )
171118 ringBuffer = . init( inputFormat)
172- outputBuffer = . init( pcmFormat: outputFormat, frameCapacity: kIOAudioMixerTrack_frameCapacity)
119+ inputBuffer = . init( pcmFormat: inputFormat, frameCapacity: kAudioMixerTrack_frameCapacity * 4 )
120+ outputBuffer = . init( pcmFormat: outputFormat, frameCapacity: kAudioMixerTrack_frameCapacity)
173121 if logger. isEnabledFor ( level: . info) {
174122 logger. info ( " inputFormat: " , inputFormat, " , outputFormat: " , outputFormat)
175123 }
0 commit comments