@@ -23,6 +23,8 @@ internal sealed class AudioPlayer : IAudioPlayer
2323 private readonly SemaphoreSlim _playbackLock = new ( 1 , 1 ) ;
2424 private CancellationTokenSource ? _playbackCts ;
2525 private System . Threading . Timer ? _progressTimer ;
26+ private bool _isWasapiWarmedUp ;
27+ private readonly object _warmupLock = new ( ) ;
2628
2729 public float Volume
2830 {
@@ -75,6 +77,44 @@ public TimeSpan Duration
7577 public event EventHandler < PlaybackStatusEventArgs > ? PlaybackStatusChanged ;
7678 public event EventHandler < PlaybackProgressEventArgs > ? PlaybackProgressChanged ;
7779
80+ public AudioPlayer ( )
81+ {
82+ Task . Run ( WarmUpWasapiAsync ) ;
83+ }
84+
85+ private async Task WarmUpWasapiAsync ( )
86+ {
87+ try
88+ {
89+ lock ( _warmupLock )
90+ {
91+ if ( _isWasapiWarmedUp )
92+ {
93+ return ;
94+ }
95+ }
96+
97+ using var tempOut = new WasapiOut ( ) ;
98+
99+ await Task . Delay ( 50 ) . ConfigureAwait ( false ) ;
100+
101+ lock ( _warmupLock )
102+ {
103+ _isWasapiWarmedUp = true ;
104+ }
105+
106+ Debug . WriteLine ( "WASAPI warmed up successfully" ) ;
107+ }
108+ catch ( Exception ex )
109+ {
110+ Debug . WriteLine ( $ "WASAPI warmup failed (non-critical): { ex . Message } ") ;
111+ lock ( _warmupLock )
112+ {
113+ _isWasapiWarmedUp = true ;
114+ }
115+ }
116+ }
117+
78118 public async Task PlayFileAsync ( string filePath , CancellationToken cancellationToken = default )
79119 {
80120 ArgumentException . ThrowIfNullOrWhiteSpace ( filePath ) ;
@@ -89,16 +129,23 @@ public async Task PlayFileAsync(string filePath, CancellationToken cancellationT
89129 try
90130 {
91131 _currentFilePath = filePath ;
132+ var token = _playbackCts . Token ;
92133
93- await Task . Run ( ( ) =>
134+ await Task . Run ( async ( ) =>
94135 {
95136 _waveSource = CodecFactory . Instance . GetCodec ( _currentFilePath ) ;
96- _soundOut = new WasapiOut ( ) ;
137+
138+ var wasapiOut = new WasapiOut { Latency = 100 } ;
139+ _soundOut = wasapiOut ;
140+
97141 _soundOut . Stopped += OnPlaybackStopped ;
98142 _soundOut . Initialize ( _waveSource ) ;
99143 _soundOut . Volume = _volume ;
144+
145+ await Task . Delay ( 50 , token ) . ConfigureAwait ( false ) ;
146+
100147 _soundOut . Play ( ) ;
101- } , _playbackCts . Token ) . ConfigureAwait ( false ) ;
148+ } , token ) . ConfigureAwait ( false ) ;
102149
103150 _playbackState = PlaybackState . Playing ;
104151
@@ -276,14 +323,39 @@ await Task.Run(() =>
276323 if ( _soundOut != null )
277324 {
278325 _soundOut . Stopped -= OnPlaybackStopped ;
279- _soundOut . Stop ( ) ;
280- _soundOut . Dispose ( ) ;
326+
327+ try
328+ {
329+ _soundOut . Stop ( ) ;
330+ }
331+ catch ( Exception ex )
332+ {
333+ Debug . WriteLine ( $ "Error stopping soundOut: { ex . Message } ") ;
334+ }
335+
336+ try
337+ {
338+ _soundOut . Dispose ( ) ;
339+ }
340+ catch ( Exception ex )
341+ {
342+ Debug . WriteLine ( $ "Error disposing soundOut: { ex . Message } ") ;
343+ }
344+
281345 _soundOut = null ;
282346 }
283347
284348 if ( _waveSource != null )
285349 {
286- _waveSource . Dispose ( ) ;
350+ try
351+ {
352+ _waveSource . Dispose ( ) ;
353+ }
354+ catch ( Exception ex )
355+ {
356+ Debug . WriteLine ( $ "Error disposing waveSource: { ex . Message } ") ;
357+ }
358+
287359 _waveSource = null ;
288360 }
289361 } , cancellationToken ) . ConfigureAwait ( false ) ;
@@ -308,7 +380,10 @@ private async Task StopFileInternalAsync(CancellationToken cancellationToken = d
308380 return ;
309381 }
310382
311- await ( ( _playbackCts ? . CancelAsync ( ) ?? Task . CompletedTask ) . ConfigureAwait ( false ) ) ;
383+ if ( _playbackCts != null )
384+ {
385+ await _playbackCts . CancelAsync ( ) . ConfigureAwait ( false ) ;
386+ }
312387
313388 await StopInternalAsync ( null , cancellationToken ) . ConfigureAwait ( false ) ;
314389 }
@@ -331,9 +406,19 @@ public void Dispose()
331406 if ( ! _disposed )
332407 {
333408 StopProgressTimer ( ) ;
334- StopFileAsync ( ) . GetAwaiter ( ) . GetResult ( ) ;
409+
410+ try
411+ {
412+ StopFileAsync ( ) . GetAwaiter ( ) . GetResult ( ) ;
413+ }
414+ catch ( Exception ex )
415+ {
416+ Debug . WriteLine ( $ "Error during dispose: { ex . Message } ") ;
417+ }
418+
335419 _playbackCts ? . Dispose ( ) ;
336420 _playbackLock . Dispose ( ) ;
421+
337422 _disposed = true ;
338423 }
339424 }
0 commit comments