int[] AudioQueueBufferToDoubleArray(AudioQueueBuffer audioQueueBuffer) { var audioData = new int[audioQueueBuffer.PacketDescriptionCount]; Marshal.Copy(audioQueueBuffer.AudioData, audioData, 0, audioQueueBuffer.PacketDescriptionCount); return(audioData); }
private void ProcessBuffer(AudioQueueBuffer buffer) { Log.Debug(TAG, "AudioQueueBuffer size:" + buffer.AudioDataByteSize); if (buffer.AudioDataByteSize > 0) { var soundData = new byte[buffer.AudioDataByteSize]; System.Runtime.InteropServices.Marshal.Copy(buffer.AudioData, soundData, 0, (int)buffer.AudioDataByteSize); if (outputAudioStream != null) { outputAudioStream.Write(soundData, 0, soundData.Length); vad.ProcessBufferEx(soundData, soundData.Length); } } }
unsafe static void HandleOutput (AudioFile audioFile, AudioQueue queue, AudioQueueBuffer *audioQueueBuffer, ref int packetsToRead, ref long currentPacket, ref bool done, ref bool flushed, ref AudioStreamPacketDescription [] packetDescriptions) { int bytes; int packets; if (done) return; packets = packetsToRead; bytes = (int) audioQueueBuffer->AudioDataBytesCapacity; packetDescriptions = audioFile.ReadPacketData (false, currentPacket, ref packets, audioQueueBuffer->AudioData, ref bytes); if (packets > 0) { audioQueueBuffer->AudioDataByteSize = (uint) bytes; queue.EnqueueBuffer (audioQueueBuffer, packetDescriptions); currentPacket += packets; } else { if (!flushed) { queue.Flush (); flushed = true; } queue.Stop (false); done = true; } }
// // Simple tone generator // void GenerateTone(AudioQueueBuffer*buffer) { // Make the buffer length a multiple of the wavelength for the output frequency. uint sampleCount = buffer->AudioDataBytesCapacity / 2; double bufferLength = sampleCount; double wavelength = sampleRate / outputFrequency; double repetitions = Math.Floor(bufferLength / wavelength); if (repetitions > 0) sampleCount = (uint)Math.Round(wavelength * repetitions); double x, y; double sd = 1.0 / sampleRate; double amp = 0.9; double max16bit = Int16.MaxValue; int i; short* p = (short*)buffer->AudioData; for (i = 0; i < sampleCount; i++) { x = i * sd * outputFrequency; switch (outputWaveForm) { case WaveForm.Sine: y = Math.Sin(x * 2.0 * Math.PI); break; case WaveForm.Triangle: x = x % 1.0; if (x < 0.25) y = x * 4.0; // up 0.0 to 1.0 else if (x < 0.75) y = (1.0 - x) * 4.0 - 2.0; // down 1.0 to -1.0 else y = (x - 1.0) * 4.0; // up -1.0 to 0.0 break; case WaveForm.Sawtooth: y = 0.8 - (x % 1.0) * 1.8; break; case WaveForm.Square: y = ((x % 1.0) < 0.5) ? 0.7 : -0.7; break; default: y = 0; break; } p[i] = (short)(y * max16bit * amp); } buffer->AudioDataByteSize = sampleCount * 2; }
// THIS HAPPENS ON ANOTHER THREAD unsafe bool HandleOutputBuffer(AudioQueueBuffer* buffer, bool priming) { uint numBytesReadFromFile; uint numPackets; if(!ReadFileIntoBuffer(buffer, out numBytesReadFromFile, out numPackets)) return false; // ERROR if(loop && numPackets == 0) { currentPacket = 0; // Restart from beginning if(!ReadFileIntoBuffer(buffer, out numBytesReadFromFile, out numPackets)) return false; // ERROR } if(numPackets > 0) // have we recieved data? { buffer->AudioDataByteSize = numBytesReadFromFile; AudioQueueStatus status = AudioQueueEnqueueBuffer(queue.Handle, new IntPtr(buffer), (packetDescriptionArray != IntPtr.Zero ? numPackets : 0), packetDescriptionArray); currentPacket += numPackets; } else { if(!priming) // Stop the queue (if priming - queue isn't running anyway) queue.Stop(false); return false; // No audio remains } return true; // More audio available }
unsafe private bool ReadFileIntoBuffer(AudioQueueBuffer* buffer, out uint numBytesReadFromFile, out uint numPackets) { numBytesReadFromFile = 0; numPackets = (uint)soundEffect.packetsToRead; if(AudioFileReadPackets(audioFile.Handle, false, ref numBytesReadFromFile, packetDescriptionArray, currentPacket, ref numPackets, buffer->AudioData) != 0) { // An error occured queue.Stop(false); return false; } return true; }