HardwareHeaven.com

HardwareHeaven.com

Looking for the skin chooser?
 
 
  • Home

  • Hardware reviews

  • Articles

  • News

  • Tools

  • Gaming at HardwareHeaven

  • Forums

 

Go Back   HardwareHeaven.com > Forums > Hardware and Related Topics > kX Project Audio Driver Support Forum > Effects and the DSP


Reply
 
Thread Tools
Old May 11, 2011, 04:50 PM   #1
HardwareHeaven Lover
 
Join Date: Mar 2003
Posts: 127
Rep Power: 0
JoshuaChang is on a distinguished road

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;
does this mean: tmp8019 = -1 + sti800c ? for 0x80000000 * 0x80000000 should be 0x7fffffff

2.
Code:
macints      sti800b,  0x0,  sti800b,  0x7fffffff;
the Y operator is 0x7fffffff, with macints instruction, it's real 0x7fffffff and not 1.0 right? then if sti800b>0x0, then the result should always be 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));
what's the algorithm behind it?

someone please help me out~
__________________
JoshuaChang is offline   Reply With Quote


Old May 11, 2011, 07:35 PM   #2
h/h member-shmember
 
Join Date: Dec 2002
Location: Evil Empire
Posts: 2,639
Rep Power: 69
Max M. is just super!Max M. is just super!Max M. is just super!Max M. is just super!Max M. is just super!Max M. is just super!

Ответ: 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.
Max M. is offline   Reply With Quote
Old May 12, 2011, 03:54 AM Threadstarter Thread Starter   #3
HardwareHeaven Lover
 
Join Date: Mar 2003
Posts: 127
Rep Power: 0
JoshuaChang is on a distinguished road

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;
what does the cc_test 0x200 mean? i couldn't found any condition related to this number

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.
JoshuaChang is offline   Reply With Quote
Old May 12, 2011, 07:25 AM   #4
h/h member-shmember
 
Join Date: Dec 2002
Location: Evil Empire
Posts: 2,639
Rep Power: 69
Max M. is just super!Max M. is just super!Max M. is just super!Max M. is just super!Max M. is just super!Max M. is just super!

Ответ: 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.
Max M. is offline   Reply With Quote
Old May 12, 2011, 07:54 AM Threadstarter Thread Starter   #5
HardwareHeaven Lover
 
Join Date: Mar 2003
Posts: 127
Rep Power: 0
JoshuaChang is on a distinguished road

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......
__________________
JoshuaChang is offline   Reply With Quote
Old May 12, 2011, 05:16 PM Threadstarter Thread Starter   #6
HardwareHeaven Lover
 
Join Date: Mar 2003
Posts: 127
Rep Power: 0
JoshuaChang is on a distinguished road

Re: more question about the emu10k instruction

more question about delayline:
Code:
acc3 &rd, delay, &wrt, 0x0;
1.seems &rd/&wrt, the delayline register address has a unit of 0x800 for one sample delay?maybe reflect to 2^32/2M samples?

2.does &rd/&wrt, the delayline register address increment by 0x800 every circle, or they just have the static address value?
__________________
JoshuaChang is offline   Reply With Quote
Old May 12, 2011, 06:55 PM   #7
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 5,563
Rep Power: 62
Russ is just super!Russ is just super!Russ is just super!Russ is just super!Russ is just super!Russ is just super!

Re: more question about the emu10k instruction

Quote:
Originally Posted by JoshuaChang View Post
2.0x80000000-0x1, this should affect borrow bit?
3.0x80000000+0xffffffff, i've got lost......
These 2 are the same thing...
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
Russ is offline   Reply With Quote
Old May 12, 2011, 09:48 PM   #8
HardwareHeaven Addict
 
Join Date: Jan 2008
Location: germany, sb0090
Posts: 259
Rep Power: 0
stylus02 will become famous soon enoughstylus02 will become famous soon enough

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.
__________________
http://kxm.dyndns.org

Last edited by stylus02; May 12, 2011 at 10:34 PM.
stylus02 is offline   Reply With Quote
Old May 12, 2011, 11:02 PM   #9
HardwareHeaven Addict
 
Join Date: Jan 2008
Location: germany, sb0090
Posts: 259
Rep Power: 0
stylus02 will become famous soon enoughstylus02 will become famous soon enough

Re: more question about the emu10k instruction

Quote:
Code:
acc3 &rd, delay, &wrt, 0x0;
i was confused about the adress calculation too some years ago. important is the 11 bit shift of the read adress.

[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?
__________________
http://kxm.dyndns.org

Last edited by stylus02; May 12, 2011 at 11:41 PM.
stylus02 is offline   Reply With Quote
Old May 13, 2011, 02:32 AM   #10
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 5,563
Rep Power: 62
Russ is just super!Russ is just super!Russ is just super!Russ is just super!Russ is just super!Russ is just super!

Re: more question about the emu10k instruction

Quote:
Originally Posted by stylus02 View Post
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?
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).
Russ is offline   Reply With Quote
Old May 13, 2011, 04:05 AM Threadstarter Thread Starter   #11
HardwareHeaven Lover
 
Join Date: Mar 2003
Posts: 127
Rep Power: 0
JoshuaChang is on a distinguished road

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?
__________________
JoshuaChang is offline   Reply With Quote
Old May 13, 2011, 07:03 AM   #12
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 5,563
Rep Power: 62
Russ is just super!Russ is just super!Russ is just super!Russ is just super!Russ is just super!Russ is just super!

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)
You can also see how that 0x800 value is used in "APS Pitch" and "Stereo Chorus" to change the read addresses, etc (using an LFO (or whatever) instead of a slider value).

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.
Russ is offline   Reply With Quote
Old May 13, 2011, 07:21 AM Threadstarter Thread Starter   #13
HardwareHeaven Lover
 
Join Date: Mar 2003
Posts: 127
Rep Power: 0
JoshuaChang is on a distinguished road

Default Post Re: more question about the emu10k instruction

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;
__________________
JoshuaChang is offline   Reply With Quote
Old May 13, 2011, 07:28 AM Threadstarter Thread Starter   #14
HardwareHeaven Lover
 
Join Date: Mar 2003
Posts: 127
Rep Power: 0
JoshuaChang is on a distinguished road

Re: more question about the emu10k instruction

if a line code like this:
Code:
macs          tmp8019,  &itr800f, 0x0, 0x0;
does the value of tmp8019 decrement by 0x800 every circle?
__________________
JoshuaChang is offline   Reply With Quote
Old May 13, 2011, 07:46 AM   #15
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 5,563
Rep Power: 62
Russ is just super!Russ is just super!Russ is just super!Russ is just super!Russ is just super!Russ is just super!

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).
Russ is offline   Reply With Quote
Old May 13, 2011, 07:54 AM   #16
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 5,563
Rep Power: 62
Russ is just super!Russ is just super!Russ is just super!Russ is just super!Russ is just super!Russ is just super!

Re: more question about the emu10k instruction

Quote:
Originally Posted by JoshuaChang View Post
if a line code like this:
Code:
macs          tmp8019,  &itr800f, 0x0, 0x0;
does the value of tmp8019 decrement by 0x800 every circle?
No, it stays constant.

Last edited by Russ; May 13, 2011 at 08:29 PM.
Russ is offline   Reply With Quote
Old May 13, 2011, 10:37 PM   #17
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 5,563
Rep Power: 62
Russ is just super!Russ is just super!Russ is just super!Russ is just super!Russ is just super!Russ is just super!

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
Russ is offline   Reply With Quote
Old May 15, 2011, 06:46 AM Threadstarter Thread Starter   #18
HardwareHeaven Lover
 
Join Date: Mar 2003
Posts: 127
Rep Power: 0
JoshuaChang is on a distinguished road

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...
__________________
JoshuaChang is offline   Reply With Quote
Old May 15, 2011, 09:09 PM   #19
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 5,563
Rep Power: 62
Russ is just super!Russ is just super!Russ is just super!Russ is just super!Russ is just super!Russ is just super!

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.
Russ is offline   Reply With Quote
Old May 16, 2011, 01:21 AM Threadstarter Thread Starter   #20
HardwareHeaven Lover
 
Join Date: Mar 2003
Posts: 127
Rep Power: 0
JoshuaChang is on a distinguished road

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
__________________
JoshuaChang is offline   Reply With Quote
Old May 16, 2011, 02:36 AM   #21
h/h member-shmember
 
Join Date: Dec 2002
Location: Evil Empire
Posts: 2,639
Rep Power: 69
Max M. is just super!Max M. is just super!Max M. is just super!Max M. is just super!Max M. is just super!Max M. is just super!

Ответ: 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.
Max M. is offline   Reply With Quote
Old May 16, 2011, 06:31 AM   #22
HardwareHeaven Extreme Member
 
Join Date: Jan 2005
Posts: 5,563
Rep Power: 62
Russ is just super!Russ is just super!Russ is just super!Russ is just super!Russ is just super!Russ is just super!

Re: more question about the emu10k instruction

Great explanation... Thanks Max
Russ is offline   Reply With Quote
Reply

Thread Tools