WIP: waveform visualization
This commit is contained in:
101
Source/Waveform.cs
Normal file
101
Source/Waveform.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user