Skip to content

Commit

Permalink
Merge pull request #170 from alnitak/newLimiter
Browse files Browse the repository at this point in the history
Limiter filter outputCeiling + attackTime
  • Loading branch information
alnitak authored Jan 23, 2025
2 parents 919da72 + 5f3c364 commit 3ed9ca7
Show file tree
Hide file tree
Showing 8 changed files with 195 additions and 98 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"name": "Flutter debug",
"type": "dart",
"request": "launch",
"program": "lib/main.dart",
"program": "lib/filters/limiter.dart",
"flutterMode": "debug",
"cwd": "${workspaceFolder}/example"
},
Expand Down
64 changes: 47 additions & 17 deletions example/lib/filters/limiter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import 'package:logging/logging.dart';
/// - `wet`: Wet/dry mix ratio, 1.0 means fully wet, 0.0 means fully dry
/// - `threshold`: The threshold in dB. Signals above this level are reduced
/// in gain. A lower value means more aggressive limiting.
/// - `makeupGain`: The make-up gain in dB applied after limiting to bring up
/// the output level.
/// - `outputCeiling`: The maximum output level in dB (should be < 0dB to
/// prevent clipping)
/// - `kneeWidth`: The width of the knee in dB. A larger value results in a
/// softer transition into limiting.
/// - `releaseTime`: The release time in milliseconds. Determines how quickly
Expand Down Expand Up @@ -72,9 +72,10 @@ class _LimiterExampleState extends State<LimiterExample> {
AudioSource? sound;
late double wet;
late double threshold;
late double makeupGain;
late double outputCeiling;
late double kneeWidth;
late double releaseTime;
late double attackTime;
bool isFilterActive = false;

@override
Expand All @@ -83,9 +84,10 @@ class _LimiterExampleState extends State<LimiterExample> {

wet = limiter.queryWet.def;
threshold = limiter.queryThreshold.def;
makeupGain = limiter.queryMakeupGain.def;
outputCeiling = limiter.queryOutputCeiling.def;
kneeWidth = limiter.queryKneeWidth.def;
releaseTime = limiter.queryReleaseTime.def;
attackTime = limiter.queryAttackTime.def;
}

@override
Expand All @@ -105,7 +107,11 @@ class _LimiterExampleState extends State<LimiterExample> {
children: [
const Text(
'WARNING: lower the volume down!',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.red,
),
),
Row(
mainAxisSize: MainAxisSize.min,
Expand All @@ -118,9 +124,10 @@ class _LimiterExampleState extends State<LimiterExample> {
limiter.activate();
limiter.wet.value = wet;
limiter.threshold.value = threshold;
limiter.makeupGain.value = makeupGain;
limiter.outputCeiling.value = outputCeiling;
limiter.kneeWidth.value = kneeWidth;
limiter.releaseTime.value = releaseTime;
limiter.attackTime.value = attackTime;
} else {
limiter.deactivate();
}
Expand All @@ -143,11 +150,16 @@ class _LimiterExampleState extends State<LimiterExample> {
///
ElevatedButton(
onPressed: () {
SoLoud.instance.play(sound!, looping: true);
SoLoud.instance.play(sound!, looping: true);
SoLoud.instance.play(sound!, looping: true);
SoLoud.instance.play(sound!, looping: true);
SoLoud.instance.play(sound!, looping: true);
SoLoud.instance.play(sound!, looping: true, volume: 2);
SoLoud.instance.play(sound!, looping: true, volume: 2);
SoLoud.instance.play(sound!, looping: true, volume: 2);
SoLoud.instance.play(sound!, looping: true, volume: 2);
SoLoud.instance.play(sound!, looping: true, volume: 2);
SoLoud.instance.play(sound!, looping: true, volume: 2);
SoLoud.instance.play(sound!, looping: true, volume: 2);
SoLoud.instance.play(sound!, looping: true, volume: 2);
SoLoud.instance.play(sound!, looping: true, volume: 2);
SoLoud.instance.play(sound!, looping: true, volume: 2);
},
child: const Text('play sound'),
),
Expand Down Expand Up @@ -199,16 +211,16 @@ class _LimiterExampleState extends State<LimiterExample> {
),
Row(
children: [
Text('Makeup gain ${makeupGain.toStringAsFixed(2)}'),
Text('Outpout ceiling ${outputCeiling.toStringAsFixed(2)}'),
Expanded(
child: Slider(
value: makeupGain,
min: limiter.queryMakeupGain.min,
max: limiter.queryMakeupGain.max,
value: outputCeiling,
min: limiter.queryOutputCeiling.min,
max: limiter.queryOutputCeiling.max,
onChanged: (value) {
setState(() {
makeupGain = value;
limiter.makeupGain.value = value;
outputCeiling = value;
limiter.outputCeiling.value = value;
});
},
),
Expand Down Expand Up @@ -251,6 +263,24 @@ class _LimiterExampleState extends State<LimiterExample> {
),
],
),
Row(
children: [
Text('Attack time ${attackTime.toStringAsFixed(2)}'),
Expanded(
child: Slider(
value: attackTime,
min: limiter.queryAttackTime.min,
max: limiter.queryAttackTime.max,
onChanged: (value) {
setState(() {
attackTime = value;
limiter.attackTime.value = value;
});
},
),
),
],
),
],
),
),
Expand Down
1 change: 0 additions & 1 deletion example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import 'dart:async';
import 'dart:developer' as dev;

import 'package:flutter/foundation.dart';
Expand Down
9 changes: 5 additions & 4 deletions lib/src/filter_params.dart
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,14 @@ const FxParams fxLimiter = (
names: [
'Wet',
'Threshold',
'Makeup Gain',
'Output Ceiling',
'Knee Width',
'Release Time',
'Attack Time',
],
mins: [0, -60, -60, 0, 1],
maxs: [1, 0, 30, 30, 1000],
defs: [1, -6, 0, 2, 100],
mins: [0, -60, -60, 0, 1, 0.1],
maxs: [1, 0, 30, 0, 1000, 200],
defs: [1, -6, 0, -1, 100, 1],
);

/// Compressor filter
Expand Down
11 changes: 7 additions & 4 deletions lib/src/filters/filters.dart
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,15 @@ final class FiltersSingle {
/// - `threshold`: The threshold in dB. Signals above this level are reduced
/// in gain. A lower value means more aggressive limiting.
///
/// - `makeupGain`: The make-up gain in dB applied after limiting to bring up
/// the output level.
/// - `outputCeiling`: The maximum output level in dB (should be < 0dB to
/// prevent clipping)
///
/// - `kneeWidth`: The width of the knee in dB. A larger value results in a
/// softer transition into limiting.
///
/// - `attackTime`: The attack time in milliseconds. Determines how quickly
/// the gain reduction recovers after a signal peaks above the threshold.
///
/// - `releaseTime`: The release time in milliseconds. Determines how quickly
/// the gain reduction recovers after a signal drops below the threshold.
LimiterSingle get limiterFilter => LimiterSingle(soundHash);
Expand Down Expand Up @@ -188,8 +191,8 @@ final class FiltersGlobal {
/// - `threshold`: The threshold in dB. Signals above this level are reduced
/// in gain. A lower value means more aggressive limiting.
///
/// - `makeupGain`: The make-up gain in dB applied after limiting to bring up
/// the output level.
/// - `outputCeiling`: The maximum output level in dB (should be < 0dB to
/// prevent clipping)
///
/// - `kneeWidth`: The width of the knee in dB. A larger value results in a
/// softer transition into limiting.
Expand Down
49 changes: 34 additions & 15 deletions lib/src/filters/limiter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import 'package:flutter_soloud/src/sound_hash.dart';
enum Limiter {
wet,
threshold,
makeupGain,
outputCeiling,
kneeWidth,
releaseTime;
releaseTime,
attackTime;

final List<double> _mins = const [0, -60, -60, 0, 1];
final List<double> _maxs = const [1, 0, 30, 30, 1000];
final List<double> _defs = const [1, -6, 0, 2, 100];
final List<double> _mins = const [0, -60, -60, 0, 1, 0.1];
final List<double> _maxs = const [1, 0, 0, 30, 1000, 200];
final List<double> _defs = const [1, -6, -1, 2, 100, 1];

double get min => _mins[index];
double get max => _maxs[index];
Expand All @@ -23,9 +24,10 @@ enum Limiter {
String toString() => switch (this) {
Limiter.wet => 'Wet',
Limiter.threshold => 'Threshold',
Limiter.makeupGain => 'Makeup Gain',
Limiter.outputCeiling => 'Output Ceiling',
Limiter.kneeWidth => 'Knee Width',
Limiter.releaseTime => 'Release Time',
Limiter.attackTime => 'Attack Time',
};
}

Expand All @@ -35,9 +37,10 @@ abstract class _LimiterInternal extends FilterBase {

Limiter get queryWet => Limiter.wet;
Limiter get queryThreshold => Limiter.threshold;
Limiter get queryMakeupGain => Limiter.makeupGain;
Limiter get queryOutputCeiling => Limiter.outputCeiling;
Limiter get queryKneeWidth => Limiter.kneeWidth;
Limiter get queryReleaseTime => Limiter.releaseTime;
Limiter get queryAttackTime => Limiter.attackTime;
}

class LimiterSingle extends _LimiterInternal {
Expand All @@ -59,12 +62,12 @@ class LimiterSingle extends _LimiterInternal {
Limiter.threshold.max,
);

FilterParam makeupGain({SoundHandle? soundHandle}) => FilterParam(
FilterParam outputCeiling({SoundHandle? soundHandle}) => FilterParam(
soundHandle,
filterType,
Limiter.makeupGain.index,
Limiter.makeupGain.min,
Limiter.makeupGain.max,
Limiter.outputCeiling.index,
Limiter.outputCeiling.min,
Limiter.outputCeiling.max,
);

FilterParam kneeWidth({SoundHandle? soundHandle}) => FilterParam(
Expand All @@ -82,6 +85,14 @@ class LimiterSingle extends _LimiterInternal {
Limiter.releaseTime.min,
Limiter.releaseTime.max,
);

FilterParam attackTime({SoundHandle? soundHandle}) => FilterParam(
soundHandle,
filterType,
Limiter.attackTime.index,
Limiter.attackTime.min,
Limiter.attackTime.max,
);
}

class LimiterGlobal extends _LimiterInternal {
Expand All @@ -103,12 +114,12 @@ class LimiterGlobal extends _LimiterInternal {
Limiter.threshold.max,
);

FilterParam get makeupGain => FilterParam(
FilterParam get outputCeiling => FilterParam(
null,
filterType,
Limiter.makeupGain.index,
Limiter.makeupGain.min,
Limiter.makeupGain.max,
Limiter.outputCeiling.index,
Limiter.outputCeiling.min,
Limiter.outputCeiling.max,
);

FilterParam get kneeWidth => FilterParam(
Expand All @@ -126,4 +137,12 @@ class LimiterGlobal extends _LimiterInternal {
Limiter.releaseTime.min,
Limiter.releaseTime.max,
);

FilterParam get attackTime => FilterParam(
null,
filterType,
Limiter.attackTime.index,
Limiter.attackTime.min,
Limiter.attackTime.max,
);
}
Loading

0 comments on commit 3ed9ca7

Please sign in to comment.