Jump to content

How to realize a "constant time slide"


TK.
 Share

Recommended Posts

This time I'm asking for help ;-)

I would like to know, how a slide/portamento function could be realized, which has a constant time, independent from the distance between the source and target frequency. At this page http://www.tb-303.org/info/history.asp it is stated, that the TB303 offers this feature, but I've no idea how to implement this properly in software.

The portamento function of MIDIbox SID and FM is realized in the following way: "current_frequency * rate_factor" will be added to the current frequency value on each update cycle, until the target frequency is reached. This works well, but the sweep time between two notes is not constant.

So, what is the trick? Varying the rate depending on the frequency difference? Based on which formula? The frequency curve of the SID is not linear, this propably has to be taken into account... :-/

Best Regards, Thorsten.

Link to comment
Share on other sites

i've just started typing my thoughts on this and then deleted it realizing i was wrong. and i did it 3 times :)

apparently it's not that easy to put it down mathematically. my next go at it:

*a few more lines deleted*

well apparently you'll have to add the frequency difference into the formula. let's see: one octave slide should last the same as two octave slide and 3 oct slide. so one octave slide's f1/f2=2 and two octave's is f1/f2=4 and three octave's f1/f2=8...

for starters i'd just try adding the freq_high/freq_low to your equasion. something like

current_frequency += current_frequency * rate_factor * freq_high/freq_low

am i taking this way too lightly?  :-\

Link to comment
Share on other sites

am i taking this way too lightly?

This isn't so bad and brings some improvement. But what should happen if at the middle between previous and new note you decide to play another note? Let's say, C-1 to C-4 (factor 8 ), and while the frequency is sweeped and has reached the frequency around C-3, D-3 is played. What should happen then? A very long sweep from C-3 to D-3? Or just ignoring this side effect, which wouldn't happen when a slide is realized with analog components?

Do you know, how other synths with a similar slide feature like the TB303 do react under such conditions?

Best Regards, Thorsten.

P.S.: thanks for your answer! At the time I wrote the initial posting, I already thought: if somebody will answer, then propably Kokoon! :-)

Link to comment
Share on other sites

i've no idea how such think works in analogue - it's obviously not a simple slew limiter or a lowpass filter - in order to get constant time it *beeds* to know source and target freq. i think :)

i remember reading a detailed description of tb-303's slide somewhere. i'll see if i can find it.

the example of interrupting the slide that you wrote - shouldn't the last slide from C-3 to D-3 be FASTER than normal in that case? anyway - i'd just store the last frequency in the process of sliding and treat that as the last pressed note before the slide.

no need thanking me - i'm honored i can help you with this  ;)

Link to comment
Share on other sites

the example of interrupting the slide that you wrote - shouldn't the last slide from C-3 to D-3 be FASTER than normal in that case? anyway - i'd just store the last frequency in the process of sliding and treat that as the last pressed note before the slide.

yes, I guess that in reality it would be faster. You are right, by using the old "slide rate factor", which was calculated at the time the slide has started, the effect would be more realistic. Maybe I should try this.

Can this help?

unfortunately not, because the question is, how to transfer a "constant time slide" into the digital world.

Ok, this evening I will try out Kokoon's suggestions

Best Regards, Thorsten.

Link to comment
Share on other sites

yeah that's the page i meant. i found it too - but like TK said, there isn't anything there that helps us with this.

yes, I guess that in reality it would be faster. You are right, by using the old "slide rate factor", which was calculated at the time the slide has started, the effect would be more realistic. Maybe I should try this.

actually no - the "constant slide time" rule would be violated in any case if you won't use the current frequency to calculate the rate modifier. do you know what i mean? each time a slide is started you calculate the "rate modifier" = max(curr_freq, target_freq)/min(curr_freq, target_freq) and use it. you shouldn't get curr_freq from last played note because the current frequency might be different if there's a slide already in progress. do you agree?

oh and that *beeds* up there in my second post should be *needs* :D

Link to comment
Share on other sites

actually no - the "constant slide time" rule would be violated in any case if you won't use the current frequency to calculate the rate modifier. do you know what i mean? each time a slide is started you calculate the "rate modifier" = max(curr_freq, target_freq)/min(curr_freq, target_freq) and use it. you shouldn't get curr_freq from last played note because the current frequency might be different if there's a slide already in progress. do you agree?

I know what you mean, but this is what I already tried months ago, and the effect wasn't really good, because the result is far from the behaviour of the analog circuit, just because the formula is too much simplified (and it *must* be simple, since 16bit calculations are taking many many cycles on the PIC!). However, your post inspirated me to a nice solution, just let me try it out :)

Best Regards, Thorsten.

Link to comment
Share on other sites

And here another typical problem - propably the same one which I noticed last time:

assumed that this formula is taken: current_frequency += current_frequency * rate_factor * freq_high/freq_low

and assumed that we are *not* calculating with floating point values (the PIC is not a DSP...)

then a slide between two octaves looks like this:

[tt]

Current Frequency:  440

Target Frequency:    880

Portamento Rate: 0.0100 * 2.0000 = 0.0200

0.819 mS: 448

1.638 mS: 457

2.458 mS: 466

3.277 mS: 476

4.096 mS: 485

4.915 mS: 495

5.734 mS: 505

6.554 mS: 515

7.373 mS: 525

8.192 mS: 536

9.011 mS: 547

9.830 mS: 558

10.650 mS: 569

11.469 mS: 580

12.288 mS: 592

13.107 mS: 604

13.926 mS: 616

14.746 mS: 628

15.565 mS: 640

16.384 mS: 653

17.203 mS: 666

18.022 mS: 680

18.842 mS: 693

19.661 mS: 707

20.480 mS: 721

21.299 mS: 736

22.118 mS: 751

22.938 mS: 766

23.757 mS: 781

24.576 mS: 796

25.395 mS: 812

26.214 mS: 829

27.034 mS: 845

27.853 mS: 862

28.672 mS: 879

29.491 mS: 880

[/tt]

But a slide over three octaves looks like this:

[tt]

Current Frequency:  440

Target Frequency:  3520

Portamento Rate: 0.0100 * 8.0000 = 0.0800

0.819 mS: 475

1.638 mS: 513

2.458 mS: 554

3.277 mS: 598

4.096 mS: 646

4.915 mS: 698

5.734 mS: 754

6.554 mS: 814

7.373 mS: 879

8.192 mS: 949

9.011 mS: 1025

9.830 mS: 1107

10.650 mS: 1196

11.469 mS: 1292

12.288 mS: 1395

13.107 mS: 1507

13.926 mS: 1628

14.746 mS: 1758

15.565 mS: 1898

16.384 mS: 2050

17.203 mS: 2214

18.022 mS: 2392

18.842 mS: 2583

19.661 mS: 2790

20.480 mS: 3013

21.299 mS: 3254

22.118 mS: 3514

22.938 mS: 3520

[/tt]

And this is a very short slide, the difference will be even more audible on slides around 500 mS and more :-/

Best Regards, Thorsten.

Link to comment
Share on other sites

damn you're right. it doesn't match.  :(

now we can try to patch it up with a constant or something simple like that... but still something will have to be done about interrupted slides.

i'll try to come up with a proper formula just to see how much more complicated it is.

Link to comment
Share on other sites

Currently I'm trying to find a formula which works without division, and which delivers not precise, but adequate results (in analog world nothing is precise anyhow ;-))

This one is promissing:


  current_frq += int((current_frq * porta_rate) >> 16);
  porta_rate += int(((target_frq>>8) * (porta_rate>>8)) >> 8);
[/code]

because it requires only a 16x16 multiplication (like the "normal" portamento function of MBSID), and a 8x8 multiplication (can be done within 1 CPU cylce)

Best Regards, Thorsten.

Link to comment
Share on other sites

Despite of the small error in the formula (results are only correct with a slide from low to high frequency), it's mathematically correct, but the slide doesn't sound that good. I've the impression, that frequency changes must be higher at the beginning...

Best Regards, Thorsten.

Link to comment
Share on other sites

Much better:


  current_frq += int((current_frq * porta_rate) >> 16);
  porta_rate += int(((abs(target_frq-current_frq)>>8) * (porta_rate>>8)) >> 8);
[/code]

Mathematically not correct anymore, but the resulting sound is cool!!! :)

Best Regards, Thorsten.

Link to comment
Share on other sites

Forget the formulas: I just have started Rebirth, and it seems that a "constant time slide" is realized by transposing the starting value into a range which is close to the target note. Is this the typical TB303 slide effect?

Best Regards, Thorsten.

Link to comment
Share on other sites

so - the tables you posted that resulted in time differences (1 octave VS 3 octaves) - is the time difference because of inaccurancies in division (the inaccurancies are accumulative because you're using previous cycle's calculated frequency for the new one) or because of error in formula? i've tried to simulate that series in excel but didn't manage to finish it :) i suck at excel haha. but i'm here at seaside for weekend and i don't have anything else... hmmm i could with javascript...

regarding your last solution - 5 semitones - what if the desired slide is less than 5 semitones?

so you're saying rebirth (and probably tb-303) is doing the same?

anyway - theoretically - is this statement correct - for 3x stronger slide (frequency range 3x larger) you need 3x faster slide? i mean - if the slides were linear (they're exponential) that would be correct... but is it still correct with exponential curves?

you said it would sound better if the slide was faster from the beginning - what if we'd try with linear slide (constant addition per cycle)? have you already tried that?

keep us informed! ;)

Link to comment
Share on other sites

i've tried to simulate that series in excel but didn't manage to finish it

only lamers (and managers ;-)) are using excel.

At the begining I used this short perl program - I made a lot of modifications, which haven't been saved, but I guess that it helps you:


my $porta_rate1 = 0.1;

my $current_frq = 220;
my $target_frq = 2*440;
#my $target_frq = 4*440;
#my $target_frq = 8*440;

my $porta_rate2 = $target_frq / $current_frq;
my $porta_rate = $porta_rate1 * $porta_rate2;

printf "Current Frequency: %5d\n", $current_frq;
printf "Target Frequency:  %5d\n", $target_frq;
printf "Portamento Rate: %5.4f * %5.4f = %5.4f\n", $porta_rate1, $porta_rate2, $porta_rate;

my $step = 0;
while( $current_frq < $target_frq ) {
  ++$step;
  $current_frq += $current_frq * $porta_rate;
  if( $current_frq > $target_frq ) { $current_frq = $target_frq; }
  printf "%6.3f mS: %d\n", 0.8192 * $step, $current_frq;
}
[/code]

regarding your last solution - 5 semitones - what if the desired slide is less than 5 semitones?

then the 5 semitones modification will be skipped.

so you're saying rebirth (and probably tb-303) is doing the same?

it seems, that at least rebirth is doing the same, maybe also because they payed more attention for the sound result, than for accuracy. Not sure, how a real TB303 behaves here.

anyway - theoretically - is this statement correct - for 3x stronger slide (frequency range 3x larger) you need 3x faster slide? i mean - if the slides were linear (they're exponential) that would be correct... but is it still correct with exponential curves?

It should

you said it would sound better if the slide was faster from the beginning - what if we'd try with linear slide (constant addition per cycle)? have you already tried that?

The idea isn't that bad, it would mean, that higher notes are sweeped more slowly than lower notes.

Best Regards, Thorsten.

Link to comment
Share on other sites

Haven't tried a linear slide yet, since I think that it doesn't lead to the desired effect. Guess what happens when the frequency sweeps from a high to low note.

In the meantime I think, that the exponential charging and decharging curve of a capacitor has to be modelled. I did something similar with the envelope curve feature (algorithm found by Jess D. Skov-Nielsen), maybe using the same for portamento will result into the desired effect:

constant_slide.gif

Best Regards, Thorsten.

Link to comment
Share on other sites

Hi.

I've been shy to comment on this thread, 'cause it's a well know fact that I don't code :)

In the meantime I think, that the exponential charging and decharging curve of a capacitor has to be modelled. I did something similar with the envelope curve feature (algorithm found by Jess D. Skov-Nielsen), maybe using the same for portamento will result into the desired effect:

Yup-ah. You'll find ASCIImatics for both linear and exponential slide/portamento here:

http://machines.hyperreal.org/categories/do-it-yourself/schematics/portamento.circuit.2.txt

Isn't this basicly the difference between constant time/rate portamento effect? Should be easy to model this with software.  

[blaablaa]

When this schematic is used with portament on/off switching, it's done by shorting "GLIDE" potentiometer. (Simplified) -> No current flows and cap is not charged, but it follows the voltage closely.

[/blaablaa]

BUT - this weird silvery box with all these strange engineering practices (we so much love) does it differently.

Tony Allgood's 303 clone or any 303 schematic will show you how..

http://www.physicsenterprises.andrews.edu/diy_archive/schematics/oakley/images/tb3030-1.gif

It's a variation of the exponential slide circuit, but this time the cap creating RC time constant is switched - between input and output of the slide buffer opamp. The buffer isn't just a basic voltage follower but - at least in tony's circuit it has gain of 1,0024 ;) not much, but at least 303 freaks think this is one of the quircks that makes it sound like it does. Each time slide is switched on it starts with voltage after the slide buffer and not with the voltage before the buffer: Small blips each time slide goes on.

Bye, Moebius

Link to comment
Share on other sites

Thanks for the input!

To the ASCIImatic: it looks like an envelope follower, and this is propably what I have to do for a more accurate slide/glide/portamento/whatever, regardless if it is linear or exponential.

Should be easy to model this with software.

You are right so long the available resources don't matter.

E.g., the simplest way to create a capacitor charging curve is the use of a precalculated table, and to scale the output values depending on the difference between the starting and end frequency. Problem: 256 16bit entries consume 512 bytes, so much is not free.

Another way: re-using the existing code, which produces a non-linear curve. Problem here: it requires at least 7 bytes per oscillator, makes 21 for all. So many bytes are not free anymore (within the reserved range for SID variables)

The way I will propably go: an optional switch which allows to use ENV2 for portamento. By doing so, the rate as well as the curve is freely controllable, and maybe the release rate allows to add some more analog behaviour (frequency change when cap not completely charged).

Each time slide is switched on it starts with voltage after the slide buffer and not with the voltage before the buffer: Small blips each time slide goes on.

thats an interesting point - maybe it can be realized without much effort by re-using ENV2 (gain is free adjustable)

Let's see...

Best Regards, Thorsten.

Link to comment
Share on other sites

After tinkering with the ENV2 mod, I think that the simplest solution (linear slide, suggested by Kokoon) is sufficient, see following examples:

http://www.ucapps.de/tmp/mbsid_constant_slide3.mp3

* at the beginning a slide with linear curve

* thereafter with "negative curve"

* at the end with "positive curve", which fits best with a cap charging curve

The differences are so small, that it isn't really worth the effort to integrate the ENV2->portamento path into the engine (it consumes some resources...).

I will make this feature selectable with sound engine option #3, so that it's possible to switch between the two different behaviours :)

Best Regards, Thorsten.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

×
×
  • Create New...