|
@@ -3,18 +3,19 @@ using NAudio.Flac;
|
|
using NAudio.Wave;
|
|
using NAudio.Wave;
|
|
using System.Runtime.InteropServices.JavaScript;
|
|
using System.Runtime.InteropServices.JavaScript;
|
|
using System.Runtime.Versioning;
|
|
using System.Runtime.Versioning;
|
|
|
|
+using Newtonsoft.Json;
|
|
|
|
|
|
namespace FNZCM.BlazorWasm.Utility
|
|
namespace FNZCM.BlazorWasm.Utility
|
|
{
|
|
{
|
|
[SupportedOSPlatform("browser")]
|
|
[SupportedOSPlatform("browser")]
|
|
- public static partial class WavePlayerModule
|
|
|
|
|
|
+ public static partial class WavePlayerModuleNAudio
|
|
{
|
|
{
|
|
public static bool IsInit { get; private set; }
|
|
public static bool IsInit { get; private set; }
|
|
|
|
|
|
private static IWaveProvider _provider;
|
|
private static IWaveProvider _provider;
|
|
private static ISampleProvider _sampleProvider;
|
|
private static ISampleProvider _sampleProvider;
|
|
public static WaveFormat OutputWaveFormat { get; private set; }
|
|
public static WaveFormat OutputWaveFormat { get; private set; }
|
|
- public static int MsPerChunk { get; set; } = 200;
|
|
|
|
|
|
+ public static int MsPerChunk { get; set; } = 150;
|
|
|
|
|
|
public static async Task InitFlacAsync(string url)
|
|
public static async Task InitFlacAsync(string url)
|
|
{
|
|
{
|
|
@@ -35,8 +36,12 @@ namespace FNZCM.BlazorWasm.Utility
|
|
var flacStream = await rsp.Content.ReadAsStreamAsync();
|
|
var flacStream = await rsp.Content.ReadAsStreamAsync();
|
|
Console.WriteLine("create flac reader");
|
|
Console.WriteLine("create flac reader");
|
|
var reader = new FlacReader(flacStream);
|
|
var reader = new FlacReader(flacStream);
|
|
|
|
+ Console.WriteLine("format:" + reader.WaveFormat);
|
|
|
|
+ Console.WriteLine("json:" + JsonConvert.SerializeObject(reader.WaveFormat));
|
|
|
|
+ Console.WriteLine("create lockAlignReductionStream");
|
|
|
|
+ var alignReader = new BlockAlignReductionStream(reader);
|
|
Console.WriteLine("init wave player");
|
|
Console.WriteLine("init wave player");
|
|
- await InitAsync(reader);
|
|
|
|
|
|
+ await InitAsync(alignReader);
|
|
Play();
|
|
Play();
|
|
}
|
|
}
|
|
|
|
|
|
@@ -61,39 +66,50 @@ namespace FNZCM.BlazorWasm.Utility
|
|
public static partial void Stop();
|
|
public static partial void Stop();
|
|
|
|
|
|
[JSExport]
|
|
[JSExport]
|
|
- public static bool TakeChunk()
|
|
|
|
|
|
+ public static double[] TakeChunk()
|
|
{
|
|
{
|
|
var sampleCountPerChannel = (int)(OutputWaveFormat.SampleRate * MsPerChunk / 1000f);
|
|
var sampleCountPerChannel = (int)(OutputWaveFormat.SampleRate * MsPerChunk / 1000f);
|
|
- var sampleCount = sampleCountPerChannel * OutputWaveFormat.Channels;
|
|
|
|
- var floats = new float[sampleCount];
|
|
|
|
- var r = _sampleProvider.Read(floats, 0, floats.Length);
|
|
|
|
|
|
|
|
- Array.Resize(ref floats, r);
|
|
|
|
-
|
|
|
|
- var channels = new double[OutputWaveFormat.Channels][];
|
|
|
|
- for (var i = 0; i < OutputWaveFormat.Channels; i++)
|
|
|
|
|
|
+ float[] sampleBuffer;
|
|
{
|
|
{
|
|
- channels[i] = new double[sampleCountPerChannel];
|
|
|
|
|
|
+ var remainSamples = sampleCountPerChannel * OutputWaveFormat.Channels;
|
|
|
|
+ sampleBuffer = new float[remainSamples];
|
|
|
|
+ var readIndex = 0;
|
|
|
|
+ while (remainSamples > 0)
|
|
|
|
+ {
|
|
|
|
+ var r = _sampleProvider.Read(sampleBuffer, readIndex, sampleBuffer.Length - readIndex);
|
|
|
|
+ if (r == 0)
|
|
|
|
+ {
|
|
|
|
+ Array.Resize(ref sampleBuffer, readIndex);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ remainSamples -= r;
|
|
|
|
+ readIndex += r;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
//de-multiplex
|
|
//de-multiplex
|
|
- var ch = 0;
|
|
|
|
- var index = 0;
|
|
|
|
- foreach (var f in floats)
|
|
|
|
|
|
+ //re-order buffer
|
|
|
|
+ // 0 1 2 3 4 5
|
|
|
|
+ // L R L R L R
|
|
|
|
+ // → L L L R R R
|
|
|
|
+ // 0 2 4 1 3 5
|
|
|
|
+ //convert float to double for marshal
|
|
|
|
+
|
|
|
|
+ var marshalBuf = new double[sampleBuffer.Length];
|
|
|
|
+ var sampleIndex = 0;
|
|
|
|
+ for (var i = 0; i < marshalBuf.Length; i += OutputWaveFormat.Channels)
|
|
{
|
|
{
|
|
- channels[ch][index] = f;
|
|
|
|
- ++ch;
|
|
|
|
- if (ch >= OutputWaveFormat.Channels)
|
|
|
|
|
|
+ for (var c = 0; c < OutputWaveFormat.Channels; c++)
|
|
{
|
|
{
|
|
- ch = 0;
|
|
|
|
- ++index;
|
|
|
|
|
|
+ var srcIdx = i + c;
|
|
|
|
+ var dstIdx = sampleCountPerChannel * c + sampleIndex;
|
|
|
|
+ marshalBuf[dstIdx] = sampleBuffer[srcIdx];
|
|
}
|
|
}
|
|
|
|
+ sampleIndex++;
|
|
}
|
|
}
|
|
|
|
|
|
- //TODO: adapt dym channels
|
|
|
|
- JsFeedChunk(channels[0], channels[1]);
|
|
|
|
-
|
|
|
|
- return index > 0;
|
|
|
|
|
|
+ return marshalBuf;
|
|
}
|
|
}
|
|
|
|
|
|
[JSImport("init", "WavePlayer")]
|
|
[JSImport("init", "WavePlayer")]
|