Skip to content

Commit

Permalink
.NET 2 support fix (#1079)
Browse files Browse the repository at this point in the history
  • Loading branch information
laves authored Aug 23, 2023
1 parent feb2b57 commit 6296221
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 135 deletions.
2 changes: 1 addition & 1 deletion binding/dotnet/Porcupine/Porcupine.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFrameworks>net6.0;netcoreapp3.0;netstandard2.0</TargetFrameworks>
<Version>2.2.1</Version>
<Version>2.2.2</Version>
<Authors>Picovoice</Authors>
<Company />
<Product>Porcupine Wake Word Engine</Product>
Expand Down
29 changes: 17 additions & 12 deletions binding/dotnet/Porcupine/Porcupine.netstandard2.0.targets
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Content Include="$(MSBuildThisFileDirectory)../../lib/netstandard2.0/Porcupine.dll">
<Link>Porcupine.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Visible>False</Visible>
</Content>
<Content Include="$(MSBuildThisFileDirectory)libpv_porcupine.dll">
<Link>libpv_porcupine.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
Expand All @@ -14,17 +19,17 @@
<Link>libpv_porcupine.so</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Visible>false</Visible>
</Content>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="$(MSBuildThisFileDirectory)resources/**">
<Link>resources/%(RecursiveDir)%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)lib/**">
<Link>lib/%(RecursiveDir)%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Visible>false</Visible>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="$(MSBuildThisFileDirectory)resources/**">
<Link>resources/%(RecursiveDir)%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)lib/**">
<Link>lib/%(RecursiveDir)%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Visible>false</Visible>
</Content>
</ItemGroup>
</Project>
22 changes: 11 additions & 11 deletions binding/dotnet/Porcupine/Porcupine.targets
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Content Include="$(MSBuildThisFileDirectory)resources/**">
<Link>resources/%(RecursiveDir)%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)lib/**">
<Link>lib/%(RecursiveDir)%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Visible>false</Visible>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="$(MSBuildThisFileDirectory)resources/**">
<Link>resources/%(RecursiveDir)%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="$(MSBuildThisFileDirectory)lib/**">
<Link>lib/%(RecursiveDir)%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Visible>false</Visible>
</Content>
</ItemGroup>
</Project>
77 changes: 34 additions & 43 deletions demo/dotnet/PorcupineDemo/FileDemo.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2020-2022 Picovoice Inc.
Copyright 2020-2023 Picovoice Inc.
You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE"
file accompanying this source.
Expand Down Expand Up @@ -50,59 +50,50 @@ public static void RunDemo(
List<string> keywords,
List<float> sensitivities)
{
Porcupine porcupine = null;
try
// init porcupine wake word engine
using (Porcupine porcupine = Porcupine.FromKeywordPaths(accessKey, keywordPaths, modelPath, sensitivities))
{
// init porcupine wake word engine
porcupine = Porcupine.FromKeywordPaths(
accessKey,
keywordPaths,
modelPath,
sensitivities);

// get keyword names for labeling detection results
List<string> keywordNames = keywordPaths.Select(k => Path.GetFileNameWithoutExtension(k).Split("_")[0]).ToList();

using BinaryReader reader = new BinaryReader(File.Open(inputAudioPath, FileMode.Open));
ValidateWavFile(reader, porcupine.SampleRate, 16, out short numChannels);

// read audio and send frames to porcupine
short[] porcupineFrame = new short[porcupine.FrameLength];
int frameIndex = 0;
long totalSamplesRead = 0;

Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
while (reader.BaseStream.Position != reader.BaseStream.Length)
using (BinaryReader reader = new BinaryReader(File.Open(inputAudioPath, FileMode.Open)))
{
totalSamplesRead++;
porcupineFrame[frameIndex++] = reader.ReadInt16();
ValidateWavFile(reader, porcupine.SampleRate, 16, out short numChannels);

if (frameIndex == porcupineFrame.Length)
// read audio and send frames to porcupine
short[] porcupineFrame = new short[porcupine.FrameLength];
int frameIndex = 0;
long totalSamplesRead = 0;

Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
while (reader.BaseStream.Position != reader.BaseStream.Length)
{
int result = porcupine.Process(porcupineFrame);
if (result >= 0)
totalSamplesRead++;
porcupineFrame[frameIndex++] = reader.ReadInt16();

if (frameIndex == porcupineFrame.Length)
{
Console.WriteLine($"Detected {keywords[result]} at " +
$"{Math.Round(totalSamplesRead / (double)porcupine.SampleRate, 2)} sec");
int result = porcupine.Process(porcupineFrame);
if (result >= 0)
{
Console.WriteLine($"Detected {keywords[result]} at " +
$"{Math.Round(totalSamplesRead / (double)porcupine.SampleRate, 2)} sec");
}
frameIndex = 0;
}
frameIndex = 0;
}

// skip right channel
if (numChannels == 2)
{
_ = reader.ReadInt16();
// skip right channel
if (numChannels == 2)
{
_ = reader.ReadInt16();
}
}
stopWatch.Stop();
double audioLen = Math.Round(totalSamplesRead / (double)porcupine.SampleRate, 2);
double realtimeFactor = Math.Round(audioLen / stopWatch.Elapsed.TotalSeconds, 2);
Console.WriteLine($"Realtime factor: {realtimeFactor}x");
}
stopWatch.Stop();
double audioLen = Math.Round(totalSamplesRead / (double)porcupine.SampleRate, 2);
double realtimeFactor = Math.Round(audioLen / stopWatch.Elapsed.TotalSeconds, 2);
Console.WriteLine($"Realtime factor: {realtimeFactor}x");
}
finally
{
porcupine?.Dispose();
}
}

Expand Down Expand Up @@ -254,7 +245,7 @@ public static void Main(string[] args)
if (!Enum.TryParse(typeof(BuiltInKeyword), k.ToUpper().Replace(" ", "_"), out object builtin))
{
throw new ArgumentException($"Keyword '{k}' is not a valid built-in keyword. Available built-ins are: " +
$"{string.Join(",", Enum.GetNames(typeof(BuiltInKeyword)).Select(k => k.ToLower().Replace("_", " ")))}");
$"{string.Join(",", Enum.GetNames(typeof(BuiltInKeyword)).Select(x => x.ToLower().Replace("_", " ")))}");
}
else
{
Expand Down
102 changes: 52 additions & 50 deletions demo/dotnet/PorcupineDemo/MicDemo.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2020-2022 Picovoice Inc.
Copyright 2020-2023 Picovoice Inc.
You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE"
file accompanying this source.
Expand Down Expand Up @@ -48,64 +48,66 @@ public static void RunDemo(
int audioDeviceIndex,
string outputPath = null)
{
// init porcupine wake word engine
using Porcupine porcupine = Porcupine.FromKeywordPaths(accessKey, keywordPaths, modelPath, sensitivities);
using (Porcupine porcupine = Porcupine.FromKeywordPaths(accessKey, keywordPaths, modelPath, sensitivities))
{
// get keyword names for labeling detection results
List<string> keywordNames = keywordPaths.Select(k => Path.GetFileNameWithoutExtension(k).Split("_")[0]).ToList();

// get keyword names for labeling detection results
List<string> keywordNames = keywordPaths.Select(k => Path.GetFileNameWithoutExtension(k).Split("_")[0]).ToList();
// create recorder
using (PvRecorder recorder = PvRecorder.Create(frameLength: porcupine.FrameLength, deviceIndex: audioDeviceIndex))
{
Console.WriteLine($"Using device: {recorder.SelectedDevice}");
Console.CancelKeyPress += delegate (object sender, ConsoleCancelEventArgs e)
{
e.Cancel = true;
recorder.Stop();
Console.WriteLine("Stopping...");
};

// create recorder
using PvRecorder recorder = PvRecorder.Create(frameLength: porcupine.FrameLength, deviceIndex: audioDeviceIndex);
Console.WriteLine($"Using device: {recorder.SelectedDevice}");
Console.CancelKeyPress += delegate (object sender, ConsoleCancelEventArgs e)
{
e.Cancel = true;
recorder.Stop();
Console.WriteLine("Stopping...");
};
// open stream to output file
BinaryWriter outputFileWriter = null;
int totalSamplesWritten = 0;
if (!string.IsNullOrWhiteSpace(outputPath))
{
outputFileWriter = new BinaryWriter(new FileStream(outputPath, FileMode.OpenOrCreate, FileAccess.Write));
WriteWavHeader(outputFileWriter, 1, 16, recorder.SampleRate, 0);
}

// open stream to output file
BinaryWriter outputFileWriter = null;
int totalSamplesWritten = 0;
if (!string.IsNullOrWhiteSpace(outputPath))
{
outputFileWriter = new BinaryWriter(new FileStream(outputPath, FileMode.OpenOrCreate, FileAccess.Write));
WriteWavHeader(outputFileWriter, 1, 16, recorder.SampleRate, 0);
}
// start recording
Console.Write($"Listening for [{string.Join(' ', keywordNames.Select(k => $"'{k}'"))}]...\n");
recorder.Start();

// start recording
Console.Write($"Listening for [{string.Join(' ', keywordNames.Select(k => $"'{k}'"))}]...\n");
recorder.Start();
while (recorder.IsRecording)
{
short[] frame = recorder.Read();

while (recorder.IsRecording)
{
short[] frame = recorder.Read();
int result = porcupine.Process(frame);
if (result >= 0)
{
Console.WriteLine($"[{DateTime.Now.ToLongTimeString()}] Detected '{keywordNames[result]}'");
}

int result = porcupine.Process(frame);
if (result >= 0)
{
Console.WriteLine($"[{DateTime.Now.ToLongTimeString()}] Detected '{keywordNames[result]}'");
}
if (outputFileWriter != null)
{
foreach (short sample in frame)
{
outputFileWriter.Write(sample);
}
totalSamplesWritten += frame.Length;
}

if (outputFileWriter != null)
{
foreach (short sample in frame)
Thread.Yield();
}

if (outputFileWriter != null)
{
outputFileWriter.Write(sample);
// write size to header and clean up
WriteWavHeader(outputFileWriter, 1, 16, recorder.SampleRate, totalSamplesWritten);
outputFileWriter.Flush();
outputFileWriter.Dispose();
Console.Write($"Wrote audio to '{outputPath}'");
}
totalSamplesWritten += frame.Length;
}

Thread.Yield();
}

if (outputFileWriter != null)
{
// write size to header and clean up
WriteWavHeader(outputFileWriter, 1, 16, recorder.SampleRate, totalSamplesWritten);
outputFileWriter.Flush();
outputFileWriter.Dispose();
Console.Write($"Wrote audio to '{outputPath}'");
}
}

Expand Down Expand Up @@ -280,7 +282,7 @@ public static void Main(string[] args)
if (!Enum.TryParse(typeof(BuiltInKeyword), k.ToUpper().Replace(" ", "_"), out object builtin))
{
throw new ArgumentException($"Keyword '{k}' is not a valid built-in keyword. Available built-ins are: " +
$"{string.Join(",", Enum.GetNames(typeof(BuiltInKeyword)).Select(k => k.ToLower().Replace("_", " ")))}");
$"{string.Join(",", Enum.GetNames(typeof(BuiltInKeyword)).Select(x => x.ToLower().Replace("_", " ")))}");
}
else
{
Expand Down
36 changes: 18 additions & 18 deletions demo/dotnet/PorcupineDemo/PorcupineDemo.csproj
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<Configurations>FileDemo.Debug;FileDemo.Release;MicDemo.Debug;MicDemo.Release</Configurations>
</PropertyGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<Configurations>FileDemo.Debug;FileDemo.Release;MicDemo.Debug;MicDemo.Release</Configurations>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)' == 'FileDemo.Debug' Or '$(Configuration)' == 'FileDemo.Release'">
<StartupObject>PorcupineDemo.FileDemo</StartupObject>
<TargetName>PorcupineFileDemo</TargetName>
<AssemblyName>PorcupineFileDemo</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'FileDemo.Debug' Or '$(Configuration)' == 'FileDemo.Release'">
<StartupObject>PorcupineDemo.FileDemo</StartupObject>
<TargetName>PorcupineFileDemo</TargetName>
<AssemblyName>PorcupineFileDemo</AssemblyName>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)' == 'MicDemo.Debug' Or '$(Configuration)' == 'MicDemo.Release'">
<StartupObject>PorcupineDemo.MicDemo</StartupObject>
<TargetName>PorcupineMicDemo</TargetName>
<AssemblyName>PorcupineMicDemo</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'MicDemo.Debug' Or '$(Configuration)' == 'MicDemo.Release'">
<StartupObject>PorcupineDemo.MicDemo</StartupObject>
<TargetName>PorcupineMicDemo</TargetName>
<AssemblyName>PorcupineMicDemo</AssemblyName>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Porcupine" Version="2.2.1" />
<ItemGroup>
<PackageReference Include="Porcupine" Version="2.2.2" />
<PackageReference Include="PvRecorder" Version="1.2.1" />
</ItemGroup>
</ItemGroup>
</Project>

0 comments on commit 6296221

Please sign in to comment.