XAudio2: Avoid buffer re-allocation.
This commit is contained in:
parent
3cea39f6e1
commit
d1bfe9c842
|
@ -18,6 +18,7 @@ namespace BizHawk.Client.EmuHawk
|
||||||
private XAudio2 _device;
|
private XAudio2 _device;
|
||||||
private MasteringVoice _masteringVoice;
|
private MasteringVoice _masteringVoice;
|
||||||
private SourceVoice _sourceVoice;
|
private SourceVoice _sourceVoice;
|
||||||
|
private BufferPool _bufferPool;
|
||||||
private long _runningSamplesQueued;
|
private long _runningSamplesQueued;
|
||||||
|
|
||||||
public XAudio2SoundOutput(Sound sound)
|
public XAudio2SoundOutput(Sound sound)
|
||||||
|
@ -79,6 +80,7 @@ namespace BizHawk.Client.EmuHawk
|
||||||
|
|
||||||
_sourceVoice = new SourceVoice(_device, format);
|
_sourceVoice = new SourceVoice(_device, format);
|
||||||
|
|
||||||
|
_bufferPool = new BufferPool();
|
||||||
_runningSamplesQueued = 0;
|
_runningSamplesQueued = 0;
|
||||||
|
|
||||||
_sourceVoice.Start();
|
_sourceVoice.Start();
|
||||||
|
@ -90,6 +92,8 @@ namespace BizHawk.Client.EmuHawk
|
||||||
_sourceVoice.Dispose();
|
_sourceVoice.Dispose();
|
||||||
_sourceVoice = null;
|
_sourceVoice = null;
|
||||||
|
|
||||||
|
_bufferPool = null;
|
||||||
|
|
||||||
BufferSizeSamples = 0;
|
BufferSizeSamples = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,16 +117,51 @@ namespace BizHawk.Client.EmuHawk
|
||||||
public void WriteSamples(short[] samples, int sampleCount)
|
public void WriteSamples(short[] samples, int sampleCount)
|
||||||
{
|
{
|
||||||
if (sampleCount == 0) return;
|
if (sampleCount == 0) return;
|
||||||
// TODO: Re-use these buffers
|
_bufferPool.Release(_sourceVoice.State.BuffersQueued);
|
||||||
byte[] bytes = new byte[sampleCount * Sound.BlockAlign];
|
int byteCount = sampleCount * Sound.BlockAlign;
|
||||||
Buffer.BlockCopy(samples, 0, bytes, 0, bytes.Length);
|
var buffer = _bufferPool.Obtain(byteCount);
|
||||||
|
Buffer.BlockCopy(samples, 0, buffer.Bytes, 0, byteCount);
|
||||||
_sourceVoice.SubmitSourceBuffer(new AudioBuffer
|
_sourceVoice.SubmitSourceBuffer(new AudioBuffer
|
||||||
{
|
{
|
||||||
AudioBytes = bytes.Length,
|
AudioBytes = byteCount,
|
||||||
AudioData = new DataStream(bytes, true, false)
|
AudioData = buffer.DataStream
|
||||||
});
|
});
|
||||||
_runningSamplesQueued += sampleCount;
|
_runningSamplesQueued += sampleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class BufferPool
|
||||||
|
{
|
||||||
|
private List<BufferPoolItem> _availableItems = new List<BufferPoolItem>();
|
||||||
|
private Queue<BufferPoolItem> _obtainedItems = new Queue<BufferPoolItem>();
|
||||||
|
|
||||||
|
public BufferPoolItem Obtain(int length)
|
||||||
|
{
|
||||||
|
BufferPoolItem item = _availableItems.Where(n => n.MaxLength >= length).OrderBy(n => n.MaxLength).FirstOrDefault() ?? new BufferPoolItem(length);
|
||||||
|
_availableItems.Remove(item);
|
||||||
|
_obtainedItems.Enqueue(item);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Release(int buffersQueued)
|
||||||
|
{
|
||||||
|
while (_obtainedItems.Count > buffersQueued)
|
||||||
|
_availableItems.Add(_obtainedItems.Dequeue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BufferPoolItem
|
||||||
|
{
|
||||||
|
public int MaxLength { get; private set; }
|
||||||
|
public byte[] Bytes { get; private set; }
|
||||||
|
public DataStream DataStream { get; private set; }
|
||||||
|
|
||||||
|
public BufferPoolItem(int length)
|
||||||
|
{
|
||||||
|
MaxLength = length;
|
||||||
|
Bytes = new byte[MaxLength];
|
||||||
|
DataStream = new DataStream(Bytes, true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue