diff --git a/4klang_VSTi/4klang.dll b/4klang_VSTi/4klang.dll index 79e1064..5b7e68f 100644 Binary files a/4klang_VSTi/4klang.dll and b/4klang_VSTi/4klang.dll differ diff --git a/4klang_VSTi/8klang.dll b/4klang_VSTi/8klang.dll index d9ec26d..ff9cd9e 100644 Binary files a/4klang_VSTi/8klang.dll and b/4klang_VSTi/8klang.dll differ diff --git a/4klang_source/4klang.asm b/4klang_source/4klang.asm index a1a93bf..3b72ebf 100644 --- a/4klang_source/4klang.asm +++ b/4klang_source/4klang.asm @@ -85,9 +85,14 @@ go4k_synth_commands dd 0 dd _go4kOUT_func@0 dd _go4kACC_func@0 dd _go4kFLD_func@0 -%ifdef GO4K_USE_FSTG - dd _go4kFSTG_func@0 +%ifdef GO4K_USE_GLITCH + dd _go4kGLITCH_func@0 +%else + dd _go4kFLD_func@0 %endif +%ifdef GO4K_USE_FSTG + dd _go4kFSTG_func@0 +%endif %ifdef USE_SECTIONS section .g4kdat2 data align=1 @@ -748,27 +753,27 @@ go4kDST_func_do: %endif movzx eax, byte [VAL-1] ; // get type flag %ifdef GO4K_USE_DST_SH - fld dword [edx+go4kDST_val.snhfreq] ; // snh in + fld dword [edx+go4kDST_val.snhfreq] ; // snh in (inr) %ifdef GO4K_USE_DST_MOD_SH - fadd dword [WRK+go4kDST_wrk.sm] ; // snh' in + fadd dword [WRK+go4kDST_wrk.sm] ; // snh' in (inr) %endif fmul st0, st0 ; // square the input so we never get negative and also have a smoother behaviour in the lower frequencies fchs - fadd dword [WRK+go4kDST_wrk.snhphase]; // snh' in + fadd dword [WRK+go4kDST_wrk.snhphase]; // snh' in (inr) fst dword [WRK+go4kDST_wrk.snhphase] - fldz ; // 0 snh' in - fucomip st1 ; // 0 snh' in + fldz ; // 0 snh' in (inr) + fucomip st1 ; // snh' in (inr) jc short go4kDST_func_hold - fld1 ; // 1 snh' in - faddp st1, st0 ; // 1+snh' in - fstp dword [WRK+go4kDST_wrk.snhphase]; // in + fld1 ; // 1 snh' in (inr) + faddp st1, st0 ; // 1+snh' in (inr) + fstp dword [WRK+go4kDST_wrk.snhphase]; // in (inr) %endif ; // calc pregain and postgain %ifdef GO4K_USE_DST_STEREO - test al, byte STEREO ; // outr inl + test al, byte STEREO jz short go4kDST_func_mono fxch st1 ; // inr inl - fld dword [edx+go4kDST_val.drive] ; // drive inr inl + fld dword [edx+go4kDST_val.drive] ; // drive inr inl %ifdef GO4K_USE_DST_MOD_DM fadd dword [WRK+go4kDST_wrk.dm] %endif @@ -779,26 +784,27 @@ go4kDST_func_do: fxch st1 ; // inl outr go4kDST_func_mono: %endif - fld dword [edx+go4kDST_val.drive] ; // drive in + fld dword [edx+go4kDST_val.drive] ; // drive in (outr) %ifdef GO4K_USE_DST_MOD_DM fadd dword [WRK+go4kDST_wrk.dm] %endif - call go4kWaveshaper ; // out + call go4kWaveshaper ; // out (outr) %ifdef GO4K_USE_DST_SH - fst dword [WRK+go4kDST_wrk.out] ; // out' + fst dword [WRK+go4kDST_wrk.out] ; // out' (outr) %endif - ret ; // out' + ret ; // out' (outr) %ifdef GO4K_USE_DST_SH -go4kDST_func_hold: - fstp st0 ; // in - fstp st0 +go4kDST_func_hold: ; // snh' in (inr) + fstp st0 ; // in (inr) + fstp st0 ; // (inr) %ifdef GO4K_USE_DST_STEREO - test al, byte STEREO ; // outr inl + fstp st0 + test al, byte STEREO jz short go4kDST_func_monohold - fld dword [WRK+go4kDST_wrk.out2] ; // out2 + fld dword [WRK+go4kDST_wrk.out2] ; // outr go4kDST_func_monohold: %endif - fld dword [WRK+go4kDST_wrk.out] ; // out + fld dword [WRK+go4kDST_wrk.out] ; // out (outr) ret %endif @@ -979,9 +985,9 @@ go4kDLL_func_buffer_nowrap2: loopne go4kDLL_func_loop fstp st0 ;// out' ;// process a dc filter to prevent heavy offsets in reverb - ;// we're using the dc filter variables from the next delay line here, but doesnt hurt anyway %ifdef GO4K_USE_DLL_DC_FILTER ; y(n) = x(n) - x(n-1) + R * y(n-1) + sub WRK, go4kDLL_wrk.size fld dword [WRK+go4kDLL_wrk.dcout] ;// dco out' fmul dword [c_dc_const] ;// dcc*dco out' fsub dword [WRK+go4kDLL_wrk.dcin] ;// dcc*dco-dci out' @@ -998,6 +1004,129 @@ go4kDLL_func_buffer_nowrap2: ret %endif + +%ifdef USE_SECTIONS +section .g4kcodu code align=1 +%else +section .text +%endif +; //---------------------------------------------------------------------------------------- +; // GLITCH Tick +; //---------------------------------------------------------------------------------------- +; // IN : WRK = unit workspace +; // IN : VAL = unit values +; // IN : ecx = global workspace +; // OUT : +; // DIRTY : eax +; //---------------------------------------------------------------------------------------- +export_func go4kGLITCH_func@0 +%ifdef GO4K_USE_GLITCH + push 5 + call go4kTransformValues + pushad + + mov edi, WRK + mov WRK, dword [_go4k_delay_buffer_ofs] ;// ebp is current delay + +; mov eax, dword [edx+go4kGLITCH_val.active] +; or eax, dword [edi+go4kGLITCH_wrk2.am] +; test eax, eax +; je go4kGLITCH_func_notactive ;// out + + fld dword [edx+go4kGLITCH_val.active] ;// a in + fadd dword [edi+go4kGLITCH_wrk2.am] ;// a' in + ; // check for activity + fldz ;// 0 a' in + fucomip st1 ;// a' in + fstp st0 ;// in + jnc go4kGLITCH_func_notactive ;// out + + ;// check for first call and init if so init (using slizesize slot) + mov eax, dword [WRK+go4kGLITCH_wrk.slizesize] + and eax, eax + jnz go4kGLITCH_func_process + mov dword [WRK+go4kGLITCH_wrk.index], eax + mov dword [WRK+go4kGLITCH_wrk.store], eax + movzx ebx, byte [VAL-(go4kGLITCH_val.size-go4kGLITCH_val.slicesize)/4] ;// slicesize index + movzx eax, word [_go4k_delay_times+ebx*2] ;// fetch slicesize + push eax + fld1 + fild dword [esp] + fstp dword [WRK+go4kGLITCH_wrk.slizesize] + fstp dword [WRK+go4kGLITCH_wrk.slicepitch] + pop eax +go4kGLITCH_func_process: + ;// fill buffer until full + mov eax, dword [WRK+go4kGLITCH_wrk.store] + cmp eax, MAX_DELAY + jae go4kGLITCH_func_filldone + fst dword [WRK+eax*4+go4kDLL_wrk.buffer] ;// in + inc dword [WRK+go4kGLITCH_wrk.store] +go4kGLITCH_func_filldone: + ;// save input + push eax + fstp dword [esp] ;// - + + ;// read from buffer + push eax + fld dword [WRK+go4kGLITCH_wrk.index] ;// idx + fist dword [esp] + pop eax + fld dword [WRK+eax*4+go4kDLL_wrk.buffer] ;// out idx + fxch ;// idx out + ;// progress readindex with current play speed + fadd dword [WRK+go4kGLITCH_wrk.slicepitch] ;// idx' out + fst dword [WRK+go4kGLITCH_wrk.index] + + ;// check for slice done + fld dword [WRK+go4kGLITCH_wrk.slizesize] ;// size idx' out + fxch ;// idx' size out + fucomip st1 ;// idx' out + fstp st0 ;// out + jc go4kGLITCH_func_process_done + ;// reinit for next loop + xor eax, eax + mov dword [WRK+go4kGLITCH_wrk.index], eax + + fld dword [edx+go4kGLITCH_val.dsize] + fadd dword [edi+go4kGLITCH_wrk2.sm] + fsub dword [c_0_5] + fmul dword [c_0_5] + call _Power@0 + fmul dword [WRK+go4kGLITCH_wrk.slizesize] + fstp dword [WRK+go4kGLITCH_wrk.slizesize] + + fld dword [edx+go4kGLITCH_val.dpitch] + fadd dword [edi+go4kGLITCH_wrk2.pm] + fsub dword [c_0_5] + fmul dword [c_0_5] + call _Power@0 + fmul dword [WRK+go4kGLITCH_wrk.slicepitch] + fstp dword [WRK+go4kGLITCH_wrk.slicepitch] +go4kGLITCH_func_process_done: + + ;// dry wet mix + fld dword [edx+go4kGLITCH_val.dry] ;// dry out + fadd dword [edi+go4kGLITCH_wrk2.dm] ;// dry' out + fld1 ;// 1 dry' out + fsub st1 ;// 1-dry' dry' out + fmulp st2 ;// dry' out' + fmul dword [esp] ;// in' out' + faddp st1, st0 ;// out' + + pop eax + jmp go4kGLITCH_func_leave +go4kGLITCH_func_notactive: + ;// mark as uninitialized again (using slizesize slot) + xor eax,eax + mov dword [WRK+go4kGLITCH_wrk.slizesize], eax +go4kGLITCH_func_leave: + add WRK, go4kDLL_wrk.size ;// go to next delay + mov dword [_go4k_delay_buffer_ofs], WRK ;// store next delay offset + popad + ret +%endif + %ifdef USE_SECTIONS section .g4kcodg code align=1 %else diff --git a/4klang_source/4klang.inc b/4klang_source/4klang.inc index 0e1e355..1208a3f 100644 --- a/4klang_source/4klang.inc +++ b/4klang_source/4klang.inc @@ -38,6 +38,7 @@ %define GO4K_USE_GLOBAL_DLL ; // removing this will skip global dll processing %define GO4K_USE_FSTG ; // removing this will skip global store unit %define GO4K_USE_FLD ; // removing this will skip float load unit +%define GO4K_USE_GLITCH ; // removing this will skip GLITCH unit %define GO4K_USE_ENV_CHECK ; // removing this skips checks if processing is needed %define GO4K_USE_ENV_MOD_GM ; // removing this will skip env gain modulation code %define GO4K_USE_ENV_MOD_ADR ; // removing this will skip env attack/decay/release modulation code @@ -475,11 +476,56 @@ struc go4kFLD_wrk .size endstruc %endif +%ifdef GO4K_USE_GLITCH +; //---------------------------------------------------------------------------------------- +; // GLITCH structs +; //---------------------------------------------------------------------------------------- +GO4K_GLITCH_ID equ 12 +%macro GO4K_GLITCH 5 + db %1 + db %2 + db %3 + db %4 + db %5 +%endmacro +%define ACTIVE(val) val +%define SLICEFACTOR(val)val +%define PITCHFACTOR(val)val +%define SLICESIZE(val) val +struc go4kGLITCH_val +;// unit paramters + .active resd 1 + .dry resd 1 + .dsize resd 1 + .dpitch resd 1 + .slicesize resd 1 + .size +endstruc +struc go4kGLITCH_wrk +;// work variables + .index resd 1 + .store resd 1 + .slizesize resd 1 + .slicepitch resd 1 + .unused resd 1 +;// the delay buffer + .buffer resd MAX_DELAY + .size +endstruc +struc go4kGLITCH_wrk2 +;// modulation targets + .am resd 1 + .dm resd 1 + .sm resd 1 + .pm resd 1 + .size +endstruc +%endif %ifdef GO4K_USE_FSTG ; //---------------------------------------------------------------------------------------- ; // FSTG structs ; //---------------------------------------------------------------------------------------- -GO4K_FSTG_ID equ 12 +GO4K_FSTG_ID equ 13 %macro GO4K_FSTG 2 db %1 dw %2 diff --git a/4klang_source/Go4kVSTi/source/GoSynth/Go4kVSTiCore.cpp b/4klang_source/Go4kVSTi/source/GoSynth/Go4kVSTiCore.cpp index eb79dd2..8310ab7 100644 --- a/4klang_source/Go4kVSTi/source/GoSynth/Go4kVSTiCore.cpp +++ b/4klang_source/Go4kVSTi/source/GoSynth/Go4kVSTiCore.cpp @@ -30,6 +30,7 @@ extern "C" void __stdcall go4kPAN_func(); extern "C" void __stdcall go4kOUT_func(); extern "C" void __stdcall go4kACC_func(); extern "C" void __stdcall go4kFLD_func(); +extern "C" void __stdcall go4kGLITCH_func(); extern "C" DWORD go4k_delay_buffer_ofs; extern "C" float go4k_delay_buffer; extern "C" WORD go4k_delay_times; @@ -54,7 +55,8 @@ static go4kFunc SynthFuncs[] = go4kPAN_func, go4kOUT_func, go4kACC_func, - go4kFLD_func + go4kFLD_func, + go4kGLITCH_func }; static float BeatsPerMinute = 120.0f; @@ -66,6 +68,7 @@ static int Solo = 0; // stream structures for recording sound static DWORD samplesProcessed = 0; static bool Recording = false; +static bool RecordingNoise = true; static bool FirstRecordingEvent = false; static DWORD PatternSize = 16; static float SamplesPerTick; @@ -227,7 +230,7 @@ void Go4kVSTi_FlipInstrumentSlots(char channel, int a, int b) memcpy(w1, temp, MAX_UNIT_SLOTS*4); } // reset dll workspaces, they are invalid now - if (v1[0] == M_DLL && v2[0] == M_DLL) + if ((v1[0] == M_DLL || v1[0] == M_GLITCH) && (v2[0] == M_DLL || v2[0] == M_GLITCH)) { Go4kVSTi_ClearDelayLines(); Go4kVSTi_UpdateDelayTimes(); @@ -257,7 +260,7 @@ void Go4kVSTi_FlipGlobalSlots(int a, int b) memcpy(w1, temp, MAX_UNIT_SLOTS*4); } // reset dll workspaces, they are invalid now - if (v1[0] == M_DLL && v2[0] == M_DLL) + if ((v1[0] == M_DLL || v1[0] == M_GLITCH) && (v2[0] == M_DLL || v2[0] == M_GLITCH)) { Go4kVSTi_ClearDelayLines(); Go4kVSTi_UpdateDelayTimes(); @@ -356,6 +359,15 @@ void Go4kVSTi_InitSlot(BYTE* slot, int channel, int type) FLD_valP v = (FLD_valP)slot; v->value = 64; } + if (type == M_GLITCH) + { + GLITCH_valP v = (GLITCH_valP)slot; + v->active = 0; + v->dry = 0; + v->dsize = 64; + v->dpitch = 64; + v->guidelay = 40; + } } // init a instrument slot @@ -367,7 +379,7 @@ void Go4kVSTi_InitInstrumentSlot(char channel, int s, int type) Go4kVSTi_ClearInstrumentSlot(channel, s); // init with default values Go4kVSTi_InitSlot(SynthObj.InstrumentValues[channel][s], channel, type); - if (type == M_DLL) + if (type == M_DLL || type == M_GLITCH) { Go4kVSTi_ClearDelayLines(); Go4kVSTi_UpdateDelayTimes(); @@ -383,7 +395,7 @@ void Go4kVSTi_InitGlobalSlot(int s, int type) Go4kVSTi_ClearGlobalSlot(s); // init with default values Go4kVSTi_InitSlot(SynthObj.GlobalValues[s], 16, type); - if (type == M_DLL) + if (type == M_DLL || type == M_GLITCH) { Go4kVSTi_ClearDelayLines(); Go4kVSTi_UpdateDelayTimes(); @@ -457,7 +469,7 @@ void Go4kVSTi_UpdateDelayTimes() if (v->id == M_DLL) { - DLL_valP v = (DLL_valP)(SynthObj.InstrumentValues[i][u]); + //DLL_valP v = (DLL_valP)(SynthObj.InstrumentValues[i][u]); if (v->reverb) { if (v->leftreverb) @@ -501,6 +513,22 @@ void Go4kVSTi_UpdateDelayTimes() delayindex++; } } + + if (v->id == M_GLITCH) + { + GLITCH_valP v2 = (GLITCH_valP)(v); + int delay; + float ftime; + float quarterlength = 60.0f/Go4kVSTi_GetBPM(); + ftime = quarterlength*delayTimeFraction[v2->guidelay>>2]; + delay = 44100.0f*ftime*0.25; // slice time is in fractions per beat (therefore / 4) + if (delay >= 65536) + delay = 65535; + (&go4k_delay_times)[delayindex] = delay; + v2->delay = delayindex; + + delayindex++; + } } } } @@ -546,328 +574,331 @@ void Go4kVSTi_Tick(float *oleft, float *oright, int samples) if (Recording) { samplesProcessed += samples; - // send a stayalive signal to the host - for (int i = 0; i < samples; i++) + + if (RecordingNoise) { - float signal = 0.0625*((float)(i&63)/32.0f - 1.0f); - *oleft++ = signal; - *oright++ = signal; + // send a stayalive signal to the host + for (int i = 0; i < samples; i++) + { + float signal = 0.03125*((float)(i & 255) / 128.0f - 1.0f); + *oleft++ = signal; + *oright++ = signal; + } + return; } } - else + + // do as many samples as requested + int s = 0; + while (s < samples) { - // do as many samples as requested - int s = 0; - while (s < samples) - { - float left=0.0f; - float right=0.0f; + float left=0.0f; + float right=0.0f; - go4k_delay_buffer_ofs = (DWORD)(&go4k_delay_buffer); - // loop all instruments - for (int i = 0; i < MAX_INSTRUMENTS; i++) + go4k_delay_buffer_ofs = (DWORD)(&go4k_delay_buffer); + // loop all instruments + for (int i = 0; i < MAX_INSTRUMENTS; i++) + { + // solo mode and not the channel we want? + if (Solo && i != SoloChannel) { - // solo mode and not the channel we want? - if (Solo && i != SoloChannel) + // loop all voices and clear outputs + for (int p = 0; p < SynthObj.Polyphony; p++) { - // loop all voices and clear outputs - for (int p = 0; p < SynthObj.Polyphony; p++) - { - InstrumentWorkspaceP iwork = &(SynthObj.InstrumentWork[i*MAX_POLYPHONY+p]); - iwork->dlloutl = 0.0f; - iwork->dlloutr = 0.0f; - iwork->outl = 0.0f; - iwork->outr = 0.0f; - } - // adjust delay index - for (int s = 0; s < MAX_UNITS; s++) + InstrumentWorkspaceP iwork = &(SynthObj.InstrumentWork[i*MAX_POLYPHONY+p]); + iwork->dlloutl = 0.0f; + iwork->dlloutr = 0.0f; + iwork->outl = 0.0f; + iwork->outr = 0.0f; + } + // adjust delay index + for (int s = 0; s < MAX_UNITS; s++) + { + BYTE* val = SynthObj.InstrumentValues[i][s]; + if (val[0] == M_DLL || val[0] == M_GLITCH) + go4k_delay_buffer_ofs += (5+65536)*4*SynthObj.Polyphony; + } + // go to next instrument + continue; + } + // if the instrument signal stack is valid and we still got a signal from that instrument + if (SynthObj.InstrumentSignalValid[i] && (fabs(SynthObj.SignalTrace[i]) > 0.00001f)) + { + float sumSignals = 0.0f; + // loop all voices + for (int p = 0; p < SynthObj.Polyphony; p++) + { + InstrumentWorkspaceP iwork = &(SynthObj.InstrumentWork[i*MAX_POLYPHONY+p]); + float *lwrk = iwork->workspace; + DWORD inote = iwork->note; + // loop each slot + for (int s = 0; s <= SynthObj.HighestSlotIndex[i]; s++) { BYTE* val = SynthObj.InstrumentValues[i][s]; - if (val[0] == M_DLL) - go4k_delay_buffer_ofs += (5+65536)*4*SynthObj.Polyphony; - } - // go to next instrument - continue; - } - // if the instrument signal stack is valid and we still got a signal from that instrument - if (SynthObj.InstrumentSignalValid[i] && (fabs(SynthObj.SignalTrace[i]) > 0.00001f)) - { - float sumSignals = 0.0f; - // loop all voices - for (int p = 0; p < SynthObj.Polyphony; p++) - { - InstrumentWorkspaceP iwork = &(SynthObj.InstrumentWork[i*MAX_POLYPHONY+p]); - float *lwrk = iwork->workspace; - DWORD inote = iwork->note; - // loop each slot - for (int s = 0; s <= SynthObj.HighestSlotIndex[i]; s++) - { - BYTE* val = SynthObj.InstrumentValues[i][s]; - float *wrk = &(iwork->workspace[s*MAX_UNIT_SLOTS]); - if (val[0] == M_FST) + float *wrk = &(iwork->workspace[s*MAX_UNIT_SLOTS]); + if (val[0] == M_FST) + { + FST_valP v = (FST_valP)val; + // if a target slot is set + if (v->dest_slot != -1) { - FST_valP v = (FST_valP)val; - // if a target slot is set - if (v->dest_slot != -1) + InstrumentWorkspaceP mwork; + int polyphonicStore = SynthObj.Polyphony; + int stack = v->dest_stack; + // local storage? + if (stack == -1 || stack == i) { - InstrumentWorkspaceP mwork; - int polyphonicStore = SynthObj.Polyphony; - int stack = v->dest_stack; - // local storage? - if (stack == -1 || stack == i) - { - // only store the sample in the current workspace - polyphonicStore = 1; - mwork = iwork; - } - else if (stack == MAX_INSTRUMENTS) - mwork = &(SynthObj.GlobalWork); - else - mwork = &(SynthObj.InstrumentWork[stack*MAX_POLYPHONY]); - - float* mdest = &(mwork->workspace[v->dest_unit*MAX_UNIT_SLOTS + v->dest_slot]); - float amount = (2.0f*v->amount - 128.0f)*0.0078125f; - int storetype = v->type; - for (int stc = 0; stc < polyphonicStore; stc++) - { - __asm - { - push eax - push ebx - - mov eax, mdest - mov ebx, storetype - - fld amount - fmul st(0), st(1) - - // test ebx, FST_MUL - // jz store_func_add - // fmul dword ptr [eax] - // jmp store_func_set - //store_func_add: - test ebx, FST_ADD - jz store_func_set - fadd dword ptr [eax] - store_func_set: - fstp dword ptr [eax] - store_func_done: - pop ebx - pop eax - } - mdest += sizeof(InstrumentWorkspace)/4; - } - // remove signal on pop flag - if (storetype & FST_POP) - { - _asm fstp st(0); - } + // only store the sample in the current workspace + polyphonicStore = 1; + mwork = iwork; } - } - else - { - // only process if note active or dll unit - if (val[0]) - { - // set up and call synth core func + else if (stack == MAX_INSTRUMENTS) + mwork = &(SynthObj.GlobalWork); + else + mwork = &(SynthObj.InstrumentWork[stack*MAX_POLYPHONY]); + + float* mdest = &(mwork->workspace[v->dest_unit*MAX_UNIT_SLOTS + v->dest_slot]); + float amount = (2.0f*v->amount - 128.0f)*0.0078125f; + int storetype = v->type; + for (int stc = 0; stc < polyphonicStore; stc++) + { __asm { - pushad - xor eax, eax - mov esi, val - lodsb - mov eax, dword ptr [SynthFuncs+eax*4] - mov ebx, inote - mov ecx, lwrk - mov ebp, wrk - call eax - popad + push eax + push ebx + + mov eax, mdest + mov ebx, storetype + + fld amount + fmul st(0), st(1) + + // test ebx, FST_MUL + // jz store_func_add + // fmul dword ptr [eax] + // jmp store_func_set + //store_func_add: + test ebx, FST_ADD + jz store_func_set + fadd dword ptr [eax] + store_func_set: + fstp dword ptr [eax] + store_func_done: + pop ebx + pop eax } + mdest += sizeof(InstrumentWorkspace)/4; } - } - } - // check for end of note - DWORD envstate = *((BYTE*)(lwrk)); - if (envstate == ENV_STATE_OFF) - { - iwork->note = 0; - } - sumSignals += fabsf(iwork->outl) + fabsf(iwork->outr) + fabsf(iwork->dlloutl) + fabsf(iwork->dlloutr); - } - // update envelope follower only for non control instruments. (1s attack rate) for total instrument signal - if (SynthObj.ControlInstrument[i]) - SynthObj.SignalTrace[i] = 1.0f; - else - SynthObj.SignalTrace[i] = sumSignals + 0.999977324f * ( SynthObj.SignalTrace[i] - sumSignals ); - } - // instrument stack invalid - else - { - // adjust delay index - for (int s = 0; s < MAX_UNITS; s++) - { - BYTE* val = SynthObj.InstrumentValues[i][s]; - if (val[0] == M_DLL) - go4k_delay_buffer_ofs += (5+65536)*4*SynthObj.Polyphony; - } - // loop all voices - for (int p = 0; p < SynthObj.Polyphony; p++) - { - InstrumentWorkspaceP iwork = &(SynthObj.InstrumentWork[i*MAX_POLYPHONY+p]); - iwork->dlloutl = 0.0f; - iwork->dlloutr = 0.0f; - iwork->outl = 0.0f; - iwork->outr = 0.0f; - } - } - } - // if the global stack is valid - if (SynthObj.GlobalSignalValid) - { - InstrumentWorkspaceP gwork = &(SynthObj.GlobalWork); - float *lwrk = gwork->workspace; - DWORD gnote = 1; - gwork->note = 1; - // loop all global slots - for (int s = 0; s <= SynthObj.HighestSlotIndex[16]; s++) - { - BYTE* val = SynthObj.GlobalValues[s]; - float *wrk = &(lwrk[s*MAX_UNIT_SLOTS]); - // manually accumulate signals - float ACCL = 0.0f; - float ACCR = 0.0f; - if (val[0] == M_ACC) - { - ACC_valP av = (ACC_valP)val; - if (av->flags == ACC_OUT) - { - for (int i = 0; i < MAX_INSTRUMENTS; i++) - { - for (int p = 0; p < SynthObj.Polyphony; p++) + // remove signal on pop flag + if (storetype & FST_POP) { - ACCL += SynthObj.InstrumentWork[i*MAX_POLYPHONY+p].outl; - ACCR += SynthObj.InstrumentWork[i*MAX_POLYPHONY+p].outr; + _asm fstp st(0); } } } else { - for (int i = 0; i < MAX_INSTRUMENTS; i++) - { - for (int p = 0; p < SynthObj.Polyphony; p++) - { - ACCL += SynthObj.InstrumentWork[i*MAX_POLYPHONY+p].dlloutl; - ACCR += SynthObj.InstrumentWork[i*MAX_POLYPHONY+p].dlloutr; - } - } - } - // push the accumulated signals on the fp stack - __asm - { - fld ACCR - fld ACCL - } - } - // no ACC unit, check store - else if (val[0] == M_FST) - { - FST_valP v = (FST_valP)val; - // if a target slot is set - if (v->dest_slot != -1) - { - InstrumentWorkspaceP mwork; - int polyphonicStore = SynthObj.Polyphony; - int stack = v->dest_stack; - // local storage? - if (stack == -1 || stack == MAX_INSTRUMENTS) - { - // only store the sample in the current workspace - polyphonicStore = 1; - mwork = &(SynthObj.GlobalWork); - } - else - mwork = &(SynthObj.InstrumentWork[stack*MAX_POLYPHONY]); - - float* mdest = &(mwork->workspace[v->dest_unit*MAX_UNIT_SLOTS + v->dest_slot]); - float amount = (2.0f*v->amount - 128.0f)*0.0078125f;; - int storetype = v->type; - for (int stc = 0; stc < polyphonicStore; stc++) + // only process if note active or dll unit + if (val[0]) { + // set up and call synth core func __asm { - push eax - push ebx - - mov eax, mdest - mov ebx, storetype - - fld amount - fmul st(0), st(1) - - // test ebx, FST_MUL - // jz gstore_func_add - // fmul dword ptr [eax] - // jmp gstore_func_set - //gstore_func_add: - test ebx, FST_ADD - jz gstore_func_set - fadd dword ptr [eax] - gstore_func_set: - fstp dword ptr [eax] - gstore_func_done: - pop ebx - pop eax + pushad + xor eax, eax + mov esi, val + lodsb + mov eax, dword ptr [SynthFuncs+eax*4] + mov ebx, inote + mov ecx, lwrk + mov ebp, wrk + call eax + popad } - mdest += sizeof(InstrumentWorkspace)/4; - } - // remove signal on pop flag - if (storetype & FST_POP) - { - _asm fstp st(0); } } } - // just call synth core func + // check for end of note + DWORD envstate = *((BYTE*)(lwrk)); + if (envstate == ENV_STATE_OFF) + { + iwork->note = 0; + } + sumSignals += fabsf(iwork->outl) + fabsf(iwork->outr) + fabsf(iwork->dlloutl) + fabsf(iwork->dlloutr); + } + // update envelope follower only for non control instruments. (1s attack rate) for total instrument signal + if (SynthObj.ControlInstrument[i]) + SynthObj.SignalTrace[i] = 1.0f; + else + SynthObj.SignalTrace[i] = sumSignals + 0.999977324f * ( SynthObj.SignalTrace[i] - sumSignals ); + } + // instrument stack invalid + else + { + // adjust delay index + for (int s = 0; s < MAX_UNITS; s++) + { + BYTE* val = SynthObj.InstrumentValues[i][s]; + if (val[0] == M_DLL || val[0] == M_GLITCH) + go4k_delay_buffer_ofs += (5+65536)*4*SynthObj.Polyphony; + } + // loop all voices + for (int p = 0; p < SynthObj.Polyphony; p++) + { + InstrumentWorkspaceP iwork = &(SynthObj.InstrumentWork[i*MAX_POLYPHONY+p]); + iwork->dlloutl = 0.0f; + iwork->dlloutr = 0.0f; + iwork->outl = 0.0f; + iwork->outr = 0.0f; + } + } + } + // if the global stack is valid + if (SynthObj.GlobalSignalValid) + { + InstrumentWorkspaceP gwork = &(SynthObj.GlobalWork); + float *lwrk = gwork->workspace; + DWORD gnote = 1; + gwork->note = 1; + // loop all global slots + for (int s = 0; s <= SynthObj.HighestSlotIndex[16]; s++) + { + BYTE* val = SynthObj.GlobalValues[s]; + float *wrk = &(lwrk[s*MAX_UNIT_SLOTS]); + // manually accumulate signals + float ACCL = 0.0f; + float ACCR = 0.0f; + if (val[0] == M_ACC) + { + ACC_valP av = (ACC_valP)val; + if (av->flags == ACC_OUT) + { + for (int i = 0; i < MAX_INSTRUMENTS; i++) + { + for (int p = 0; p < SynthObj.Polyphony; p++) + { + ACCL += SynthObj.InstrumentWork[i*MAX_POLYPHONY+p].outl; + ACCR += SynthObj.InstrumentWork[i*MAX_POLYPHONY+p].outr; + } + } + } else { - if (val[0]) + for (int i = 0; i < MAX_INSTRUMENTS; i++) + { + for (int p = 0; p < SynthObj.Polyphony; p++) + { + ACCL += SynthObj.InstrumentWork[i*MAX_POLYPHONY+p].dlloutl; + ACCR += SynthObj.InstrumentWork[i*MAX_POLYPHONY+p].dlloutr; + } + } + } + // push the accumulated signals on the fp stack + __asm + { + fld ACCR + fld ACCL + } + } + // no ACC unit, check store + else if (val[0] == M_FST) + { + FST_valP v = (FST_valP)val; + // if a target slot is set + if (v->dest_slot != -1) + { + InstrumentWorkspaceP mwork; + int polyphonicStore = SynthObj.Polyphony; + int stack = v->dest_stack; + // local storage? + if (stack == -1 || stack == MAX_INSTRUMENTS) + { + // only store the sample in the current workspace + polyphonicStore = 1; + mwork = &(SynthObj.GlobalWork); + } + else + mwork = &(SynthObj.InstrumentWork[stack*MAX_POLYPHONY]); + + float* mdest = &(mwork->workspace[v->dest_unit*MAX_UNIT_SLOTS + v->dest_slot]); + float amount = (2.0f*v->amount - 128.0f)*0.0078125f;; + int storetype = v->type; + for (int stc = 0; stc < polyphonicStore; stc++) { __asm { - pushad - xor eax, eax - mov esi, val - lodsb - mov eax, dword ptr [SynthFuncs+eax*4] - mov ebx, gnote - mov ecx, lwrk - mov ebp, wrk - call eax - popad + push eax + push ebx + + mov eax, mdest + mov ebx, storetype + + fld amount + fmul st(0), st(1) + + // test ebx, FST_MUL + // jz gstore_func_add + // fmul dword ptr [eax] + // jmp gstore_func_set + //gstore_func_add: + test ebx, FST_ADD + jz gstore_func_set + fadd dword ptr [eax] + gstore_func_set: + fstp dword ptr [eax] + gstore_func_done: + pop ebx + pop eax } + mdest += sizeof(InstrumentWorkspace)/4; + } + // remove signal on pop flag + if (storetype & FST_POP) + { + _asm fstp st(0); + } + } + } + // just call synth core func + else + { + if (val[0]) + { + __asm + { + pushad + xor eax, eax + mov esi, val + lodsb + mov eax, dword ptr [SynthFuncs+eax*4] + mov ebx, gnote + mov ecx, lwrk + mov ebp, wrk + call eax + popad } } } - left = gwork->outl; - right = gwork->outr; } + left = gwork->outl; + right = gwork->outr; + } - // clip - if (left < -1.0f) - left = -1.0f; - if (left > 1.0f) - left = 1.0f; - if (right < -1.0f) - right = -1.0f; - if (right > 1.0f) - right = 1.0f; + // clip + if (left < -1.0f) + left = -1.0f; + if (left > 1.0f) + left = 1.0f; + if (right < -1.0f) + right = -1.0f; + if (right > 1.0f) + right = 1.0f; - *(oleft++) = left; - *(oright++) = right; + *(oleft++) = left; + *(oright++) = right; - s++; - } // end sample loop - } + s++; + } // end sample loop } //////////////////////////////////////////////////////////////////////////// @@ -877,9 +908,10 @@ void Go4kVSTi_Tick(float *oleft, float *oright, int samples) //////////////////////////////////////////////////////////////////////////// // prepare for recording the midi stream -void Go4kVSTi_Record(bool record, int patternsize, float patternquant) +void Go4kVSTi_Record(bool record, bool recordingNoise, int patternsize, float patternquant) { Recording = record; + RecordingNoise = recordingNoise; // if we started recording, clear all record streams if (Recording) { @@ -957,35 +989,37 @@ void Go4kVSTi_AddVoice(int channel, int note) InstrumentRecord[channel][CurrentTick] = note; InstrumentOn[channel] = CurrentTick; } + + // no signals to synth when using recording noise + if (RecordingNoise == true) + return; } - else + + InstrumentWorkspaceP work,work2; + work = &(SynthObj.InstrumentWork[channel*MAX_POLYPHONY+0]); + work->release = 1; + work2 = &(SynthObj.InstrumentWork[channel*MAX_POLYPHONY+1]); + work2->release = 1; + // filp worspace + if (SynthObj.Polyphony > 1) { - InstrumentWorkspaceP work,work2; - work = &(SynthObj.InstrumentWork[channel*MAX_POLYPHONY+0]); - work->release = 1; - work2 = &(SynthObj.InstrumentWork[channel*MAX_POLYPHONY+1]); - work2->release = 1; - // filp worspace - if (SynthObj.Polyphony > 1) - { - work = &(SynthObj.InstrumentWork[channel*MAX_POLYPHONY+SynthObj.VoiceIndex[channel]]); - SynthObj.VoiceIndex[channel] = SynthObj.VoiceIndex[channel] ^ 0x1; - } - // add new note - memset(work, 0, (2+MAX_UNITS*MAX_UNIT_SLOTS)*4); - work->note = note; - SynthObj.SignalTrace[channel] = 1.0f; - // check if its a controll instrument which is played - SynthObj.ControlInstrument[channel] = 1; - for (int i = 0; i < MAX_UNITS; i++) - { - if (SynthObj.InstrumentValues[channel][i][0] == M_OUT) - { - SynthObj.ControlInstrument[channel] = 0; - break; - } - } + work = &(SynthObj.InstrumentWork[channel*MAX_POLYPHONY+SynthObj.VoiceIndex[channel]]); + SynthObj.VoiceIndex[channel] = SynthObj.VoiceIndex[channel] ^ 0x1; } + // add new note + memset(work, 0, (2+MAX_UNITS*MAX_UNIT_SLOTS)*4); + work->note = note; + SynthObj.SignalTrace[channel] = 1.0f; + // check if its a controll instrument which is played + SynthObj.ControlInstrument[channel] = 1; + for (int i = 0; i < MAX_UNITS; i++) + { + if (SynthObj.InstrumentValues[channel][i][0] == M_OUT) + { + SynthObj.ControlInstrument[channel] = 0; + break; + } + } } // stop a voice with given parameters in synth @@ -1005,16 +1039,18 @@ void Go4kVSTi_StopVoice(int channel, int note) } // if (!InstrumentRecord[channel][CurrentTick]) InstrumentOn[channel] = -1; + + // no signals to synth when only using recording noise + if (RecordingNoise == true) + return; } - else - { - InstrumentWorkspaceP work,work2; - // release notes - work = &(SynthObj.InstrumentWork[channel*MAX_POLYPHONY+0]); - work->release = 1; - work2 = &(SynthObj.InstrumentWork[channel*MAX_POLYPHONY+1]); - work2->release = 1; - } + + InstrumentWorkspaceP work,work2; + // release notes + work = &(SynthObj.InstrumentWork[channel*MAX_POLYPHONY+0]); + work->release = 1; + work2 = &(SynthObj.InstrumentWork[channel*MAX_POLYPHONY+1]); + work2->release = 1; } //---------------------------------------------------------------------------------------------------- @@ -1527,7 +1563,7 @@ void Go4kVSTi_LoadUnit(char* filename, BYTE* slot) { fread(slot, 1, MAX_UNIT_SLOTS, file); fclose(file); - if (slot[0] == M_DLL) + if (slot[0] == M_DLL || slot[0] == M_GLITCH) { Go4kVSTi_ClearDelayLines(); Go4kVSTi_UpdateDelayTimes(); @@ -1605,6 +1641,8 @@ struct SynthUses bool fld_use; bool fld_vm; + + bool glitch_use; }; void GetUses(SynthUses *uses, bool InstrumentUsed[]) @@ -1667,6 +1705,10 @@ void GetUses(SynthUses *uses, bool InstrumentUsed[]) { uses->fld_use = true; } + if (v[0] == M_GLITCH) + { + uses->glitch_use = true; + } if (v[0] == M_FST) { if ((((FST_valP)v)->dest_stack != -1) && (((FST_valP)v)->dest_stack != i)) @@ -1784,6 +1826,11 @@ void GetUses(SynthUses *uses, bool InstrumentUsed[]) if (slot == 0) uses->fld_vm = true; } + // if (v2[0] == M_GLITCH) + // { + // if (slot == 0) + // uses->glitch_am = true; + // } } } } @@ -2045,6 +2092,31 @@ void Go4kVSTi_SaveByteStream(HINSTANCE hInst, char* filename, int useenvlevels, hasReverb = true; } } + if (v->id == M_GLITCH) + { + DWORD times = (&go4k_delay_times)[delay_indices.size()]; + // check if indexed value already existed + int found = -1; + for (int j = 17; j < delay_times.size(); j++) + { + if (delay_times[j] == times) + { + found = j; + break; + } + } + if (found != -1) + { + // already in list, so let index point to that one + delay_indices.push_back(found); + } + else + { + // new value, so push it + delay_times.push_back(times); + delay_indices.push_back(delay_times.size()-1); + } + } } // no used instrument else @@ -2063,6 +2135,11 @@ void Go4kVSTi_SaveByteStream(HINSTANCE hInst, char* filename, int useenvlevels, } } } + if (v->id == M_GLITCH) + { + // just push a dummy index + delay_indices.push_back(-1); + } } } } @@ -2174,6 +2251,8 @@ void Go4kVSTi_SaveByteStream(HINSTANCE hInst, char* filename, int useenvlevels, fprintf(file, "%%define GO4K_USE_FSTG\n"); if (uses.fld_use) fprintf(file, "%%define GO4K_USE_FLD\n"); + if (uses.glitch_use) + fprintf(file, "%%define GO4K_USE_GLITCH\n"); fprintf(file, "%%define GO4K_USE_ENV_CHECK\n"); if (uses.env_gm) fprintf(file, "%%define GO4K_USE_ENV_MOD_GM\n"); @@ -2255,8 +2334,8 @@ void Go4kVSTi_SaveByteStream(HINSTANCE hInst, char* filename, int useenvlevels, fprintf(file, "%%define GO4K_USE_DLL_MOD_AM\n"); fprintf(file, "%%define MAX_DELAY 65536\n"); - fprintf(file, "%%define MAX_UNITS 48\n"); - fprintf(file, "%%define MAX_UNIT_SLOTS 9\n"); + fprintf(file, "%%define MAX_UNITS 64\n"); + fprintf(file, "%%define MAX_UNIT_SLOTS 16\n"); fprintf(file, "%%define GO4K_BEGIN_CMDDEF(def_name)\n"); fprintf(file, "%%define GO4K_END_CMDDEF db 0\n"); fprintf(file, "%%define GO4K_BEGIN_PARAMDEF(def_name)\n"); @@ -2598,9 +2677,48 @@ void Go4kVSTi_SaveByteStream(HINSTANCE hInst, char* filename, int useenvlevels, fprintf(file, " .size\n"); fprintf(file, "endstruc\n"); fprintf(file, "%%endif\n"); + + fprintf(file, "%%ifdef GO4K_USE_GLITCH\n"); + fprintf(file, "GO4K_GLITCH_ID equ 12\n"); + fprintf(file, "%%macro GO4K_GLITCH 5\n"); + fprintf(file, " db %%1\n"); + fprintf(file, " db %%2\n"); + fprintf(file, " db %%3\n"); + fprintf(file, " db %%4\n"); + fprintf(file, " db %%5\n"); + fprintf(file, "%%endmacro\n"); + fprintf(file, "%%define ACTIVE(val) val\n"); + fprintf(file, "%%define SLICEFACTOR(val)val\n"); + fprintf(file, "%%define PITCHFACTOR(val)val\n"); + fprintf(file, "%%define SLICESIZE(val) val\n"); + fprintf(file, "struc go4kGLITCH_val\n"); + fprintf(file, " .active resd 1\n"); + fprintf(file, " .dry resd 1\n"); + fprintf(file, " .dsize resd 1\n"); + fprintf(file, " .dpitch resd 1\n"); + fprintf(file, " .slicesize resd 1\n"); + fprintf(file, " .size\n"); + fprintf(file, "endstruc\n"); + fprintf(file, "struc go4kGLITCH_wrk\n"); + fprintf(file, " .index resd 1\n"); + fprintf(file, " .store resd 1\n"); + fprintf(file, " .slizesize resd 1\n"); + fprintf(file, " .slicepitch resd 1\n"); + fprintf(file, " .unused resd 1\n"); + fprintf(file, " .buffer resd MAX_DELAY\n"); + fprintf(file, " .size\n"); + fprintf(file, "endstruc\n"); + fprintf(file, "struc go4kGLITCH_wrk2\n"); + fprintf(file, " .am resd 1\n"); + fprintf(file, " .dm resd 1\n"); + fprintf(file, " .sm resd 1\n"); + fprintf(file, " .pm resd 1\n"); + fprintf(file, " .size\n"); + fprintf(file, "endstruc\n"); + fprintf(file, "%%endif\n"); fprintf(file, "%%ifdef GO4K_USE_FSTG\n"); - fprintf(file, "GO4K_FSTG_ID equ 12\n"); + fprintf(file, "GO4K_FSTG_ID equ 13\n"); fprintf(file, "%%macro GO4K_FSTG 2\n"); fprintf(file, " db %%1\n"); fprintf(file, " dw %%2\n"); @@ -2751,6 +2869,8 @@ void Go4kVSTi_SaveByteStream(HINSTANCE hInst, char* filename, int useenvlevels, sprintf(comstr, "\tdb GO4K_ACC_ID\n"); if (SynthObj.InstrumentValues[i][u][0] == M_FLD) sprintf(comstr, "\tdb GO4K_FLD_ID\n"); + if (SynthObj.InstrumentValues[i][u][0] == M_GLITCH) + sprintf(comstr, "\tdb GO4K_GLITCH_ID\n"); CommandString += comstr; } @@ -2791,6 +2911,8 @@ void Go4kVSTi_SaveByteStream(HINSTANCE hInst, char* filename, int useenvlevels, fprintf(file, "\tdb GO4K_ACC_ID\n"); if (SynthObj.GlobalValues[u][0] == M_FLD) fprintf(file, "\tdb GO4K_FLD_ID\n"); + if (SynthObj.GlobalValues[u][0] == M_GLITCH) + fprintf(file, "\tdb GO4K_GLITCH_ID\n"); } fprintf(file, "GO4K_END_CMDDEF\n"); fprintf(file, "go4k_synth_instructions_end\n"); @@ -3001,6 +3123,21 @@ void Go4kVSTi_SaveByteStream(HINSTANCE hInst, char* filename, int useenvlevels, FLD_valP v = (FLD_valP)(SynthObj.InstrumentValues[i][u]); sprintf(valstr, "\tGO4K_FLD\tVALUE(%d)\n", v->value); } + if (SynthObj.InstrumentValues[i][u][0] == M_GLITCH) + { + GLITCH_valP v = (GLITCH_valP)(SynthObj.InstrumentValues[i][u]); + if (v->delay < delay_indices.size()) + { + sprintf(valstr, "\tGO4K_GLITCH\tACTIVE(%d),DRY(%d),SLICEFACTOR(%d),PITCHFACTOR(%d),SLICESIZE(%d)\n", + v->active, v->dry, v->dsize, v->dpitch, delay_indices[v->delay]); + } + // error handling in case indices are fucked up + else + { + sprintf(valstr, "\tGO4K_GLITCH\tACTIVE(%d),DRY(%d),SLICEFACTOR(%d),PITCHFACTOR(%d),SLICESIZE(%d) ; ERROR\n", + v->active, v->dry, v->dsize, v->dpitch, v->delay); + } + } ValueString += valstr; } @@ -3130,7 +3267,7 @@ void Go4kVSTi_SaveByteStream(HINSTANCE hInst, char* filename, int useenvlevels, // modes = "FST_MUL"; if (v->type & FST_POP) modes += "+FST_POP"; - fprintf(file, "\tGO4K_FST\tAMOUNT(%d),DEST(%d*MAX_UNIT_SLOTS+%d+%s)\n", v->amount, v->dest_unit-emptySkip, v->dest_slot, modes ); + fprintf(file, "\tGO4K_FST\tAMOUNT(%d),DEST(%d*MAX_UNIT_SLOTS+%d+%s)\n", v->amount, v->dest_unit-emptySkip, v->dest_slot, modes.c_str()); } // global storage else @@ -3185,6 +3322,21 @@ void Go4kVSTi_SaveByteStream(HINSTANCE hInst, char* filename, int useenvlevels, FLD_valP v = (FLD_valP)(SynthObj.GlobalValues[u]); fprintf(file, "\tGO4K_FLD\tVALUE(%d)\n", v->value); } + if (SynthObj.GlobalValues[u][0] == M_GLITCH) + { + GLITCH_valP v = (GLITCH_valP)(SynthObj.GlobalValues[u]); + if (v->delay < delay_indices.size()) + { + fprintf(file, "\tGO4K_GLITCH\tACTIVE(%d),DRY(%d),SLICEFACTOR(%d),PITCHFACTOR(%d),SLICESIZE(%d)\n", + v->active, v->dry, v->dsize, v->dpitch, delay_indices[v->delay]); + } + // error handling in case indices are fucked up + else + { + fprintf(file, "\tGO4K_GLITCH\tACTIVE(%d),DRY(%d),SLICEFACTOR(%d),PITCHFACTOR(%d),SLICESIZE(%d) ; ERROR\n", + v->active, v->dry, v->dsize, v->dpitch, v->delay); + } + } } fprintf(file, "GO4K_END_PARAMDEF\n"); } diff --git a/4klang_source/Go4kVSTi/source/GoSynth/Go4kVSTiCore.h b/4klang_source/Go4kVSTi/source/GoSynth/Go4kVSTiCore.h index 4d2f4df..c1af657 100644 --- a/4klang_source/Go4kVSTi/source/GoSynth/Go4kVSTiCore.h +++ b/4klang_source/Go4kVSTi/source/GoSynth/Go4kVSTiCore.h @@ -38,7 +38,7 @@ float Go4kVSTi_GetBPM(); // activate solo mode void Go4kVSTi_Solo(int channel, int solo); // stream recording activation/deactivation -void Go4kVSTi_Record(bool record, int patternsize, float patternquant); +void Go4kVSTi_Record(bool record, bool recordingNoise, int patternsize, float patternquant); // panic void Go4kVSTi_Panic(); // update dll times (e.g. sync to current bpm) @@ -87,6 +87,7 @@ enum UnitID M_OUT, M_ACC, M_FLD, + M_GLITCH, NUM_MODULES }; @@ -267,6 +268,19 @@ typedef struct FLD_val // GUI STUFF } *FLD_valP; +typedef struct GLITCH_val +{ + BYTE id; + BYTE active; + BYTE dry; + BYTE dsize; + BYTE dpitch; + BYTE delay; +// GUI STUFF + BYTE guidelay; +} *GLITCH_valP; + + ///////////////////////////////////////////////////////////////////////////////////// // workspace definitions ///////////////////////////////////////////////////////////////////////////////////// diff --git a/4klang_source/Go4kVSTi/source/GoSynth/Go4kVSTiGUI.cpp b/4klang_source/Go4kVSTi/source/GoSynth/Go4kVSTiGUI.cpp index 5157922..9d93fb2 100644 --- a/4klang_source/Go4kVSTi/source/GoSynth/Go4kVSTiGUI.cpp +++ b/4klang_source/Go4kVSTi/source/GoSynth/Go4kVSTiGUI.cpp @@ -52,7 +52,8 @@ static char* UnitName[NUM_MODULES] = "Panning", "Output", "Accumulate", - "Load" + "Load", + "Glitch" }; // minimal signal precondition for each unit @@ -70,6 +71,7 @@ static int UnitPreSignals[NUM_MODULES] = 2, // out 0, // acc 0, // fld + 1, // glitch }; // signal post condition (relative to precondition) @@ -86,7 +88,8 @@ static int UnitPostSignals[NUM_MODULES] = 1, // pan -2, // out 2, // acc - 1 // fld + 1, // fld + 0 // glitch }; static char* UnitModulationTargetNames[][8] = @@ -103,6 +106,7 @@ static char* UnitModulationTargetNames[][8] = { "AUX", "Gain", "", "", "", "", "", "" }, { "", "", "", "", "", "", "", "" }, { "Value", "", "", "", "", "", "", "" }, + { "Active", "Dry", "Delta Size", "Delta Pitch", "", "", "", "" }, }; static char* UnitModulationTargetShortNames[][8] = @@ -119,6 +123,7 @@ static char* UnitModulationTargetShortNames[][8] = { "AUX", "Gain", "", "", "", "", "", "" }, { "", "", "", "", "", "", "", "" }, { "Value", "", "", "", "", "", "", "" }, + { "Active", "Dry", "DSize", "DPitch", "", "", "", "" }, }; static char* delayName[33] = @@ -288,6 +293,11 @@ char* GetUnitString(BYTE* unit, char* unitname) FLD_valP val = (FLD_valP)unit; sprintf(UnitDesc, " (%d)", val->value-64); } + if (unit[0] == M_GLITCH) + { + GLITCH_valP val = (GLITCH_valP)unit; + sprintf(UnitDesc, " (%s)","Glitch"); + } sprintf(unitname, "%s%s", UnitName[unit[0]], UnitDesc); return unitname; @@ -323,6 +333,18 @@ void UpdateDelayTimes(DLL_valP unit) } } +void UpdateDelayTimes(GLITCH_valP unit) +{ + Go4kVSTi_UpdateDelayTimes(); + + int delay; + char text[10]; + GLITCH_valP v = (GLITCH_valP)unit; + sprintf(text, "%s", delayName[v->guidelay>>2]); + sprintf(SliderValTxt, "%s", text); + SetWindowText(GetDlgItem(ModuleWnd[M_GLITCH], IDC_GLITCH_DTIME_VAL), SliderValTxt); +} + // CB for the main DLG BOOL CALLBACK MainDialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) { @@ -370,6 +392,7 @@ BOOL CALLBACK MainDialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM l SendDlgItemMessage(hwndDlg, IDC_POLYPHONY, CB_SETCURSEL, (WPARAM)1, (LPARAM)0); SendDlgItemMessage(hwndDlg, IDC_CLIPOUTPUT, BM_SETCHECK, 1, 0); + SendDlgItemMessage(hwndDlg, IDC_RECORDBUSYSIGNAL, BM_SETCHECK, 1, 0); return TRUE; } @@ -435,6 +458,22 @@ BOOL CALLBACK MainDialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM l return TRUE; } } + else if (SynthObjP->InstrumentValues[SelectedInstrument][u][0] == M_GLITCH) + { + GLITCH_valP ds = (GLITCH_valP)SynthObjP->InstrumentValues[SelectedInstrument][u]; + GLITCH_valP dl = (GLITCH_valP)SynthObjP->InstrumentValues[linkToInstrument][u]; + if (ds->active != dl->active || + ds->dry != dl->dry || + ds->dsize != dl->dsize || + ds->dpitch != dl->dpitch || + ds->guidelay != dl->guidelay + ) + { + MessageBox(DialogWnd, "Instruments cannot be linked as they differ!", "Info", MB_OK); + SendDlgItemMessage(hwndDlg, IDC_INSTRUMENTLINK, CB_SETCURSEL, (WPARAM)16, (LPARAM)0); + return TRUE; + } + } else { if (memcmp(SynthObjP->InstrumentValues[SelectedInstrument][u], SynthObjP->InstrumentValues[linkToInstrument][u], MAX_UNIT_SLOTS)) @@ -567,8 +606,69 @@ BOOL CALLBACK MainDialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM l //instrument check for (int i = 0; i < MAX_INSTRUMENTS; i++) { - UpdateSignalCount(i); + UpdateSignalCount(i); LinkToInstrument[i] = 16; + // try setting up instrument links + if (i > 0) + { + for (int j = 0; j < i; j++) + { + int linkToInstrument = j; + // compare instruments + for (int u = 0; u < MAX_UNITS; u++) + { + // special case, compare manually + if (SynthObjP->InstrumentValues[i][u][0] == M_DLL) + { + DLL_valP ds = (DLL_valP)SynthObjP->InstrumentValues[i][u]; + DLL_valP dl = (DLL_valP)SynthObjP->InstrumentValues[j][u]; + if (ds->pregain != dl->pregain || + ds->dry != dl->dry || + ds->feedback != dl->feedback || + ds->damp != dl->damp || + ds->freq != dl->freq || + ds->depth != dl->depth || + ds->guidelay != dl->guidelay || + ds->synctype != dl->synctype || + ds->leftreverb != dl->leftreverb || + ds->reverb != dl->reverb) + { + linkToInstrument = 16; + break; + } + } + else if (SynthObjP->InstrumentValues[i][u][0] == M_GLITCH) + { + GLITCH_valP ds = (GLITCH_valP)SynthObjP->InstrumentValues[i][u]; + GLITCH_valP dl = (GLITCH_valP)SynthObjP->InstrumentValues[j][u]; + if (ds->active != dl->active || + ds->dry != dl->dry || + ds->dsize != dl->dsize || + ds->dpitch != dl->dpitch || + ds->guidelay != dl->guidelay + ) + { + linkToInstrument = 16; + break; + } + } + else + { + if (memcmp(SynthObjP->InstrumentValues[i][u], SynthObjP->InstrumentValues[j][u], MAX_UNIT_SLOTS)) + { + linkToInstrument = 16; + break; + } + } + } + // set link + if (linkToInstrument != 16) + { + LinkToInstrument[i] = linkToInstrument; + break; + } + } + } } UpdateControls(SelectedInstrument); } @@ -910,14 +1010,17 @@ BOOL CALLBACK MainDialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM l patternquant = 4.0; if (pquant == 5) patternquant = 8.0; - Go4kVSTi_Record(true, patternsize, patternquant); + + bool recordingNoise = SendDlgItemMessage(hwndDlg, IDC_RECORDBUSYSIGNAL, BM_GETCHECK, 0, 0) == BST_CHECKED; + + Go4kVSTi_Record(true, recordingNoise, patternsize, patternquant); return TRUE; } case IDC_STOP_BUTTON: { EnableWindow(GetDlgItem(DialogWnd, IDC_RECORD_BUTTON), true); EnableWindow(GetDlgItem(DialogWnd, IDC_STOP_BUTTON), false); - Go4kVSTi_Record(false, 0, 0); + Go4kVSTi_Record(false, false, 0, 0); return TRUE; } case IDC_PANIC: @@ -1034,6 +1137,67 @@ BOOL CALLBACK MainDialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM l { UpdateSignalCount(i); LinkToInstrument[i] = 16; + // try setting up instrument links + if (i > 0) + { + for (int j = 0; j < i; j++) + { + int linkToInstrument = j; + // compare instruments + for (int u = 0; u < MAX_UNITS; u++) + { + // special case, compare manually + if (SynthObjP->InstrumentValues[i][u][0] == M_DLL) + { + DLL_valP ds = (DLL_valP)SynthObjP->InstrumentValues[i][u]; + DLL_valP dl = (DLL_valP)SynthObjP->InstrumentValues[j][u]; + if (ds->pregain != dl->pregain || + ds->dry != dl->dry || + ds->feedback != dl->feedback || + ds->damp != dl->damp || + ds->freq != dl->freq || + ds->depth != dl->depth || + ds->guidelay != dl->guidelay || + ds->synctype != dl->synctype || + ds->leftreverb != dl->leftreverb || + ds->reverb != dl->reverb) + { + linkToInstrument = 16; + break; + } + } + else if (SynthObjP->InstrumentValues[i][u][0] == M_GLITCH) + { + GLITCH_valP ds = (GLITCH_valP)SynthObjP->InstrumentValues[i][u]; + GLITCH_valP dl = (GLITCH_valP)SynthObjP->InstrumentValues[j][u]; + if (ds->active != dl->active || + ds->dry != dl->dry || + ds->dsize != dl->dsize || + ds->dpitch != dl->dpitch || + ds->guidelay != dl->guidelay + ) + { + linkToInstrument = 16; + break; + } + } + else + { + if (memcmp(SynthObjP->InstrumentValues[i][u], SynthObjP->InstrumentValues[j][u], MAX_UNIT_SLOTS)) + { + linkToInstrument = 16; + break; + } + } + } + // set link + if (linkToInstrument != 16) + { + LinkToInstrument[i] = linkToInstrument; + break; + } + } + } } UpdateControls(SelectedInstrument); } @@ -1410,6 +1574,17 @@ void LinkInstrumentUnit(int selectedInstrument, int selectedIUnit) dl->leftreverb = ds->leftreverb; dl->reverb = ds->reverb; } + else if (SynthObjP->InstrumentValues[selectedInstrument][selectedIUnit][0] == M_GLITCH) + { + GLITCH_valP ds = (GLITCH_valP)SynthObjP->InstrumentValues[selectedInstrument][selectedIUnit]; + GLITCH_valP dl = (GLITCH_valP)SynthObjP->InstrumentValues[i][selectedIUnit]; + dl->id = ds->id; + dl->active = ds->active; + dl->dry = ds->dry; + dl->dsize = ds->dsize; + dl->dpitch = ds->dpitch; + dl->guidelay = ds->guidelay; + } else { memcpy(SynthObjP->InstrumentValues[i][selectedIUnit], @@ -2030,6 +2205,36 @@ void SetSliderParams(int uid, BYTE* val, LPARAM lParam) UpdateSliderValueCenter(IDC_FLD_VALUE, v->value); } } + else if (uid == M_GLITCH) + { + GLITCH_valP v = (GLITCH_valP)val; + // active + if ((HWND)lParam == GetDlgItem(ModuleWnd[uid], IDC_GLITCH_ACTIVE)) + { + UpdateSliderValue(IDC_GLITCH_ACTIVE, v->active); + } + // dry + if ((HWND)lParam == GetDlgItem(ModuleWnd[uid], IDC_GLITCH_DRY)) + { + UpdateSliderValue(IDC_GLITCH_DRY, v->dry); + } + // delta size + if ((HWND)lParam == GetDlgItem(ModuleWnd[uid], IDC_GLITCH_DSIZE)) + { + UpdateSliderValue(IDC_GLITCH_DSIZE, v->dsize); + } + // delta pitch + if ((HWND)lParam == GetDlgItem(ModuleWnd[uid], IDC_GLITCH_DPITCH)) + { + UpdateSliderValue(IDC_GLITCH_DPITCH, v->dpitch); + } + // delay + if ((HWND)lParam == GetDlgItem(ModuleWnd[uid], IDC_GLITCH_DTIME)) + { + v->guidelay = SendMessage(GetDlgItem(ModuleWnd[uid], IDC_GLITCH_DTIME), TBM_GETPOS, 0, 0); + UpdateDelayTimes(v); + } + } } bool ScrollbarChanged(HWND hwndDlg, WPARAM wParam, LPARAM lParam) @@ -3122,6 +3327,25 @@ void UpdateModule(int uid, BYTE* val) // panning InitSliderCenter(ModuleWnd[uid], IDC_FLD_VALUE, 0, 128, v->value); } + else if (uid == M_GLITCH) + { + GLITCH_valP v = (GLITCH_valP)val; + // active + InitSlider(ModuleWnd[uid], IDC_GLITCH_ACTIVE, 0, 128, v->active); + // dry + InitSlider(ModuleWnd[uid], IDC_GLITCH_DRY, 0, 128, v->dry); + // delta size + InitSlider(ModuleWnd[uid], IDC_GLITCH_DSIZE, 0, 128, v->dsize); + // delta pitch + InitSlider(ModuleWnd[uid], IDC_GLITCH_DPITCH, 0, 128, v->dpitch); + // delay + InitSliderNoGUI(ModuleWnd[uid], IDC_GLITCH_DTIME, 0, 128, v->guidelay); + + ShowWindow(GetDlgItem(ModuleWnd[M_DLL], IDC_GLITCH_DTIME), SW_SHOW); + ShowWindow(GetDlgItem(ModuleWnd[M_DLL], IDC_GLITCH_DTIME_VAL), SW_SHOW); + + UpdateDelayTimes(v); + } } void UpdateModuleParamWindow(int tab, int unit) diff --git a/4klang_source/Go4kVSTi/win/4klang.asm b/4klang_source/Go4kVSTi/win/4klang.asm index a1a93bf..3b72ebf 100644 --- a/4klang_source/Go4kVSTi/win/4klang.asm +++ b/4klang_source/Go4kVSTi/win/4klang.asm @@ -85,9 +85,14 @@ go4k_synth_commands dd 0 dd _go4kOUT_func@0 dd _go4kACC_func@0 dd _go4kFLD_func@0 -%ifdef GO4K_USE_FSTG - dd _go4kFSTG_func@0 +%ifdef GO4K_USE_GLITCH + dd _go4kGLITCH_func@0 +%else + dd _go4kFLD_func@0 %endif +%ifdef GO4K_USE_FSTG + dd _go4kFSTG_func@0 +%endif %ifdef USE_SECTIONS section .g4kdat2 data align=1 @@ -748,27 +753,27 @@ go4kDST_func_do: %endif movzx eax, byte [VAL-1] ; // get type flag %ifdef GO4K_USE_DST_SH - fld dword [edx+go4kDST_val.snhfreq] ; // snh in + fld dword [edx+go4kDST_val.snhfreq] ; // snh in (inr) %ifdef GO4K_USE_DST_MOD_SH - fadd dword [WRK+go4kDST_wrk.sm] ; // snh' in + fadd dword [WRK+go4kDST_wrk.sm] ; // snh' in (inr) %endif fmul st0, st0 ; // square the input so we never get negative and also have a smoother behaviour in the lower frequencies fchs - fadd dword [WRK+go4kDST_wrk.snhphase]; // snh' in + fadd dword [WRK+go4kDST_wrk.snhphase]; // snh' in (inr) fst dword [WRK+go4kDST_wrk.snhphase] - fldz ; // 0 snh' in - fucomip st1 ; // 0 snh' in + fldz ; // 0 snh' in (inr) + fucomip st1 ; // snh' in (inr) jc short go4kDST_func_hold - fld1 ; // 1 snh' in - faddp st1, st0 ; // 1+snh' in - fstp dword [WRK+go4kDST_wrk.snhphase]; // in + fld1 ; // 1 snh' in (inr) + faddp st1, st0 ; // 1+snh' in (inr) + fstp dword [WRK+go4kDST_wrk.snhphase]; // in (inr) %endif ; // calc pregain and postgain %ifdef GO4K_USE_DST_STEREO - test al, byte STEREO ; // outr inl + test al, byte STEREO jz short go4kDST_func_mono fxch st1 ; // inr inl - fld dword [edx+go4kDST_val.drive] ; // drive inr inl + fld dword [edx+go4kDST_val.drive] ; // drive inr inl %ifdef GO4K_USE_DST_MOD_DM fadd dword [WRK+go4kDST_wrk.dm] %endif @@ -779,26 +784,27 @@ go4kDST_func_do: fxch st1 ; // inl outr go4kDST_func_mono: %endif - fld dword [edx+go4kDST_val.drive] ; // drive in + fld dword [edx+go4kDST_val.drive] ; // drive in (outr) %ifdef GO4K_USE_DST_MOD_DM fadd dword [WRK+go4kDST_wrk.dm] %endif - call go4kWaveshaper ; // out + call go4kWaveshaper ; // out (outr) %ifdef GO4K_USE_DST_SH - fst dword [WRK+go4kDST_wrk.out] ; // out' + fst dword [WRK+go4kDST_wrk.out] ; // out' (outr) %endif - ret ; // out' + ret ; // out' (outr) %ifdef GO4K_USE_DST_SH -go4kDST_func_hold: - fstp st0 ; // in - fstp st0 +go4kDST_func_hold: ; // snh' in (inr) + fstp st0 ; // in (inr) + fstp st0 ; // (inr) %ifdef GO4K_USE_DST_STEREO - test al, byte STEREO ; // outr inl + fstp st0 + test al, byte STEREO jz short go4kDST_func_monohold - fld dword [WRK+go4kDST_wrk.out2] ; // out2 + fld dword [WRK+go4kDST_wrk.out2] ; // outr go4kDST_func_monohold: %endif - fld dword [WRK+go4kDST_wrk.out] ; // out + fld dword [WRK+go4kDST_wrk.out] ; // out (outr) ret %endif @@ -979,9 +985,9 @@ go4kDLL_func_buffer_nowrap2: loopne go4kDLL_func_loop fstp st0 ;// out' ;// process a dc filter to prevent heavy offsets in reverb - ;// we're using the dc filter variables from the next delay line here, but doesnt hurt anyway %ifdef GO4K_USE_DLL_DC_FILTER ; y(n) = x(n) - x(n-1) + R * y(n-1) + sub WRK, go4kDLL_wrk.size fld dword [WRK+go4kDLL_wrk.dcout] ;// dco out' fmul dword [c_dc_const] ;// dcc*dco out' fsub dword [WRK+go4kDLL_wrk.dcin] ;// dcc*dco-dci out' @@ -998,6 +1004,129 @@ go4kDLL_func_buffer_nowrap2: ret %endif + +%ifdef USE_SECTIONS +section .g4kcodu code align=1 +%else +section .text +%endif +; //---------------------------------------------------------------------------------------- +; // GLITCH Tick +; //---------------------------------------------------------------------------------------- +; // IN : WRK = unit workspace +; // IN : VAL = unit values +; // IN : ecx = global workspace +; // OUT : +; // DIRTY : eax +; //---------------------------------------------------------------------------------------- +export_func go4kGLITCH_func@0 +%ifdef GO4K_USE_GLITCH + push 5 + call go4kTransformValues + pushad + + mov edi, WRK + mov WRK, dword [_go4k_delay_buffer_ofs] ;// ebp is current delay + +; mov eax, dword [edx+go4kGLITCH_val.active] +; or eax, dword [edi+go4kGLITCH_wrk2.am] +; test eax, eax +; je go4kGLITCH_func_notactive ;// out + + fld dword [edx+go4kGLITCH_val.active] ;// a in + fadd dword [edi+go4kGLITCH_wrk2.am] ;// a' in + ; // check for activity + fldz ;// 0 a' in + fucomip st1 ;// a' in + fstp st0 ;// in + jnc go4kGLITCH_func_notactive ;// out + + ;// check for first call and init if so init (using slizesize slot) + mov eax, dword [WRK+go4kGLITCH_wrk.slizesize] + and eax, eax + jnz go4kGLITCH_func_process + mov dword [WRK+go4kGLITCH_wrk.index], eax + mov dword [WRK+go4kGLITCH_wrk.store], eax + movzx ebx, byte [VAL-(go4kGLITCH_val.size-go4kGLITCH_val.slicesize)/4] ;// slicesize index + movzx eax, word [_go4k_delay_times+ebx*2] ;// fetch slicesize + push eax + fld1 + fild dword [esp] + fstp dword [WRK+go4kGLITCH_wrk.slizesize] + fstp dword [WRK+go4kGLITCH_wrk.slicepitch] + pop eax +go4kGLITCH_func_process: + ;// fill buffer until full + mov eax, dword [WRK+go4kGLITCH_wrk.store] + cmp eax, MAX_DELAY + jae go4kGLITCH_func_filldone + fst dword [WRK+eax*4+go4kDLL_wrk.buffer] ;// in + inc dword [WRK+go4kGLITCH_wrk.store] +go4kGLITCH_func_filldone: + ;// save input + push eax + fstp dword [esp] ;// - + + ;// read from buffer + push eax + fld dword [WRK+go4kGLITCH_wrk.index] ;// idx + fist dword [esp] + pop eax + fld dword [WRK+eax*4+go4kDLL_wrk.buffer] ;// out idx + fxch ;// idx out + ;// progress readindex with current play speed + fadd dword [WRK+go4kGLITCH_wrk.slicepitch] ;// idx' out + fst dword [WRK+go4kGLITCH_wrk.index] + + ;// check for slice done + fld dword [WRK+go4kGLITCH_wrk.slizesize] ;// size idx' out + fxch ;// idx' size out + fucomip st1 ;// idx' out + fstp st0 ;// out + jc go4kGLITCH_func_process_done + ;// reinit for next loop + xor eax, eax + mov dword [WRK+go4kGLITCH_wrk.index], eax + + fld dword [edx+go4kGLITCH_val.dsize] + fadd dword [edi+go4kGLITCH_wrk2.sm] + fsub dword [c_0_5] + fmul dword [c_0_5] + call _Power@0 + fmul dword [WRK+go4kGLITCH_wrk.slizesize] + fstp dword [WRK+go4kGLITCH_wrk.slizesize] + + fld dword [edx+go4kGLITCH_val.dpitch] + fadd dword [edi+go4kGLITCH_wrk2.pm] + fsub dword [c_0_5] + fmul dword [c_0_5] + call _Power@0 + fmul dword [WRK+go4kGLITCH_wrk.slicepitch] + fstp dword [WRK+go4kGLITCH_wrk.slicepitch] +go4kGLITCH_func_process_done: + + ;// dry wet mix + fld dword [edx+go4kGLITCH_val.dry] ;// dry out + fadd dword [edi+go4kGLITCH_wrk2.dm] ;// dry' out + fld1 ;// 1 dry' out + fsub st1 ;// 1-dry' dry' out + fmulp st2 ;// dry' out' + fmul dword [esp] ;// in' out' + faddp st1, st0 ;// out' + + pop eax + jmp go4kGLITCH_func_leave +go4kGLITCH_func_notactive: + ;// mark as uninitialized again (using slizesize slot) + xor eax,eax + mov dword [WRK+go4kGLITCH_wrk.slizesize], eax +go4kGLITCH_func_leave: + add WRK, go4kDLL_wrk.size ;// go to next delay + mov dword [_go4k_delay_buffer_ofs], WRK ;// store next delay offset + popad + ret +%endif + %ifdef USE_SECTIONS section .g4kcodg code align=1 %else diff --git a/4klang_source/Go4kVSTi/win/4klang.bin b/4klang_source/Go4kVSTi/win/4klang.bin index d5ba738..5e5e1f6 100644 Binary files a/4klang_source/Go4kVSTi/win/4klang.bin and b/4klang_source/Go4kVSTi/win/4klang.bin differ diff --git a/4klang_source/Go4kVSTi/win/4klang.inc b/4klang_source/Go4kVSTi/win/4klang.inc index 0e1e355..1208a3f 100644 --- a/4klang_source/Go4kVSTi/win/4klang.inc +++ b/4klang_source/Go4kVSTi/win/4klang.inc @@ -38,6 +38,7 @@ %define GO4K_USE_GLOBAL_DLL ; // removing this will skip global dll processing %define GO4K_USE_FSTG ; // removing this will skip global store unit %define GO4K_USE_FLD ; // removing this will skip float load unit +%define GO4K_USE_GLITCH ; // removing this will skip GLITCH unit %define GO4K_USE_ENV_CHECK ; // removing this skips checks if processing is needed %define GO4K_USE_ENV_MOD_GM ; // removing this will skip env gain modulation code %define GO4K_USE_ENV_MOD_ADR ; // removing this will skip env attack/decay/release modulation code @@ -475,11 +476,56 @@ struc go4kFLD_wrk .size endstruc %endif +%ifdef GO4K_USE_GLITCH +; //---------------------------------------------------------------------------------------- +; // GLITCH structs +; //---------------------------------------------------------------------------------------- +GO4K_GLITCH_ID equ 12 +%macro GO4K_GLITCH 5 + db %1 + db %2 + db %3 + db %4 + db %5 +%endmacro +%define ACTIVE(val) val +%define SLICEFACTOR(val)val +%define PITCHFACTOR(val)val +%define SLICESIZE(val) val +struc go4kGLITCH_val +;// unit paramters + .active resd 1 + .dry resd 1 + .dsize resd 1 + .dpitch resd 1 + .slicesize resd 1 + .size +endstruc +struc go4kGLITCH_wrk +;// work variables + .index resd 1 + .store resd 1 + .slizesize resd 1 + .slicepitch resd 1 + .unused resd 1 +;// the delay buffer + .buffer resd MAX_DELAY + .size +endstruc +struc go4kGLITCH_wrk2 +;// modulation targets + .am resd 1 + .dm resd 1 + .sm resd 1 + .pm resd 1 + .size +endstruc +%endif %ifdef GO4K_USE_FSTG ; //---------------------------------------------------------------------------------------- ; // FSTG structs ; //---------------------------------------------------------------------------------------- -GO4K_FSTG_ID equ 12 +GO4K_FSTG_ID equ 13 %macro GO4K_FSTG 2 db %1 dw %2 diff --git a/4klang_source/Go4kVSTi/win/Go4kVSTi.rc b/4klang_source/Go4kVSTi/win/Go4kVSTi.rc index 46834d3..cf2d5a2 100644 --- a/4klang_source/Go4kVSTi/win/Go4kVSTi.rc +++ b/4klang_source/Go4kVSTi/win/Go4kVSTi.rc @@ -7,7 +7,9 @@ // // Generated from the TEXTINCLUDE 2 resource. // -#include "afxres.h" +#include "WinResrc.h" + +#define IDC_STATIC -1 ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS @@ -35,7 +37,7 @@ IDR_ASM_RES BINARY "4klang.bin" IDD_GO4KVSTIDIALOG DIALOGEX 0, 0, 594, 341 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_ACCEPTFILES -CAPTION "Alcatraz - 4klang Synth Plugin - Version 3.11" +CAPTION "Alcatraz - 4klang Synth Plugin - Version 3.2.1" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN PUSHBUTTON "Load Patch Data",IDC_LOAD_PATCH,13,13,70,14 @@ -96,6 +98,8 @@ BEGIN COMBOBOX IDC_OBJFORMAT,515,51,66,72,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP LTEXT "Link To",IDC_STATIC,241,47,23,8 COMBOBOX IDC_INSTRUMENTLINK,301,44,85,184,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + CONTROL "Stayalive Noise while Recording",IDC_RECORDBUSYSIGNAL, + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,431,267,64,21 END IDD_VCO DIALOGEX 0, 0, 300, 170 @@ -1265,6 +1269,28 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN END +IDD_GLITCH DIALOGEX 0, 0, 300, 170 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + GROUPBOX "Glitch",IDC_STATIC,0,0,300,170 + CONTROL "",IDC_GLITCH_DRY,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,65,200,15 + CONTROL "",IDC_GLITCH_ACTIVE,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,49,200,15 + LTEXT "Active",IDC_STATIC,4,53,21,8 + LTEXT "Dry",IDC_STATIC,4,68,12,8 + CTEXT " ",IDC_GLITCH_ACTIVE_VAL,242,50,48,12,SS_SUNKEN + CTEXT " ",IDC_GLITCH_DRY_VAL,242,66,48,12,SS_SUNKEN + CONTROL "",IDC_GLITCH_DSIZE,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,97,200,15 + LTEXT "DSize",IDC_STATIC,4,100,18,8 + CTEXT " ",IDC_GLITCH_DSIZE_VAL,242,97,48,12,SS_SUNKEN + CONTROL "",IDC_GLITCH_DPITCH,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,113,200,15 + LTEXT "DPitch",IDC_STATIC,4,117,21,8 + CTEXT " ",IDC_GLITCH_DPITCH_VAL,242,113,48,12,SS_SUNKEN + CONTROL "",IDC_GLITCH_DTIME,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,81,200,15 + LTEXT "Delay",IDC_STATIC,4,85,19,8 + CTEXT " ",IDC_GLITCH_DTIME_VAL,242,81,48,12,SS_SUNKEN +END + ///////////////////////////////////////////////////////////////////////////// // @@ -1290,6 +1316,10 @@ BEGIN BEGIN END + IDD_DLL, DIALOG + BEGIN + END + IDD_DST, DIALOG BEGIN END @@ -1305,6 +1335,10 @@ BEGIN TOPMARGIN, 7 BOTTOMMARGIN, 35 END + + IDD_GLITCH, DIALOG + BEGIN + END END #endif // APSTUDIO_INVOKED @@ -1335,6 +1369,17 @@ BEGIN 0 END + +///////////////////////////////////////////////////////////////////////////// +// +// AFX_DIALOG_LAYOUT +// + +IDD_GO4KVSTIDIALOG AFX_DIALOG_LAYOUT +BEGIN + 0x0000 +END + #endif // German (Germany) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/4klang_source/Go4kVSTi/win/Go4kVSTi.vcxproj b/4klang_source/Go4kVSTi/win/Go4kVSTi.vcxproj index 6fe69f6..b600542 100644 --- a/4klang_source/Go4kVSTi/win/Go4kVSTi.vcxproj +++ b/4klang_source/Go4kVSTi/win/Go4kVSTi.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -14,16 +14,19 @@ 4klang {107757EA-2FE1-4C5E-964F-DE7E482E253F} Go4kVSTi + 8.1 DynamicLibrary false false + v140 DynamicLibrary false + v140 diff --git a/4klang_source/Go4kVSTi/win/Go4kVSTi2.rc b/4klang_source/Go4kVSTi/win/Go4kVSTi2.rc index e8ba6da..669ed91 100644 --- a/4klang_source/Go4kVSTi/win/Go4kVSTi2.rc +++ b/4klang_source/Go4kVSTi/win/Go4kVSTi2.rc @@ -7,7 +7,8 @@ // // Generated from the TEXTINCLUDE 2 resource. // -#include "afxres.h" +#include "WinResrc.h" +#define IDC_STATIC -1 ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS @@ -35,7 +36,7 @@ IDR_ASM_RES BINARY "4klang.bin" IDD_GO4KVSTIDIALOG DIALOGEX 0, 0, 594, 341 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_ACCEPTFILES -CAPTION "Alcatraz - 8klang Synth Plugin (4klang addon) - Version 3.11" +CAPTION "Alcatraz - 8klang Synth Plugin (4klang addon) - Version 3.2.1" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN PUSHBUTTON "Load Patch Data",IDC_LOAD_PATCH,13,13,70,14 @@ -96,6 +97,8 @@ BEGIN COMBOBOX IDC_OBJFORMAT,515,51,66,72,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP LTEXT "Link To",IDC_STATIC,241,47,23,8 COMBOBOX IDC_INSTRUMENTLINK,301,44,85,184,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + CONTROL "Stayalive Noise while Recording",IDC_RECORDBUSYSIGNAL, + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,431,267,64,21 END IDD_VCO DIALOGEX 0, 0, 300, 170 @@ -1265,6 +1268,28 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN END +IDD_GLITCH DIALOGEX 0, 0, 300, 170 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + GROUPBOX "Glitch",IDC_STATIC,0,0,300,170 + CONTROL "",IDC_GLITCH_DRY,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,65,200,15 + CONTROL "",IDC_GLITCH_ACTIVE,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,49,200,15 + LTEXT "Active",IDC_STATIC,4,53,21,8 + LTEXT "Dry",IDC_STATIC,4,68,12,8 + CTEXT " ",IDC_GLITCH_ACTIVE_VAL,242,50,48,12,SS_SUNKEN + CTEXT " ",IDC_GLITCH_DRY_VAL,242,66,48,12,SS_SUNKEN + CONTROL "",IDC_GLITCH_DSIZE,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,97,200,15 + LTEXT "DSize",IDC_STATIC,4,100,18,8 + CTEXT " ",IDC_GLITCH_DSIZE_VAL,242,97,48,12,SS_SUNKEN + CONTROL "",IDC_GLITCH_DPITCH,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,113,200,15 + LTEXT "DPitch",IDC_STATIC,4,117,21,8 + CTEXT " ",IDC_GLITCH_DPITCH_VAL,242,113,48,12,SS_SUNKEN + CONTROL "",IDC_GLITCH_DTIME,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,38,81,200,15 + LTEXT "Delay",IDC_STATIC,4,85,19,8 + CTEXT " ",IDC_GLITCH_DTIME_VAL,242,81,48,12,SS_SUNKEN +END + ///////////////////////////////////////////////////////////////////////////// // @@ -1290,6 +1315,10 @@ BEGIN BEGIN END + IDD_DLL, DIALOG + BEGIN + END + IDD_DST, DIALOG BEGIN END @@ -1305,6 +1334,10 @@ BEGIN TOPMARGIN, 7 BOTTOMMARGIN, 35 END + + IDD_GLITCH, DIALOG + BEGIN + END END #endif // APSTUDIO_INVOKED @@ -1335,6 +1368,17 @@ BEGIN 0 END + +///////////////////////////////////////////////////////////////////////////// +// +// AFX_DIALOG_LAYOUT +// + +IDD_GO4KVSTIDIALOG AFX_DIALOG_LAYOUT +BEGIN + 0 +END + #endif // German (Germany) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/4klang_source/Go4kVSTi/win/Go4kVSTi2.vcxproj b/4klang_source/Go4kVSTi/win/Go4kVSTi2.vcxproj index 2b1a784..cd4a1bb 100644 --- a/4klang_source/Go4kVSTi/win/Go4kVSTi2.vcxproj +++ b/4klang_source/Go4kVSTi/win/Go4kVSTi2.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -14,16 +14,19 @@ 8klang {FA790F08-0B8E-43D9-A4B4-519AB01B820C} Go4kVSTi2 + 8.1 DynamicLibrary false false + v140 DynamicLibrary false + v140 diff --git a/4klang_source/Go4kVSTi/win/resource.h b/4klang_source/Go4kVSTi/win/resource.h index 2791050..4d4083d 100644 --- a/4klang_source/Go4kVSTi/win/resource.h +++ b/4klang_source/Go4kVSTi/win/resource.h @@ -14,6 +14,7 @@ #define IDD_OUT 109 #define IDD_ACC 110 #define IDD_FLD 111 +#define IDD_GLITCH 112 #define IDD_GO4KVSTIDIALOG 115 #define IDD_INSTRUMENT_STACK 120 #define IDD_GLOBAL_STACK 121 @@ -65,6 +66,7 @@ #define IDC_GSTACK_VALID 1041 #define IDC_PATTERN_QUANT 1042 #define IDC_INSTRUMENTLINK 1043 +#define IDC_RECORDBUSYSIGNAL 1044 #define IDC_UNIT_RESET 1050 #define IDC_UNIT_COPY 1051 #define IDC_UNIT_PASTE 1052 @@ -974,14 +976,25 @@ #define IDC_GSTACK__SET32 3982 #define IDC_GSTACK__RESET32 3983 #define IDC_DST_STEREO 5004 +#define IDC_GLITCH_ACTIVE 5050 +#define IDC_GLITCH_ACTIVE_VAL 5051 +#define IDC_GLITCH_DRY 5052 +#define IDC_GLITCH_DRY_VAL 5053 +#define IDC_GLITCH_DSIZE 5054 +#define IDC_GLITCH_DSIZE_VAL 5055 +#define IDC_GLITCH_DPITCH 5056 +#define IDC_GLITCH_DPITCH_VAL 5057 +#define IDC_GLITCH_DTIME 5058 +#define IDC_GLITCH_DTIME_VAL 5059 + // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 124 +#define _APS_NEXT_RESOURCE_VALUE 125 #define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 5005 +#define _APS_NEXT_CONTROL_VALUE 5015 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif