static void ReadCallback(SoundIOInStream instream, int frameCountMin, int frameCountMax) { SoundIORingBuffer ringBuffer = ringBuffers[instream.UserData]; SoundIOChannelAreas areas; SoundIoError err; IntPtr writePtr = ringBuffer.WritePointer; int freeBytes = ringBuffer.FreeCount; int freeCount = freeBytes / instream.BytesPerFrame; if (frameCountMin > freeCount) { throw new SoundIOException("Ring buffer overflow"); } int writeFrames = Math.Min(freeCount, frameCountMax); int framesLeft = writeFrames; while (true) { int frameCount = framesLeft; err = instream.BeginRead(out areas, ref frameCount); if (err != SoundIoError.None) { throw new SoundIOException(string.Format("Begin read error: {0}.", err.GetErrorMessage())); } if (frameCount == 0) { break; } if (areas == null) { // Due to an overflow there is a hole. Fill the ring buffer with // silence for the size of the hole. int count = frameCount * instream.BytesPerFrame; for (int i = 0; i < count; i++) { Marshal.WriteByte(writePtr + i, 0); } } else { int channelCount = instream.Layout.ChannelCount; int bytesPerSample = instream.BytesPerSample; for (int frame = 0; frame < frameCount; frame++) { for (int ch = 0; ch < channelCount; ch++) { unsafe { Buffer.MemoryCopy((void *)areas[ch].Pointer, (void *)writePtr, bytesPerSample, bytesPerSample); } areas[ch].AdvancePointer(); writePtr += bytesPerSample; } } } err = instream.EndRead(); if (err != SoundIoError.None) { throw new SoundIOException(string.Format("End read error: {0}.", err.GetErrorMessage())); } framesLeft -= frameCount; if (framesLeft <= 0) { break; } } int advanceBytes = writeFrames * instream.BytesPerFrame; ringBuffer.AdvanceWritePointer(advanceBytes); }
private unsafe void ReadCallback(int frameCountMin, int frameCountMax) { int writeFrames = frameCountMax; int framesLeft = writeFrames; UnionBuffer unionBuffer = new UnionBuffer(); for (; ;) { int frameCount = framesLeft; var areas = _instream.BeginRead(ref frameCount); if (frameCount == 0) { break; } if (areas.IsEmpty) { // Due to an overflow there is a hole. Fill the ring buffer with // silence for the size of the hole. Console.Error.WriteLine("Dropped {0} frames due to internal overflow", frameCount); } else { for (int frame = 0; frame < frameCount; frame += 1) { int chCount = _instream.Layout.ChannelCount; int copySize = _instream.BytesPerSample; unionBuffer.Bytes = new byte[copySize]; fixed(byte *buffer = unionBuffer.Bytes) { for (int ch = 0; ch < chCount; ch += 1) { var area = areas.GetArea(ch); Buffer.MemoryCopy((void *)area.Pointer, buffer, copySize, copySize); _ringBuffer.Enqueue(unionBuffer.Bytes, 0, copySize); area.Pointer += area.Step; } } } } _instream.EndRead(); framesLeft -= frameCount; if (framesLeft <= 0) { break; } } int length = (int)_ringBuffer.GetLength(); if (length >= FlushCount) { if (_flushBuffer == null || _flushBuffer.Length != length) { _flushBuffer = new byte[length]; } _ringBuffer.Dequeue(_flushBuffer); Filled?.Invoke(this, new FillEventArgs(_flushBuffer, 0, length)); } }
static void read_callback(SoundIOInStream instream, int frame_count_min, int frame_count_max) { var write_ptr = ring_buffer.WritePointer; int free_bytes = ring_buffer.FreeCount; int free_count = free_bytes / instream.BytesPerFrame; if (frame_count_min > free_count) { throw new InvalidOperationException("ring buffer overflow"); // panic() } int write_frames = Math.Min(free_count, frame_count_max); int frames_left = write_frames; for (; ;) { int frame_count = frames_left; var areas = instream.BeginRead(ref frame_count); if (frame_count == 0) { break; } if (areas.IsEmpty) { // Due to an overflow there is a hole. Fill the ring buffer with // silence for the size of the hole. for (int i = 0; i < frame_count * instream.BytesPerFrame; i++) { Marshal.WriteByte(write_ptr + i, 0); } Console.Error.WriteLine("Dropped {0} frames due to internal overflow", frame_count); } else { for (int frame = 0; frame < frame_count; frame += 1) { int chCount = instream.Layout.ChannelCount; int copySize = instream.BytesPerSample; unsafe { for (int ch = 0; ch < chCount; ch += 1) { var area = areas.GetArea(ch); Buffer.MemoryCopy((void *)area.Pointer, (void *)write_ptr, copySize, copySize); area.Pointer += area.Step; write_ptr += copySize; } } } } instream.EndRead(); frames_left -= frame_count; if (frames_left <= 0) { break; } } int advance_bytes = write_frames * instream.BytesPerFrame; ring_buffer.AdvanceWritePointer(advance_bytes); }