Improve CRingBuffer
This commit is contained in:
1 parent
6e4ccb39c0
commit
a46681c22b
4 files changed
+93
-105
No files matched your search
@@ -15,6 +15,8 @@
|
||||
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace Vocaluxe.Lib.Sound.Playback
|
||||
{
|
||||
public enum EStreamAction
|
||||
@@ -77,53 +79,75 @@ namespace Vocaluxe.Lib.Sound.Playback
|
||||
class CRingBuffer
|
||||
{
|
||||
private readonly byte[] _Data;
|
||||
private readonly long _Size;
|
||||
private long _ReadPos;
|
||||
private long _WritePos;
|
||||
private long _BytesNotRead;
|
||||
private readonly int _Size;
|
||||
private int _ReadPos;
|
||||
private int _WritePos;
|
||||
private int _BytesNotRead;
|
||||
|
||||
public long BytesNotRead
|
||||
public int BytesNotRead
|
||||
{
|
||||
get { return _BytesNotRead; }
|
||||
}
|
||||
|
||||
public CRingBuffer(long size)
|
||||
public CRingBuffer(int size)
|
||||
{
|
||||
_Size = size;
|
||||
_Data = new byte[size];
|
||||
_ReadPos = 0L;
|
||||
_WritePos = 0L;
|
||||
_BytesNotRead = 0L;
|
||||
Reset();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_ReadPos = 0;
|
||||
_WritePos = 0;
|
||||
_BytesNotRead = 0;
|
||||
}
|
||||
|
||||
public void Write(byte[] data)
|
||||
{
|
||||
long written = 0L;
|
||||
while (written < data.Length)
|
||||
int start = 0;
|
||||
int end = data.Length;
|
||||
if (end - start > _Size)
|
||||
start = end - _Size;
|
||||
int lenTotal = end - start;
|
||||
int len = Math.Min(lenTotal, _Size - _WritePos);
|
||||
Buffer.BlockCopy(data, start, _Data, _WritePos, len);
|
||||
_WritePos += len;
|
||||
if (_WritePos >= _Size)
|
||||
{
|
||||
_Data[_WritePos] = data[written];
|
||||
_WritePos++;
|
||||
if (_WritePos >= _Size)
|
||||
_WritePos = 0L;
|
||||
|
||||
written++;
|
||||
_BytesNotRead++;
|
||||
_WritePos = 0;
|
||||
start += len;
|
||||
len = end - start;
|
||||
if (len > 0)
|
||||
{
|
||||
Buffer.BlockCopy(data, start, _Data, _WritePos, len);
|
||||
_WritePos += len;
|
||||
}
|
||||
}
|
||||
_BytesNotRead += lenTotal;
|
||||
}
|
||||
|
||||
public void Read(byte[] data)
|
||||
{
|
||||
long read = 0L;
|
||||
while (read < data.Length && _BytesNotRead > 0L)
|
||||
{
|
||||
data[read] = _Data[_ReadPos];
|
||||
_ReadPos++;
|
||||
if (_ReadPos >= _Size)
|
||||
_ReadPos = 0L;
|
||||
int lenTotal = Math.Min(data.Length, _BytesNotRead);
|
||||
if (lenTotal == 0)
|
||||
return;
|
||||
|
||||
read++;
|
||||
_BytesNotRead--;
|
||||
int len = Math.Min(lenTotal, _Size - _ReadPos);
|
||||
Buffer.BlockCopy(_Data, _ReadPos, data, 0, len);
|
||||
_ReadPos += len;
|
||||
if (_ReadPos >= _Size)
|
||||
{
|
||||
_ReadPos = 0;
|
||||
int start = len;
|
||||
len = lenTotal - len;
|
||||
if (len > 0)
|
||||
{
|
||||
Buffer.BlockCopy(_Data, _ReadPos, data, start, len);
|
||||
_ReadPos += len;
|
||||
}
|
||||
}
|
||||
_BytesNotRead -= lenTotal;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ namespace Vocaluxe.Lib.Sound.Playback.OpenAL
|
||||
{
|
||||
private const int _BufferSize = 2048;
|
||||
private const int _BufferCount = 5;
|
||||
private const long _Bufsize = 50000L;
|
||||
private const int _Bufsize = 50000;
|
||||
|
||||
private Object _CloseMutex;
|
||||
|
||||
@@ -288,7 +288,7 @@ namespace Vocaluxe.Lib.Sound.Playback.OpenAL
|
||||
|
||||
lock (_MutexData)
|
||||
{
|
||||
_Data = new CRingBuffer(_Bufsize);
|
||||
_Data.Reset();
|
||||
_NoMoreData = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,8 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
|
||||
{
|
||||
class CPortAudioStream : IDisposable
|
||||
{
|
||||
private const long _Bufsize = 1000000L;
|
||||
private const long _Beginrefill = 800000L;
|
||||
private const int _Bufsize = 1000000;
|
||||
private const int _Beginrefill = 800000;
|
||||
|
||||
public readonly int ID;
|
||||
private readonly Closeproc _Closeproc;
|
||||
@@ -53,22 +53,21 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
|
||||
|
||||
private bool _FileOpened;
|
||||
|
||||
private bool _Waiting;
|
||||
private bool _Skip;
|
||||
|
||||
private bool _Loop;
|
||||
private float _Duration;
|
||||
private float _CurrentTime;
|
||||
private float _TimeCode;
|
||||
private volatile float _TimeCode;
|
||||
|
||||
private bool _Paused;
|
||||
private volatile bool _Paused;
|
||||
|
||||
private CRingBuffer _Data;
|
||||
private float _SetStart;
|
||||
private volatile float _SetStart;
|
||||
private float _Start;
|
||||
private bool _SetLoop;
|
||||
private bool _SetSkip;
|
||||
private bool _Terminated;
|
||||
private volatile bool _SetLoop;
|
||||
private volatile bool _SetSkip;
|
||||
private volatile bool _Terminated;
|
||||
|
||||
private Thread _DecoderThread;
|
||||
|
||||
@@ -114,7 +113,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
|
||||
{
|
||||
lock (_LockData)
|
||||
{
|
||||
return _NoMoreData && _Data.BytesNotRead == 0L && _SyncTimer.Time >= _Duration;
|
||||
return _NoMoreData && _Data.BytesNotRead == 0 && _SyncTimer.Time >= _Duration;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,11 +123,8 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
|
||||
get { return _Volume * 100f; }
|
||||
set
|
||||
{
|
||||
lock (_LockData)
|
||||
{
|
||||
value.Clamp(0f, 100f);
|
||||
_Volume = value / 100f;
|
||||
}
|
||||
value.Clamp(0f, 100f);
|
||||
_Volume = value / 100f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,11 +133,8 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
|
||||
get { return _VolumeMax * 100f; }
|
||||
set
|
||||
{
|
||||
lock (_LockData)
|
||||
{
|
||||
value.Clamp(0f, 100f);
|
||||
_VolumeMax = value / 100f;
|
||||
}
|
||||
value.Clamp(0f, 100f);
|
||||
_VolumeMax = value / 100f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,8 +146,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
|
||||
{
|
||||
if (Finished)
|
||||
_SyncTimer.Pause();
|
||||
//TODO: Why not use Decoder.GetPosition()?
|
||||
//Decoder may return wrong timestamps. If you change this to exessive testing for monoton timestamps espacially for ogg files
|
||||
//Decoder may return wrong timestamps. If you change this do exessive testing for monoton timestamps espacially for ogg files
|
||||
return _SyncTimer.Time;
|
||||
}
|
||||
}
|
||||
@@ -273,6 +265,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
|
||||
_ByteCount = 2 * format.ChannelCount;
|
||||
_BytesPerSecond = format.SamplesPerSecond * _ByteCount;
|
||||
_CurrentTime = 0f;
|
||||
_SyncTimer.Pause();
|
||||
_SyncTimer.Time = _CurrentTime;
|
||||
|
||||
PortAudioSharp.PortAudio.PaStreamParameters? outputParams = new PortAudioSharp.PortAudio.PaStreamParameters
|
||||
@@ -303,7 +296,6 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
|
||||
//From now on closing the driver and the decoder is handled by the thread ONLY!
|
||||
|
||||
_Paused = true;
|
||||
_Waiting = true;
|
||||
_FileOpened = true;
|
||||
_Data = new CRingBuffer(_Bufsize);
|
||||
_NoMoreData = false;
|
||||
@@ -319,7 +311,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
|
||||
{
|
||||
_SetStart = time;
|
||||
_SetSkip = true;
|
||||
_Waiting = true;
|
||||
_EventDecode.Set();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,10 +323,8 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
|
||||
_Decoder.SetPosition(_Start);
|
||||
_CurrentTime = _Start;
|
||||
_TimeCode = _Start;
|
||||
_Data = new CRingBuffer(_Bufsize);
|
||||
_Data.Reset();
|
||||
_NoMoreData = false;
|
||||
_EventDecode.Set();
|
||||
_Waiting = false;
|
||||
_SyncTimer.Time = _Start;
|
||||
}
|
||||
}
|
||||
@@ -343,35 +333,27 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
|
||||
{
|
||||
while (!_Terminated)
|
||||
{
|
||||
if (_EventDecode.WaitOne(10))
|
||||
lock (_LockSyncSignals)
|
||||
{
|
||||
lock (_LockSyncSignals)
|
||||
if (_SetSkip)
|
||||
{
|
||||
if (_SetSkip)
|
||||
{
|
||||
_Skip = true;
|
||||
_EventDecode.Set();
|
||||
_Waiting = true;
|
||||
}
|
||||
|
||||
_Skip = true;
|
||||
_SetSkip = false;
|
||||
|
||||
_Start = _SetStart;
|
||||
_Loop = _SetLoop;
|
||||
}
|
||||
|
||||
if (_Skip)
|
||||
{
|
||||
_DoSkip();
|
||||
_Skip = false;
|
||||
}
|
||||
|
||||
if (!_Waiting)
|
||||
{
|
||||
_DoDecode();
|
||||
_Update();
|
||||
}
|
||||
_Start = _SetStart;
|
||||
_Loop = _SetLoop;
|
||||
}
|
||||
|
||||
if (_Skip)
|
||||
{
|
||||
_DoSkip();
|
||||
_Skip = false;
|
||||
}
|
||||
|
||||
_DoDecode();
|
||||
_Update();
|
||||
_EventDecode.WaitOne();
|
||||
}
|
||||
|
||||
_DoFree();
|
||||
@@ -422,12 +404,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
|
||||
_Data.Write(buffer);
|
||||
_TimeCode = timecode;
|
||||
if (_Data.BytesNotRead < _Beginrefill)
|
||||
{
|
||||
_Waiting = false;
|
||||
_EventDecode.Set();
|
||||
}
|
||||
else
|
||||
_Waiting = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,7 +435,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
|
||||
{
|
||||
try
|
||||
{
|
||||
Marshal.Copy(buf, 0, output, (int)frameCount * _ByteCount);
|
||||
Marshal.Copy(buf, 0, output, buf.Length);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -482,13 +459,8 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
|
||||
}
|
||||
}
|
||||
|
||||
if (_Data.BytesNotRead < _Beginrefill)
|
||||
{
|
||||
if (_Data.BytesNotRead < _Beginrefill && !_NoMoreData)
|
||||
_EventDecode.Set();
|
||||
_Waiting = false;
|
||||
}
|
||||
else
|
||||
_Waiting = true;
|
||||
|
||||
float latency = buf.Length / _BytesPerSecond + CConfig.AudioLatency / 1000f;
|
||||
float time = _TimeCode - _Data.BytesNotRead / _BytesPerSecond - latency;
|
||||
@@ -503,7 +475,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
CLog.LogError("Error PortAudio.treamCallback: " + e.Message);
|
||||
CLog.LogError("Error PortAudio.StreamCallback: " + e.Message);
|
||||
}
|
||||
|
||||
return PortAudioSharp.PortAudio.PaStreamCallbackResult.paContinue;
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Vocaluxe.Base;
|
||||
|
||||
namespace Vocaluxe.Lib.Sound.Record
|
||||
@@ -32,7 +30,6 @@ namespace Vocaluxe.Lib.Sound.Record
|
||||
|
||||
private const float _MaxDelayTime = 1000;
|
||||
public bool Running { get; private set; }
|
||||
private readonly Stopwatch _Timer = new Stopwatch();
|
||||
private int _Stream = -1;
|
||||
|
||||
private readonly SDelayChannel[] _DelaysChannel;
|
||||
@@ -72,7 +69,6 @@ namespace Vocaluxe.Lib.Sound.Record
|
||||
if (!Running)
|
||||
return;
|
||||
Running = false;
|
||||
_Timer.Stop();
|
||||
_CloseStream();
|
||||
foreach (SDelayChannel delay in _DelaysChannel)
|
||||
{
|
||||
@@ -101,16 +97,13 @@ namespace Vocaluxe.Lib.Sound.Record
|
||||
{
|
||||
if (!Running)
|
||||
return;
|
||||
if (!_Timer.IsRunning)
|
||||
{
|
||||
if (CSound.GetPosition(_Stream) > 0f)
|
||||
_Timer.Restart();
|
||||
}
|
||||
if (!_Timer.IsRunning)
|
||||
|
||||
float time = CSound.GetPosition(_Stream) * 1000f;
|
||||
if (time <= 0f)
|
||||
return;
|
||||
|
||||
bool isActive = false;
|
||||
if (_Timer.ElapsedMilliseconds <= _MaxDelayTime)
|
||||
if (time <= _MaxDelayTime)
|
||||
{
|
||||
for (int i = 0; i < _DelaysChannel.Length; i++)
|
||||
{
|
||||
@@ -118,12 +111,11 @@ namespace Vocaluxe.Lib.Sound.Record
|
||||
continue;
|
||||
if (CRecord.GetTone(_DelaysChannel[i].Channel) == 9)
|
||||
{
|
||||
Delays[i] = (int)_Timer.ElapsedMilliseconds;
|
||||
Delays[i] = (int)time;
|
||||
_DelaysChannel[i].Finished = true;
|
||||
}
|
||||
else
|
||||
isActive = true;
|
||||
Console.WriteLine(CRecord.GetMaxVolume(_DelaysChannel[i].Channel));
|
||||
}
|
||||
}
|
||||
if (!isActive)
|
||||
|
||||
Reference in new issue
Block a user