@mentra/bluetooth-sdk 0.1.8 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -18
- package/android/build.gradle +289 -16
- package/android/gradle.properties.example +9 -0
- package/android/lc3Lib/build.gradle +95 -6
- package/android/settings.gradle +3 -0
- package/android/silero/LICENSE.md +17 -0
- package/android/silero/build.gradle +42 -0
- package/android/silero/proguard-rules.pro +24 -0
- package/android/silero/src/androidTest/assets/hello.wav +0 -0
- package/android/silero/src/androidTest/java/com/konovalov/vad/silero/VadSileroTest.kt +79 -0
- package/android/silero/src/main/assets/LICENSE +21 -0
- package/android/silero/src/main/assets/silero_vad.onnx +0 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/Vad.kt +160 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/VadSilero.kt +449 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/config/FrameSize.kt +15 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/config/Mode.kt +14 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/config/SampleRate.kt +12 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/utils/AudioUtils.kt +47 -0
- package/android/silero/src/main/java/com/konovalov/vad/silero/utils/TensorMap.kt +41 -0
- package/android/silero/src/test/java/com/konovalov/vad/silero/utils/AudioUtilsTest.kt +44 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkDefaults.kt +6 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkModule.kt +165 -27
- package/android/src/main/java/com/mentra/bluetoothsdk/Bridge.kt +89 -21
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceManager.kt +189 -16
- package/android/src/main/java/com/mentra/bluetoothsdk/DeviceStore.kt +22 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdk.kt +787 -85
- package/android/src/main/java/com/mentra/bluetoothsdk/audio/AudioModels.kt +6 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/camera/CameraModels.kt +123 -10
- package/android/src/main/java/com/mentra/bluetoothsdk/controllers/ControllerManager.kt +12 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/controllers/R1.kt +8 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/debug/BleTraceLogger.kt +33 -17
- package/android/src/main/java/com/mentra/bluetoothsdk/events/BluetoothEvents.kt +101 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/internal/MapParsing.kt +8 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/photoreceiver/LocalPhotoReceiverRegistry.java +108 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/photoreceiver/LocalPhotoUploadServer.kt +399 -74
- package/android/src/main/java/com/mentra/bluetoothsdk/photoreceiver/MentraPhotoReceiverModule.kt +100 -17
- package/android/src/main/java/com/mentra/bluetoothsdk/requests/DisplayRequests.kt +17 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G1.java +2 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G2.kt +569 -220
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Mach1.java +2 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLive.java +271 -66
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraNex.kt +176 -104
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraosBle.java +12753 -27036
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/SGCManager.kt +54 -2
- package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Simulated.kt +16 -4
- package/android/src/main/java/com/mentra/bluetoothsdk/status/DeviceStatus.kt +60 -3
- package/android/src/main/java/com/mentra/bluetoothsdk/streaming/StreamModels.kt +12 -3
- package/android/src/main/java/com/mentra/bluetoothsdk/stt/STTTools.kt +87 -36
- package/android/src/main/java/com/mentra/bluetoothsdk/stt/SherpaOnnxTranscriber.kt +13 -4
- package/android/src/main/java/com/mentra/bluetoothsdk/stt/VadGateSpeechPolicy.kt +229 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/tts/TTSTools.kt +180 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/AvifExifStripper.java +573 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/BlePhotoUploadService.java +488 -50
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/HeifExifTagReader.java +199 -0
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/MessageChunkReassembler.java +18 -1
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/MessageChunker.java +64 -18
- package/android/src/main/java/com/mentra/bluetoothsdk/utils/NexSGCUtils.kt +48 -39
- package/android/src/test/java/com/mentra/bluetoothsdk/camera/PhotoRequestTest.kt +23 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/photoreceiver/LocalPhotoReceiverRegistryTest.java +75 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/utils/AvifExifStripperTest.java +30 -0
- package/android/src/test/java/com/mentra/bluetoothsdk/utils/BlePhotoUploadServiceTest.java +98 -0
- package/android/src/test/resources/avif_with_exif.avif +0 -0
- package/build/BluetoothSdk.types.d.ts +241 -43
- package/build/BluetoothSdk.types.d.ts.map +1 -1
- package/build/BluetoothSdk.types.js +11 -10
- package/build/BluetoothSdk.types.js.map +1 -1
- package/build/_private/BluetoothSdkModule.d.ts +36 -23
- package/build/_private/BluetoothSdkModule.d.ts.map +1 -1
- package/build/_private/BluetoothSdkModule.js +30 -52
- package/build/_private/BluetoothSdkModule.js.map +1 -1
- package/build/_private/photoRequestPayload.d.ts +4 -0
- package/build/_private/photoRequestPayload.d.ts.map +1 -0
- package/build/_private/photoRequestPayload.js +25 -0
- package/build/_private/photoRequestPayload.js.map +1 -0
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +23 -0
- package/build/index.js.map +1 -1
- package/build/react/useMentraBluetooth.d.ts +2 -2
- package/build/react/useMentraBluetooth.d.ts.map +1 -1
- package/build/react/useMentraBluetooth.js +3 -3
- package/build/react/useMentraBluetooth.js.map +1 -1
- package/ios/BluetoothSdkModule.swift +174 -70
- package/ios/LocalPhotoUploadServer.swift +370 -105
- package/ios/MentraBluetoothSDK.podspec +3 -1
- package/ios/MentraPhotoReceiverModule.swift +62 -10
- package/ios/Packages/CoreObjC/include/PcmConverter.h +22 -0
- package/ios/Packages/SherpaOnnx/SherpaOnnx.swift +668 -26
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Info.plist +13 -9
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/Headers/sherpa-onnx/c-api/c-api.h +4551 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/Headers/sherpa-onnx/c-api/cxx-api.h +1745 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/libsherpa-onnx.a +0 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/Headers/sherpa-onnx/c-api/c-api.h +4551 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/Headers/sherpa-onnx/c-api/cxx-api.h +1745 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/libsherpa-onnx.a +0 -0
- package/ios/Source/BluetoothSdkDefaults.swift +6 -0
- package/ios/Source/Bridge.swift +58 -19
- package/ios/Source/DeviceManager.swift +149 -17
- package/ios/Source/DeviceStore.swift +16 -6
- package/ios/Source/MentraBluetoothSDK.swift +803 -47
- package/ios/Source/ObservableStore.swift +8 -2
- package/ios/Source/{Audio → audio}/AudioModels.swift +9 -7
- package/ios/Source/{Camera → camera}/CameraModels.swift +225 -16
- package/ios/Source/controllers/ControllerManager.swift +4 -3
- package/ios/Source/controllers/R1.swift +3 -3
- package/ios/Source/{Events → events}/BluetoothEvents.swift +183 -1
- package/ios/Source/{Internal → internal}/ValueParsing.swift +10 -1
- package/ios/Source/{Requests → requests}/DisplayRequests.swift +28 -4
- package/ios/Source/services/PhoneMic.swift +1 -0
- package/ios/Source/sgcs/G1.swift +2 -2
- package/ios/Source/sgcs/G2.swift +645 -403
- package/ios/Source/sgcs/Mach1.swift +2 -2
- package/ios/Source/sgcs/MentraLive.swift +812 -319
- package/ios/Source/sgcs/MentraNex.swift +412 -182
- package/ios/Source/sgcs/SGCManager.swift +57 -3
- package/ios/Source/sgcs/Simulated.swift +7 -3
- package/ios/Source/sgcs/mentraos_ble.pb.swift +3073 -3134
- package/ios/Source/status/DeviceStatus.swift +974 -0
- package/ios/Source/{Status → status}/WifiHotspotStatus.swift +4 -4
- package/ios/Source/{Streaming → streaming}/StreamModels.swift +24 -9
- package/ios/Source/stt/STTTools.swift +27 -12
- package/ios/Source/stt/SherpaOnnxTranscriber.swift +31 -8
- package/ios/Source/tts/TTSTools.swift +164 -0
- package/ios/Source/utils/JSCExperiment.swift +7 -7
- package/ios/Source/utils/MessageChunkReassembler.swift +20 -1
- package/ios/Source/utils/MessageChunker.swift +78 -21
- package/ios/Source/utils/TarBz2Extractor.swift +53 -2
- package/package.json +1 -1
- package/plugin/build/withAndroid.js +68 -4
- package/src/BluetoothSdk.types.ts +331 -59
- package/src/_private/BluetoothSdkModule.ts +113 -102
- package/src/_private/photoRequestPayload.ts +28 -0
- package/src/index.ts +58 -15
- package/src/react/useMentraBluetooth.ts +6 -4
- package/android/.project +0 -28
- package/android/lc3Lib/.project +0 -28
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Headers/cargs.h +0 -162
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Headers/sherpa-onnx/c-api/c-api.h +0 -1852
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Headers/sherpa-onnx/c-api/cxx-api.h +0 -674
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/sherpa-onnx.a +0 -0
- package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/sherpa-onnx.a +0 -0
- package/ios/Source/Status/DeviceStatus.swift +0 -471
- /package/ios/Source/{Connection → connection}/ScanSession.swift +0 -0
- /package/ios/Source/{Errors → errors}/BluetoothError.swift +0 -0
- /package/ios/Source/{Internal → internal}/BluetoothAvailability.swift +0 -0
- /package/ios/Source/{Status → status}/RuntimeState.swift +0 -0
- /package/ios/Source/{Types → types}/DeviceModels.swift +0 -0
|
@@ -7,12 +7,81 @@ plugins {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
def packageJson = new JsonSlurper().parse(file("../../package.json"))
|
|
10
|
+
def mavenGroupId = 'com.mentraglass'
|
|
11
|
+
def mavenPublishVersion = (findProperty('mentraMavenVersion') ?: System.getenv('MENTRA_MAVEN_VERSION') ?: packageJson.version).toString()
|
|
10
12
|
|
|
11
|
-
group =
|
|
12
|
-
version =
|
|
13
|
+
group = mavenGroupId
|
|
14
|
+
version = mavenPublishVersion
|
|
13
15
|
|
|
14
|
-
def
|
|
15
|
-
|
|
16
|
+
def credentialValue = { List<String> propertyNames, List<String> envNames ->
|
|
17
|
+
for (propertyName in propertyNames) {
|
|
18
|
+
def value = findProperty(propertyName)
|
|
19
|
+
if (value != null && value.toString().trim()) {
|
|
20
|
+
return value.toString()
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
for (envName in envNames) {
|
|
24
|
+
def value = System.getenv(envName)
|
|
25
|
+
if (value != null && value.trim()) {
|
|
26
|
+
return value
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return null
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
def centralTokenParts = { boolean failOnInvalid = false ->
|
|
33
|
+
def token = credentialValue(['sonatypeTokenBase64', 'mavenCentralTokenBase64'], ['SONATYPE_TOKEN_BASE64', 'MAVEN_CENTRAL_TOKEN_BASE64'])
|
|
34
|
+
if (!token) {
|
|
35
|
+
return null
|
|
36
|
+
}
|
|
37
|
+
def decoded
|
|
38
|
+
try {
|
|
39
|
+
decoded = new String(token.decodeBase64(), 'UTF-8')
|
|
40
|
+
} catch (Exception e) {
|
|
41
|
+
if (failOnInvalid) {
|
|
42
|
+
throw new GradleException('Sonatype token must be valid base64 for username:password', e)
|
|
43
|
+
}
|
|
44
|
+
return null
|
|
45
|
+
}
|
|
46
|
+
def separator = decoded.indexOf(':')
|
|
47
|
+
if (separator <= 0) {
|
|
48
|
+
if (failOnInvalid) {
|
|
49
|
+
throw new GradleException('Sonatype token must decode to username:password')
|
|
50
|
+
}
|
|
51
|
+
return null
|
|
52
|
+
}
|
|
53
|
+
return [decoded.substring(0, separator), decoded.substring(separator + 1)]
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
def centralUsername = { boolean failOnInvalidToken = false ->
|
|
57
|
+
credentialValue(['sonatypeUsername', 'mavenCentralUsername'], ['SONATYPE_USERNAME', 'MAVEN_CENTRAL_USERNAME']) ?: centralTokenParts(failOnInvalidToken)?.get(0)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
def centralPassword = { boolean failOnInvalidToken = false ->
|
|
61
|
+
credentialValue(['sonatypePassword', 'mavenCentralPassword'], ['SONATYPE_PASSWORD', 'MAVEN_CENTRAL_PASSWORD']) ?: centralTokenParts(failOnInvalidToken)?.get(1)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
def signingKey = {
|
|
65
|
+
credentialValue(['signingKey'], ['SIGNING_KEY'])
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
def signingPassword = {
|
|
69
|
+
credentialValue(['signingPassword'], ['SIGNING_PASSWORD'])
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
def shouldUseGpgCmd = {
|
|
73
|
+
(credentialValue(['signing.useGpgCmd'], ['SIGNING_USE_GPG_CMD']) ?: 'false').toBoolean()
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
def isCentralPublishTask = {
|
|
77
|
+
gradle.taskGraph.allTasks.any { it.name.toLowerCase().contains('sonatypecentral') }
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
gradle.taskGraph.whenReady {
|
|
81
|
+
if (isCentralPublishTask()) {
|
|
82
|
+
centralUsername(true)
|
|
83
|
+
centralPassword(true)
|
|
84
|
+
}
|
|
16
85
|
}
|
|
17
86
|
|
|
18
87
|
android {
|
|
@@ -67,7 +136,7 @@ afterEvaluate {
|
|
|
67
136
|
publishing {
|
|
68
137
|
publications {
|
|
69
138
|
release(MavenPublication) {
|
|
70
|
-
groupId =
|
|
139
|
+
groupId = mavenGroupId
|
|
71
140
|
artifactId = 'lc3Lib'
|
|
72
141
|
version = project.version
|
|
73
142
|
|
|
@@ -98,12 +167,32 @@ afterEvaluate {
|
|
|
98
167
|
}
|
|
99
168
|
}
|
|
100
169
|
}
|
|
170
|
+
repositories {
|
|
171
|
+
maven {
|
|
172
|
+
name = 'sonatypeCentral'
|
|
173
|
+
url = uri('https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/')
|
|
174
|
+
credentials {
|
|
175
|
+
username = centralUsername()
|
|
176
|
+
password = centralPassword()
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
101
180
|
}
|
|
102
181
|
|
|
103
182
|
signing {
|
|
183
|
+
def inMemorySigningKey = signingKey()
|
|
184
|
+
if (inMemorySigningKey) {
|
|
185
|
+
useInMemoryPgpKeys(inMemorySigningKey, signingPassword())
|
|
186
|
+
} else if (shouldUseGpgCmd()) {
|
|
187
|
+
useGpgCmd()
|
|
188
|
+
}
|
|
104
189
|
required {
|
|
105
|
-
|
|
190
|
+
isCentralPublishTask()
|
|
106
191
|
}
|
|
107
192
|
sign publishing.publications.release
|
|
108
193
|
}
|
|
109
194
|
}
|
|
195
|
+
|
|
196
|
+
tasks.withType(Sign).configureEach {
|
|
197
|
+
onlyIf { isCentralPublishTask() }
|
|
198
|
+
}
|
package/android/settings.gradle
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Copyright 2023 Georgiy Konovalov
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
|
5
|
+
associated documentation files (the "Software"), to deal in the Software without restriction,
|
|
6
|
+
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
7
|
+
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
8
|
+
subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial
|
|
11
|
+
portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
|
14
|
+
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
15
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
16
|
+
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
17
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Vendored from https://github.com/gkonovalov/android-vad (silero module, v2.0.10)
|
|
2
|
+
// Consumed in-place by the bluetooth-sdk so we can pin ORT to a version that
|
|
3
|
+
// matches our other ORT consumer (sherpa-onnx) without depending on a Jitpack
|
|
4
|
+
// AAR whose prebuilt JNI was built against a different ORT.
|
|
5
|
+
plugins {
|
|
6
|
+
id 'com.android.library'
|
|
7
|
+
id 'kotlin-android'
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
android {
|
|
11
|
+
namespace "com.konovalov.vad.silero"
|
|
12
|
+
compileSdk 36
|
|
13
|
+
|
|
14
|
+
defaultConfig {
|
|
15
|
+
minSdkVersion 24
|
|
16
|
+
targetSdkVersion 36
|
|
17
|
+
|
|
18
|
+
ndk {
|
|
19
|
+
abiFilters "armeabi-v7a", "x86", "x86_64", "arm64-v8a"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
aaptOptions {
|
|
24
|
+
noCompress "onnx"
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
compileOptions {
|
|
28
|
+
sourceCompatibility JavaVersion.VERSION_17
|
|
29
|
+
targetCompatibility JavaVersion.VERSION_17
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
kotlinOptions {
|
|
33
|
+
jvmTarget = '17'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
dependencies {
|
|
38
|
+
// 1.24.3 matches the ORT version sherpa-onnx 1.13.2 was built against, so
|
|
39
|
+
// both consumers can share a single libonnxruntime.so (same versioned
|
|
40
|
+
// OrtGetApiBase@@VERS_1.24.3 symbol). Keep these versions in lockstep.
|
|
41
|
+
implementation 'com.microsoft.onnxruntime:onnxruntime-android:1.24.3'
|
|
42
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Add project specific ProGuard rules here.
|
|
2
|
+
# You can control the set of applied configuration files using the
|
|
3
|
+
# proguardFiles setting in build.gradle.
|
|
4
|
+
#
|
|
5
|
+
# For more details, see
|
|
6
|
+
# http://developer.android.com/guide/developing/tools/proguard.html
|
|
7
|
+
|
|
8
|
+
# If your project uses WebView with JS, uncomment the following
|
|
9
|
+
# and specify the fully qualified class name to the JavaScript interface
|
|
10
|
+
# class:
|
|
11
|
+
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
|
12
|
+
# public *;
|
|
13
|
+
#}
|
|
14
|
+
|
|
15
|
+
# Uncomment this to preserve the line number information for
|
|
16
|
+
# debugging stack traces.
|
|
17
|
+
#-keepattributes SourceFile,LineNumberTable
|
|
18
|
+
|
|
19
|
+
# If you keep the line number information, uncomment this to
|
|
20
|
+
# hide the original source file name.
|
|
21
|
+
#-renamesourcefileattribute SourceFile
|
|
22
|
+
-keep class ai.onnxruntime.** {*;}
|
|
23
|
+
-keep class com.konovalov.vad.** {*;}
|
|
24
|
+
-dontwarn com.google.**
|
|
Binary file
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
package com.konovalov.silero
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import androidx.test.ext.junit.runners.AndroidJUnit4
|
|
5
|
+
import androidx.test.platform.app.InstrumentationRegistry
|
|
6
|
+
import com.konovalov.vad.silero.Vad
|
|
7
|
+
import com.konovalov.vad.silero.VadSilero
|
|
8
|
+
import com.konovalov.vad.silero.config.FrameSize
|
|
9
|
+
import com.konovalov.vad.silero.config.Mode
|
|
10
|
+
import com.konovalov.vad.silero.config.SampleRate
|
|
11
|
+
import junit.framework.TestCase.assertEquals
|
|
12
|
+
import org.junit.After
|
|
13
|
+
import org.junit.Before
|
|
14
|
+
import org.junit.Test
|
|
15
|
+
import org.junit.runner.RunWith
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Created by Georgiy Konovalov on 12/22/2023.
|
|
20
|
+
*
|
|
21
|
+
* Instrumented test for VadSilero class.
|
|
22
|
+
*/
|
|
23
|
+
@RunWith(AndroidJUnit4::class)
|
|
24
|
+
class VadSileroTest {
|
|
25
|
+
|
|
26
|
+
private lateinit var vad: VadSilero
|
|
27
|
+
private lateinit var testContext: Context
|
|
28
|
+
|
|
29
|
+
@Before
|
|
30
|
+
fun setUp() {
|
|
31
|
+
this.testContext = InstrumentationRegistry.getInstrumentation().context
|
|
32
|
+
|
|
33
|
+
this.vad = Vad.builder()
|
|
34
|
+
.setContext(testContext)
|
|
35
|
+
.setSampleRate(SampleRate.SAMPLE_RATE_16K)
|
|
36
|
+
.setFrameSize(FrameSize.FRAME_SIZE_512)
|
|
37
|
+
.setMode(Mode.VERY_AGGRESSIVE)
|
|
38
|
+
.build()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@After
|
|
42
|
+
fun shutdown() {
|
|
43
|
+
vad.close()
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@Test
|
|
47
|
+
fun testIsSpeech() {
|
|
48
|
+
// List for VAD results
|
|
49
|
+
val actualResult = mutableListOf<Boolean>()
|
|
50
|
+
|
|
51
|
+
// List with expected VAD results
|
|
52
|
+
val expectedResult = listOf(
|
|
53
|
+
false, false, false, false, false,
|
|
54
|
+
false, true, true, true, true,
|
|
55
|
+
true, true, true, true, true,
|
|
56
|
+
true, true, true, false, false
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
// Buffer size should be 2x for ByteArray
|
|
60
|
+
val chunkSize = vad.frameSize.value * 2
|
|
61
|
+
|
|
62
|
+
// Reading audio data from test file
|
|
63
|
+
testContext.assets.open("hello.wav").buffered().use { input ->
|
|
64
|
+
// Skip WAV Header
|
|
65
|
+
input.skip(44)
|
|
66
|
+
|
|
67
|
+
while (input.available() > 0) {
|
|
68
|
+
// Read audio Frame
|
|
69
|
+
val frameChunk = ByteArray(chunkSize).apply { input.read(this) }
|
|
70
|
+
|
|
71
|
+
// Save interference result
|
|
72
|
+
actualResult.add(vad.isSpeech(frameChunk))
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Compare expectedResult with actualResult
|
|
77
|
+
assertEquals(expectedResult, actualResult)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020-present Silero Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
Binary file
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
package com.konovalov.vad.silero
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import com.konovalov.vad.silero.config.FrameSize
|
|
5
|
+
import com.konovalov.vad.silero.config.Mode
|
|
6
|
+
import com.konovalov.vad.silero.config.SampleRate
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Created by Georgiy Konovalov on 6/26/2023.
|
|
10
|
+
*
|
|
11
|
+
* The Silero VAD algorithm, based on DNN, analyzes the audio signal to determine whether it
|
|
12
|
+
* contains speech or non-speech segments. It offers higher accuracy in differentiating speech from
|
|
13
|
+
* background noise compared to the WebRTC VAD algorithm.
|
|
14
|
+
*
|
|
15
|
+
* The Silero VAD supports the following parameters:
|
|
16
|
+
*
|
|
17
|
+
* Sample Rates:
|
|
18
|
+
*
|
|
19
|
+
* 8000Hz,
|
|
20
|
+
* 16000Hz
|
|
21
|
+
*
|
|
22
|
+
* Frame Sizes (per sample rate):
|
|
23
|
+
*
|
|
24
|
+
* For 8000Hz: 80, 160, 240
|
|
25
|
+
* For 16000Hz: 160, 320, 480
|
|
26
|
+
*
|
|
27
|
+
* Mode:
|
|
28
|
+
*
|
|
29
|
+
* NORMAL,
|
|
30
|
+
* LOW_BITRATE,
|
|
31
|
+
* AGGRESSIVE,
|
|
32
|
+
* VERY_AGGRESSIVE
|
|
33
|
+
*
|
|
34
|
+
* Please note that the VAD class supports these specific combinations of sample
|
|
35
|
+
* rates and frame sizes, and the classifiers determine the aggressiveness of the voice
|
|
36
|
+
* activity detection algorithm.
|
|
37
|
+
*
|
|
38
|
+
* @param context is required for reading the model file from file system.
|
|
39
|
+
* @param sampleRate is required for processing audio input.
|
|
40
|
+
* @param frameSize is required for processing audio input.
|
|
41
|
+
* @param mode is required for the VAD model.
|
|
42
|
+
* @param speechDurationMs is minimum duration in milliseconds for speech segments (optional).
|
|
43
|
+
* @param silenceDurationMs is minimum duration in milliseconds for silence segments (optional).
|
|
44
|
+
*/
|
|
45
|
+
class Vad private constructor() {
|
|
46
|
+
private lateinit var context: Context
|
|
47
|
+
private lateinit var sampleRate: SampleRate
|
|
48
|
+
private lateinit var frameSize: FrameSize
|
|
49
|
+
private lateinit var mode: Mode
|
|
50
|
+
private var speechDurationMs = 0
|
|
51
|
+
private var silenceDurationMs = 0
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Set Context for Vad Model.
|
|
55
|
+
*
|
|
56
|
+
* @param context is required for accessing the model file.
|
|
57
|
+
*/
|
|
58
|
+
fun setContext(context: Context): Vad = apply {
|
|
59
|
+
this.context = context.applicationContext ?: context
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Set, retrieve and validate sample rate for Vad Model.
|
|
64
|
+
*
|
|
65
|
+
* Valid Sample Rates:
|
|
66
|
+
*
|
|
67
|
+
* 8000Hz,
|
|
68
|
+
* 16000Hz
|
|
69
|
+
*
|
|
70
|
+
* @param sampleRate is required for processing audio input.
|
|
71
|
+
*/
|
|
72
|
+
fun setSampleRate(sampleRate: SampleRate): Vad = apply {
|
|
73
|
+
this.sampleRate = sampleRate
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Set, retrieve and validate frame size for Vad Model.
|
|
78
|
+
*
|
|
79
|
+
* Valid Frame Sizes (per sample rate):
|
|
80
|
+
*
|
|
81
|
+
* For 8000Hz: 256, 512, 768
|
|
82
|
+
* For 16000Hz: 512, 1024, 1536
|
|
83
|
+
*
|
|
84
|
+
* @param frameSize is required for processing audio input.
|
|
85
|
+
*/
|
|
86
|
+
fun setFrameSize(frameSize: FrameSize): Vad = apply {
|
|
87
|
+
this.frameSize = frameSize
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Set and retrieve detection mode for Vad model.
|
|
92
|
+
*
|
|
93
|
+
* Mode:
|
|
94
|
+
*
|
|
95
|
+
* NORMAL,
|
|
96
|
+
* LOW_BITRATE,
|
|
97
|
+
* AGGRESSIVE,
|
|
98
|
+
* VERY_AGGRESSIVE
|
|
99
|
+
*
|
|
100
|
+
* @param mode is required for the VAD model.
|
|
101
|
+
*/
|
|
102
|
+
fun setMode(mode: Mode): Vad = apply {
|
|
103
|
+
this.mode = mode
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Set the minimum duration in milliseconds for speech segments.
|
|
108
|
+
* The value of this parameter will define the necessary and sufficient duration of positive
|
|
109
|
+
* results to recognize result as speech. This parameter is optional.
|
|
110
|
+
*
|
|
111
|
+
* Permitted range (0ms >= speechDurationMs <= 300000ms).
|
|
112
|
+
*
|
|
113
|
+
* Parameters used for {@link VadSilero.isSpeech}.
|
|
114
|
+
*
|
|
115
|
+
* @param speechDurationMs minimum duration in milliseconds for speech segments.
|
|
116
|
+
*/
|
|
117
|
+
fun setSpeechDurationMs(speechDurationMs: Int): Vad = apply {
|
|
118
|
+
this.speechDurationMs = speechDurationMs
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Set the minimum duration in milliseconds for silence segments.
|
|
123
|
+
* The value of this parameter will define the necessary and sufficient duration of
|
|
124
|
+
* negative results to recognize it as silence. This parameter is optional.
|
|
125
|
+
*
|
|
126
|
+
* Permitted range (0ms >= silenceDurationMs <= 300000ms).
|
|
127
|
+
*
|
|
128
|
+
* Parameters used in {@link VadSilero.isSpeech}.
|
|
129
|
+
*
|
|
130
|
+
* @param silenceDurationMs minimum duration in milliseconds for silence segments.
|
|
131
|
+
*/
|
|
132
|
+
fun setSilenceDurationMs(silenceDurationMs: Int): Vad = apply {
|
|
133
|
+
this.silenceDurationMs = silenceDurationMs
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Builds and returns a VadModel instance based on the specified parameters.
|
|
138
|
+
*
|
|
139
|
+
* @return constructed VadSilero model.
|
|
140
|
+
* @throws IllegalArgumentException if invalid parameters have been set for the model.
|
|
141
|
+
* @throws OrtException if the model failed to parse, wasn't compatible or caused an error.
|
|
142
|
+
*/
|
|
143
|
+
fun build(): VadSilero {
|
|
144
|
+
return VadSilero(
|
|
145
|
+
context,
|
|
146
|
+
sampleRate,
|
|
147
|
+
frameSize,
|
|
148
|
+
mode,
|
|
149
|
+
speechDurationMs,
|
|
150
|
+
silenceDurationMs
|
|
151
|
+
)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
companion object {
|
|
155
|
+
@JvmStatic
|
|
156
|
+
fun builder(): Vad {
|
|
157
|
+
return Vad()
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|