diff --git a/.github/workflows/rust-codestyle.yml b/.github/workflows/rust-codestyle.yml index b01ea13fd..12f955f40 100644 --- a/.github/workflows/rust-codestyle.yml +++ b/.github/workflows/rust-codestyle.yml @@ -42,11 +42,11 @@ jobs: override: true - name: Local Porcupine dependency - run: ./copy.sh + run: bash copy.sh && cargo build working-directory: resources/porcupine/binding/rust - name: Local Rhino dependency - run: ./copy.sh + run: bash copy.sh && cargo build working-directory: resources/rhino/binding/rust - name: Run clippy @@ -71,6 +71,18 @@ jobs: toolchain: stable override: true + - name: Local Porcupine dependency + run: bash copy.sh && cargo build + working-directory: resources/porcupine/binding/rust + + - name: Local Rhino dependency + run: bash copy.sh && cargo build + working-directory: resources/rhino/binding/rust + + - name: Local dependency + run: cargo build + working-directory: sdk/rust + - name: Run clippy run: cargo clippy -- -D warnings working-directory: demo/rust/filedemo @@ -93,6 +105,22 @@ jobs: toolchain: stable override: true + - name: Local Porcupine dependency + run: bash copy.sh && cargo build + working-directory: resources/porcupine/binding/rust + + - name: Local Rhino dependency + run: bash copy.sh && cargo build + working-directory: resources/rhino/binding/rust + + - name: Local dependency + run: cargo build + working-directory: sdk/rust + + - name: Local dependency + run: cargo build + working-directory: sdk/rust + - name: Run clippy run: cargo clippy -- -D warnings working-directory: demo/rust/micdemo diff --git a/.github/workflows/rust-demos.yml b/.github/workflows/rust-demos.yml index 2057afd18..f0d8169c6 100644 --- a/.github/workflows/rust-demos.yml +++ b/.github/workflows/rust-demos.yml @@ -53,6 +53,18 @@ jobs: toolchain: stable override: true + - name: Local Porcupine dependency + run: bash copy.sh && cargo build + working-directory: resources/porcupine/binding/rust + + - name: Local Rhino dependency + run: bash copy.sh && cargo build + working-directory: resources/rhino/binding/rust + + - name: Local dependency + run: cargo build + working-directory: sdk/rust + - name: Rust build micdemo run: cargo build --verbose working-directory: demo/rust/micdemo @@ -98,6 +110,18 @@ jobs: toolchain: nightly override: true + - name: Local Porcupine dependency + run: bash copy.sh && cargo build + working-directory: resources/porcupine/binding/rust + + - name: Local Rhino dependency + run: bash copy.sh && cargo build + working-directory: resources/rhino/binding/rust + + - name: Local dependency + run: cargo build + working-directory: sdk/rust + - name: Rust build micdemo run: cargo build --verbose working-directory: demo/rust/micdemo diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 3521663b0..3860dde7d 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -56,11 +56,11 @@ jobs: override: true - name: Local Porcupine dependency - run: ./copy.sh + run: bash copy.sh && cargo build working-directory: resources/porcupine/binding/rust - name: Local Rhino dependency - run: ./copy.sh + run: bash copy.sh && cargo build working-directory: resources/rhino/binding/rust - name: Rust build @@ -84,15 +84,15 @@ jobs: - name: Install stable toolchain uses: actions-rs/toolchain@v1 with: - toolchain: nightly + toolchain: stable override: true - name: Local Porcupine dependency - run: ./copy.sh + run: bash copy.sh && cargo build working-directory: resources/porcupine/binding/rust - name: Local Rhino dependency - run: ./copy.sh + run: bash copy.sh && cargo build working-directory: resources/rhino/binding/rust - name: Rust build diff --git a/demo/rust/filedemo/Cargo.toml b/demo/rust/filedemo/Cargo.toml index cdcde3eda..7892cf2ec 100644 --- a/demo/rust/filedemo/Cargo.toml +++ b/demo/rust/filedemo/Cargo.toml @@ -7,4 +7,4 @@ edition = "2018" clap = "3.2.3" hound = "3.4.0" itertools = "0.10.3" -picovoice = "=2.2.1" +picovoice = { path = "../../../sdk/rust" } diff --git a/demo/rust/micdemo/Cargo.toml b/demo/rust/micdemo/Cargo.toml index 182043e4a..d5b53215f 100644 --- a/demo/rust/micdemo/Cargo.toml +++ b/demo/rust/micdemo/Cargo.toml @@ -9,5 +9,5 @@ clap = "3.2.3" ctrlc = "3.1.9" hound = "3.4.0" itertools = "0.10.3" -picovoice = "=2.2.1" +picovoice = { path = "../../../sdk/rust" } pv_recorder = "=1.2.1" diff --git a/sdk/rust/Cargo.lock b/sdk/rust/Cargo.lock index 0eb957c31..7717992ab 100644 --- a/sdk/rust/Cargo.lock +++ b/sdk/rust/Cargo.lock @@ -112,7 +112,7 @@ checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3" dependencies = [ "glob", "libc", - "libloading", + "libloading 0.7.4", ] [[package]] @@ -363,6 +363,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "libloading" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +dependencies = [ + "cfg-if", + "windows-sys", +] + [[package]] name = "lock_api" version = "0.4.9" @@ -632,7 +642,7 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "picovoice" -version = "2.2.1" +version = "3.0.0" dependencies = [ "itertools", "pv_porcupine", @@ -668,22 +678,18 @@ dependencies = [ [[package]] name = "pv_porcupine" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae7af04db856a9c23f9f35f5b4b3a224dc4d16555a0f1079f3573127f429d102" +version = "3.0.0" dependencies = [ "libc", - "libloading", + "libloading 0.8.1", ] [[package]] name = "pv_rhino" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c83df0b253a4ee96e3428394f2f7a4769505c7e0bd91e1b4379141a289494c53" +version = "3.0.0" dependencies = [ "libc", - "libloading", + "libloading 0.7.4", ] [[package]] @@ -985,3 +991,69 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/sdk/rust/Cargo.toml b/sdk/rust/Cargo.toml index 074b3b4b9..f13a493b0 100644 --- a/sdk/rust/Cargo.toml +++ b/sdk/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "picovoice" -version = "2.2.1" +version = "3.0.0" edition = "2018" description = "Rust SDK for Picovoice's voice recognition platform" license = "Apache-2.0" @@ -25,8 +25,8 @@ path = "src/lib.rs" crate_type = ["lib"] [dependencies] -pv_porcupine = "=2.2.1" -pv_rhino = "=2.2.1" +pv_porcupine = { path = "../../resources/porcupine/binding/rust" } +pv_rhino = { path = "../../resources/rhino/binding/rust" } [dev-dependencies] itertools = "0.10.1" diff --git a/sdk/rust/src/lib.rs b/sdk/rust/src/lib.rs index b9429c712..c9e063ff4 100644 --- a/sdk/rust/src/lib.rs +++ b/sdk/rust/src/lib.rs @@ -240,7 +240,7 @@ where let frame_length = porcupine.frame_length(); let version = format!( - "2.1.1 (Porcupine v{}) (Rhino v{})", + "3.0.0 (Porcupine v{}) (Rhino v{})", porcupine.version(), rhino.version() ); @@ -287,6 +287,13 @@ where Ok(()) } + pub fn reset(&mut self) -> Result<(), PicovoiceError> { + self.wake_word_detected = false; + self.rhino.reset().map_err(PicovoiceError::from_rhino)?; + + Ok(()) + } + pub fn frame_length(&self) -> u32 { self.frame_length } diff --git a/sdk/rust/tests/picovoice_tests.rs b/sdk/rust/tests/picovoice_tests.rs index 0f2c8ae87..3b89b1a00 100644 --- a/sdk/rust/tests/picovoice_tests.rs +++ b/sdk/rust/tests/picovoice_tests.rs @@ -90,6 +90,42 @@ mod tests { ) } + fn process_file_helper( + picovoice: &mut Picovoice, + audio_file_name: &str, + max_process_count: i32 + ) { + let soundfile_path = format!( + "{}{}{}", + env!("CARGO_MANIFEST_DIR"), + "/../../resources/audio_samples/", + audio_file_name + ); + + let mut reader = BufReader::new(File::open(&soundfile_path).unwrap()); + reader.seek_relative(44).unwrap(); // Skip .wav header + + let i16_size = std::mem::size_of::(); + let frame_length_bytes = picovoice.frame_length() as usize * i16_size; + + let mut frame_buffer = vec![0u8; frame_length_bytes]; + + let mut processed = 0; + while reader.read_exact(&mut frame_buffer).is_ok() { + let frame_samples: Vec = frame_buffer + .chunks(i16_size) + .map(|i16_slice| { + i16::from_le_bytes(i16_slice.try_into().expect("Incorrect i16 slice size")) + }) + .collect(); + picovoice.process(&frame_samples).unwrap(); + if max_process_count != -1 && processed >= max_process_count { + break; + } + processed += 1; + } + } + fn run_picovoice_test( language: &str, keyword: &str, @@ -128,29 +164,7 @@ mod tests { .init() .expect("Failed to init Picovoice"); - let soundfile_path = format!( - "{}{}{}", - env!("CARGO_MANIFEST_DIR"), - "/../../resources/audio_samples/", - audio_file_name - ); - - let mut reader = BufReader::new(File::open(&soundfile_path).unwrap()); - reader.seek_relative(44).unwrap(); // Skip .wav header - - let i16_size = std::mem::size_of::(); - let frame_length_bytes = picovoice.frame_length() as usize * i16_size; - - let mut frame_buffer = vec![0u8; frame_length_bytes]; - while reader.read_exact(&mut frame_buffer).is_ok() { - let frame_samples: Vec = frame_buffer - .chunks(i16_size) - .map(|i16_slice| { - i16::from_le_bytes(i16_slice.try_into().expect("Incorrect i16 slice size")) - }) - .collect(); - picovoice.process(&frame_samples).unwrap(); - } + process_file_helper(&mut picovoice, audio_file_name, -1); assert_eq!( *is_wake_word_detected.lock().unwrap(), @@ -177,6 +191,43 @@ mod tests { ); } + #[test] + fn test_reset() { + let access_key = env::var("PV_ACCESS_KEY") + .expect("Pass the AccessKey in using the PV_ACCESS_KEY env variable"); + + let is_wake_word_detected = Arc::new(Mutex::new(false)); + let is_inference = Arc::new(Mutex::new(false)); + + let wake_word_callback = || { + if let Ok(mut is_wake_word_detected) = is_wake_word_detected.lock() { + *is_wake_word_detected = true; + } + }; + + let inference_callback = |_| { + if let Ok(mut is_inference) = is_inference.lock() { + *is_inference = true; + } + }; + + let mut picovoice = PicovoiceBuilder::new( + access_key, + keyword_path_by_language("picovoice", "en"), + wake_word_callback, + context_path_by_language("coffee_maker", "en"), + inference_callback, + ).init().expect("Failed to init Picovoice"); + + process_file_helper(&mut picovoice, "picovoice-coffee.wav", 25); + assert_eq!(*is_inference.lock().unwrap(), false); + + let _ = picovoice.reset(); + + process_file_helper(&mut picovoice, "picovoice-coffee.wav", 25); + assert_eq!(*is_inference.lock().unwrap(), false); + } + #[test] fn test_parameters() { let test_json: Value = load_test_data();