Re: Problems Fading Out Music
Re: Problems Fading Out Music
- Subject: Re: Problems Fading Out Music
- From: Graham Cox <email@hidden>
- Date: Fri, 8 Jan 2010 11:19:23 +1100
On 08/01/2010, at 6:17 AM, Chunk 1978 wrote:
> ok i'll use NSTimer instead of performSelector:withObject:afterDelay,
> it should be easier to track this way. however, i'm still having an
> issue with executing logic for the callback method:
>
> so i set the timer to fire ever 0.15 seconds with this:
>
> currentVolume =+ targetVolume / (fadeDuration / 0.15);
>
> this makes sense to me but it doesn't work.
>
> i see in your example you have callback which you said is used for
> both fading in and fading out
>
> float vol = [fi level1] + ([fi delta] * ( t / [fi time]));
>
> in comparing the two, i believe i'm missing the entire end of the
> logic: * ( t / [fi time])), but i can't really figure out what [fi
> time] is...
>
> ughhh...
Well, maybe it'll help to just review linear scaling-over-time arithmetic.
You want to take a quantity from a value v0 to a new value v1 in a period of time d. To do this, the time d is broken down into a series of discrete steps. We are not concerned with precisely how many steps, as long as there are enough to make the transition smooth. That's why the timer, which is what is doing the breaking up of d into steps, is simply set to run at some sufficiently fast constant rate. However, this rate does need to be considerably faster than d so that there are at least several steps - if it's too slow the result will be that the value changes abruptly to the end value as soon as it runs. My code uses 1/30th of a second as the timer rate, which is a reasonable starting point. If you want more smoothness, go faster. I think you are setting your timer to the value d; that won't work.
At any point in time t between the start time, t0 and the end time, t1, we need to know the value of v(t). At t0, v(t) = v0. At t1, v(t) = v1.
If we arrange the value t to scale linearly from 0 to 1, it's easy to map that to a second quantity that goes from v0 to v1.
v = v0 + (( v1 - v0 ) * t )
So now all we need to do is to arrange for our desired timespan to be normalised to the range 0..1
To do that, we must know the start time, t0. So at the start of the run we make a note of it - it's simply the current time.
To scale the actual elapsed time into the range 0..1, is simply:
t = ( tc - t0 ) / d
where tc is the current time and d is the desired total run time.
Substitute this into the first equation:
v = v0 + (( v1 - v0 ) * (( tc - t0 ) / d ))
The value v is the instantaneous value of (whatever). In your case it's the desired volume. Note that this works no matter what rate you set the timer to, and whether v0 is greater or less than v1. Does it work? Let's try some numbers. If our desired fade time is 5 seconds, and we are going from full volume (1.0 ) to silence (0.0), and the callback is called at the halfway point (here the actual timestamp values are just made up):
v = 1.0 + (( 0.0 - 1.0 ) * (( 125.5 - 123 ) / 5.0 )) = 1.0 + -1.0 * ( 2.5 / 5.0 ) = 1.0 - 0.5 = 0.5
Yes it does - at the halfway mark in time, the volume is half of what it was.
We also know when to stop - as soon as t >= 1.0, we're done.
My code doesn't quite appear to implement this equation, because it precalculates some of the terms, such as v1 - v0, but in fact this saves no useful time which is why I wouldn't bother doing it that way now - just keep it direct and simple.
If you want a non-linear ramp, the best place to do that is after calculating the value t in the range 0..1. You can convert that into a new range 0..1 that is not linear. Because you've normalised the range to 0..1 regardless of the value of d or anything else, this can be a simple conversion function of the form t' = f(t).
hope this helps,
--Graham
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden