Recording with AudioQueue and Monotouch static sound

不打扰是莪最后的温柔 提交于 2019-12-19 21:49:23

问题


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

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

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

回答1:


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

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.

Best regards

Alex



来源:https://stackoverflow.com/questions/13002449/recording-with-audioqueue-and-monotouch-static-sound

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!