WIP: waveform visualization
This commit is contained in:
88
Source/AudioFileAnalyzer.cs
Normal file
88
Source/AudioFileAnalyzer.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Godot;
|
||||
using NAudio.Wave;
|
||||
|
||||
namespace AudioEditor;
|
||||
|
||||
public partial class AudioFileAnalyzer : Node
|
||||
{
|
||||
public static AudioFileAnalyzer Instance { get; private set; }
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
base._Ready();
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
public void AnalyzeFile(string path, out WaveformInfo waveformInfo)
|
||||
{
|
||||
waveformInfo = new();
|
||||
|
||||
if (_waveformInfoCache.ContainsKey(path))
|
||||
{
|
||||
waveformInfo = _waveformInfoCache[path];
|
||||
return;
|
||||
}
|
||||
|
||||
var ext = Path.GetExtension(path);
|
||||
|
||||
switch (ext)
|
||||
{
|
||||
case ".wav":
|
||||
GD.Print("Analyzing a WAV file...");
|
||||
AnalyzeWav(path, out waveformInfo);
|
||||
break;
|
||||
default:
|
||||
GD.Print($"Format {ext} is not supported!");
|
||||
break;
|
||||
}
|
||||
|
||||
_waveformInfoCache.Add(path, waveformInfo);
|
||||
}
|
||||
|
||||
public bool TryGetFromCache(string path, out WaveformInfo waveformInfo)
|
||||
{
|
||||
return _waveformInfoCache.TryGetValue(path, out waveformInfo);
|
||||
}
|
||||
|
||||
private void AnalyzeWav(string path, out WaveformInfo waveformInfo)
|
||||
{
|
||||
waveformInfo = new WaveformInfo();
|
||||
using (var reader = new WaveFileReader(path))
|
||||
{
|
||||
waveformInfo.Length = reader.TotalTime;
|
||||
waveformInfo.SampleRate = reader.WaveFormat.SampleRate;
|
||||
|
||||
long sampleCount = reader.Length / reader.WaveFormat.BlockAlign;
|
||||
waveformInfo.Samples = new float[sampleCount];
|
||||
|
||||
// Render the waveform
|
||||
byte[] buffer = new byte[reader.WaveFormat.BlockAlign];
|
||||
for (int i = 0; i < sampleCount; i++)
|
||||
{
|
||||
int sampleIndex = i * reader.WaveFormat.BlockAlign;
|
||||
while (reader.Position < reader.Length)
|
||||
{
|
||||
// Read the raw bytes for the current sample
|
||||
reader.Read(buffer, 0, buffer.Length);
|
||||
|
||||
// Convert the byte array to a 16-bit sample (assuming 16-bit PCM)
|
||||
short sample = BitConverter.ToInt16(buffer, 0); // Assuming 16-bit signed samples
|
||||
|
||||
waveformInfo.Samples[sampleIndex++] = (float)sample / short.MaxValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<string, WaveformInfo> _waveformInfoCache = new();
|
||||
}
|
||||
|
||||
public class WaveformInfo
|
||||
{
|
||||
public int SampleRate { get; set; }
|
||||
public TimeSpan Length { get; set; }
|
||||
public float[] Samples { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user