Commit e841ea96 authored by PoroCYon's avatar PoroCYon
Browse files

[clinkster] get rid of easy_exe (won't really need it anyway)

parent f9d8bc24
del /q temp\*
del music.exe
tools\RenoiseConvert.exe music.xrns temp\music.asm
tools\nasmw -f win32 src\clinkster_multithreaded.asm -o temp\clinkster_multithreaded.obj
tools\nasmw -f win32 src\play.asm -o temp\play.obj
tools\crinkler20\crinkler temp\clinkster_multithreaded.obj temp\play.obj /OUT:music.exe /ENTRY:main tools\kernel32.lib tools\user32.lib tools\winmm.lib tools\msvcrt_old.lib @crinkler_options.txt
pause
del /q temp\*
del music_wav.exe
tools\RenoiseConvert.exe music.xrns temp\music.asm
tools\nasmw -f win32 src\clinkster_multithreaded.asm -o temp\clinkster_multithreaded.obj
tools\nasmw -f win32 -dWRITE_WAV src\play.asm -o temp\play.obj
tools\crinkler20\crinkler temp\clinkster_multithreaded.obj temp\play.obj /OUT:music_wav.exe /ENTRY:main tools\kernel32.lib tools\user32.lib tools\winmm.lib tools\msvcrt_old.lib @crinkler_options.txt
pause
/UNSAFEIMPORT /COMPMODE:INSTANT /HASHSIZE:100
Music composed using 4k synth "Clinkster" by Blueberry / Loonies
Generating music...
This setup is for easily building an executable version of a piece of music
created using Clinkster.
Proceed as follows:
1. Place your music here, named music.xrns.
2. Place a text file containing the text you would like the executable to
print at startup, named music.txt.
3. Optionally modify the Crinkler options in crinkler_options.txt
(read the Crinkler manual for details).
4. Run build.bat to get an executable that plays the music, or
build_wav.bat to get one that writes the music in WAV format to
music.wav and then plays it.
Enjoy!
extern Clinkster_GenerateMusic
extern Clinkster_StartMusic
extern Clinkster_GetPosition
extern Clinkster_GetInstrumentTrigger
extern Clinkster_MusicBuffer
extern Clinkster_NoteTiming
extern Clinkster_TicksPerSecond
extern Clinkster_MusicLength
extern Clinkster_NumTracks
extern Clinkster_WavFileHeader
; If set to 1, timing information is generated during music generation
; which is needed for Clinkster_GetInstrumentTrigger.
; Set it to 0 if you don't need this functionality.
%define CLINKSTER_GENERATE_TIMING_DATA 0
; Offset applied by Clinkster_GetPosition to compensate for graphics latency.
; Measured in samples (44100ths of a second).
; The default value of 2048 (corresponding to about 46 milliseconds) is
; appropriate for typical display latencies for high-framerate effects.
%define CLINKSTER_TIMER_OFFSET 0
%include "temp/music.asm"
;; ********** Definitions **********
global Clinkster_GenerateMusic
global _Clinkster_GenerateMusic@0
global Clinkster_StartMusic
global _Clinkster_StartMusic@0
global Clinkster_GetPosition
global _Clinkster_GetPosition@0
global Clinkster_GetInstrumentTrigger
global _Clinkster_GetInstrumentTrigger@8
global Clinkster_MusicBuffer
global _Clinkster_MusicBuffer
global Clinkster_TicksPerSecond
global _Clinkster_TicksPerSecond
global Clinkster_MusicLength
global _Clinkster_MusicLength
global Clinkster_NumTracks
global _Clinkster_NumTracks
%if CLINKSTER_GENERATE_TIMING_DATA
global Clinkster_NoteTiming
global _Clinkster_NoteTiming
%endif
global Clinkster_WavFileHeader
global _Clinkster_WavFileHeader
extern __imp__waveOutOpen@24
extern __imp__waveOutPrepareHeader@12
extern __imp__waveOutWrite@12
extern __imp__waveOutGetPosition@12
extern __imp__CreateThread@24
extern __imp__WaitForSingleObject@8
%define SAMPLE_RATE 44100
%define WAVE_SIZE 65536
;; ********** Public variables **********
section MusBuf bss align=4
Clinkster_MusicBuffer:
_Clinkster_MusicBuffer:
.align24
resw (TOTAL_SAMPLES*2)
resw 2 ; padding to catch extra write in conversion
section tps rdata align=4
Clinkster_TicksPerSecond:
_Clinkster_TicksPerSecond:
dd TICKS_PER_SECOND
section muslen rdata align=4
Clinkster_MusicLength:
_Clinkster_MusicLength:
dd MUSIC_LENGTH
section numtr rdata align=4
Clinkster_NumTracks:
_Clinkster_NumTracks:
dd NUMTRACKS
%if CLINKSTER_GENERATE_TIMING_DATA
section musdat bss align=4
Clinkster_NoteTiming:
_Clinkster_NoteTiming:
.align16
resd 2*(NUMTRACKS<<LOGNUMTICKS)
section timing data align=4
timing_ptr: dd Clinkster_NoteTiming
%endif
section WavFile rdata align=4
Clinkster_WavFileHeader:
_Clinkster_WavFileHeader:
db "RIFF"
dd 36+TOTAL_SAMPLES*4
db "WAVE"
db "fmt "
dd 16
dw 1,2
dd SAMPLE_RATE
dd SAMPLE_RATE*4
dw 4,16
db "data"
dd TOTAL_SAMPLES*4
;; ********** System structures **********
section WaveForm rdata align=1
_WaveFormat:
dw 1,2
dd SAMPLE_RATE
dd SAMPLE_RATE*4
dw 4,16,0
section WaveHdr data align=4
_WaveHdr:
dd Clinkster_MusicBuffer
dd (TOTAL_SAMPLES*4)
dd 0,0,0,0,0,0
section wavehand bss align=4
_WaveOutHandle:
.align16
resd 1
section WaveTime data align=4
_WaveTime:
dd 4,0,0,0,0,0,0,0
;; ********** Internal buffers **********
section wforms bss align=4
waveforms:
.align16
resd 6*WAVE_SIZE
;; ********** Instrument parameter access **********
section paramw rdata align=4
param_weights:
dd 0.125 ; Release
dd 0.125 ; Decay
dd 0.125 ; Attack
%if USES_GAIN
dd 0.125 ; Gain
%endif
%if USES_INDEXDECAY
dd 0.0009765625 ; IndexDecay
%endif
dd 0.0009765625 ; M PitchDecay
dd 0.0009765625 ; B PitchDecay
dd 0.083333333333 ; M Pitch
dd 0.083333333333 ; B Pitch
dd 0.0000152587890625 ; Volume
%if USES_PANNING
dd 0.0000152587890625 ; Volume
%endif
dd 0.03125 ; Sustain
dd 16307 ; RandomSeed
dd 1 ; Layers
dd 4096.0 ; Index
dd 0.125 ; Index Spread
dd 0.0009765625 ; M Detune
dd 0.0009765625 ; B Detune
dd 65536 ; ModWave
dd 65536 ; BaseWave
struc instr_params
ip_basewave: resd 1
ip_modwave: resd 1
ip_bdetune: resd 1
ip_mdetune: resd 1
ip_indexspr: resd 1
ip_index: resd 1
ip_layers: resd 1
ip_randomseed: resd 1
ip_sustain: resd 1
ip_volume: resd 1+USES_PANNING
ip_bpitch: resd 1
ip_mpitch: resd 1
ip_bpitchd: resd 1
ip_mpitchd: resd 1
%if USES_INDEXDECAY
ip_indexd: resd 1
%endif
%if USES_GAIN
ip_gain: resd 1
%endif
ip_attack: resd 1
ip_decay: resd 1
ip_release: resd 1
endstruc
%define ip_INT 0
%define ip_FLOAT 0
%define IP(f,t) dword [dword ebx + g_instrparams + ip_ %+ f + ip_ %+ t]
%define IPI(f,i,t) dword [dword ebx + g_instrparams + ip_ %+ f + ip_ %+ t + i]
;; ********** Internal constants and tables **********
section resamp rdata align=4
resamplefilter:
db -1,-2,-4,-4,-2,3,14,30,51,98,116,126
db 126,116,98,51,30,14,3,-2,-4,-4,-2,-1
resamplefilter_end:
FILTER_SIZE equ (resamplefilter_end-resamplefilter)
section wavestep rdata align=4
c_wavestep: dd 0.000030517578125
section basefreq rdata align=4
c_basefreq: dd 2.86698696365342
section halfnote rdata align=4
c_halfnote: dd 1.05946309435929
section finalamp rdata align=4
c_finalamp: dd 32767
section velfac rdata align=4
c_velocityfac: dd 0.007874015748031496
section delaystr rdata align=4
c_delaystr: dd DELAY_STRENGTH
section offset rdata align=4
c_timeoffset: dd CLINKSTER_TIMER_OFFSET*4
section tempo rdata align=4
c_ticklength: dd SUBSAMPLES_PER_TICK/4*4
section half rdata align=4
c_onehalf: dd 0.5
;; ********** Internal global variables **********
struc globalvars
g_phasetemp: resd 1
g_layer_random: resd 1
g_stereo: resd 1 ; 0 for left channel, 2 for right channel
g_noteposptr: resd 1
g_notesamptr: resd 1
g_instrparams: resb instr_params_size
g_layerparams: resq 0
g_layer_bfreq: resq 1
g_layer_mfreq: resq 1
g_layer_index: resq 1
g_layer_bpitch: resq 1
g_layer_mpitch: resq 1
g_layer_bpitchd: resq 1
g_layer_mpitchd: resq 1
%if USES_INDEXDECAY
g_layer_indexd: resq 1
%endif
%if USES_GAIN
g_layer_gain: resq 1
%endif
g_layer_attack: resq 1
g_layer_decay: resq 1
g_layer_release: resq 1
alignb 256
g_InstrumentPointers:
resd MAX_TRACK_INSTRUMENT_RENDERS+1
resd MAX_DELAY_LENGTH
alignb 16777216
g_MixingBuffer:
resd TOTAL_SAMPLES
alignb 16777216
g_InstrumentBuffer:
resd MAX_INSTRUMENT_SUBSAMPLES
resd 256
alignb 16777216
g_InstrumentRender:
resd MAX_INSTRUMENT_SUBSAMPLES
alignb 16777216
g_InstrumentStore:
resd MAX_TOTAL_INSTRUMENT_SAMPLES
endstruc
section vars bss align=8
vars_align16
globals:
resb globalvars_size
resb globalvars_size
;; ********** Generate the sound for one layer **********
section mklayer text align=1
makelayer:
lea edx, [dword ebx + g_layerparams]
; Init random variables for layer
fild word [dword ebx + g_layer_random]
mov ecx, dword [dword ebx + g_layer_random]
ror ecx, cl
dec ecx
mov dword [dword ebx + g_layer_random], ecx
fld IP(bdetune, FLOAT)
fmul st0, st0
fmulp st1, st0
fadd st0, st1
fstp qword [edx]
add edx, byte 8
fild word [dword ebx + g_layer_random]
mov ecx, dword [dword ebx + g_layer_random]
ror ecx, cl
dec ecx
mov dword [dword ebx + g_layer_random], ecx
fld IP(mdetune, FLOAT)
fmul st0, st0
fmulp st1, st0
fadd st0, st1
fstp qword [edx]
add edx, byte 8
fild word [dword ebx + g_layer_random]
mov ecx, dword [dword ebx + g_layer_random]
ror ecx, cl
dec ecx
mov dword [dword ebx + g_layer_random], ecx
fmul IP(indexspr, FLOAT)
fadd IP(index, FLOAT)
fstp qword [edx]
add edx, byte 8
; Init exponentiated variables for layer
lea edi, [dword ebx + g_instrparams+ip_bpitch]
mov ecx, 7+USES_INDEXDECAY+USES_GAIN
.powloop:
fld dword [edi]
fld1
fld st1
fprem
fstp st1
f2xm1
fld1
faddp st1, st0
fscale
fstp qword [edx]
add edx, byte 8
fstp st0
scasd
loop .powloop
; Loop over samples
fldz ; b phase
fldz ; m phase
lea edi, [dword ebx + g_InstrumentBuffer]
; Calculate max note size
xor eax, eax
%if USES_VELOCITY
lodsb ; Skip velocity
%endif
%if USES_LONG_NOTES
cmp [esi], byte 0
jge near .short_notelen
lodsb
not al
shl eax, 8
.short_notelen:
%endif
lodsb ; Length of longest note with this tone
mov edx, SUBSAMPLES_PER_TICK
mul edx
add eax, MAX_RELEASE_SUBSAMPLES
xchg ecx, eax
.sampleloop:
lea edx, [dword ebx + g_layerparams]
; Look up and normalize mod wave
fist dword [ebx]
mov eax, IP(modwave,INT)
mov ax, [ebx]
fld dword [waveforms + eax*4]
; Adjust by index
fmul qword [edx + 2*8] ; layer_index
fadd st0, st2
; Look up base wave
fistp dword [ebx]
mov eax, IP(basewave,INT)
mov ax, [ebx]
fld dword [waveforms + eax*4]
; Update phases
fld qword [edx] ; layer_bfreq
add edx, byte 8
fmul qword [edx + 2*8] ; layer_bpitch
faddp st3, st0
fld qword [edx] ; layer_mfreq
add edx, byte 8
fmul qword [edx + 2*8] ; layer_mpitch
faddp st2, st0
%if USES_INDEXDECAY
fld qword [edx] ; layer_index
fld1
fadd st1, st0
fsubp st1, st0
%endif
add edx, byte 8
; Update pitches: p := (p-1)*d+1
.update:
fld1
fld qword [edx] ; layer_(b/m)pitch
fsub st0, st1
fmul qword [edx + 2*8] ; layer_(b/m)pitchd
faddp st1, st0
fstp qword [edx] ; layer_(b/m)pitch
add edx, byte 8
neg ecx
js .update
%if USES_INDEXDECAY
fmul qword [edx + 2*8] ; layer_indexd
fstp qword [edx - 3*8] ; layer_index
%endif
; Add to existing layers
fadd dword [edi]
fstp dword [edi]
scasd
loop .sampleloop
fstp st0
fstp st0
ret
;; ********** Interpolate one section of amplitude envelope **********
section adsr text align=1
apply_adsr:
; On condition g:
; st0 = amplitude target
; st1 = amplitude
; st2 = velocity / nlayers
; eax = number of samples
; ecx = sample index
; On condition le:
; st0 = number of samples
; st1 = amplitude target
; st2 = amplitude
; st3 = velocity / nlayers
; ecx = sample index
push eax
jg .integer_length
fimul dword [c_finalamp]
fistp dword [esp]
.integer_length:
fsub st0, st1
fild dword [esp]
pop eax
add eax, ecx
fdivp st1, st0
.adsrloop:
fld dword [dword ebx + g_InstrumentBuffer + ecx*4]
fmul st0, st3 ; velocity / nlayers
fmul st0, st2 ; envelope value
%if USES_GAIN
fld1
fsubr qword [dword ebx + g_layer_gain]
fmul st0, st1
fmul st0, st1
fld1
faddp st1, st0
fdivr qword [dword ebx + g_layer_gain]
fsqrt
fmulp st1, st0
%endif
fstp dword [dword ebx + g_InstrumentRender + ecx*4]
fadd st1, st0
inc ecx
cmp ecx, eax
jl .adsrloop
fstp st0
ret
;; ********** Main music generation **********
section genMus text align=1
Clinkster_GenerateMusic:
_Clinkster_GenerateMusic@0:
pusha
fninit
; Make waveforms
mov edi, waveforms
%if USES_SINE
fldz
mov ecx, WAVE_SIZE
.sineloop:
fadd dword [c_wavestep]
fld st0
fldpi
fmulp st1, st0
fsin
fstp dword [edi]
scasd
loop .sineloop
fstp st0
%endif
%if USES_SAWTOOTH
fld1
fchs
mov ecx, WAVE_SIZE
.sawtoothloop:
fadd dword [c_wavestep]
fst dword [edi]
scasd
loop .sawtoothloop
fstp st0
%endif
%if USES_SQUARE
fld1
fchs
mov ecx, WAVE_SIZE
.squareloop:
cmp ecx, WAVE_SIZE/2
jne .notflipsq