1
0
mirror of https://github.com/Picovoice/porcupine.git synced 2022-01-28 03:27:53 +03:00

Github actions dotnet add platforms and non-English tests (#607)

This commit is contained in:
Iliad Ramezani
2021-12-29 15:20:55 -08:00
committed by GitHub
parent 7f55e64654
commit 10dfa18c9f
2 changed files with 244 additions and 63 deletions

View File

@@ -45,8 +45,12 @@ defaults:
working-directory: binding/dotnet
jobs:
build:
runs-on: ubuntu-latest
build-github-hosted:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
steps:
- uses: actions/checkout@v2
@@ -69,3 +73,22 @@ jobs:
- name: Test
run: dotnet test -- TestRunParameters.Parameter\(name=\"pvTestAccessKey\",\ value=\"${{secrets.PV_VALID_ACCESS_KEY}}\"\)
build-self-hosted:
runs-on: ${{ matrix.machine }}
strategy:
matrix:
machine: [rpi2, rpi3, rpi4, jetson, beaglebone]
steps:
- uses: actions/checkout@v2
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore
- name: Test
run: dotnet test -- TestRunParameters.Parameter\(name=\"pvTestAccessKey\",\ value=\"${{secrets.PV_VALID_ACCESS_KEY}}\"\)

View File

@@ -11,8 +11,10 @@
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Pv;
@@ -23,6 +25,35 @@ namespace PorcupineTest
public class MainTest
{
private static string ACCESS_KEY;
private static string _relativeDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
private static Architecture _arch => RuntimeInformation.ProcessArchitecture;
private static string _env => RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "mac" :
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "windows" :
RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && _arch == Architecture.X64 ? "linux" :
RuntimeInformation.IsOSPlatform(OSPlatform.Linux) &&
(_arch == Architecture.Arm || _arch == Architecture.Arm64) ? PvLinuxEnv() : "";
private Porcupine porcupine;
private static string PvLinuxEnv()
{
string cpuInfo = File.ReadAllText("/proc/cpuinfo");
string[] cpuPartList = cpuInfo.Split('\n').Where(x => x.Contains("CPU part")).ToArray();
if (cpuPartList.Length == 0)
throw new PlatformNotSupportedException($"Unsupported CPU.\n{cpuInfo}");
string cpuPart = cpuPartList[0].Split(' ').Last().ToLower();
switch (cpuPart)
{
case "0xc07":
case "0xd03":
case "0xd08": return "raspberry-pi";
case "0xd07": return "jetson";
case "0xc08": return "beaglebone";
default:
throw new PlatformNotSupportedException($"This device (CPU part = {cpuPart}) is not supported by Picovoice.");
}
}
[ClassInitialize]
public static void ClassInitialize(TestContext testContext)
@@ -33,28 +64,48 @@ namespace PorcupineTest
}
}
[TestMethod]
public void TestFrameLength()
private static string AppendLanguage(string s, string language)
{
using Porcupine p = Porcupine.FromBuiltInKeywords(ACCESS_KEY, new List<BuiltInKeyword> { BuiltInKeyword.PORCUPINE });
Assert.IsTrue(p.FrameLength > 0, "Specified frame length was not a valid number.");
if(language == "en")
return s;
return $"{s}_{language}";
}
[TestMethod]
public void TestVersion()
private static string GetKeywordPath(string language, string keyword)
{
using Porcupine p = Porcupine.FromBuiltInKeywords(ACCESS_KEY, new List<BuiltInKeyword> { BuiltInKeyword.PORCUPINE });
Assert.IsFalse(string.IsNullOrWhiteSpace(p.Version), "Porcupine did not return a valid version number.");
return Path.Combine(
_relativeDir,
"../../../../../../resources",
AppendLanguage("keyword_files", language),
$"{_env}/{keyword}_{_env}.ppn"
);
}
[TestMethod]
public void TestProcess()
private static List<string> GetKeywordPaths(string language, List<string> keywords)
{
using Porcupine p = Porcupine.FromBuiltInKeywords(ACCESS_KEY, new List<BuiltInKeyword> { BuiltInKeyword.PORCUPINE });
int frameLen = p.FrameLength;
List<string> keywordPaths = new List<string>();
foreach (string keyword in keywords)
{
keywordPaths.Add(GetKeywordPath(language, keyword));
}
return keywordPaths;
}
string testAudioPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "resources/audio_samples/porcupine.wav");
List<short> data = GetPcmFromFile(testAudioPath, p.SampleRate);
private static string GetModelPath(string language)
{
string file_name = AppendLanguage("porcupine_params", language);
return Path.Combine(
_relativeDir,
"../../../../../../lib/common",
$"{file_name}.pv"
);
}
private void RunTestCase(string audioFileName, List<int> expectedResults)
{
int frameLen = porcupine.FrameLength;
string testAudioPath = Path.Combine(_relativeDir, "resources/audio_samples", audioFileName);
List<short> data = GetPcmFromFile(testAudioPath, porcupine.SampleRate);
int framecount = (int)Math.Floor((float)(data.Count / frameLen));
var results = new List<int>();
@@ -63,20 +114,50 @@ namespace PorcupineTest
int start = i * frameLen;
int count = frameLen;
List<short> frame = data.GetRange(start, count);
int result = p.Process(frame.ToArray());
Assert.IsTrue(result == -1 || result == 0, "Porcupine returned an unexpected result (should return 0 or -1)");
int result = porcupine.Process(frame.ToArray());
Assert.IsTrue(result >= -1, "Porcupine returned an unexpected result (<-1)");
if (result >= 0)
{
results.Add(result);
}
}
Assert.IsTrue(results.Count == 1 && results[0] == 0, "Expected to find keyword 'porcupine', but no keyword was detected.");
p.Dispose();
Assert.AreEqual(expectedResults.Count, results.Count, $"Should have found {expectedResults.Count} keywords, but {results.Count} were found.");
for (int i = 0; i < results.Count; i++)
{
Assert.AreEqual(expectedResults[i], results[i], $"Expected keyword {expectedResults[i]}, but Porcupine detected keyword {results[i]}.");
}
porcupine.Dispose();
}
[TestMethod]
public void TestProcessMultiple()
public void TestFrameLength()
{
porcupine = Porcupine.FromBuiltInKeywords(ACCESS_KEY, new List<BuiltInKeyword> { BuiltInKeyword.PORCUPINE });
Assert.IsTrue(porcupine.FrameLength > 0, "Specified frame length was not a valid number.");
porcupine.Dispose();
}
[TestMethod]
public void TestVersion()
{
porcupine = Porcupine.FromBuiltInKeywords(ACCESS_KEY, new List<BuiltInKeyword> { BuiltInKeyword.PORCUPINE });
Assert.IsFalse(string.IsNullOrWhiteSpace(porcupine.Version), "Porcupine did not return a valid version number.");
porcupine.Dispose();
}
[TestMethod]
public void TestSingleKeyword()
{
porcupine = Porcupine.FromBuiltInKeywords(ACCESS_KEY, new List<BuiltInKeyword> { BuiltInKeyword.PORCUPINE });
RunTestCase(
"porcupine.wav",
new List<int>() {0});
}
[TestMethod]
public void TestMultipleKeyword()
{
List<BuiltInKeyword> inputKeywords = new List<BuiltInKeyword>
{
@@ -90,54 +171,131 @@ namespace PorcupineTest
BuiltInKeyword.PORCUPINE,
BuiltInKeyword.TERMINATOR
};
porcupine = Porcupine.FromBuiltInKeywords(ACCESS_KEY, inputKeywords);
RunTestCase(
"multiple_keywords.wav",
new List<int>() {7, 0, 1, 2, 3, 4, 5, 6, 7, 8});
}
List<BuiltInKeyword> expectedResults = new List<BuiltInKeyword>() {
BuiltInKeyword.PORCUPINE,
BuiltInKeyword.ALEXA,
BuiltInKeyword.AMERICANO,
BuiltInKeyword.BLUEBERRY,
BuiltInKeyword.BUMBLEBEE,
BuiltInKeyword.GRAPEFRUIT,
BuiltInKeyword.GRASSHOPPER,
BuiltInKeyword.PICOVOICE,
BuiltInKeyword.PORCUPINE,
BuiltInKeyword.TERMINATOR
[TestMethod]
public void TestSingleKeywordDe()
{
string language = "de";
List<string> keywords = new List<string>() {"heuschrecke"};
porcupine = Porcupine.FromKeywordPaths(
ACCESS_KEY,
GetKeywordPaths(language, keywords),
GetModelPath(language)
);
RunTestCase(
"heuschrecke.wav",
new List<int>() {0});
}
[TestMethod]
public void TestMultipleKeywordDe()
{
string language = "de";
List<string> keywords = new List<string>() {
"heuschrecke",
"ananas",
"leguan",
"stachelschwein"
};
Porcupine p = Porcupine.FromBuiltInKeywords(ACCESS_KEY, inputKeywords);
int frameLen = p.FrameLength;
porcupine = Porcupine.FromKeywordPaths(
ACCESS_KEY,
GetKeywordPaths(language, keywords),
GetModelPath(language)
);
string testAudioPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "resources/audio_samples/multiple_keywords.wav");
List<short> data = GetPcmFromFile(testAudioPath, p.SampleRate);
int framecount = (int)Math.Floor((float)(data.Count / frameLen));
var results = new List<int>();
for (int i = 0; i < framecount; i++)
{
int start = i * frameLen;
int count = frameLen;
List<short> frame = data.GetRange(start, count);
int result = p.Process(frame.ToArray());
Assert.IsTrue(result >= -1, "Porcupine returned an unexpected result (<-1)");
if (result >= 0)
{
results.Add(result);
}
}
Assert.AreEqual(expectedResults.Count, results.Count, $"Should have found {expectedResults.Count} keywords, but {results.Count} were found.");
for (int i = 0; i < results.Count; i++)
{
Assert.AreEqual(
expectedResults[i],
inputKeywords[results[i]],
$"Expected '{expectedResults[i]}', but '{inputKeywords[results[i]]}' was detected.");
}
p.Dispose();
RunTestCase(
"multiple_keywords_de.wav",
new List<int>() {1, 0, 2, 3});
}
[TestMethod]
public void TestSingleKeywordEs()
{
string language = "es";
List<string> keywords = new List<string>() {
"manzana"
};
porcupine = Porcupine.FromKeywordPaths(
ACCESS_KEY,
GetKeywordPaths(language, keywords),
GetModelPath(language)
);
RunTestCase(
"manzana.wav",
new List<int>() {0});
}
[TestMethod]
public void TestMultipleKeywordEs()
{
string language = "es";
List<string> keywords = new List<string>() {
"emparedado",
"leopardo",
"manzana"
};
porcupine = Porcupine.FromKeywordPaths(
ACCESS_KEY,
GetKeywordPaths(language, keywords),
GetModelPath(language)
);
RunTestCase(
"multiple_keywords_es.wav",
new List<int>() {0, 1, 2});
}
[TestMethod]
public void TestSingleKeywordFr()
{
string language = "fr";
List<string> keywords = new List<string>() {
"mon chouchou"
};
porcupine = Porcupine.FromKeywordPaths(
ACCESS_KEY,
GetKeywordPaths(language, keywords),
GetModelPath(language)
);
RunTestCase(
"mon_chouchou.wav",
new List<int>() {0});
}
[TestMethod]
public void TestMultipleKeywordFr()
{
string language = "fr";
List<string> keywords = new List<string>() {
"framboise",
"mon chouchou",
"parapluie"
};
porcupine = Porcupine.FromKeywordPaths(
ACCESS_KEY,
GetKeywordPaths(language, keywords),
GetModelPath(language)
);
RunTestCase(
"multiple_keywords_fr.wav",
new List<int>() {0, 1, 0, 2});
}
private List<short> GetPcmFromFile(string audioFilePath, int expectedSampleRate)
{
List<short> data = new List<short>();