@@ -15,6 +15,7 @@ import androidx.preference.Preference.SummaryProvider
1515import androidx.preference.PreferenceFragmentCompat
1616import androidx.preference.ListPreference
1717import androidx.preference.PreferenceScreen
18+ import androidx.preference.SwitchPreferenceCompat
1819import androidx.recyclerview.widget.RecyclerView
1920import me.timschneeberger.rootlessjamesdsp.R
2021import me.timschneeberger.rootlessjamesdsp.activity.GraphicEqualizerActivity
@@ -248,19 +249,53 @@ class PreferenceGroupFragment : PreferenceFragmentCompat(), KoinComponent {
248249 val unitPref = findPreference<ListPreference >(getString(R .string.key_spectrum_ext_strength_unit))
249250 val strengthPercentPref = findPreference<MaterialSeekbarPreference >(getString(R .string.key_spectrum_ext_strength_percent))
250251 val strengthDbPref = findPreference<MaterialSeekbarPreference >(getString(R .string.key_spectrum_ext_strength_db))
252+ val allowBoostPref = findPreference<SwitchPreferenceCompat >(getString(R .string.key_spectrum_ext_allow_boost))
251253 val harmonicsPref = findPreference<EditTextPreference >(getString(R .string.key_spectrum_ext_harmonics))
252254
253255 bindStrengthUnitPreferences(
254256 unitPref = unitPref,
255257 strengthPercentPref = strengthPercentPref,
256258 strengthDbPref = strengthDbPref,
257- maxDb = 0.0f ,
259+ maxDbProvider = {
260+ if (allowBoostPref?.isChecked == true ) {
261+ SPECTRUM_STRENGTH_BOOST_DB_MAX
262+ } else {
263+ SPECTRUM_STRENGTH_DB_DEFAULT_MAX
264+ }
265+ },
258266 minPercent = 0.0f ,
259- maxPercent = 100.0f ,
267+ maxPercentProvider = {
268+ if (allowBoostPref?.isChecked == true ) {
269+ strengthPercentFromDb(SPECTRUM_STRENGTH_BOOST_DB_MAX )
270+ } else {
271+ 100.0f
272+ }
273+ },
260274 minLinear = 0.0f ,
261275 mapMinDbToZero = true
262276 )
263277
278+ fun applyBoostUi (isEnabled : Boolean ) {
279+ val maxDb = if (isEnabled) SPECTRUM_STRENGTH_BOOST_DB_MAX else SPECTRUM_STRENGTH_DB_DEFAULT_MAX
280+ val maxPercent = if (isEnabled) strengthPercentFromDb(SPECTRUM_STRENGTH_BOOST_DB_MAX ) else 100.0f
281+
282+ strengthDbPref?.setMax(maxDb)
283+ strengthPercentPref?.setMax(maxPercent)
284+
285+ if ((strengthDbPref?.getValue() ? : maxDb) > maxDb) {
286+ strengthDbPref?.setValue(maxDb)
287+ }
288+ if ((strengthPercentPref?.getValue() ? : maxPercent) > maxPercent) {
289+ strengthPercentPref?.setValue(maxPercent)
290+ }
291+ }
292+
293+ applyBoostUi(allowBoostPref?.isChecked == true )
294+ allowBoostPref?.setOnPreferenceChangeListener { _, newValue ->
295+ applyBoostUi(newValue as Boolean )
296+ true
297+ }
298+
264299 harmonicsPref?.setOnPreferenceChangeListener { _, newValue ->
265300 val harmonicsRaw = (newValue as ? String )?.trim().orEmpty()
266301 if (isValidSemicolonDelimitedHarmonics(harmonicsRaw)) {
@@ -279,9 +314,9 @@ class PreferenceGroupFragment : PreferenceFragmentCompat(), KoinComponent {
279314 unitPref = unitPref,
280315 strengthPercentPref = strengthPercentPref,
281316 strengthDbPref = strengthDbPref,
282- maxDb = CLARITY_STRENGTH_DB_MAX ,
317+ maxDbProvider = { CLARITY_STRENGTH_DB_MAX } ,
283318 minPercent = 0.0f ,
284- maxPercent = 800.0f ,
319+ maxPercentProvider = { 800.0f } ,
285320 minLinear = 0.0f ,
286321 mapMinDbToZero = true
287322 )
@@ -322,39 +357,40 @@ class PreferenceGroupFragment : PreferenceFragmentCompat(), KoinComponent {
322357 unitPref : ListPreference ? ,
323358 strengthPercentPref : MaterialSeekbarPreference ? ,
324359 strengthDbPref : MaterialSeekbarPreference ? ,
325- maxDb : Float ,
360+ maxDbProvider : () -> Float ,
326361 minPercent : Float ,
327- maxPercent : Float ,
362+ maxPercentProvider : () -> Float ,
328363 minLinear : Float = 0.01f,
329364 mapMinDbToZero : Boolean = false,
330365 ) {
331- val maxLinear = dbToLinear(maxDb)
332366 val minDb = MIN_STRENGTH_DB
333367 val percentUnit = requireContext().getString(R .string.strength_unit_value_percent)
334368 val dbUnit = requireContext().getString(R .string.strength_unit_value_db)
335369 var internalUpdate = false
336370
337371 fun percentToLinear (percent : Float ): Float {
372+ val maxLinear = dbToLinear(maxDbProvider())
338373 return clampLinear(percent / 100.0f , minLinear, maxLinear)
339374 }
340375
341376 fun dbToLinearMapped (db : Float ): Float {
342377 if (mapMinDbToZero && db <= minDb) {
343378 return 0.0f
344379 }
380+ val maxLinear = dbToLinear(maxDbProvider())
345381 return clampLinear(dbToLinear(db), minLinear, maxLinear)
346382 }
347383
348384 fun linearToDbMapped (linear : Float ): Float {
349385 if (mapMinDbToZero && linear <= 0.0f ) {
350386 return minDb
351387 }
352- return linearToDb(linear).coerceIn(minDb, maxDb )
388+ return linearToDb(linear).coerceIn(minDb, maxDbProvider() )
353389 }
354390
355391 strengthPercentPref?.setOnPreferenceChangeListener { _, newValue ->
356392 if (internalUpdate) return @setOnPreferenceChangeListener true
357- val percent = (newValue as Float ).coerceIn(minPercent, maxPercent )
393+ val percent = (newValue as Float ).coerceIn(minPercent, maxPercentProvider() )
358394 val linear = percentToLinear(percent)
359395 val db = linearToDbMapped(linear)
360396 internalUpdate = true
@@ -365,9 +401,9 @@ class PreferenceGroupFragment : PreferenceFragmentCompat(), KoinComponent {
365401
366402 strengthDbPref?.setOnPreferenceChangeListener { _, newValue ->
367403 if (internalUpdate) return @setOnPreferenceChangeListener true
368- val db = (newValue as Float ).coerceIn(minDb, maxDb )
404+ val db = (newValue as Float ).coerceIn(minDb, maxDbProvider() )
369405 val linear = dbToLinearMapped(db)
370- val percent = (linear * 100.0f ).coerceIn(minPercent, maxPercent )
406+ val percent = (linear * 100.0f ).coerceIn(minPercent, maxPercentProvider() )
371407 internalUpdate = true
372408 strengthPercentPref?.setValue(percent)
373409 internalUpdate = false
@@ -384,7 +420,7 @@ class PreferenceGroupFragment : PreferenceFragmentCompat(), KoinComponent {
384420 } else if (newUnit == percentUnit) {
385421 val db = strengthDbPref?.getValue() ? : minDb
386422 val linear = dbToLinearMapped(db)
387- strengthPercentPref?.setValue((linear * 100.0f ).coerceIn(minPercent, maxPercent ))
423+ strengthPercentPref?.setValue((linear * 100.0f ).coerceIn(minPercent, maxPercentProvider() ))
388424 }
389425 internalUpdate = false
390426 setStrengthVisibility(newUnit, strengthPercentPref, strengthDbPref)
@@ -413,6 +449,8 @@ class PreferenceGroupFragment : PreferenceFragmentCompat(), KoinComponent {
413449
414450 private fun dbToLinear (db : Float ): Float = 10.0 .pow((db / 20.0f ).toDouble()).toFloat()
415451
452+ private fun strengthPercentFromDb (db : Float ): Float = dbToLinear(db) * 100.0f
453+
416454 /* *
417455 * Domain-specific clamping for linear gain values used by [linearToDb] and [dbToLinear].
418456 * Inputs and bounds are linear-domain amplitudes and must stay positive for log conversion.
@@ -460,6 +498,8 @@ class PreferenceGroupFragment : PreferenceFragmentCompat(), KoinComponent {
460498 private const val CROSSFEED_MODE_DEFAULT_VALUE = " 5"
461499 private const val CUSTOM_CROSSFEED_MODE_VALUE = " 99"
462500 private const val MIN_STRENGTH_DB = - 40.0f
501+ private const val SPECTRUM_STRENGTH_DB_DEFAULT_MAX = 0.0f
502+ private const val SPECTRUM_STRENGTH_BOOST_DB_MAX = 12.0f
463503 private const val CLARITY_STRENGTH_LINEAR_MAX = 8.0f
464504 private val CLARITY_STRENGTH_DB_MAX = (20.0 * log10(CLARITY_STRENGTH_LINEAR_MAX .toDouble())).toFloat()
465505 // Semicolon-separated decimal numbers used by Spectrum Extension harmonics list.
0 commit comments