Fix beeper, slightly broken (unexpected console output on linux)

This commit is contained in:
CreepyCrafter24 2020-03-17 15:08:52 +01:00
parent fc043e0219
commit 574b85ceb0
5 changed files with 72 additions and 55 deletions

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Threading;
using testexetrisathlon.SoundManagement;
using static System.Console;
@ -79,7 +80,6 @@ namespace testexetrisathlon
SetWindowSize(50, 40);
}
SetCursorPosition(0, 0);
Clear();
bool playing = true;
GameState state = GameState.Menu;
try
@ -185,6 +185,7 @@ namespace testexetrisathlon
ForegroundColor = Colors[1];
SetCursorPosition(0, 0);
Clear();
Beeper.Dispose();
}
private static void DrawSymbol()
@ -212,11 +213,6 @@ namespace testexetrisathlon
{
Clear();
DrawSymbol();
if (!OSCheck.IsWindows)
{
SetCursorPosition(2, 19);
Write("Volume is not supported in this build!");
}
bool barActive = true;
int currentSetting = 0;
while (barActive)
@ -380,6 +376,7 @@ namespace testexetrisathlon
WriteLine("Score " + _score + "/" + (Math.Pow(_level, 2) * 100));
SetCursorPosition(25, 2);
WriteLine("LinesCleared " + _linesCleared);
DrawBorder();
}
public static void DrawBorder()

View File

@ -1,15 +1,60 @@
using System;
using System.Collections.Generic;
using System.IO;
using Bassoon;
namespace testexetrisathlon.SoundManagement
{
public static class Beeper
{
private static readonly Dictionary<Tuple<int, int>, Tuple<string, Sound>> Beeps = new Dictionary<Tuple<int, int>, Tuple<string, Sound>>();
public static void Beep(int frequency, int duration)
{
if (OSCheck.IsWindows)
Console.Beep(frequency, duration);
else
Console.Write("\a");
{
Tuple<int, int> key = new Tuple<int, int>(frequency, duration);
if (!Beeps.ContainsKey(key))
{
string file = Path.GetTempFileName();
File.Move(file, Path.ChangeExtension(file, "wav"));
file = Path.ChangeExtension(file, "wav");
File.WriteAllBytes(file, BeepBeep(1000, frequency, duration));
Beeps.Add(key, new Tuple<string, Sound>(file, new Sound(file)));
}
Beeps[key].Item2.Cursor = 0;
Beeps[key].Item2.Play();
Console.Clear();
}
}
private static byte[] BeepBeep(int amplitude, int frequency, int duration)
{
double a = ((amplitude * Math.Pow(2, 15)) / 1000) - 1;
double deltaFt = (2 * Math.PI * frequency) / 44100.0;
int samples = (441 * duration) / 10;
int bytes = samples * 4;
int[] hdr = {0X46464952, 36 + bytes, 0X45564157, 0X20746D66, 16, 0X20001, 44100, 176400, 0X100004, 0X61746164, bytes};
using MemoryStream ms = new MemoryStream(44 + bytes);
using BinaryWriter bw = new BinaryWriter(ms);
for (int I = 0; I < hdr.Length; I++) bw.Write(hdr[I]);
for (int T = 0; T < samples; T++)
{
short sample = Convert.ToInt16(a * Math.Sin(deltaFt * T));
bw.Write(sample);
bw.Write(sample);
}
bw.Flush();
ms.Seek(0, SeekOrigin.Begin);
return ms.ToArray();
}
public static void Dispose()
{
if (OSCheck.IsWindows)
foreach (Tuple<string, Sound> file in Beeps.Values) File.Delete(file.Item1);
}
}
}

View File

@ -1,26 +1,31 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using Bassoon;
namespace testexetrisathlon.SoundManagement
{
public class LinuxSoundManager : ISoundManager
{
private static readonly Assembly Assembly = Assembly.GetExecutingAssembly();
private ProcessLoop? _alsaProc;
private string _current;
private BassoonEngine _bassoon;
private Dictionary<string, Sound> _loadedSounds;
private Dictionary<string, string> _files;
private string _current;
private int _volume = 100;
private static readonly Assembly Assembly = Assembly.GetExecutingAssembly();
public void Dispose()
{
foreach (Sound sound in _loadedSounds.Values) sound.Dispose();
_bassoon.Dispose();
foreach (string file in _files.Values) File.Delete(file);
if (_alsaProc != null) _alsaProc.IsRunning = false;
}
public void Init(Dictionary<string, string> manifestResources)
{
_bassoon = new BassoonEngine();
_files = new Dictionary<string, string>();
_loadedSounds = new Dictionary<string, Sound>();
foreach ((string name, string key) in manifestResources)
{
string file = Path.GetTempFileName();
@ -31,26 +36,28 @@ namespace testexetrisathlon.SoundManagement
resource.Seek(0, SeekOrigin.Begin);
resource.CopyTo(fileStream);
_files.Add(name, file);
_loadedSounds.Add(name, new Sound(file));
}
Console.Clear();
}
public void SetCurrent(string id)
{
if (_current == id) return;
if (_alsaProc != null) _alsaProc.IsRunning = false;
_current = id;
//TODO fix actually killing, remove orphan processes
_alsaProc = new ProcessLoop(new ProcessStartInfo
if (!string.IsNullOrWhiteSpace(_current))
{
FileName = "aplay",
Arguments = $"-q {_files[id].Replace("\"", "\\\"")}",
CreateNoWindow = true
});
_alsaProc.CreateLoopThread().Start();
_loadedSounds[_current].Pause();
_loadedSounds[_current].Cursor = 0;
}
_current = id;
_loadedSounds[_current].Play();
Console.Clear();
}
public void SetVolume(int percent)
{
_volume = percent;
foreach (Sound sound in _loadedSounds.Values) sound.Volume = _volume / 100f;
}
}
}

View File

@ -1,33 +0,0 @@
using System.Diagnostics;
using System.Threading;
namespace testexetrisathlon.SoundManagement
{
internal class ProcessLoop
{
private readonly ProcessStartInfo _info;
private Process _currentProc;
private bool _isRunning = true;
public ProcessLoop(ProcessStartInfo info) => _info = info;
public bool IsRunning
{
set
{
if (_isRunning && !value)
_currentProc.Kill();
_isRunning = value;
}
}
public Thread CreateLoopThread() => new Thread(() =>
{
while (_isRunning)
{
_currentProc = Process.Start(_info);
_currentProc.WaitForExit();
}
});
}
}

View File

@ -28,6 +28,7 @@
<Content Include="tetris_yUxH6t_256px.ico" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Bassoon" Version="1.1.1" />
<PackageReference Include="NAudio" Version="1.10.0" />
</ItemGroup>
</Project>