|
@@ -3,6 +3,7 @@ using System.ComponentModel;
|
|
|
using System.Text;
|
|
|
using System.Threading.Channels;
|
|
|
using Bmp.Core.Common.EventBus;
|
|
|
+using Bmp.Core.Common.Utility;
|
|
|
using Bmp.Core.Common.Win32;
|
|
|
using Bmp.Core.NAudioExt;
|
|
|
using Bmp.Core.Playback.Inputs;
|
|
@@ -128,7 +129,7 @@ namespace Bmp.WinForms
|
|
|
|
|
|
try
|
|
|
{
|
|
|
- _inputSource = await Task.Run(() => InputSourceProvider.CreateWaveStream(item.Name, _sl?.State?.DecodeDsdToPcm == true));
|
|
|
+ await ReloadSource();
|
|
|
}
|
|
|
catch (Exception e)
|
|
|
{
|
|
@@ -175,6 +176,11 @@ namespace Bmp.WinForms
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private async Task ReloadSource()
|
|
|
+ {
|
|
|
+ _inputSource = await Task.Run(() => InputSourceProvider.CreateWaveStream(_currentListViewItem!.Name, _sl?.State?.DecodeDsdToPcm == true));
|
|
|
+ }
|
|
|
+
|
|
|
private async Task DeInitOutputDevice()
|
|
|
{
|
|
|
var local = _outputDevice;
|
|
@@ -186,12 +192,9 @@ namespace Bmp.WinForms
|
|
|
|
|
|
if (local is AsioOut ao)
|
|
|
{
|
|
|
- if (_nativeDsd)
|
|
|
- {
|
|
|
- //try reset device
|
|
|
- ao.SetNativeDsd(false);
|
|
|
- ao.Driver.SetSampleRate(44100);
|
|
|
- }
|
|
|
+ //try reset device
|
|
|
+ if (_nativeDsd) ao.SetNativeDsd(false);
|
|
|
+ ao.Driver.SetSampleRate(44100);
|
|
|
}
|
|
|
|
|
|
local.Dispose();
|
|
@@ -283,9 +286,10 @@ namespace Bmp.WinForms
|
|
|
_visualizeDataMiddleWrap = new VisualizeDataMiddleWrap(_inputSource!);
|
|
|
_visualizeDataMiddleWrap.DataTransferred += _visualizeDataMiddleWrap_DataTransferred;
|
|
|
|
|
|
+ IWavePlayer od;
|
|
|
try
|
|
|
{
|
|
|
- _outputDevice = OutputDeviceProvider.CreateWavePlayer(_selectedOutputDevice, _nativeDsd);
|
|
|
+ od = OutputDeviceProvider.CreateWavePlayer(_selectedOutputDevice, _nativeDsd);
|
|
|
}
|
|
|
catch (Exception e)
|
|
|
{
|
|
@@ -303,7 +307,7 @@ namespace Bmp.WinForms
|
|
|
|
|
|
try
|
|
|
{
|
|
|
- _outputDevice.Init(_visualizeDataMiddleWrap);
|
|
|
+ od.Init(_visualizeDataMiddleWrap);
|
|
|
}
|
|
|
catch (Exception e)
|
|
|
{
|
|
@@ -317,6 +321,7 @@ namespace Bmp.WinForms
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+ _outputDevice = od;
|
|
|
_outputDevice.PlaybackStopped += _outputDevice_PlaybackStopped;
|
|
|
}
|
|
|
catch (Exception e)
|
|
@@ -365,6 +370,7 @@ namespace Bmp.WinForms
|
|
|
|
|
|
private async Task<bool> PlayAsync()
|
|
|
{
|
|
|
+ if (_inputSource == null) return false;
|
|
|
_playbackState = UIPlaybackState.Playing;
|
|
|
if (await ReInitOutputDevice())
|
|
|
{
|
|
@@ -410,7 +416,6 @@ namespace Bmp.WinForms
|
|
|
{
|
|
|
if (_playbackState == UIPlaybackState.Seeking) return;
|
|
|
if (_playbackState == UIPlaybackState.Paused) return;
|
|
|
- if (_playbackState == UIPlaybackState.Loading) return;
|
|
|
|
|
|
if (e.Exception == null)
|
|
|
{
|
|
@@ -1025,9 +1030,9 @@ namespace Bmp.WinForms
|
|
|
unit = "M";
|
|
|
}
|
|
|
|
|
|
- sb.Append(sampleRate % 1000 == 0
|
|
|
- ? $"/{sampleRate / 1000.0}{unit}Hz"
|
|
|
- :$"/{Math.Floor((float)sampleRate / 100) / 10.0:0.0}{unit}Hz");
|
|
|
+ sb.Append(sampleRate % 1000 == 0
|
|
|
+ ? $"/{sampleRate / 1000.0}{unit}Hz"
|
|
|
+ : $"/{Math.Floor((float)sampleRate / 100) / 10.0:0.0}{unit}Hz");
|
|
|
}
|
|
|
|
|
|
if (_selectedOutputDevice != null && _playbackState == UIPlaybackState.Playing)
|
|
@@ -1074,19 +1079,21 @@ namespace Bmp.WinForms
|
|
|
await Task.Run(() => _inputSource.CurrentTime = seekTo);
|
|
|
MainPanel.Enabled = true;
|
|
|
|
|
|
- var bytesOf100Ms = (int)((double)_inputSource.WaveFormat.BitsPerSample / 8 * _inputSource.WaveFormat.Channels * _inputSource.WaveFormat.SampleRate / 10);
|
|
|
-
|
|
|
- var mod = bytesOf100Ms % _inputSource.BlockAlign;
|
|
|
- if (mod != 0) bytesOf100Ms -= mod;
|
|
|
- if (bytesOf100Ms == 0) bytesOf100Ms = _inputSource.BlockAlign;
|
|
|
-
|
|
|
- var buf = new byte[bytesOf100Ms];
|
|
|
-
|
|
|
- do
|
|
|
+ _inputSource.ReadBytes(_inputSource.BlockAlign);
|
|
|
+ if (seekTo - _inputSource.CurrentTime > TimeSpan.FromSeconds(1))
|
|
|
{
|
|
|
- var count = await _inputSource.ReadAsync(buf, 0, bytesOf100Ms);
|
|
|
- if (count == 0) break;
|
|
|
- } while (_inputSource.CurrentTime < seekTo);
|
|
|
+ //if content not support seek, reload and read&discard until target pos
|
|
|
+ await ReloadSource();
|
|
|
+
|
|
|
+ await Task.Run(() =>
|
|
|
+ {
|
|
|
+ do
|
|
|
+ {
|
|
|
+ var count = _inputSource.ReadBytes(_inputSource.BlockAlign);
|
|
|
+ if (count.Length == 0) break;
|
|
|
+ } while (_inputSource != null && _inputSource.CurrentTime < seekTo && _playbackState == UIPlaybackState.Seeking);
|
|
|
+ });
|
|
|
+ }
|
|
|
|
|
|
await PlayAsync();
|
|
|
}
|