|
|||||||
![]() |
|
|
Thread Tools |
|
|
#1 |
|
HardwareHeaven Lover
Join Date: Mar 2003
Posts: 127
Rep Power: 0 ![]() |
more question about the emu10k instruction
i'm now researching the aps pitch plugin, it has some strange instruction that i can't understand:
1. Code:
macw tmp8019, sti800c, 0x80000000, 0x80000000; 2. Code:
macints sti800b, 0x0, sti800b, 0x7fffffff; 3.the pitch coefficient was calculated by a very complex expression : Code:
x = (double)value; //range is -12.50 to 12.50
x=x/100.0;
y = x;
x=(-3.372957086043240E-09+x*-8.859580403504260E-05)/(1.0+x*(-0.02887715356902830+x*0.0002749755844979194));
set_dsp_register(_PITCH, _dbl_to_dspword(x));
y=-4.002216357671908E-07+y*(-5.641437909059427E-05+ y*(-1.621408704872448E-06+y*(-3.204726841065972E-08+ y*-4.932649619664321E-10)));
set_dsp_register(_PITCH2, _dbl_to_dspword(y));
someone please help me out~
__________________
|
|
|
|
|
|
#2 |
|
h/h member-shmember
Join Date: Dec 2002
Location: Evil Empire
Posts: 2,639
Rep Power: 69 ![]() ![]() ![]() ![]() ![]() ![]() |
Ответ: more question about the emu10k instruction
1. I think yes - it's just -1*-1 (well, this code is produced by the original Emu "algebraic syntax" assembler which may result in quite ornate instructions for relatively trivial operations).
2. Yes, it's basicaly a sort of "sign switch" (i.e. return -1, 0 or 1), (for example it can be used to convert sawtooth LFO wave to square one). 3. Notice that all DLL parts of APS* plugins are complete quesswork (so the code just some approximation of most likely trivial trigonometric formulae used in original Emu plugin). I guess the pitch shift algorithm of this plugin is pretty much similiar to the one you can find here
__________________
Last edited by Max M.; May 11, 2011 at 07:54 PM. |
|
|
|
|
|
|
|
HardwareHeaven Lover
Join Date: Mar 2003
Posts: 127
Rep Power: 0 ![]() |
Re: more question about the emu10k instruction
thanks for the answer and the pdf, it's very useful,
another more question : Code:
skip 0x0, ccr, 0x200, 0x2; edit:have further research the as10k and found some rule(?), the 0x200 maybe the not saturation condition?(0x10<<5??)
__________________
Last edited by JoshuaChang; May 12, 2011 at 04:37 AM. |
|
|
|
|
|
#4 |
|
h/h member-shmember
Join Date: Dec 2002
Location: Evil Empire
Posts: 2,639
Rep Power: 69 ![]() ![]() ![]() ![]() ![]() ![]() |
Ответ: more question about the emu10k instruction
I think yes - 0x200 is the saturation bit in "not frame" (i.e. "not saturation") - but that skip stuff always has been same black magic for me too
![]() The "skip forms" table in as10k1 manual came from the US5930158 patent - and since those patents are known to give some minor disinformation - you never know for sure till you test it with real hardware (though the "Form 1" seems to be correct - at least it works as expected for many programs). btw: 'Skip' instruction : how does this work ?
__________________
Last edited by Max M.; May 12, 2011 at 07:33 AM. |
|
|
|
|
|
|
|
HardwareHeaven Lover
Join Date: Mar 2003
Posts: 127
Rep Power: 0 ![]() |
Re: more question about the emu10k instruction
skip can makes the emu10k do some flow control based on cc_test, the Y operand define the number of instructions to be skiped
i still have no idea when the saturation bit should be set: 1.0x7fffffff+0x1, this is for sure 2.0x80000000-0x1, this should affect borrow bit? 3.0x80000000+0xffffffff, i've got lost......
__________________
|
|
|
|
|
|
|
|
HardwareHeaven Lover
Join Date: Mar 2003
Posts: 127
Rep Power: 0 ![]() |
Re: more question about the emu10k instruction
more question about delayline:
Code:
acc3 &rd, delay, &wrt, 0x0; 2.does &rd/&wrt, the delayline register address increment by 0x800 every circle, or they just have the static address value?
__________________
|
|
|
|
|
|
#7 | |
|
HardwareHeaven Extreme Member
Join Date: Jan 2005
Posts: 5,563
Rep Power: 62 ![]() ![]() ![]() ![]() ![]() ![]() |
Re: more question about the emu10k instruction
Quote:
i.e. -1 - 0.0000000004656612873077392578125 -1 + (-0.0000000004656612873077392578125) Both should result in (negative) saturation (Result is 0x80000000 with the S and M (and N) flags set). I am not completely sure how the borrow or normalize flags are used. As for the delay line, did you read this page?: Emu10k1 Tram Engine Last edited by Russ; May 12, 2011 at 10:27 PM. Reason: clarify |
|
|
|
|
|
|
#8 |
|
HardwareHeaven Addict
Join Date: Jan 2008
Location: germany, sb0090
Posts: 259
Rep Power: 0 ![]() ![]() |
Re: more question about the emu10k instruction
"I guess the pitch shift algorithm of this plugin is pretty much similiar to the one you can find here"
this adsp paper is quite impressive. the programming and accessibility seems simple. Last edited by stylus02; May 12, 2011 at 10:34 PM. |
|
|
|
|
|
#9 | |
|
HardwareHeaven Addict
Join Date: Jan 2008
Location: germany, sb0090
Posts: 259
Rep Power: 0 ![]() ![]() |
Re: more question about the emu10k instruction
Quote:
[read address]=[write address]+[calculated number of delay samples]*0x800 (taken from russ's link to the tram engine) "0x800" = 11 bit "calculated number of delay samples" means the itramsize or xtramsize. i hope i remember right. if you do so, you will see it works. i used this to build a lookup table for the first keyboard unit for kxm. precalcuated "note" values were writen in the delay memory an maped exactly to incoming midi controller values 0-127 via kx control. russ did a better version, without using the delay line as a "memory bank", but allways in dane. later we had the smart c++ solution. btw: i wondered a bit because i expected a bit reduction to 16 bit while writing values in delay ram. can anyone confirm this bit reduction? Last edited by stylus02; May 12, 2011 at 11:41 PM. |
|
|
|
|
|
|
#10 |
|
HardwareHeaven Extreme Member
Join Date: Jan 2005
Posts: 5,563
Rep Power: 62 ![]() ![]() ![]() ![]() ![]() ![]() |
Re: more question about the emu10k instruction
Yes, but IIRC, it is not just a bit reduction, the data is also compressed (so depending on the specific value, you might get more or less than 16 bit accuracy).
|
|
|
|
|
|
|
|
HardwareHeaven Lover
Join Date: Mar 2003
Posts: 127
Rep Power: 0 ![]() |
Re: more question about the emu10k instruction
i've read the tram manual, seems the value in tram address register is static once it is defined(unless modify it manually)? and when i need to access the delayline data, the real delayline address should be tram address register+DBAC?
__________________
|
|
|
|
|
|
#12 |
|
HardwareHeaven Extreme Member
Join Date: Jan 2005
Posts: 5,563
Rep Power: 62 ![]() ![]() ![]() ![]() ![]() ![]() |
Re: more question about the emu10k instruction
To read and write to the delay line, you do not have to deal with any addresses, you just use the variables declared in your code.
You only deal with the addresses if you want to change something dynamically (e.g. move a read pointer in order to change the delay length (maybe based on a slider position, or as a result of some DSP instructions), etc). This is where the 0x800 stuff comes in, and it is done as stated in the manual. e.g. [read address]=[write address]+[calculated number of delay samples]*0x800 or maybe... [read address]=[write address]+[max number of delay samples]*0x800*[slider value] See the "Delay A" plugin for an example. It has a max delay size of 32000 samples for each of it's delay lines. 32000 * 0x800 = 0x3E80000 Note that there is a variable "maxdlysize" with this value. The following code changes the read addresses for each delay line in the plugin: Code:
macs &d1r, &d1, maxdlysize, time1; ; read_addr1 = write_addr1 + (maxdlysize * time1_slider) macs &d2r, &d2, maxdlysize, time2; ; read_addr2 = write_addr2 + (maxdlysize * time2_slider) The DBAC is not typically used with delay lines. As it says in the manual, it is used to find the start of TRAM space or to access TRAM in a non-circular fashion. AFAIK, it is used by the Creative driver to implement AC3 passthrough, but kX does not use TRAM this way. Last edited by Russ; May 13, 2011 at 07:18 AM. |
|
|
|
|
|
|
|
HardwareHeaven Lover
Join Date: Mar 2003
Posts: 127
Rep Power: 0 ![]() |
i can understand the usage of change address in delay A plugin, but i can't understand the usage in aps pitch...
Code:
macs tmp8019, &itr800f, sti800c, sti8005;
macs &itr8011, tmp8019, 0x0, 0x0;
macsn &itr8013, &itr8011, sti8004, 0x80000000;
macintw dyn8008, 0x0, tmp8019, 0x00100000;
macw tmp8019, sti800c, 0x80000000, 0x80000000;
macs tmp8019, &itr800f, tmp8019, sti8005;
macs &itr8015, tmp8019, 0x0, 0x0;
macsn &itr8017, &itr8015, sti8004, 0x80000000;
macintw dyn8009, 0x0, tmp8019, 0x00100000;
__________________
|
|
|
|
|
|
|
|
HardwareHeaven Lover
Join Date: Mar 2003
Posts: 127
Rep Power: 0 ![]() |
Re: more question about the emu10k instruction
if a line code like this:
Code:
macs tmp8019, &itr800f, 0x0, 0x0;
__________________
|
|
|
|
|
|
#15 |
|
HardwareHeaven Extreme Member
Join Date: Jan 2005
Posts: 5,563
Rep Power: 62 ![]() ![]() ![]() ![]() ![]() ![]() |
Re: more question about the emu10k instruction
In APS Pitch, sti8004 = 0x800;
It appears to be calculating it's new read addresses from previous read addresses, instead of the write address (which I guess would work in a similar way). The code is a bit confusing as the variable names are auto-generated, etc, and the algorithm used by the plugin to calculate the coefficients, etc, is not known (and as Max stated, some of the instructions are probably more complicated then is necessary). |
|
|
|
|
|
#16 |
|
HardwareHeaven Extreme Member
Join Date: Jan 2005
Posts: 5,563
Rep Power: 62 ![]() ![]() ![]() ![]() ![]() ![]() |
Re: more question about the emu10k instruction
No, it stays constant.
Last edited by Russ; May 13, 2011 at 08:29 PM. |
|
|
|
|
|
#17 |
|
HardwareHeaven Extreme Member
Join Date: Jan 2005
Posts: 5,563
Rep Power: 62 ![]() ![]() ![]() ![]() ![]() ![]() |
Re: more question about the emu10k instruction
Maybe this is helpful?
APS Pitch with some variable renaming and some quick notes (may not be 100% correct): Code:
itramsize 2048
input in0, in1;
output out0, out1;
control level=1;
static pitch1=0xfffffff9, pitch2=0xfffffca4; -> calculated in C++
static dyn1=0, dyn2=0;
static sti1=0, sti2=1, sti3=-1;
temp t1, t2;
temp t_in0, t_in1;
idelay write w at 0;
idelay read r1 at 0x400; -> 1024
idelay read r2 at 0x400; -> 1024
idelay read r3 at 0x401; -> 1025
idelay read r4 at 0x400; -> 1024
idelay read r5 at 0x401; -> 1025
; Code
macs t_in0, in0, 0, 0; -> buffer input 0
macs t_in1, in1, 0, 0; -> buffer input 1
macs 0, 0, t_in0, 0.707; -> see below
macs w, accum, t_in1, 0.707; -> mono mix at half power and write to tram
macwn sti3, sti3, pitch2, -1; -> sti3 (LFO?) = sti3 + pitch2 *** (wraps around)
skip 0, ccr, 0x200, 0x2; -> if (S == 1)
macs sti1, 0, 0, 0; -> sti1 = 0
macints sti2, 0x0, sti2, 0x7fffffff; -> sti2 = -1 or 0 or 1
macs sti1, sti1, pitch1, sti2; -> sti1 = sti1 + (pitch1 * sti2) *** (crossfade coef)
macsn sti2, sti2, pitch1, sti1; -> sti2 = sti2 - (pitch1 * sti1) *** (crossfade coef)
interp t1, r2, dyn1, r3; -> interpolate between r2 and r3
interp dyn1, r4, dyn2, r5; -> interpolate between r4 and r5
macs 0, 0, t1, sti1; -> see below
macs t1, accum, dyn1, sti2; -> t1 = (t1 * sti1) + (dyn1 * sti2) *** (crossfading)
interp out0, t_in0, level, t1; -> wet/dry mix
interp out1, t_in1, level, t1; -> wet/dry mix
macs t1, &r1, sti3, 0x1ff800; -> 0x1ff800 = 1023 samples * 0x800
macs &r2, t1, 0, 0; -> &r2 is moved fractional amount from &r1
macsn &r3, &r2, 0x800, -1; -> move &r3 1 sample location after &r2
macintw dyn1, 0, t1, 0x100000; -> see Max's reply (below)
macw t1, sti3, -1, -1; -> t1 = sti3 + 1 *** (wraps around)
macs t1, &r1, t1, 0x1ff800; -> 0x1ff800 = 1023 samples * 0x800
macs &r4, t1, 0, 0; -> &r4 is moved fractional amount from &r1 (opposite direction of &r2)
macsn &r5, &r4, 0x800, -1; -> move &r5 1 sample location after &r4
macintw dyn2, 0, t1, 0x100000; -> see Max's reply (below)
end
Last edited by Russ; May 16, 2011 at 07:40 AM. Reason: some corrections |
|
|
|
|
|
|
|
HardwareHeaven Lover
Join Date: Mar 2003
Posts: 127
Rep Power: 0 ![]() |
Re: more question about the emu10k instruction
big thanks, Russ
i've tried to translate pitch fx to c language but failed, although it can shift tones, it produce more noise than the original one, maybe the plugin use the "fractional" delay mentioned in as10k1 manual...
__________________
|
|
|
|
|
|
#19 |
|
HardwareHeaven Extreme Member
Join Date: Jan 2005
Posts: 5,563
Rep Power: 62 ![]() ![]() ![]() ![]() ![]() ![]() |
Re: more question about the emu10k instruction
I am not completely sure what the purpose of the macintw instructions are in the code... The note I made there was just something I noticed but may not be relevant... It seems to be doing 20 bit left shift(?) (of a value ranging from 0 to 0x1ff7ff (0 to (+/-)1022 samples * 0x800)), and the result seems to be used for interpolation between 2 samples (I wrote crossfade there, but I think that is probably doing interpolation between 2 contiguous samples(?), and the instructions immediately above/below that are doing crossfading).
@Max M. Can you explain those instructions? It seems to be same code you wrote here: MACW wraparound ...But, I do not completely follow how it works. Can you give a few more details (e.g. what is the significance of the 0x100000, and why macintw?)? Code:
... ; calculate an interpolation coeffs for mixing taps... ; (or, in other words, 'fractional part of new address') ; (should be done one sample later, after writing t1/t2 to address regs) macintw t1, 0, t1, 0x100000 macintw t2, 0, t2, 0x100000 ; interpolate between taps and output (e.g. 'smoothing') interp out1, d11, t1, d12; interp out2, d21, t2, d22; ... Last edited by Russ; May 15, 2011 at 10:07 PM. |
|
|
|
|
|
|
|
HardwareHeaven Lover
Join Date: Mar 2003
Posts: 127
Rep Power: 0 ![]() |
Re: more question about the emu10k instruction
i have tested macintw R, 0x0, X, 0x100000,
seems it looks like this: R = X << 20; if(R<0) R= (~R+1)|0x80000000
__________________
|
|
|
|
|
|
#21 |
|
h/h member-shmember
Join Date: Dec 2002
Location: Evil Empire
Posts: 2,639
Rep Power: 69 ![]() ![]() ![]() ![]() ![]() ![]() |
Ответ: more question about the emu10k instruction
This is basicaly a "fractional delay line". The macintw stuff "extracts" fractional part of delay time value (which is in "TRAM scale" i.e: 1 sample = 0x800) and scales it to "normal" 32-bit fixed-point value (1 sample = unsigned(0x80000000)) to be used as an interpolation coefficient.
For example if delay time is 13.25 samples (TRAM address: 13.25 * 0x800 = 0x6a00) we take two delay outputs at 13 and 14 sample times and mix them as: virtual_delay[13.25] = delay[13] * (1 - 0.25) + delay[14] * 0.25; So it's macintw that converts 0x6a00 to 0.25 (0x20000000) and 0x100000 multiplier there is just "unsigned(0x80000000) / 0x800". edit: if you prefer shifts you can think of macintw R, 0, X, 0x100000 as R = ((X << 31) >> 11) & 0x7fffffff; // assuming positive values
__________________
Last edited by Max M.; May 16, 2011 at 03:16 AM. |
|
|
|
|
|
#22 |
|
HardwareHeaven Extreme Member
Join Date: Jan 2005
Posts: 5,563
Rep Power: 62 ![]() ![]() ![]() ![]() ![]() ![]() |
Re: more question about the emu10k instruction
Great explanation... Thanks Max
|
|
|
|
![]() |
| Thread Tools | |
|
|