From 57d301018ec6e3b65e68cdf5f193ec143b56a5be Mon Sep 17 00:00:00 2001 From: Alexander Eckart Date: Sun, 6 Jan 2013 15:07:08 +0100 Subject: [PATCH] initialize portaudio playback only once --- Vocaluxe/Lib/Sound/CPortAudioPlay.cs | 78 +++++++++++++++++++--------- 1 file changed, 53 insertions(+), 25 deletions(-) diff --git a/Vocaluxe/Lib/Sound/CPortAudioPlay.cs b/Vocaluxe/Lib/Sound/CPortAudioPlay.cs index 1d4fd1bf..9eb62509 100644 --- a/Vocaluxe/Lib/Sound/CPortAudioPlay.cs +++ b/Vocaluxe/Lib/Sound/CPortAudioPlay.cs @@ -388,7 +388,9 @@ namespace Vocaluxe.Lib.Sound const long BEGINREFILL = 800000L; private CSyncTimer _SyncTimer; - private bool _Initialized; + private static bool _Initialized = false; + private static int _NumStreams = 0; + private static Object _Mutex = new object(); private int _ByteCount = 4; private float _Volume = 1f; private float _VolumeMax = 1f; @@ -403,8 +405,8 @@ namespace Vocaluxe.Lib.Sound private bool _fading = false; - private PortAudio.PaHostApiInfo _apiInfo; - private PortAudio.PaDeviceInfo _outputDeviceInfo; + private static PortAudio.PaHostApiInfo _apiInfo; + private static PortAudio.PaDeviceInfo _outputDeviceInfo; private IntPtr _Ptr = new IntPtr(0); private Stopwatch _FadeTimer = new Stopwatch(); @@ -446,7 +448,6 @@ namespace Vocaluxe.Lib.Sound public PortAudioStream() { - _Initialized = false; _SyncTimer = new CSyncTimer(0f, 1f, 0.02f); _DecoderThread = new Thread(Execute); } @@ -578,12 +579,18 @@ namespace Vocaluxe.Lib.Sound { Paused = false; _pauseStreamAfterFade = false; - errorCheck("StartStream", PortAudio.Pa_StartStream(_Ptr)); + lock (_Mutex) + { + errorCheck("StartStream", PortAudio.Pa_StartStream(_Ptr)); + } } public void Stop() { - errorCheck("StartStream", PortAudio.Pa_StopStream(_Ptr)); + lock (_Mutex) + { + errorCheck("StopStream (playback)", PortAudio.Pa_StopStream(_Ptr)); + } Skip(0f); } @@ -609,17 +616,23 @@ namespace Vocaluxe.Lib.Sound try { - if (errorCheck("Initialize", PortAudio.Pa_Initialize())) - return -1; + lock (_Mutex) + { + if (!_Initialized) + { + if (errorCheck("Initialize", PortAudio.Pa_Initialize())) + return -1; + _Initialized = true; - _Initialized = true; - int hostApi = apiSelect(); - _apiInfo = PortAudio.Pa_GetHostApiInfo(hostApi); - _outputDeviceInfo = PortAudio.Pa_GetDeviceInfo(_apiInfo.defaultOutputDevice); - _paStreamCallback = new PortAudio.PaStreamCallbackDelegate(_PaStreamCallback); + int hostApi = apiSelect(); + _apiInfo = PortAudio.Pa_GetHostApiInfo(hostApi); + _outputDeviceInfo = PortAudio.Pa_GetDeviceInfo(_apiInfo.defaultOutputDevice); + if (_outputDeviceInfo.defaultLowOutputLatency < 0.1) + _outputDeviceInfo.defaultLowOutputLatency = 0.1; + } + } - if (_outputDeviceInfo.defaultLowOutputLatency < 0.1) - _outputDeviceInfo.defaultLowOutputLatency = 0.1; + _paStreamCallback = new PortAudio.PaStreamCallbackDelegate(_PaStreamCallback); } catch (Exception) @@ -634,6 +647,9 @@ namespace Vocaluxe.Lib.Sound _Duration = _Decoder.GetLength(); FormatInfo format = _Decoder.GetFormatInfo(); + if (format.SamplesPerSecond == 0) + return -1; + _ByteCount = 2 * format.ChannelCount; _BytesPerSecond = format.SamplesPerSecond * _ByteCount; _CurrentTime = 0f; @@ -650,20 +666,24 @@ namespace Vocaluxe.Lib.Sound outputParams.suggestedLatency = _outputDeviceInfo.defaultLowOutputLatency; uint bufsize = (uint)CConfig.AudioBufferSize; - errorCheck("OpenDefaultStream (playback)", PortAudio.Pa_OpenStream( - out _Ptr, - IntPtr.Zero, - ref outputParams, - format.SamplesPerSecond, - bufsize, - PortAudio.PaStreamFlags.paNoFlag, - _paStreamCallback, - data)); + lock (_Mutex) + { + errorCheck("OpenDefaultStream (playback)", PortAudio.Pa_OpenStream( + out _Ptr, + IntPtr.Zero, + ref outputParams, + format.SamplesPerSecond, + bufsize, + PortAudio.PaStreamFlags.paNoFlag, + _paStreamCallback, + data)); + } stream.handle = _Ptr.ToInt32(); if (stream.handle != 0) { + _NumStreams++; _Paused = true; _waiting = true; _FileOpened = true; @@ -808,7 +828,15 @@ namespace Vocaluxe.Lib.Sound if (_Initialized) { Stop(); - PortAudio.Pa_Terminate(); + _NumStreams--; + if (_NumStreams == 0) + { + lock (_Mutex) + { + PortAudio.Pa_Terminate(); + _Initialized = false; + } + } } _Closeproc(_StreamID);