Recording using AudioQueue sound and Monotouch static sound

I wrote a small program in MonoTouch to record the sound from the microphone of my iPhone 4 using InputAudioQueue.

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

When playing just a little stuttering garbage / static sound. I tried to fill the buffer with sin waves before playing, and then it sounds good, so I think the problem is in the recording, not in the playback. Can someone help me figure out 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); } } 
+4
source share
1 answer

ok, it may be too late, but I faced the same problem when I heard the sound of garbage and found a solution.

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

Best wishes

Alex

+3
source

Source: https://habr.com/ru/post/1441158/


All Articles