101 lines
3.2 KiB
C#
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
|
|
}
|
|
} |