NSSound taper, revisited
NSSound taper, revisited
- Subject: NSSound taper, revisited
- From: Glenn English <email@hidden>
- Date: Thu, 26 Jun 2008 13:18:21 -0600
A while back, I posted to this list asking about the taper of NSSound
-- I wanted to fade some stuff in the program I'm working on (http://www.auraluserinterface.com
), and I wanted it to sound good. I figured out how to do it, but
haven't posted the solution because it's so trivial. But this morning,
I saw yet another sound app talking about its "400 steps of level
settings".
How an audio level control is done really makes a huge difference, as
you probably know.
Here's my #import file (#define INCLUDE_TAPER_ARRAY to get the array
itself):
// an array to be used for level control
// creates a taper of 1.5 db per step to 25.5 db
// then tapers like an old Daven pot to infinity
#ifdef INCLUDE_TAPER_ARRAY
static CGFloat taper[] =
{ 1.0000, .84140, .70795, .59566, .50119,
.42170, .35481, .29854, .25119, .21135,
.17783, .14962, .12589, .10593, .08913,
.07499, .06310, .05309, .04217, .03162,
.02113, .01000, .00316, .00010, 0.0000
};
#endif
#define TAPER_MAX_INDEX 24
#define DOWN_6_DB 4
#define DOWN_8_DB 5
#define DOWN_10_DB 7
#define DOWN_15_DB 10
#define DOWN_20_DB 13
#define DOWN_25_DB 17
#define DOWN_30_DB 19
#define DOWN_35_DB 20
#define DOWN_40_DB 21
#define DOWN_50_DB 22
#define DOWN_80_DB 23
#define WIDE_OPEN 0
#define CUTOFF TAPER_MAX_INDEX
Assuming instance variables:
NSSound * theSound;
NSTimer * fadeTimer;
NSInteger fadeIncrement, fadeDest, faderStep;
NSNotificationCenter * noteCenter;
NSString * FADE_DONE;
and a #define of FADE_INTERVAL, the time between the steps
Here's some objective-c (may contain oopsies -- it's simplified from
what compiled and ran):
- (void) fadeTo:(NSInteger) destFaderStep
{
if ((fadeTimer == nil) && (destFaderStep >= WIDE_OPEN) &&
(destFaderStep <= CUTOFF))
{
fadeIncrement = ((destFaderStep > faderStep) ? 1 : -1);
fadeDest = destFaderStep;
fadeTimer = [NSTimer scheduledTimerWithTimeInterval:FADE_INTERVAL
target:self
selector:@selector(fadeCallback:)
userInfo:nil
repeats:YES];
}
}
- (void) fadeCallback:(NSTimer *) notUsed
{
if (faderStep != fadeDest)
{
faderStep += fadeIncrement;
[theSound setVolume:taper[faderStep]];
}
else
{
[fadeTimer invalidate];
fadeTimer = nil;
[noteCenter postNotification:[NSNotification notificationWithName:
FADE_DONE
object:self]];
}
}
This provides fades between 0 and 25 db, linear in db at 1.5 db per
step. Below that, it goes into a steep taper to the noise floor (much
like the end of the movie "Thelma & Louise").
It's done in a lookup table instead of calculating the steps on the
fly because of the change in taper at the bottom, and for speed (on a
Mac Mini (Intel, 1.6GHz, Leopard) I've seen it run between 1 and 2 ms
per step, including writing to the log -- I don't know how long it
takes a Mini to calculate a log, but my old PDP-11 took a couple
weeks :-).
The taper is modeled on the characteristics of the Daven, Langevin,
and Altec attenuators I worked with so many years ago in radio
broadcasting. I started out planning to create a fader with a hundred
or so steps, but these 20+ steps are plenty for what I wanted -- when
fading real world sounds, they're inaudible. And because there are so
few steps, it's fast enough to be used instead of just stopping a
sound; sounds much more civilized.
The values were calculated in a spreadsheet, and, of course, it should
work anywhere the level setting is a float between 0.0 and 1.0. Feel
free to use it if you think it might help.
In hopes that this might improve the sound of audio software...
--
Glenn English
email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden