Skip to content

Commit

Permalink
add - doc - Added beep synth from Nitrocid KS
Browse files Browse the repository at this point in the history
---

We've backported the beep synth feature to Terminaux from Nitrocid KS for
wider accessibility.

---

Type: add
Breaking: False
Doc Required: True
Backport Required: False
Part: 1/1
  • Loading branch information
AptiviCEO committed Nov 18, 2024
1 parent a5ea8d9 commit 8c02821
Show file tree
Hide file tree
Showing 5 changed files with 288 additions and 0 deletions.
64 changes: 64 additions & 0 deletions Terminaux.Console/Fixtures/Cases/Consoles/BeepSynth.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//
// Terminaux Copyright (C) 2023-2024 Aptivi
//
// This file is part of Terminaux
//
// Terminaux is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Terminaux is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY, without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//

using Terminaux.Base;
using Terminaux.Base.Extensions;
using Terminaux.Writer.ConsoleWriters;

namespace Terminaux.Console.Fixtures.Cases.Consoles
{
internal class BeepSynth : IFixture
{
public FixtureCategory Category => FixtureCategory.Console;

public void RunFixture()
{
string synthJson =
"""
{
"name": "Test synth info",
"chapters": [
{
"name": "Chapter 1",
"synths": [
"128 100",
"256 200",
"512 300",
"256 400",
"128 500",
]
},
{
"name": "Chapter 2",
"synths": [
"256 100",
"512 200",
"1024 300",
"512 400",
"256 500",
]
},
]
}
""";
var synthInfo = ConsoleAcoustic.GetSynthInfo(synthJson);
ConsoleAcoustic.PlaySynth(synthInfo);
}
}
}
1 change: 1 addition & 0 deletions Terminaux.Console/Fixtures/FixtureManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ internal static class FixtureManager
new AlternateBuffers(),
new Sizes(),
new BeepTones(),
new BeepSynth(),
new ProgressTest(),
new ProgressFailTest(),
new ProgressWarnFailTest(),
Expand Down
77 changes: 77 additions & 0 deletions Terminaux.Tests/Base/ConsoleExtensionTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//
// Terminaux Copyright (C) 2023-2024 Aptivi
//
// This file is part of Terminaux
//
// Terminaux is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Terminaux is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY, without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Shouldly;
using Terminaux.Base.Extensions;
using Textify.General.Structures;

namespace Terminaux.Tests.Base
{
[TestClass]
public class ConsoleExtensionTests
{
/// <summary>
/// Tests getting synth info from the JSON representation
/// </summary>
[TestMethod]
[Description("Querying")]
public void TestGetSynthInfo()
{
string synthJson =
"""
{
"name": "Test synth info",
"chapters": [
{
"name": "Chapter 1",
"synths": [
"128 100",
"256 200",
"512 300",
"256 400",
"128 500",
]
},
{
"name": "Chapter 2",
"synths": [
"256 100",
"512 200",
"1024 300",
"512 400",
"256 500",
]
},
]
}
""";
var synthInfo = ConsoleAcoustic.GetSynthInfo(synthJson);
synthInfo.ShouldNotBeNull();
synthInfo.Name.ShouldBe("Test synth info");
synthInfo.Chapters.Length.ShouldBe(2);
synthInfo.Chapters[0].Name.ShouldBe("Chapter 1");
synthInfo.Chapters[0].Synths.Length.ShouldBe(5);
synthInfo.Chapters[0].Synths[0].ShouldBe("128 100");
synthInfo.Chapters[1].Name.ShouldBe("Chapter 2");
synthInfo.Chapters[1].Synths.Length.ShouldBe(5);
synthInfo.Chapters[1].Synths[0].ShouldBe("256 100");
}
}
}
77 changes: 77 additions & 0 deletions Terminaux/Base/Extensions/ConsoleAcoustic.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//
// Terminaux Copyright (C) 2023-2024 Aptivi
//
// This file is part of Terminaux
//
// Terminaux is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Terminaux is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY, without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//

using Newtonsoft.Json;
using System.Threading;
using Terminaux.Base.Extensions.Data;

namespace Terminaux.Base.Extensions
{
/// <summary>
/// Sound-related extensions for console
/// </summary>
public static class ConsoleAcoustic
{
private static object synthLock = new();

/// <summary>
/// Gets synth information from the synth JSON representation
/// </summary>
/// <param name="synthJson">Synth JSON representation</param>
/// <returns>An output <see cref="SynthInfo"/> class that contains the necessary information</returns>
/// <exception cref="TerminauxException"></exception>
public static SynthInfo GetSynthInfo(string synthJson)
{
var synthInfo = JsonConvert.DeserializeObject<SynthInfo>(synthJson) ??
throw new TerminauxException("Can't get synth info from the provided representation.");
return synthInfo;
}

/// <summary>
/// Plays the beep synth
/// </summary>
/// <param name="synthInfo">Synth info. You can obtain this from <see cref="GetSynthInfo(string)"/>.</param>
/// <exception cref="TerminauxException"></exception>
public static void PlaySynth(SynthInfo synthInfo)
{
lock (synthLock)
{
for (int i = 0; i < synthInfo.Chapters.Length; i++)
{
SynthInfo.Chapter chapter = synthInfo.Chapters[i];
for (int j = 0; j < chapter.Synths.Length; j++)
{
string synth = chapter.Synths[j];
var split = synth.Split(' ');
if (split.Length != 2)
throw new TerminauxException($"Synth representation is invalid at [{i + 1}.{j + 1}]");
if (!int.TryParse(split[0], out int freq))
throw new TerminauxException($"Frequency is invalid at [{i + 1}.{j + 1}]");
if (!int.TryParse(split[1], out int ms))
throw new TerminauxException($"Duration is invalid at [{i + 1}.{j + 1}]");
if (freq == 0)
Thread.Sleep(ms);
else
ConsoleWrapper.Beep(freq, ms);
}
}
}
}
}
}
69 changes: 69 additions & 0 deletions Terminaux/Base/Extensions/Data/SynthInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//
// Nitrocid KS Copyright (C) 2018-2024 Aptivi
//
// This file is part of Nitrocid KS
//
// Nitrocid KS is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Nitrocid KS is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY, without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//

using Newtonsoft.Json;

namespace Terminaux.Base.Extensions.Data
{
/// <summary>
/// Console synth info
/// </summary>
public class SynthInfo
{
/// <summary>
/// Name of the console synth (usually a music name)
/// </summary>
[JsonProperty("name")]
[JsonRequired]
public string Name { get; set; } = "";

/// <summary>
/// Beep synth chapters
/// </summary>
[JsonProperty("chapters")]
[JsonRequired]
public Chapter[] Chapters { get; set; } = [];

/// <summary>
/// Chapter synthesis class
/// </summary>
public class Chapter
{
/// <summary>
/// Name of the chapter
/// </summary>
[JsonProperty("name")]
[JsonRequired]
public string Name { get; set; } = "";

/// <summary>
/// List of synths in this format: <c>&lt;freq&gt; &lt;ms&gt;</c>
/// </summary>
[JsonProperty("synths")]
[JsonRequired]
public string[] Synths { get; set; } = [];

internal Chapter()
{ }
}

internal SynthInfo()
{ }
}
}

0 comments on commit 8c02821

Please sign in to comment.