This commit is contained in:
melekhin
2026-09-25 15:52:58 +07:00
parent 34a005540d
commit 7baeb0dfed
2 changed files with 81 additions and 6 deletions
+7 -1
View File
@@ -2,11 +2,17 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework> <TargetFramework>net10.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<PublishAot>true</PublishAot> <PublishAot>true</PublishAot>
<InvariantGlobalization>true</InvariantGlobalization> <InvariantGlobalization>true</InvariantGlobalization>
<StartupObject>HearingProtector.Program</StartupObject>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="NAudio" Version="3.1.0" />
<PackageReference Include="NAudio.Wasapi" Version="3.1.0" />
</ItemGroup>
</Project> </Project>
+73 -4
View File
@@ -1,10 +1,79 @@
namespace HearingProtector using NAudio.CoreAudioApi;
namespace HearingProtector;
internal static class Program
{ {
internal class Program // ─── Настройки — только то, что интересно пользователю ───────────────
private const double MinVolumePercent = 1.0; // до какого % убавляем
private const double FullDecayMinutes = 30.0; // за сколько минут 100% → MinVolume
private const int PollMs = 1000; // шаг цикла
private const float UserChangeEps = 0.005f;// порог «ручное изменение»
private const int LogEveryTicks = 30; // лог раз в 30 сек
// ─── Производные величины — считаются автоматически ──────────────────
private static readonly double MinVolume = MinVolumePercent / 100.0;
private static readonly double TotalTicks = FullDecayMinutes * 60_000.0 / PollMs;
private static readonly double DecayPerTick = Math.Pow(MinVolume, 1.0 / TotalTicks);
private static readonly double DbPerTick = 20.0 * Math.Log10(DecayPerTick);
private static async Task Main()
{ {
static void Main(string[] args) using var enumerator = new MMDeviceEnumerator();
var device = enumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
var volume = device.AudioEndpointVolume;
// ── Показываем пользователю, что мы из его настроек вывели ──
Console.WriteLine($"Диапазон: 100% → {MinVolumePercent:F1}%");
Console.WriteLine($"Заданное время: {FullDecayMinutes:F1} мин " +
$"({TotalTicks:F0} тиков по {PollMs} мс)");
Console.WriteLine($"Множитель/тик: ×{DecayPerTick:F6} " +
$"= {DbPerTick:F4} дБ");
Console.WriteLine();
float current = volume.MasterVolumeLevelScalar;
float lastSet = current;
Console.WriteLine($"Стартуем с {current * 100:F1}%. Ctrl+C — выход.");
Console.WriteLine();
int tick = 0;
while (true)
{ {
Console.WriteLine("Hello, World!"); float actual = volume.MasterVolumeLevelScalar;
// 1) Реакция на ручное изменение громкости.
if (Math.Abs(actual - lastSet) > UserChangeEps)
{
var dir = actual > lastSet ? "повышение" : "понижение";
Console.WriteLine(
$"[{DateTime.Now:HH:mm:ss}] Ручное изменение ({dir}): " +
$"{lastSet * 100:F1}% → {actual * 100:F1}%");
current = actual;
}
// 2) Один экспоненциальный шаг вниз.
current = (float)Math.Max(MinVolume, current * DecayPerTick);
// 3) Применяем, если значение реально отличается.
if (Math.Abs(volume.MasterVolumeLevelScalar - current) > 0.0005f)
volume.MasterVolumeLevelScalar = current;
lastSet = current;
// 4) Редкий лог с ETA.
if (++tick % LogEveryTicks == 0)
{
double etaSec = Math.Log(MinVolume / current) / Math.Log(DecayPerTick)
* PollMs / 1000.0;
var eta = TimeSpan.FromSeconds(Math.Max(0, etaSec));
Console.WriteLine(
$"[{DateTime.Now:HH:mm:ss}] " +
$"Громкость: {current * 100:F1}% " +
$"(до минимума ~{eta:hh\\:mm\\:ss})");
}
await Task.Delay(PollMs);
} }
} }
} }