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

88 lines
2.5 KiB
C#

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