home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Large Pack of OldSkool DOS MOD Trackers
/
tsm.zip
/
Replay
/
TSMReplay.asm
< prev
next >
Wrap
Assembly Source File
|
2004-10-06
|
58KB
|
1,798 lines
; ------------------------------------------------------
; TSM v1.1 Replay routine
; Written by Franck 'hitchhikr' Charlet/TRSI
; ------------------------------------------------------
; buildblock RELEASE
; CAPT [BINDIR]\ml.exe /c /coff /I"[INCLUDEDIR]" "%2"
; buildblockend
; buildblock DEBUG
; CAPT [BINDIR]\ml.exe /Zd /Zi /c /coff /I"[INCLUDEDIR]" "%2"
; buildblockend
; --------------- File model
.386
.model flat,stdcall
option casemap:none
; --------------- Includes
include windows.inc
include kernel32.inc
include user32.inc
include dsound.inc
include DSoundConst.inc
; --------------- Constants
TSM_INS_WF_CUST equ 5
TSM_DSP_DELAY equ 4
TSM_MAX_NOTES equ 120
; --------------- Structures
TSM_INSTRUMENT_DAT STRUCT
Operator BYTE ?
Waveform BYTE ?
PhaseShift WORD ?
Attack_Volume BYTE ?
Attack WORD ?
Decay_Volume BYTE ?
Decay WORD ?
Sustain_Volume BYTE ?
Sustain WORD ?
Release_Volume BYTE ?
Release WORD ?
Attack_Volume_Delta BYTE ?
Decay_Volume_Delta BYTE ?
Sustain_Volume_Delta BYTE ?
Release_Volume_Delta BYTE ?
TSM_INSTRUMENT_DAT ENDS
TSM_SEQUENCE_DAT STRUCT
Note BYTE 16 dup (?)
Instrument WORD 16 dup (?)
Volume BYTE 16 dup (?)
Panning BYTE 16 dup (?)
DspMask BYTE 16 dup (?)
Dsp BYTE 16 dup (?)
DspDatas1 BYTE 16 dup (?)
DspDatas2 BYTE 16 dup (?)
DspDatas3 BYTE 16 dup (?)
Fx BYTE 16 dup (?)
FxDatas BYTE 16 dup (?)
TSM_SEQUENCE_DAT ENDS
TSM_SONG_DAT STRUCT
Sequence WORD ?
Transpose BYTE ?
Volume BYTE ?
TSM_SONG_DAT ENDS
TSM_INSTRUMENT_VARS STRUCT
Volume REAL4 ?
Ticks DWORD ?
RndVal1 REAL4 ?
RndVal2 REAL4 ?
wrpos REAL4 ?
FPos REAL4 ?
Frac_Lo_Pos DWORD ?
Oscillator DWORD ?
TSM_INSTRUMENT_VARS ENDS
TSM_SEQUENCE STRUCT
Current_Sequence DWORD ?
Current_Instrument DWORD ?
Current_Instrument_Dat DWORD ?
Instrument_NbrComb DWORD ?
Freq_Lo_Speed DWORD ?
Freq_Hi_Speed DWORD ?
Pan REAL4 ?
Volume REAL4 ?
Position_Volume REAL4 ?
Position_Transpose DWORD ?
Global_Volume REAL4 ?
Formant_Param1 DWORD ?
Disto_Param REAL4 ?
Disto_Abs_Input REAL4 ?
Hi_Pass_Param1 REAL4 ?
Hi_Pass_Param2 REAL4 ?
Hi_Pass_In1 REAL4 ?
Hi_Pass_Out1 REAL4 ?
Hi_Pass_In2 REAL4 ?
Hi_Pass_Out2 REAL4 ?
Lo_Pass_Param1 REAL4 ?
Lo_Pass_Param2 REAL4 ?
Lo_Pass_In1 REAL4 ?
Lo_Pass_Out1 REAL4 ?
Lo_Pass_In2 REAL4 ?
Lo_Pass_Out2 REAL4 ?
VCF_Pass_Param1 REAL4 ?
VCF_Pass_Param2 REAL4 ?
VCF_Pass_Out1 REAL4 ?
VCF_Pass_Out2 REAL4 ?
VCF_Pass_Out3 REAL4 ?
VCF_Pass_Out4 REAL4 ?
VCF_Pass_In1 REAL4 ?
VCF_Pass_In2 REAL4 ?
VCF_Pass_In3 REAL4 ?
VCF_Pass_In4 REAL4 ?
Delay_Cursor DWORD ?
Delay_Value DWORD ?
Delay_Left_FeedBack_Value REAL4 ?
Delay_Right_FeedBack_Value REAL4 ?
Delay_Left_Buffer DWORD ?
Delay_Right_Buffer DWORD ?
Arpeggio DWORD ?
Vol_Side REAL4 ?
Pitch_Bend_Freq DWORD ?
Current_Freq DWORD ?
Pitch_Bend DWORD ?
Vibrato DWORD ?
Vibrato_Freq DWORD ?
Vibrato_Tick DWORD ?
Tone_Portamento_Speed DWORD ?
Tone_Portamento_Note DWORD ?
Sound_Datas REAL4 ?
Old_Vol_Side_Down DWORD ?
Old_Vol_Side_Up DWORD ?
Old_Pitch_Bend_Down DWORD ?
Old_Pitch_Bend_Up DWORD ?
Old_Vibrato DWORD ?
Old_Arpeggio DWORD ?
Old_Tone_Portamento_Speed DWORD ?
Old_Tone_Portamento_Note DWORD ?
Cur_Note DWORD ?
Cur_Freq DWORD ?
Cur_Instrument_Vars TSM_INSTRUMENT_VARS 256 dup (<?>)
Formant_Tmp_Mem REAL8 10 dup (?)
Source_Formant REAL8 11 dup (?)
Dest_Formant REAL8 11 dup (?)
TSM_SEQUENCE ENDS
; --------------- Datas section
.data
TSM_Mixing_Buffer_Stereo DWORD 0
TSM_DSound_Context DWORD 0
TSM_Sound_Buffer_Desc DSBUFFERDESC <>
TSM_Sound_Buffer DWORD 0
TSM_Wave_Format WAVEFORMATEX <>
TSM_Buffer_Pos DWORD 0
TSM_Old_Buffer_Pos DWORD 0
TSM_Audio_Ptr1 DWORD 0
TSM_Audio_Bytes1 DWORD 0
TSM_Audio_Ptr2 DWORD 0
TSM_Audio_Bytes2 DWORD 0
TSM_Song_Position DWORD 0
TSM_Song_Restart DWORD 0
TSM_Cur_Ticks DWORD 0
TSM_Fx_Ticks DWORD 0
TSM_Speed_Tick DWORD 0
TSM_Speed_Counter DWORD 0
TSM_Tempo DWORD 0
TSM_Fx_Tempo DWORD 0
TSM_Tempo_Ticks DWORD 0
TSM_Fx_Tempo_Ticks DWORD 0
TSM_Can_Play DWORD 0
TSM_BufferSize DWORD 0
TSM_Instr_Dat_Number DWORD 0
TSM_Instr_Dat_Vars DWORD 0
TSM_Sequences_Dats DWORD 0
TSM_Cur_Play_Pos DWORD 0
TSM_Final_Signal REAL4 0.0
TSM_Module_Instruments DWORD 0
TSM_Module_Positions DWORD 0
TSM_Module_Sequences DWORD 0
TSM_Nbr_Instruments DWORD 0
TSM_Nbr_Positions DWORD 0
TSM_Length_Track DWORD 0
TSM_Nbr_Sequences DWORD 0
TSM_Synth_CallBack DWORD 0
TSM_Max_Buffer DWORD 44100
TSM_Global_Volume REAL4 0.0
TSM_Flt32767 REAL4 32767.0
TSM_Flt32768 REAL4 32768.0
TSM_Fltm1 REAL4 -1.0
TSM_Flt025 REAL4 0.25
TSM_Flt05 REAL4 0.5
TSM_Fltm05 REAL4 -0.5
TSM_Flt005 REAL4 0.05
TSM_Flt1 REAL4 1.0
TSM_Fltm005 REAL4 -0.05
TSM_Flt100 REAL4 100.0
TSM_Flt001 REAL4 0.01
TSM_Flt00001 REAL4 0.0001
TSM_Flt01 REAL4 0.1
TSM_FltPI2 REAL4 6.2831853071
TSM_FltPI REAL4 3.1415926535
TSM_Flt0000023 REAL4 0.000023
TSM_Fltm2 REAL4 -2.0
TSM_Flt116 REAL4 1.16
TSM_Flt015 REAL4 0.15
TSM_Flt035 REAL4 0.35
TSM_Flt03 REAL4 0.3
TSM_Random_Seed DWORD 012341234h
TSM_Formant_Coefficients REAL8 3.11044e-06
REAL8 8.943665402
REAL8 -36.83889529
REAL8 92.01697887
REAL8 -154.337906
REAL8 181.6233289
REAL8 -151.8651235
REAL8 89.09614114
REAL8 -35.10298511
REAL8 8.388101016
REAL8 -0.923313471
REAL8 4.36215e-06
REAL8 8.90438318
REAL8 -36.55179099
REAL8 91.05750846
REAL8 -152.422234
REAL8 179.1170248
REAL8 -149.6496211
REAL8 87.78352223
REAL8 -34.60687431
REAL8 8.282228154
REAL8 -0.914150747
REAL8 3.33819e-06
REAL8 8.893102966
REAL8 -36.49532826
REAL8 90.96543286
REAL8 -152.4545478
REAL8 179.4835618
REAL8 -150.315433
REAL8 88.43409371
REAL8 -34.98612086
REAL8 8.407803364
REAL8 -0.932568035
REAL8 1.13572e-06
REAL8 8.994734087
REAL8 -37.2084849
REAL8 93.22900521
REAL8 -156.6929844
REAL8 184.596544
REAL8 -154.3755513
REAL8 90.49663749
REAL8 -35.58964535
REAL8 8.478996281
REAL8 -0.929252233
REAL8 4.09431e-07
REAL8 8.997322763
REAL8 -37.20218544
REAL8 93.11385476
REAL8 -156.2530937
REAL8 183.7080141
REAL8 -153.2631681
REAL8 89.59539726
REAL8 -35.12454591
REAL8 8.338655623
REAL8 -0.910251753
TSM_Freqs_Table DWORD 000000417h,00000455h,000000497h,0000004DDh,000000527h,000000575h,0000005C8h,000000620h,00000067Dh,0000006E0h,000000749h,0000007B8h
DWORD 00000082Dh,000008A9h,00000092Dh,0000009B9h,000000A4Dh,000000AEAh,000000B90h,000000C40h,000000CFAh,000000DC0h,000000E91h,000000F6Fh
DWORD 00000105Ah,00001153h,00000125Bh,000001372h,00000149Ah,0000015D4h,000001720h,000001880h,0000019F5h,000001B80h,000001D23h,000001EDEh
DWORD 0000020B4h,000022A6h,0000024B5h,0000026E4h,000002934h,000002BA7h,000002E40h,000003100h,0000033EAh,000003700h,000003A45h,000003DBCh
DWORD 000004168h,0000454Ch,00000496Bh,000004DC8h,000005268h,00000574Fh,000005C80h,000006200h,0000067D3h,000006E00h,00000748Ah,000007B79h
DWORD 0000082D0h,00008A97h,0000092D5h,000009B90h,00000A4D0h,00000AE9Dh,00000B8FFh,00000C3FFh,00000CFA7h,00000DC00h,00000E915h,00000F6F1h
DWORD 0000105A0h,0001152Fh,0000125AAh,000013721h,0000149A1h,000015D3Ah,0000171FFh,0000187FFh,000019F4Eh,00001B800h,00001D22Ah,00001EDE2h
DWORD 000020B40h,00022A5Dh,000024B54h,000026E41h,000029341h,00002BA75h,00002E3FDh,000030FFEh,000033E9Ch,000037000h,00003A454h,00003DBC4h
DWORD 000041681h,000454BBh,0000496A9h,00004DC82h,000052683h,0000574EAh,00005C7FAh,000061FFBh,000067D38h,00006E000h,0000748A8h,00007B789h
DWORD 000082D01h,0008A976h,000092D52h,00009B904h,0000A4D05h,0000AE9D4h,0000B8FF5h,0000C3FF6h,0000CFA70h,0000DC000h,0000E914Fh,0000F6F11h
; --------------- Code section
.code
; ------------------------------------------------------
; Name: TSM_Init()
; Desc: Init the synthetizer
TSM_Init PROC uses ebx esi edi TSM_Module:DWORD,TSM_hWnd:HWND,TSM_CallBack_Routine:DWORD
mov esi,[TSM_Module]
mov ebx,esi
lodsd
cmp eax,0024d5354h
jne TSM_Err_Init
xor eax,eax
lodsw
mov [TSM_Tempo],eax
lodsw
mov [TSM_Fx_Tempo],eax
lodsw
mov [TSM_Song_Restart],eax
lodsd
add eax,ebx
mov [TSM_Module_Sequences],eax
lodsd
add eax,ebx
mov [TSM_Module_Instruments],esi
mov esi,eax
lodsd
mov [TSM_Nbr_Positions],eax
imul ebx,eax,sizeof TSM_SONG_DAT
mov [TSM_Length_Track],ebx
imul eax,sizeof TSM_SONG_DAT
shl eax,3
invoke GlobalAlloc, GMEM_FIXED or GMEM_ZEROINIT, eax
test eax,eax
jz TSM_Err_Init
mov edi,eax
mov [TSM_Module_Positions],edi
mov ebx,8
TSM_Convert_Positions: push edi
push edi
mov ecx,[TSM_Nbr_Positions]
test ecx,ecx
jz TSM_Err_Init
TSM_Copy_Song_Datas_w: movsw
add edi,(sizeof TSM_SONG_DAT) - 2
loop TSM_Copy_Song_Datas_w
pop edi
add edi,2
call TSM_Copy_Module_Datas
inc edi
call TSM_Copy_Module_Datas
pop edi
add edi,[TSM_Length_Track]
dec ebx
jnz TSM_Convert_Positions
; Allocate room for intruments pointers
mov esi,[TSM_Module_Instruments]
lodsd
mov [TSM_Nbr_Instruments],eax
push eax
shl eax,3
invoke GlobalAlloc, GMEM_FIXED or GMEM_ZEROINIT, eax
test eax,eax
jz TSM_Err_Init
mov [TSM_Module_Instruments],eax
mov ebx,eax
pop ecx
TSM_Create_Intruments: push ecx
; Allocate slots
movzx eax,byte ptr [esi]
imul eax,sizeof TSM_INSTRUMENT_DAT
invoke GlobalAlloc, GMEM_FIXED or GMEM_ZEROINIT, eax
mov edi,eax
test eax,eax
jz TSM_Err_Init
movzx ecx,byte ptr [esi]
mov [ebx],eax ; Address
add ebx,4
mov [ebx],ecx ; Number of combinators
add ebx,4
inc esi
TSM_Create_Instruments_Datas: push ecx
push edi
mov ecx,16 ; Copy datas
rep movsb
pop edi
; Calc the deltas
mov al,[edi + TSM_INSTRUMENT_DAT.Attack_Volume]
mov [edi + TSM_INSTRUMENT_DAT.Attack_Volume_Delta],al
mov al,[edi + TSM_INSTRUMENT_DAT.Decay_Volume]
sub al,[edi + TSM_INSTRUMENT_DAT.Attack_Volume]
mov [edi + TSM_INSTRUMENT_DAT.Decay_Volume_Delta],al
mov al,[edi + TSM_INSTRUMENT_DAT.Sustain_Volume]
sub al,[edi + TSM_INSTRUMENT_DAT.Decay_Volume]
mov [edi + TSM_INSTRUMENT_DAT.Sustain_Volume_Delta],al
mov al,[edi + TSM_INSTRUMENT_DAT.Release_Volume]
sub al,[edi + TSM_INSTRUMENT_DAT.Sustain_Volume]
mov [edi + TSM_INSTRUMENT_DAT.Release_Volume_Delta],al
add edi, sizeof TSM_INSTRUMENT_DAT
pop ecx
loop TSM_Create_Instruments_Datas
pop ecx
loop TSM_Create_Intruments
; Set the sequences pointer
mov esi,[TSM_Module_Sequences]
lodsd
mov [TSM_Nbr_Sequences],eax
mov [TSM_Module_Sequences],esi
invoke DirectSoundCreate, NULL, addr TSM_DSound_Context, NULL
test eax,eax
jnz TSM_Err_Init
DSINVOKE SetCooperativeLevel, [TSM_DSound_Context], [TSM_hWnd], DSSCL_EXCLUSIVE
test eax,eax
jnz TSM_Err_Init
mov [TSM_Sound_Buffer_Desc.dwSize], sizeof DSBUFFERDESC
mov [TSM_Sound_Buffer_Desc.dwFlags], DSBCAPS_STICKYFOCUS
; 44100 hz
mov eax,[TSM_Max_Buffer]
mov [TSM_Sound_Buffer_Desc.dwBufferBytes],eax
mov [TSM_Wave_Format.wFormatTag], WAVE_FORMAT_PCM
; Stereo
mov [TSM_Wave_Format.nChannels], 2
mov [TSM_Wave_Format.nSamplesPerSec], 44100
mov [TSM_Wave_Format.nAvgBytesPerSec], (44100 * ((16 * 2) shr 3))
mov [TSM_Wave_Format.nBlockAlign], ((16 * 2) shr 3)
; 16 bits
mov [TSM_Wave_Format.wBitsPerSample], 16
mov [TSM_Sound_Buffer_Desc.lpwfxFormat], offset TSM_Wave_Format
DSINVOKE CreateSoundBuffer, [TSM_DSound_Context], addr TSM_Sound_Buffer_Desc, addr TSM_Sound_Buffer, NULL
test eax,eax
jnz TSM_Err_Init
DSBINVOKE Play, [TSM_Sound_Buffer], 0, 0, DSBPLAY_LOOPING
test eax,eax
jnz TSM_Err_Init
invoke GlobalAlloc, GMEM_FIXED or GMEM_ZEROINIT, ((44100 * 2) + 4) * 4
test eax,eax
jz TSM_Err_Init
mov [TSM_Mixing_Buffer_Stereo],eax
invoke GlobalAlloc, GMEM_FIXED or GMEM_ZEROINIT, (sizeof TSM_SEQUENCE) * 8
test eax,eax
jz TSM_Err_Init
mov [TSM_Sequences_Dats],eax
mov dword ptr [TSM_Global_Volume],03f800000h
mov dword ptr [TSM_Speed_Counter],3
mov dword ptr [TSM_Cur_Play_Pos],15
mov edi,[TSM_Sequences_Dats]
mov ebx,8
TSM_Alloc_Delay_Buffers: invoke GlobalAlloc, GMEM_FIXED or GMEM_ZEROINIT, (44100 * 4)
test eax,eax
jz TSM_Err_Init
mov [edi + TSM_SEQUENCE.Delay_Left_Buffer],eax
invoke GlobalAlloc, GMEM_FIXED or GMEM_ZEROINIT, (44100 * 4)
test eax,eax
jz TSM_Err_Init
mov [edi + TSM_SEQUENCE.Delay_Right_Buffer],eax
; Set default position volume to 1.0
mov [edi + TSM_SEQUENCE.Position_Volume],03f800000h
add edi,sizeof TSM_SEQUENCE
dec ebx
jnz TSM_Alloc_Delay_Buffers
push dword ptr [TSM_Tempo]
call TSM_Get_Mix_Buffer_Len
mov [TSM_Tempo_Ticks],eax
push dword ptr [TSM_Fx_Tempo]
call TSM_Get_Mix_Buffer_Len
mov [TSM_Fx_Tempo_Ticks],eax
inc dword ptr [TSM_Can_Play]
mov eax,[TSM_CallBack_Routine]
mov [TSM_Synth_CallBack],eax
TSM_Err_Init: mov eax,[TSM_Can_Play]
ret
TSM_Init ENDP
TSM_Copy_Module_Datas: push edi
mov ecx,[TSM_Nbr_Positions]
TSM_Copy_Module_Datas_b: movsb
add edi,(sizeof TSM_SONG_DAT) - 1
loop TSM_Copy_Module_Datas_b
pop edi
ret
; ------------------------------------------------------
; Name: TSM_Stop()
; Desc: Stop the synthetizer
TSM_Stop PROC uses edi
dec dword ptr [TSM_Can_Play]
mov eax,[TSM_Sound_Buffer]
test eax,eax
jz TSM_Release_SoundBuffer
DSBINVOKE Stop,[TSM_Sound_Buffer]
DSBINVOKE Release,[TSM_Sound_Buffer]
TSM_Release_SoundBuffer: mov eax,[TSM_DSound_Context]
test eax,eax
jz TSM_Release_DSContext
DSINVOKE Release, [TSM_DSound_Context]
TSM_Release_DSContext: mov eax,[TSM_Mixing_Buffer_Stereo]
test eax,eax
jz TSM_Free_Mixing_Buffer_Stereo
invoke GlobalFree,eax
TSM_Free_Mixing_Buffer_Stereo: mov edi,[TSM_Sequences_Dats]
test edi,edi
jz TSM_No_Sequences_Dats
mov ebx,8
TSM_Free_Delay_Buffers: mov eax,[edi + TSM_SEQUENCE.Delay_Left_Buffer]
test eax,eax
jz TSM_Free_Delay_Left_Buffer
invoke GlobalFree,eax
TSM_Free_Delay_Left_Buffer: mov eax,[edi + TSM_SEQUENCE.Delay_Right_Buffer]
test eax,eax
jz TSM_Free_Delay_Right_Buffer
invoke GlobalFree,eax
TSM_Free_Delay_Right_Buffer: add edi,sizeof TSM_SEQUENCE
dec ebx
jnz TSM_Free_Delay_Buffers
TSM_No_Sequences_Dats: mov eax,[TSM_Sequences_Dats]
test eax,eax
jz TSM_Free_Sequences_Dats
invoke GlobalFree,eax
TSM_Free_Sequences_Dats: mov eax,[TSM_Module_Positions]
test eax,eax
jz TSM_Free_Module_Positions
invoke GlobalFree,eax
TSM_Free_Module_Positions: ret
TSM_Stop ENDP
; ------------------------------------------------------
; Name: TSM_Play()
; Desc: Replay routine
TSM_Play PROC uses ebx esi edi
local TSM_Bytes_To_Lock:dword
cmp dword ptr [TSM_Can_Play],0
jne TSM_Proceed_Play
ret
TSM_Proceed_Play: DSBINVOKE GetCurrentPosition, [TSM_Sound_Buffer], addr TSM_Buffer_Pos, NULL
mov eax,[TSM_Buffer_Pos]
sub eax,[TSM_Old_Buffer_Pos]
jns TSM_Reset_Buffer_Pos
add eax,[TSM_Max_Buffer]
TSM_Reset_Buffer_Pos: mov [TSM_Bytes_To_Lock],eax
DSBINVOKE mLock, [TSM_Sound_Buffer], [TSM_Old_Buffer_Pos], [TSM_Bytes_To_Lock], addr TSM_Audio_Ptr1, addr TSM_Audio_Bytes1, addr TSM_Audio_Ptr2, addr TSM_Audio_Bytes2, 0
mov eax,[TSM_Buffer_Pos]
mov [TSM_Old_Buffer_Pos],eax
mov edx,[TSM_Audio_Bytes1]
mov eax,[TSM_Audio_Ptr1]
call TSM_Process_Sound_Dat
mov edx,[TSM_Audio_Bytes2]
mov eax,[TSM_Audio_Ptr2]
call TSM_Process_Sound_Dat
DSBINVOKE Unlock, [TSM_Sound_Buffer], [TSM_Audio_Ptr1], [TSM_Audio_Bytes1], [TSM_Audio_Ptr2], [TSM_Audio_Bytes2]
ret
TSM_Play ENDP
; ------------------------------------------------------
; Name: TSM_Process_Sound_Dat()
; Desc: Inner part of the replay
TSM_Process_Sound_Dat: push ebp
push eax
mov [TSM_BufferSize],edx
shr edx,2
mov edi,[TSM_Mixing_Buffer_Stereo]
TSM_Mix_Loop: test edx,edx
jz TSM_End_Mix_Loop
push edx
mov ebp,[TSM_Sequences_Dats]
mov dword ptr [TSM_Speed_Tick],0
dec dword ptr [TSM_Fx_Ticks]
jns TSM_Speed_Limit
push dword ptr [TSM_Fx_Tempo_Ticks]
pop dword ptr [TSM_Fx_Ticks]
inc dword ptr [TSM_Speed_Tick]
inc dword ptr [TSM_Speed_Counter]
cmp dword ptr [TSM_Speed_Counter],3
jl TSM_Speed_Limit
mov dword ptr [TSM_Speed_Counter],0
TSM_Speed_Limit: dec dword ptr [TSM_Cur_Ticks]
jns TSM_Update_Channels
push dword ptr [TSM_Tempo_Ticks]
pop dword ptr [TSM_Cur_Ticks]
; Goto next position
inc dword ptr [TSM_Cur_Play_Pos]
cmp dword ptr [TSM_Cur_Play_Pos],16
jne TSM_Reset_Sequence_Pos
mov dword ptr [TSM_Cur_Play_Pos],0
; Fill the sequences datas
lea ebx,[ebp]
xor esi,esi
mov ecx,8
TSM_Set_Sequences: push ecx
mov eax,[TSM_Module_Positions]
mov edx,[TSM_Length_Track]
imul edx,esi
add eax,edx ; Start address of the track
imul edx,[TSM_Song_Position],sizeof TSM_SONG_DAT
add eax,edx
movzx edx,byte ptr [eax + TSM_SONG_DAT.Volume]
push edx ; Push volume
movzx edx,byte ptr [eax + TSM_SONG_DAT.Transpose]
mov cl,dl
and dl,07fh
and cl,080h
jz TSM_Negative_Transpose
neg edx
TSM_Negative_Transpose: push edx ; Push transpose
movzx eax,word ptr [eax + TSM_SONG_DAT.Sequence]
test eax,eax
jz TSM_No_Sequence
dec eax
cmp [TSM_Nbr_Sequences],eax
ja TSM_Wrong_Sequence
xor eax,eax
jmp TSM_No_Sequence
TSM_Wrong_Sequence: imul eax,sizeof TSM_SEQUENCE_DAT
add eax,[TSM_Module_Sequences]
TSM_No_Sequence: mov [ebx + TSM_SEQUENCE.Current_Sequence],eax
; Set transpose for this sequence
pop dword ptr [ebx + TSM_SEQUENCE.Position_Transpose]
; Set global volume for this sequence
pop eax
test eax,eax
jz TSM_No_New_Global_Volume
dec eax
push eax
fild dword ptr [esp]
fmul dword ptr [TSM_Flt001]
pop eax
fstp dword ptr [ebx + TSM_SEQUENCE.Position_Volume]
TSM_No_New_Global_Volume: add ebx,sizeof TSM_SEQUENCE
inc esi
pop ecx
dec ecx
jnz TSM_Set_Sequences
mov eax,[TSM_Nbr_Positions]
inc dword ptr [TSM_Song_Position]
cmp [TSM_Song_Position],eax
jl TSM_Reset_Song_Position
xor ebx,ebx
test eax,eax
jz TSM_Max_Restart
mov ebx,[TSM_Song_Restart]
dec ebx
dec eax
cmp ebx,eax
jb TSM_Max_Restart
mov ebx,eax
TSM_Max_Restart: mov [TSM_Song_Position],ebx
TSM_Reset_Song_Position: ; Set the default pans of the sequences
lea eax,[ebp]
mov ecx,8
TSM_Reset_Pan: ; (Default pan)
fld dword ptr [TSM_Flt05]
fstp dword ptr [eax + TSM_SEQUENCE.Pan]
add eax,sizeof TSM_SEQUENCE
loop TSM_Reset_Pan
TSM_Reset_Sequence_Pos: mov ecx,8
TSM_Set_Song_Datas: push ecx
push edi
mov dword ptr [ebp + TSM_SEQUENCE.Vol_Side],0
mov dword ptr [ebp + TSM_SEQUENCE.Arpeggio],0
mov dword ptr [ebp + TSM_SEQUENCE.Pitch_Bend],0
mov dword ptr [ebp + TSM_SEQUENCE.Vibrato],0
mov dword ptr [ebp + TSM_SEQUENCE.Vibrato_Freq],0
mov dword ptr [ebp + TSM_SEQUENCE.Tone_Portamento_Speed],0
mov dword ptr [ebp + TSM_SEQUENCE.Tone_Portamento_Note],0
; Set the effects
mov edi,[ebp + TSM_SEQUENCE.Current_Sequence]
test edi,edi
jz TSM_No_New_Panning
mov esi,[TSM_Cur_Play_Pos]
movzx ebx,byte ptr [edi + esi + TSM_SEQUENCE_DAT.Fx]
movzx eax,byte ptr [edi + esi + TSM_SEQUENCE_DAT.FxDatas]
; Arpeggio
dec ebx
js TSM_Fx_NoFx
jnz TSM_Fx_Arpeggio
test eax,eax
jnz TSM_Fx_Old_Arpeggio
mov eax,[ebp + TSM_SEQUENCE.Old_Arpeggio]
TSM_Fx_Old_Arpeggio: mov [ebp + TSM_SEQUENCE.Arpeggio],eax
mov [ebp + TSM_SEQUENCE.Old_Arpeggio],eax
TSM_Fx_Arpeggio: ; Pitch bend up
dec ebx
jnz TSM_Fx_Pitch_Bend_Up
test eax,eax
jnz TSM_Fx_Old_Pitch_Bend_Up
mov eax,[ebp + TSM_SEQUENCE.Old_Pitch_Bend_Up]
TSM_Fx_Old_Pitch_Bend_Up: mov [ebp + TSM_SEQUENCE.Pitch_Bend],eax
mov [ebp + TSM_SEQUENCE.Old_Pitch_Bend_Up],eax
TSM_Fx_Pitch_Bend_Up: ; Pitch bend down
dec ebx
jnz TSM_Fx_Pitch_Bend_Down
neg eax
test eax,eax
jnz TSM_Fx_Old_Pitch_Bend_Down
mov eax,[ebp + TSM_SEQUENCE.Old_Pitch_Bend_Down]
TSM_Fx_Old_Pitch_Bend_Down: mov [ebp + TSM_SEQUENCE.Pitch_Bend],eax
mov [ebp + TSM_SEQUENCE.Old_Pitch_Bend_Down],eax
TSM_Fx_Pitch_Bend_Down: ; Vibrato
dec ebx
jnz TSM_Fx_Vibrato
test eax,eax
jnz TSM_Fx_Old_Vibrato
mov eax,[ebp + TSM_SEQUENCE.Old_Vibrato]
TSM_Fx_Old_Vibrato: mov [ebp + TSM_SEQUENCE.Vibrato],eax
mov [ebp + TSM_SEQUENCE.Old_Vibrato],eax
TSM_Fx_Vibrato: ; Volume slide up
dec ebx
jnz TSM_Fx_Vol_Slide_Up
test eax,eax
jnz TSM_Fx_Old_Vol_Slide_Up
mov eax,[ebp + TSM_SEQUENCE.Old_Vol_Side_Up]
TSM_Fx_Old_Vol_Slide_Up: push eax
fild dword ptr [esp]
pop eax
fmul dword ptr [TSM_Flt001]
fstp dword ptr [ebp + TSM_SEQUENCE.Vol_Side]
mov [ebp + TSM_SEQUENCE.Old_Vol_Side_Up],eax
TSM_Fx_Vol_Slide_Up: ; Volume slide down
dec ebx
jnz TSM_Fx_Vol_Slide_Down
test eax,eax
jnz TSM_Fx_Old_Vol_Slide_Down
mov eax,[ebp + TSM_SEQUENCE.Old_Vol_Side_Down]
TSM_Fx_Old_Vol_Slide_Down: push eax
fild dword ptr [esp]
pop eax
fmul dword ptr [TSM_Flt001]
fchs
fstp dword ptr [ebp + TSM_SEQUENCE.Vol_Side]
mov [ebp + TSM_SEQUENCE.Old_Vol_Side_Down],eax
TSM_Fx_Vol_Slide_Down: ; Modify tempo
dec ebx
jnz TSM_Fx_Set_Tempo
mov [TSM_Tempo],eax
push eax
call TSM_Get_Mix_Buffer_Len
mov [TSM_Tempo_Ticks],eax
TSM_Fx_Set_Tempo: ; Modify misc. FX tempo
dec ebx
jnz TSM_Fx_Set_Misc_Tempo
mov [TSM_Fx_Tempo],eax
push eax
call TSM_Get_Mix_Buffer_Len
mov [TSM_Fx_Tempo_Ticks],eax
TSM_Fx_Set_Misc_Tempo: ; Modify global volume
dec ebx
jnz TSM_Fx_Set_Global_Volume
push eax
fild dword ptr [esp]
pop eax
fmul dword ptr [TSM_Flt001]
call TSM_Clamp_Value
fstp dword ptr [TSM_Global_Volume]
TSM_Fx_Set_Global_Volume: ; Tone portamento
dec ebx
jnz Fx_Tone_Portamento
movzx edx,byte ptr [edi + esi + TSM_SEQUENCE_DAT.Note]
test eax,eax
jnz TSM_Fx_Old_Tone_Portamento_Spd
mov eax,[ebp + TSM_SEQUENCE.Old_Tone_Portamento_Speed]
TSM_Fx_Old_Tone_Portamento_Spd: dec edx
jns TSM_Fx_Old_Tone_Portamento_Nt
mov edx,[ebp + TSM_SEQUENCE.Old_Tone_Portamento_Note]
TSM_Fx_Old_Tone_Portamento_Nt: mov [ebp + TSM_SEQUENCE.Tone_Portamento_Speed],eax
mov [ebp + TSM_SEQUENCE.Old_Tone_Portamento_Speed],eax
mov [ebp + TSM_SEQUENCE.Tone_Portamento_Note],edx
mov [ebp + TSM_SEQUENCE.Old_Tone_Portamento_Note],edx
Fx_Tone_Portamento: ; External program control
dec ebx
jnz TSM_Fx_NoFx
push esi
push edi
mov ebx,[TSM_Synth_CallBack]
test ebx,ebx
jz No_Synchro
push eax
call ebx
No_Synchro: pop edi
pop esi
TSM_Fx_NoFx: ; Set the instrument
movzx eax,word ptr [edi + TSM_SEQUENCE_DAT.Instrument + esi * 2]
dec eax
js TSM_No_New_Instrument
cmp [TSM_Nbr_Instruments],eax
jg TSM_Return_Instrument
xor eax,eax
jmp TSM_Wrong_Instrument
TSM_Return_Instrument: shl eax,3
add eax,[TSM_Module_Instruments]
TSM_Wrong_Instrument: mov [ebp + TSM_SEQUENCE.Current_Instrument],eax
push 0
push dword ptr [ebp + TSM_SEQUENCE.Current_Instrument]
call TSM_Get_Instrument_Dat
mov [ebp + TSM_SEQUENCE.Current_Instrument_Dat],eax
test eax,eax
jz TSM_No_New_Instrument
mov eax,[ebp + TSM_SEQUENCE.Current_Instrument]
test eax,eax
jz TSM_Return_Comb
mov eax,[eax + 4]
TSM_Return_Comb: mov [ebp + TSM_SEQUENCE.Instrument_NbrComb],eax
fld1
fstp dword ptr [ebp + TSM_SEQUENCE.Volume]
TSM_No_New_Instrument: ; Set the note
mov esi,[TSM_Cur_Play_Pos]
cmp dword ptr [ebp + TSM_SEQUENCE.Tone_Portamento_Speed],0
jne TSM_No_New_Note
movzx ebx,byte ptr [edi + esi + TSM_SEQUENCE_DAT.Note]
dec ebx
js TSM_No_New_Note
add ebx,[ebp + TSM_SEQUENCE.Position_Transpose]
mov [ebp + TSM_SEQUENCE.Cur_Note],ebx
mov [ebp + TSM_SEQUENCE.Cur_Freq],ebx
mov dword ptr [ebp + TSM_SEQUENCE.Pitch_Bend_Freq],0
mov eax,[ebp + TSM_SEQUENCE.Current_Instrument]
test eax,eax
jz TSM_No_New_Note
mov ecx,[ebp + TSM_SEQUENCE.Instrument_NbrComb]
lea eax,[ebp + TSM_SEQUENCE.Cur_Instrument_Vars]
TSM_Clear_Instrument_Dats: xor edx,edx
mov [eax + TSM_INSTRUMENT_VARS.Volume],edx
mov [eax + TSM_INSTRUMENT_VARS.Ticks],edx
mov [eax + TSM_INSTRUMENT_VARS.RndVal1],edx
mov [eax + TSM_INSTRUMENT_VARS.RndVal2],edx
mov [eax + TSM_INSTRUMENT_VARS.wrpos],edx
mov [eax + TSM_INSTRUMENT_VARS.FPos],edx
mov [eax + TSM_INSTRUMENT_VARS.Oscillator],edx
mov [eax + TSM_INSTRUMENT_VARS.Frac_Lo_Pos],edx
add eax,sizeof TSM_INSTRUMENT_VARS
loop TSM_Clear_Instrument_Dats
TSM_No_New_Note: ; Set the volume
movzx ebx,byte ptr [edi + esi + TSM_SEQUENCE_DAT.Volume]
dec ebx
js TSM_No_New_Volume
push ebx
fild dword ptr [esp]
pop ebx
fmul dword ptr [TSM_Flt001]
fstp dword ptr [ebp + TSM_SEQUENCE.Volume]
TSM_No_New_Volume: ; Set the panning
movzx ebx,byte ptr [edi + esi + TSM_SEQUENCE_DAT.Panning]
dec ebx
js TSM_No_New_Panning
push ebx
fild dword ptr [esp]
pop ebx
fmul dword ptr [TSM_Flt001]
fstp dword ptr [ebp + TSM_SEQUENCE.Pan]
TSM_No_New_Panning: pop edi
pop ecx
add ebp,sizeof TSM_SEQUENCE
dec ecx
jnz TSM_Set_Song_Datas
TSM_Update_Channels: ; -------------------------------------------------
; Process in-between effects
mov ebp,[TSM_Sequences_Dats]
mov ecx,8
TSM_Set_Song_Fx: push ecx
cmp dword ptr [ebp + TSM_SEQUENCE.Pitch_Bend],0
je TSM_No_PitchBend
cmp dword ptr [TSM_Speed_Tick],0
je TSM_No_PitchBend
mov eax,[ebp + TSM_SEQUENCE.Pitch_Bend_Freq]
add eax,[ebp + TSM_SEQUENCE.Pitch_Bend]
mov [ebp + TSM_SEQUENCE.Pitch_Bend_Freq],eax
TSM_No_PitchBend: cmp dword ptr [ebp + TSM_SEQUENCE.Vibrato],0
je TSM_No_Vibrato
cmp dword ptr [TSM_Speed_Tick],0
je TSM_No_Vibrato
mov eax,[ebp + TSM_SEQUENCE.Vibrato]
mov ebx,eax
shr ebx,4
and eax,0fh
push eax
fild dword ptr [esp]
fadd st(0),st(0)
fadd st(0),st(0)
fadd st(0),st(0)
fadd st(0),st(0)
pop eax
push dword ptr [ebp + TSM_SEQUENCE.Vibrato_Tick]
fild dword ptr [esp]
fmul dword ptr [TSM_Flt005]
fsin
fmulp st(1),st(0)
fistp dword ptr [esp]
pop eax
mov [ebp + TSM_SEQUENCE.Vibrato_Freq],eax
add [ebp + TSM_SEQUENCE.Vibrato_Tick],ebx
TSM_No_Vibrato: cmp dword ptr [ebp + TSM_SEQUENCE.Arpeggio],0
je TSM_No_Arpeggio
mov eax,[TSM_Speed_Counter]
xor edx,edx
mov ebx,3
div ebx
dec edx
jz TSM_Do_Arpeggio1
dec edx
jz TSM_Do_Arpeggio2
xor edx,edx
jmp TSM_Do_Arpeggio
TSM_Do_Arpeggio1: mov edx,[ebp + TSM_SEQUENCE.Arpeggio]
shr edx,4
jmp TSM_Do_Arpeggio
TSM_Do_Arpeggio2: mov edx,[ebp + TSM_SEQUENCE.Arpeggio]
and edx,0fh
TSM_Do_Arpeggio: add edx,[ebp + TSM_SEQUENCE.Cur_Note]
mov [ebp + TSM_SEQUENCE.Cur_Freq],edx
TSM_No_Arpeggio: cmp dword ptr [ebp + TSM_SEQUENCE.Tone_Portamento_Speed],0
je TSM_No_TonePortamento
cmp dword ptr [TSM_Speed_Tick],0
je TSM_No_TonePortamento
mov ebx,[ebp + TSM_SEQUENCE.Pitch_Bend_Freq]
mov ecx,[ebp + TSM_SEQUENCE.Tone_Portamento_Speed]
mov edx,[ebp + TSM_SEQUENCE.Tone_Portamento_Note]
mov eax,[TSM_Freqs_Table + edx * 4]
cmp eax,[ebp + TSM_SEQUENCE.Current_Freq]
je TSM_Portamento_Stop
ja TSM_Portamento_Up
sub ebx,ecx
cmp eax,ebx
ja TSM_Portamento_Stop
jmp TSM_Set_Portamento_Freq
TSM_Portamento_Up: add ebx,ecx
cmp eax,ebx
jb TSM_Portamento_Stop
jmp TSM_Set_Portamento_Freq
TSM_Portamento_Stop: mov [ebp + TSM_SEQUENCE.Cur_Freq],edx
xor ebx,ebx
TSM_Set_Portamento_Freq: mov [ebp + TSM_SEQUENCE.Pitch_Bend_Freq],ebx
TSM_No_TonePortamento: pop ecx
add ebp,sizeof TSM_SEQUENCE
dec ecx
jnz TSM_Set_Song_Fx
; -------------------------
; Handle waves combinations
mov ebp,[TSM_Sequences_Dats]
mov ecx,8
TSM_Set_Song_Instruments: push ecx
push edi
lea eax,[ebp + TSM_SEQUENCE.Cur_Instrument_Vars]
mov [TSM_Instr_Dat_Vars],eax
mov dword ptr [ebp + TSM_SEQUENCE.Sound_Datas],0
mov dword ptr [TSM_Instr_Dat_Number], 0
mov ebx,[ebp + TSM_SEQUENCE.Current_Instrument_Dat]
; Load number of combinators
mov ecx,[ebp + TSM_SEQUENCE.Instrument_NbrComb]
TSM_Load_Instrument: test ebx,ebx
jz TSM_No_Instrument
push ecx
mov edi,[TSM_Instr_Dat_Vars]
mov ecx,[ebp + TSM_SEQUENCE.Cur_Freq]
mov dword ptr [ebp + TSM_SEQUENCE.Freq_Hi_Speed],0
mov dword ptr [ebp + TSM_SEQUENCE.Freq_Lo_Speed],0
test ecx,ecx
js TSM_No_Freq
cmp ecx,TSM_MAX_NOTES
jge TSM_No_Freq
mov eax,[TSM_Freqs_Table + ecx * 4]
add eax,[ebp + TSM_SEQUENCE.Vibrato_Freq]
add eax,[ebp + TSM_SEQUENCE.Pitch_Bend_Freq]
movzx edx,byte ptr [ebx + TSM_INSTRUMENT_DAT.Waveform]
cmp dl,TSM_INS_WF_CUST
je TSM_Custom_Value
movsx edx,word ptr [ebx + TSM_INSTRUMENT_DAT.PhaseShift]
add eax,edx
TSM_Custom_Value: cmp eax,0417h
jg TSM_Min_Frequency
mov eax,0417h
TSM_Min_Frequency: cmp eax,0F6F11h
jl TSM_Max_Frequency
mov eax,0F6F11h
TSM_Max_Frequency: mov [ebp + TSM_SEQUENCE.Current_Freq],eax
xor edx,edx
div dword ptr [TSM_Max_Buffer]
mov [ebp + TSM_SEQUENCE.Freq_Hi_Speed],eax
xor eax,eax
div dword ptr [TSM_Max_Buffer]
mov [ebp + TSM_SEQUENCE.Freq_Lo_Speed],eax
TSM_No_Freq: mov edx,[edi + TSM_INSTRUMENT_VARS.Frac_Lo_Pos]
mov esi,[edi + TSM_INSTRUMENT_VARS.Oscillator]
add edx,[ebp + TSM_SEQUENCE.Freq_Lo_Speed]
adc esi,[ebp + TSM_SEQUENCE.Freq_Hi_Speed]
mov [edi + TSM_INSTRUMENT_VARS.Frac_Lo_Pos],edx
fld dword ptr [ebp + TSM_SEQUENCE.Sound_Datas]
mov [edi + TSM_INSTRUMENT_VARS.Oscillator],esi
fild dword ptr [edi + TSM_INSTRUMENT_VARS.Oscillator]
fmul dword ptr [TSM_Flt01]
movzx edx,byte ptr [ebx + TSM_INSTRUMENT_DAT.Waveform]
dec dl
jnz TSM_Set_Ins_Sin
fsin
TSM_Set_Ins_Sin: dec dl
jnz TSM_Set_Ins_Sqr
fsin
fld st(0)
push eax
fistp dword ptr [esp]
fild dword ptr [esp]
fxch st(1)
cmp dword ptr [esp],0
jne TSM_Sqr_Zero
ftst
fstsw ax
sahf
fstp st(0)
fstp st(0)
fld1
ja TSM_Sqr_Neg
fchs
TSM_Sqr_Neg: fld st(0)
TSM_Sqr_Zero: fstp st(0)
pop eax
TSM_Set_Ins_Sqr: dec dl
jnz TSM_Set_Ins_Saw
fld dword ptr [TSM_FltPI2]
fxch st(1)
TSM_FModf_Saw: fprem
fstsw ax
sahf
jp TSM_FModf_Saw
fstp st(1)
fdiv dword ptr [TSM_FltPI]
fsub dword ptr [TSM_Flt1]
TSM_Set_Ins_Saw: dec dl
jnz TSM_Set_Ins_Rnd
fstp dword ptr [edi + TSM_INSTRUMENT_VARS.FPos]
cmp dword ptr [edi + TSM_INSTRUMENT_VARS.wrpos],0
jne TSM_Reset_Noise
call TSM_Wave_WhiteNoise
fstp dword ptr [edi + TSM_INSTRUMENT_VARS.RndVal1]
call TSM_Wave_WhiteNoise
fstp dword ptr [edi + TSM_INSTRUMENT_VARS.RndVal2]
mov eax,[edi + TSM_INSTRUMENT_VARS.FPos]
mov [edi + TSM_INSTRUMENT_VARS.wrpos],eax
TSM_Reset_Noise: fld dword ptr [edi + TSM_INSTRUMENT_VARS.wrpos]
fadd dword ptr [TSM_FltPI2]
fcom dword ptr [edi + TSM_INSTRUMENT_VARS.FPos]
fnstsw ax
sahf
jae TSM_Done_Rnd
fstp dword ptr [edi + TSM_INSTRUMENT_VARS.wrpos]
mov eax,[edi + TSM_INSTRUMENT_VARS.RndVal2]
mov [edi + TSM_INSTRUMENT_VARS.RndVal1],eax
call TSM_Wave_WhiteNoise
fstp dword ptr [edi + TSM_INSTRUMENT_VARS.RndVal2]
jmp TSM_Reset_Noise
TSM_Done_Rnd: fstp st(0)
fld dword ptr [edi + TSM_INSTRUMENT_VARS.FPos]
fsub dword ptr [edi + TSM_INSTRUMENT_VARS.wrpos]
fmul dword ptr [edi + TSM_INSTRUMENT_VARS.RndVal2]
fld dword ptr [TSM_FltPI2]
fadd dword ptr [edi + TSM_INSTRUMENT_VARS.wrpos]
fsub dword ptr [edi + TSM_INSTRUMENT_VARS.FPos]
fmul dword ptr [edi + TSM_INSTRUMENT_VARS.RndVal1]
faddp st(1),st(0)
fmul dword ptr [TSM_Flt05]
TSM_Set_Ins_Rnd: dec dl
jnz TSM_Set_Ins_Tri
fld dword ptr [TSM_FltPI2]
fxch st(1)
TSM_FModf_Tri: fprem
fstsw ax
sahf
jp TSM_FModf_Tri
fstp st(1)
fcom dword ptr [TSM_FltPI]
fnstsw ax
sahf
fld1
ja TSM_Tri_Desc
fchs
TSM_Tri_Desc: fxch st(1)
fcom dword ptr [TSM_FltPI2]
fnstsw ax
sahf
jb TSM_Tri_Ramp
fsub dword ptr [TSM_FltPI2]
fld dword ptr [TSM_FltPI2]
fsubrp st(1),st(0)
TSM_Tri_Ramp: fdiv dword ptr [TSM_FltPI2]
fmulp st(1),st(0)
fadd dword ptr [TSM_Flt025]
fcom dword ptr [TSM_Flt05]
fnstsw ax
sahf
jb TSM_Tri_Invert
fsub dword ptr [TSM_Flt1]
TSM_Tri_Invert: fadd st(0),st(0)
fadd st(0),st(0)
TSM_Set_Ins_Tri: dec dl
jnz TSM_Set_Ins_Cust
fstp st(0)
movzx eax,byte ptr [ebx + TSM_INSTRUMENT_DAT.PhaseShift]
push eax
fild dword ptr [esp]
pop eax
cmp word ptr [ebx + TSM_INSTRUMENT_DAT.PhaseShift],0
jg TSM_Negative_Shift
fchs
TSM_Negative_Shift: fmul dword ptr [TSM_Flt001]
TSM_Set_Ins_Cust: push ebp
mov ebp,[TSM_Instr_Dat_Vars]
; Handle ADSR
push edi
movzx edi,byte ptr [ebx + TSM_INSTRUMENT_DAT.Attack_Volume]
movzx ecx,word ptr [ebx + TSM_INSTRUMENT_DAT.Attack]
xor edx,edx
movsx eax,byte ptr [ebx + TSM_INSTRUMENT_DAT.Attack_Volume_Delta]
mov esi,ecx
test ecx,ecx
jz TSM_Load_Decay
add edx,ecx
cmp [ebp + TSM_INSTRUMENT_VARS.Ticks],edx
jb TSM_Load_Decay
movzx edi,byte ptr [ebx + TSM_INSTRUMENT_DAT.Decay_Volume]
movzx esi,word ptr [ebx + TSM_INSTRUMENT_DAT.Decay]
movsx eax,byte ptr [ebx + TSM_INSTRUMENT_DAT.Decay_Volume_Delta]
TSM_Load_Decay: movzx ecx,word ptr [ebx + TSM_INSTRUMENT_DAT.Decay]
test ecx,ecx
jz TSM_Load_Sustain
add edx,ecx
cmp [ebp + TSM_INSTRUMENT_VARS.Ticks],edx
jb TSM_Load_Sustain
movzx edi,byte ptr [ebx + TSM_INSTRUMENT_DAT.Sustain_Volume]
movzx esi,word ptr [ebx + TSM_INSTRUMENT_DAT.Sustain]
movsx eax,byte ptr [ebx + TSM_INSTRUMENT_DAT.Sustain_Volume_Delta]
TSM_Load_Sustain: movzx ecx,word ptr [ebx + TSM_INSTRUMENT_DAT.Sustain]
test ecx,ecx
jz TSM_Load_Release
add edx,ecx
cmp dword ptr [ebp + TSM_INSTRUMENT_VARS.Ticks],edx
jb TSM_Load_Release
movzx edi,byte ptr [ebx + TSM_INSTRUMENT_DAT.Release_Volume]
movzx esi,word ptr [ebx + TSM_INSTRUMENT_DAT.Release]
movsx eax,byte ptr [ebx + TSM_INSTRUMENT_DAT.Release_Volume_Delta]
TSM_Load_Release: test esi,esi
jz TSM_Done_Ramping
test eax,eax
jz TSM_Done_Ramping
push eax
jg TSM_Vol_Ramp_Up
; Ramping down
push edi ; Dest volume
fild dword ptr [esp]
pop edi
fmul dword ptr [TSM_Flt001]
fcomp dword ptr [ebp + TSM_INSTRUMENT_VARS.Volume]
fnstsw ax
sahf
jb TSM_Volume_Max
jmp TSM_Volume_Equal
; Ramping up
TSM_Vol_Ramp_Up: push edi
fild dword ptr [esp]
pop edi
fmul dword ptr [TSM_Flt001]
fcomp dword ptr [ebp + TSM_INSTRUMENT_VARS.Volume]
fnstsw ax
sahf
jz TSM_Volume_Equal
ja TSM_Volume_Max
TSM_Volume_Equal: ; Set the Dest volume
mov [esp],edi
fild dword ptr [esp]
pop edi
fmul dword ptr [TSM_Flt001]
fstp dword ptr [ebp + TSM_INSTRUMENT_VARS.Volume]
jmp TSM_Done_Ramping
TSM_Volume_Max: fild dword ptr [esp] ; Delta volume
pop eax
push esi
fild dword ptr [esp] ; Ramping time
pop esi
fdivp st(1),st(0)
fmul dword ptr [TSM_Flt001]
fadd dword ptr [ebp + TSM_INSTRUMENT_VARS.Volume]
call TSM_Clamp_Value
fstp dword ptr [ebp + TSM_INSTRUMENT_VARS.Volume]
TSM_Done_Ramping: ; Set the volume of the sample according to the ADSR
fmul dword ptr [ebp + TSM_INSTRUMENT_VARS.Volume]
pop edi
; Handle operators
mov dl,[ebx + TSM_INSTRUMENT_DAT.Operator]
dec dl
jnz TSM_Set_Ins_Op_Add
faddp st(1),st(0)
TSM_Set_Ins_Op_Add: dec dl
jnz TSM_Set_Ins_Op_Sub
fsubp st(1),st(0)
TSM_Set_Ins_Op_Sub: dec dl
jnz TSM_Set_Ins_Op_Mul
fmulp st(1),st(0)
TSM_Set_Ins_Op_Mul: dec dl
jnz TSM_Set_Ins_Op_Div
fdivp st(1),st(0)
TSM_Set_Ins_Op_Div: inc dword ptr [ebp + TSM_INSTRUMENT_VARS.Ticks]
pop ebp
; Store oscillator value now
fstp dword ptr [ebp + TSM_SEQUENCE.Sound_Datas]
; Next instrument's datas
inc dword ptr [TSM_Instr_Dat_Number]
push dword ptr [TSM_Instr_Dat_Number]
; Next datas of the instrument of the sequence
push dword ptr [ebp + TSM_SEQUENCE.Current_Instrument]
call TSM_Get_Instrument_Dat
mov ebx,eax
add [TSM_Instr_Dat_Vars],sizeof TSM_INSTRUMENT_VARS
pop ecx
dec ecx
jnz TSM_Load_Instrument
TSM_No_Instrument: pop edi
; Set channel volume
fld dword ptr [ebp + TSM_SEQUENCE.Sound_Datas]
fld dword ptr [ebp + TSM_SEQUENCE.Volume]
cmp dword ptr [TSM_Speed_Tick],0
je TSM_No_Vol_Slide
fadd dword ptr [ebp + TSM_SEQUENCE.Vol_Side]
call TSM_Clamp_Value
fst dword ptr [ebp + TSM_SEQUENCE.Volume]
TSM_No_Vol_Slide: fmulp st(1),st(0)
; Set song position volume
fmul dword ptr [ebp + TSM_SEQUENCE.Position_Volume]
fmul dword ptr [TSM_Global_Volume]
fstp dword ptr [ebp + TSM_SEQUENCE.Sound_Datas]
; Reset DSP effects parameters
mov edx,[ebp + TSM_SEQUENCE.Current_Sequence]
test edx,edx
jz TSM_No_DSP_Params
mov esi,[TSM_Cur_Play_Pos]
mov bl,[edx + esi + TSM_SEQUENCE_DAT.DspMask]
test bl,1
jz TSM_Switch_Lo_Pass_Off
mov dword ptr [ebp + TSM_SEQUENCE.Lo_Pass_Param1],0
mov dword ptr [ebp + TSM_SEQUENCE.Lo_Pass_Param2],0
TSM_Switch_Lo_Pass_Off: test bl,2
jz TSM_Switch_Hi_Pass_Off
mov dword ptr [ebp + TSM_SEQUENCE.Hi_Pass_Param1],0
mov dword ptr [ebp + TSM_SEQUENCE.Hi_Pass_Param2],0
TSM_Switch_Hi_Pass_Off: test bl,4
jz TSM_Switch_VCF_Pass_Off
mov dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_Param1],0
mov dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_Param2],0
TSM_Switch_VCF_Pass_Off: test bl,8
jz TSM_Switch_Delay_Off
push 0
push 0
push 0
push ebp
call TSM_Set_Delay
mov dword ptr [ebp + TSM_SEQUENCE.Delay_Cursor],0
TSM_Switch_Delay_Off: test bl,16
jz TSM_Switch_Disto_Off
mov dword ptr [ebp + TSM_SEQUENCE.Disto_Param],0
TSM_Switch_Disto_Off: test bl,32
jz TSM_Switch_Formant_Off
mov dword ptr [ebp + TSM_SEQUENCE.Formant_Param1],0
TSM_Switch_Formant_Off: ; Process DSP effects
mov bl,byte ptr [edx + esi + TSM_SEQUENCE_DAT.Dsp]
dec bl
js TSM_No_DSP_Params
jnz TSM_No_Lo_Pass_Filter
movzx eax,byte ptr [edx + esi + TSM_SEQUENCE_DAT.DspDatas3]
mov ah,[edx + esi + TSM_SEQUENCE_DAT.DspDatas2]
push eax
fild dword ptr [esp]
pop eax
fstp dword ptr [ebp + TSM_SEQUENCE.Lo_Pass_Param2]
movzx eax,byte ptr [edx + esi + TSM_SEQUENCE_DAT.DspDatas1]
push eax
fild dword ptr [esp]
pop eax
fmul dword ptr [TSM_Flt01]
fstp dword ptr [ebp + TSM_SEQUENCE.Lo_Pass_Param1]
TSM_No_Lo_Pass_Filter: dec bl
jnz TSM_No_Hi_Pass_Filter
movzx eax,byte ptr [edx + esi + TSM_SEQUENCE_DAT.DspDatas3]
mov ah,[edx + esi + TSM_SEQUENCE_DAT.DspDatas2]
push eax
fild dword ptr [esp]
pop eax
fstp dword ptr [ebp + TSM_SEQUENCE.Hi_Pass_Param2]
movzx eax,byte ptr [edx + esi + TSM_SEQUENCE_DAT.DspDatas1]
push eax
fild dword ptr [esp]
pop eax
fmul dword ptr [TSM_Flt01]
fstp dword ptr [ebp + TSM_SEQUENCE.Hi_Pass_Param1]
TSM_No_Hi_Pass_Filter: dec bl
jnz TSM_No_VCF_Pass_Filter
movzx eax,byte ptr [edx + esi + TSM_SEQUENCE_DAT.DspDatas3]
mov ah,[edx + esi + TSM_SEQUENCE_DAT.DspDatas2]
push eax
fild dword ptr [esp]
pop eax
fmul dword ptr [TSM_Flt00001]
fstp dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_Param2]
movzx eax,byte ptr [edx + esi + TSM_SEQUENCE_DAT.DspDatas1]
push eax
fild dword ptr [esp]
pop eax
fmul dword ptr [TSM_Flt001]
fstp dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_Param1]
TSM_No_VCF_Pass_Filter: dec bl
dec bl
jnz TSM_No_Disto_Filter
movzx eax,byte ptr [edx + esi + TSM_SEQUENCE_DAT.DspDatas3]
mov ah,[edx + esi + TSM_SEQUENCE_DAT.DspDatas2]
push eax
fild dword ptr [esp]
pop eax
fmul dword ptr [TSM_Flt01]
fstp dword ptr [ebp + TSM_SEQUENCE.Disto_Param]
TSM_No_Disto_Filter: dec bl
jnz TSM_No_DSP_Params
movzx eax,byte ptr [edx + esi + TSM_SEQUENCE_DAT.DspDatas1]
cmp eax,5
jb TSM_Max_Formant_Filter
mov eax,5
TSM_Max_Formant_Filter: mov [ebp + TSM_SEQUENCE.Formant_Param1],eax
TSM_No_DSP_Params: cmp dword ptr [ebp + TSM_SEQUENCE.Lo_Pass_Param1],0
je TSM_No_Process_Lo_Pass
cmp dword ptr [ebp + TSM_SEQUENCE.Lo_Pass_Param2],0
je TSM_No_Process_Lo_Pass
fldpi
fmul dword ptr [ebp + TSM_SEQUENCE.Lo_Pass_Param2]
fmul dword ptr [TSM_Flt0000023]
fptan
fstp st(0)
mov edx,[ebp + TSM_SEQUENCE.Lo_Pass_In1]
mov ecx,[ebp + TSM_SEQUENCE.Lo_Pass_Out1]
fld1
fld st(0)
fdivrp st(2),st(0)
fld dword ptr [ebp + TSM_SEQUENCE.Lo_Pass_Param1]
fmul st(0),st(2)
fxch st(2)
fmul st(0),st(0)
fld st(1)
fadd st(0),st(3)
fadd st(0),st(1)
fdivr st(0),st(2)
fld st(0)
fadd st(0),st(0)
fld st(3)
fsub st(0),st(3)
fadd st(0),st(0)
fmul st(0),st(2)
fxch st(4)
fsubrp st(5),st(0)
fxch st(2)
faddp st(4),st(0)
fmul st(3),st(0)
fld st(0)
fmul dword ptr [ebp + TSM_SEQUENCE.Sound_Datas]
fxch st(2)
fmul dword ptr [ebp + TSM_SEQUENCE.Lo_Pass_In1]
faddp st(2),st(0)
fmul dword ptr [ebp + TSM_SEQUENCE.Lo_Pass_In2]
faddp st(1),st(0)
fld dword ptr [ebp + TSM_SEQUENCE.Lo_Pass_Out1]
fchs
fmulp st(2),st(0)
faddp st(1),st(0)
fld dword ptr [ebp + TSM_SEQUENCE.Lo_Pass_Out2]
fchs
fmulp st(2),st(0)
faddp st(1),st(0)
mov [ebp + TSM_SEQUENCE.Lo_Pass_In2],edx
fld st(0)
mov [ebp + TSM_SEQUENCE.Lo_Pass_Out2],ecx
push dword ptr [ebp + TSM_SEQUENCE.Sound_Datas]
pop dword ptr [ebp + TSM_SEQUENCE.Lo_Pass_In1]
fxch st(1)
fstp dword ptr [ebp + TSM_SEQUENCE.Lo_Pass_Out1]
fstp dword ptr [ebp + TSM_SEQUENCE.Sound_Datas]
TSM_No_Process_Lo_Pass: cmp dword ptr [ebp + TSM_SEQUENCE.Hi_Pass_Param1],0
je TSM_No_Process_Hi_Pass
cmp dword ptr [ebp + TSM_SEQUENCE.Hi_Pass_Param2],0
je TSM_No_Process_Hi_Pass
fldpi
fmul dword ptr [ebp + TSM_SEQUENCE.Hi_Pass_Param2]
fmul dword ptr [TSM_Flt0000023]
fptan
fstp st(0)
fld st(0)
fmul st(0),st(0)
fld1
fld st(0)
fadd st(0),st(2)
fld dword ptr [ebp + TSM_SEQUENCE.Hi_Pass_Param1]
fmulp st(4),st(0)
fld st(0)
fadd st(0),st(4)
fdivp st(2),st(0)
fxch st(2)
fadd dword ptr [TSM_Fltm1]
fld dword ptr [TSM_Fltm2]
fmul st(0),st(2)
fxch st(1)
fadd st(0),st(0)
fmul st(0),st(2)
fxch st(4)
fsubp st(3),st(0)
fxch st(1)
fmul st(2),st(0)
mov edx,[ebp + TSM_SEQUENCE.Hi_Pass_In1]
mov ecx,[ebp + TSM_SEQUENCE.Hi_Pass_Out1]
fld st(0)
fmul dword ptr [ebp + TSM_SEQUENCE.Sound_Datas]
fxch st(2)
fmul dword ptr [ebp + TSM_SEQUENCE.Hi_Pass_In1]
faddp st(2),st(0)
fmul dword ptr [ebp + TSM_SEQUENCE.Hi_Pass_In2]
faddp st(1),st(0)
fld dword ptr [ebp + TSM_SEQUENCE.Hi_Pass_Out1]
fchs
fmulp st(3),st(0)
faddp st(2),st(0)
fld dword ptr [ebp + TSM_SEQUENCE.Hi_Pass_Out2]
fchs
fmulp st(1),st(0)
faddp st(1),st(0)
mov [ebp + TSM_SEQUENCE.Hi_Pass_In2],edx
fld st(0)
mov [ebp + TSM_SEQUENCE.Hi_Pass_Out2],ecx
push dword ptr [ebp + TSM_SEQUENCE.Sound_Datas]
pop dword ptr [ebp + TSM_SEQUENCE.Hi_Pass_In1]
fxch st(1)
fstp dword ptr [ebp + TSM_SEQUENCE.Hi_Pass_Out1]
fstp dword ptr [ebp + TSM_SEQUENCE.Sound_Datas]
TSM_No_Process_Hi_Pass: cmp dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_Param1],0
je TSM_No_Process_VCF_Pass
cmp dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_Param2],0
je TSM_No_Process_VCF_Pass
fld dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_Param2]
fmul dword ptr [TSM_Flt116]
fld1
fld st(1)
fmul st(0),st(0)
fld dword ptr [TSM_Flt015]
fmul st(0),st(3)
fmul st(0),st(3)
fsubr st(0),st(2)
fmul dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_Param1]
fld dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_Out4]
fld st(0)
fchs
fmulp st(2),st(0)
fxch st(1)
fadd dword ptr [ebp + TSM_SEQUENCE.Sound_Datas]
fxch st(3)
fsubrp st(4),st(0)
fld dword ptr [TSM_Flt035]
fmul st(0),st(2)
fmulp st(2),st(0)
fxch st(1)
fmulp st(2),st(0)
fld st(2)
fld dword ptr [TSM_Flt03]
fld st(0)
fld st(5)
fld dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_In1]
fmulp st(2),st(0)
fxch st(1)
fadd st(0),st(5)
fld dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_Out1]
fmulp st(4),st(0)
faddp st(3),st(0)
fxch st(2)
fst dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_Out1]
fld st(1)
fxch st(5)
fstp dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_In1]
fld st(5)
fxch st(4)
fmulp st(6),st(0)
fld dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_In2]
fmulp st(5),st(0)
fadd st(4),st(0)
fld dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_Out2]
fmulp st(3),st(0)
fxch st(2)
faddp st(4),st(0)
fxch st(3)
fst dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_Out2]
fld st(3)
fxch st(2)
fstp dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_In2]
fld dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_In3]
fmulp st(2),st(0)
fadd st(1),st(0)
fld dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_Out3]
fmulp st(3),st(0)
fxch st(2)
faddp st(1),st(0)
fst dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_Out3]
fxch st(1)
fstp dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_In3]
fld dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_In4]
fmulp st(2),st(0)
fadd st(1),st(0)
fxch st(2)
faddp st(1),st(0)
fst dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_Out4]
fxch st(1)
fstp dword ptr [ebp + TSM_SEQUENCE.VCF_Pass_In4]
fstp dword ptr [ebp + TSM_SEQUENCE.Sound_Datas]
TSM_No_Process_VCF_Pass: cmp dword ptr [ebp + TSM_SEQUENCE.Disto_Param],0
je TSM_No_Process_Disto
fld dword ptr [ebp + TSM_SEQUENCE.Sound_Datas]
fabs
fst qword ptr [ebp + TSM_SEQUENCE.Disto_Abs_Input]
fld1
fld dword ptr [ebp + TSM_SEQUENCE.Disto_Param]
fld st(0)
fadd qword ptr [ebp + TSM_SEQUENCE.Disto_Abs_Input]
fld dword ptr [ebp + TSM_SEQUENCE.Sound_Datas]
fmul st(1),st(0)
fmul st(0),st(0)
fadd st(0),st(3)
fld dword ptr [TSM_Fltm1]
faddp st(3),st(0)
fxch st(4)
fmulp st(2),st(0)
fxch st(1)
faddp st(3),st(0)
fxch st(1)
fdivrp st(2),st(0)
fmulp st(1),st(0)
fstp dword ptr [ebp + TSM_SEQUENCE.Sound_Datas]
TSM_No_Process_Disto: mov eax,[ebp + TSM_SEQUENCE.Formant_Param1]
test eax,eax
jz TSM_No_Process_Filters
dec eax
imul eax,eax,(11 * 8)
fld qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem + (8 * 5)]
fld qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem + (8 * 6)]
fld qword ptr [eax + TSM_Formant_Coefficients]
fmul dword ptr [ebp + TSM_SEQUENCE.Sound_Datas]
fld qword ptr [eax + TSM_Formant_Coefficients + (8 * 1)]
fmul qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem]
fld qword ptr [eax + TSM_Formant_Coefficients + (8 * 2)]
fmul qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem + (8 * 1)]
fld qword ptr [eax + TSM_Formant_Coefficients + (8 * 3)]
fmul qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem + (8 * 2)]
fld qword ptr [eax + TSM_Formant_Coefficients + (8 * 4)]
fmul qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem + (8 * 3)]
fld qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem + (8 * 7)]
fxch st(6)
fst qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem + (8 * 7)]
fxch st(7)
fst qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem + (8 * 6)]
fxch st(4)
faddp st(5),st(0)
fxch st(2)
faddp st(4),st(0)
faddp st(3),st(0)
faddp st(2),st(0)
fld qword ptr [eax + TSM_Formant_Coefficients + (8 * 5)]
fmul qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem + (8 * 4)]
fld qword ptr [eax + TSM_Formant_Coefficients + (8 * 6)]
fmulp st(2),st(0)
faddp st(1),st(0)
faddp st(1),st(0)
fld qword ptr [eax + TSM_Formant_Coefficients + (8 * 7)]
fmulp st(3),st(0)
fld qword ptr [eax + TSM_Formant_Coefficients + (8 * 8)]
fmul st(0),st(2)
faddp st(3),st(0)
fld qword ptr [eax + TSM_Formant_Coefficients + (8 * 9)]
fld qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem + (8 * 8)]
fld qword ptr [eax + TSM_Formant_Coefficients + (8 * 10)]
fmul qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem + (8 * 9)]
fxch st(1)
fmul st(2),st(0)
fstp qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem + (8 * 9)]
fxch st(3)
fstp qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem + (8 * 8)]
faddp st(2),st(0)
fxch st(1)
faddp st(2),st(0)
faddp st(1),st(0)
fld qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem + (8 * 4)]
fstp qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem + (8 * 5)]
fld qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem + (8 * 3)]
fstp qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem + (8 * 4)]
fld qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem + (8 * 2)]
fstp qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem + (8 * 3)]
fld qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem + (8 * 1)]
fstp qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem + (8 * 2)]
fld qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem]
fstp qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem + (8 * 1)]
fst qword ptr [ebp + TSM_SEQUENCE.Formant_Tmp_Mem]
fstp dword ptr [ebp + TSM_SEQUENCE.Sound_Datas]
TSM_No_Process_Filters: pop ecx
add ebp,sizeof TSM_SEQUENCE
dec ecx
jnz TSM_Set_Song_Instruments
; ----------------------------------
; Split stereo signal now
xor edx,edx
mov ebp,[TSM_Sequences_Dats]
mov ecx,8
TSM_Process_Effects: push edx
push ecx
fld1
fsub dword ptr [ebp + TSM_SEQUENCE.Pan]
fsqrt
fmul dword ptr [ebp+TSM_SEQUENCE.Sound_Datas]
; Store left signal
test edx,edx
jz TSM_Set_Left_Channel
fadd dword ptr [edi]
TSM_Set_Left_Channel: fstp dword ptr [edi]
fld dword ptr [ebp + TSM_SEQUENCE.Pan]
fsqrt
fmul dword ptr [ebp + TSM_SEQUENCE.Sound_Datas]
; Store right signal
test edx,edx
jz TSM_Set_Right_Channel
fadd dword ptr [edi + 4]
TSM_Set_Right_Channel: fstp dword ptr [edi + 4]
; ----------------------------------
; Process delay if necessary
mov edx,[ebp + TSM_SEQUENCE.Current_Sequence]
test edx,edx
jz TSM_No_Delay_Dsp
mov esi,[TSM_Cur_Play_Pos]
mov bl,byte ptr [edx + esi + TSM_SEQUENCE_DAT.Dsp]
cmp bl,TSM_DSP_DELAY
jne TSM_No_Delay_Dsp
movzx eax,byte ptr [edx + esi + TSM_SEQUENCE_DAT.DspDatas3]
push eax
fild dword ptr [esp]
fmul dword ptr [TSM_Flt001]
fstp dword ptr [esp]
movzx eax,byte ptr [edx + esi + TSM_SEQUENCE_DAT.DspDatas2]
push eax
fild dword ptr [esp]
fmul dword ptr [TSM_Flt001]
fstp dword ptr [esp]
movzx eax,byte ptr [edx + esi + TSM_SEQUENCE_DAT.DspDatas1]
push eax
fild dword ptr [esp]
fmul dword ptr [TSM_Flt001]
fstp dword ptr [esp]
push ebp
call TSM_Set_Delay
TSM_No_Delay_Dsp: mov eax,[ebp + TSM_SEQUENCE.Delay_Value]
test eax,eax
jz TSM_No_Delay
mov eax,[ebp + TSM_SEQUENCE.Delay_Cursor]
mov ebx,[ebp + TSM_SEQUENCE.Delay_Left_Buffer]
mov ecx,edi
fld dword ptr [ebx + eax * 4]
fadd dword ptr [ecx]
fstp dword ptr [ecx]
add ecx,4
fld dword ptr [ebp + TSM_SEQUENCE.Sound_Datas]
fadd dword ptr [ebx + eax * 4]
fmul dword ptr [ebp + TSM_SEQUENCE.Delay_Left_FeedBack_Value]
fstp dword ptr [ebx + eax * 4]
mov eax,[ebp + TSM_SEQUENCE.Delay_Cursor]
mov ebx,[ebp + TSM_SEQUENCE.Delay_Right_Buffer]
fld dword ptr [ebx + eax * 4]
fadd dword ptr [ecx]
fstp dword ptr [ecx]
fld dword ptr [ebp + TSM_SEQUENCE.Sound_Datas]
fadd dword ptr [ebx + eax * 4]
fmul dword ptr [ebp + TSM_SEQUENCE.Delay_Right_FeedBack_Value]
fstp dword ptr [ebx + eax * 4]
inc dword ptr [ebp + TSM_SEQUENCE.Delay_Cursor]
mov eax,[ebp + TSM_SEQUENCE.Delay_Value]
cmp [ebp + TSM_SEQUENCE.Delay_Cursor],eax
jl TSM_No_Delay
mov dword ptr [ebp + TSM_SEQUENCE.Delay_Cursor],0
TSM_No_Delay: pop ecx
pop edx
mov edx,1
add ebp,sizeof TSM_SEQUENCE
dec ecx
jnz TSM_Process_Effects
add edi,8
pop edx
dec edx
jmp TSM_Mix_Loop
TSM_End_Mix_Loop: pop edi
; ----------------------------------
; Final mixing and conversion into 16 bits output
mov edx,[TSM_BufferSize]
shr edx,1
mov esi,[TSM_Mixing_Buffer_Stereo]
TSM_Final_Mix_Loop: test edx,edx
jz TSM_End_Final_Mix_Loop
lodsd
mov [TSM_Final_Signal],eax
; Clip sample
fld dword ptr [TSM_Final_Signal]
fld1
fcom st(1)
fnstsw ax
sahf
jae TSM_Min_Value
fst dword ptr [TSM_Final_Signal]
TSM_Min_Value: fstp st(0)
fstp st(0)
fld dword ptr [TSM_Final_Signal]
fld dword ptr [TSM_Fltm1]
fcom st(1)
fnstsw ax
sahf
jbe TSM_Max_Value
fst dword ptr [TSM_Final_Signal]
TSM_Max_Value: fstp st(0)
fstp st(0)
fld dword ptr [TSM_Final_Signal]
fmul dword ptr [TSM_Flt32767] ; Sign the sample
fistp dword ptr [TSM_Final_Signal]
fstp st(0)
mov eax,[TSM_Final_Signal]
stosw
dec edx
jmp TSM_Final_Mix_Loop
TSM_End_Final_Mix_Loop: pop ebp
ret
; ------------------------------------------------------
; Name: TSM_Get_Instrument_Dat()
; Desc: Retrieve the address of an instrument
TSM_Get_Instrument_Dat PROC TSM_Cur_Instrument:DWORD,TSM_Instr_Number:DWORD
mov eax,[TSM_Cur_Instrument]
test eax,eax
jz TSM_Return_Dat
push ebx
mov ebx,[eax + 4]
cmp [TSM_Instr_Number],ebx
jl TSM_Max_Comb
pop ebx
xor eax,eax
ret
TSM_Max_Comb: imul ebx,[TSM_Instr_Number],sizeof TSM_INSTRUMENT_DAT
mov eax,[eax]
add eax,ebx ; Offset to instrument's datas
pop ebx
TSM_Return_Dat: ret
TSM_Get_Instrument_Dat ENDP
; ------------------------------------------------------
; Name: TSM_Wave_WhiteNoise()
; Desc: Produce a whitenoise
TSM_Wave_WhiteNoise: mov eax,[TSM_Random_Seed]
inc eax
imul eax,01df5d45h
mov [TSM_Random_Seed],eax
and eax,0ffffh
sub eax,08000h
push eax
fild dword ptr [esp]
pop eax
fdiv dword ptr [TSM_Flt32768]
ret
; ------------------------------------------------------
; Name: TSM_Get_Mix_Buffer_Len()
; Desc: Convert a given BPM into ticks
TSM_Get_Mix_Buffer_Len PROC TSM_BPM:DWORD
push ebx
push edx
mov eax,44100
mov ebx,10
imul eax,ebx
xor edx,edx
mov ebx,[TSM_BPM]
test ebx,ebx
jz TSM_ZeroBPM
idiv ebx
TSM_ZeroBPM: shr eax,2
pop edx
pop ebx
ret
TSM_Get_Mix_Buffer_Len ENDP
; ------------------------------------------------------
; Name: TSM_Set_Delay()
; Desc: Set the delay effect values
TSM_Set_Delay PROC TSM_Sequence:DWORD,TSM_Delay_Distance:REAL4,TSM_Delay_Feedback:REAL4,TSM_Delay_Pan:REAL4
mov eax,[TSM_Sequence]
fld dword ptr [TSM_Delay_Distance]
fimul dword ptr [TSM_Max_Buffer]
fistp dword ptr [eax + TSM_SEQUENCE.Delay_Value]
fld1
fsub dword ptr [TSM_Delay_Pan]
fsqrt
fmul dword ptr [TSM_Delay_Feedback]
fstp dword ptr [eax + TSM_SEQUENCE.Delay_Left_FeedBack_Value]
fld dword ptr [TSM_Delay_Pan]
fsqrt
fmul dword ptr [TSM_Delay_Feedback]
fstp dword ptr [eax + TSM_SEQUENCE.Delay_Right_FeedBack_Value]
ret
TSM_Set_Delay ENDP
; ------------------------------------------------------
; Name: TSM_Clamp_Value()
; Desc: Clamp the a value between [0..1]
TSM_Clamp_Value: fcom dword ptr [TSM_Flt1]
fnstsw ax
sahf
jb TSM_Clamp_Volume_Max
fstp st(0)
fld1
TSM_Clamp_Volume_Max: ftst
fnstsw ax
sahf
ja TSM_Clamp_Volume_Min
fsub st(0),st(0)
TSM_Clamp_Volume_Min: ret
end