Files
audioeditor/Source/Waveform.cs
2025-02-17 00:04:42 +01:00

101 lines
3.2 KiB
C#

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
}
}