Shop OBEX P1 Docs P2 Docs Learn Events
Math help needed — Parallax Forums

Math help needed

hippyhippy Posts: 1,981
edited 2007-11-25 17:48 in Propeller 1
This is probably a no-brainer for an expert, but I've been banging my head on the desk for a long while now and getting nowhere, so any expert help woud be most appreciated.

What are the equations needed to implement Y=F(X,N) so N affects the linearity of Y=X as per the attached image ...
140 x 190 - 2K

Comments

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2007-11-24 19:24
    Do you want a piecewise linear function, as shown, or would you rather have a smooth curve?

    -Phil
  • Fred HawkinsFred Hawkins Posts: 997
    edited 2007-11-24 19:51
    Looks like a scaling problem to me. SideLength=n+x which is equal to SideLength=n+y. So pick a sidelength and subtract either x or y giving n. In any case the intersection point on the diagonal is either x by y, x by x, y by y, or n by n, depending upon which end of the diagonal that you traverse.

    To answer your question y=SideLength-n
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2007-11-24 22:40
    For the piecewise linear case, and without loss of generality (since both x and y can be scaled later), confine x and y to lie between 0 and 1. That way n lies in the same interval. Set

    ····p = n, and
    ····q = 1 - p.

    For x <= p:

    ····y = a·x + b
    ····y(0) = 0 = a·0 + b = b
    , so b = 0.
    ····y(p) = q = a·p, so a = q / p = (1 - p)/p, leaving

    ····y(x) = (1 - p)·x/p, where x <= p.

    For x >= p:

    ····y = c·x + d
    ····y(p) = q
    , so c·p + d = q = 1 - p
    ····y(1) = 1, so c + d = 1
    ····Therefore, c + d - c·p - d = p = c·(1 - p), so c = p/(1 - p).
    ····From c + d = 1, we get p/(1 - p) + d = 1, so d = 1 - p/(1 - p); therefore
    ····y(x) = p·x/(1 - p) + 1 - p/(1 - p), leaving

    ····y(x) = p·(x - 1)/(1 - p) + 1, where x >= p

    -Phil
  • hippyhippy Posts: 1,981
    edited 2007-11-24 23:46
    Thanks Phil. I think that translates into the following code. Seems to work with the test cases I tried ...

    PRI f( x, n ) | maxVal
      maxVal := $7FFF_FFFF
      
      if x < n
        result := ( x * (maxVal-n) ) / n
      else
        if n == maxVal
          result := 0
        else
          result := ( ( x-n ) / (maxVal-n) * n ) + ( maxVal-n )
    
    
    
  • rjo_rjo_ Posts: 1,825
    edited 2007-11-25 04:08
    Hippy,

    I think I understand what you are doing... but I don't know of an application. Can you share a little more? Sounds like an engineering thing to me[noparse]:)[/noparse]

    Rich
  • hippyhippy Posts: 1,981
    edited 2007-11-25 05:27
    This is a part of my Propeller Sound Synthesiser project, which came about in a rather round about way ...

    At the core of each oscillator there's a linear timing ramp repeating 0-full, 0-full ad infinitum which is an index into a wave table and this is used to pull out a sine wave ( probably called phase accumulation, DDS or something like it - I don't know the lingo ). Ramp waveform is just the ramp, square depends on whether the ramp is above or below half way to full.

    To do variable width pulses (PWM) I was comparing the ramp against an adjustable level rather than a fixed half way point. Then I realised that rather than alter that level I could keep it fixed at halfway and adjust the way the ramp actually slopes. A secondary benefit is that changing the ramp also skews the shape of triangle and sine waveforms thus the PWM adjustment also becomes useful as a general purpose wave shape distortion. Bingo.

    A further use is for compressors, expanders, volume normalisation and noise suppression ( the function envelope may need inverting in some cases ). By feeding all waves through the function, quiet noises can be made as loud as louder ones, or lower noises can be attenuated more than louder ones. It's probably not perfect because it alters the wave shape as well as its intensity, but for a simple function it's flexible and comes free with what it was actually needed to do.

    Because it involves some awkward math and I'm writing in Asssembler, running out of cycle time and code space in the cog, I have currently implemented a simpler ramp modifier which adds or subtracts with underflow / overflow capping. That allows the necessary PWM and also gives a fair degree of distortion.

    Hijacking my own thread ... The code's working well at present ...

    6 Oscillators, VLF upwards -

    Sine, Square/Pulse/PWM, Triangle, Ramp, Saw, Curved-Up, Curved-Down, Spike, Noise and Random, and 'Vocal' waveforms. With distortion and overtone generation.

    Waveform synchronisation from self, other oscillator or note trigger.

    Ring modulation from any oscillator, envelope generator or mixer.

    Amplitude modulation from any oscillator, envelope generator or mixer, plus overall volume control.

    No frequency modulation yet.

    8 Envelope Generators -

    Delayed trigger time, attack time, attack level, attack hold time, decay time, decay hold, sustain level, delayed release time, release time, release level, with optional Attack/Release repeat until released. Can be configured from AD, through ADSR to WAHDHSWR.

    3 Output Mixers -

    Sources mixed from any oscillator or other mixer with amplitude control from other oscillators, envelope generators plus output volume control. Panning not implemented yet.

    Serial Control Interface / TV Display -

    Raw binary and terminal command line friendly mode ( not that friendly though ! ).

    TV Display shows debugging information; general overview / timing and parameter / patch settings for oscillators, envelope generators and mixers.


    The core design allows anything to be patched into anything else but that is a big hit on performance. I'm looking at having variable loop timing to balance simple patches with fast execution against slower execution for complex patches.

    It's making some zany noises at present but patching is by editing the source code, easily done but not well documented. As soon as I get a note sequencer written and working I'll release the updated code.
  • deSilvadeSilva Posts: 2,967
    edited 2007-11-25 08:20
    HippY: What is your opionion wrt using floating pint? FLOAT32 needs just one COG.. The time needed (around 10 µs/flop) can possibly be used. A "call" will look like:
    JMPRET #do_flop
    LONG flopcode

    and
    JMPRET #get_flopresult

    with storing and retrieving things into/from HUB in the (short) routines...
    I prsume that COG RAM is the limiting factor; as each FLOP will need 2 to 3 longs...


    BTW: "maxval" is called POSX in SPIN - but no-one can keep this in mind....
  • hippyhippy Posts: 1,981
    edited 2007-11-25 15:56
    I hadn't considered floating point but doubt there's enough processing time for that. I'm currently doing all the processing as listed above in a 125uS loop and am trying to keep in that ballpark.
  • rjo_rjo_ Posts: 1,825
    edited 2007-11-25 17:48
    Hippy,

    I am constantly amazed...

    Thanks,

    Rich
Sign In or Register to comment.