用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);
}
}
答
确定,这可能是太晚了,但我只听到声音的垃圾有同样的问题,并找到了解决办法。
您无法直接从e.IntPtrBuffer读取音频数据。该指针是指向AudioQueueBuffer对象的指针,而不是音频数据本身。因此,要读取音频数据,您可以使用e.UnsafeBuffer,它使您可以访问此对象并使用其AudioData指针。这是一个IntPtr,您可以将它(在不安全的上下文中)转换为byte *或short *并且您有音频数据。
问候
亚历
下面是一个类似的代码示例这可能会帮助您:https://github.com/xamarin/monotouch-samples/tree/master/AudioQueueOfflineRenderDemo。 –
感谢您的回答,但我有问题使用AudioQueue从麦克风获取输入,而不是从文件:-) –