mirror of
https://github.com/ptitSeb/Serious-Engine
synced 2024-12-27 07:54:51 +01:00
373 lines
11 KiB
NASM
373 lines
11 KiB
NASM
|
; /* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */
|
||
|
;
|
||
|
; ------- YOU DO NOT NEED THIS FILE UNDER WIN32 AT THE MOMENT. -------
|
||
|
;
|
||
|
; Chances are, you will need NASM (http://www.octium.net/nasm/) to assemble
|
||
|
; this file.
|
||
|
;
|
||
|
; If we were smart, we'd move all the inline asm to similar files, which
|
||
|
; cleans up the C, and makes the assembly (ahem) more portable. NASM can
|
||
|
; generate Visual C compatible object files as well as Linux ELF and Intel
|
||
|
; Mac Mach-O binaries.
|
||
|
;
|
||
|
; --ryan.
|
||
|
|
||
|
; asm shortcuts
|
||
|
%define O offset
|
||
|
%define Q qword
|
||
|
%define D dword
|
||
|
%define W word
|
||
|
%define B byte
|
||
|
|
||
|
%define TRUE 1
|
||
|
%define FALSE 0
|
||
|
|
||
|
; ************************
|
||
|
; ** Start Data Block **
|
||
|
; ************************
|
||
|
SECTION .data
|
||
|
|
||
|
global slMixerBufferSize
|
||
|
global bEndOfSound
|
||
|
global bNotLoop
|
||
|
global fLeftOfs
|
||
|
global fLeftStep
|
||
|
global fOfsDelta
|
||
|
global fPhase
|
||
|
global fRightOfs
|
||
|
global fRightStep
|
||
|
global fSoundSampleRate
|
||
|
global fStep
|
||
|
global fixLeftOfs
|
||
|
global fixRightOfs
|
||
|
global mmSurroundFactor
|
||
|
global mmVolumeGain
|
||
|
global pswSrcBuffer
|
||
|
global pvMixerBuffer
|
||
|
global slLastLeftSample
|
||
|
global slLastRightSample
|
||
|
global slLeftFilter
|
||
|
global slLeftVolume
|
||
|
global slRightFilter
|
||
|
global slRightVolume
|
||
|
global slSoundBufferSize
|
||
|
|
||
|
slMixerBufferSize dd 0
|
||
|
pvMixerBuffer dd 0
|
||
|
pswSrcBuffer dd 0
|
||
|
slLeftVolume dd 0
|
||
|
slRightVolume dd 0
|
||
|
slLeftFilter dd 0
|
||
|
slRightFilter dd 0
|
||
|
slLastLeftSample dd 0
|
||
|
slLastRightSample dd 0
|
||
|
slSoundBufferSize dd 0
|
||
|
fSoundSampleRate dd 0
|
||
|
fPhase dd 0
|
||
|
fOfsDelta dd 0
|
||
|
fStep dd 0
|
||
|
fLeftStep dd 0
|
||
|
fRightStep dd 0
|
||
|
fLeftOfs dd 0
|
||
|
fRightOfs dd 0
|
||
|
fixLeftOfs dd 0, 0
|
||
|
fixRightOfs dd 0, 0
|
||
|
mmSurroundFactor dd 0, 0
|
||
|
mmLeftStep dd 0, 0
|
||
|
mmRightStep dd 0, 0
|
||
|
mmVolumeGain dd 0, 0
|
||
|
mmInvFactor dd 0x00007FFF, 0x00007FFF
|
||
|
bNotLoop dd 0
|
||
|
bEndOfSound dd 0
|
||
|
f65536 dd 65536.0
|
||
|
f4G dd 4294967296.0
|
||
|
|
||
|
|
||
|
; ************************
|
||
|
; ** End Data Block **
|
||
|
; ************************
|
||
|
|
||
|
|
||
|
; ************************
|
||
|
; ** Start Code Block **
|
||
|
; ************************
|
||
|
SEGMENT .text
|
||
|
|
||
|
global MixMono_asm
|
||
|
MixMono_asm:
|
||
|
push ebx ; Save GCC register.
|
||
|
; convert from floats to fixints 32:16
|
||
|
fld D [fLeftOfs]
|
||
|
fmul D [f65536]
|
||
|
fld D [fRightOfs]
|
||
|
fmul D [f65536]
|
||
|
fld D [fLeftStep]
|
||
|
fmul D [f65536]
|
||
|
fld D [fRightStep]
|
||
|
fmul D [f4G]
|
||
|
fistp Q [mmRightStep] ; fixint 32:32
|
||
|
fistp Q [mmLeftStep] ; fixint 32:16
|
||
|
fistp Q [fixRightOfs] ; fixint 32:16
|
||
|
fistp Q [fixLeftOfs] ; fixint 32:16
|
||
|
|
||
|
; get last played sample (for filtering purposes)
|
||
|
movzx eax,W [slLastRightSample]
|
||
|
movzx edx,W [slLastLeftSample]
|
||
|
shl eax,16
|
||
|
or eax,edx
|
||
|
movd mm6,eax ; MM6 = 0 | 0 || lastRightSample | lastLeftSample
|
||
|
|
||
|
; get volume
|
||
|
movd mm5,D [slRightVolume]
|
||
|
movd mm0,D [slLeftVolume]
|
||
|
psllq mm5,32
|
||
|
por mm5,mm0 ; MM5 = rightVolume || leftVolume
|
||
|
|
||
|
; get filter
|
||
|
mov eax,D [slRightFilter]
|
||
|
mov edx,D [slLeftFilter]
|
||
|
shl eax,16
|
||
|
or eax,edx
|
||
|
movd mm7,eax ; MM7 = 0 | 0 || rightFilter | leftFilter
|
||
|
|
||
|
; get offset of each channel inside sound and loop thru destination buffer
|
||
|
mov W [mmRightStep],0
|
||
|
movzx eax,W [fixLeftOfs]
|
||
|
movzx edx,W [fixRightOfs]
|
||
|
shl edx,16
|
||
|
or eax,edx ; EAX = right ofs frac | left ofs frac
|
||
|
mov ebx,D [fixLeftOfs+2] ; EBX = left ofs int
|
||
|
mov edx,D [fixRightOfs+2] ; EDX = right ofs int
|
||
|
mov esi,D [pswSrcBuffer] ; ESI = source sound buffer start ptr
|
||
|
mov edi,D [pvMixerBuffer] ; EDI = mixer buffer ptr
|
||
|
mov ecx,D [slMixerBufferSize] ; ECX = samples counter
|
||
|
|
||
|
sampleLoop_MixMono:
|
||
|
; check if source offsets came to the end of source sound buffer
|
||
|
cmp ebx,D [slSoundBufferSize]
|
||
|
jl lNotEnd_MixMono
|
||
|
sub ebx,D [slSoundBufferSize]
|
||
|
push D [bNotLoop]
|
||
|
pop D [bEndOfSound]
|
||
|
lNotEnd_MixMono:
|
||
|
; same for right channel
|
||
|
cmp edx,D [slSoundBufferSize]
|
||
|
jl rNotEnd_MixMono
|
||
|
sub edx,D [slSoundBufferSize]
|
||
|
push D [bNotLoop]
|
||
|
pop D [bEndOfSound]
|
||
|
rNotEnd_MixMono:
|
||
|
|
||
|
; check end of sample
|
||
|
cmp ecx,0
|
||
|
jle near loopEnd_MixMono
|
||
|
cmp D [bEndOfSound],TRUE
|
||
|
je near loopEnd_MixMono
|
||
|
|
||
|
; get sound samples
|
||
|
movd mm1,D [esi+ ebx*2] ; MM1 = 0 | 0 || nextLeftSample | leftSample
|
||
|
movd mm2,D [esi+ edx*2] ; MM2 = 0 | 0 || nextRightSample | RightSample
|
||
|
psllq mm2,32
|
||
|
por mm1,mm2 ; MM1 = nextRightSample | rightSample || nextLeftSample | leftSample
|
||
|
|
||
|
; calc linear interpolation factor (strength)
|
||
|
movd mm3,eax ; MM3 = 0 | 0 || right frac | left frac
|
||
|
punpcklwd mm3,mm3
|
||
|
psrlw mm3,1 ; MM3 = rightFrac | rightFrac || leftFrac | leftFrac
|
||
|
pxor mm3,Q [mmInvFactor] ; MM3 = rightFrac | 1-rightFrac || leftFrac | 1-leftFrac
|
||
|
; apply linear interpolation
|
||
|
pmaddwd mm1,mm3
|
||
|
psrad mm1,15
|
||
|
packssdw mm1,mm1 ; MM1 = ? | ? || linearRightSample | linearLeftSample
|
||
|
|
||
|
; apply filter
|
||
|
psubsw mm1,mm6
|
||
|
pmulhw mm1,mm7
|
||
|
psllw mm1,1
|
||
|
paddsw mm1,mm6
|
||
|
movq mm6,mm1
|
||
|
|
||
|
; apply volume adjustment
|
||
|
movq mm0,mm5
|
||
|
psrad mm0,16
|
||
|
packssdw mm0,mm0
|
||
|
pmulhw mm1,mm0
|
||
|
psllw mm1,1
|
||
|
pxor mm1,Q [mmSurroundFactor]
|
||
|
paddd mm5,Q [mmVolumeGain] ; modify volume
|
||
|
|
||
|
; unpack to 32bit and mix it into destination buffer
|
||
|
punpcklwd mm1,mm1
|
||
|
psrad mm1,16 ; MM1 = finalRightSample || finalLeftSample
|
||
|
paddd mm1,Q [edi]
|
||
|
movq Q [edi],mm1
|
||
|
|
||
|
; advance to next samples in source sound
|
||
|
add eax,D [mmRightStep+0]
|
||
|
adc edx,D [mmRightStep+4]
|
||
|
add ax,W [mmLeftStep +0]
|
||
|
adc ebx,D [mmLeftStep +2]
|
||
|
add edi,8
|
||
|
dec ecx
|
||
|
jmp sampleLoop_MixMono
|
||
|
|
||
|
loopEnd_MixMono:
|
||
|
; store modified asm local vars
|
||
|
mov D [fixLeftOfs +0],eax
|
||
|
shr eax,16
|
||
|
mov D [fixRightOfs+0],eax
|
||
|
mov D [fixLeftOfs +2],ebx
|
||
|
mov D [fixRightOfs+2],edx
|
||
|
movd eax,mm6
|
||
|
mov edx,eax
|
||
|
and eax,0x0000FFFF
|
||
|
shr edx,16
|
||
|
mov D [slLastLeftSample],eax
|
||
|
mov D [slLastRightSample],edx
|
||
|
pop ebx ; Restore GCC register.
|
||
|
emms
|
||
|
ret
|
||
|
|
||
|
|
||
|
global MixStereo_asm
|
||
|
MixStereo_asm:
|
||
|
push ebx ; Save GCC register.
|
||
|
; convert from floats to fixints 32:16
|
||
|
fld D [fLeftOfs]
|
||
|
fmul D [f65536]
|
||
|
fld D [fRightOfs]
|
||
|
fmul D [f65536]
|
||
|
fld D [fLeftStep]
|
||
|
fmul D [f65536]
|
||
|
fld D [fRightStep]
|
||
|
fmul D [f4G]
|
||
|
fistp Q [mmRightStep] ; fixint 32:32
|
||
|
fistp Q [mmLeftStep] ; fixint 32:16
|
||
|
fistp Q [fixRightOfs] ; fixint 32:16
|
||
|
fistp Q [fixLeftOfs] ; fixint 32:16
|
||
|
|
||
|
; get last played sample (for filtering purposes)
|
||
|
movzx eax,W [slLastRightSample]
|
||
|
movzx edx,W [slLastLeftSample]
|
||
|
shl eax,16
|
||
|
or eax,edx
|
||
|
movd mm6,eax ; MM6 = 0 | 0 || lastRightSample | lastLeftSample
|
||
|
|
||
|
; get volume
|
||
|
movd mm5,D [slRightVolume]
|
||
|
movd mm0,D [slLeftVolume]
|
||
|
psllq mm5,32
|
||
|
por mm5,mm0 ; MM5 = rightVolume || leftVolume
|
||
|
|
||
|
; get filter
|
||
|
mov eax,D [slRightFilter]
|
||
|
mov edx,D [slLeftFilter]
|
||
|
shl eax,16
|
||
|
or eax,edx
|
||
|
movd mm7,eax ; MM7 = 0 | 0 || rightFilter | leftFilter
|
||
|
|
||
|
; get offset of each channel inside sound and loop thru destination buffer
|
||
|
mov W [mmRightStep],0
|
||
|
movzx eax,W [fixLeftOfs]
|
||
|
movzx edx,W [fixRightOfs]
|
||
|
shl edx,16
|
||
|
or eax,edx ; EAX = right ofs frac | left ofs frac
|
||
|
mov ebx,D [fixLeftOfs+2] ; EBX = left ofs int
|
||
|
mov edx,D [fixRightOfs+2] ; EDX = right ofs int
|
||
|
mov esi,D [pswSrcBuffer] ; ESI = source sound buffer start ptr
|
||
|
mov edi,D [pvMixerBuffer] ; EDI = mixer buffer ptr
|
||
|
mov ecx,D [slMixerBufferSize] ; ECX = samples counter
|
||
|
|
||
|
sampleLoop_MixStereo:
|
||
|
; check if source offsets came to the end of source sound buffer
|
||
|
cmp ebx,D [slSoundBufferSize]
|
||
|
jl lNotEnd_MixStereo
|
||
|
sub ebx,D [slSoundBufferSize]
|
||
|
push D [bNotLoop]
|
||
|
pop D [bEndOfSound]
|
||
|
lNotEnd_MixStereo:
|
||
|
; same for right channel
|
||
|
cmp edx,D [slSoundBufferSize]
|
||
|
jl rNotEnd_MixStereo
|
||
|
sub edx,D [slSoundBufferSize]
|
||
|
push D [bNotLoop]
|
||
|
pop D [bEndOfSound]
|
||
|
rNotEnd_MixStereo:
|
||
|
|
||
|
; check end of sample
|
||
|
cmp ecx,0
|
||
|
jle near loopEnd_MixStereo
|
||
|
cmp D [bEndOfSound],TRUE
|
||
|
je near loopEnd_MixStereo
|
||
|
|
||
|
; get sound samples
|
||
|
movq mm1,Q [esi+ ebx*4]
|
||
|
movq mm2,Q [esi+ edx*4]
|
||
|
pslld mm1,16
|
||
|
psrad mm1,16 ; MM1 = 0 | nextLeftSample || 0 | leftSample
|
||
|
psrad mm2,16 ; MM2 = 0 | nextRightSample || 0 | rightSample
|
||
|
packssdw mm1,mm2 ; MM1 = nextRightSample | rightSample || nextLeftSample | leftSample
|
||
|
|
||
|
; calc linear interpolation factor (strength)
|
||
|
movd mm3,eax ; MM3 = 0 | 0 || right frac | left frac
|
||
|
punpcklwd mm3,mm3
|
||
|
psrlw mm3,1 ; MM3 = rightFrac | rightFrac || leftFrac | leftFrac
|
||
|
pxor mm3,Q [mmInvFactor] ; MM3 = rightFrac | 1-rightFrac || leftFrac | 1-leftFrac
|
||
|
; apply linear interpolation
|
||
|
pmaddwd mm1,mm3
|
||
|
psrad mm1,15
|
||
|
packssdw mm1,mm1 ; MM1 = ? | ? || linearRightSample | linearLeftSample
|
||
|
|
||
|
; apply filter
|
||
|
psubsw mm1,mm6
|
||
|
pmulhw mm1,mm7
|
||
|
psllw mm1,1
|
||
|
paddsw mm1,mm6
|
||
|
movq mm6,mm1
|
||
|
|
||
|
; apply volume adjustment
|
||
|
movq mm0,mm5
|
||
|
psrad mm0,16
|
||
|
packssdw mm0,mm0
|
||
|
pmulhw mm1,mm0
|
||
|
psllw mm1,1
|
||
|
pxor mm1,Q [mmSurroundFactor]
|
||
|
paddd mm5,Q [mmVolumeGain] ; modify volume
|
||
|
|
||
|
; unpack to 32bit and mix it into destination buffer
|
||
|
punpcklwd mm1,mm1
|
||
|
psrad mm1,16 ; MM1 = finalRightSample || finalLeftSample
|
||
|
paddd mm1,Q [edi]
|
||
|
movq Q [edi],mm1
|
||
|
|
||
|
; advance to next samples in source sound
|
||
|
add eax,D [mmRightStep+0]
|
||
|
adc edx,D [mmRightStep+4]
|
||
|
add ax,W [mmLeftStep +0]
|
||
|
adc ebx,D [mmLeftStep +2]
|
||
|
add edi,8
|
||
|
dec ecx
|
||
|
jmp sampleLoop_MixStereo
|
||
|
|
||
|
loopEnd_MixStereo:
|
||
|
; store modified asm local vars
|
||
|
mov D [fixLeftOfs +0],eax
|
||
|
shr eax,16
|
||
|
mov D [fixRightOfs+0],eax
|
||
|
mov D [fixLeftOfs +2],ebx
|
||
|
mov D [fixRightOfs+2],edx
|
||
|
movd eax,mm6
|
||
|
mov edx,eax
|
||
|
and eax,0x0000FFFF
|
||
|
shr edx,16
|
||
|
mov D [slLastLeftSample],eax
|
||
|
mov D [slLastRightSample],edx
|
||
|
emms
|
||
|
pop ebx ; Restore GCC register.
|
||
|
ret
|
||
|
|
||
|
; ************************
|
||
|
; ** End Code Block **
|
||
|
; ************************
|
||
|
|