Transfer function?

Discussion in 'Effects and the DSP' started by Nappylady, May 19, 2005.

  1. Nappylady

    Nappylady New Member

    Joined:
    Jun 26, 2003
    Messages:
    257
    Likes Received:
    0
    Trophy Points:
    0
    Hi there.

    My experience with kX DSP involves pasting code snippets from this forum into the Dane editor and saving it and using it. I really know nothing about DSP coding myself. But, I want to know if something can be done. (And, of course, can someone code it for me! :D )

    If my sound were normalized to within (-1, 1), I'd like a function that, when given a sample, returns sin(sample * pi/2). I believe this would give a specific soft clip and limit sound, and could be useful.

    Anyone help? :) Thanks.
     
  2. Tiger M

    Tiger M kX user

    Joined:
    Apr 14, 2004
    Messages:
    851
    Likes Received:
    0
    Trophy Points:
    0
    This gives you virtually the same result((the function graph is identical):

    2*x*(1-abs(x)*0.5)

    If you want further compression remove the 2.
     
  3. Nappylady

    Nappylady New Member

    Joined:
    Jun 26, 2003
    Messages:
    257
    Likes Received:
    0
    Trophy Points:
    0
    Are you sure about that?

    (maybe abs means something different to you... abs to me means absolute value.)

    Edit: I plugged it into my graphing calculator... by golly, it is the same!

    So... How do I code this into a kX DSP plugin? Assuming I know nothing about DSP programming?
     
  4. Tiger M

    Tiger M kX user

    Joined:
    Apr 14, 2004
    Messages:
    851
    Likes Received:
    0
    Trophy Points:
    0
    You should trust me in the future;)

    Code:
    input in
    output out
    control level=1, compress=0.5
    temp tmp, tmp2
    
    ;level
    macs tmp, 0, in, level
    ;abs(in)
    tstneg tmp2, tmp, tmp, 0
    ;compress should be from 0 to 0.5, should not exceed 0.5
    macs tmp2, 0, tmp2, compress
    interp out, tmp, tmp2, 0
    end
    
    This is not the original formula, but: x*(1-abs(x)*0.5), since the original formula is actually an expander. If you still want it you should not tweak compress, but make it constant 0.5 and then the code will be:


    Code:
    input in
    output out
    control level=1
    temp tmp, tmp2
    
    ;level
    macs tmp, 0, in, level
    ;abs(in)
    tstneg tmp2, tmp, tmp, 0
    macs tmp2, 0, tmp2, 0.5
    interp tmp, tmp, tmp2, 0
    macints out, 0, tmp, 2
    end
    
    Mistakes in the code are possible, report if something doesn't work so I could fix it;)
     
  5. Nappylady

    Nappylady New Member

    Joined:
    Jun 26, 2003
    Messages:
    257
    Likes Received:
    0
    Trophy Points:
    0
    I pasted that code into a new kX plugin and saved it, and when I tried to register it, I got an error that it's an "invalid plugin library". What now?
     
  6. Russ

    Russ Well-Known Member

    Joined:
    Jan 17, 2005
    Messages:
    5,722
    Likes Received:
    13
    Trophy Points:
    48
    Make sure there is a new line after 'end'.
     
  7. Tiger M

    Tiger M kX user

    Joined:
    Apr 14, 2004
    Messages:
    851
    Likes Received:
    0
    Trophy Points:
    0
    It works, try again.
     
  8. radiocolonel.it

    radiocolonel.it New Member

    Joined:
    Jan 16, 2005
    Messages:
    192
    Likes Received:
    0
    Trophy Points:
    0
    ... i tried it... awesome... there is so much to learn from you Martin!:duh:
    Why do you say to set compress not higher than 0.5, what should happen?
    ... maybe i got: if compress>0.5 the approximation of the sin.. function is not good anymore?
     
    Last edited: May 20, 2005
  9. Nappylady

    Nappylady New Member

    Joined:
    Jun 26, 2003
    Messages:
    257
    Likes Received:
    0
    Trophy Points:
    0
    Okay, I got it to work, and yes, it was because there wasn't a blank line after end. :rolleyes:

    I tried it, and by my tests, it adds 6dB to the output, but the transfer function is still linear. If you take the 2 from the macints instruction and replace it with a 1, the output of the function is identical to the input.

    I trace through your instructions, and if there's a problem, it seems like it would be with interp. I read your beginners' guide to DSP programming for kX, and by what you have written there, your code is correct... but it still isn't doing what it should be doing.

    Any ideas?
     
  10. Tiger M

    Tiger M kX user

    Joined:
    Apr 14, 2004
    Messages:
    851
    Likes Received:
    0
    Trophy Points:
    0
    Simply said: if you set 'compress' over 0.5, input values over 0.5 will become less than 0.5 and values smaller than -0.5 will become bigger than -0.5 (take a look at the function plot). So actually values which were greater before the signal is passed trough the plugin will become smaller than values which are in reality smaller.

    The implementation is correct. I am not responsible for how the actual formula behaves. Don't forget that with the expander variant you should let 0.5 remain fixed, if you set it below 0.5 you will get clipping.
     
    Last edited: May 20, 2005
  11. radiocolonel.it

    radiocolonel.it New Member

    Joined:
    Jan 16, 2005
    Messages:
    192
    Likes Received:
    0
    Trophy Points:
    0
    ... yeah, Martin is right! The formula is well implemented, i tried different setting and i drawed yhe function to understand it better, anyway i have that 6dB increase (exactly i get 4.5dB increase). We'll see, i'll make some tries, if i get some nice result i'll post the code here. :)
     
  12. Nappylady

    Nappylady New Member

    Joined:
    Jun 26, 2003
    Messages:
    257
    Likes Received:
    0
    Trophy Points:
    0
    http://www.naptastic.com/function.jpg

    This image shows direct recording, by Goldwave, of our expander plugin. On the left is the original sound I played. This played out in stereo from FXbus into (on the left) the expander plugin, with the volume at 50%, then into WinMM recording, and (on the right) straight into WinMM recording. The result was recorded and shown on the right-hand side of this picture; the left (wet) channel on top in green, and right (dry) channel on the bottom in red.

    You can see that, because of the lowered volume setting, the wet signal is a little bit quieter than the right signal, but other than that, it is unchanged. (If the volume is set at 100%, then the signal clips heavily. I have not made a screenshot of that.)

    I read your code, and did the math, and you are right--it *should* do the exact thing I predicted. But it isn't. The transfer function is linear.

    It seems like the interp function is not being processed correctly. I don't know why. I don't know anything about DSP programming except what I read on your website. (I think it was your website anyway.) If interp works the way your website says it does, then this program will work the way it's supposed to... but it isn't. Any ideas?
     
  13. Tiger M

    Tiger M kX user

    Joined:
    Apr 14, 2004
    Messages:
    851
    Likes Received:
    0
    Trophy Points:
    0
    Again, the implementation is correct. I don't know which version are you using the first I posted (pseudo compressor) or the second (pseudo expander). I have tested both just to make shure and they both work. Do not make any modifications if you don't know nothing about dsp.

    To test them, pass a 1 constant trough the input of the "compressor" (leave the 'cpmressor' value to 0.5) the output will be 0.5, meaning that the value of 1 is comressed to 0.5 and it is working.

    Pass a 0.5 constant to the input of the "expander". The output value will be 0.75, meaning that the value of 0.5 has expanded to 0.75 and it works.

    It works dude, perhaps you should start learning dsp.
     
  14. radiocolonel.it

    radiocolonel.it New Member

    Joined:
    Jan 16, 2005
    Messages:
    192
    Likes Received:
    0
    Trophy Points:
    0
    ... Hi, guys! I made some tries and everything works! Nappylady, here there the two plots:

    ---> compressor

    ---> expander

    actually i'm using this: 2*x*(1-abs(x)*0.5)
    i set the values that Martin suggested not to touch as static registers, so there are no controls, there is no need. Thanks again Martin!
     
    Last edited: May 21, 2005
  15. radiocolonel.it

    radiocolonel.it New Member

    Joined:
    Jan 16, 2005
    Messages:
    192
    Likes Received:
    0
    Trophy Points:
    0
    ... hi, Martin, may i ask u some? Is there any way to improve- develop this plugin?
    It would be cool making it more effective and flexible! Let me know!
     
  16. Nappylady

    Nappylady New Member

    Joined:
    Jun 26, 2003
    Messages:
    257
    Likes Received:
    0
    Trophy Points:
    0
    Okay, I fixed it!

    http://www.naptastic.com/function2.jpg

    On the left is the sound I played. On the bottom-right is the sound recorded straight from FXbus -> WinMM recording. On the top-right is the same signal, passed through my expander before being recorded. You can see that the transfer function actually looks like I intended it to. :D

    Here is the code for the stereo version of the plugin:

    Code:
     
    ; Registers
     input lin, rin;
     output lout, rout;
     temp tmp, tmp2
    ; Code
      macs   tmp,  0x0,  lin,  0x7fffffff;
      tstneg   tmp2,  tmp,  tmp,  0x0;
      macsn   tmp2,  0x20000000,  tmp2,  0x40000000;
      macs   tmp2,  0x0,  tmp2,  tmp;
      macints   lout,  0x0,  tmp2,  0x10;
      macs   tmp,  0x0,  rin,  0x7fffffff;
      tstneg   tmp2,  tmp,  tmp,  0x0;
      macsn   tmp2,  0x20000000,  tmp2,  0x40000000;
      macs   tmp2,  0x0,  tmp2,  tmp;
      macints   rout,  0x0,  tmp2,  0x10;
    end
    This does *not* have gain control on it. It provides a healthy +12dB boost to any signal at a low level. As the level increases, it starts to sound warm, then a little dirty, then a little harsh, and then it simply sounds like you have it up too loud. It's really quite a bit like working with analog tape.

    The gain is +12dB, and the plugin allows its output to reach +6dB on the peak meter... so perhaps a gain control would be a good idea, if you are using ProFX sources, or something really hot like that. Overall, it removes 6dB of dynamic range from the signal, which is nice if you are working with a vocalist who is inconsistent with her microphone.

    Coupling this plugin with a slower compressor is highly recommended.

    Thanks, everyone, for your help, and enjoy the plugin!
     
  17. Tiger M

    Tiger M kX user

    Joined:
    Apr 14, 2004
    Messages:
    851
    Likes Received:
    0
    Trophy Points:
    0
    Btw, this implementation is very clumsy, but if it works for you it's OK;)

    I now figured out why the implementation I proposed does not work for you. I always forget that when the signal gets into the dsp it is divided by 4 and when it leaves it it is multiplied by 4 (open the code of k2lt and you'll see what I mean). I always use dsp internal signals to test stuff. You use an external signal and when it enters the dsp it ends up being not from -1 to 1, but from -0.25 to 0.25 and the above formula starts to compress or expand somewhere above 0.5, so your signal never gets to that point and remains unchainged. Here's what you can do to test: compile my implementation, before the signal enters the plugin add a 'x4' plugin and after it leaves add a 'div4', then test.

    radiocolonel.it: you could easily add threshold control with 'limit' and 'limitn' instructions. Subsequently you could add attack and release times.
     
  18. radiocolonel.it

    radiocolonel.it New Member

    Joined:
    Jan 16, 2005
    Messages:
    192
    Likes Received:
    0
    Trophy Points:
    0
    Thanks a lot Martin! i knew there was something strange... :w00t: i'll try to follow your tips, so i hope to come up with some useful stuff! Your help is always essential, Martin, thanks again!
     
  19. radiocolonel.it

    radiocolonel.it New Member

    Joined:
    Jan 16, 2005
    Messages:
    192
    Likes Received:
    0
    Trophy Points:
    0
    ... Hi Martin! This is the new code with the improvements u told me!
    This time it seems to work properly as u described it. This is the code, please check if there is some wrong and test it!
    Martin please help me with adding a threshold, i tried but i came up with crop, what i was doing was too much incorrect i guess, can you make me an example?
    As always.. THANKS a LOT!

    code:

    input inl, inr
    output outl, outr
    static tmpl, tmpr, tl, tr, out_tl, out_tr

    ;in level
    macints tmpl, 0, inl, 0x4
    macints tmpr, 0, inr, 0x4
    ;abs(in)
    tstneg tl, tmpl, tmpl, 0
    tstneg tr, tmpr, tmpr, 0
    ;abs(in)*0.5
    macs tl, 0, tl, 0.5
    macs tr, 0, tr, 0.5
    ;(in)*(1-abs(in)*0.5)
    interp tmpl, tmpl, tl, 0
    interp tmpr, tmpr, tr, 0
    ; 2*
    macints out_tl, 0, tmpl, 0x2
    macints out_tr, 0, tmpr, 0x2
    ;out level
    macs outl, 0, out_tl, 0.25
    macs outr, 0, out_tr, 0.25

    end
     
    Last edited: May 25, 2005
  20. Tiger M

    Tiger M kX user

    Joined:
    Apr 14, 2004
    Messages:
    851
    Likes Received:
    0
    Trophy Points:
    0
    As I understand this should be the expander version, right? If it works than everything is OK, it is far from optimized but 2-3 registers don't matter. I made a few tests and found that this thing compresses/expands much better and smoother than the available kX compressors/expanders, it's only problem is that it could not be tweaked like a standart compressor, but who cares;).

    You could add a kind of threshold with the 'limitn' instruction, something like this:

    EDIT:code removed

    You should adapt this to your code.
     
    Last edited: May 26, 2005

Share This Page

visited