void Callback()
{
lock (_mutex)
{
for (int l = 0; l < MaxDigitalTracks + MaxDigitalFadeTracks; l++)
{
var track = _track[l];
if (track.Used)
{
// Ignore tracks which are about to finish. Also, if it did finish in the meantime,
// mark it as unused.
if (track.Stream == null)
{
if (!_mixer.IsSoundHandleActive(track.MixChanHandle))
{
_track[l].Clear();
}
continue;
}
if (_pause)
{
return;
}
if (track.VolFadeUsed)
{
if (track.VolFadeStep < 0)
{
if (track.vol > track.VolFadeDest)
{
track.vol += track.VolFadeStep;
if (track.vol < track.VolFadeDest)
{
track.vol = track.VolFadeDest;
track.VolFadeUsed = false;
}
if (track.vol == 0)
{
// Fade out complete . remove this track
FlushTrack(track);
continue;
}
}
}
else if (track.VolFadeStep > 0)
{
if (track.vol < track.VolFadeDest)
{
track.vol += track.VolFadeStep;
if (track.vol > track.VolFadeDest)
{
track.vol = track.VolFadeDest;
track.VolFadeUsed = false;
}
}
}
// Debug.WriteLine("Fade: sound({0}), Vol({1})", track.SoundId, track.vol / 1000);
}
if (!track.SouStreamUsed)
{
Debug.Assert(track.Stream != null);
byte[] tmpSndBufferPtr = null;
int curFeedSize = 0;
if (track.CurRegion == -1)
{
SwitchToNextRegion(track);
if (track.Stream == null) // Seems we reached the end of the stream
{
continue;
}
}
int bits = _sound.GetBits(track.SoundDesc);
int channels = _sound.GetChannels(track.SoundDesc);
int feedSize = track.FeedSize / _callbackFps;
if (track.Stream.IsEndOfData)
{
feedSize *= 2;
}
if ((bits == 12) || (bits == 16))
{
if (channels == 1)
{
feedSize &= ~1;
}
if (channels == 2)
{
feedSize &= ~3;
}
}
else if (bits == 8)
{
if (channels == 2)
{
feedSize &= ~1;
}
}
else
{
// Console.Error.WriteLine("IMuseDigita::callback: Unexpected sample width, {0} bits", bits);
continue;
}
if (feedSize == 0)
{
continue;
}
do
{
switch (bits)
{
case 12:
byte[] tmpPtr;
feedSize += track.DataMod12Bit;
int tmpFeedSize12Bits = (feedSize * 3) / 4;
int tmpLength12Bits = (tmpFeedSize12Bits / 3) * 4;
track.DataMod12Bit = feedSize - tmpLength12Bits;
int tmpOffset = (track.RegionOffset * 3) / 4;
int tmpFeedSize = _sound.GetDataFromRegion(track.SoundDesc, track.CurRegion, out tmpPtr, tmpOffset, tmpFeedSize12Bits);
curFeedSize = BundleCodecs.Decode12BitsSample(tmpPtr, out tmpSndBufferPtr, tmpFeedSize);
break;
case 16:
curFeedSize = _sound.GetDataFromRegion(track.SoundDesc, track.CurRegion, out tmpSndBufferPtr, track.RegionOffset, feedSize);
if (channels == 1)
{
curFeedSize &= ~1;
}
if (channels == 2)
{
curFeedSize &= ~3;
}
break;
case 8:
curFeedSize = _sound.GetDataFromRegion(track.SoundDesc, track.CurRegion, out tmpSndBufferPtr, track.RegionOffset, feedSize);
if (RadioChatterSFX && track.SoundId == 10000)
{
if (curFeedSize > feedSize)
{
curFeedSize = feedSize;
}
var buf = new byte[curFeedSize];
int index = 0;
int count = curFeedSize - 4;
var ptr_1 = 0;
var ptr_2 = 4;
int value = tmpSndBufferPtr[ptr_1 + 0] - 0x80;
value += tmpSndBufferPtr[ptr_1 + 1] - 0x80;
value += tmpSndBufferPtr[ptr_1 + 2] - 0x80;
value += tmpSndBufferPtr[ptr_1 + 3] - 0x80;
do
{
int t = tmpSndBufferPtr[ptr_1++];
int v = t - (value / 4);
value = tmpSndBufferPtr[ptr_2++] - 0x80 + (value - t + 0x80);
buf[index++] = (byte)(v * 2 + 0x80);
}while ((--count) != 0);
buf[curFeedSize - 1] = 0x80;
buf[curFeedSize - 2] = 0x80;
buf[curFeedSize - 3] = 0x80;
buf[curFeedSize - 4] = 0x80;
tmpSndBufferPtr = buf;
}
if (channels == 2)
{
curFeedSize &= ~1;
}
break;
}
if (curFeedSize > feedSize)
{
curFeedSize = feedSize;
}
if (_mixer.IsReady)
{
track.Stream.QueueBuffer(tmpSndBufferPtr, curFeedSize, true, MakeMixerFlags(track));
track.RegionOffset += curFeedSize;
}
else
{
tmpSndBufferPtr = null;
}
if (_sound.IsEndOfRegion(track.SoundDesc, track.CurRegion))
{
SwitchToNextRegion(track);
if (track.Stream == null) // Seems we reached the end of the stream
{
break;
}
}
feedSize -= curFeedSize;
Debug.Assert(feedSize >= 0);
} while (feedSize != 0);
}
if (_mixer.IsReady)
{
_mixer.SetChannelVolume(track.MixChanHandle, track.Volume);
_mixer.SetChannelBalance(track.MixChanHandle, track.Pan);
}
}
}
}
}