Skip to content

Commit 00de2bd

Browse files
dfengpo东风破
and
东风破
authored
Refactor .Net example project (#1049)
Co-authored-by: 东风破 <[email protected]>
1 parent 6b7ced2 commit 00de2bd

File tree

77 files changed

+525
-650
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+525
-650
lines changed

.github/workflows/test-dot-net.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ jobs:
134134
- name: Copy files
135135
shell: bash
136136
run: |
137+
cp -v scripts/dotnet/examples/Common.csproj dotnet-examples/Common/
137138
cp -v scripts/dotnet/examples/offline-tts.csproj dotnet-examples/offline-tts/
138139
cp -v scripts/dotnet/examples/offline-decode-files.csproj dotnet-examples/offline-decode-files/
139140
cp -v scripts/dotnet/examples/online-decode-files.csproj dotnet-examples/online-decode-files/

dotnet-examples/.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
bin
22
obj
3+
v17
4+
.vs
35
!*.sh
6+
*.vsidx

dotnet-examples/Common/Common.csproj

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net6.0</TargetFramework>
5+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
6+
<RestoreSources>/tmp/packages;$(RestoreSources);https://api.nuget.org/v3/index.json</RestoreSources>
7+
</PropertyGroup>
8+
<ItemGroup>
9+
<PackageReference Include="CommandLineParser" Version="2.9.1" />
10+
<PackageReference Include="org.k2fsa.sherpa.onnx" Version="1.10.1" />
11+
</ItemGroup>
12+
13+
</Project>
Original file line numberDiff line numberDiff line change
@@ -1,174 +1,174 @@
1-
// Copyright (c) 2023 Xiaomi Corporation (authors: Fangjun Kuang)
2-
using System;
3-
using System.IO;
4-
5-
using System.Runtime.InteropServices;
6-
7-
namespace SherpaOnnx
8-
{
9-
10-
[StructLayout(LayoutKind.Sequential)]
11-
public struct WaveHeader
12-
{
13-
public Int32 ChunkID;
14-
public Int32 ChunkSize;
15-
public Int32 Format;
16-
public Int32 SubChunk1ID;
17-
public Int32 SubChunk1Size;
18-
public Int16 AudioFormat;
19-
public Int16 NumChannels;
20-
public Int32 SampleRate;
21-
public Int32 ByteRate;
22-
public Int16 BlockAlign;
23-
public Int16 BitsPerSample;
24-
public Int32 SubChunk2ID;
25-
public Int32 SubChunk2Size;
26-
27-
public bool Validate()
28-
{
29-
if (ChunkID != 0x46464952)
30-
{
31-
Console.WriteLine($"Invalid chunk ID: 0x{ChunkID:X}. Expect 0x46464952");
32-
return false;
33-
}
34-
35-
// E V A W
36-
if (Format != 0x45564157)
37-
{
38-
Console.WriteLine($"Invalid format: 0x{Format:X}. Expect 0x45564157");
39-
return false;
40-
}
41-
42-
// t m f
43-
if (SubChunk1ID != 0x20746d66)
44-
{
45-
Console.WriteLine($"Invalid SubChunk1ID: 0x{SubChunk1ID:X}. Expect 0x20746d66");
46-
return false;
47-
}
48-
49-
if (SubChunk1Size != 16)
50-
{
51-
Console.WriteLine($"Invalid SubChunk1Size: {SubChunk1Size}. Expect 16");
52-
return false;
53-
}
54-
55-
if (AudioFormat != 1)
56-
{
57-
Console.WriteLine($"Invalid AudioFormat: {AudioFormat}. Expect 1");
58-
return false;
59-
}
60-
61-
if (NumChannels != 1)
62-
{
63-
Console.WriteLine($"Invalid NumChannels: {NumChannels}. Expect 1");
64-
return false;
65-
}
66-
67-
if (ByteRate != (SampleRate * NumChannels * BitsPerSample / 8))
68-
{
69-
Console.WriteLine($"Invalid byte rate: {ByteRate}.");
70-
return false;
71-
}
72-
73-
if (BlockAlign != (NumChannels * BitsPerSample / 8))
74-
{
75-
Console.WriteLine($"Invalid block align: {ByteRate}.");
76-
return false;
77-
}
78-
79-
if (BitsPerSample != 16)
80-
{ // we support only 16 bits per sample
81-
Console.WriteLine($"Invalid bits per sample: {BitsPerSample}. Expect 16");
82-
return false;
83-
}
84-
85-
return true;
86-
}
87-
}
88-
89-
// It supports only 16-bit, single channel WAVE format.
90-
// The sample rate can be any value.
91-
public class WaveReader
92-
{
93-
public WaveReader(String fileName)
94-
{
95-
if (!File.Exists(fileName))
96-
{
97-
throw new ApplicationException($"{fileName} does not exist!");
98-
}
99-
100-
using (var stream = File.Open(fileName, FileMode.Open))
101-
{
102-
using (var reader = new BinaryReader(stream))
103-
{
104-
_header = ReadHeader(reader);
105-
106-
if (!_header.Validate())
107-
{
108-
throw new ApplicationException($"Invalid wave file ${fileName}");
109-
}
110-
111-
SkipMetaData(reader);
112-
113-
// now read samples
114-
// _header.SubChunk2Size contains number of bytes in total.
115-
// we assume each sample is of type int16
116-
byte[] buffer = reader.ReadBytes(_header.SubChunk2Size);
117-
short[] samples_int16 = new short[_header.SubChunk2Size / 2];
118-
Buffer.BlockCopy(buffer, 0, samples_int16, 0, buffer.Length);
119-
120-
_samples = new float[samples_int16.Length];
121-
122-
for (var i = 0; i < samples_int16.Length; ++i)
123-
{
124-
_samples[i] = samples_int16[i] / 32768.0F;
125-
}
126-
}
127-
}
128-
}
129-
130-
private static WaveHeader ReadHeader(BinaryReader reader)
131-
{
132-
byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(WaveHeader)));
133-
134-
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
135-
WaveHeader header = (WaveHeader)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(WaveHeader))!;
136-
handle.Free();
137-
138-
return header;
139-
}
140-
141-
private void SkipMetaData(BinaryReader reader)
142-
{
143-
var bs = reader.BaseStream;
144-
145-
Int32 subChunk2ID = _header.SubChunk2ID;
146-
Int32 subChunk2Size = _header.SubChunk2Size;
147-
148-
while (bs.Position != bs.Length && subChunk2ID != 0x61746164)
149-
{
150-
bs.Seek(subChunk2Size, SeekOrigin.Current);
151-
subChunk2ID = reader.ReadInt32();
152-
subChunk2Size = reader.ReadInt32();
153-
}
154-
_header.SubChunk2ID = subChunk2ID;
155-
_header.SubChunk2Size = subChunk2Size;
156-
}
157-
158-
private WaveHeader _header;
159-
160-
// Samples are normalized to the range [-1, 1]
161-
private float[] _samples;
162-
163-
public int SampleRate => _header.SampleRate;
164-
public float[] Samples => _samples;
165-
166-
public static void Test(String fileName)
167-
{
168-
WaveReader reader = new WaveReader(fileName);
169-
Console.WriteLine($"samples length: {reader.Samples.Length}");
170-
Console.WriteLine($"samples rate: {reader.SampleRate}");
171-
}
172-
}
173-
174-
}
1+
// Copyright (c) 2023 Xiaomi Corporation (authors: Fangjun Kuang)
2+
using System;
3+
using System.IO;
4+
5+
using System.Runtime.InteropServices;
6+
7+
namespace SherpaOnnx
8+
{
9+
10+
[StructLayout(LayoutKind.Sequential)]
11+
public struct WaveHeader
12+
{
13+
public Int32 ChunkID;
14+
public Int32 ChunkSize;
15+
public Int32 Format;
16+
public Int32 SubChunk1ID;
17+
public Int32 SubChunk1Size;
18+
public Int16 AudioFormat;
19+
public Int16 NumChannels;
20+
public Int32 SampleRate;
21+
public Int32 ByteRate;
22+
public Int16 BlockAlign;
23+
public Int16 BitsPerSample;
24+
public Int32 SubChunk2ID;
25+
public Int32 SubChunk2Size;
26+
27+
public bool Validate()
28+
{
29+
if (ChunkID != 0x46464952)
30+
{
31+
Console.WriteLine($"Invalid chunk ID: 0x{ChunkID:X}. Expect 0x46464952");
32+
return false;
33+
}
34+
35+
// E V A W
36+
if (Format != 0x45564157)
37+
{
38+
Console.WriteLine($"Invalid format: 0x{Format:X}. Expect 0x45564157");
39+
return false;
40+
}
41+
42+
// t m f
43+
if (SubChunk1ID != 0x20746d66)
44+
{
45+
Console.WriteLine($"Invalid SubChunk1ID: 0x{SubChunk1ID:X}. Expect 0x20746d66");
46+
return false;
47+
}
48+
49+
if (SubChunk1Size != 16)
50+
{
51+
Console.WriteLine($"Invalid SubChunk1Size: {SubChunk1Size}. Expect 16");
52+
return false;
53+
}
54+
55+
if (AudioFormat != 1)
56+
{
57+
Console.WriteLine($"Invalid AudioFormat: {AudioFormat}. Expect 1");
58+
return false;
59+
}
60+
61+
if (NumChannels != 1)
62+
{
63+
Console.WriteLine($"Invalid NumChannels: {NumChannels}. Expect 1");
64+
return false;
65+
}
66+
67+
if (ByteRate != (SampleRate * NumChannels * BitsPerSample / 8))
68+
{
69+
Console.WriteLine($"Invalid byte rate: {ByteRate}.");
70+
return false;
71+
}
72+
73+
if (BlockAlign != (NumChannels * BitsPerSample / 8))
74+
{
75+
Console.WriteLine($"Invalid block align: {ByteRate}.");
76+
return false;
77+
}
78+
79+
if (BitsPerSample != 16)
80+
{ // we support only 16 bits per sample
81+
Console.WriteLine($"Invalid bits per sample: {BitsPerSample}. Expect 16");
82+
return false;
83+
}
84+
85+
return true;
86+
}
87+
}
88+
89+
// It supports only 16-bit, single channel WAVE format.
90+
// The sample rate can be any value.
91+
public class WaveReader
92+
{
93+
public WaveReader(String fileName)
94+
{
95+
if (!File.Exists(fileName))
96+
{
97+
throw new ApplicationException($"{fileName} does not exist!");
98+
}
99+
100+
using (var stream = File.Open(fileName, FileMode.Open))
101+
{
102+
using (var reader = new BinaryReader(stream))
103+
{
104+
_header = ReadHeader(reader);
105+
106+
if (!_header.Validate())
107+
{
108+
throw new ApplicationException($"Invalid wave file ${fileName}");
109+
}
110+
111+
SkipMetaData(reader);
112+
113+
// now read samples
114+
// _header.SubChunk2Size contains number of bytes in total.
115+
// we assume each sample is of type int16
116+
byte[] buffer = reader.ReadBytes(_header.SubChunk2Size);
117+
short[] samples_int16 = new short[_header.SubChunk2Size / 2];
118+
Buffer.BlockCopy(buffer, 0, samples_int16, 0, buffer.Length);
119+
120+
_samples = new float[samples_int16.Length];
121+
122+
for (var i = 0; i < samples_int16.Length; ++i)
123+
{
124+
_samples[i] = samples_int16[i] / 32768.0F;
125+
}
126+
}
127+
}
128+
}
129+
130+
private static WaveHeader ReadHeader(BinaryReader reader)
131+
{
132+
byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(WaveHeader)));
133+
134+
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
135+
WaveHeader header = (WaveHeader)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(WaveHeader))!;
136+
handle.Free();
137+
138+
return header;
139+
}
140+
141+
private void SkipMetaData(BinaryReader reader)
142+
{
143+
var bs = reader.BaseStream;
144+
145+
Int32 subChunk2ID = _header.SubChunk2ID;
146+
Int32 subChunk2Size = _header.SubChunk2Size;
147+
148+
while (bs.Position != bs.Length && subChunk2ID != 0x61746164)
149+
{
150+
bs.Seek(subChunk2Size, SeekOrigin.Current);
151+
subChunk2ID = reader.ReadInt32();
152+
subChunk2Size = reader.ReadInt32();
153+
}
154+
_header.SubChunk2ID = subChunk2ID;
155+
_header.SubChunk2Size = subChunk2Size;
156+
}
157+
158+
private WaveHeader _header;
159+
160+
// Samples are normalized to the range [-1, 1]
161+
private float[] _samples;
162+
163+
public int SampleRate => _header.SampleRate;
164+
public float[] Samples => _samples;
165+
166+
public static void Test(String fileName)
167+
{
168+
WaveReader reader = new WaveReader(fileName);
169+
Console.WriteLine($"samples length: {reader.Samples.Length}");
170+
Console.WriteLine($"samples rate: {reader.SampleRate}");
171+
}
172+
}
173+
174+
}

dotnet-examples/offline-decode-files/WaveReader.cs

-1
This file was deleted.

dotnet-examples/offline-decode-files/offline-decode-files.csproj

+1-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@
99
</PropertyGroup>
1010

1111
<ItemGroup>
12-
<PackageReference Include="CommandLineParser" Version="2.9.1" />
13-
<PackageReference Include="org.k2fsa.sherpa.onnx" Version="*" />
12+
<ProjectReference Include="..\Common\Common.csproj" />
1413
</ItemGroup>
1514

1615
</Project>

0 commit comments

Comments
 (0)