Volume control: Make preamp optional, defaulting to a limit of 100% volume
parent
6684a8280f
commit
7a0c1d230e
|
@ -63,6 +63,7 @@ NSString *CogPlaybackDidStopNotficiation = @"CogPlaybackDidStopNotficiation";
|
|||
[NSNumber numberWithBool:NO], @"GraphicEQenable",
|
||||
[NSNumber numberWithInt:-1], @"GraphicEQpreset",
|
||||
[NSNumber numberWithBool:NO], @"GraphicEQtrackgenre",
|
||||
[NSNumber numberWithBool:YES], @"volumeLimit",
|
||||
nil];
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] registerDefaults:defaultsDictionary];
|
||||
|
@ -72,9 +73,12 @@ NSString *CogPlaybackDidStopNotficiation = @"CogPlaybackDidStopNotficiation";
|
|||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
double volume = [[NSUserDefaults standardUserDefaults] doubleForKey:@"volume"];
|
||||
BOOL volumeLimit = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"volumeLimit"];
|
||||
const double MAX_VOLUME = (volumeLimit) ? 100.0 : 800.0;
|
||||
|
||||
[volumeSlider setDoubleValue:logarithmicToLinear(volume)];
|
||||
double volume = [[NSUserDefaults standardUserDefaults] doubleForKey:@"volume"];
|
||||
|
||||
[volumeSlider setDoubleValue:logarithmicToLinear(volume, MAX_VOLUME)];
|
||||
[audioPlayer setVolume:volume];
|
||||
|
||||
[self setSeekable:NO];
|
||||
|
@ -350,9 +354,12 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
|
|||
*/
|
||||
- (IBAction)changeVolume:(id)sender
|
||||
{
|
||||
DLog(@"VOLUME: %lf, %lf", [sender doubleValue], linearToLogarithmic([sender doubleValue]));
|
||||
BOOL volumeLimit = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"volumeLimit"];
|
||||
const double MAX_VOLUME = (volumeLimit) ? 100.0 : 800.0;
|
||||
|
||||
[audioPlayer setVolume:linearToLogarithmic([sender doubleValue])];
|
||||
DLog(@"VOLUME: %lf, %lf", [sender doubleValue], linearToLogarithmic([sender doubleValue], MAX_VOLUME));
|
||||
|
||||
[audioPlayer setVolume:linearToLogarithmic([sender doubleValue], MAX_VOLUME)];
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] setDouble:[audioPlayer volume] forKey:@"volume"];
|
||||
}
|
||||
|
@ -374,9 +381,12 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
|
|||
}
|
||||
else // volume is at 0 or below, we are ready to release the timer and move on
|
||||
{
|
||||
[audioPlayer pause];
|
||||
BOOL volumeLimit = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"volumeLimit"];
|
||||
const double MAX_VOLUME = (volumeLimit) ? 100.0 : 800.0;
|
||||
|
||||
[audioPlayer pause];
|
||||
[audioPlayer setVolume:originalVolume];
|
||||
[volumeSlider setDoubleValue: logarithmicToLinear(originalVolume)];
|
||||
[volumeSlider setDoubleValue: logarithmicToLinear(originalVolume, MAX_VOLUME)];
|
||||
[audioTimer invalidate];
|
||||
|
||||
fading = NO;
|
||||
|
@ -401,8 +411,11 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
|
|||
}
|
||||
else // volume is at or near original level, we are ready to release the timer and move on
|
||||
{
|
||||
BOOL volumeLimit = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"volumeLimit"];
|
||||
const double MAX_VOLUME = (volumeLimit) ? 100.0 : 800.0;
|
||||
|
||||
[audioPlayer setVolume:originalVolume];
|
||||
[volumeSlider setDoubleValue: logarithmicToLinear(originalVolume)];
|
||||
[volumeSlider setDoubleValue: logarithmicToLinear(originalVolume, MAX_VOLUME)];
|
||||
[audioTimer invalidate];
|
||||
|
||||
fading = NO;
|
||||
|
@ -539,8 +552,11 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
|
|||
|
||||
- (IBAction)volumeDown:(id)sender
|
||||
{
|
||||
double newVolume = [audioPlayer volumeDown:DEFAULT_VOLUME_DOWN];
|
||||
[volumeSlider setDoubleValue:logarithmicToLinear(newVolume)];
|
||||
BOOL volumeLimit = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"volumeLimit"];
|
||||
const double MAX_VOLUME = (volumeLimit) ? 100.0 : 800.0;
|
||||
|
||||
double newVolume = [audioPlayer volumeDown:DEFAULT_VOLUME_DOWN];
|
||||
[volumeSlider setDoubleValue:logarithmicToLinear(newVolume, MAX_VOLUME)];
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] setDouble:[audioPlayer volume] forKey:@"volume"];
|
||||
|
||||
|
@ -548,9 +564,12 @@ NSDictionary * makeRGInfo(PlaylistEntry *pe)
|
|||
|
||||
- (IBAction)volumeUp:(id)sender
|
||||
{
|
||||
double newVolume;
|
||||
BOOL volumeLimit = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"volumeLimit"];
|
||||
const double MAX_VOLUME = (volumeLimit) ? 100.0 : 800.0;
|
||||
|
||||
double newVolume;
|
||||
newVolume = [audioPlayer volumeUp:DEFAULT_VOLUME_UP];
|
||||
[volumeSlider setDoubleValue:logarithmicToLinear(newVolume)];
|
||||
[volumeSlider setDoubleValue:logarithmicToLinear(newVolume, MAX_VOLUME)];
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] setDouble:[audioPlayer volume] forKey:@"volume"];
|
||||
}
|
||||
|
|
|
@ -566,7 +566,10 @@
|
|||
|
||||
- (double)volumeUp:(double)amount
|
||||
{
|
||||
double newVolume = linearToLogarithmic(logarithmicToLinear(volume + amount));
|
||||
BOOL volumeLimit = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"volumeLimit"];
|
||||
const double MAX_VOLUME = (volumeLimit) ? 100.0 : 800.0;
|
||||
|
||||
double newVolume = linearToLogarithmic(logarithmicToLinear(volume + amount, MAX_VOLUME), MAX_VOLUME);
|
||||
if (newVolume > MAX_VOLUME)
|
||||
newVolume = MAX_VOLUME;
|
||||
|
||||
|
@ -579,11 +582,14 @@
|
|||
|
||||
- (double)volumeDown:(double)amount
|
||||
{
|
||||
double newVolume;
|
||||
BOOL volumeLimit = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"volumeLimit"];
|
||||
const double MAX_VOLUME = (volumeLimit) ? 100.0 : 800.0;
|
||||
|
||||
double newVolume;
|
||||
if (amount > volume)
|
||||
newVolume = 0.0;
|
||||
else
|
||||
newVolume = linearToLogarithmic(logarithmicToLinear(volume - amount));
|
||||
newVolume = linearToLogarithmic(logarithmicToLinear(volume - amount, MAX_VOLUME), MAX_VOLUME);
|
||||
|
||||
[self setVolume:newVolume];
|
||||
return newVolume;
|
||||
|
|
|
@ -7,7 +7,5 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define MAX_VOLUME 800.0
|
||||
|
||||
double logarithmicToLinear(double logarithmic);
|
||||
double linearToLogarithmic(double linear);
|
||||
double logarithmicToLinear(double logarithmic, double MAX_VOLUME);
|
||||
double linearToLogarithmic(double linear, double MAX_VOLUME);
|
||||
|
|
|
@ -15,13 +15,13 @@
|
|||
//Here's why: http://www.dr-lex.34sp.com/info-stuff/volumecontrols.html
|
||||
//We are using the approximation of X^4.
|
||||
//Input/Output values are in percents.
|
||||
double logarithmicToLinear(double logarithmic)
|
||||
double logarithmicToLinear(double logarithmic, double MAX_VOLUME)
|
||||
{
|
||||
return pow((logarithmic/MAX_VOLUME), 0.25) * 100.0;
|
||||
return pow((logarithmic/MAX_VOLUME), 0.25) * 100.0;
|
||||
}
|
||||
|
||||
double linearToLogarithmic(double linear)
|
||||
double linearToLogarithmic(double linear, double MAX_VOLUME)
|
||||
{
|
||||
return (linear/100.0) * (linear/100.0) * (linear/100.0) * (linear/100.0) * MAX_VOLUME;
|
||||
return (linear/100.0) * (linear/100.0) * (linear/100.0) * (linear/100.0) * MAX_VOLUME;
|
||||
}
|
||||
//End helper volume function thingies. ONWARDS TO GLORY!
|
||||
|
|
|
@ -245,18 +245,9 @@
|
|||
</connections>
|
||||
</customObject>
|
||||
<customView id="58" userLabel="OutputView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="530" height="110"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="530" height="150"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="65">
|
||||
<rect key="frame" x="17" y="78" width="123" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Output Device: " id="211">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8GG-SU-ZrX">
|
||||
<rect key="frame" x="5" y="16" width="135" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
|
@ -267,7 +258,7 @@
|
|||
</textFieldCell>
|
||||
</textField>
|
||||
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="60">
|
||||
<rect key="frame" x="144" y="72" width="251" height="26"/>
|
||||
<rect key="frame" x="144" y="80" width="251" height="26"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Item1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" inset="2" arrowPosition="arrowAtCenter" preferredEdge="maxY" selectedItem="62" id="210">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
|
@ -288,7 +279,7 @@
|
|||
</connections>
|
||||
</popUpButton>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zkP-2E-1Kc">
|
||||
<rect key="frame" x="17" y="47" width="123" height="17"/>
|
||||
<rect key="frame" x="17" y="51" width="123" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Volume Level:" id="wK4-EF-8Wa">
|
||||
<font key="font" metaFont="system"/>
|
||||
|
@ -297,7 +288,7 @@
|
|||
</textFieldCell>
|
||||
</textField>
|
||||
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2v7-Ef-ekr">
|
||||
<rect key="frame" x="144" y="41" width="251" height="26"/>
|
||||
<rect key="frame" x="144" y="45" width="251" height="26"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<popUpButtonCell key="cell" type="push" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" id="vmS-eb-zen">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
|
@ -338,8 +329,28 @@
|
|||
<binding destination="52" name="selectedObject" keyPath="values.outputResampling" previousBinding="lIz-gH-9kJ" id="wcT-TT-yKh"/>
|
||||
</connections>
|
||||
</popUpButton>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="65">
|
||||
<rect key="frame" x="17" y="86" width="123" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Output Device: " id="211">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DhK-tx-xFv">
|
||||
<rect key="frame" x="18" y="121" width="227" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="check" title="Limit volume control to 100%" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="ds2-aw-ebU">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<binding destination="52" name="value" keyPath="values.volumeLimit" id="7Sl-LJ-ljd"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<point key="canvasLocation" x="-151" y="337.5"/>
|
||||
<point key="canvasLocation" x="-151" y="318"/>
|
||||
</customView>
|
||||
<customObject id="i5B-ga-Atm" userLabel="MIDIPane" customClass="MIDIPane">
|
||||
<connections>
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
@interface VolumeSlider : NSSlider {
|
||||
NSPopover *popover;
|
||||
NSText *textView;
|
||||
double MAX_VOLUME;
|
||||
}
|
||||
|
||||
- (void)showToolTip;
|
||||
|
|
|
@ -28,6 +28,9 @@
|
|||
}
|
||||
|
||||
- (void) awakeFromNib {
|
||||
BOOL volumeLimit = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"volumeLimit"];
|
||||
MAX_VOLUME = (volumeLimit) ? 100.0 : 800.0;
|
||||
|
||||
wasInsideSnapRange = NO;
|
||||
textView = [[NSText alloc] init];
|
||||
[textView setFrame:NSMakeRect(0, 0, 50, 20)];
|
||||
|
@ -44,12 +47,19 @@
|
|||
popover.behavior = NSPopoverBehaviorTransient;
|
||||
popover.animates = NO;
|
||||
[popover setContentSize:textView.bounds.size];
|
||||
|
||||
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.volumeLimit" options:0 context:nil];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.volumeLimit"];
|
||||
}
|
||||
|
||||
- (void)updateToolTip
|
||||
{
|
||||
double value = [self doubleValue];
|
||||
double volume = linearToLogarithmic(value);
|
||||
double volume = linearToLogarithmic(value, MAX_VOLUME);
|
||||
|
||||
NSString *text = [NSString stringWithFormat:@"%0.lf%%", volume];
|
||||
|
||||
|
@ -114,10 +124,24 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
|
||||
{
|
||||
if ([keyPath isEqualToString:@"values.volumeLimit"]) {
|
||||
BOOL volumeLimit = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"volumeLimit"];
|
||||
const double new_MAX_VOLUME = (volumeLimit) ? 100.0 : 800.0;
|
||||
|
||||
if (MAX_VOLUME != new_MAX_VOLUME) {
|
||||
double currentLevel = linearToLogarithmic([self doubleValue], MAX_VOLUME);
|
||||
[self setDoubleValue:logarithmicToLinear(currentLevel, new_MAX_VOLUME)];
|
||||
}
|
||||
MAX_VOLUME = new_MAX_VOLUME;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)sendAction:(SEL)theAction to:(id)theTarget
|
||||
{
|
||||
// Snap to 100% if value is close
|
||||
double snapTarget = logarithmicToLinear(100.0);
|
||||
double snapTarget = logarithmicToLinear(100.0, MAX_VOLUME);
|
||||
double snapProgress = ([self doubleValue] - snapTarget) / (self.maxValue - self.minValue);
|
||||
|
||||
if (fabs(snapProgress) < 0.005)
|
||||
|
|
Loading…
Reference in New Issue