使用AudioQueue和Monotouch静音录制 [英] Recording with AudioQueue and Monotouch static sound

查看:167
本文介绍了使用AudioQueue和Monotouch静音录制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have written a small program in MonoTouch to record sound from the mic of my iPhone 4s using an InputAudioQueue.

我将记录的数据保存在数组和提要中这个缓冲区到我的音频播放器进行播放(使用OutputAudioQueue)。

I save the recorded data in an array and feed this buffer to the my audio player for playback (using OutputAudioQueue).

播放时,它只是一些口吃的垃圾/静音。我在播放前尝试用sin波填充缓冲区然后听起来不错,所以我猜问题出在录音中,而不是播放。任何人都可以帮我看看有什么问题吗? (下面的代码)

When playing back it's just some stuttering garbage / static sound. I have tried filling the buffer with sin waves before playback and then it sounds good, so I guess the problem is in the recording, not the playback. Can anyone help me see what is wrong? (Code below)

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);
    }
}


推荐答案

确定,这可能为时已晚,但我在听到垃圾声时遇到了同样的问题并找到了解决方案。

ok, this might be too late, but I had the same problem with hearing garbage sound only and found the solution.

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

You cannot read the audio data directly from e.IntPtrBuffer. This pointer is a pointer to a AudioQueueBuffer object and not to the audio data itself. So to read the audio data you can make use of the e.UnsafeBuffer which gives you the access to this object and use its AudioData pointer. This is a IntPtr which you can cast (in unsafe context) to a byte* or short* and you have your audio data.

祝你好运

Alex

这篇关于使用AudioQueue和Monotouch静音录制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆