Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions AudioStreaming/Streaming/AudioPlayer/AudioPlayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,9 @@ open class AudioPlayer {
frameFilterProcessor
}

/// An `AVAudioFormat` object for the canonical audio stream
private var outputAudioFormat: AVAudioFormat = .init(commonFormat: .pcmFormatFloat32, sampleRate: 44100.0, channels: 2, interleaved: true)!
/// An `AVAudioFormat` object for the canonical audio stream.
/// Built from `configuration.outputSampleRate` in `init` and fixed for the player's lifetime.
private let outputAudioFormat: AVAudioFormat

/// Keeps track of the player's state before being paused.
private var stateBeforePaused: InternalState = .initial
Expand Down Expand Up @@ -185,7 +186,13 @@ open class AudioPlayer {

public init(configuration: AudioPlayerConfiguration = .default,
clientCertificateProvider: ClientCertificateProvider? = nil) {
self.configuration = configuration.normalizeValues()
let normalizedConfiguration = configuration.normalizeValues()
self.configuration = normalizedConfiguration
// `normalizeValues` guarantees a positive rate, so this cannot fail.
outputAudioFormat = .init(commonFormat: .pcmFormatFloat32,
sampleRate: normalizedConfiguration.outputSampleRate,
channels: 2,
interleaved: true)!
let engine = AVAudioEngine()
audioEngine = engine
rendererContext = AudioRendererContext(configuration: configuration, outputAudioFormat: outputAudioFormat)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ public struct AudioPlayerConfiguration: Equatable {
/// - note: Must be larger that `bufferSizeInSeconds`
let secondsRequiredToStartPlayingAfterBufferUnderrun: Int

/// The sample rate, in hertz, of the player's output format.
///
/// Decoded audio is converted to this rate before it reaches the engine, so it should match
/// the rate the output hardware is actually running at — on iOS,
/// `AVAudioSession.sharedInstance().sampleRate`. Leaving it at the 44100 default on hardware
/// running at another rate makes the system resample a second time: a 48 kHz source is
/// converted down to 44100 here and back up to 48000 by the output unit.
let outputSampleRate: Double

/// Enables the internal logs
let enableLogs: Bool

Expand All @@ -28,6 +37,7 @@ public struct AudioPlayerConfiguration: Equatable {
secondsRequiredToStartPlaying: 1,
gracePeriodAfterSeekInSeconds: 0.5,
secondsRequiredToStartPlayingAfterBufferUnderrun: 7,
outputSampleRate: 44100,
enableLogs: false)
/// Initializes the configuration for the `AudioPlayer`
///
Expand All @@ -38,20 +48,23 @@ public struct AudioPlayerConfiguration: Equatable {
/// - parameter secondsRequiredToStartPlaying: Number of seconds of audio required to before playback first starts.
/// - parameter gracePeriodAfterSeekInSeconds: Number of seconds of audio required after seek occurs.
/// - parameter secondsRequiredToStartPlayingAfterBufferUnderrun: Number of seconds of audio required to before playback resumes after a buffer underrun
/// - parameter outputSampleRate: Sample rate, in hertz, of the player's output format
/// - parameter enableLogs: Enables the internal logs
///
public init(flushQueueOnSeek: Bool = true,
bufferSizeInSeconds: Double = 10,
secondsRequiredToStartPlaying: Double = 1,
gracePeriodAfterSeekInSeconds: Double = 0.5,
secondsRequiredToStartPlayingAfterBufferUnderrun: Int = 1,
outputSampleRate: Double = 44100,
enableLogs: Bool = true)
{
self.flushQueueOnSeek = flushQueueOnSeek
self.bufferSizeInSeconds = bufferSizeInSeconds
self.secondsRequiredToStartPlaying = secondsRequiredToStartPlaying
self.gracePeriodAfterSeekInSeconds = gracePeriodAfterSeekInSeconds
self.secondsRequiredToStartPlayingAfterBufferUnderrun = secondsRequiredToStartPlayingAfterBufferUnderrun
self.outputSampleRate = outputSampleRate
self.enableLogs = enableLogs
Logger.isEnabled = enableLogs
}
Expand All @@ -76,11 +89,17 @@ public struct AudioPlayerConfiguration: Equatable {
? defaults.secondsRequiredToStartPlayingAfterBufferUnderrun
: self.secondsRequiredToStartPlayingAfterBufferUnderrun

// A non-positive rate would make `AVAudioFormat` fail to initialise.
let outputSampleRate = self.outputSampleRate > 0
? self.outputSampleRate
: defaults.outputSampleRate

return AudioPlayerConfiguration(flushQueueOnSeek: flushQueueOnSeek,
bufferSizeInSeconds: bufferSizeInSeconds,
secondsRequiredToStartPlaying: secondsRequiredToStartPlaying,
gracePeriodAfterSeekInSeconds: gracePeriodAfterSeekInSeconds,
secondsRequiredToStartPlayingAfterBufferUnderrun: secondsRequiredToStartPlayingAfterBufferUnderrun,
outputSampleRate: outputSampleRate,
enableLogs: enableLogs)
}
}