📄 snd_mix.pas
字号:
ps: playsound_p;
s, stop: Integer;
begin
snd_vol := Trunc(s_volume^.value * 256);
//Com_Printf ("%i to %i\n", paintedtime, endtime);
while (paintedtime < endtime) do
begin
// if paintbuffer is smaller than DMA buffer
_end := endtime;
if (endtime - paintedtime > PAINTBUFFER_SIZE) then
_end := paintedtime + PAINTBUFFER_SIZE;
// start any playsounds
while (True) do
begin
ps := s_pendingplays.next;
if (ps = @s_pendingplays) then
break; // no more pending sounds
if (ps^._begin <= paintedtime) then
begin
S_IssuePlaysound(ps);
continue;
end;
if (ps^._begin < _end) then
_end := ps^._begin; // stop here
break;
end;
// clear the paint buffer
if (s_rawend < paintedtime) then
begin
// Com_Printf ("clear\n");
FillChar(paintbuffer, (_end - paintedtime) * sizeof(portable_samplepair_t), 0);
end
else
begin // copy from the streaming sound source
//stop := (_end < s_rawend) ? _end : s_rawend;
if (_end < s_rawend) then
stop := _end
else
stop := s_rawend;
for i := paintedtime to stop - 1 do
begin
s := i and (MAX_RAW_SAMPLES - 1);
paintbuffer[i - paintedtime] := s_rawsamples_[s];
end;
// if (i != end)
// Com_Printf ("partial stream\n");
// else
// Com_Printf ("full stream\n");
for i := stop to _end - 1 do
begin
paintbuffer[i - paintedtime].left := 0;
paintbuffer[i - paintedtime].right := 0;
end;
end;
// paint in the channels.
for i := 0 to MAX_CHANNELS - 1 do //i++, ch++)
begin
ltime := paintedtime;
while (ltime < _end) do
begin
if ((channels[i].sfx = nil) or ((channels[i].leftvol = 0) and (channels[i].rightvol = 0))) then
break;
// max painting is to the end of the buffer
count := _end - ltime;
// might be stopped by running out of data
if (channels[i]._end - ltime < count) then
count := channels[i]._end - ltime;
sc := S_LoadSound(channels[i].sfx);
if (sc = nil) then
break;
if ((count > 0) and (channels[i].sfx <> nil)) then
begin
if (sc^.width = 1) then // FIXME; 8 bit asm is wrong now
S_PaintChannelFrom8(@channels[i], sc, count, ltime - paintedtime)
else
S_PaintChannelFrom16(@channels[i], sc, count, ltime - paintedtime);
Inc(ltime, count);
end;
// if at end of loop, restart
if (ltime >= channels[i]._end) then
begin
if (channels[i].autosound) then
begin // autolooping sounds always go back to start
channels[i].pos := 0;
channels[i]._end := ltime + sc^.length;
end
else if (sc^.loopstart >= 0) then
begin
channels[i].pos := sc^.loopstart;
channels[i]._end := ltime + sc^.length - channels[i].pos;
end
else
begin // channel just stopped
channels[i].sfx := nil;
end;
end;
end;
end;
// transfer out according to DMA format
S_TransferPaintBuffer(_end);
paintedtime := _end;
end;
end;
procedure S_InitScaletable;
var
i, j, scale: Integer;
begin
s_volume^.modified := false;
for i := 0 to 31 do
begin
scale := Trunc(i * 8 * 256 * s_volume^.value);
for j := 0 to 255 do
snd_scaletable[i][j] := ShortInt(j) * scale;
end;
end;
procedure S_PaintChannelFrom8(ch: channel_p; sc: sfxcache_p; count, offset: Integer);
var
data, i: Integer;
lscale, rscale: PIntegerArray;
sfx: PByteArray;
samp: portable_samplepair_p;
begin
if (ch^.leftvol > 255) then
ch^.leftvol := 255;
if (ch^.rightvol > 255) then
ch^.rightvol := 255;
//ZOID-- shr 11 has been changed to shr 3, shr 11 didn't make much sense
//as it would always be zero.
lscale := @snd_scaletable[ch^.leftvol shr 3];
rscale := @snd_scaletable[ch^.rightvol shr 3];
sfx := Pointer(Cardinal(@sc^.data) + ch^.pos);
samp := @paintbuffer[offset];
for i := 0 to count - 1 do
begin
data := sfx[i];
samp.left := samp.left + lscale[data];
samp.right := samp.right + rscale[data];
Inc(samp);
end;
ch^.pos := ch^.pos + count;
end;
(*
procedure S_PaintChannelFrom8(ch : channel_p; sc : sfxcache_p; count, offset: Integer);
asm
push esi
push edi
push ebx
push ebp
mov ebx,ds:dword ptr[4+16+esp]
mov esi,ds:dword ptr[8+16+esp]
mov eax,ds:dword ptr[4+ebx]
mov edx,ds:dword ptr[8+ebx]
cmp eax,255
jna @LLeftSet
mov eax,255
@LLeftSet:
cmp edx,255
jna @LRightSet
mov edx,255
@LRightSet:
and eax,0F8h
add esi,20
and edx,0F8h
mov edi,ds:dword ptr[16+ebx]
mov ecx,ds:dword ptr[12+16+esp]
add esi,edi
shl eax,7
add edi,ecx
shl edx,7
mov ds:dword ptr[16+ebx],edi
add eax,offset snd_scaletable
add edx,offset snd_scaletable
sub ebx,ebx
mov bl,ds:byte ptr[-1+esi+ecx*1]
test ecx,1
jz @LMix8Loop
mov edi,ds:dword ptr[eax+ebx*4]
mov ebp,ds:dword ptr[edx+ebx*4]
add edi,ds:dword ptr[paintbuffer+0-8+ecx*8]
add ebp,ds:dword ptr[paintbuffer+4-8+ecx*8]
mov ds:dword ptr[paintbuffer+0-8+ecx*8],edi
mov ds:dword ptr[paintbuffer+4-8+ecx*8],ebp
mov bl,ds:byte ptr[-2+esi+ecx*1]
dec ecx
jz @LDone
@LMix8Loop:
mov edi,ds:dword ptr[eax+ebx*4]
mov ebp,ds:dword ptr[edx+ebx*4]
add edi,ds:dword ptr[paintbuffer+0-8+ecx*8]
add ebp,ds:dword ptr[paintbuffer+4-8+ecx*8]
mov bl,ds:byte ptr[-2+esi+ecx*1]
mov ds:dword ptr[paintbuffer+0-8+ecx*8],edi
mov ds:dword ptr[paintbuffer+4-8+ecx*8],ebp
mov edi,ds:dword ptr[eax+ebx*4]
mov ebp,ds:dword ptr[edx+ebx*4]
mov bl,ds:byte ptr[-3+esi+ecx*1]
add edi,ds:dword ptr[paintbuffer+0-8*2+ecx*8]
add ebp,ds:dword ptr[paintbuffer+4-8*2+ecx*8]
mov ds:dword ptr[paintbuffer+0-8*2+ecx*8],edi
mov ds:dword ptr[paintbuffer+4-8*2+ecx*8],ebp
sub ecx,2
jnz @LMix8Loop
@LDone:
pop ebp
pop ebx
pop edi
pop esi
ret
end;
*)
procedure S_PaintChannelFrom16(ch: channel_p; sc: sfxcache_p; count, offset: Integer);
var
data,
left,
right,
leftvol,
rightvol,
i: Integer;
sfx: PSmallIntArray;
samp: portable_samplepair_p;
begin
leftvol := ch^.leftvol * snd_vol;
rightvol := ch^.rightvol * snd_vol;
sfx := Pointer(Cardinal(@sc^.data) + ch^.pos * SizeOf(SmallInt));
samp := @paintbuffer[offset];
for i := 0 to count - 1 do
begin
data := sfx[i];
asm
mov edi, data
// left = (data * leftvol)>>8;
mov eax, edi // data
imul leftvol
sar eax, 8
mov left, eax
// right = (data * rightvol)>>8;
mov eax, edi // data
imul rightvol
sar eax, 8
mov right, eax
end;
samp.left := samp.left + left;
samp.right := samp.right + right;
Inc(samp);
end;
ch^.pos := ch^.pos + count;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -