Improve CRingBuffer

This commit is contained in:
Flamefire committed 2014-05-01 00:15:21 +02:00
1 parent 6e4ccb39c0
commit a46681c22b
4 files changed
+93 -105

No files matched your search

+51 -27
View File
@@ -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;
+5 -13
View File
@@ -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)