private static Bitmap DrawSpectrogram(int nfft, double[] samples, Fourier f, Color[] palette) { const int overlap = 0; int numSamples = samples.Length; int colIncrement = nfft * (1 - overlap); int numcols = numSamples / colIncrement; // make sure we don't step beyond the end of the recording while ((numcols - 1) * colIncrement + nfft > numSamples) { numcols--; } double[] real = new double[nfft]; double[] imag = new double[nfft]; double[] magnitude = new double[nfft / 2]; var bmp = new Bitmap(numcols, nfft / 2); for (int col = 0; col <= numcols - 1; col++) { // read a segment of the recorded signal for (int c = 0; c <= nfft - 1; c++) { imag[c] = 0; real[c] = samples[col * colIncrement + c] * Fourier.Hanning(nfft, c); } // transform to the frequency domain f.FourierTransform(real, imag); // and compute the magnitude spectrum f.MagnitudeSpectrum(real, imag, Fourier.W0Hanning, magnitude); // Draw for (int newY = 0; newY < nfft / 2 - 1; newY++) { int colorIndex = MapToPixelIndex(magnitude[newY], 100, 255); bmp.SetPixel(col, (nfft / 2 - 1) - newY, palette[colorIndex]); } } return(bmp); }
private Bitmap DrawSpectrogram(int nfft, double[] samples, Fourier f, Color[] palette) { const int overlap = 0; int numSamples = samples.Length; int colIncrement = nfft * (1 - overlap); int numcols = numSamples / colIncrement; // make sure we don't step beyond the end of the recording while ((numcols - 1) * colIncrement + nfft > numSamples) numcols--; double[] real = new double[nfft]; double[] imag = new double[nfft]; double[] magnitude = new double[nfft / 2]; var bmp = new Bitmap(numcols, nfft / 2); for (int col = 0; col <= numcols - 1; col++) { // read a segment of the recorded signal for (int c = 0; c <= nfft - 1; c++) { imag[c] = 0; real[c] = samples[col * colIncrement + c] * Fourier.Hanning(nfft, c); } // transform to the frequency domain f.FourierTransform(real, imag); // and compute the magnitude spectrum f.MagnitudeSpectrum(real, imag, Fourier.W0Hanning, magnitude); // Draw for (int newY = 0; newY < nfft / 2 - 1; newY++) { int colorIndex = MapToPixelIndex(magnitude[newY], 100, 255); bmp.SetPixel(col, (nfft / 2 - 1) - newY, palette[colorIndex]); } } return bmp; }
//////////////////////////////////////// SPECTRUM /////////////////////////////////////////////////////////// public List<Bitmap> GenerateFourierData(int nfft, string spectrogramDirectory, int delayInMilliseconds) { const int bitmapWidth = 1024; var bitmaps = new List<Bitmap>(); // setup fourier transformation var f = new Fourier(nfft, true); double divider = 2.0; for (int k = 0; k < Header.BitsPerSample - 2; k++) divider *= 2; // determine how to read sample values ReadSampleDataValueDelegate readSampleDataValue = GetSampleDataRerader(); // set up one column of the spectrogram var palette = new Color[nfft]; if (Configuration.Settings.VideoControls.SpectrogramAppearance == "Classic") { for (int colorIndex = 0; colorIndex < nfft; colorIndex++) palette[colorIndex] = PaletteValue(colorIndex, nfft); } else { var list = SmoothColors(0, 0, 0, Configuration.Settings.VideoControls.WaveFormColor.R, Configuration.Settings.VideoControls.WaveFormColor.G, Configuration.Settings.VideoControls.WaveFormColor.B, nfft); for (int i = 0; i < nfft; i++) palette[i] = list[i]; } // read sample values DataMinValue = int.MaxValue; DataMaxValue = int.MinValue; var samples = new List<int>(); int index = 0; int sampleSize = nfft * bitmapWidth; int count = 0; long totalSamples = 0; // write delay (if any) int delaySampleCount = (int) (Header.SampleRate * (delayInMilliseconds / 1000.0)); for (int i = 0; i < delaySampleCount; i++) { samples.Add(0); if (samples.Count == sampleSize) { var samplesAsReal = new double[sampleSize]; for (int k = 0; k < sampleSize; k++) samplesAsReal[k] = 0; var bmp = DrawSpectrogram(nfft, samplesAsReal, f, palette); bmp.Save(Path.Combine(spectrogramDirectory, count + ".gif"), System.Drawing.Imaging.ImageFormat.Gif); bitmaps.Add(bmp); samples = new List<int>(); count++; } } // load data in smaller parts _data = new byte[Header.BytesPerSecond]; _stream.Position = Header.DataStartPosition; int bytesRead = _stream.Read(_data, 0, _data.Length); while (bytesRead == Header.BytesPerSecond) { while (index < Header.BytesPerSecond) { int value = 0; for (int channelNumber = 0; channelNumber < Header.NumberOfChannels; channelNumber++) { value += readSampleDataValue.Invoke(ref index); } value = value / Header.NumberOfChannels; if (value < DataMinValue) DataMinValue = value; if (value > DataMaxValue) DataMaxValue = value; samples.Add(value); totalSamples++; if (samples.Count == sampleSize) { var samplesAsReal = new double[sampleSize]; for (int k = 0; k < sampleSize; k++) samplesAsReal[k] = samples[k] / divider; var bmp = DrawSpectrogram(nfft, samplesAsReal, f, palette); bmp.Save(Path.Combine(spectrogramDirectory, count + ".gif"), System.Drawing.Imaging.ImageFormat.Gif); bitmaps.Add(bmp); samples = new List<int>(); count++; } } bytesRead = _stream.Read(_data, 0, _data.Length); index = 0; } if (samples.Count > 0) { var samplesAsReal = new double[sampleSize]; for (int k = 0; k < sampleSize && k < samples.Count; k++) samplesAsReal[k] = samples[k] / divider; var bmp = DrawSpectrogram(nfft, samplesAsReal, f, palette); bmp.Save(Path.Combine(spectrogramDirectory, count + ".gif"), System.Drawing.Imaging.ImageFormat.Gif); bitmaps.Add(bmp); } var doc = new XmlDocument(); doc.LoadXml("<SpectrogramInfo><SampleDuration/><TotalDuration/><AudioFormat /><AudioFormat /><ChunkId /><SecondsPerImage /><ImageWidth /><NFFT /></SpectrogramInfo>"); double sampleDuration = Header.LengthInSeconds / (totalSamples / Convert.ToDouble(nfft)); doc.DocumentElement.SelectSingleNode("SampleDuration").InnerText = sampleDuration.ToString(CultureInfo.InvariantCulture); doc.DocumentElement.SelectSingleNode("TotalDuration").InnerText = Header.LengthInSeconds.ToString(CultureInfo.InvariantCulture); doc.DocumentElement.SelectSingleNode("AudioFormat").InnerText = Header.AudioFormat.ToString(CultureInfo.InvariantCulture); doc.DocumentElement.SelectSingleNode("ChunkId").InnerText = Header.ChunkId.ToString(CultureInfo.InvariantCulture); doc.DocumentElement.SelectSingleNode("SecondsPerImage").InnerText = ((double)(sampleSize / (double)Header.SampleRate)).ToString(CultureInfo.InvariantCulture); doc.DocumentElement.SelectSingleNode("ImageWidth").InnerText = bitmapWidth.ToString(CultureInfo.InvariantCulture); doc.DocumentElement.SelectSingleNode("NFFT").InnerText = nfft.ToString(CultureInfo.InvariantCulture); doc.Save(Path.Combine(spectrogramDirectory, "Info.xml")); return bitmaps; }
//////////////////////////////////////// SPECTRUM /////////////////////////////////////////////////////////// public List <Bitmap> GenerateFourierData(int nfft, string spectrogramDirectory, int delayInMilliseconds) { const int bitmapWidth = 1024; var bitmaps = new List <Bitmap>(); // setup fourier transformation var f = new Fourier(nfft, true); double divider = 2.0; for (int k = 0; k < Header.BitsPerSample - 2; k++) { divider *= 2; } // determine how to read sample values ReadSampleDataValueDelegate readSampleDataValue = GetSampleDataRerader(); // set up one column of the spectrogram var palette = new Color[nfft]; if (Configuration.Settings.VideoControls.SpectrogramAppearance == "Classic") { for (int colorIndex = 0; colorIndex < nfft; colorIndex++) { palette[colorIndex] = PaletteValue(colorIndex, nfft); } } else { var list = SmoothColors(0, 0, 0, Configuration.Settings.VideoControls.WaveformColor.R, Configuration.Settings.VideoControls.WaveformColor.G, Configuration.Settings.VideoControls.WaveformColor.B, nfft); for (int i = 0; i < nfft; i++) { palette[i] = list[i]; } } // read sample values DataMinValue = int.MaxValue; DataMaxValue = int.MinValue; var samples = new List <int>(); int index = 0; int sampleSize = nfft * bitmapWidth; int count = 0; long totalSamples = 0; // write delay (if any) int delaySampleCount = (int)(Header.SampleRate * (delayInMilliseconds / TimeCode.BaseUnit)); for (int i = 0; i < delaySampleCount; i++) { samples.Add(0); if (samples.Count == sampleSize) { var samplesAsReal = new double[sampleSize]; for (int k = 0; k < sampleSize; k++) { samplesAsReal[k] = 0; } var bmp = DrawSpectrogram(nfft, samplesAsReal, f, palette); bmp.Save(Path.Combine(spectrogramDirectory, count + ".gif"), System.Drawing.Imaging.ImageFormat.Gif); bitmaps.Add(bmp); samples = new List <int>(); count++; } } // load data in smaller parts _data = new byte[Header.BytesPerSecond]; _stream.Position = Header.DataStartPosition; int bytesRead = _stream.Read(_data, 0, _data.Length); while (bytesRead == Header.BytesPerSecond) { while (index < Header.BytesPerSecond) { int value = 0; for (int channelNumber = 0; channelNumber < Header.NumberOfChannels; channelNumber++) { value += readSampleDataValue.Invoke(ref index); } value = value / Header.NumberOfChannels; if (value < DataMinValue) { DataMinValue = value; } if (value > DataMaxValue) { DataMaxValue = value; } samples.Add(value); totalSamples++; if (samples.Count == sampleSize) { var samplesAsReal = new double[sampleSize]; for (int k = 0; k < sampleSize; k++) { samplesAsReal[k] = samples[k] / divider; } var bmp = DrawSpectrogram(nfft, samplesAsReal, f, palette); bmp.Save(Path.Combine(spectrogramDirectory, count + ".gif"), System.Drawing.Imaging.ImageFormat.Gif); bitmaps.Add(bmp); samples = new List <int>(); count++; } } bytesRead = _stream.Read(_data, 0, _data.Length); index = 0; } if (samples.Count > 0) { var samplesAsReal = new double[sampleSize]; for (int k = 0; k < sampleSize && k < samples.Count; k++) { samplesAsReal[k] = samples[k] / divider; } var bmp = DrawSpectrogram(nfft, samplesAsReal, f, palette); bmp.Save(Path.Combine(spectrogramDirectory, count + ".gif"), System.Drawing.Imaging.ImageFormat.Gif); bitmaps.Add(bmp); } var doc = new XmlDocument(); doc.LoadXml("<SpectrogramInfo><SampleDuration/><TotalDuration/><AudioFormat /><AudioFormat /><ChunkId /><SecondsPerImage /><ImageWidth /><NFFT /></SpectrogramInfo>"); double sampleDuration = Header.LengthInSeconds / (totalSamples / Convert.ToDouble(nfft)); doc.DocumentElement.SelectSingleNode("SampleDuration").InnerText = sampleDuration.ToString(CultureInfo.InvariantCulture); doc.DocumentElement.SelectSingleNode("TotalDuration").InnerText = Header.LengthInSeconds.ToString(CultureInfo.InvariantCulture); doc.DocumentElement.SelectSingleNode("AudioFormat").InnerText = Header.AudioFormat.ToString(CultureInfo.InvariantCulture); doc.DocumentElement.SelectSingleNode("ChunkId").InnerText = Header.ChunkId.ToString(CultureInfo.InvariantCulture); doc.DocumentElement.SelectSingleNode("SecondsPerImage").InnerText = ((double)(sampleSize / (double)Header.SampleRate)).ToString(CultureInfo.InvariantCulture); doc.DocumentElement.SelectSingleNode("ImageWidth").InnerText = bitmapWidth.ToString(CultureInfo.InvariantCulture); doc.DocumentElement.SelectSingleNode("NFFT").InnerText = nfft.ToString(CultureInfo.InvariantCulture); doc.Save(Path.Combine(spectrogramDirectory, "Info.xml")); return(bitmaps); }