2016-07-21 3 views
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의 문제와 비슷하지만 아무도 대답하지 않았습니다.

도움이 될 것입니다.

답변

0

출력 콜백에서 새로운 오디오 데이터 집합을 생성하지 않았습니다. 여기서 새 버퍼의 첫 번째 샘플 단계는 이전 버퍼의 마지막 샘플 증가분입니다.

+0

나는 이것이 문제가 될 수 있다고 생각했지만,이 로그는 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. 보시다시피 단계가 정확합니다. –