feat: true RMS dBFS level measurement for LevelMeterFab via getFloatTimeDomainData

This commit is contained in:
daniel-c-harvey
2026-06-08 14:40:11 -04:00
parent 9cbc09edf7
commit 58725c4646
5 changed files with 150 additions and 29 deletions
@@ -243,6 +243,35 @@ public class AudioInteropService : IAsyncDisposable
return await InvokeJsAsync<AudioOperationResult>("DeepDrftAudio.stopSpectrumAnimation", playerId, callbackId);
}
public async Task<AudioOperationResult> StartLevelAnimationAsync(string playerId, string callbackId, Func<double, Task> callback)
{
try
{
var callbackWrapper = new LevelCallback { OnData = callback };
var dotNetObjectRef = DotNetObjectReference.Create(callbackWrapper);
_callbacks[playerId + "_level_" + callbackId] = dotNetObjectRef;
return await _jsRuntime.InvokeAsync<AudioOperationResult>(
"DeepDrftAudio.startLevelAnimation",
playerId, callbackId, dotNetObjectRef, "OnLevelDataCallback");
}
catch (Exception ex)
{
return new AudioOperationResult { Success = false, Error = ex.Message };
}
}
public async Task<AudioOperationResult> StopLevelAnimationAsync(string playerId, string callbackId)
{
var key = playerId + "_level_" + callbackId;
if (_callbacks.TryGetValue(key, out var callback))
{
callback?.Dispose();
_callbacks.Remove(key);
}
return await InvokeJsAsync<AudioOperationResult>("DeepDrftAudio.stopLevelAnimation", playerId, callbackId);
}
public async Task<AudioOperationResult> DisposePlayerAsync(string playerId)
{
CleanupPlayerCallbacks(playerId);
@@ -341,6 +370,18 @@ public class SpectrumCallback
}
}
public class LevelCallback
{
public Func<double, Task>? OnData { get; set; }
[JSInvokable]
public async Task OnLevelDataCallback(double db)
{
if (OnData != null)
await OnData(db);
}
}
public class AudioOperationResult
{
public bool Success { get; set; }