mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-01-24 10:02:08 -05:00
fix crackling/popping when playing music on openal backend
This commit is contained in:
parent
de3bce77a6
commit
9399d5b384
5 changed files with 54 additions and 32 deletions
|
@ -27,12 +27,33 @@ namespace SharpWave {
|
|||
|
||||
public AudioFormat Format;
|
||||
public abstract void SetFormat(AudioFormat format);
|
||||
public abstract void PlayData(int index, AudioChunk chunk);
|
||||
public abstract void BufferData(int index, AudioChunk chunk);
|
||||
public abstract void Play();
|
||||
public abstract bool IsCompleted(int index);
|
||||
public abstract bool IsFinished();
|
||||
|
||||
public int NumBuffers;
|
||||
public bool pendingStop;
|
||||
public void PlayData(int index, AudioChunk chunk) {
|
||||
BufferData(index, chunk);
|
||||
Play();
|
||||
}
|
||||
|
||||
bool BufferBlock(AudioChunk tmp, AudioFormat fmt, IEnumerator<AudioChunk> chunks) {
|
||||
// decode up to around a second
|
||||
int secondSize = fmt.SampleRate * fmt.Channels * sizeof(short);
|
||||
tmp.Length = 0;
|
||||
|
||||
while (tmp.Length < secondSize) {
|
||||
if (!chunks.MoveNext()) return true;
|
||||
AudioChunk src = chunks.Current;
|
||||
|
||||
Buffer.BlockCopy(src.Data, 0, tmp.Data, tmp.Length, src.Length);
|
||||
tmp.Length += src.Length;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void PlayStreaming(Stream stream) {
|
||||
VorbisCodec codec = new VorbisCodec();
|
||||
AudioFormat fmt = codec.ReadHeader(stream);
|
||||
|
@ -43,12 +64,19 @@ namespace SharpWave {
|
|||
|
||||
// largest possible vorbis frame decodes to blocksize1 samples
|
||||
// so we may end up decoding slightly over a second of audio
|
||||
int secondSize = fmt.SampleRate * fmt.Channels * sizeof(short);
|
||||
int chunkSize = (fmt.SampleRate + 8192) * fmt.Channels * sizeof(short);
|
||||
byte[][] data = new byte[NumBuffers][];
|
||||
for (int i = 0; i < NumBuffers; i++) { data[i] = new byte[chunkSize]; }
|
||||
for (int i = 0; i < NumBuffers; i++) { data[i] = new byte[chunkSize]; }
|
||||
|
||||
for (;;) {
|
||||
bool reachedEnd = false;
|
||||
for (int i = 0; i < NumBuffers && !reachedEnd; i++) {
|
||||
tmp.Data = data[i];
|
||||
reachedEnd = BufferBlock(tmp, fmt, chunks);
|
||||
BufferData(i, tmp);
|
||||
}
|
||||
Play();
|
||||
|
||||
for (; !reachedEnd;) {
|
||||
int next = -1;
|
||||
for (int i = 0; i < NumBuffers; i++) {
|
||||
if (IsCompleted(i)) { next = i; break; }
|
||||
|
@ -56,23 +84,10 @@ namespace SharpWave {
|
|||
|
||||
if (next == -1) { Thread.Sleep(10); continue; }
|
||||
if (pendingStop) break;
|
||||
|
||||
// decode up to around a second
|
||||
|
||||
tmp.Data = data[next];
|
||||
tmp.Length = 0;
|
||||
bool reachedEnd = false;
|
||||
|
||||
while (tmp.Length < secondSize) {
|
||||
if (!chunks.MoveNext()) { reachedEnd = true; break; }
|
||||
|
||||
AudioChunk src = chunks.Current;
|
||||
Buffer.BlockCopy(src.Data, 0, tmp.Data, tmp.Length, src.Length);
|
||||
tmp.Length += src.Length;
|
||||
}
|
||||
|
||||
PlayData(next, tmp);
|
||||
// need to specially handle last bit of audio
|
||||
if (reachedEnd) break;
|
||||
reachedEnd = BufferBlock(tmp, fmt, chunks);
|
||||
BufferData(next, tmp);
|
||||
}
|
||||
|
||||
while (!IsFinished()) { Thread.Sleep(10); }
|
||||
|
|
|
@ -48,12 +48,12 @@ namespace SharpWave {
|
|||
|
||||
public override bool IsCompleted(int index) {
|
||||
int processed = 0;
|
||||
uint buffer = 0;
|
||||
uint buffer = 0;
|
||||
lock (contextLock) {
|
||||
MakeContextCurrent();
|
||||
|
||||
AL.alGetSourcei(source, ALGetSourcei.BuffersProcessed, &processed);
|
||||
CheckError("GetSources");
|
||||
CheckError("GetSources");
|
||||
if (processed == 0) return completed[index];
|
||||
|
||||
AL.alSourceUnqueueBuffers(source, 1, &buffer);
|
||||
|
@ -80,7 +80,7 @@ namespace SharpWave {
|
|||
}
|
||||
}
|
||||
|
||||
public override void PlayData(int index, AudioChunk chunk) {
|
||||
public override void BufferData(int index, AudioChunk chunk) {
|
||||
fixed (byte* data = chunk.Data) {
|
||||
uint buffer = bufferIDs[index];
|
||||
completed[index] = false;
|
||||
|
@ -88,17 +88,23 @@ namespace SharpWave {
|
|||
lock (contextLock) {
|
||||
MakeContextCurrent();
|
||||
AL.alBufferData(buffer, dataFormat, (IntPtr)data,
|
||||
chunk.Length, Format.SampleRate);
|
||||
chunk.Length, Format.SampleRate);
|
||||
CheckError("BufferData");
|
||||
|
||||
AL.alSourceQueueBuffers(source, 1, &buffer);
|
||||
CheckError("QueueBuffers");
|
||||
AL.alSourcePlay(source);
|
||||
CheckError("SourcePlay");
|
||||
CheckError("QueueBuffers");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Play() {
|
||||
lock (contextLock) {
|
||||
MakeContextCurrent();
|
||||
AL.alSourcePlay(source);
|
||||
CheckError("SourcePlay");
|
||||
}
|
||||
}
|
||||
|
||||
void CheckError(string location) {
|
||||
ALError error = AL.alGetError();
|
||||
if (error != ALError.NoError) {
|
||||
|
|
|
@ -70,7 +70,7 @@ namespace SharpWave {
|
|||
CheckError(result, "Open");
|
||||
}
|
||||
|
||||
public override void PlayData(int index, AudioChunk chunk) {
|
||||
public override void BufferData(int index, AudioChunk chunk) {
|
||||
if (chunk.Length > dataSizes[index]) {
|
||||
IntPtr ptr = dataHandles[index];
|
||||
if (ptr != IntPtr.Zero) Marshal.FreeHGlobal(ptr);
|
||||
|
@ -97,6 +97,8 @@ namespace SharpWave {
|
|||
CheckError(result, "Write");
|
||||
}
|
||||
|
||||
public override void Play() { }
|
||||
|
||||
void ApplyVolume(IntPtr handle, AudioChunk chunk) {
|
||||
if (volumePercent == 100) return;
|
||||
|
||||
|
|
|
@ -11,11 +11,9 @@ namespace SharpWave {
|
|||
chunk = new AudioChunk();
|
||||
}
|
||||
|
||||
AudioChunk chunk, rawChunk;
|
||||
AudioChunk chunk;
|
||||
Stream input;
|
||||
byte[] rawPcm;
|
||||
int rawIndex;
|
||||
|
||||
|
||||
SyncState oy = new SyncState(); // sync and verify incoming physical bitstream
|
||||
StreamState os = new StreamState(); // take physical pages, weld into a logical stream of packets
|
||||
Page og = new Page(); // one Ogg bitstream page. Vorbis packets are inside
|
||||
|
|
|
@ -932,6 +932,7 @@ static void CPE_MakeSelection(UInt8* data) {
|
|||
p2.Z = (Int16)Stream_GetU16_BE(&data[4]);
|
||||
|
||||
PackedCol c; data += 6;
|
||||
/* R,G,B,A are actually 16 bit unsigned integers */
|
||||
c.R = data[1]; c.G = data[3]; c.B = data[5]; c.A = data[7];
|
||||
Selections_Add(selectionId, p1, p2, c);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue