using Godot; using System; namespace AudioEditor; public partial class Waveform : Control { private WaveformInfo _waveform; public void SetWaveformInfo(WaveformInfo waveform) { _waveform = waveform; QueueRedraw(); } public override void _Draw() { if (_waveform == null) return; base._Draw(); int width = (int)Size.X; int height = (int)Size.Y; // Downsample the waveform to get a reasonable number of peaks to draw float[] averagePeaks = DownsampleToAveragePeaks(_waveform.Samples, width, _waveform.SampleRate); // Begin drawing the waveform for (int i = 0; i < width; i++) { float averagePeak = averagePeaks[i]; // Normalize the average peak to fit within the height of the control int y = (int)(averagePeak * height / 2); // Drawing the line in the positive and negative direction from the center DrawLine(new Vector2(i, height / 2 - y), new Vector2(i, height / 2 + y), new Color(1, 1, 1, 0.7f)); // White with transparency } } private float[] DownsampleToAveragePeaks(float[] samples, int targetWidth, int sampleRate) { int totalSamples = samples.Length; float durationInSeconds = totalSamples / (float)sampleRate; // Calculate the total duration in seconds int stepSize = totalSamples / targetWidth; // Larger chunks for downsampling // If stepSize is 0 (due to rounding), default to 1 to prevent division by zero if (stepSize == 0) stepSize = 1; float[] averagePeaks = new float[targetWidth]; for (int i = 0; i < targetWidth; i++) { int startIndex = i * stepSize; int endIndex = Math.Min(startIndex + stepSize, totalSamples); // Calculate the average or peak for this window (you can use GetPeak if needed) averagePeaks[i] = GetAverage(samples, startIndex, endIndex); } return averagePeaks; } // Get the average value of samples in the current window private float GetAverage(float[] samples, int startIndex, int endIndex) { float sum = 0f; int count = 0; for (int i = startIndex; i < endIndex; i++) { sum += Math.Abs(samples[i]); // Use absolute values for consistency count++; } return count > 0 ? sum / count : 0f; } // Optional: You could use this method if you prefer showing the peak values private float GetPeak(float[] samples, int startIndex, int endIndex) { float maxPeak = 0f; for (int i = startIndex; i < endIndex; i++) { maxPeak = Math.Max(maxPeak, Math.Abs(samples[i])); } return maxPeak; } // This can be an alternative to GetAverage if you want to show average peak private float GetAveragePeak(float[] samples, int startIndex, int endIndex) { float sum = 0f; int count = 0; for (int i = startIndex; i < endIndex; i++) { sum += Math.Abs(samples[i]); // Use absolute value for a more stable peak count++; } return count > 0 ? sum / count : 0f; // Return the average } }