1
Core Audio AudioQueue (Swift 3)를 사용하여 순수한 사인파를 재생하려고합니다.AudioQueueBuffers 간 팝업 노이즈
잘 재생되지만 오디오 데이터가있는 새 버퍼를 채우기 위해 AudioQueueOutputCallback이 호출 될 때마다 소리가 들립니다.
내 AudioStreamer 클래스는 다음과 같습니다
func generateAudioData(frequency: Double) {
semaphore.wait()
let amplitude: Double = 0.25
let theta_increment: Double = 2.0 * M_PI * frequency/sampleRate
for j in 0 ..< Int(bufferSize) {
audioData[j] = Float(sin(theta) * amplitude)
theta += theta_increment
if theta > 2.0 * M_PI {
theta -= 2.0 * M_PI
}
}
}
:
가와의 ViewController 클래스의let kNumberBuffers = 3
protocol AudioStreamerDelegate {
func requestAudioData() -> [Float]
}
let sampleRate = 48000.0
let bufferSize = Int(sampleRate)/50
let bufferByteSize = UInt32(bufferSize * sizeof(Float)) // 20 mili sec of audio
class AudioStreamer {
var delegate: AudioStreamerDelegate
var outputQueue: AudioQueueRef?
var buffers = [AudioQueueBufferRef?](repeatElement(nil, count: kNumberBuffers))
var streamBasicDescription = AudioStreamBasicDescription(
mSampleRate: sampleRate,
mFormatID: kAudioFormatLinearPCM,
mFormatFlags: kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved,
mBytesPerPacket: UInt32(sizeof(Float)),
mFramesPerPacket: 1,
mBytesPerFrame: UInt32(sizeof(Float)),
mChannelsPerFrame: 1,
mBitsPerChannel: UInt32(8 * sizeof(Float)),
mReserved: 0
)
init(delegate: AudioStreamerDelegate) {
// create new output audio queue
self.delegate = delegate
}
func play() {
let queue = DispatchQueue.main
queue.async(execute: {
let selfPointer = unsafeBitCast(self, to: UnsafeMutablePointer<Void>.self)
AudioQueueNewOutput(
&self.streamBasicDescription,
AudioStreamerOuputCallback,
selfPointer,
nil,
nil,
0,
&self.outputQueue
)
// allocate buffers
for i in 0 ..< kNumberBuffers {
AudioQueueAllocateBuffer(
self.outputQueue!,
bufferByteSize,
&self.buffers[i]
)
if let bufferRef = self.buffers[i] {
// configure audio buffer
let selfPointer = unsafeBitCast(self, to: UnsafeMutablePointer<Void>.self)
bufferRef.pointee.mUserData = selfPointer
bufferRef.pointee.mAudioDataByteSize = bufferByteSize
}
}
AudioQueuePrime(self.outputQueue!, 0, nil)
for bufferRef in self.buffers {
AudioStreamerOuputCallback(userData: unsafeBitCast(self, to: UnsafeMutablePointer<Void>.self), queueRef: self.outputQueue!, buffer: bufferRef!)
}
AudioQueueStart(self.outputQueue!, nil)
})
}
}
func AudioStreamerOuputCallback(userData: Optional<UnsafeMutablePointer<Void>>, queueRef: AudioQueueRef, buffer: AudioQueueBufferRef) {
let this = Unmanaged<AudioStreamer>.fromOpaque(OpaquePointer(userData!)).takeUnretainedValue()
let audioData = this.delegate.requestAudioData()
memcpy(buffer.pointee.mAudioData, unsafeBitCast(audioData, to: UnsafeMutablePointer<Void>.self), Int(bufferByteSize))
AudioQueueEnqueueBuffer(queueRef, buffer, 0, nil)
}
오디오 데이터 생성 방법 단지는 (세타가의 ViewController에 저장된 속성입니다) 버튼을 "재생" 문제는 this question의 문제와 비슷하지만 아무도 대답하지 않았습니다.
도움이 될 것입니다.
나는 이것이 문제가 될 수 있다고 생각했지만,이 로그는 las 버퍼의 마지막 4 개 샘플과 현재 1 번째 샘플을 보여줍니다 : -0.051978 - 957 - -0.039109 958 - -0.026132 959 - -0.013084 0 - 0.000000 1 - 0.013084 2 - 0.026132 3 - 0.039109. 보시다시피 단계가 정확합니다. –