HDCD: Make HDCD extension processing optional
Some checks are pending
Check if Cog buildable / Build Universal Cog.app (push) Waiting to run

And disabled by default, at that. I can't actually hear the difference
of Peak Extension in the Rock track I have that claims to use it. And
Low Level Range Extension is more trouble than it's worth on tracks that
use it by mistake, or maliciously, if the case may be. I may add track
tag level control in the future.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
Christopher Snowhill 2025-04-23 21:43:51 -07:00
parent 91c4ed0c98
commit a92973c6aa
6 changed files with 48 additions and 17 deletions

View file

@ -129,6 +129,7 @@ NSString *CogPlaybackDidStopNotificiation = @"CogPlaybackDidStopNotificiation";
@"volumeLimit": @(YES), @"volumeLimit": @(YES),
@"enableHrtf": @(NO), @"enableHrtf": @(NO),
@"enableHeadTracking": @(NO), @"enableHeadTracking": @(NO),
@"enableHDCD": @(NO),
/*@"rubberbandEngine": @"faster",*/ /*@"rubberbandEngine": @"faster",*/
@"rubberbandTransients": @"crisp", @"rubberbandTransients": @"crisp",
@"rubberbandDetector": @"compound", @"rubberbandDetector": @"compound",

View file

@ -42,6 +42,7 @@ NS_ASSUME_NONNULL_BEGIN
BOOL observersRegistered; BOOL observersRegistered;
BOOL halveDSDVolume; BOOL halveDSDVolume;
BOOL enableHDCD;
void *hdcd_decoder; void *hdcd_decoder;
BOOL formatRead; BOOL formatRead;

View file

@ -408,8 +408,10 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
- (void)addObservers { - (void)addObservers {
if(!observersRegistered) { if(!observersRegistered) {
halveDSDVolume = NO; halveDSDVolume = NO;
enableHDCD = NO;
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.halveDSDVolume" options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew) context:kChunkListContext]; [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.halveDSDVolume" options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew) context:kChunkListContext];
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.enableHDCD" options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew) context:kChunkListContext];
observersRegistered = YES; observersRegistered = YES;
} }
@ -418,6 +420,7 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
- (void)removeObservers { - (void)removeObservers {
if(observersRegistered) { if(observersRegistered) {
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.halveDSDVolume" context:kChunkListContext]; [[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.halveDSDVolume" context:kChunkListContext];
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.enableHDCD" context:kChunkListContext];
observersRegistered = NO; observersRegistered = NO;
} }
@ -456,6 +459,8 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
if([keyPath isEqualToString:@"values.halveDSDVolume"]) { if([keyPath isEqualToString:@"values.halveDSDVolume"]) {
halveDSDVolume = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"halveDSDVolume"]; halveDSDVolume = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"halveDSDVolume"];
} else if([keyPath isEqualToString:@"values.enableHDCD"]) {
enableHDCD = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"enableHDCD"];
} }
} }
@ -693,6 +698,7 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
inputFormat.mChannelsPerFrame == 2 && inputFormat.mChannelsPerFrame == 2 &&
inputFormat.mSampleRate == 44100) { inputFormat.mSampleRate == 44100) {
// possibly HDCD, run through decoder // possibly HDCD, run through decoder
[self addObservers];
if(hdcd_decoder) { if(hdcd_decoder) {
free(hdcd_decoder); free(hdcd_decoder);
hdcd_decoder = NULL; hdcd_decoder = NULL;
@ -839,13 +845,19 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
((hdcd_state_stereo_t *)hdcd_decoder)->channel[1].sustain) { ((hdcd_state_stereo_t *)hdcd_decoder)->channel[1].sustain) {
hdcdSustained = YES; hdcdSustained = YES;
} }
if(enableHDCD) {
gain = 2.0; gain = 2.0;
bitsPerSample = 32; bitsPerSample = 32;
bytesReadFromInput = samplesRead * 4; bytesReadFromInput = samplesRead * 4;
isUnsigned = NO; isUnsigned = NO;
inputBuffer = &tempData[buffer_adder]; inputBuffer = &tempData[buffer_adder];
inputChanged = YES; inputChanged = YES;
} else {
// Discard the output of the decoder and process again
goto process16bit;
}
} else if(bitsPerSample <= 16) { } else if(bitsPerSample <= 16) {
process16bit:
samplesRead = bytesReadFromInput / 2; samplesRead = bytesReadFromInput / 2;
const size_t buffer_adder = (inputBuffer == &tempData[0]) ? buffer_adder_base : 0; const size_t buffer_adder = (inputBuffer == &tempData[0]) ? buffer_adder_base : 0;
if(isUnsigned) { if(isUnsigned) {

View file

@ -314,11 +314,11 @@
</connections> </connections>
</customObject> </customObject>
<customView id="58" userLabel="OutputView"> <customView id="58" userLabel="OutputView">
<rect key="frame" x="0.0" y="0.0" width="640" height="197"/> <rect key="frame" x="0.0" y="0.0" width="640" height="225"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DhK-tx-xFv"> <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DhK-tx-xFv">
<rect key="frame" x="18" y="160" width="602" height="18"/> <rect key="frame" x="18" y="188" width="602" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <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"> <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"/> <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
@ -329,7 +329,7 @@
</connections> </connections>
</button> </button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7K3-EO-1eu"> <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7K3-EO-1eu">
<rect key="frame" x="18" y="134" width="602" height="18"/> <rect key="frame" x="18" y="162" width="602" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Reduce DSD volume level by 6 dB" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="Phw-hj-6tI"> <buttonCell key="cell" type="check" title="Reduce DSD volume level by 6 dB" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="Phw-hj-6tI">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/> <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
@ -340,7 +340,7 @@
</connections> </connections>
</button> </button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="SIK-tH-5VQ"> <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="SIK-tH-5VQ">
<rect key="frame" x="18" y="108" width="602" height="18"/> <rect key="frame" x="18" y="136" width="602" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Enable FreeSurround stereo to surround upmixing" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="F0i-UK-6Nu"> <buttonCell key="cell" type="check" title="Enable FreeSurround stereo to surround upmixing" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="F0i-UK-6Nu">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/> <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
@ -351,7 +351,7 @@
</connections> </connections>
</button> </button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="rG5-80-FId"> <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="rG5-80-FId">
<rect key="frame" x="18" y="80" width="200" height="18"/> <rect key="frame" x="18" y="108" width="200" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Enable HRTF filter" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="NGx-0c-WVR"> <buttonCell key="cell" type="check" title="Enable HRTF filter" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="NGx-0c-WVR">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/> <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
@ -362,7 +362,7 @@
</connections> </connections>
</button> </button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="mz3-1e-AVD" userLabel="Head Tracking"> <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="mz3-1e-AVD" userLabel="Head Tracking">
<rect key="frame" x="224" y="80" width="184" height="18"/> <rect key="frame" x="224" y="108" width="184" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Head Tracking" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="Lpr-85-geO" userLabel="Head Tracking"> <buttonCell key="cell" type="check" title="Head Tracking" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="Lpr-85-geO" userLabel="Head Tracking">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/> <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
@ -373,7 +373,7 @@
</connections> </connections>
</button> </button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="BBu-91-qdU" userLabel="Recenter button"> <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="BBu-91-qdU" userLabel="Recenter button">
<rect key="frame" x="450" y="72" width="89" height="32"/> <rect key="frame" x="450" y="100" width="89" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Recenter" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="aQP-kn-fMB"> <buttonCell key="cell" type="push" title="Recenter" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="aQP-kn-fMB">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
@ -383,7 +383,18 @@
</connections> </connections>
</buttonCell> </buttonCell>
</button> </button>
<textField focusRingType="none" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="65"> <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gp7-Ol-WjT" userLabel="Enable HDCD Peak and Low Level Range Extend">
<rect key="frame" x="18" y="83" width="364" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Enable HDCD Peak and Low Level Range Extend" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="IU9-uF-gU9" userLabel="Enable HDCD Peak and Low Level Range Extend">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="52" name="value" keyPath="values.enableHDCD" id="bCr-eK-F3i"/>
</connections>
</button>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="65">
<rect key="frame" x="6" y="53" width="134" height="17"/> <rect key="frame" x="6" y="53" width="134" height="17"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Output Device: " id="211"> <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Output Device: " id="211">
@ -413,8 +424,8 @@
<binding destination="59" name="selectedIndex" keyPath="selectionIndex" previousBinding="71" id="72"/> <binding destination="59" name="selectedIndex" keyPath="selectionIndex" previousBinding="71" id="72"/>
</connections> </connections>
</popUpButton> </popUpButton>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zkP-2E-1Kc"> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zkP-2E-1Kc">
<rect key="frame" x="17" y="20" width="123" height="17"/> <rect key="frame" x="17" y="23" width="123" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <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"> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Volume Level:" id="wK4-EF-8Wa">
<font key="font" metaFont="system"/> <font key="font" metaFont="system"/>
@ -423,7 +434,7 @@
</textFieldCell> </textFieldCell>
</textField> </textField>
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2v7-Ef-ekr" userLabel="Volume Level"> <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2v7-Ef-ekr" userLabel="Volume Level">
<rect key="frame" x="144" y="16" width="480" height="26"/> <rect key="frame" x="144" y="19" width="480" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <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"> <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"/> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>

View file

@ -248,6 +248,9 @@
/* Class = "NSButtonCell"; title = "Recenter"; ObjectID = "aQP-kn-fMB"; */ /* Class = "NSButtonCell"; title = "Recenter"; ObjectID = "aQP-kn-fMB"; */
"aQP-kn-fMB.title" = "Recenter"; "aQP-kn-fMB.title" = "Recenter";
/* Class = "NSButtonCell"; title = "Enable HDCD Peak and Low Level Range Extend"; ObjectID = "IU9-uF-gU9"; */
"IU9-uF-gU9.title" = "Enable HDCD Peak and Low Level Range Extend";
/* Class = "NSButtonCell"; title = "Enable FreeSurround stereo to surround upmixing"; ObjectID = "F0i-UK-6Nu"; */ /* Class = "NSButtonCell"; title = "Enable FreeSurround stereo to surround upmixing"; ObjectID = "F0i-UK-6Nu"; */
"F0i-UK-6Nu.title" = "Enable FreeSurround stereo to surround upmixing"; "F0i-UK-6Nu.title" = "Enable FreeSurround stereo to surround upmixing";

View file

@ -244,6 +244,9 @@
/* Class = "NSButtonCell"; title = "Recenter"; ObjectID = "aQP-kn-fMB"; */ /* Class = "NSButtonCell"; title = "Recenter"; ObjectID = "aQP-kn-fMB"; */
"aQP-kn-fMB.title" = "Recalibrar"; "aQP-kn-fMB.title" = "Recalibrar";
/* Class = "NSButtonCell"; title = "Enable HDCD Peak and Low Level Range Extend"; ObjectID = "IU9-uF-gU9"; */
"IU9-uF-gU9.title" = "Activar extensiones de HDCD";
/* Class = "NSButtonCell"; title = "Automatically check for updates on startup"; ObjectID = "207"; */ /* Class = "NSButtonCell"; title = "Automatically check for updates on startup"; ObjectID = "207"; */
"207.title" = "Buscar actualizaciones al abrir"; "207.title" = "Buscar actualizaciones al abrir";