public int Convolve(double *src, int srcLength, double *dst, int dstLength) { var input = new UnionBuffer(delayData.Data, delay * Size, (IntPtr)src, srcLength * Size); int kernelLength = kernel.Length, offset = 0, step, copyLength; int outLen = Math.Max(Math.Min(delay + srcLength - (kernelLength - 1), dstLength), 0); IntPtr tempInput; bool fast = fft != null; if (fast) { copyLength = fft.FFTSize; tempInput = fftIn; step = kernelLength + 1; } else { copyLength = FixedStep + kernelLength - 1; tempBuffer.Resize(copyLength * Size); tempInput = tempBuffer.data; step = FixedStep; } for (; outLen >= step; outLen -= step, offset += step) { input.CopyTo(offset * Size, tempInput, copyLength * Size); ConvolveOnce(tempInput, dst + offset, step, fast); } if (outLen > 0) { input.CopyTo(offset * Size, tempInput, (outLen + kernelLength - 1) * Size); ConvolveOnce(tempInput, dst + offset, outLen, fast); offset += outLen; } delay = Math.Min(Math.Max(kernelLength - 1, delay + srcLength - dstLength), delay + srcLength); tempBuffer.Resize(delay * Size); input.CopyTo(offset * Size, tempBuffer.Data, delay * Size); var temp = tempBuffer; tempBuffer = delayData; delayData = temp; return(offset); }
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)); } }