/* ************************************************************************************************** * MONOSTEREO_DELAY.ASM * * * * Slapback ('Doubling') Effect (also called Mono Automatic Double Tracking) * * One popular use of the digital delay is to quickly repeat the input signal with a single * * reflection at unity gain. By making the delay an input signal around 15-40 milliseconds, * * the resulting output produces a "slapback/doubling " effect. The slight differences in the * * delay create the effect of the two parts being played in unison. The effect is created by * * adding a delayed signal together with the original, where a single input source is mixed with * * the delay, and the result is sent to both output channels. With short delays, slapback can * * thicken the sound of an instrument or voice when mixed for a mono result, although * * cancellations can occur from comb filtering side effects when the delay is under 10 ms, * * which will result in a hollow, resonant sound. Longer slapback delay effects were commonly * * used in the 1950's/1960's music industry. * * * * * * Mono ADT I/O Equation and Structure: * * y(n) = x(n) - ax(n - D) * * yLeft(n) = yRight(n) = y(n) * * * * x(n) ------------------------------------------|>------>O--------> y(n) * * | 1/2 ^ * * | | * * | _______________ | * * | | | | * * | | | | * * |-------------->| Z^(-D) |------|>--------| * * | | 1/2 * * |_______________| * * * * * * Stereo Automatic Double Tracking (Stereo Doubling) - "Concert Announcer Simulation" * * Automatic Double Tracking, which is used by audio engineers in the music industry to create * * a sense of spaciousness in stereophonic systems. This effect is set up to playback the * * original "dry" signal in one stereo channel and the delayed signal in the other channel. * * This creates the impression of a stereo effect using a single mono source. By making the * * delay an input signal around 15-40 milliseconds, the resulting output produces a * * "stereo doubling" effect. * * * * * * Stereo ADT I/O Equation and Structure: * * yLeft(n) = x(n) * * yRight(n) = x(n - D) * * * * x(n) --------------------------------------------------|>-----------> yLeft(n) * * | 1/2 * * | * * | _______________ * * | | | * * | | | * * |----------->| Z^(-D) |-----------|>-----------> yRight(n) * * | | 1/2 * * |_______________| * * * * * * * * These effects are great for 'spicing' up an instrument or vocal track, such as compensating * * for a singer who is slightly out of key. To truly simulate a doubling effect, some random * * delay line modulation can be added, since 2 voices are never truely in sync with one another. * * * * IRQ1 pushbutton is used to vary the delay length on-the-fly. * * IRQ2 selects between either Slapback or Stereo Doubling effects. * * * !!!pozostawione dla ciekawskich:)))))))! * * *****************************************************************************************************/ /* ADSP-21060 System Register bit definitions */ #include "def21161.h" #define rzad_fir 25 #define krok 0.05 .GLOBAL Init_Delay_Buffer; .GLOBAL process_audio; /* zastosowano bufor "w" majacy na celu gromadzenie probek wejsciowych w nim dokonywany jest proces "opoznienia" sygnalu poprzez regulacje dlugosci bufora kolowego bufor "w" dzieki swojej wielkosci umozliwia zmiany opoznienia sygnalu poprzez stala -> czas_opoznienia <- */ /* ------------- DATA MEMORY FILTER BUFFERS ---------------------------------*/ .section /dm /NO_INIT dm_delay; #define DelayLine 1632 /* Depth, or TD = D/fs = 1680/48000 = 35 msec */ .var w[1000]; /* delay-line buffer, max delay = D */ .VAR linia_wej[rzad_fir+1]; .section /pm pm_data; .VAR wsp_fir[rzad_fir+1]; .VAR wsp_odbicia[rzad_fir]; /* ----------- INTERRUPT/FLAG REVERB FX DEMO CONTROL PARAMETERS ---------*/ .section /dm IRQ_ctl; /* Reverb Control Parameters, these control 'knobs' are used to change the response on-the-fly */ .VAR czas_opoznienia =10 ; /* controls length (L6 register)of predelay buffer */ /* length value always << max buffer length! */ /* ---------------------------------- PROGRAM MEMORY CODE ------------------------------------- */ .section /pm pm_code; Init_Delay_Buffer: b0=linia_wej; l0=@linia_wej; m0=0; m1=1; b8=wsp_odbicia; l8=@wsp_odbicia; b10=wsp_fir; l10=@wsp_fir; m8=0; m9=1; f7=krok; f0=0.0; //zerowanie buforow kolowych lcntr=rzad_fir, do czysc_bufor until lce; dm(i0,m1)=f0, pm(i8,m9)=f0; czysc_bufor: pm(i10,m9)=f0; // dm(i0,m1)=f0, pm(i10,m9)=f0; B6 = w; L6 = @w; /* delay-line buffer pointer and length for ADT Effect */ M6 = 1; //zerowanie lini opozniajacej LCNTR = L6; /* clear delay line buffer 2 to zero */ DO clrDline UNTIL LCE; clrDline: dm(I6, M6) = 0; rts; Init_Delay_Buffer.end: .EXTERN Left_Channel_In1; .EXTERN Left_Channel_Out0; .EXTERN Right_Channel_In1; .EXTERN Right_Channel_Out0; .EXTERN Left_Channel_Out1; .EXTERN Right_Channel_Out1; .EXTERN Left_Channel_Out2; .EXTERN Right_Channel_Out2; /* ///////////////////////////////////////////////////////////////////////////////////////// */ /* Stereo Automatic Double Tracking - ADT Audio Effect using a digital delay-line */ /* Digital Delay Effect to create a stereo field effect */ /* Also called 'Stereo Doubling' */ /* ///////////////////////////////////////////////////////////////////////////////////////// */ process_audio: /* process right channel input only */ /* get input samples from data holders */ r0 = dm(Left_Channel_In1); /* left input sample */ r1 = dm(Left_Channel_In1); /* right input sample */ L6 = dm(czas_opoznienia); /* tap output of circular delay line */ r3 = dm(i6, 0); /* point to d-th tap and put in data register */ /* fetch address with no update */ /* write output samples to AD1836 Multichannel Codec channels */ dm(Left_Channel_Out2) = r0; /* left output sample */ dm(Right_Channel_Out2) = r3; /* right output sample */ /* put input sample into tap-0 of delay line, post-modify address after storage of input */ dm(i6, -1) = r1; /* put value from register r1 into delay line */ /* and decrement address by -1 */ r2=-31; f0 = float r3 by r2;//opoznione f9 = float r1 by r2; //d(n) nie opoznione kratowy_lms_alg: f10=pass f0, f1=dm(i0,m0), f4=pm(i10,m8); //f0= b0(n)=x0(n), f10= f0(n), f1= b0(n-1), f4= g0(n)} f12=f0*f4, dm(i0,m1)=f0, f5=pm(i8,m9); //f12= y0(n)= b0(n)*g0(n), magazynuje b0(n), f5= k1(n)} f13=f1*f5, f6=f9-f12; //f13= b0(n-1)*k1(n), f6= e0(n)} lcntr=rzad_fir, do modyfikuj_wsp until lce; f3=f0*f7, f2=f10-f13, f8=f4; //f2= fm(n), f3= bm-1(n)*krok, f8= gm-1(n)} f13=f3*f6, f3=f10; //f13= krok*bm-1(n)*em-1(n), f3= fm-1(n)} f13=f3*f5, f4=f8+f13, f8=f5; //f4= gm-1(n+1), f13= fm-1(n)*km(n), f8= km(n)} f0=f1-f13, pm(i10,m9)=f4; //f0= bm(n), magazynuje gm-1(n+1)} f10=f0*f3, f9=dm(i0,m0); //f10= bm(n)*fm-1(n), f9= bm(n-1)} f13=f1*f2, dm(i0,m1)=f0, f4=pm(i10,m8); //f13= bm-1(n-1)*fm(n), magazynuje bm(n), f4= gm(n)} f13=f0*f4, f1=f10+f13, f10=f6; //f10= em-1(n)} //f13= bm(n)*gm(n), f1= fm(n)*bm-1(n-1)+bm(n)*fm-1(n)} f12=f12+f13, f5=pm(i8,-1); //f12= y(n) dla m stopnia, f5= km+1(n)} f13=f1*f7, f6=f10-f13, f1=f9; //f6= em(n), f13= krok*f1, f1= bm(n-1)} f13=f1*f5, f8=f8+f13, f10=f2; //f13= bm(n-1)*km+1(n), f8= km(n+1), f10= fm(n)} modyfikuj_wsp: f3= f0*f6, pm(i8,2)=f8; //f3= bm(n)*em(n), magazynuje km(n+1)} f3=f3*f7; //f3= krok*em(n)*bm(n)} f4=f3+f4, f3=pm(i8,-1); //f4= gm(n+1), i8 -> k1(n+1)} pm(i10,m9)=f4; //magazynuje gm(n+1)} /* f0= bm(n)= //blad predykcji w tyl f2= fm(n)= //blad predykcji w przod f12= y(n)= // wyjscie filtru f6= em(n)= // sygnal bledu */ r1 = 31; /* scale the result back up to MSBs */ r12 = fix f12 by r1; /* convert back to fixed point */ r6 = fix f6 by r1; DM(Left_Channel_Out1) = r12; /* send left channel result to AD1836 Left DAC0 */ DM(Right_Channel_Out1) = r6; rts(db); DM(Left_Channel_Out0) = r12; /* send left channel result to AD1836 Left DAC0 */ DM(Right_Channel_Out0) = r6; /* send right channel result to AD1836 Right DAC0 */ process_audio.end: