Log inRegister an accountBrowse CSDbHelp & documentationFacts & StatisticsThe forumsAvailable RSS-feeds on CSDbSupport CSDb Commodore 64 Scene Database
You are not logged in - nap
CSDb User Forums


Forums > C64 Coding > SID Envelope delay question
2020-01-31 08:42
Mr. Mouse

Registered: Dec 2001
Posts: 235
SID Envelope delay question

Hi folks, I've a question.
While studying the information on the ADSR circuitry through various in-depth sites and DIEs I thought I had pretty much nailed the details.
Yet, I still come across this typical behaviour that I couldn't find explained anywhere in detail, or I'm just too stupid to see.
So let's do this with a simple example that shows what I mean.
On a PAL machine, I change the gate on/off bit every other frame. I set ADSR to F00F.

Frame 1: Gate on
Frame 2: Do nothing
Frame 3: Gate off
Frame 4: Do nothing
REPEAT.

So technically, each frame would take ~20 ms, so the gate on/off frequency would be ~40 ms, ~80 ms for full cycle.

With and Attack rate of F and a Release rate of F, both rate periods for those will be 31251 cycles, or 31,251 ms. Now I know the Attack rate simply makes the Envelope counter go up in linear steps, while the Release rate will implement on top of the rate period the rate counter period delays at fixed envelope counter numbers to approximate an exponential decay.
If I would do the math, and taking into account the ADSR bug, by looping when Attack or Release is set at a value below the current rate counter, the program would simply be silent, with Envelope counter just going up to max 3 or 4, and then go down again, and just fluctuate around those numbers a bit. Attack cycle would start, push it up, but release cycle would push it down again.
This is not what happens on a real C64. On a real C64 the Release part is somehow delayed, giving more time to the Attack cycle, causing the sound amplitude to slowly go up.

I tried looking at the envelope code from Resid, and run that, but also that doesn't show that behaviour. It remains silent. For that code I run the Clock() function continously and change the gate every 40.000 ticks.

What am I missing? I think the behaviour has been reasonably implemented in for example Goattracker (that uses Resid as far as I know) and also Sidplay.
Is it still simply the ADSR bug? From what I can see, the behaviour is overall reproducible, though sometimes it may take a little bit longer before the Attack cycle wins it from the Release cycle and the amplitude goes up. That of course being influenced by the current state of the rate counter when the program starts.

I feel it may be obvious, but perhaps I've invested too much time that I cannot see what is right before me.
2020-01-31 09:23
ChristopherJam

Registered: Aug 2004
Posts: 1409
You're seeing the fake exponential decay at work. There's a separate counter that's incremented each rate counter reset, and reset whenever it hits the exponential_counter_period, or also whenever the generator re-enters the attack state. The envelope level only decreases in Decay or Release when that auxiliary counter resets.

Given you're getting at most two rate counter resets in the decay state, the envelope level won't decrease at all until the ECP drops to 2, which happens when the envelope level reaches 0x5d. Even then, the envelope will still continue to rise on average, as it's going to be skipping every second decrement.

Check out set_exponential_counter() in the ReSID sources, and also the line that references exponential_counter_period in clock()
2020-01-31 09:47
Mr. Mouse

Registered: Dec 2001
Posts: 235
Thanks. But I still don't see it.
In that code, upon reset the exponential counter period is set to 1, and the exponential counter = set to 0 .

Now, when we run EnvelopeGenerator::clock() we see the following:

if (state == ATTACK || ++exponential_counter == exponential_counter_period)
{
exponential_counter = 0;
etc.
}

Yes, attack would reset the counter, but we would also go on if ++exponential counter = exponential_counter_period.
The expression would be true upon reset, since 0+1 = 1.
Doesn't that mean Release would still be triggered at the start? It is the Envelope counter that determines the exponential_counter_period later in the function. Since the Envelope counter is 0 at the start, the exponential_counter_period would be set to 1 again, and the next Clock Release would still be triggered. Wouldn't the exponential_counter_period only change to 30 when the envelope counter reaches 6?
2020-01-31 11:02
Laurent

Registered: Apr 2004
Posts: 40
so you are not changing ADSR value F00F at any point ? only gate ? What do you mean by "by looping when Attack or Release is set at a value below the current rate counter" ? It is not very clear which sequence of values you are passing to the SID, and at which cycles.

Maybe it's due to the initial state of the SID counters when you start your program.
The exponential counter period should start with 1 and stay like this at least during the first loops since you are not attacking long enough for envelope counter to reach 6.

Perhaps you are experiencing the effect of an unknown/uncontrolled initial value of the rate counter 0-32767 that could in average "favor" attack over release, enough for envelope counter to finally reach 6 and suddenly make the release appear almost stalled since it will now take 30*31251 cycles for envelope counter to decay by one ?
2020-01-31 11:11
ChristopherJam

Registered: Aug 2004
Posts: 1409
Quoting Mr. Mouse
In that code, upon reset the exponential counter period is set to 1, and the exponential counter = set to 0.


Oh that's interesting. I wonder if that reset behaviour has been tested on real hardware, or if it was just an arbitrary sane value selected by the implementors?

I'd ordinarily expect the ECP to be 30 for a voice that's currently quiet, as it would have fallen past level 6 at the end of a prior note.
2020-01-31 12:38
Mixer

Registered: Apr 2008
Posts: 452
Ideas: Consider doing the hard restart or getting the sid envelope counter to known state(LFT method) before starting the on/off sequence to see if that is the cause. Also, dumping the data from $d41c and making a graph might help everyone to understand what is happening.
2020-01-31 17:48
Mr. Mouse

Registered: Dec 2001
Posts: 235
Okay, I output ENV3 every frame and this is the chart that comes with it.



Before the run, I reset the SID by writing 0's to the registers, then setting gate on, wait 60 ms, close gate, 60 ms, in order to make sure the release cycle is 0 and hold-zero is true (which, as I read, can only be reset by starting an Attack cycle).

The arrows in the chart show the envelope rate where the exponential counter period should change. Attack goes up from env=0. In the code, when env = 0, the expcntperiod should be set to 1. If attack set the expcounter to 0, the release should trigger the code as mentioned above and decrease env. Theoretically, env should not increase at all, because the attack rate = release rate = 31251.
Yet it does.
When env hits 6, the increase is steeper, probably because the expcntperiod is now 30 (so basically no release, according to the code).
Then env hits 14, expcntperiod should turn to 16.
Etc.

Geir just reached out to me as I wrote this just now, and he says the folling: the exponential counter does not reset during attack.
2020-02-04 09:28
Mr. Mouse

Registered: Dec 2001
Posts: 235
Well, I still don't get what is happening exactly.

For example, at env =6 , exp-period = 30. This would amount to 30 x 31,251 ms before a release (value 0xf) would kick in. In the graph this is ok, since attack rises with no apparent delay from that point onwards.

In the beginning however (between env = 0 and 6), it looks like exp-period =1, since release is working to counter the attack.

It isn't until env =93, when exp-period should be set to 2 when release is working again to counter the rise in attack.

What strikes me from the graph is the "background rhythm" of release being active to counter the rise in env. The zig-zag in the curve is indicative of this. This is quite clear from env=93 upwards, but you can also see this in the earlier time frame, but less obvious.

The period of this "background rhythm" is around 64 frames on average, according to my rough calculation. 64 frames of 20 ms (PAL 50 Hz) = around 1280 ms, or 1,28 seconds. The rise in attack from env=93 onwards is slow, fast, slow, fast etc, as you can see. Please not that the fast period there is exactly as fast as the time from env 6 to env 14, when exp-period would be set to 30 (basically no release possible in this set up).

Now why would there be a "cycle" of around 1280 ms of release (with exp-period of 2) being active, and then deactive (as if exp-period was set to 30) alternating?

What is causing this? I simply cannot explain this from any code or DIE analysis I have seen. But I might need to grow a brain.

Is it a sync between rate counter, exp counter and the gate on/off sequence every other frame? It can't be the exp counter, I think, since the "rhythm" is seen more or less the whole time.
2020-02-04 10:11
ChristopherJam

Registered: Aug 2004
Posts: 1409
Hi Mr. Mouse.

I've not gotten round to looking closely at the other details yet (and I really need to get some real hardware working again so I can test Geir's assertion about the exponential counter), but the oscillation at least makes sense to me.

You're seeing the rate counter underflows drift in and out of phase with your raster interrupts. Sometimes it underflows twice, sometimes once. Every third frame the first underflow happens (31251*2-19656*3)=3534 cycles later into the frame,

Try the following python snippet:
cycles_per_frame = 19656
rate_period = 31251

rc=0
for frame in range(40):

    gate_on_ticks = 0
    for i in range(cycles_per_frame*2):
        rc+=1
        if rc==rate_period:
            rc=0
            gate_on_ticks+=1

    gate_off_ticks = 0
    for i in range(cycles_per_frame*2):
        rc+=1
        if rc==rate_period:
            rc=0
            gate_off_ticks+=1

    print("frame {:3d}: {} attack ticks,  {} decay ticks".format (frame*4, gate_on_ticks, gate_off_ticks))
2020-02-04 11:37
ChristopherJam

Registered: Aug 2004
Posts: 1409
Or alternately, this might be easier to follow.

Graph shows value of rate counter over time, colour indicates whether gate is on or off.

Time period selected to show the transition from
- every second gate-on period contains two rc-resets (yellow downstrokes)
to
- every second gate-off period contains two rc-resets (purple downstrokes)



The envelope value will increase every yellow downstroke, and decrease for every Nth purple downstroke.
2020-02-04 13:07
Mr. Mouse

Registered: Dec 2001
Posts: 235
Thanks for your suggestion, and I did indeed look into that from that perspective, and did also the math. However, as in your chart, you will find that attack and release will cancel eachother out when it comes to env. In your chart there are about as many release as attack rate counter moments, leading to env to fluctuate between 0 to 3, but never reaching 6. Would you agree?

Also, the "rhythm" I mentioned in my previous post is 64 frames long, where every other ~64 frames (from env=93 onwards most clear) there is NO effect of release at all for ~64 frames.
 
... 4 posts hidden. Click here to view all posts....
 
Previous - 1 | 2 - Next
RefreshSubscribe to this thread:

You need to be logged in to post in the forum.

Search the forum:
Search   for   in  
All times are CET.
Search CSDb
Advanced
Users Online
Inge/HVSC
Acidchild/Padua
LHS/Padua
Mike
psych
Guests online: 90
Top Demos
1 Next Level  (9.7)
2 13:37  (9.7)
3 Mojo  (9.7)
4 Coma Light 13  (9.6)
5 Edge of Disgrace  (9.6)
6 What Is The Matrix 2  (9.6)
7 The Demo Coder  (9.6)
8 Uncensored  (9.6)
9 Comaland 100%  (9.6)
10 Wonderland XIV  (9.6)
Top onefile Demos
1 Layers  (9.6)
2 No Listen  (9.6)
3 Party Elk 2  (9.6)
4 Cubic Dream  (9.6)
5 Copper Booze  (9.6)
6 Rainbow Connection  (9.5)
7 Dawnfall V1.1  (9.5)
8 Onscreen 5k  (9.5)
9 Morph  (9.5)
10 Libertongo  (9.5)
Top Groups
1 Performers  (9.3)
2 Booze Design  (9.3)
3 Oxyron  (9.3)
4 Triad  (9.3)
5 Censor Design  (9.3)
Top Webmasters
1 Slaygon  (9.6)
2 Perff  (9.6)
3 Sabbi  (9.5)
4 Morpheus  (9.4)
5 CreaMD  (9.1)

Home - Disclaimer
Copyright © No Name 2001-2024
Page generated in: 0.041 sec.