public void CalculateScaledData(int scaleFactor, int steps) { int peakSize = 0; unsafe { peakSize = sizeof(Peak); } int previousStepSamplesPerPeak = SamplesPerPeak; for (int step = 1; step <= steps; step++) { int samplesPerPeak = previousStepSamplesPerPeak * scaleFactor; int peaksPerPeak = steps * scaleFactor; byte[][] peakData = step == 1 ? data : scaledData[previousStepSamplesPerPeak]; int downscaledPeakDataLength = (int)Math.Ceiling((float)peakData[0].Length / scaleFactor); if (downscaledPeakDataLength % peakSize != 0) { downscaledPeakDataLength += peakSize - (downscaledPeakDataLength % peakSize); } byte[][] downscaledPeakData = AudioUtil.CreateArray <byte>(peakData.Length, downscaledPeakDataLength); unsafe { // calculate scaled peaks for (int channel = 0; channel < Channels; channel++) { int peakCount = peakData[0].Length / sizeof(Peak); fixed(byte *peaksB = &peakData[channel][0], downscaledPeaksB = &downscaledPeakData[channel][0]) { Peak *peaks = (Peak *)peaksB; Peak *downscaledPeaks = (Peak *)downscaledPeaksB; Peak downscaledPeak = new Peak(float.MaxValue, float.MinValue); int downscaledPeakIndex = 0; for (int p = 0; p < peakCount; p++) { downscaledPeak.Merge(peaks[p]); if ((p > 0 && p % scaleFactor == 0) || p == peakCount - 1) { downscaledPeaks[downscaledPeakIndex++] = downscaledPeak; downscaledPeak = new Peak(float.MaxValue, float.MinValue); } } } } } this.scaledData.Add(samplesPerPeak, downscaledPeakData); previousStepSamplesPerPeak = samplesPerPeak; } }
public int ReadPeaks(float[][] peaks, int sampleCount, int peakCount) { long streamPosition = sourceStream.Position; int samplesPerPeak = (int)Math.Ceiling((float)sampleCount / peakCount); unsafe { // if the samplesPerPeak count is beyond the PeakStore threshold, load the peaks from there if (samplesPerPeak > peakStore.SamplesPerPeak) { byte[][] peakData = peakStore.GetData(samplesPerPeak, out samplesPerPeak); int positionOffset = (int)(streamPosition / SampleBlockSize / samplesPerPeak) * sizeof(Peak); int sourcePeakCount = (int)Math.Round((float)sampleCount / samplesPerPeak); float sourceToTargetIndex = 1 / ((float)sourcePeakCount / peakCount); for (int channel = 0; channel < Properties.Channels; channel++) { fixed(byte *peakChannelDataB = &peakData[channel][positionOffset]) { Peak *peakChannelDataP = (Peak *)peakChannelDataB; fixed(float *peakChannelF = &peaks[channel][0]) { Peak *peakChannelP = (Peak *)peakChannelF; int peak = 0; peakChannelP[0] = new Peak(float.MaxValue, float.MinValue); for (int p = 0; p < sourcePeakCount; p++) { if ((int)(p * sourceToTargetIndex) > peak) { peak++; peakChannelP[peak] = new Peak(float.MaxValue, float.MinValue); } peakChannelP[peak].Merge(peakChannelDataP[p]); } } } } return(peakCount); } // else load samples from the stream and generate peaks int requiredBytes = sampleCount * Properties.SampleBlockByteSize; int bufferOffset = 0; int bytesRead = 0; if (bufferPosition <= sourceStream.Position && sourceStream.Position + requiredBytes <= bufferPosition + bufferLength) { // the requested data can be read directly from the buffer, no need to read from the stream bufferOffset = (int)(sourceStream.Position - bufferPosition); bytesRead = requiredBytes; } else { // resize buffer and read data from stream ResizeBuffer(requiredBytes); bufferPosition = sourceStream.Position; bytesRead = StreamUtil.ForceRead(sourceStream, buffer, 0, requiredBytes); bufferLength = bytesRead; } if (bytesRead % Properties.SampleBlockByteSize != 0) { throw new Exception(); } int samplesRead = bytesRead / Properties.SampleBlockByteSize; float sampleIndexToPeakIndex = 1 / ((float)samplesRead / peakCount); fixed(byte *bufferB = &buffer[bufferOffset]) { float *bufferF = (float *)bufferB; for (int channel = 0; channel < Properties.Channels; channel++) { fixed(float *peakChannelF = &peaks[channel][0]) { Peak *peakChannelP = (Peak *)peakChannelF; int index = channel; int peakIndex = 0; peakChannelP[peakIndex] = new Peak(float.MaxValue, float.MinValue); for (int i = 0; i < samplesRead; i++) { float sampleValue = bufferF[index]; index += Properties.Channels; peakChannelP[peakIndex].Merge(sampleValue, sampleValue); if ((int)(i * sampleIndexToPeakIndex) > peakIndex) { peakChannelP[++peakIndex] = new Peak(sampleValue, sampleValue); } } } } } } return(peakCount); }