用AudioQueue和Monotouch静态录音录音

问题描述:

我在MonoTouch中编写了一个小程序,使用InputAudioQueue从我的iPhone 4s的麦克风录制声音。用AudioQueue和Monotouch静态录音录音

我将录制的数据保存在一个数组中,并将此缓冲区提供给我的音频播放器进行播放(使用OutputAudioQueue)。

回放时,它只是一些口吃垃圾/静态声音。我已经尝试在播放之前用正弦波填充缓冲区,然后听起来不错,所以我猜想问题在于录制,而不是播放。任何人都可以帮我看看有什么不对吗? (代码如下所示)

public class AQRecorder 
{ 
    private const int CountAudioBuffers = 3; 
    private const int AudioBufferLength = 22050; 
    private const int SampleRate = 44100; 
    private const int BitsPerChannel = 16; 
    private const int Channels = 1; 
    private const int MaxRecordingTime = 5; 
    private AudioStreamBasicDescription audioStreamDescription; 
    private InputAudioQueue inputQueue; 
    private short[] rawData; 
    private int indexNextRawData; 

    public AQRecorder() 
    { 
     this.audioStreamDescription.Format = AudioFormatType.LinearPCM; 
     this.audioStreamDescription.FormatFlags = AudioFormatFlags.LinearPCMIsSignedInteger | 
                AudioFormatFlags.LinearPCMIsPacked; 
     this.audioStreamDescription.SampleRate = AQRecorder.SampleRate; 
     this.audioStreamDescription.BitsPerChannel = AQRecorder.BitsPerChannel; 
     this.audioStreamDescription.ChannelsPerFrame = AQRecorder.Channels; 
     this.audioStreamDescription.BytesPerFrame = (AQRecorder.BitsPerChannel/8) * AQRecorder.Channels; 
     this.audioStreamDescription.FramesPerPacket = 1; 
     this.audioStreamDescription.BytesPerPacket = audioStreamDescription.BytesPerFrame * audioStreamDescription.FramesPerPacket; 
     this.audioStreamDescription.Reserved = 0; 
    } 

    public void Start() 
    { 
     int totalBytesToRecord = this.audioStreamDescription.BytesPerFrame * AQRecorder.SampleRate * AQRecorder.MaxRecordingTime; 
     this.rawData = new short[totalBytesToRecord/sizeof(short)]; 
     this.indexNextRawData = 0; 
     this.inputQueue = SetupInputQueue (this.audioStreamDescription); 
     this.inputQueue.Start(); 
    } 

    public void Stop() 
    { 
     if (this.inputQueue.IsRunning) 
     { 
      this.inputQueue.Stop (true); 
     } 
    } 

    public short[] GetData() 
    { 
     return this.rawData;; 
    } 

    private InputAudioQueue SetupInputQueue (AudioStreamBasicDescription audioStreamDescription) 
    { 
     InputAudioQueue inputQueue = new InputAudioQueue (audioStreamDescription); 

     for (int count = 0; count < AQRecorder.CountAudioBuffers; count++) 
     { 
      IntPtr bufferPointer; 
      inputQueue.AllocateBuffer(AQRecorder.AudioBufferLength, out bufferPointer); 
      inputQueue.EnqueueBuffer(bufferPointer, AQRecorder.AudioBufferLength, null); 
     } 
     inputQueue.InputCompleted += HandleInputCompleted; 
     return inputQueue; 
    } 

    private void HandleInputCompleted (object sender, InputCompletedEventArgs e) 
    { 
     unsafe 
     { 
      short* shortPtr = (short*)e.IntPtrBuffer; 

      for (int count = 0; count < AQRecorder.AudioBufferLength; count += sizeof(short)) 
      { 
       if (indexNextRawData >= this.rawData.Length) 
       { 
        this.inputQueue.Stop (true); 
        return; 
       } 
       this.rawData [indexNextRawData] = *shortPtr; 
       indexNextRawData++; 
       shortPtr++; 
      } 
     } 
     this.inputQueue.EnqueueBuffer(e.IntPtrBuffer, AQRecorder.AudioBufferLength, null); 
    } 
} 
+1

下面是一个类似的代码示例这可能会帮助您:https://github.com/xamarin/monotouch-samples/tree/master/AudioQueueOfflineRenderDemo。 –

+0

感谢您的回答,但我有问题使用AudioQueue从麦克风获取输入,而不是从文件:-) –

确定,这可能是太晚了,但我只听到声音的垃圾有同样的问题,并找到了解决办法。

您无法直接从e.IntPtrBuffer读取音频数据。该指针是指向AudioQueueBuffer对象的指针,而不是音频数据本身。因此,要读取音频数据,您可以使用e.UnsafeBuffer,它使您可以访问此对象并使用其AudioData指针。这是一个IntPtr,您可以将它(在不安全的上下文中)转换为byte *或short *并且您有音频数据。

问候

亚历

+0

感谢您的回答:-) –

+1

如果它解决了您的问题,您可以将我的答案标记为解决方案你的问题 :)。 – Alex

+0

@BårdM和Alex,你们中的任何一个人可能都会对我的[相关问题]提供见解(http://*.com/questions/21024401/streaming-audio-from-microphone-in-iphone-using-xamarin)? – mrtnkrstn