├── scripts ├── .gitignore ├── requirements.txt └── plot_audio.py ├── .gitattributes ├── models └── silero_vad.onnx ├── .github ├── dependabot.yml └── workflows │ ├── audit.yml │ └── rust_ci.yml ├── example └── file_inference │ ├── audios │ └── sample_1.mp3 │ ├── Cargo.toml │ └── src │ ├── main.rs │ └── audio_reading.rs ├── tests ├── audio │ ├── birds.wav │ ├── rooster.wav │ ├── sample_1.wav │ ├── sample_2.wav │ ├── sample_3.wav │ ├── sample_4.wav │ └── sample_1_trimmed.wav ├── consistency.rs ├── snapshot.rs └── data │ └── chunk_50_8000Hz_default.json ├── src ├── errors.rs ├── audio_resampler.rs └── lib.rs ├── .gitignore ├── Cargo.toml ├── README.md ├── LICENSE ├── CHANGELOG.md └── benches └── usage.rs /scripts/.gitignore: -------------------------------------------------------------------------------- 1 | env/ 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | tests/audio/** filter=lfs diff=lfs merge=lfs -text 2 | -------------------------------------------------------------------------------- /models/silero_vad.onnx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emotechlab/silero-rs/HEAD/models/silero_vad.onnx -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | -------------------------------------------------------------------------------- /example/file_inference/audios/sample_1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emotechlab/silero-rs/HEAD/example/file_inference/audios/sample_1.mp3 -------------------------------------------------------------------------------- /tests/audio/birds.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b5b97e7c3ddd8f08f7f3c914c09a62b7ee315e119cba06abf671326c1d96ba9c 3 | size 1239118 4 | -------------------------------------------------------------------------------- /tests/audio/rooster.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:290c4c1d2cdc774dfe6af34d3874b6f134284ac10bab5dbe2fbe628d2fcc2e4b 3 | size 265900 4 | -------------------------------------------------------------------------------- /tests/audio/sample_1.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3ba6b72c9b739b15373120635d4b8b5950677af55d30dd355ed5f89fd0c36c2f 3 | size 147200 4 | -------------------------------------------------------------------------------- /tests/audio/sample_2.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b1d3bdbf1d5b31a8c971c6606e98d6676d5692645992bafb7337b49afe846666 3 | size 168098 4 | -------------------------------------------------------------------------------- /tests/audio/sample_3.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5d1a0cdeab30cfe6eed8eb00a8e773f0ed1245785767ac96db8d35b3813b00ac 3 | size 112928 4 | -------------------------------------------------------------------------------- /tests/audio/sample_4.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0fe244840f3ba1175f4b3dfeb8cbefcb45613b406d56e75a7aebc98106b36cf0 3 | size 270080 4 | -------------------------------------------------------------------------------- /tests/audio/sample_1_trimmed.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:31481009cbec561903bcd0ae8e668ac28c8f714e5496694e571bcf5c85369ec4 3 | size 26718 4 | -------------------------------------------------------------------------------- /src/errors.rs: -------------------------------------------------------------------------------- 1 | //! All possible errors VAD might encounter. 2 | use thiserror::Error; 3 | 4 | #[derive(Debug, Error)] 5 | pub enum VadError { 6 | #[error("Float sample must be in the range -1.0 to 1.0")] 7 | InvalidData, 8 | } 9 | -------------------------------------------------------------------------------- /scripts/requirements.txt: -------------------------------------------------------------------------------- 1 | contourpy==1.2.1 2 | cycler==0.12.1 3 | fonttools==4.53.1 4 | kiwisolver==1.4.5 5 | matplotlib==3.9.2 6 | numpy==2.1.0 7 | packaging==24.1 8 | pillow==10.4.0 9 | pyparsing==3.1.2 10 | python-dateutil==2.9.0.post0 11 | six==1.16.0 12 | Wave==0.0.2 13 | -------------------------------------------------------------------------------- /example/file_inference/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "file_inference" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | anyhow = "1.0.90" 8 | clap = { version = "4.5.20", features = ["derive"] } 9 | silero = { path = "../.." } 10 | symphonia = { version = "0.5.4", features = ["all"] } 11 | tracing = "0.1.40" 12 | -------------------------------------------------------------------------------- /.github/workflows/audit.yml: -------------------------------------------------------------------------------- 1 | name: Security audit 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * 0' 6 | 7 | jobs: 8 | audit: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v3 12 | with: 13 | submodules: recursive 14 | ssh-key: ${{ secrets.SSH_PRIVATE_KEY }} 15 | - uses: rustsec/audit-check@v1.4.1 16 | with: 17 | token: ${{ secrets.GITHUB_TOKEN }} 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | target/ 5 | example/*/target/ 6 | 7 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 8 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 9 | Cargo.lock 10 | 11 | # These are backup files generated by rustfmt 12 | **/*.rs.bk 13 | 14 | # MSVC Windows builds of rustc generate these, which store debugging information 15 | *.pdb 16 | 17 | # IDEs 18 | .idea/ 19 | .vscode/ 20 | 21 | # MacOS 22 | .DS_Store 23 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "silero" 3 | version = "0.1.0" 4 | repository = "https://github.com/emotechlab/Silero" 5 | readme = "README.md" 6 | license = "MIT" 7 | edition = "2021" 8 | 9 | [features] 10 | default = ["static-model", "audio_resampler"] 11 | static-model = [] 12 | audio_resampler = ["dep:rubato"] 13 | serde = ["dep:serde"] 14 | 15 | [dependencies] 16 | anyhow = "1.0.86" 17 | ndarray = "0.16" 18 | ort = "=2.0.0-rc.10" 19 | rubato = { version = "0.16.0", optional = true} 20 | serde = { version = "1.0.208", features = ["derive"], optional = true } 21 | thiserror = "2.0.4" 22 | tracing = { version = "0.1.40", default-features = false, features = ["std"] } 23 | 24 | [dev-dependencies] 25 | approx = "0.5.1" 26 | divan = "0.1.15" 27 | hound = "3.5.1" 28 | serde_json = "1.0.125" 29 | tracing-test = "0.2.5" 30 | 31 | [[bench]] 32 | name = "usage" 33 | harness = false 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Silero 2 | 3 | Rust implementation of [Silero VAD](https://github.com/snakers4/silero-vad). 4 | 5 | ## Running Tests 6 | 7 | Tests require all the features to be present as serde deserializations are used 8 | for snapshot testing. Also, test data is stored via git lfs so you'll need to use 9 | git lfs to clone the repository to run the tests. 10 | 11 | To run tests do: 12 | 13 | ```text 14 | cargo test --all-features 15 | ``` 16 | 17 | If a test fails we have a script in `scripts/plot_audio.py` which will plot out 18 | a number of insights from the generated files. You can run this on the existing 19 | snapshots and ones generated from your test and try to see why the behaviour 20 | differs. In some instances the difference may be desired, but in others it will 21 | be symptomatic of a bug or issue in the code. Please justify in the PR text 22 | whenever you update a snapshot file! 23 | 24 | ## License 25 | 26 | This code is licensed under the terms of the MIT License. See LICENSE for more 27 | details. 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2024 Emotech Ltd 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /example/file_inference/src/main.rs: -------------------------------------------------------------------------------- 1 | //! An example to show how to read any audio file into pcm format and then send it to silero vad for 2 | //! inference. 3 | 4 | use anyhow::Result; 5 | use audio_reading::{MultiChannelStrategy, read_audio}; 6 | use clap::Parser; 7 | use silero::{VadConfig, VadSession}; 8 | 9 | mod audio_reading; 10 | 11 | #[derive(Parser, Debug)] 12 | #[command(version, about, long_about = None)] 13 | struct Args { 14 | #[clap(short, long)] 15 | file: String, 16 | } 17 | 18 | fn main() -> Result<()> { 19 | let args = Args::parse(); 20 | 21 | let (samples, original_sample_rate) = read_audio(args.file, MultiChannelStrategy::FirstOnly); 22 | 23 | let mut config = VadConfig::default(); 24 | config.sample_rate = original_sample_rate; 25 | let mut session = VadSession::new(config)?; 26 | 27 | // You do not need to worry about sample rate as long as you are using our library with 28 | // `audio_resampler` feature enabled. 29 | let results = session.process(&samples)?; 30 | dbg!(&results); 31 | 32 | Ok(()) 33 | } 34 | -------------------------------------------------------------------------------- /.github/workflows/rust_ci.yml: -------------------------------------------------------------------------------- 1 | name: Checks 2 | 3 | on: 4 | push: 5 | branches: ["main"] 6 | pull_request: 7 | branches: ["*"] 8 | 9 | jobs: 10 | build_and_test: 11 | name: Rust project 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v3 15 | with: 16 | lfs: true 17 | submodules: recursive 18 | ssh-key: ${{ secrets.SSH_PRIVATE_KEY }} 19 | - uses: dtolnay/rust-toolchain@stable 20 | with: 21 | components: rustfmt clippy 22 | - name: Rustfmt 23 | run: cargo fmt --check 24 | - name: Cargo test 25 | run: cargo test --all-features 26 | - uses: taiki-e/install-action@cargo-hack 27 | - name: Cargo build 28 | run: | 29 | cargo hack check --each-feature --no-dev-deps 30 | cargo hack check --feature-powerset --no-dev-deps 31 | - name: Clippy 32 | run: cargo clippy 33 | - name: Benchmark builds 34 | run: cargo check --benches 35 | - name: Check example works 36 | run: | 37 | cd example/file_inference 38 | cargo run --release -- --file=./audios/sample_1.mp3 39 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | ### Added 10 | - Initial version of inference and switching logic taken from internal Emotech 11 | code 12 | - Added in `end_silence_length` to track the raw end silences 13 | - Added new pub function `validate_input` for `VadSession` struct. `process` function will use it to make sure input is valid in debug mode. 14 | - Added a new method: `processed_duration`. A sample is considered as processed if it has been seen by Silero NN. 15 | - API to get current start/end time of session audio 16 | - Ability to trim the starting silence to keep buffer size down 17 | 18 | ### Fixed 19 | - Potential OOM when handling long autio. 20 | - Incorrect segments when processing whole files 21 | - Made output deterministic by not eagerly processing frame remainders (silent padding may cause issues) 22 | 23 | ### Changed 24 | - Deleted `timestamp_ms` in `SpeechEnd`. 25 | - Added `start_timestamp_ms`, `end_timestamp_ms`, and `samples` in `SpeechEnd`. 26 | 27 | -------------------------------------------------------------------------------- /benches/usage.rs: -------------------------------------------------------------------------------- 1 | use hound::WavReader; 2 | use silero::VadSession; 3 | use std::time::Duration; 4 | 5 | fn main() { 6 | divan::main(); 7 | } 8 | 9 | #[divan::bench(args = [20, 30, 50, 100])] 10 | fn process_file(chunk_ms: usize) { 11 | let chunk_size = chunk_ms * 16; // 16000/1000 12 | 13 | let mut session = VadSession::new(Default::default()).unwrap(); 14 | let samples: Vec = WavReader::open("tests/audio/sample_2.wav") 15 | .unwrap() 16 | .into_samples() 17 | .map(|x| { 18 | let modified = x.unwrap_or(0i16) as f32 / (i16::MAX as f32); 19 | modified.clamp(-1.0, 1.0) 20 | }) 21 | .collect(); 22 | 23 | let num_chunks = samples.len() / chunk_size; 24 | for i in 0..num_chunks { 25 | let start = i * chunk_size; 26 | let end = if i < num_chunks - 1 { 27 | start + chunk_size 28 | } else { 29 | samples.len() 30 | }; 31 | 32 | let _transitions = session.process(&samples[start..end]).unwrap(); 33 | } 34 | } 35 | 36 | #[divan::bench(args = [1, 2, 3, 4, 5, 6])] 37 | fn take(to_take: u64) { 38 | let mut session = VadSession::new(Default::default()).unwrap(); 39 | let samples: Vec = WavReader::open("tests/audio/rooster.wav") 40 | .unwrap() 41 | .into_samples() 42 | .map(|x| { 43 | let modified = x.unwrap_or(0i16) as f32 / (i16::MAX as f32); 44 | modified.clamp(-1.0, 1.0) 45 | }) 46 | .collect(); 47 | 48 | let _ = session.process(&samples); 49 | 50 | let _ = session.take_until(Duration::from_secs(to_take)); 51 | } 52 | 53 | #[divan::bench] 54 | fn push_multiple_silences() { 55 | let mut session = VadSession::new(Default::default()).unwrap(); 56 | let silence = vec![0.0; 500]; 57 | // Push 500ms of silence 58 | for _ in 0..16 { 59 | let _ = session.process(&silence); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/audio_resampler.rs: -------------------------------------------------------------------------------- 1 | use rubato::{FftFixedIn, Resampler}; 2 | use tracing::trace; 3 | 4 | /// Resample one channel of pcm data into desired sample rate. 5 | pub fn resample_pcm( 6 | pcm_data: Vec, 7 | original_sample_rate: usize, 8 | desired_sample_rate: usize, 9 | ) -> anyhow::Result> { 10 | if original_sample_rate == desired_sample_rate { 11 | trace!("no need to do any resample work"); 12 | return Ok(pcm_data); 13 | } 14 | trace!( 15 | "Resampling {} samples from {}Hz to {}Hz", 16 | &pcm_data.len(), 17 | original_sample_rate, 18 | desired_sample_rate 19 | ); 20 | 21 | let mut resampler = FftFixedIn::new( 22 | original_sample_rate, 23 | desired_sample_rate, 24 | pcm_data.len(), 25 | pcm_data.len(), // I don't know what does sub_chunks mean, just a random choice. 26 | 1, 27 | )?; 28 | 29 | let waves_in = vec![pcm_data]; 30 | let mut waves_out = resampler.process(&waves_in, None)?; 31 | Ok(waves_out.remove(0)) 32 | } 33 | 34 | #[cfg(test)] 35 | mod tests { 36 | use super::*; 37 | use anyhow::Result; 38 | use hound::WavReader; 39 | use std::fs::read_dir; 40 | use std::path::{Path, PathBuf}; 41 | 42 | fn read_wav_file(file_path: impl AsRef, sample_rate: usize) -> Result> { 43 | let step = if sample_rate == 16000 { 1 } else { 2 }; 44 | 45 | let samples: Vec = WavReader::open(file_path)? 46 | .into_samples() 47 | .step_by(step) 48 | .map(|x| { 49 | let x_f32 = x.unwrap_or(0i16) as f32 / i16::MAX as f32; 50 | x_f32.clamp(-1.0, 1.0) 51 | }) 52 | .collect(); 53 | 54 | Ok(samples) 55 | } 56 | 57 | fn get_audios() -> Vec { 58 | let audio_dir = Path::new("tests/audio/"); 59 | let mut result = vec![]; 60 | for entry in read_dir(audio_dir).unwrap() { 61 | let entry = entry.unwrap(); 62 | let path = entry.path(); 63 | if !path.is_dir() && path.extension().unwrap() == "wav" { 64 | result.push(path.to_path_buf()); 65 | } 66 | } 67 | result 68 | } 69 | 70 | #[test] 71 | fn read_wav() { 72 | let audios = get_audios(); 73 | assert!(!audios.is_empty()); 74 | for audio in audios { 75 | let samples = read_wav_file(audio, 16000).unwrap(); 76 | assert!(!samples.is_empty()); 77 | } 78 | } 79 | 80 | #[test] 81 | fn resample_up() { 82 | let audios = get_audios(); 83 | assert!(!audios.is_empty()); 84 | 85 | for audio in audios { 86 | let samples_16k = read_wav_file(audio, 16000).unwrap(); 87 | let samples_32k = resample_pcm(samples_16k.clone(), 16000, 32000).unwrap(); 88 | assert_eq!(samples_16k.len() * 2, samples_32k.len()); 89 | } 90 | } 91 | 92 | #[test] 93 | fn resample_no_change() { 94 | let audios = get_audios(); 95 | assert!(!audios.is_empty()); 96 | 97 | for audio in audios { 98 | let samples_16k = read_wav_file(audio, 16000).unwrap(); 99 | let resampled_16k = resample_pcm(samples_16k.clone(), 16000, 16000).unwrap(); 100 | assert_eq!(samples_16k.len(), resampled_16k.len()); 101 | } 102 | } 103 | 104 | #[test] 105 | fn resample_down() { 106 | let audios = get_audios(); 107 | assert!(!audios.is_empty()); 108 | 109 | for audio in audios { 110 | let samples_16k = read_wav_file(audio, 16000).unwrap(); 111 | let samples_8k = resample_pcm(samples_16k.clone(), 16000, 8000).unwrap(); 112 | assert_eq!(samples_16k.len() / 2, samples_8k.len()); 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /scripts/plot_audio.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S uv run 2 | # /// script 3 | # dependencies = [ 4 | # "contourpy==1.2.1", 5 | # "cycler==0.12.1", 6 | # "fonttools==4.53.1", 7 | # "kiwisolver==1.4.5", 8 | # "matplotlib==3.9.2", 9 | # "numpy==2.1.0", 10 | # "packaging==24.1", 11 | # "pillow==10.4.0", 12 | # "pyparsing==3.1.2", 13 | # "python-dateutil==2.9.0.post0", 14 | # "six==1.16.0", 15 | # "Wave==0.0.2" 16 | # ] 17 | # /// 18 | import wave 19 | import numpy as np 20 | import matplotlib.pyplot as plt 21 | import json 22 | import argparse 23 | 24 | parser = argparse.ArgumentParser() 25 | parser.add_argument("--audio", "-a", help="audio file to plot") 26 | parser.add_argument("--input", "-i", help="test data file to plot") 27 | parser.add_argument("--output", "-o", help="file to save plot to (optional)") 28 | 29 | args = parser.parse_args() 30 | 31 | 32 | wav_obj = wave.open(args.audio, 'rb') 33 | 34 | speech_segments = [] 35 | silence_samples = [] 36 | speech_samples = [] 37 | 38 | def rust_duration_to_seconds(obj): 39 | return int(obj["secs"]) + (float(obj["nanos"]) / 1000000000.0) 40 | 41 | redemption_time = 0 42 | 43 | with open(args.input) as f: 44 | data = json.load(f) 45 | start = None 46 | end = None 47 | 48 | vad = data["summary"][args.audio] 49 | silence_samples = vad["current_silence_samples"] 50 | speech_samples = vad["current_speech_samples"] 51 | audio_samples = vad["current_session_samples"] 52 | likelihoods = vad["likelihoods"] 53 | redemption_time = rust_duration_to_seconds(data["config"]["redemption_time"]) 54 | pre_speech_pad = rust_duration_to_seconds(data["config"]["pre_speech_pad"]) 55 | 56 | positive_thresh = float(data["config"]["positive_speech_threshold"]) * 100 57 | negative_thresh = float(data["config"]["negative_speech_threshold"]) * 100 58 | 59 | print(f"redemption time: {redemption_time}") 60 | for segment in vad["transitions"]: 61 | if "SpeechStart" in segment: 62 | start = int(segment["SpeechStart"]["timestamp_ms"]) 63 | end = None 64 | elif "SpeechEnd" in segment: 65 | end = int(segment["SpeechEnd"]["end_timestamp_ms"]) 66 | if start is not None and end is not None: 67 | speech_segments.append((start, end)) 68 | start = None 69 | end = None 70 | 71 | 72 | sample_freq = wav_obj.getframerate() 73 | n_samples = wav_obj.getnframes() 74 | t_audio = n_samples/sample_freq 75 | 76 | redemption_time_samples = sample_freq * redemption_time 77 | 78 | duration = 1000*n_samples / sample_freq 79 | finished_with_silence = True 80 | if start is not None and end is None: 81 | finished_with_silence = False 82 | end = int(round(duration)) 83 | speech_segments.append((start, end)) 84 | 85 | print(f"Segments: {speech_segments}") 86 | 87 | signal_wave = wav_obj.readframes(n_samples) 88 | signal_array = np.frombuffer(signal_wave, dtype=np.int16) 89 | 90 | 91 | times = np.linspace(0, n_samples/sample_freq, num=n_samples) 92 | 93 | fig, (ax, ax2, ax3) = plt.subplots(3) 94 | 95 | ax.plot(times, signal_array) 96 | 97 | ax.set(xlabel="Time (s)", ylabel="Signal", title="Audio") 98 | ax2.set(title = "Buffer Sizes") 99 | ax3.set(title = "Network likelihoods") 100 | 101 | ax2.plot(silence_samples, label = "Current silence samples") 102 | ax2.plot(speech_samples, label = "Current speech samples") 103 | ax2.plot(audio_samples, label = "Current stored samples") 104 | ax3.plot(likelihoods, label = "network likelihoods") 105 | labeled_start = False 106 | labeled_end = False 107 | for (i, (start, end)) in enumerate(speech_segments): 108 | if start > 0: 109 | ax.axvline( 110 | start/1000+pre_speech_pad, 111 | ymin=min(signal_array), 112 | ymax=max(signal_array), 113 | linestyle='dashed', 114 | color = '#42f5c2', 115 | label=None if labeled_start else "speech_start" 116 | ) 117 | labeled_start = True 118 | if not finished_with_silence and i==len(speech_segments)-1: 119 | break 120 | ax.axvline( 121 | end/1000+redemption_time, 122 | ymin=min(signal_array), 123 | ymax=max(signal_array), 124 | linestyle='dashed', 125 | color = '#f56f42', 126 | label=None if labeled_end else "speech_end" 127 | ) 128 | labeled_end = True 129 | ax.legend() 130 | 131 | ax2.axhline(y=redemption_time_samples, color = 'r', linestyle = 'dashed', label = "redemption_time") 132 | ax2.legend() 133 | 134 | ax3.axhline(y=positive_thresh, color = 'g', linestyle = 'dashed', label = "positive threshold") 135 | ax3.axhline(y=negative_thresh, color = 'r', linestyle = 'dashed', label = "negative threshold") 136 | ax3.legend() 137 | 138 | fill_regions = [False] * len(signal_array) 139 | 140 | for i in range(len(signal_array)): 141 | timestamp = 1000*i/sample_freq 142 | 143 | for (start, end) in speech_segments: 144 | if start <= timestamp < end: 145 | fill_regions[i] = True 146 | break 147 | 148 | ax.fill_between(times, min(signal_array), max(signal_array), where=fill_regions, alpha=0.5) 149 | 150 | if args.output: 151 | plt.tight_layout() 152 | plt.savefig(args.output, dpi=200) 153 | else: 154 | plt.show() 155 | -------------------------------------------------------------------------------- /tests/consistency.rs: -------------------------------------------------------------------------------- 1 | use hound::WavReader; 2 | use silero::*; 3 | use std::fmt; 4 | use std::path::Path; 5 | use tracing_test::traced_test; 6 | 7 | #[test] 8 | #[traced_test] 9 | fn compare_audio_1() { 10 | let audio = Path::new("tests/audio/sample_1.wav"); 11 | compare_audio(&audio); 12 | } 13 | 14 | #[test] 15 | #[traced_test] 16 | fn compare_audio_2() { 17 | let audio = Path::new("tests/audio/sample_2.wav"); 18 | compare_audio(&audio); 19 | } 20 | 21 | #[test] 22 | #[traced_test] 23 | fn compare_audio_3() { 24 | let audio = Path::new("tests/audio/sample_3.wav"); 25 | compare_audio(&audio); 26 | } 27 | 28 | #[test] 29 | #[traced_test] 30 | fn compare_audio_4() { 31 | let audio = Path::new("tests/audio/sample_4.wav"); 32 | compare_audio(&audio); 33 | } 34 | 35 | #[test] 36 | #[traced_test] 37 | fn compare_birds() { 38 | let audio = Path::new("tests/audio/birds.wav"); 39 | compare_audio(&audio); 40 | } 41 | 42 | fn compare_audio(audio: &Path) { 43 | let config = VadConfig::default(); 44 | 45 | let whole_file = silero_whole_file(audio, config.clone()); 46 | 47 | let chunks_30ms = silero_streaming(audio, 30, config.clone()); 48 | assert_eq!(whole_file, chunks_30ms); 49 | 50 | // 20ms initial remainder 51 | let chunks_100ms = silero_streaming(audio, 100, config.clone()); 52 | assert_eq!(whole_file, chunks_100ms); 53 | 54 | // 1ms initial remainder 55 | let chunks_35ms = silero_streaming(audio, 31, config.clone()); 56 | assert_eq!(whole_file, chunks_35ms); 57 | } 58 | 59 | #[derive(Clone, PartialEq, Eq)] 60 | struct Segment { 61 | start_timestamp_ms: usize, 62 | end_timestamp_ms: usize, 63 | /// Convert to i16 to make comparing samples easier 64 | samples: Vec, 65 | } 66 | 67 | impl fmt::Debug for Segment { 68 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 69 | f.debug_struct("Segment") 70 | .field("start_time_ms", &self.start_timestamp_ms) 71 | .field("end_time_ms", &self.end_timestamp_ms) 72 | .field("samples::len", &self.samples.len()) 73 | .finish() 74 | } 75 | } 76 | 77 | fn silero_whole_file(audio: &Path, config: VadConfig) -> Vec { 78 | let step = if config.sample_rate == 16000 { 79 | 1 80 | } else { 81 | 2 // Other sample rates are invalid so we'll just work on less data 82 | }; 83 | let samples: Vec = WavReader::open(audio) 84 | .unwrap() 85 | .into_samples() 86 | .step_by(step) 87 | .map(|x| { 88 | let modified = x.unwrap_or(0i16) as f32 / (i16::MAX as f32); 89 | modified.clamp(-1.0, 1.0) 90 | }) 91 | .collect(); 92 | 93 | let len = samples.len(); 94 | inner_vad_process(samples, len, config) 95 | } 96 | 97 | fn silero_streaming(audio: &Path, chunk_ms: usize, config: VadConfig) -> Vec { 98 | let chunk_size = (config.sample_rate * chunk_ms) / 1000; 99 | let step = if config.sample_rate == 16000 { 100 | 1 101 | } else { 102 | 2 // Other sample rates are invalid so we'll just work on less data 103 | }; 104 | let samples: Vec = WavReader::open(audio) 105 | .unwrap() 106 | .into_samples() 107 | .step_by(step) 108 | .map(|x| { 109 | let modified = x.unwrap_or(0i16) as f32 / (i16::MAX as f32); 110 | modified.clamp(-1.0, 1.0) 111 | }) 112 | .collect(); 113 | 114 | inner_vad_process(samples, chunk_size, config) 115 | } 116 | 117 | fn inner_vad_process(samples: Vec, chunk_size: usize, config: VadConfig) -> Vec { 118 | let mut result = vec![]; 119 | let mut session = VadSession::new(config.clone()).unwrap(); 120 | let num_chunks = samples.len() / chunk_size; 121 | for i in 0..num_chunks { 122 | let start = i * chunk_size; 123 | let end = if i < num_chunks - 1 { 124 | start + chunk_size 125 | } else { 126 | samples.len() 127 | }; 128 | 129 | let mut transitions = session.process(&samples[start..end]).unwrap(); 130 | for transition in transitions.drain(..) { 131 | if let VadTransition::SpeechEnd { 132 | start_timestamp_ms, 133 | end_timestamp_ms, 134 | samples, 135 | } = transition 136 | { 137 | let samples = samples 138 | .iter() 139 | .map(|x| (*x * i16::MAX as f32) as i16) 140 | .collect(); 141 | result.push(Segment { 142 | start_timestamp_ms, 143 | end_timestamp_ms, 144 | samples, 145 | }); 146 | } 147 | } 148 | } 149 | 150 | if session.is_speaking() { 151 | let end = session.session_time(); 152 | let start = end - session.current_speech_duration(); 153 | 154 | let samples = session 155 | .get_current_speech() 156 | .iter() 157 | .map(|x| (*x * i16::MAX as f32) as i16) 158 | .collect(); 159 | result.push(Segment { 160 | start_timestamp_ms: start.as_millis() as usize, 161 | end_timestamp_ms: end.as_millis() as usize, 162 | samples, 163 | }); 164 | } 165 | 166 | result 167 | } 168 | -------------------------------------------------------------------------------- /example/file_inference/src/audio_reading.rs: -------------------------------------------------------------------------------- 1 | //! Some useful utilities to handle audio file reading, resampling, and writing. Should work with 2 | //! any audio format. 3 | 4 | // System libraries. 5 | use std::fs::File; 6 | use std::path::Path; 7 | 8 | // Third party libraries. 9 | use anyhow::Result; 10 | use symphonia::core::audio::SampleBuffer; 11 | use symphonia::core::codecs::DecoderOptions; 12 | use symphonia::core::errors::Error; 13 | use symphonia::core::formats::FormatOptions; 14 | use symphonia::core::io::MediaSourceStream; 15 | use symphonia::core::meta::MetadataOptions; 16 | use symphonia::core::probe::Hint; 17 | use tracing::{debug, info}; 18 | 19 | // Project libraries. 20 | use silero::audio_resampler::resample_pcm; 21 | 22 | /// The way to deal with Stereo audio file 23 | pub enum MultiChannelStrategy { 24 | /// Only take the first channel data for VAD inference. 25 | FirstOnly, 26 | 27 | /// Take the average of all channels for VAD inference. 28 | Average, 29 | } 30 | 31 | /// Read an audio file of arbitrary format into pcm data with desired sampling rate. 32 | /// Code modified from https://github.com/pdeljanov/Symphonia/blob/master/symphonia/examples/basic-interleaved.rs 33 | pub fn read_audio( 34 | file_path: impl AsRef, 35 | multi_channel_strategy: MultiChannelStrategy, 36 | ) -> (Vec, usize) { 37 | info!("Reading {}", file_path.as_ref().display()); 38 | // Create a media source. Note that the MediaSource trait is automatically implemented for File, 39 | // among other types. 40 | let file = Box::new(File::open(file_path).unwrap()); 41 | 42 | // Create the media source stream using the boxed media source from above. 43 | let mss = MediaSourceStream::new(file, Default::default()); 44 | 45 | // Create a hint to help the format registry guess what format reader is appropriate. In this 46 | // example we'll leave it empty. 47 | let hint = Hint::new(); 48 | 49 | // Use the default options when reading and decoding. 50 | let format_opts: FormatOptions = Default::default(); 51 | let metadata_opts: MetadataOptions = Default::default(); 52 | let decoder_opts: DecoderOptions = Default::default(); 53 | 54 | // Probe the media source stream for a format. 55 | let probed = symphonia::default::get_probe() 56 | .format(&hint, mss, &format_opts, &metadata_opts) 57 | .unwrap(); 58 | 59 | // Get the format reader yielded by the probe operation. 60 | let mut format = probed.format; 61 | 62 | // Get the default track. 63 | let track = format.default_track().unwrap(); 64 | 65 | // Create a decoder for the track. 66 | let mut decoder = symphonia::default::get_codecs() 67 | .make(&track.codec_params, &decoder_opts) 68 | .unwrap(); 69 | 70 | // Store the track identifier, we'll use it to filter packets. 71 | let track_id = track.id; 72 | 73 | let mut sample_buf = None; 74 | let mut interleave_samples = vec![]; 75 | let mut original_sample_rate = 0; 76 | let mut num_of_channels = 0; 77 | 78 | loop { 79 | // Get the next packet from the format reader. 80 | let packet = match format.next_packet() { 81 | Ok(packet) => packet, 82 | Err(_) => { 83 | break; 84 | } 85 | }; 86 | 87 | // If the packet does not belong to the selected track, skip it. 88 | if packet.track_id() != track_id { 89 | continue; 90 | } 91 | 92 | // Decode the packet into audio samples, ignoring any decode errors. 93 | match decoder.decode(&packet) { 94 | Ok(audio_buf) => { 95 | // The decoded audio samples may now be accessed via the audio buffer if per-channel 96 | // slices of samples in their native decoded format is desired. Use-cases where 97 | // the samples need to be accessed in an interleaved order or converted into 98 | // another sample format, or a byte buffer is required, are covered by copying the 99 | // audio buffer into a sample buffer or raw sample buffer, respectively. In the 100 | // example below, we will copy the audio buffer into a sample buffer in an 101 | // interleaved order while also converting to a f32 sample format. 102 | 103 | // If this is the *first* decoded packet, create a sample buffer matching the 104 | // decoded audio buffer format. 105 | if sample_buf.is_none() { 106 | // Get the audio buffer specification. 107 | let spec = *audio_buf.spec(); 108 | original_sample_rate = spec.rate; 109 | num_of_channels = spec.channels.count(); 110 | debug!( 111 | "Original file has {} channel(s) with sample rate {}", 112 | num_of_channels, original_sample_rate 113 | ); 114 | 115 | // Get the capacity of the decoded buffer. Note: This is capacity, not length! 116 | let duration = audio_buf.capacity() as u64; 117 | 118 | // Create the f32 sample buffer. 119 | sample_buf = Some(SampleBuffer::::new(duration, spec)); 120 | } 121 | 122 | // Copy the decoded audio buffer into the sample buffer in an interleaved format. 123 | if let Some(buf) = &mut sample_buf { 124 | buf.copy_interleaved_ref(audio_buf); 125 | interleave_samples.extend_from_slice(buf.samples()); 126 | } 127 | } 128 | Err(Error::DecodeError(_)) => (), 129 | Err(Error::IoError(e)) => { 130 | dbg!(e); 131 | break; 132 | } 133 | Err(_) => break, 134 | } 135 | } 136 | 137 | // Now we have interleaved audio, need to convert it to channel based. 138 | let stereo_audio = interleaved_to_channel(interleave_samples, num_of_channels); 139 | 140 | // Silero VAD only work with mono audio. 141 | let mono_audio = stereo_to_mono(stereo_audio, multi_channel_strategy); 142 | 143 | (mono_audio, original_sample_rate as usize) 144 | } 145 | 146 | /// Convert stereo audio to mono audio based on [MultiChannelStrategy]. 147 | fn stereo_to_mono(stereo: Vec>, multi_channel_strategy: MultiChannelStrategy) -> Vec { 148 | match multi_channel_strategy { 149 | MultiChannelStrategy::FirstOnly => stereo[0].clone(), 150 | MultiChannelStrategy::Average => { 151 | let samples = stereo[0].len(); 152 | let channels = stereo.len(); 153 | let mut mono = Vec::new(); 154 | mono.resize(samples, 0.0); 155 | 156 | for i in 0..samples { 157 | let mut sum = 0.0; 158 | for channel in 0..channels { 159 | sum += stereo[channel][i]; 160 | } 161 | mono[i] = sum / channels as f32; 162 | } 163 | mono 164 | } 165 | } 166 | } 167 | 168 | /// Convert an interleaved pcm data to channel based. 169 | fn interleaved_to_channel(interleave_samples: Vec, num_of_channels: usize) -> Vec> { 170 | let mut audio = vec![vec![]; num_of_channels]; 171 | let mut channel_idx = 0; 172 | for sample in interleave_samples { 173 | audio[channel_idx].push(sample); 174 | channel_idx += 1; 175 | channel_idx %= num_of_channels; 176 | } 177 | 178 | // A quick sanity check 179 | let len = audio[0].len(); 180 | for channel in &audio { 181 | assert_eq!(len, channel.len()); 182 | } 183 | 184 | audio 185 | } 186 | -------------------------------------------------------------------------------- /tests/snapshot.rs: -------------------------------------------------------------------------------- 1 | //! Snapshot tests of the VAD behaviour. 2 | //! 3 | //! The general approach of this is snapshot testing like we might see with a crate like 4 | //! [insta](crates.io/crates/insta) but we're not going to use insta. Why? Because it is a bit 5 | //! fiddly to fit it into a workflow where test failures may need an analysis of the data and 6 | //! neural network output to see if the snapshot should be updated. And without being able to make 7 | //! use of the diff-review and accepting tools it seems easier to roll our own solution specialised 8 | //! to the application. 9 | //! 10 | //! So here I'll make a report type, and for each test we'll compare to an existing report and also 11 | //! save the new reports if they differ. And provide some scripts to generally plot the data in the 12 | //! reports versus the audio and help us debug via charts! Each test will be ran for all audio in 13 | //! the audio folder as well. 14 | //! 15 | //! Also, all test audios will be 16kHz to make it easy to test silero in both 16kHz and 8kHz modes. 16 | use approx::assert_ulps_eq; 17 | use hound::WavReader; 18 | use serde::{Deserialize, Serialize}; 19 | use silero::*; 20 | use std::collections::BTreeMap; 21 | use std::fs; 22 | use std::path::{Path, PathBuf}; 23 | use std::time::Duration; 24 | use tracing_test::traced_test; 25 | 26 | #[derive(Default, Debug, PartialEq, Deserialize, Serialize)] 27 | struct Summary { 28 | input_size_ms: usize, 29 | config: VadConfig, 30 | summary: BTreeMap, 31 | } 32 | 33 | #[derive(Default, Debug, PartialEq, Deserialize, Serialize)] 34 | struct Report { 35 | transitions: Vec, 36 | current_session_samples: Vec, 37 | current_silence_samples: Vec, 38 | current_speech_samples: Vec, 39 | likelihoods: Vec, 40 | } 41 | 42 | #[test] 43 | #[traced_test] 44 | fn chunk_50_long_prespeech_16k() { 45 | let mut config = VadConfig::default(); 46 | config.pre_speech_pad = Duration::from_millis(1000); 47 | run_snapshot_test(50, config, "long_pre_speech"); 48 | } 49 | 50 | #[test] 51 | #[traced_test] 52 | fn chunk_50_short_redemption_16k() { 53 | let mut config = VadConfig::default(); 54 | config.redemption_time = Duration::from_millis(300); 55 | run_snapshot_test(50, config, "short_redemption"); 56 | } 57 | 58 | #[test] 59 | #[traced_test] 60 | fn chunk_50_default_params_16k() { 61 | run_snapshot_test(50, VadConfig::default(), "default"); 62 | } 63 | 64 | #[test] 65 | #[traced_test] 66 | fn chunk_50_default_params_8k() { 67 | let mut config = VadConfig::default(); 68 | config.sample_rate = 8000; 69 | run_snapshot_test(50, config, "default"); 70 | } 71 | 72 | #[test] 73 | #[traced_test] 74 | fn chunk_30_default_params_16k() { 75 | run_snapshot_test(30, VadConfig::default(), "default"); 76 | } 77 | 78 | #[test] 79 | #[traced_test] 80 | fn chunk_30_default_params_8k() { 81 | let mut config = VadConfig::default(); 82 | config.sample_rate = 8000; 83 | run_snapshot_test(30, config, "default"); 84 | } 85 | 86 | #[test] 87 | #[traced_test] 88 | fn chunk_20_default_params_16k() { 89 | run_snapshot_test(20, VadConfig::default(), "default"); 90 | } 91 | 92 | #[test] 93 | #[traced_test] 94 | fn chunk_20_default_params_8k() { 95 | let mut config = VadConfig::default(); 96 | config.sample_rate = 8000; 97 | run_snapshot_test(20, config, "default"); 98 | } 99 | 100 | fn run_snapshot_test(chunk_ms: usize, config: VadConfig, config_name: &str) { 101 | let audios = get_audios(); 102 | 103 | let chunk_size = get_chunk_size(config.sample_rate, chunk_ms); 104 | 105 | let mut summary = BTreeMap::new(); 106 | 107 | for audio in audios.iter() { 108 | let mut session = VadSession::new(config.clone()).unwrap(); 109 | let mut report = Report::default(); 110 | let step = if config.sample_rate == 16000 { 111 | 1 112 | } else { 113 | 2 // Other sample rates are invalid so we'll just work on less data 114 | }; 115 | let samples: Vec = WavReader::open(&audio) 116 | .unwrap() 117 | .into_samples() 118 | .step_by(step) 119 | .map(|x| { 120 | let modified = x.unwrap_or(0i16) as f32 / (i16::MAX as f32); 121 | modified.clamp(-1.0, 1.0) 122 | }) 123 | .collect(); 124 | 125 | let num_chunks = samples.len() / chunk_size; 126 | let mut last_end = 0; 127 | for i in 0..num_chunks { 128 | let start = i * chunk_size; 129 | let end = if i < num_chunks - 1 { 130 | start + chunk_size 131 | } else { 132 | samples.len() 133 | }; 134 | 135 | let mut transitions = session.process(&samples[start..end]).unwrap(); 136 | report.transitions.append(&mut transitions); 137 | report 138 | .current_silence_samples 139 | .push(session.current_silence_samples()); 140 | report 141 | .current_speech_samples 142 | .push(session.current_speech_samples()); 143 | report 144 | .current_session_samples 145 | .push(session.session_audio_samples()); 146 | 147 | if let Ok(network_outputs) = session.forward(samples[last_end..end].to_vec()) { 148 | let prob = *network_outputs 149 | .try_extract_array::() 150 | .unwrap() 151 | .first() 152 | .unwrap() 153 | * 100.0; 154 | report.likelihoods.push(prob as usize); 155 | // Try and solve the too small inference issue 156 | last_end = end; 157 | } 158 | } 159 | summary.insert(audio.to_path_buf(), report); 160 | } 161 | 162 | let summary = Summary { 163 | input_size_ms: chunk_ms, 164 | summary, 165 | config, 166 | }; 167 | let report = serde_json::to_string_pretty(&summary).unwrap(); 168 | 169 | let name = format!( 170 | "chunk_{}_{}Hz_{}.json", 171 | chunk_ms, config.sample_rate, config_name 172 | ); 173 | 174 | let current_report = Path::new("target").join(&name); 175 | let baseline_report = Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/data")).join(&name); 176 | 177 | fs::write(¤t_report, &report).unwrap(); 178 | 179 | println!("Loading snapshot from: {}", baseline_report.display()); 180 | let expected = fs::read_to_string(&baseline_report).unwrap(); 181 | let expected: Summary = serde_json::from_str(&expected).unwrap(); 182 | 183 | println!( 184 | "Checking current results {} with snapshot {}", 185 | current_report.display(), 186 | baseline_report.display() 187 | ); 188 | 189 | // Lets do some basic checks first just to make sure we're not complete trash 190 | println!("Checking snapshot is generated with same configuration!"); 191 | compare_configs(&summary.config, &expected.config); 192 | assert_eq!(summary.input_size_ms, expected.input_size_ms); 193 | 194 | let mut failing_files = vec![]; 195 | println!(); 196 | 197 | for sample in summary.summary.keys() { 198 | let baseline = &summary.summary[sample]; 199 | let current = &expected.summary[sample]; 200 | 201 | if baseline != current { 202 | println!("{} is failing", sample.display()); 203 | if baseline.transitions != current.transitions { 204 | println!("\tDifference in transitions list!"); 205 | } 206 | if baseline.current_silence_samples != current.current_silence_samples { 207 | println!("\tDifference in silence lengths"); 208 | } 209 | if baseline.current_speech_samples != current.current_speech_samples { 210 | println!("\tDifference in speech lengths"); 211 | } 212 | failing_files.push(sample.to_path_buf()); 213 | } 214 | } 215 | if !failing_files.is_empty() { 216 | println!(); 217 | println!("You have some failing files and targets. If you get a snapshot file and audio you can plot it via our plot_audio script e.g."); 218 | println!(); 219 | println!( 220 | "python3 scripts/plot_audio.py -a {} -i {}", 221 | failing_files[0].display(), 222 | current_report.display() 223 | ); 224 | println!(); 225 | 226 | panic!("The following files are failing: {:?}", failing_files); 227 | } 228 | } 229 | 230 | fn compare_configs(a: &VadConfig, b: &VadConfig) { 231 | assert_ulps_eq!(a.positive_speech_threshold, b.positive_speech_threshold); 232 | assert_ulps_eq!(a.negative_speech_threshold, b.negative_speech_threshold); 233 | assert_eq!(a.pre_speech_pad, b.pre_speech_pad); 234 | assert_eq!(a.redemption_time, b.redemption_time); 235 | assert_eq!(a.sample_rate, b.sample_rate); 236 | assert_eq!(a.min_speech_time, b.min_speech_time); 237 | } 238 | 239 | fn get_audios() -> Vec { 240 | let audio_dir = Path::new("tests/audio"); 241 | let mut result = vec![]; 242 | for entry in fs::read_dir(&audio_dir).unwrap() { 243 | let entry = entry.unwrap(); 244 | let path = entry.path(); 245 | if !path.is_dir() { 246 | result.push(path.to_path_buf()); 247 | } 248 | } 249 | assert!(!result.is_empty()); 250 | result 251 | } 252 | 253 | fn get_chunk_size(sample_rate: usize, chunk_ms: usize) -> usize { 254 | (sample_rate * chunk_ms) / 1000 255 | } 256 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![doc = include_str!("../README.md")] 2 | #[cfg(feature = "audio_resampler")] 3 | pub use crate::audio_resampler::resample_pcm; 4 | pub use crate::errors::VadError; 5 | use anyhow::{bail, Context, Result}; 6 | use ndarray::{Array1, Array2, Array3, ArrayBase, Ix1, Ix3, OwnedRepr}; 7 | use ort::session::{builder::GraphOptimizationLevel, Session}; 8 | use ort::value::TensorRef; 9 | use std::fmt; 10 | use std::ops::Range; 11 | use std::path::Path; 12 | use std::time::Duration; 13 | use tracing::trace; 14 | 15 | #[cfg(feature = "audio_resampler")] 16 | pub mod audio_resampler; 17 | pub mod errors; 18 | 19 | /// Parameters used to configure a vad session. These will determine the sensitivity and switching 20 | /// speed of detection. 21 | #[derive(Clone, Copy, Debug, PartialEq)] 22 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 23 | pub struct VadConfig { 24 | pub positive_speech_threshold: f32, 25 | pub negative_speech_threshold: f32, 26 | pub pre_speech_pad: Duration, 27 | pub post_speech_pad: Duration, 28 | pub redemption_time: Duration, 29 | pub sample_rate: usize, 30 | pub min_speech_time: Duration, 31 | } 32 | 33 | /// A VAD session create one of these for each audio stream you want to detect voice activity on 34 | /// and feed the audio into it. 35 | pub struct VadSession { 36 | config: VadConfig, 37 | model: Session, // TODO: would this be safe to share? does the runtime graph hold any state? 38 | h_tensor: ArrayBase, Ix3>, 39 | c_tensor: ArrayBase, Ix3>, 40 | sample_rate_tensor: ArrayBase, Ix1>, 41 | state: VadState, 42 | session_audio: Vec, 43 | processed_samples: usize, 44 | deleted_samples: usize, 45 | silent_samples: usize, 46 | 47 | /// Current start of the speech in milliseconds 48 | speech_start_ms: Option, 49 | 50 | /// Cached current active samples 51 | cached_active_speech: Vec, 52 | } 53 | 54 | impl fmt::Debug for VadSession { 55 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 56 | f.debug_struct("VadSession") 57 | .field("config", &self.config) 58 | .field("model", &self.model) 59 | .field("state", &self.state) 60 | .field("session_audio::len", &self.session_audio.len()) 61 | .field( 62 | "cached_active_speech::len", 63 | &self.cached_active_speech.len(), 64 | ) 65 | .field("processed_samples", &self.processed_samples) 66 | .field("deleted_samples", &self.deleted_samples) 67 | .field("silent_samples", &self.silent_samples) 68 | .field("speech_start_ms", &self.speech_start_ms) 69 | .finish() 70 | } 71 | } 72 | 73 | /// Current state of the VAD (speaking or silent) 74 | #[derive(Clone, Debug)] 75 | enum VadState { 76 | Speech { 77 | start_ms: usize, 78 | redemption_passed: bool, 79 | speech_time: Duration, 80 | }, 81 | Silence, 82 | } 83 | 84 | #[derive(Clone, Debug)] 85 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 86 | pub enum VadTransition { 87 | SpeechStart { 88 | /// When the speech started, in milliseconds since the start of the VAD session. 89 | timestamp_ms: usize, 90 | }, 91 | SpeechEnd { 92 | /// When the speech started, in milliseconds since the start of the VAD session. 93 | start_timestamp_ms: usize, 94 | /// When the speech ended, in milliseconds since the start of the VAD session. 95 | end_timestamp_ms: usize, 96 | /// The active speech samples. This field is skipped in serde output even serde feature is enabled. 97 | #[cfg_attr(feature = "serde", serde(default, skip))] 98 | samples: Vec, 99 | }, 100 | } 101 | 102 | impl PartialEq for VadTransition { 103 | fn eq(&self, other: &Self) -> bool { 104 | match (self, other) { 105 | ( 106 | VadTransition::SpeechStart { timestamp_ms: ts1 }, 107 | VadTransition::SpeechStart { timestamp_ms: ts2 }, 108 | ) => ts1 == ts2, 109 | ( 110 | VadTransition::SpeechEnd { 111 | start_timestamp_ms: ts1, 112 | end_timestamp_ms: ts2, 113 | .. 114 | }, 115 | VadTransition::SpeechEnd { 116 | start_timestamp_ms: ts3, 117 | end_timestamp_ms: ts4, 118 | .. 119 | }, 120 | ) => ts1 == ts3 && ts2 == ts4, 121 | _ => false, 122 | } 123 | } 124 | } 125 | 126 | impl Eq for VadTransition {} 127 | 128 | impl VadSession { 129 | /// Create a new VAD session loading an onnx file from the specified path and using the 130 | /// provided config. 131 | pub fn new_from_path(file: impl AsRef, config: VadConfig) -> Result { 132 | let bytes = std::fs::read(file.as_ref()) 133 | .with_context(|| format!("Couldn't read onnx file: {}", file.as_ref().display()))?; 134 | Self::new_from_bytes(&bytes, config) 135 | } 136 | 137 | /// Create a new VAD session loading an onnx file from memory and using the provided config. 138 | pub fn new_from_bytes(model_bytes: &[u8], config: VadConfig) -> Result { 139 | if ![8000_usize, 16000].contains(&config.sample_rate) { 140 | bail!("Unsupported sample rate, use 8000 or 16000!"); 141 | } 142 | let model = Session::builder()? 143 | .with_optimization_level(GraphOptimizationLevel::Level3)? 144 | .with_intra_threads(4)? 145 | .commit_from_memory(model_bytes)?; 146 | let h_tensor = Array3::::zeros((2, 1, 64)); 147 | let c_tensor = Array3::::zeros((2, 1, 64)); 148 | let sample_rate_tensor = Array1::from_vec(vec![config.sample_rate as i64]); 149 | 150 | Ok(Self { 151 | config, 152 | model, 153 | h_tensor, 154 | c_tensor, 155 | sample_rate_tensor, 156 | state: VadState::Silence, 157 | session_audio: vec![], 158 | processed_samples: 0, 159 | deleted_samples: 0, 160 | silent_samples: 0, 161 | speech_start_ms: None, 162 | cached_active_speech: vec![], 163 | }) 164 | } 165 | 166 | /// Create a new VAD session using the provided config. The ONNX file has been statically 167 | /// embedded within the library so this will increase binary size by 1.7M. 168 | #[cfg(feature = "static-model")] 169 | pub fn new(config: VadConfig) -> Result { 170 | let model_bytes: &[u8] = include_bytes!(concat!( 171 | env!("CARGO_MANIFEST_DIR"), 172 | "/models/silero_vad.onnx" 173 | )); 174 | Self::new_from_bytes(model_bytes, config) 175 | } 176 | 177 | /// Reserve the session audio buffer size by number of samples 178 | pub fn reserve_audio_buffer(&mut self, samples: usize) { 179 | self.session_audio.reserve(samples); 180 | } 181 | 182 | pub fn validate_input(&self, audio_frame: &[f32]) -> Result<()> { 183 | if audio_frame 184 | .iter() 185 | .all(|&sample| -1.0 <= sample && sample <= 1.0) 186 | { 187 | Ok(()) 188 | } else { 189 | Err(VadError::InvalidData.into()) 190 | } 191 | } 192 | 193 | /// Pass in some audio to the VAD and return a list of any speech transitions that happened 194 | /// during the segment. 195 | /// 196 | /// If "audio_resampler" feature is enabled, then this function will resample whatever it 197 | /// receives to 16000Hz samples. If not enabled, then user input is expected to be either 198 | /// 8000 or 16000Hz. 199 | pub fn process(&mut self, audio_frame: &[f32]) -> Result> { 200 | #[cfg(debug_assertions)] 201 | if let Err(e) = self.validate_input(audio_frame) { 202 | return Err(e); 203 | } 204 | 205 | #[cfg(feature = "audio_resampler")] 206 | let audio_frame = if ![8000, 16000].contains(&self.config.sample_rate) { 207 | &resample_pcm(audio_frame.to_vec(), self.config.sample_rate, 16000)? 208 | } else { 209 | audio_frame 210 | }; 211 | 212 | const VAD_BUFFER: Duration = Duration::from_millis(30); // TODO This should be configurable 213 | let vad_segment_length = VAD_BUFFER.as_millis() as usize * self.config.sample_rate / 1000; 214 | 215 | let unprocessed = self.deleted_samples + self.session_audio.len() - self.processed_samples; 216 | let num_chunks = (unprocessed + audio_frame.len()) / vad_segment_length; 217 | 218 | self.session_audio.extend_from_slice(audio_frame); 219 | 220 | let mut transitions = vec![]; 221 | 222 | for _ in 0..num_chunks { 223 | // We have removed non-determinism by only keeping to 30ms frames, but this means any 224 | // remainder at the end of the audio file will never be processed. This is fine because 225 | // we don't expect to get useful speech in <30ms and if it's at the end and it's 226 | // speaking we don't lose anything by keeping an extra silence <30ms at the end. 227 | // 228 | // So in summary, the remainder will be processed on the next call to process, but if 229 | // there's no more calls to process it will be left untouched. 230 | let sample_range = (self.processed_samples - self.deleted_samples) 231 | ..(self.processed_samples + vad_segment_length - self.deleted_samples); 232 | let vad_result = self.process_internal(sample_range)?; 233 | 234 | if let Some(vad_ev) = vad_result { 235 | transitions.push(vad_ev); 236 | } 237 | } 238 | Ok(transitions) 239 | } 240 | 241 | pub fn forward(&mut self, input: Vec) -> Result { 242 | let samples = input.len(); 243 | let audio_tensor = Array2::from_shape_vec((1, samples), input)?; 244 | let mut result = self.model.run(ort::inputs![ 245 | TensorRef::from_array_view(audio_tensor.view())?, 246 | TensorRef::from_array_view(self.sample_rate_tensor.view())?, 247 | TensorRef::from_array_view(self.h_tensor.view())?, 248 | TensorRef::from_array_view(self.c_tensor.view())? 249 | ])?; 250 | 251 | // Update internal state tensors. 252 | self.h_tensor = result 253 | .get("hn") 254 | .unwrap() 255 | .try_extract_array::()? 256 | .to_owned() 257 | .into_shape_with_order((2, 1, 64)) 258 | .context("Shape mismatch for h_tensor")?; 259 | 260 | self.c_tensor = result 261 | .get("cn") 262 | .unwrap() 263 | .try_extract_array::()? 264 | .to_owned() 265 | .into_shape_with_order((2, 1, 64)) 266 | .context("Shape mismatch for h_tensor")?; 267 | 268 | let prob_tensor = result.remove("output").unwrap(); 269 | Ok(prob_tensor) 270 | } 271 | 272 | /// Advance the VAD state machine with an audio frame. Keep between 30-96ms in length. 273 | /// Return indicates if a transition from speech to silence (or silence to speech) occurred. 274 | /// 275 | /// Important: don't implement your own endpointing logic. 276 | /// Instead, when a `SpeechEnd` is returned, you can use the `get_current_speech()` method to retrieve the audio. 277 | fn process_internal(&mut self, range: Range) -> Result> { 278 | let audio_frame = self.session_audio[range].to_vec(); 279 | let samples = audio_frame.len(); 280 | let frame_duration = self.samples_to_duration(samples); 281 | 282 | let result = self.forward(audio_frame)?; 283 | 284 | let prob = *result.try_extract_array::().unwrap().first().unwrap(); 285 | 286 | let mut vad_change = None; 287 | 288 | if prob < self.config.negative_speech_threshold { 289 | self.silent_samples += samples; 290 | } else { 291 | self.silent_samples = 0; 292 | } 293 | 294 | trace!( 295 | vad_likelihood = prob, 296 | samples, 297 | silent_samples = self.silent_samples, 298 | "performed silero inference" 299 | ); 300 | 301 | let current_silence = self.current_silence_duration(); 302 | 303 | match self.state { 304 | VadState::Silence => { 305 | let start_ms = self 306 | .processed_duration() 307 | .saturating_sub(self.config.pre_speech_pad) 308 | .as_millis() as usize; 309 | let deleted_end = 310 | self.samples_to_duration(self.deleted_samples).as_millis() as usize; 311 | let start_ms = start_ms.max(deleted_end); 312 | if prob > self.config.positive_speech_threshold { 313 | self.state = VadState::Speech { 314 | start_ms: start_ms, 315 | redemption_passed: false, 316 | speech_time: Duration::ZERO, 317 | }; 318 | } 319 | } 320 | VadState::Speech { 321 | start_ms, 322 | ref mut redemption_passed, 323 | ref mut speech_time, 324 | } => { 325 | *speech_time += frame_duration; 326 | if !*redemption_passed && *speech_time > self.config.min_speech_time { 327 | *redemption_passed = true; 328 | // TODO: the pre speech padding should not cross over the previous speech->silence 329 | // transition, if there was one 330 | vad_change = Some(VadTransition::SpeechStart { 331 | timestamp_ms: start_ms, 332 | }); 333 | self.speech_start_ms = Some(start_ms); 334 | } 335 | 336 | if prob < self.config.negative_speech_threshold { 337 | if !*redemption_passed { 338 | self.state = VadState::Silence; 339 | } else if current_silence > self.config.redemption_time { 340 | if *redemption_passed { 341 | let speech_end_ms = (self.processed_samples + samples 342 | - self.silent_samples) 343 | / (self.config.sample_rate / 1000); 344 | 345 | // Since speech_end_ms does not include silent_samples, the post 346 | // padding should be added to speech_end_ms. 347 | let mut speech_end_with_pad_ms = 348 | speech_end_ms + self.config.post_speech_pad.as_millis() as usize; 349 | 350 | let end_time_ms = self.session_time().as_millis() as usize; 351 | 352 | if end_time_ms < speech_end_with_pad_ms { 353 | trace!("Padding exceeds speech buffer, truncating cached speech"); 354 | speech_end_with_pad_ms = end_time_ms; 355 | } 356 | 357 | self.cached_active_speech = self 358 | .get_speech(start_ms, Some(speech_end_with_pad_ms)) 359 | .to_vec(); 360 | 361 | vad_change = Some(VadTransition::SpeechEnd { 362 | start_timestamp_ms: start_ms, 363 | end_timestamp_ms: speech_end_with_pad_ms, 364 | samples: self.cached_active_speech.clone(), 365 | }); 366 | 367 | // Need to delete the current speech samples from internal buffer to prevent OOM. 368 | assert!(self.speech_start_ms.is_some()); 369 | let speech_end_idx = self.unchecked_duration_to_index( 370 | Duration::from_millis(speech_end_ms as u64), 371 | ); 372 | let to_delete_idx = 0..(speech_end_idx + 1); 373 | self.session_audio.drain(to_delete_idx); 374 | self.deleted_samples += speech_end_idx + 1; 375 | self.speech_start_ms = None; 376 | } 377 | self.state = VadState::Silence 378 | } 379 | } 380 | } 381 | }; 382 | 383 | self.processed_samples += samples; 384 | 385 | Ok(vad_change) 386 | } 387 | 388 | /// Removes the starting silence from the session audio. If the vad is speaking this will 389 | /// remove all audio up-to the utterance start. If it is not speaking it will keep silence 390 | /// equal to the pre-speech padding frames at the end. 391 | pub fn trim_start_silence(&mut self) { 392 | let last_index = if let Some(start_ms) = self.speech_start_ms { 393 | self.duration_to_index(Duration::from_millis(start_ms as u64)) 394 | } else { 395 | let remove_to = self 396 | .session_time() 397 | .saturating_sub(self.config.pre_speech_pad); 398 | self.duration_to_index(remove_to) 399 | }; 400 | if let Some(last_index) = last_index { 401 | self.session_audio.drain(..last_index); 402 | self.deleted_samples += last_index; 403 | } 404 | } 405 | 406 | /// This will remove audio in the buffer until a duration and panic if it exceeds the duration. 407 | /// This won't touch the active speech cache or the VAD state. It's intended usage is if the 408 | /// current speech buffer is too long and you want to remove some for processing and not have 409 | /// it be re-processed or considered again. 410 | /// 411 | /// If there is no remaining audio within the range this will return an empty vector. 412 | /// Additionally, if the speech is just in the cached last-segment it won't take from that 413 | /// (though this could be done in the future). 414 | /// 415 | /// # Panics 416 | /// 417 | /// If the time given is beyond the range of the current session this will panic. 418 | pub fn take_until(&mut self, end: Duration) -> Vec { 419 | if end > self.session_time() { 420 | panic!( 421 | "{}ms is greater than session time of {}ms", 422 | end.as_millis(), 423 | self.session_time().as_millis() 424 | ); 425 | } else { 426 | match self.duration_to_index(end) { 427 | Some(s) => { 428 | let mut returned_audio = self.session_audio.split_off(s); 429 | std::mem::swap(&mut self.session_audio, &mut returned_audio); 430 | self.deleted_samples += returned_audio.len(); 431 | if matches!(self.state, VadState::Speech { .. }) { 432 | if let Some(start_ms) = self.speech_start_ms.take() { 433 | if start_ms < end.as_millis() as usize { 434 | self.speech_start_ms = Some(end.as_millis() as usize); 435 | } 436 | } 437 | } 438 | returned_audio 439 | } 440 | None => vec![], 441 | } 442 | } 443 | } 444 | 445 | /// Returns whether the vad current believes the audio to contain speech 446 | pub fn is_speaking(&self) -> bool { 447 | matches!(self.state, VadState::Speech { 448 | redemption_passed, .. 449 | } if redemption_passed) 450 | } 451 | 452 | /// Takes a duration and converts it to an index if it's within the current session audio or 453 | /// `None` if it's not. 454 | /// 455 | /// # Panics 456 | /// 457 | /// If this is out of the range it will panic 458 | fn unchecked_duration_to_index(&self, duration: Duration) -> usize { 459 | match self.duration_to_index(duration) { 460 | Some(idx) => idx, 461 | None => panic!( 462 | "Duration {}ms is outside of session audio range", 463 | duration.as_millis() 464 | ), 465 | } 466 | } 467 | 468 | /// Takes a duration and converts it to an index if it's within the current session audio or 469 | /// `None` if it's not. 470 | fn duration_to_index(&self, duration: Duration) -> Option { 471 | let unadjusted_index = duration.as_millis() as usize * (self.config.sample_rate / 1000); 472 | if unadjusted_index < self.deleted_samples { 473 | None 474 | } else { 475 | Some(unadjusted_index - self.deleted_samples) 476 | } 477 | } 478 | 479 | /// Gets the speech within a given range of milliseconds. You can use previous speech start/end 480 | /// event pairs to get speech windows before the current speech using this API. If end is 481 | /// `None` this will return from the start point to the end of the buffer. 482 | /// 483 | /// # Panics 484 | /// 485 | /// If the range is out of bounds of the speech buffer this method will panic due to an 486 | /// assertion failure. 487 | pub fn get_speech(&self, start_ms: usize, end_ms: Option) -> &[f32] { 488 | let speech_start_idx = 489 | self.unchecked_duration_to_index(Duration::from_millis(start_ms as u64)); 490 | if let Some(speech_end) = end_ms { 491 | let speech_end_idx = 492 | self.unchecked_duration_to_index(Duration::from_millis(speech_end as u64)); 493 | &self.session_audio[speech_start_idx..speech_end_idx] 494 | } else { 495 | &self.session_audio[speech_start_idx..] 496 | } 497 | } 498 | 499 | /// Gets a buffer of the most recent active speech frames from the time the speech started to the 500 | /// end of the speech. Parameters from `VadConfig` have already been applied here so this isn't 501 | /// derived from the raw VAD inferences but instead after padding and filtering operations have 502 | /// been applied. 503 | pub fn get_current_speech(&self) -> &[f32] { 504 | if let Some(speech_start) = self.speech_start_ms { 505 | if self 506 | .duration_to_index(Duration::from_millis(speech_start as u64)) 507 | .is_some() 508 | { 509 | self.get_speech(speech_start, None) 510 | } else { 511 | &self.cached_active_speech 512 | } 513 | } else { 514 | &self.cached_active_speech 515 | } 516 | } 517 | 518 | /// Get how long the current speech is in samples. 519 | pub fn current_speech_samples(&self) -> usize { 520 | self.get_current_speech().len() 521 | } 522 | 523 | /// Returns the duration of the current speech segment. It is possible for this and 524 | /// `Self::current_silence_duration` to both report >0s at the same time as this takes into 525 | /// account the switching and padding parameters of the VAD whereas the silence measure ignores 526 | /// them instead of just focusing on raw network output. 527 | pub fn current_speech_duration(&self) -> Duration { 528 | self.samples_to_duration(self.current_speech_samples()) 529 | } 530 | 531 | /// Get the current duration of the VAD session, which includes both processed and unprocessed 532 | /// samples. 533 | pub fn session_time(&self) -> Duration { 534 | self.samples_to_duration(self.session_audio.len() + self.deleted_samples) 535 | } 536 | 537 | /// Get the current duration of processed samples. A sample is considered as processed if it has 538 | /// been seen by Silero neural network. 539 | pub fn processed_duration(&self) -> Duration { 540 | self.samples_to_duration(self.processed_samples) 541 | } 542 | 543 | /// Reset the status of the model 544 | // TODO should this reset the audio buffer as well? 545 | pub fn reset(&mut self) { 546 | self.h_tensor = Array3::::zeros((2, 1, 64)); 547 | self.c_tensor = Array3::::zeros((2, 1, 64)); 548 | self.speech_start_ms = None; 549 | self.silent_samples = 0; 550 | self.state = VadState::Silence; 551 | } 552 | 553 | /// Returns the length of the end silence in number of samples. The VAD may be showing this as 554 | /// speaking because of redemption frames or other parameters that slow down the speed it can 555 | /// switch at. But this measure is a raw unprocessed look of how many segments since the last 556 | /// speech are below the negative speech threshold. 557 | pub fn current_silence_samples(&self) -> usize { 558 | self.silent_samples 559 | } 560 | 561 | /// Returns the duration of the end silence. The VAD may be showing this as speaking because of 562 | /// redemption frames or other parameters that slow down the speed it can switch at. But this 563 | /// measure is a raw unprocessed look of how many segments since the last speech are below the 564 | /// negative speech threshold. 565 | pub fn current_silence_duration(&self) -> Duration { 566 | self.samples_to_duration(self.silent_samples) 567 | } 568 | 569 | /// Returns an inclusive range of the audio currently stored in the session buffer. The 570 | /// previously complete active speech segment may exceed these bounds! 571 | pub fn current_buffer_range(&self) -> (Duration, Duration) { 572 | ( 573 | self.samples_to_duration(self.deleted_samples), 574 | self.session_time(), 575 | ) 576 | } 577 | 578 | /// Returns a mutable reference to the VadConfig. 579 | /// Changes to this will take effect on the next inference, and won't modify past state 580 | pub fn config_mut(&mut self) -> &mut VadConfig { 581 | &mut self.config 582 | } 583 | 584 | #[inline(always)] 585 | fn samples_to_duration(&self, samples: usize) -> Duration { 586 | Duration::from_secs_f64(samples as f64 / self.config.sample_rate as f64) 587 | } 588 | 589 | /// Utility function to add a bit more tracking into the snapshot tests 590 | #[doc(hidden)] 591 | pub fn session_audio_samples(&self) -> usize { 592 | self.session_audio.len() 593 | } 594 | } 595 | 596 | impl Default for VadConfig { 597 | fn default() -> Self { 598 | Self { 599 | // https://github.com/ricky0123/vad/blob/ea584aaf66d9162fb19d9bfba607e264452980c3/packages/_common/src/frame-processor.ts#L52 600 | positive_speech_threshold: 0.5, 601 | negative_speech_threshold: 0.35, 602 | pre_speech_pad: Duration::from_millis(600), 603 | post_speech_pad: Duration::from_millis(0), 604 | redemption_time: Duration::from_millis(600), 605 | sample_rate: 16000, 606 | min_speech_time: Duration::from_millis(90), 607 | } 608 | } 609 | } 610 | 611 | impl VadConfig { 612 | pub fn new( 613 | positive_speech_threshold: f32, 614 | negative_speech_threshold: f32, 615 | pre_speech_pad: Duration, 616 | post_speech_pad: Duration, 617 | redemption_time: Duration, 618 | sample_rate: usize, 619 | min_speech_time: Duration, 620 | ) -> Result { 621 | let config = VadConfig { 622 | positive_speech_threshold, 623 | negative_speech_threshold, 624 | pre_speech_pad, 625 | post_speech_pad, 626 | redemption_time, 627 | sample_rate, 628 | min_speech_time, 629 | }; 630 | match config.validate_config() { 631 | Ok(_) => Ok(config), 632 | Err(e) => Err(e), 633 | } 634 | } 635 | 636 | pub fn validate_config(&self) -> Result<()> { 637 | #[cfg(feature = "audio_resampler")] 638 | const HAS_RESAMPLER: bool = true; 639 | #[cfg(not(feature = "audio_resampler"))] 640 | const HAS_RESAMPLER: bool = false; 641 | 642 | self.validate_config_internal(HAS_RESAMPLER) 643 | } 644 | 645 | fn validate_config_internal(&self, has_resampler: bool) -> Result<()> { 646 | if self.post_speech_pad > self.redemption_time { 647 | bail!("post speech pad cannot be longer than redemption time") 648 | } 649 | 650 | if has_resampler { 651 | Ok(()) 652 | } else { 653 | if ![8000, 16000].contains(&self.sample_rate) { 654 | bail!( 655 | "Invalid sample rate of {}, expected either 8000Hz or 16000Hz", 656 | self.sample_rate 657 | ); 658 | } else { 659 | Ok(()) 660 | } 661 | } 662 | } 663 | } 664 | 665 | #[cfg(test)] 666 | mod tests { 667 | use super::*; 668 | use hound::WavReader; 669 | use std::fs; 670 | use std::path::{Path, PathBuf}; 671 | use tracing_test::traced_test; 672 | 673 | /// Feed only silence into the network and ensure that `get_current_speech` returns an empty 674 | /// slice 675 | #[test] 676 | #[traced_test] 677 | fn only_silence_get_speech() { 678 | let mut session = VadSession::new(VadConfig::default()).unwrap(); 679 | let short_audio = vec![0.0; 1000]; 680 | 681 | session.process(&short_audio).unwrap(); 682 | 683 | assert!(session.get_current_speech().is_empty()); 684 | } 685 | 686 | /// Basic smoke test that the model loads correctly and we haven't committed rubbish to the 687 | /// repo. 688 | #[test] 689 | #[traced_test] 690 | fn model_loads() { 691 | let _session = VadSession::new(VadConfig::default()).unwrap(); 692 | let _session = 693 | VadSession::new_from_path("models/silero_vad.onnx", VadConfig::default()).unwrap(); 694 | } 695 | 696 | /// Too short tensors result in inference errors which we don't want to unnecessarily bubble up 697 | /// to the user and instead handle in our buffering implementation. This test will check that a 698 | /// short inference in the internal inference call bubbles up an error but when using the 699 | /// public API no error is presented. 700 | #[test] 701 | #[traced_test] 702 | fn short_audio_handling() { 703 | let mut session = VadSession::new(VadConfig::default()).unwrap(); 704 | 705 | let short_audio = vec![0.0; 160]; 706 | 707 | session.session_audio = short_audio.clone(); 708 | assert!(session.process_internal(0..160).is_err()); 709 | session.session_audio.clear(); 710 | assert!(session.process(&short_audio).unwrap().is_empty()); 711 | } 712 | 713 | /// Check that a long enough packet of just zeros gets an inference and it doesn't flag as 714 | /// transitioning to speech 715 | #[test] 716 | #[traced_test] 717 | fn silence_handling() { 718 | let mut session = VadSession::new(VadConfig::default()).unwrap(); 719 | let silence = vec![0.0; 30 * 16]; // 30ms of silence 720 | 721 | assert!(session.process(&silence).unwrap().is_empty()); 722 | assert_eq!(session.processed_samples, silence.len()); 723 | } 724 | 725 | /// We only allow for 8khz and 16khz audio. 726 | #[test] 727 | #[traced_test] 728 | fn reject_invalid_sample_rate() { 729 | let mut config = VadConfig::default(); 730 | config.sample_rate = 16000; 731 | VadSession::new(config.clone()).unwrap(); 732 | config.sample_rate = 8000; 733 | VadSession::new(config.clone()).unwrap(); 734 | 735 | config.sample_rate += 1; 736 | assert!(VadSession::new(config.clone()).is_err()); 737 | assert!(VadSession::new_from_path("models/silero_vad.onnx", config.clone()).is_err()); 738 | 739 | let bytes = std::fs::read("models/silero_vad.onnx").unwrap(); 740 | assert!(VadSession::new_from_bytes(&bytes, config).is_err()); 741 | } 742 | 743 | /// Just a sanity test of speech duration to make sure the calculation seems roughly right in 744 | /// terms of number of samples, sample rate and taking into account the speech starts/ends. 745 | #[test] 746 | #[traced_test] 747 | fn simple_speech_duration() { 748 | let mut config = VadConfig::default(); 749 | config.sample_rate = 8000; 750 | let mut session = VadSession::new(config.clone()).unwrap(); 751 | session.session_audio.resize(16080, 0.0); 752 | 753 | assert_eq!(session.current_speech_duration(), Duration::from_secs(0)); 754 | 755 | session.speech_start_ms = Some(10); 756 | assert_eq!(session.current_speech_duration(), Duration::from_secs(2)); 757 | 758 | session.config.sample_rate = 16000; 759 | session.session_audio.resize(16160, 0.0); 760 | assert_eq!(session.current_speech_duration(), Duration::from_secs(1)); 761 | } 762 | 763 | /// The provided audio sample must be in the range -1.0 to 1.0 764 | #[test] 765 | #[traced_test] 766 | fn audio_sample_range() { 767 | let config = VadConfig::default(); 768 | 769 | let mut session = VadSession::new(config.clone()).unwrap(); 770 | let valid_samples = [0.0; 1000]; 771 | let result = session.process(&valid_samples); 772 | assert!(result.is_ok()); 773 | 774 | let mut session2 = VadSession::new(config).unwrap(); 775 | let mut invalid_samples = valid_samples.clone(); 776 | invalid_samples[0] = -1.01; 777 | let result = session2.process(&invalid_samples); 778 | assert!(matches!( 779 | result.unwrap_err().downcast::().unwrap(), 780 | VadError::InvalidData 781 | )); 782 | } 783 | 784 | #[test] 785 | #[traced_test] 786 | fn overlapping_segments() { 787 | let mut samples: Vec = WavReader::open("tests/audio/sample_1_trimmed.wav") 788 | .unwrap() 789 | .into_samples() 790 | .map(|x| { 791 | let modified = x.unwrap_or(0i16) as f32 / (i16::MAX as f32); 792 | modified.clamp(-1.0, 1.0) 793 | }) 794 | .collect(); 795 | 796 | let og = samples.clone(); 797 | 798 | samples.resize(samples.len() + 2000, 0.0); 799 | samples.extend_from_slice(&og); 800 | 801 | let mut config = VadConfig::default(); 802 | config.redemption_time = Duration::from_millis(0); 803 | config.pre_speech_pad = Duration::from_secs(1); 804 | let mut session = VadSession::new(config.clone()).unwrap(); 805 | 806 | let chunk_size = 480; // 60ms 807 | let max_chunks = samples.len() / chunk_size; 808 | 809 | let mut last_end = None; 810 | 811 | for i in 0..max_chunks { 812 | let start = i * chunk_size; 813 | let end = (start + chunk_size).min(samples.len()); 814 | let trans = session.process(&samples[start..end]).unwrap(); 815 | 816 | for transition in &trans { 817 | match transition { 818 | VadTransition::SpeechStart { timestamp_ms } => { 819 | println!("Start time: {}ms", timestamp_ms); 820 | if let Some(last_end) = last_end { 821 | assert!(*timestamp_ms >= last_end, "segments are overlapping"); 822 | } 823 | } 824 | VadTransition::SpeechEnd { 825 | start_timestamp_ms, 826 | end_timestamp_ms, 827 | .. 828 | } => { 829 | last_end = Some(*end_timestamp_ms); 830 | println!("End segment: {}-{}ms", start_timestamp_ms, end_timestamp_ms); 831 | } 832 | } 833 | } 834 | } 835 | // If this is going into the deleted speech buffer it'll panic 836 | let _speech = session.get_current_speech(); 837 | } 838 | 839 | /// Apply some audio with speech in and ensure that the take API works as expected 840 | #[test] 841 | #[traced_test] 842 | fn taking_audio() { 843 | let samples: Vec = WavReader::open("tests/audio/sample_4.wav") 844 | .unwrap() 845 | .into_samples() 846 | .map(|x| { 847 | let modified = x.unwrap_or(0i16) as f32 / (i16::MAX as f32); 848 | modified.clamp(-1.0, 1.0) 849 | }) 850 | .collect(); 851 | 852 | let config = VadConfig::default(); 853 | let mut session = VadSession::new(config.clone()).unwrap(); 854 | 855 | let chunk_size = 480; // 30ms 856 | let max_chunks = samples.len() / chunk_size; 857 | 858 | let mut start_time = 0; 859 | 860 | for i in 0..max_chunks { 861 | let start = i * chunk_size; 862 | let end = (start + chunk_size).min(samples.len()); 863 | let trans = session.process(&samples[start..end]).unwrap(); 864 | 865 | for transition in &trans { 866 | match transition { 867 | VadTransition::SpeechStart { timestamp_ms } => { 868 | start_time = *timestamp_ms as u64; 869 | } 870 | _ => panic!("Oh no it's over"), 871 | } 872 | } 873 | 874 | if session.is_speaking() 875 | && (session.session_time() - Duration::from_millis(start_time)) 876 | >= Duration::from_millis(120) 877 | { 878 | break; 879 | } 880 | } 881 | assert!(session.is_speaking(), "never found speech"); 882 | 883 | let current_untaken = session.get_current_speech().to_vec(); 884 | 885 | let session_end = session.session_time(); 886 | 887 | let (start, end) = session.current_buffer_range(); 888 | assert_eq!(start, Duration::from_secs(0)); 889 | assert_eq!(end, session_end); 890 | 891 | let until = Duration::from_millis(start_time + 60); 892 | let taken = session.take_until(until); 893 | 894 | let (start, end) = session.current_buffer_range(); 895 | assert_eq!(start, until); 896 | assert_eq!(end, session_end); 897 | 898 | assert!(session.current_speech_samples() < current_untaken.len()); 899 | assert_eq!( 900 | session.current_speech_samples() + taken.len(), 901 | current_untaken.len() 902 | ); 903 | 904 | assert!(session 905 | .take_until(Duration::from_millis(start_time)) 906 | .is_empty()); 907 | } 908 | 909 | /// If we take past our boundary we panic! 910 | #[test] 911 | #[traced_test] 912 | #[should_panic] 913 | fn excessive_take() { 914 | let config = VadConfig::default(); 915 | let mut session = VadSession::new(config).unwrap(); 916 | 917 | let silence = vec![0.0; 16000]; 918 | let _ = session.process(&silence); 919 | 920 | session.take_until(Duration::from_millis(1001)); 921 | } 922 | 923 | /// If we just have silence we don't want to remove the padding silence 924 | #[test] 925 | #[traced_test] 926 | fn trim_start_silence_keep_padding() { 927 | let config = VadConfig::default(); 928 | let mut session = VadSession::new(config.clone()).unwrap(); 929 | let silence = vec![0.0; 16000]; 930 | let mut added_samples = 0; 931 | while session.samples_to_duration(session.session_audio.len()) < config.pre_speech_pad * 2 { 932 | added_samples += silence.len(); 933 | session.process(&silence).unwrap(); 934 | } 935 | 936 | session.trim_start_silence(); 937 | 938 | let (start, end) = session.current_buffer_range(); 939 | assert!(end - start == config.pre_speech_pad); 940 | assert!(session.session_audio.len() < added_samples); 941 | assert_eq!( 942 | added_samples - session.deleted_samples, 943 | session.session_audio.len() 944 | ); 945 | } 946 | 947 | /// If we have speech in the current buffer then trimming silence shouldn't go beyond the start 948 | /// ms! We'll use sample_1 since it starts with a second of speech and then goes silent for a 949 | /// bit. 950 | #[test] 951 | #[traced_test] 952 | fn trim_to_audio_start() { 953 | // the start of sample 1 is speech so we'll 954 | let mut samples: Vec = WavReader::open("tests/audio/sample_1.wav") 955 | .unwrap() 956 | .into_samples() 957 | .map(|x| { 958 | let modified = x.unwrap_or(0i16) as f32 / (i16::MAX as f32); 959 | modified.clamp(-1.0, 1.0) 960 | }) 961 | .collect(); 962 | 963 | // Keep only the first second 964 | samples.resize(15000, 0.0); 965 | 966 | // Add some starting silence 967 | let mut end_audio = vec![0.0; 16000]; 968 | end_audio.append(&mut samples); 969 | 970 | let config = VadConfig::default(); 971 | let mut session = VadSession::new(config.clone()).unwrap(); 972 | 973 | let res = session.process(&end_audio).unwrap(); 974 | 975 | // This ensures we just have a start audio and no more! 976 | assert_eq!(res.len(), 1); 977 | 978 | assert!(matches!(session.speech_start_ms, Some(x) if x > 0)); 979 | 980 | session.trim_start_silence(); 981 | let (start, _end) = session.current_buffer_range(); 982 | 983 | assert_eq!(start.as_millis() as usize, session.speech_start_ms.unwrap()); 984 | } 985 | 986 | fn get_audio_sample(audio_file: impl AsRef, config: &VadConfig) -> Vec { 987 | let step = if config.sample_rate == 16000 { 988 | 1 989 | } else { 990 | 2 // Other sample rates are invalid so we'll just work on less data 991 | }; 992 | let samples: Vec = WavReader::open(&audio_file) 993 | .unwrap() 994 | .into_samples() 995 | .step_by(step) 996 | .map(|x| { 997 | let modified = x.unwrap_or(0i16) as f32 / (i16::MAX as f32); 998 | modified.clamp(-1.0, 1.0) 999 | }) 1000 | .collect(); 1001 | 1002 | samples 1003 | } 1004 | 1005 | #[inline] 1006 | fn get_chunk_size(sample_rate: usize, chunk_ms: usize) -> usize { 1007 | (sample_rate * chunk_ms) / 1000 1008 | } 1009 | 1010 | fn get_audios() -> Vec { 1011 | let audio_dir = Path::new("tests/audio"); 1012 | let mut result = vec![]; 1013 | for entry in fs::read_dir(&audio_dir).unwrap() { 1014 | let entry = entry.unwrap(); 1015 | let path = entry.path(); 1016 | if !path.is_dir() { 1017 | result.push(path.to_path_buf()); 1018 | } 1019 | } 1020 | assert!(!result.is_empty()); 1021 | result 1022 | } 1023 | 1024 | /// post_speech_pad should result to an increase in the number of samples that SpeechEnd 1025 | /// transition contains. 1026 | #[test] 1027 | #[traced_test] 1028 | fn post_speech_pad() { 1029 | let audio_files = get_audios(); 1030 | for audio_file in audio_files { 1031 | let mut config = VadConfig::default(); 1032 | let samples = get_audio_sample(&audio_file, &config); 1033 | assert!(!samples.is_empty()); 1034 | 1035 | let chunk_size_ms = 50; 1036 | let chunk_size = get_chunk_size(config.sample_rate, chunk_size_ms); 1037 | 1038 | // Do inference with post_speech_pad = 0, a.k.a the default. 1039 | let mut vad = VadSession::new(config).unwrap(); 1040 | let baseline = do_vad_inference(&samples, chunk_size, &mut vad); 1041 | 1042 | // Now, do inference with post_speech_pad, and compare it with the baseline. 1043 | for post_speech_pad in (50..config.redemption_time.as_millis() as usize + 1).step_by(50) 1044 | { 1045 | config.post_speech_pad = Duration::from_millis(post_speech_pad as u64); 1046 | let mut vad = VadSession::new(config).unwrap(); 1047 | let current = do_vad_inference(&samples, chunk_size, &mut vad); 1048 | assert_eq!(baseline.len(), current.len()); 1049 | for (b, c) in baseline.iter().zip(current.iter()) { 1050 | match (b, c) { 1051 | ( 1052 | VadTransition::SpeechEnd { 1053 | start_timestamp_ms: start1, 1054 | end_timestamp_ms: end1, 1055 | samples: samples1, 1056 | }, 1057 | VadTransition::SpeechEnd { 1058 | start_timestamp_ms: start2, 1059 | end_timestamp_ms: end2, 1060 | samples: samples2, 1061 | }, 1062 | ) => { 1063 | assert_eq!(start1, start2); 1064 | assert_eq!(*end1, *end2 - post_speech_pad); 1065 | assert_eq!( 1066 | samples1.len(), 1067 | samples2.len() - config.sample_rate * post_speech_pad / 1000 1068 | ); 1069 | } 1070 | _ => unreachable!(), 1071 | } 1072 | } 1073 | } 1074 | } 1075 | } 1076 | 1077 | #[test] 1078 | fn validate_config() { 1079 | VadConfig::default().validate_config().unwrap(); 1080 | 1081 | let mut config = VadConfig::default(); 1082 | config.sample_rate = 8000; 1083 | 1084 | config.validate_config_internal(true).unwrap(); 1085 | config.validate_config_internal(false).unwrap(); 1086 | 1087 | config.sample_rate = 9000; 1088 | config.validate_config_internal(true).unwrap(); 1089 | assert!(config.validate_config_internal(false).is_err()); 1090 | 1091 | config.post_speech_pad = 2 * config.redemption_time; 1092 | 1093 | assert!(config.validate_config().is_err()); 1094 | assert!(config.validate_config_internal(false).is_err()); 1095 | assert!(config.validate_config_internal(true).is_err()); 1096 | } 1097 | 1098 | /// If we change a config during runtime we should see that change reflected in subsequence 1099 | /// segments 1100 | #[test] 1101 | #[traced_test] 1102 | fn change_config() { 1103 | // the start of sample 1 is speech so we'll 1104 | let mut samples: Vec = WavReader::open("tests/audio/sample_1.wav") 1105 | .unwrap() 1106 | .into_samples() 1107 | .map(|x| { 1108 | let modified = x.unwrap_or(0i16) as f32 / (i16::MAX as f32); 1109 | modified.clamp(-1.0, 1.0) 1110 | }) 1111 | .collect(); 1112 | 1113 | // Keep only the first second 1114 | samples.resize(16000, 0.0); 1115 | // Add 4 seconds silence 1116 | samples.resize(16000 * 5, 0.0); 1117 | 1118 | let mut config = VadConfig::default(); 1119 | config.pre_speech_pad = Duration::from_millis(0); 1120 | config.post_speech_pad = Duration::from_millis(500); 1121 | let mut session = VadSession::new(config.clone()).unwrap(); 1122 | 1123 | let transitions = do_vad_inference(&samples, 8000, &mut session); 1124 | 1125 | // I only expect one segment of speech! 1126 | assert_eq!(transitions.len(), 1); 1127 | 1128 | let config = session.config_mut(); 1129 | config.post_speech_pad = Duration::from_millis(600); 1130 | // config.redemption_time = Duration::from_millis(600); 1131 | 1132 | let transitions_2 = do_vad_inference(&samples, 8000, &mut session); 1133 | 1134 | // I only expect one segment of speech! 1135 | assert_eq!(transitions_2.len(), 1); 1136 | 1137 | let duration = if let VadTransition::SpeechEnd { 1138 | start_timestamp_ms, 1139 | end_timestamp_ms, 1140 | .. 1141 | } = transitions[0] 1142 | { 1143 | end_timestamp_ms - start_timestamp_ms 1144 | } else { 1145 | panic!("Expected the last transition in `transitions` to be a speech end"); 1146 | }; 1147 | 1148 | let duration_2 = if let VadTransition::SpeechEnd { 1149 | start_timestamp_ms, 1150 | end_timestamp_ms, 1151 | .. 1152 | } = transitions_2[0] 1153 | { 1154 | end_timestamp_ms - start_timestamp_ms 1155 | } else { 1156 | panic!("Expected the last transition in `transitions_2` to be a speech end"); 1157 | }; 1158 | 1159 | println!( 1160 | "With padding of 500ms we have {}ms. Padding of 600ms we have {}ms", 1161 | duration, duration_2 1162 | ); 1163 | 1164 | assert_eq!(duration + 100, duration_2); 1165 | } 1166 | 1167 | /// Get all SpeechEnd variant of [VadTransition] from the given file. 1168 | fn do_vad_inference( 1169 | samples: &Vec, 1170 | chunk_size: usize, 1171 | vad: &mut VadSession, 1172 | ) -> Vec { 1173 | let num_chunks = samples.len() / chunk_size; 1174 | let mut speech_ends = vec![]; 1175 | for i in 0..num_chunks { 1176 | let start = i * chunk_size; 1177 | let end = if i < num_chunks - 1 { 1178 | start + chunk_size 1179 | } else { 1180 | samples.len() 1181 | }; 1182 | 1183 | let mut transitions = vad.process(&samples[start..end]).unwrap(); 1184 | for transition in transitions.drain(..) { 1185 | if let VadTransition::SpeechEnd { .. } = transition { 1186 | speech_ends.push(transition); 1187 | } 1188 | } 1189 | } 1190 | 1191 | speech_ends 1192 | } 1193 | } 1194 | -------------------------------------------------------------------------------- /tests/data/chunk_50_8000Hz_default.json: -------------------------------------------------------------------------------- 1 | { 2 | "input_size_ms": 50, 3 | "config": { 4 | "positive_speech_threshold": 0.5, 5 | "negative_speech_threshold": 0.35, 6 | "pre_speech_pad": { 7 | "secs": 0, 8 | "nanos": 600000000 9 | }, 10 | "post_speech_pad": { 11 | "secs": 0, 12 | "nanos": 0 13 | }, 14 | "redemption_time": { 15 | "secs": 0, 16 | "nanos": 600000000 17 | }, 18 | "sample_rate": 8000, 19 | "min_speech_time": { 20 | "secs": 0, 21 | "nanos": 90000000 22 | } 23 | }, 24 | "summary": { 25 | "tests/audio/birds.wav": { 26 | "transitions": [], 27 | "current_session_samples": [ 28 | 400, 29 | 800, 30 | 1200, 31 | 1600, 32 | 2000, 33 | 2400, 34 | 2800, 35 | 3200, 36 | 3600, 37 | 4000, 38 | 4400, 39 | 4800, 40 | 5200, 41 | 5600, 42 | 6000, 43 | 6400, 44 | 6800, 45 | 7200, 46 | 7600, 47 | 8000, 48 | 8400, 49 | 8800, 50 | 9200, 51 | 9600, 52 | 10000, 53 | 10400, 54 | 10800, 55 | 11200, 56 | 11600, 57 | 12000, 58 | 12400, 59 | 12800, 60 | 13200, 61 | 13600, 62 | 14000, 63 | 14400, 64 | 14800, 65 | 15200, 66 | 15600, 67 | 16000, 68 | 16400, 69 | 16800, 70 | 17200, 71 | 17600, 72 | 18000, 73 | 18400, 74 | 18800, 75 | 19200, 76 | 19600, 77 | 20000, 78 | 20400, 79 | 20800, 80 | 21200, 81 | 21600, 82 | 22000, 83 | 22400, 84 | 22800, 85 | 23200, 86 | 23600, 87 | 24000, 88 | 24400, 89 | 24800, 90 | 25200, 91 | 25600, 92 | 26000, 93 | 26400, 94 | 26800, 95 | 27200, 96 | 27600, 97 | 28000, 98 | 28400, 99 | 28800, 100 | 29200, 101 | 29600, 102 | 30000, 103 | 30400, 104 | 30800, 105 | 31200, 106 | 31600, 107 | 32000, 108 | 32400, 109 | 32800, 110 | 33200, 111 | 33600, 112 | 34000, 113 | 34400, 114 | 34800, 115 | 35200, 116 | 35600, 117 | 36000, 118 | 36400, 119 | 36800, 120 | 37200, 121 | 37600, 122 | 38000, 123 | 38400, 124 | 38800, 125 | 39200, 126 | 39600, 127 | 40000, 128 | 40400, 129 | 40800, 130 | 41200, 131 | 41600, 132 | 42000, 133 | 42400, 134 | 42800, 135 | 43200, 136 | 43600, 137 | 44000, 138 | 44400, 139 | 44800, 140 | 45200, 141 | 45600, 142 | 46000, 143 | 46400, 144 | 46800, 145 | 47200, 146 | 47600, 147 | 48000, 148 | 48400, 149 | 48800, 150 | 49200, 151 | 49600, 152 | 50000, 153 | 50400, 154 | 50800, 155 | 51200, 156 | 51600, 157 | 52000, 158 | 52400, 159 | 52800, 160 | 53200, 161 | 53600, 162 | 54000, 163 | 54400, 164 | 54800, 165 | 55200, 166 | 55600, 167 | 56000, 168 | 56400, 169 | 56800, 170 | 57200, 171 | 57600, 172 | 58000, 173 | 58400, 174 | 58800, 175 | 59200, 176 | 59600, 177 | 60000, 178 | 60400, 179 | 60800, 180 | 61200, 181 | 61600, 182 | 62000, 183 | 62400, 184 | 62800, 185 | 63200, 186 | 63600, 187 | 64000, 188 | 64400, 189 | 64800, 190 | 65200, 191 | 65600, 192 | 66000, 193 | 66400, 194 | 66800, 195 | 67200, 196 | 67600, 197 | 68000, 198 | 68400, 199 | 68800, 200 | 69200, 201 | 69600, 202 | 70000, 203 | 70400, 204 | 70800, 205 | 71200, 206 | 71600, 207 | 72000, 208 | 72400, 209 | 72800, 210 | 73200, 211 | 73600, 212 | 74000, 213 | 74400, 214 | 74800, 215 | 75200, 216 | 75600, 217 | 76000, 218 | 76400, 219 | 76800, 220 | 77200, 221 | 77600, 222 | 78000, 223 | 78400, 224 | 78800, 225 | 79200, 226 | 79600, 227 | 80000, 228 | 80400, 229 | 80800, 230 | 81200, 231 | 81600, 232 | 82000, 233 | 82400, 234 | 82800, 235 | 83200, 236 | 83600, 237 | 84000, 238 | 84400, 239 | 84800, 240 | 85200, 241 | 85600, 242 | 86000, 243 | 86400, 244 | 86800, 245 | 87200, 246 | 87600, 247 | 88000, 248 | 88400, 249 | 88800, 250 | 89200, 251 | 89600, 252 | 90000, 253 | 90400, 254 | 90800, 255 | 91200, 256 | 91600, 257 | 92000, 258 | 92400, 259 | 92800, 260 | 93200, 261 | 93600, 262 | 94000, 263 | 94400, 264 | 94800, 265 | 95200, 266 | 95600, 267 | 96000, 268 | 96400, 269 | 96800, 270 | 97200, 271 | 97600, 272 | 98000, 273 | 98400, 274 | 98800, 275 | 99200, 276 | 99600, 277 | 100000, 278 | 100400, 279 | 100800, 280 | 101200, 281 | 101600, 282 | 102000, 283 | 102400, 284 | 102800, 285 | 103200, 286 | 103600, 287 | 104000, 288 | 104400, 289 | 104800, 290 | 105200, 291 | 105600, 292 | 106000, 293 | 106400, 294 | 106800, 295 | 107200, 296 | 107600, 297 | 108000, 298 | 108400, 299 | 108800, 300 | 109200, 301 | 109600, 302 | 110000, 303 | 110400, 304 | 110800, 305 | 111200, 306 | 111600, 307 | 112000, 308 | 112400, 309 | 112800, 310 | 113200, 311 | 113600, 312 | 114000, 313 | 114400, 314 | 114800, 315 | 115200, 316 | 115600, 317 | 116000, 318 | 116400, 319 | 116800, 320 | 117200, 321 | 117600, 322 | 118000, 323 | 118400, 324 | 118800, 325 | 119200, 326 | 119600, 327 | 120000, 328 | 120400, 329 | 120800, 330 | 121200, 331 | 121600, 332 | 122000, 333 | 122400, 334 | 122800, 335 | 123200, 336 | 123600, 337 | 124000, 338 | 124400, 339 | 124800, 340 | 125200, 341 | 125600, 342 | 126000, 343 | 126400, 344 | 126800, 345 | 127200, 346 | 127600, 347 | 128000, 348 | 128400, 349 | 128800, 350 | 129200, 351 | 129600, 352 | 130000, 353 | 130400, 354 | 130800, 355 | 131200, 356 | 131600, 357 | 132000, 358 | 132400, 359 | 132800, 360 | 133200, 361 | 133600, 362 | 134000, 363 | 134400, 364 | 134800, 365 | 135200, 366 | 135600, 367 | 136000, 368 | 136400, 369 | 136800, 370 | 137200, 371 | 137600, 372 | 138000, 373 | 138400, 374 | 138800, 375 | 139200, 376 | 139600, 377 | 140000, 378 | 140400, 379 | 140800, 380 | 141200, 381 | 141600, 382 | 142000, 383 | 142400, 384 | 142800, 385 | 143200, 386 | 143600, 387 | 144000, 388 | 144400, 389 | 144800, 390 | 145200, 391 | 145600, 392 | 146000, 393 | 146400, 394 | 146800, 395 | 147200, 396 | 147600, 397 | 148000, 398 | 148400, 399 | 148800, 400 | 149200, 401 | 149600, 402 | 150000, 403 | 150400, 404 | 150800, 405 | 151200, 406 | 151600, 407 | 152000, 408 | 152400, 409 | 152800, 410 | 153200, 411 | 153600, 412 | 154000, 413 | 154400, 414 | 154800, 415 | 155200, 416 | 155600, 417 | 156000, 418 | 156400, 419 | 156800, 420 | 157200, 421 | 157600, 422 | 158000, 423 | 158400, 424 | 158800, 425 | 159200, 426 | 159600, 427 | 160000, 428 | 160400, 429 | 160800, 430 | 161200, 431 | 161600, 432 | 162000, 433 | 162400, 434 | 162800, 435 | 163200, 436 | 163600, 437 | 164000, 438 | 164400, 439 | 164800, 440 | 165200, 441 | 165600, 442 | 166000, 443 | 166400, 444 | 166800, 445 | 167200, 446 | 167600, 447 | 168000, 448 | 168400, 449 | 168800, 450 | 169200, 451 | 169600, 452 | 170000, 453 | 170400, 454 | 170800, 455 | 171200, 456 | 171600, 457 | 172000, 458 | 172400, 459 | 172800, 460 | 173200, 461 | 173600, 462 | 174000, 463 | 174400, 464 | 174800, 465 | 175200, 466 | 175600, 467 | 176000, 468 | 176400, 469 | 176800, 470 | 177200, 471 | 177600, 472 | 178000, 473 | 178400, 474 | 178800, 475 | 179200, 476 | 179600, 477 | 180000, 478 | 180400, 479 | 180800, 480 | 181200, 481 | 181600, 482 | 182000, 483 | 182400, 484 | 182800, 485 | 183200, 486 | 183600, 487 | 184000, 488 | 184400, 489 | 184800, 490 | 185200, 491 | 185600, 492 | 186000, 493 | 186400, 494 | 186800, 495 | 187200, 496 | 187600, 497 | 188000, 498 | 188400, 499 | 188800, 500 | 189200, 501 | 189600, 502 | 190000, 503 | 190400, 504 | 190800, 505 | 191200, 506 | 191600, 507 | 192000, 508 | 192400, 509 | 192800, 510 | 193200, 511 | 193600, 512 | 194000, 513 | 194400, 514 | 194800, 515 | 195200, 516 | 195600, 517 | 196000, 518 | 196400, 519 | 196800, 520 | 197200, 521 | 197600, 522 | 198000, 523 | 198400, 524 | 198800, 525 | 199200, 526 | 199600, 527 | 200000, 528 | 200400, 529 | 200800, 530 | 201200, 531 | 201600, 532 | 202000, 533 | 202400, 534 | 202800, 535 | 203200, 536 | 203600, 537 | 204000, 538 | 204400, 539 | 204800, 540 | 205200, 541 | 205600, 542 | 206000, 543 | 206400, 544 | 206800, 545 | 207200, 546 | 207600, 547 | 208000, 548 | 208400, 549 | 208800, 550 | 209200, 551 | 209600, 552 | 210000, 553 | 210400, 554 | 210800, 555 | 211200, 556 | 211600, 557 | 212000, 558 | 212400, 559 | 212800, 560 | 213200, 561 | 213600, 562 | 214000, 563 | 214400, 564 | 214800, 565 | 215200, 566 | 215600, 567 | 216000, 568 | 216400, 569 | 216800, 570 | 217200, 571 | 217600, 572 | 218000, 573 | 218400, 574 | 218800, 575 | 219200, 576 | 219600, 577 | 220000, 578 | 220400, 579 | 220800, 580 | 221200, 581 | 221600, 582 | 222000, 583 | 222400, 584 | 222800, 585 | 223200, 586 | 223600, 587 | 224000, 588 | 224400, 589 | 224800, 590 | 225200, 591 | 225600, 592 | 226000, 593 | 226400, 594 | 226800, 595 | 227200, 596 | 227600, 597 | 228000, 598 | 228400, 599 | 228800, 600 | 229200, 601 | 229600, 602 | 230000, 603 | 230400, 604 | 230800, 605 | 231200, 606 | 231600, 607 | 232000, 608 | 232400, 609 | 232800, 610 | 233200, 611 | 233600, 612 | 234000, 613 | 234400, 614 | 234800, 615 | 235200, 616 | 235600, 617 | 236000, 618 | 236400, 619 | 236800, 620 | 237200, 621 | 237600, 622 | 238000, 623 | 238400, 624 | 238800, 625 | 239200, 626 | 239600, 627 | 240000, 628 | 240400, 629 | 240800, 630 | 241200, 631 | 241600, 632 | 242000, 633 | 242400, 634 | 242800, 635 | 243200, 636 | 243600, 637 | 244000, 638 | 244400, 639 | 244800, 640 | 245200, 641 | 245600, 642 | 246000, 643 | 246400, 644 | 246800, 645 | 247200, 646 | 247600, 647 | 248000, 648 | 248400, 649 | 248800, 650 | 249200, 651 | 249600, 652 | 250000, 653 | 250400, 654 | 250800, 655 | 251200, 656 | 251600, 657 | 252000, 658 | 252400, 659 | 252800, 660 | 253200, 661 | 253600, 662 | 254000, 663 | 254400, 664 | 254800, 665 | 255200, 666 | 255600, 667 | 256000, 668 | 256400, 669 | 256800, 670 | 257200, 671 | 257600, 672 | 258000, 673 | 258400, 674 | 258800, 675 | 259200, 676 | 259600, 677 | 260000, 678 | 260400, 679 | 260800, 680 | 261200, 681 | 261600, 682 | 262000, 683 | 262400, 684 | 262800, 685 | 263200, 686 | 263600, 687 | 264000, 688 | 264400, 689 | 264800, 690 | 265200, 691 | 265600, 692 | 266000, 693 | 266400, 694 | 266800, 695 | 267200, 696 | 267600, 697 | 268000, 698 | 268400, 699 | 268800, 700 | 269200, 701 | 269600, 702 | 270000, 703 | 270400, 704 | 270800, 705 | 271200, 706 | 271600, 707 | 272000, 708 | 272400, 709 | 272800, 710 | 273200, 711 | 273600, 712 | 274000, 713 | 274400, 714 | 274800, 715 | 275200, 716 | 275600, 717 | 276000, 718 | 276400, 719 | 276800, 720 | 277200, 721 | 277600, 722 | 278000, 723 | 278400, 724 | 278800, 725 | 279200, 726 | 279600, 727 | 280000, 728 | 280400, 729 | 280800, 730 | 281200, 731 | 281600, 732 | 282000, 733 | 282400, 734 | 282800, 735 | 283200, 736 | 283600, 737 | 284000, 738 | 284400, 739 | 284800, 740 | 285200, 741 | 285600, 742 | 286000, 743 | 286400, 744 | 286800, 745 | 287200, 746 | 287600, 747 | 288000, 748 | 288400, 749 | 288800, 750 | 289200, 751 | 289600, 752 | 290000, 753 | 290400, 754 | 290800, 755 | 291200, 756 | 291600, 757 | 292000, 758 | 292400, 759 | 292800, 760 | 293200, 761 | 293600, 762 | 294000, 763 | 294400, 764 | 294800, 765 | 295200, 766 | 295600, 767 | 296000, 768 | 296400, 769 | 296800, 770 | 297200, 771 | 297600, 772 | 298000, 773 | 298400, 774 | 298800, 775 | 299200, 776 | 299600, 777 | 300000, 778 | 300400, 779 | 300800, 780 | 301200, 781 | 301600, 782 | 302000, 783 | 302400, 784 | 302800, 785 | 303200, 786 | 303600, 787 | 304000, 788 | 304400, 789 | 304800, 790 | 305200, 791 | 305600, 792 | 306000, 793 | 306400, 794 | 306800, 795 | 307200, 796 | 307600, 797 | 308000, 798 | 308400, 799 | 308800, 800 | 309200, 801 | 309760 802 | ], 803 | "current_silence_samples": [ 804 | 240, 805 | 720, 806 | 0, 807 | 0, 808 | 0, 809 | 480, 810 | 720, 811 | 240, 812 | 720, 813 | 960, 814 | 1440, 815 | 1920, 816 | 2160, 817 | 2640, 818 | 3120, 819 | 3360, 820 | 3840, 821 | 4320, 822 | 4560, 823 | 5040, 824 | 0, 825 | 240, 826 | 720, 827 | 1200, 828 | 1440, 829 | 1920, 830 | 2400, 831 | 2640, 832 | 3120, 833 | 3600, 834 | 3840, 835 | 4320, 836 | 4800, 837 | 5040, 838 | 5520, 839 | 6000, 840 | 6240, 841 | 6720, 842 | 7200, 843 | 0, 844 | 480, 845 | 960, 846 | 1200, 847 | 1680, 848 | 2160, 849 | 2400, 850 | 2880, 851 | 3360, 852 | 3600, 853 | 4080, 854 | 4560, 855 | 4800, 856 | 5280, 857 | 5760, 858 | 6000, 859 | 6480, 860 | 6960, 861 | 7200, 862 | 7680, 863 | 8160, 864 | 8400, 865 | 8880, 866 | 9360, 867 | 9600, 868 | 10080, 869 | 10560, 870 | 10800, 871 | 11280, 872 | 11760, 873 | 12000, 874 | 12480, 875 | 12960, 876 | 13200, 877 | 13680, 878 | 14160, 879 | 14400, 880 | 14880, 881 | 15360, 882 | 15600, 883 | 16080, 884 | 16560, 885 | 16800, 886 | 17280, 887 | 17760, 888 | 18000, 889 | 18480, 890 | 18960, 891 | 19200, 892 | 19680, 893 | 20160, 894 | 20400, 895 | 20880, 896 | 21360, 897 | 21600, 898 | 22080, 899 | 22560, 900 | 22800, 901 | 23280, 902 | 23760, 903 | 24000, 904 | 24480, 905 | 24960, 906 | 25200, 907 | 25680, 908 | 26160, 909 | 26400, 910 | 26880, 911 | 27360, 912 | 27600, 913 | 28080, 914 | 28560, 915 | 28800, 916 | 29280, 917 | 29760, 918 | 30000, 919 | 30480, 920 | 30960, 921 | 31200, 922 | 31680, 923 | 32160, 924 | 32400, 925 | 32880, 926 | 33360, 927 | 33600, 928 | 34080, 929 | 34560, 930 | 34800, 931 | 35280, 932 | 35760, 933 | 36000, 934 | 36480, 935 | 36960, 936 | 37200, 937 | 37680, 938 | 38160, 939 | 38400, 940 | 38880, 941 | 39360, 942 | 39600, 943 | 40080, 944 | 40560, 945 | 40800, 946 | 41280, 947 | 41760, 948 | 42000, 949 | 42480, 950 | 42960, 951 | 43200, 952 | 43680, 953 | 44160, 954 | 44400, 955 | 44880, 956 | 45360, 957 | 45600, 958 | 46080, 959 | 46560, 960 | 46800, 961 | 47280, 962 | 47760, 963 | 48000, 964 | 48480, 965 | 48960, 966 | 49200, 967 | 49680, 968 | 50160, 969 | 50400, 970 | 50880, 971 | 51360, 972 | 51600, 973 | 52080, 974 | 52560, 975 | 52800, 976 | 53280, 977 | 53760, 978 | 54000, 979 | 54480, 980 | 54960, 981 | 55200, 982 | 55680, 983 | 56160, 984 | 56400, 985 | 56880, 986 | 57360, 987 | 57600, 988 | 58080, 989 | 58560, 990 | 58800, 991 | 59280, 992 | 59760, 993 | 60000, 994 | 60480, 995 | 60960, 996 | 61200, 997 | 61680, 998 | 62160, 999 | 62400, 1000 | 62880, 1001 | 63360, 1002 | 63600, 1003 | 64080, 1004 | 64560, 1005 | 64800, 1006 | 65280, 1007 | 65760, 1008 | 66000, 1009 | 66480, 1010 | 66960, 1011 | 67200, 1012 | 67680, 1013 | 68160, 1014 | 68400, 1015 | 68880, 1016 | 69360, 1017 | 69600, 1018 | 70080, 1019 | 70560, 1020 | 70800, 1021 | 71280, 1022 | 71760, 1023 | 72000, 1024 | 72480, 1025 | 72960, 1026 | 73200, 1027 | 73680, 1028 | 74160, 1029 | 74400, 1030 | 74880, 1031 | 75360, 1032 | 75600, 1033 | 76080, 1034 | 76560, 1035 | 76800, 1036 | 77280, 1037 | 77760, 1038 | 78000, 1039 | 78480, 1040 | 240, 1041 | 480, 1042 | 960, 1043 | 1440, 1044 | 1680, 1045 | 2160, 1046 | 2640, 1047 | 2880, 1048 | 3360, 1049 | 3840, 1050 | 4080, 1051 | 4560, 1052 | 5040, 1053 | 5280, 1054 | 5760, 1055 | 6240, 1056 | 6480, 1057 | 6960, 1058 | 7440, 1059 | 7680, 1060 | 8160, 1061 | 8640, 1062 | 8880, 1063 | 9360, 1064 | 9840, 1065 | 10080, 1066 | 10560, 1067 | 11040, 1068 | 11280, 1069 | 11760, 1070 | 12240, 1071 | 12480, 1072 | 12960, 1073 | 13440, 1074 | 13680, 1075 | 14160, 1076 | 14640, 1077 | 14880, 1078 | 15360, 1079 | 15840, 1080 | 16080, 1081 | 16560, 1082 | 17040, 1083 | 17280, 1084 | 17760, 1085 | 18240, 1086 | 18480, 1087 | 18960, 1088 | 19440, 1089 | 19680, 1090 | 20160, 1091 | 20640, 1092 | 20880, 1093 | 21360, 1094 | 21840, 1095 | 22080, 1096 | 22560, 1097 | 23040, 1098 | 23280, 1099 | 23760, 1100 | 24240, 1101 | 24480, 1102 | 24960, 1103 | 25440, 1104 | 25680, 1105 | 26160, 1106 | 26640, 1107 | 26880, 1108 | 27360, 1109 | 27840, 1110 | 28080, 1111 | 28560, 1112 | 29040, 1113 | 29280, 1114 | 29760, 1115 | 30240, 1116 | 30480, 1117 | 30960, 1118 | 31440, 1119 | 31680, 1120 | 32160, 1121 | 32640, 1122 | 32880, 1123 | 33360, 1124 | 33840, 1125 | 34080, 1126 | 34560, 1127 | 35040, 1128 | 35280, 1129 | 35760, 1130 | 36240, 1131 | 36480, 1132 | 36960, 1133 | 37440, 1134 | 37680, 1135 | 38160, 1136 | 38640, 1137 | 38880, 1138 | 39360, 1139 | 39840, 1140 | 40080, 1141 | 40560, 1142 | 41040, 1143 | 41280, 1144 | 41760, 1145 | 42240, 1146 | 42480, 1147 | 42960, 1148 | 43440, 1149 | 43680, 1150 | 44160, 1151 | 44640, 1152 | 44880, 1153 | 45360, 1154 | 45840, 1155 | 46080, 1156 | 46560, 1157 | 47040, 1158 | 47280, 1159 | 47760, 1160 | 48240, 1161 | 48480, 1162 | 48960, 1163 | 49440, 1164 | 49680, 1165 | 50160, 1166 | 50640, 1167 | 50880, 1168 | 51360, 1169 | 51840, 1170 | 52080, 1171 | 52560, 1172 | 53040, 1173 | 53280, 1174 | 53760, 1175 | 54240, 1176 | 54480, 1177 | 54960, 1178 | 55440, 1179 | 55680, 1180 | 56160, 1181 | 56640, 1182 | 56880, 1183 | 57360, 1184 | 57840, 1185 | 58080, 1186 | 58560, 1187 | 59040, 1188 | 59280, 1189 | 59760, 1190 | 60240, 1191 | 60480, 1192 | 60960, 1193 | 61440, 1194 | 61680, 1195 | 62160, 1196 | 62640, 1197 | 62880, 1198 | 63360, 1199 | 63840, 1200 | 64080, 1201 | 64560, 1202 | 65040, 1203 | 65280, 1204 | 65760, 1205 | 66240, 1206 | 66480, 1207 | 66960, 1208 | 67440, 1209 | 67680, 1210 | 68160, 1211 | 68640, 1212 | 68880, 1213 | 69360, 1214 | 69840, 1215 | 70080, 1216 | 70560, 1217 | 71040, 1218 | 71280, 1219 | 71760, 1220 | 72240, 1221 | 72480, 1222 | 72960, 1223 | 73440, 1224 | 73680, 1225 | 74160, 1226 | 74640, 1227 | 74880, 1228 | 75360, 1229 | 75840, 1230 | 76080, 1231 | 76560, 1232 | 77040, 1233 | 77280, 1234 | 77760, 1235 | 78240, 1236 | 78480, 1237 | 78960, 1238 | 79440, 1239 | 79680, 1240 | 80160, 1241 | 80640, 1242 | 80880, 1243 | 81360, 1244 | 81840, 1245 | 82080, 1246 | 82560, 1247 | 83040, 1248 | 83280, 1249 | 83760, 1250 | 84240, 1251 | 84480, 1252 | 84960, 1253 | 85440, 1254 | 85680, 1255 | 86160, 1256 | 86640, 1257 | 86880, 1258 | 87360, 1259 | 87840, 1260 | 88080, 1261 | 88560, 1262 | 89040, 1263 | 89280, 1264 | 89760, 1265 | 90240, 1266 | 90480, 1267 | 90960, 1268 | 91440, 1269 | 91680, 1270 | 92160, 1271 | 92640, 1272 | 92880, 1273 | 93360, 1274 | 93840, 1275 | 94080, 1276 | 94560, 1277 | 95040, 1278 | 95280, 1279 | 95760, 1280 | 96240, 1281 | 96480, 1282 | 96960, 1283 | 97440, 1284 | 97680, 1285 | 98160, 1286 | 98640, 1287 | 98880, 1288 | 99360, 1289 | 99840, 1290 | 100080, 1291 | 100560, 1292 | 101040, 1293 | 101280, 1294 | 101760, 1295 | 102240, 1296 | 102480, 1297 | 102960, 1298 | 103440, 1299 | 103680, 1300 | 104160, 1301 | 104640, 1302 | 104880, 1303 | 105360, 1304 | 105840, 1305 | 106080, 1306 | 106560, 1307 | 107040, 1308 | 107280, 1309 | 107760, 1310 | 108240, 1311 | 108480, 1312 | 108960, 1313 | 109440, 1314 | 109680, 1315 | 110160, 1316 | 110640, 1317 | 110880, 1318 | 111360, 1319 | 111840, 1320 | 112080, 1321 | 112560, 1322 | 113040, 1323 | 113280, 1324 | 113760, 1325 | 114240, 1326 | 114480, 1327 | 114960, 1328 | 115440, 1329 | 115680, 1330 | 116160, 1331 | 116640, 1332 | 116880, 1333 | 117360, 1334 | 117840, 1335 | 118080, 1336 | 118560, 1337 | 119040, 1338 | 119280, 1339 | 119760, 1340 | 120240, 1341 | 120480, 1342 | 120960, 1343 | 121440, 1344 | 121680, 1345 | 122160, 1346 | 122640, 1347 | 122880, 1348 | 123360, 1349 | 123840, 1350 | 124080, 1351 | 124560, 1352 | 125040, 1353 | 125280, 1354 | 125760, 1355 | 126240, 1356 | 126480, 1357 | 126960, 1358 | 127440, 1359 | 127680, 1360 | 128160, 1361 | 128640, 1362 | 128880, 1363 | 129360, 1364 | 129840, 1365 | 130080, 1366 | 130560, 1367 | 131040, 1368 | 131280, 1369 | 131760, 1370 | 132240, 1371 | 132480, 1372 | 132960, 1373 | 133440, 1374 | 133680, 1375 | 134160, 1376 | 134640, 1377 | 134880, 1378 | 135360, 1379 | 135840, 1380 | 136080, 1381 | 136560, 1382 | 137040, 1383 | 137280, 1384 | 137760, 1385 | 138240, 1386 | 138480, 1387 | 138960, 1388 | 139440, 1389 | 139680, 1390 | 140160, 1391 | 140640, 1392 | 140880, 1393 | 141360, 1394 | 141840, 1395 | 142080, 1396 | 142560, 1397 | 143040, 1398 | 143280, 1399 | 143760, 1400 | 144240, 1401 | 144480, 1402 | 144960, 1403 | 145440, 1404 | 145680, 1405 | 146160, 1406 | 146640, 1407 | 146880, 1408 | 147360, 1409 | 147840, 1410 | 148080, 1411 | 148560, 1412 | 149040, 1413 | 149280, 1414 | 149760, 1415 | 150240, 1416 | 150480, 1417 | 150960, 1418 | 151440, 1419 | 151680, 1420 | 152160, 1421 | 152640, 1422 | 152880, 1423 | 153360, 1424 | 153840, 1425 | 154080, 1426 | 154560, 1427 | 155040, 1428 | 155280, 1429 | 155760, 1430 | 156240, 1431 | 156480, 1432 | 156960, 1433 | 157440, 1434 | 157680, 1435 | 158160, 1436 | 158640, 1437 | 158880, 1438 | 159360, 1439 | 159840, 1440 | 160080, 1441 | 160560, 1442 | 161040, 1443 | 161280, 1444 | 161760, 1445 | 162240, 1446 | 162480, 1447 | 162960, 1448 | 163440, 1449 | 163680, 1450 | 164160, 1451 | 164640, 1452 | 164880, 1453 | 165360, 1454 | 165840, 1455 | 166080, 1456 | 166560, 1457 | 167040, 1458 | 167280, 1459 | 167760, 1460 | 168240, 1461 | 168480, 1462 | 168960, 1463 | 169440, 1464 | 169680, 1465 | 170160, 1466 | 170640, 1467 | 170880, 1468 | 171360, 1469 | 171840, 1470 | 172080, 1471 | 172560, 1472 | 173040, 1473 | 173280, 1474 | 173760, 1475 | 174240, 1476 | 174480, 1477 | 174960, 1478 | 175440, 1479 | 175680, 1480 | 176160, 1481 | 176640, 1482 | 176880, 1483 | 177360, 1484 | 177840, 1485 | 178080, 1486 | 178560, 1487 | 179040, 1488 | 179280, 1489 | 179760, 1490 | 180240, 1491 | 180480, 1492 | 180960, 1493 | 181440, 1494 | 181680, 1495 | 182160, 1496 | 182640, 1497 | 182880, 1498 | 183360, 1499 | 183840, 1500 | 184080, 1501 | 184560, 1502 | 185040, 1503 | 185280, 1504 | 185760, 1505 | 186240, 1506 | 186480, 1507 | 186960, 1508 | 187440, 1509 | 187680, 1510 | 188160, 1511 | 188640, 1512 | 188880, 1513 | 189360, 1514 | 189840, 1515 | 190080, 1516 | 190560, 1517 | 191040, 1518 | 191280, 1519 | 191760, 1520 | 192240, 1521 | 192480, 1522 | 192960, 1523 | 193440, 1524 | 193680, 1525 | 194160, 1526 | 194640, 1527 | 194880, 1528 | 195360, 1529 | 195840, 1530 | 196080, 1531 | 196560, 1532 | 197040, 1533 | 197280, 1534 | 197760, 1535 | 198240, 1536 | 198480, 1537 | 198960, 1538 | 199440, 1539 | 199680, 1540 | 200160, 1541 | 200640, 1542 | 200880, 1543 | 201360, 1544 | 201840, 1545 | 202080, 1546 | 202560, 1547 | 203040, 1548 | 203280, 1549 | 203760, 1550 | 204240, 1551 | 204480, 1552 | 204960, 1553 | 205440, 1554 | 205680, 1555 | 206160, 1556 | 206640, 1557 | 206880, 1558 | 207360, 1559 | 207840, 1560 | 208080, 1561 | 208560, 1562 | 209040, 1563 | 209280, 1564 | 209760, 1565 | 210240, 1566 | 210480, 1567 | 210960, 1568 | 211440, 1569 | 211680, 1570 | 212160, 1571 | 212640, 1572 | 212880, 1573 | 213360, 1574 | 213840, 1575 | 214080, 1576 | 214560, 1577 | 215040 1578 | ], 1579 | "current_speech_samples": [ 1580 | 0, 1581 | 0, 1582 | 0, 1583 | 0, 1584 | 0, 1585 | 0, 1586 | 0, 1587 | 0, 1588 | 0, 1589 | 0, 1590 | 0, 1591 | 0, 1592 | 0, 1593 | 0, 1594 | 0, 1595 | 0, 1596 | 0, 1597 | 0, 1598 | 0, 1599 | 0, 1600 | 0, 1601 | 0, 1602 | 0, 1603 | 0, 1604 | 0, 1605 | 0, 1606 | 0, 1607 | 0, 1608 | 0, 1609 | 0, 1610 | 0, 1611 | 0, 1612 | 0, 1613 | 0, 1614 | 0, 1615 | 0, 1616 | 0, 1617 | 0, 1618 | 0, 1619 | 0, 1620 | 0, 1621 | 0, 1622 | 0, 1623 | 0, 1624 | 0, 1625 | 0, 1626 | 0, 1627 | 0, 1628 | 0, 1629 | 0, 1630 | 0, 1631 | 0, 1632 | 0, 1633 | 0, 1634 | 0, 1635 | 0, 1636 | 0, 1637 | 0, 1638 | 0, 1639 | 0, 1640 | 0, 1641 | 0, 1642 | 0, 1643 | 0, 1644 | 0, 1645 | 0, 1646 | 0, 1647 | 0, 1648 | 0, 1649 | 0, 1650 | 0, 1651 | 0, 1652 | 0, 1653 | 0, 1654 | 0, 1655 | 0, 1656 | 0, 1657 | 0, 1658 | 0, 1659 | 0, 1660 | 0, 1661 | 0, 1662 | 0, 1663 | 0, 1664 | 0, 1665 | 0, 1666 | 0, 1667 | 0, 1668 | 0, 1669 | 0, 1670 | 0, 1671 | 0, 1672 | 0, 1673 | 0, 1674 | 0, 1675 | 0, 1676 | 0, 1677 | 0, 1678 | 0, 1679 | 0, 1680 | 0, 1681 | 0, 1682 | 0, 1683 | 0, 1684 | 0, 1685 | 0, 1686 | 0, 1687 | 0, 1688 | 0, 1689 | 0, 1690 | 0, 1691 | 0, 1692 | 0, 1693 | 0, 1694 | 0, 1695 | 0, 1696 | 0, 1697 | 0, 1698 | 0, 1699 | 0, 1700 | 0, 1701 | 0, 1702 | 0, 1703 | 0, 1704 | 0, 1705 | 0, 1706 | 0, 1707 | 0, 1708 | 0, 1709 | 0, 1710 | 0, 1711 | 0, 1712 | 0, 1713 | 0, 1714 | 0, 1715 | 0, 1716 | 0, 1717 | 0, 1718 | 0, 1719 | 0, 1720 | 0, 1721 | 0, 1722 | 0, 1723 | 0, 1724 | 0, 1725 | 0, 1726 | 0, 1727 | 0, 1728 | 0, 1729 | 0, 1730 | 0, 1731 | 0, 1732 | 0, 1733 | 0, 1734 | 0, 1735 | 0, 1736 | 0, 1737 | 0, 1738 | 0, 1739 | 0, 1740 | 0, 1741 | 0, 1742 | 0, 1743 | 0, 1744 | 0, 1745 | 0, 1746 | 0, 1747 | 0, 1748 | 0, 1749 | 0, 1750 | 0, 1751 | 0, 1752 | 0, 1753 | 0, 1754 | 0, 1755 | 0, 1756 | 0, 1757 | 0, 1758 | 0, 1759 | 0, 1760 | 0, 1761 | 0, 1762 | 0, 1763 | 0, 1764 | 0, 1765 | 0, 1766 | 0, 1767 | 0, 1768 | 0, 1769 | 0, 1770 | 0, 1771 | 0, 1772 | 0, 1773 | 0, 1774 | 0, 1775 | 0, 1776 | 0, 1777 | 0, 1778 | 0, 1779 | 0, 1780 | 0, 1781 | 0, 1782 | 0, 1783 | 0, 1784 | 0, 1785 | 0, 1786 | 0, 1787 | 0, 1788 | 0, 1789 | 0, 1790 | 0, 1791 | 0, 1792 | 0, 1793 | 0, 1794 | 0, 1795 | 0, 1796 | 0, 1797 | 0, 1798 | 0, 1799 | 0, 1800 | 0, 1801 | 0, 1802 | 0, 1803 | 0, 1804 | 0, 1805 | 0, 1806 | 0, 1807 | 0, 1808 | 0, 1809 | 0, 1810 | 0, 1811 | 0, 1812 | 0, 1813 | 0, 1814 | 0, 1815 | 0, 1816 | 0, 1817 | 0, 1818 | 0, 1819 | 0, 1820 | 0, 1821 | 0, 1822 | 0, 1823 | 0, 1824 | 0, 1825 | 0, 1826 | 0, 1827 | 0, 1828 | 0, 1829 | 0, 1830 | 0, 1831 | 0, 1832 | 0, 1833 | 0, 1834 | 0, 1835 | 0, 1836 | 0, 1837 | 0, 1838 | 0, 1839 | 0, 1840 | 0, 1841 | 0, 1842 | 0, 1843 | 0, 1844 | 0, 1845 | 0, 1846 | 0, 1847 | 0, 1848 | 0, 1849 | 0, 1850 | 0, 1851 | 0, 1852 | 0, 1853 | 0, 1854 | 0, 1855 | 0, 1856 | 0, 1857 | 0, 1858 | 0, 1859 | 0, 1860 | 0, 1861 | 0, 1862 | 0, 1863 | 0, 1864 | 0, 1865 | 0, 1866 | 0, 1867 | 0, 1868 | 0, 1869 | 0, 1870 | 0, 1871 | 0, 1872 | 0, 1873 | 0, 1874 | 0, 1875 | 0, 1876 | 0, 1877 | 0, 1878 | 0, 1879 | 0, 1880 | 0, 1881 | 0, 1882 | 0, 1883 | 0, 1884 | 0, 1885 | 0, 1886 | 0, 1887 | 0, 1888 | 0, 1889 | 0, 1890 | 0, 1891 | 0, 1892 | 0, 1893 | 0, 1894 | 0, 1895 | 0, 1896 | 0, 1897 | 0, 1898 | 0, 1899 | 0, 1900 | 0, 1901 | 0, 1902 | 0, 1903 | 0, 1904 | 0, 1905 | 0, 1906 | 0, 1907 | 0, 1908 | 0, 1909 | 0, 1910 | 0, 1911 | 0, 1912 | 0, 1913 | 0, 1914 | 0, 1915 | 0, 1916 | 0, 1917 | 0, 1918 | 0, 1919 | 0, 1920 | 0, 1921 | 0, 1922 | 0, 1923 | 0, 1924 | 0, 1925 | 0, 1926 | 0, 1927 | 0, 1928 | 0, 1929 | 0, 1930 | 0, 1931 | 0, 1932 | 0, 1933 | 0, 1934 | 0, 1935 | 0, 1936 | 0, 1937 | 0, 1938 | 0, 1939 | 0, 1940 | 0, 1941 | 0, 1942 | 0, 1943 | 0, 1944 | 0, 1945 | 0, 1946 | 0, 1947 | 0, 1948 | 0, 1949 | 0, 1950 | 0, 1951 | 0, 1952 | 0, 1953 | 0, 1954 | 0, 1955 | 0, 1956 | 0, 1957 | 0, 1958 | 0, 1959 | 0, 1960 | 0, 1961 | 0, 1962 | 0, 1963 | 0, 1964 | 0, 1965 | 0, 1966 | 0, 1967 | 0, 1968 | 0, 1969 | 0, 1970 | 0, 1971 | 0, 1972 | 0, 1973 | 0, 1974 | 0, 1975 | 0, 1976 | 0, 1977 | 0, 1978 | 0, 1979 | 0, 1980 | 0, 1981 | 0, 1982 | 0, 1983 | 0, 1984 | 0, 1985 | 0, 1986 | 0, 1987 | 0, 1988 | 0, 1989 | 0, 1990 | 0, 1991 | 0, 1992 | 0, 1993 | 0, 1994 | 0, 1995 | 0, 1996 | 0, 1997 | 0, 1998 | 0, 1999 | 0, 2000 | 0, 2001 | 0, 2002 | 0, 2003 | 0, 2004 | 0, 2005 | 0, 2006 | 0, 2007 | 0, 2008 | 0, 2009 | 0, 2010 | 0, 2011 | 0, 2012 | 0, 2013 | 0, 2014 | 0, 2015 | 0, 2016 | 0, 2017 | 0, 2018 | 0, 2019 | 0, 2020 | 0, 2021 | 0, 2022 | 0, 2023 | 0, 2024 | 0, 2025 | 0, 2026 | 0, 2027 | 0, 2028 | 0, 2029 | 0, 2030 | 0, 2031 | 0, 2032 | 0, 2033 | 0, 2034 | 0, 2035 | 0, 2036 | 0, 2037 | 0, 2038 | 0, 2039 | 0, 2040 | 0, 2041 | 0, 2042 | 0, 2043 | 0, 2044 | 0, 2045 | 0, 2046 | 0, 2047 | 0, 2048 | 0, 2049 | 0, 2050 | 0, 2051 | 0, 2052 | 0, 2053 | 0, 2054 | 0, 2055 | 0, 2056 | 0, 2057 | 0, 2058 | 0, 2059 | 0, 2060 | 0, 2061 | 0, 2062 | 0, 2063 | 0, 2064 | 0, 2065 | 0, 2066 | 0, 2067 | 0, 2068 | 0, 2069 | 0, 2070 | 0, 2071 | 0, 2072 | 0, 2073 | 0, 2074 | 0, 2075 | 0, 2076 | 0, 2077 | 0, 2078 | 0, 2079 | 0, 2080 | 0, 2081 | 0, 2082 | 0, 2083 | 0, 2084 | 0, 2085 | 0, 2086 | 0, 2087 | 0, 2088 | 0, 2089 | 0, 2090 | 0, 2091 | 0, 2092 | 0, 2093 | 0, 2094 | 0, 2095 | 0, 2096 | 0, 2097 | 0, 2098 | 0, 2099 | 0, 2100 | 0, 2101 | 0, 2102 | 0, 2103 | 0, 2104 | 0, 2105 | 0, 2106 | 0, 2107 | 0, 2108 | 0, 2109 | 0, 2110 | 0, 2111 | 0, 2112 | 0, 2113 | 0, 2114 | 0, 2115 | 0, 2116 | 0, 2117 | 0, 2118 | 0, 2119 | 0, 2120 | 0, 2121 | 0, 2122 | 0, 2123 | 0, 2124 | 0, 2125 | 0, 2126 | 0, 2127 | 0, 2128 | 0, 2129 | 0, 2130 | 0, 2131 | 0, 2132 | 0, 2133 | 0, 2134 | 0, 2135 | 0, 2136 | 0, 2137 | 0, 2138 | 0, 2139 | 0, 2140 | 0, 2141 | 0, 2142 | 0, 2143 | 0, 2144 | 0, 2145 | 0, 2146 | 0, 2147 | 0, 2148 | 0, 2149 | 0, 2150 | 0, 2151 | 0, 2152 | 0, 2153 | 0, 2154 | 0, 2155 | 0, 2156 | 0, 2157 | 0, 2158 | 0, 2159 | 0, 2160 | 0, 2161 | 0, 2162 | 0, 2163 | 0, 2164 | 0, 2165 | 0, 2166 | 0, 2167 | 0, 2168 | 0, 2169 | 0, 2170 | 0, 2171 | 0, 2172 | 0, 2173 | 0, 2174 | 0, 2175 | 0, 2176 | 0, 2177 | 0, 2178 | 0, 2179 | 0, 2180 | 0, 2181 | 0, 2182 | 0, 2183 | 0, 2184 | 0, 2185 | 0, 2186 | 0, 2187 | 0, 2188 | 0, 2189 | 0, 2190 | 0, 2191 | 0, 2192 | 0, 2193 | 0, 2194 | 0, 2195 | 0, 2196 | 0, 2197 | 0, 2198 | 0, 2199 | 0, 2200 | 0, 2201 | 0, 2202 | 0, 2203 | 0, 2204 | 0, 2205 | 0, 2206 | 0, 2207 | 0, 2208 | 0, 2209 | 0, 2210 | 0, 2211 | 0, 2212 | 0, 2213 | 0, 2214 | 0, 2215 | 0, 2216 | 0, 2217 | 0, 2218 | 0, 2219 | 0, 2220 | 0, 2221 | 0, 2222 | 0, 2223 | 0, 2224 | 0, 2225 | 0, 2226 | 0, 2227 | 0, 2228 | 0, 2229 | 0, 2230 | 0, 2231 | 0, 2232 | 0, 2233 | 0, 2234 | 0, 2235 | 0, 2236 | 0, 2237 | 0, 2238 | 0, 2239 | 0, 2240 | 0, 2241 | 0, 2242 | 0, 2243 | 0, 2244 | 0, 2245 | 0, 2246 | 0, 2247 | 0, 2248 | 0, 2249 | 0, 2250 | 0, 2251 | 0, 2252 | 0, 2253 | 0, 2254 | 0, 2255 | 0, 2256 | 0, 2257 | 0, 2258 | 0, 2259 | 0, 2260 | 0, 2261 | 0, 2262 | 0, 2263 | 0, 2264 | 0, 2265 | 0, 2266 | 0, 2267 | 0, 2268 | 0, 2269 | 0, 2270 | 0, 2271 | 0, 2272 | 0, 2273 | 0, 2274 | 0, 2275 | 0, 2276 | 0, 2277 | 0, 2278 | 0, 2279 | 0, 2280 | 0, 2281 | 0, 2282 | 0, 2283 | 0, 2284 | 0, 2285 | 0, 2286 | 0, 2287 | 0, 2288 | 0, 2289 | 0, 2290 | 0, 2291 | 0, 2292 | 0, 2293 | 0, 2294 | 0, 2295 | 0, 2296 | 0, 2297 | 0, 2298 | 0, 2299 | 0, 2300 | 0, 2301 | 0, 2302 | 0, 2303 | 0, 2304 | 0, 2305 | 0, 2306 | 0, 2307 | 0, 2308 | 0, 2309 | 0, 2310 | 0, 2311 | 0, 2312 | 0, 2313 | 0, 2314 | 0, 2315 | 0, 2316 | 0, 2317 | 0, 2318 | 0, 2319 | 0, 2320 | 0, 2321 | 0, 2322 | 0, 2323 | 0, 2324 | 0, 2325 | 0, 2326 | 0, 2327 | 0, 2328 | 0, 2329 | 0, 2330 | 0, 2331 | 0, 2332 | 0, 2333 | 0, 2334 | 0, 2335 | 0, 2336 | 0, 2337 | 0, 2338 | 0, 2339 | 0, 2340 | 0, 2341 | 0, 2342 | 0, 2343 | 0, 2344 | 0, 2345 | 0, 2346 | 0, 2347 | 0, 2348 | 0, 2349 | 0, 2350 | 0, 2351 | 0, 2352 | 0, 2353 | 0 2354 | ], 2355 | "likelihoods": [ 2356 | 1, 2357 | 49, 2358 | 55, 2359 | 68, 2360 | 23, 2361 | 8, 2362 | 40, 2363 | 27, 2364 | 26, 2365 | 13, 2366 | 6, 2367 | 3, 2368 | 20, 2369 | 20, 2370 | 10, 2371 | 6, 2372 | 6, 2373 | 5, 2374 | 11, 2375 | 30, 2376 | 32, 2377 | 20, 2378 | 10, 2379 | 5, 2380 | 10, 2381 | 27, 2382 | 16, 2383 | 8, 2384 | 4, 2385 | 3, 2386 | 4, 2387 | 6, 2388 | 4, 2389 | 3, 2390 | 2, 2391 | 2, 2392 | 2, 2393 | 15, 2394 | 37, 2395 | 36, 2396 | 9, 2397 | 6, 2398 | 4, 2399 | 3, 2400 | 15, 2401 | 11, 2402 | 9, 2403 | 5, 2404 | 4, 2405 | 3, 2406 | 2, 2407 | 13, 2408 | 15, 2409 | 7, 2410 | 5, 2411 | 3, 2412 | 2, 2413 | 3, 2414 | 2, 2415 | 2, 2416 | 2, 2417 | 1, 2418 | 1, 2419 | 1, 2420 | 1, 2421 | 0, 2422 | 0, 2423 | 0, 2424 | 0, 2425 | 1, 2426 | 0, 2427 | 0, 2428 | 0, 2429 | 0, 2430 | 0, 2431 | 0, 2432 | 0, 2433 | 1, 2434 | 1, 2435 | 1, 2436 | 2, 2437 | 1, 2438 | 1, 2439 | 1, 2440 | 1, 2441 | 1, 2442 | 1, 2443 | 0, 2444 | 1, 2445 | 1, 2446 | 1, 2447 | 1, 2448 | 1, 2449 | 1, 2450 | 1, 2451 | 16, 2452 | 14, 2453 | 6, 2454 | 4, 2455 | 2, 2456 | 2, 2457 | 14, 2458 | 8, 2459 | 5, 2460 | 2, 2461 | 2, 2462 | 2, 2463 | 2, 2464 | 5, 2465 | 4, 2466 | 2, 2467 | 1, 2468 | 2, 2469 | 2, 2470 | 2, 2471 | 1, 2472 | 1, 2473 | 1, 2474 | 1, 2475 | 1, 2476 | 1, 2477 | 1, 2478 | 1, 2479 | 1, 2480 | 1, 2481 | 1, 2482 | 1, 2483 | 1, 2484 | 1, 2485 | 1, 2486 | 1, 2487 | 2, 2488 | 1, 2489 | 2, 2490 | 1, 2491 | 1, 2492 | 4, 2493 | 2, 2494 | 2, 2495 | 1, 2496 | 1, 2497 | 1, 2498 | 1, 2499 | 1, 2500 | 1, 2501 | 1, 2502 | 1, 2503 | 1, 2504 | 3, 2505 | 2, 2506 | 2, 2507 | 2, 2508 | 2, 2509 | 2, 2510 | 2, 2511 | 1, 2512 | 1, 2513 | 1, 2514 | 1, 2515 | 1, 2516 | 1, 2517 | 1, 2518 | 1, 2519 | 1, 2520 | 1, 2521 | 1, 2522 | 1, 2523 | 1, 2524 | 1, 2525 | 1, 2526 | 1, 2527 | 1, 2528 | 1, 2529 | 2, 2530 | 1, 2531 | 1, 2532 | 1, 2533 | 1, 2534 | 1, 2535 | 1, 2536 | 1, 2537 | 1, 2538 | 3, 2539 | 2, 2540 | 1, 2541 | 1, 2542 | 1, 2543 | 2, 2544 | 1, 2545 | 1, 2546 | 1, 2547 | 2, 2548 | 1, 2549 | 1, 2550 | 1, 2551 | 1, 2552 | 1, 2553 | 1, 2554 | 1, 2555 | 2, 2556 | 2, 2557 | 2, 2558 | 1, 2559 | 1, 2560 | 1, 2561 | 1, 2562 | 1, 2563 | 1, 2564 | 1, 2565 | 1, 2566 | 1, 2567 | 1, 2568 | 1, 2569 | 1, 2570 | 1, 2571 | 1, 2572 | 1, 2573 | 2, 2574 | 1, 2575 | 1, 2576 | 4, 2577 | 1, 2578 | 2, 2579 | 28, 2580 | 39, 2581 | 14, 2582 | 7, 2583 | 6, 2584 | 6, 2585 | 33, 2586 | 28, 2587 | 20, 2588 | 9, 2589 | 22, 2590 | 19, 2591 | 31, 2592 | 25, 2593 | 27, 2594 | 16, 2595 | 10, 2596 | 11, 2597 | 23, 2598 | 23, 2599 | 14, 2600 | 9, 2601 | 10, 2602 | 11, 2603 | 21, 2604 | 38, 2605 | 32, 2606 | 21, 2607 | 16, 2608 | 14, 2609 | 27, 2610 | 35, 2611 | 34, 2612 | 24, 2613 | 19, 2614 | 18, 2615 | 24, 2616 | 22, 2617 | 22, 2618 | 17, 2619 | 15, 2620 | 14, 2621 | 12, 2622 | 9, 2623 | 9, 2624 | 6, 2625 | 5, 2626 | 6, 2627 | 5, 2628 | 6, 2629 | 9, 2630 | 5, 2631 | 4, 2632 | 4, 2633 | 10, 2634 | 4, 2635 | 4, 2636 | 4, 2637 | 3, 2638 | 3, 2639 | 3, 2640 | 3, 2641 | 3, 2642 | 2, 2643 | 2, 2644 | 2, 2645 | 2, 2646 | 2, 2647 | 2, 2648 | 2, 2649 | 2, 2650 | 2, 2651 | 3, 2652 | 2, 2653 | 3, 2654 | 3, 2655 | 2, 2656 | 2, 2657 | 3, 2658 | 2, 2659 | 2, 2660 | 4, 2661 | 2, 2662 | 2, 2663 | 3, 2664 | 2, 2665 | 2, 2666 | 3, 2667 | 2, 2668 | 2, 2669 | 1, 2670 | 2, 2671 | 2, 2672 | 2, 2673 | 2, 2674 | 2, 2675 | 2, 2676 | 2, 2677 | 2, 2678 | 2, 2679 | 2, 2680 | 1, 2681 | 1, 2682 | 1, 2683 | 2, 2684 | 3, 2685 | 2, 2686 | 2, 2687 | 2, 2688 | 11, 2689 | 4, 2690 | 5, 2691 | 4, 2692 | 4, 2693 | 2, 2694 | 2, 2695 | 3, 2696 | 3, 2697 | 3, 2698 | 2, 2699 | 2, 2700 | 2, 2701 | 2, 2702 | 2, 2703 | 2, 2704 | 2, 2705 | 2, 2706 | 3, 2707 | 2, 2708 | 1, 2709 | 8, 2710 | 3, 2711 | 2, 2712 | 2, 2713 | 2, 2714 | 2, 2715 | 2, 2716 | 2, 2717 | 2, 2718 | 2, 2719 | 3, 2720 | 1, 2721 | 1, 2722 | 1, 2723 | 1, 2724 | 2, 2725 | 2, 2726 | 3, 2727 | 2, 2728 | 2, 2729 | 1, 2730 | 1, 2731 | 2, 2732 | 1, 2733 | 2, 2734 | 1, 2735 | 2, 2736 | 2, 2737 | 1, 2738 | 1, 2739 | 1, 2740 | 3, 2741 | 1, 2742 | 1, 2743 | 2, 2744 | 2, 2745 | 1, 2746 | 1, 2747 | 1, 2748 | 2, 2749 | 2, 2750 | 1, 2751 | 1, 2752 | 1, 2753 | 1, 2754 | 1, 2755 | 1, 2756 | 1, 2757 | 2, 2758 | 1, 2759 | 1, 2760 | 1, 2761 | 1, 2762 | 1, 2763 | 2, 2764 | 2, 2765 | 5, 2766 | 3, 2767 | 2, 2768 | 2, 2769 | 2, 2770 | 2, 2771 | 1, 2772 | 1, 2773 | 2, 2774 | 1, 2775 | 1, 2776 | 1, 2777 | 1, 2778 | 1, 2779 | 1, 2780 | 2, 2781 | 1, 2782 | 1, 2783 | 1, 2784 | 1, 2785 | 2, 2786 | 2, 2787 | 4, 2788 | 4, 2789 | 2, 2790 | 5, 2791 | 2, 2792 | 1, 2793 | 1, 2794 | 1, 2795 | 1, 2796 | 1, 2797 | 1, 2798 | 1, 2799 | 1, 2800 | 1, 2801 | 1, 2802 | 1, 2803 | 1, 2804 | 1, 2805 | 1, 2806 | 1, 2807 | 2, 2808 | 1, 2809 | 9, 2810 | 10, 2811 | 4, 2812 | 4, 2813 | 2, 2814 | 5, 2815 | 4, 2816 | 2, 2817 | 2, 2818 | 2, 2819 | 2, 2820 | 2, 2821 | 1, 2822 | 2, 2823 | 1, 2824 | 1, 2825 | 1, 2826 | 1, 2827 | 1, 2828 | 1, 2829 | 1, 2830 | 2, 2831 | 1, 2832 | 2, 2833 | 2, 2834 | 2, 2835 | 2, 2836 | 1, 2837 | 1, 2838 | 3, 2839 | 3, 2840 | 1, 2841 | 2, 2842 | 3, 2843 | 3, 2844 | 2, 2845 | 7, 2846 | 2, 2847 | 2, 2848 | 3, 2849 | 2, 2850 | 2, 2851 | 3, 2852 | 2, 2853 | 2, 2854 | 2, 2855 | 2, 2856 | 2, 2857 | 2, 2858 | 2, 2859 | 2, 2860 | 2, 2861 | 3, 2862 | 2, 2863 | 2, 2864 | 1, 2865 | 2, 2866 | 2, 2867 | 2, 2868 | 2, 2869 | 2, 2870 | 2, 2871 | 1, 2872 | 1, 2873 | 2, 2874 | 1, 2875 | 1, 2876 | 1, 2877 | 2, 2878 | 1, 2879 | 1, 2880 | 2, 2881 | 1, 2882 | 1, 2883 | 1, 2884 | 1, 2885 | 2, 2886 | 1, 2887 | 10, 2888 | 7, 2889 | 1, 2890 | 1, 2891 | 1, 2892 | 1, 2893 | 1, 2894 | 1, 2895 | 2, 2896 | 1, 2897 | 2, 2898 | 2, 2899 | 1, 2900 | 1, 2901 | 1, 2902 | 1, 2903 | 1, 2904 | 1, 2905 | 4, 2906 | 2, 2907 | 4, 2908 | 3, 2909 | 3, 2910 | 2, 2911 | 2, 2912 | 1, 2913 | 1, 2914 | 2, 2915 | 4, 2916 | 2, 2917 | 2, 2918 | 2, 2919 | 2, 2920 | 2, 2921 | 2, 2922 | 3, 2923 | 2, 2924 | 2, 2925 | 1, 2926 | 1, 2927 | 1, 2928 | 4, 2929 | 4, 2930 | 3, 2931 | 2, 2932 | 2, 2933 | 2, 2934 | 5, 2935 | 6, 2936 | 3, 2937 | 2, 2938 | 11, 2939 | 4, 2940 | 5, 2941 | 3, 2942 | 2, 2943 | 2, 2944 | 2, 2945 | 1, 2946 | 2, 2947 | 1, 2948 | 1, 2949 | 1, 2950 | 1, 2951 | 1, 2952 | 1, 2953 | 1, 2954 | 1, 2955 | 1, 2956 | 2, 2957 | 1, 2958 | 1, 2959 | 2, 2960 | 3, 2961 | 2, 2962 | 2, 2963 | 2, 2964 | 2, 2965 | 3, 2966 | 2, 2967 | 2, 2968 | 1, 2969 | 2, 2970 | 1, 2971 | 4, 2972 | 3, 2973 | 2, 2974 | 3, 2975 | 9, 2976 | 5, 2977 | 2, 2978 | 7, 2979 | 2, 2980 | 3, 2981 | 1, 2982 | 4, 2983 | 2, 2984 | 1, 2985 | 2, 2986 | 1, 2987 | 2, 2988 | 1, 2989 | 1, 2990 | 1, 2991 | 1, 2992 | 1, 2993 | 1, 2994 | 1, 2995 | 1, 2996 | 1, 2997 | 1, 2998 | 1, 2999 | 1, 3000 | 1, 3001 | 1, 3002 | 1, 3003 | 5, 3004 | 2, 3005 | 1, 3006 | 1, 3007 | 1, 3008 | 2, 3009 | 1, 3010 | 2, 3011 | 1, 3012 | 5, 3013 | 3, 3014 | 2, 3015 | 2, 3016 | 1, 3017 | 2, 3018 | 2, 3019 | 1, 3020 | 3, 3021 | 1, 3022 | 3, 3023 | 2, 3024 | 2, 3025 | 2, 3026 | 3, 3027 | 3, 3028 | 1, 3029 | 1, 3030 | 1, 3031 | 1, 3032 | 2, 3033 | 9, 3034 | 2, 3035 | 6, 3036 | 2, 3037 | 1, 3038 | 1, 3039 | 13, 3040 | 5, 3041 | 3, 3042 | 5, 3043 | 3, 3044 | 3, 3045 | 2, 3046 | 2, 3047 | 2, 3048 | 2, 3049 | 3, 3050 | 2, 3051 | 3, 3052 | 2, 3053 | 1, 3054 | 2, 3055 | 2, 3056 | 2, 3057 | 1, 3058 | 1, 3059 | 1, 3060 | 1, 3061 | 3, 3062 | 2, 3063 | 2, 3064 | 2, 3065 | 2, 3066 | 2, 3067 | 2, 3068 | 2, 3069 | 2, 3070 | 2, 3071 | 1, 3072 | 1, 3073 | 5, 3074 | 8, 3075 | 2, 3076 | 2, 3077 | 3, 3078 | 1, 3079 | 2, 3080 | 1, 3081 | 1, 3082 | 1, 3083 | 1, 3084 | 1, 3085 | 1, 3086 | 2, 3087 | 1, 3088 | 1, 3089 | 1, 3090 | 2, 3091 | 1, 3092 | 4, 3093 | 1, 3094 | 1, 3095 | 2, 3096 | 2, 3097 | 2, 3098 | 1, 3099 | 1, 3100 | 1, 3101 | 1, 3102 | 1, 3103 | 1, 3104 | 3, 3105 | 6, 3106 | 4, 3107 | 2, 3108 | 1, 3109 | 2, 3110 | 2, 3111 | 2, 3112 | 1, 3113 | 2, 3114 | 5, 3115 | 6, 3116 | 2, 3117 | 2, 3118 | 1, 3119 | 1, 3120 | 2, 3121 | 1, 3122 | 1, 3123 | 1, 3124 | 1, 3125 | 1, 3126 | 1, 3127 | 1, 3128 | 8, 3129 | 1 3130 | ] 3131 | }, 3132 | "tests/audio/rooster.wav": { 3133 | "transitions": [], 3134 | "current_session_samples": [ 3135 | 400, 3136 | 800, 3137 | 1200, 3138 | 1600, 3139 | 2000, 3140 | 2400, 3141 | 2800, 3142 | 3200, 3143 | 3600, 3144 | 4000, 3145 | 4400, 3146 | 4800, 3147 | 5200, 3148 | 5600, 3149 | 6000, 3150 | 6400, 3151 | 6800, 3152 | 7200, 3153 | 7600, 3154 | 8000, 3155 | 8400, 3156 | 8800, 3157 | 9200, 3158 | 9600, 3159 | 10000, 3160 | 10400, 3161 | 10800, 3162 | 11200, 3163 | 11600, 3164 | 12000, 3165 | 12400, 3166 | 12800, 3167 | 13200, 3168 | 13600, 3169 | 14000, 3170 | 14400, 3171 | 14800, 3172 | 15200, 3173 | 15600, 3174 | 16000, 3175 | 16400, 3176 | 16800, 3177 | 17200, 3178 | 17600, 3179 | 18000, 3180 | 18400, 3181 | 18800, 3182 | 19200, 3183 | 19600, 3184 | 20000, 3185 | 20400, 3186 | 20800, 3187 | 21200, 3188 | 21600, 3189 | 22000, 3190 | 22400, 3191 | 22800, 3192 | 23200, 3193 | 23600, 3194 | 24000, 3195 | 24400, 3196 | 24800, 3197 | 25200, 3198 | 25600, 3199 | 26000, 3200 | 26400, 3201 | 26800, 3202 | 27200, 3203 | 27600, 3204 | 28000, 3205 | 28400, 3206 | 28800, 3207 | 29200, 3208 | 29600, 3209 | 30000, 3210 | 30400, 3211 | 30800, 3212 | 31200, 3213 | 31600, 3214 | 32000, 3215 | 32400, 3216 | 32800, 3217 | 33200, 3218 | 33600, 3219 | 34000, 3220 | 34400, 3221 | 34800, 3222 | 35200, 3223 | 35600, 3224 | 36000, 3225 | 36400, 3226 | 36800, 3227 | 37200, 3228 | 37600, 3229 | 38000, 3230 | 38400, 3231 | 38800, 3232 | 39200, 3233 | 39600, 3234 | 40000, 3235 | 40400, 3236 | 40800, 3237 | 41200, 3238 | 41600, 3239 | 42000, 3240 | 42400, 3241 | 42800, 3242 | 43200, 3243 | 43600, 3244 | 44000, 3245 | 44400, 3246 | 44800, 3247 | 45200, 3248 | 45600, 3249 | 46000, 3250 | 46400, 3251 | 46800, 3252 | 47200, 3253 | 47600, 3254 | 48000, 3255 | 48400, 3256 | 48800, 3257 | 49200, 3258 | 49600, 3259 | 50000, 3260 | 50400, 3261 | 50800, 3262 | 51200, 3263 | 51600, 3264 | 52000, 3265 | 52400, 3266 | 52800, 3267 | 53200, 3268 | 53600, 3269 | 54000, 3270 | 54400, 3271 | 54800, 3272 | 55200, 3273 | 55600, 3274 | 56000, 3275 | 56400, 3276 | 56800, 3277 | 57200, 3278 | 57600, 3279 | 58000, 3280 | 58400, 3281 | 58800, 3282 | 59200, 3283 | 59600, 3284 | 60000, 3285 | 60400, 3286 | 60800, 3287 | 61200, 3288 | 61600, 3289 | 62000, 3290 | 62400, 3291 | 62800, 3292 | 63200, 3293 | 63600, 3294 | 64000, 3295 | 64400, 3296 | 64800, 3297 | 65200, 3298 | 65600, 3299 | 66000, 3300 | 66456 3301 | ], 3302 | "current_silence_samples": [ 3303 | 240, 3304 | 720, 3305 | 1200, 3306 | 1440, 3307 | 1920, 3308 | 2400, 3309 | 2640, 3310 | 3120, 3311 | 3600, 3312 | 3840, 3313 | 4320, 3314 | 4800, 3315 | 5040, 3316 | 5520, 3317 | 6000, 3318 | 6240, 3319 | 6720, 3320 | 7200, 3321 | 7440, 3322 | 7920, 3323 | 8400, 3324 | 8640, 3325 | 9120, 3326 | 9600, 3327 | 9840, 3328 | 10320, 3329 | 10800, 3330 | 11040, 3331 | 11520, 3332 | 12000, 3333 | 12240, 3334 | 12720, 3335 | 13200, 3336 | 13440, 3337 | 13920, 3338 | 14400, 3339 | 14640, 3340 | 15120, 3341 | 15600, 3342 | 15840, 3343 | 16320, 3344 | 16800, 3345 | 17040, 3346 | 17520, 3347 | 18000, 3348 | 18240, 3349 | 18720, 3350 | 19200, 3351 | 19440, 3352 | 19920, 3353 | 20400, 3354 | 20640, 3355 | 21120, 3356 | 21600, 3357 | 21840, 3358 | 22320, 3359 | 22800, 3360 | 23040, 3361 | 23520, 3362 | 24000, 3363 | 24240, 3364 | 24720, 3365 | 25200, 3366 | 25440, 3367 | 25920, 3368 | 240, 3369 | 480, 3370 | 960, 3371 | 1440, 3372 | 1680, 3373 | 2160, 3374 | 2640, 3375 | 2880, 3376 | 3360, 3377 | 3840, 3378 | 4080, 3379 | 4560, 3380 | 5040, 3381 | 5280, 3382 | 5760, 3383 | 6240, 3384 | 6480, 3385 | 6960, 3386 | 7440, 3387 | 7680, 3388 | 8160, 3389 | 8640, 3390 | 8880, 3391 | 9360, 3392 | 9840, 3393 | 10080, 3394 | 10560, 3395 | 11040, 3396 | 11280, 3397 | 11760, 3398 | 12240, 3399 | 12480, 3400 | 12960, 3401 | 13440, 3402 | 13680, 3403 | 14160, 3404 | 14640, 3405 | 14880, 3406 | 15360, 3407 | 15840, 3408 | 16080, 3409 | 16560, 3410 | 17040, 3411 | 17280, 3412 | 17760, 3413 | 18240, 3414 | 18480, 3415 | 18960, 3416 | 19440, 3417 | 19680, 3418 | 20160, 3419 | 20640, 3420 | 20880, 3421 | 21360, 3422 | 21840, 3423 | 22080, 3424 | 22560, 3425 | 23040, 3426 | 23280, 3427 | 23760, 3428 | 24240, 3429 | 24480, 3430 | 24960, 3431 | 25440, 3432 | 25680, 3433 | 26160, 3434 | 26640, 3435 | 26880, 3436 | 27360, 3437 | 27840, 3438 | 28080, 3439 | 28560, 3440 | 29040, 3441 | 29280, 3442 | 29760, 3443 | 30240, 3444 | 30480, 3445 | 30960, 3446 | 31440, 3447 | 31680, 3448 | 32160, 3449 | 32640, 3450 | 32880, 3451 | 33360, 3452 | 33840, 3453 | 34080, 3454 | 34560, 3455 | 35040, 3456 | 35280, 3457 | 35760, 3458 | 36240, 3459 | 36480, 3460 | 36960, 3461 | 37440, 3462 | 37680, 3463 | 38160, 3464 | 38640, 3465 | 38880, 3466 | 39360, 3467 | 39840, 3468 | 40080 3469 | ], 3470 | "current_speech_samples": [ 3471 | 0, 3472 | 0, 3473 | 0, 3474 | 0, 3475 | 0, 3476 | 0, 3477 | 0, 3478 | 0, 3479 | 0, 3480 | 0, 3481 | 0, 3482 | 0, 3483 | 0, 3484 | 0, 3485 | 0, 3486 | 0, 3487 | 0, 3488 | 0, 3489 | 0, 3490 | 0, 3491 | 0, 3492 | 0, 3493 | 0, 3494 | 0, 3495 | 0, 3496 | 0, 3497 | 0, 3498 | 0, 3499 | 0, 3500 | 0, 3501 | 0, 3502 | 0, 3503 | 0, 3504 | 0, 3505 | 0, 3506 | 0, 3507 | 0, 3508 | 0, 3509 | 0, 3510 | 0, 3511 | 0, 3512 | 0, 3513 | 0, 3514 | 0, 3515 | 0, 3516 | 0, 3517 | 0, 3518 | 0, 3519 | 0, 3520 | 0, 3521 | 0, 3522 | 0, 3523 | 0, 3524 | 0, 3525 | 0, 3526 | 0, 3527 | 0, 3528 | 0, 3529 | 0, 3530 | 0, 3531 | 0, 3532 | 0, 3533 | 0, 3534 | 0, 3535 | 0, 3536 | 0, 3537 | 0, 3538 | 0, 3539 | 0, 3540 | 0, 3541 | 0, 3542 | 0, 3543 | 0, 3544 | 0, 3545 | 0, 3546 | 0, 3547 | 0, 3548 | 0, 3549 | 0, 3550 | 0, 3551 | 0, 3552 | 0, 3553 | 0, 3554 | 0, 3555 | 0, 3556 | 0, 3557 | 0, 3558 | 0, 3559 | 0, 3560 | 0, 3561 | 0, 3562 | 0, 3563 | 0, 3564 | 0, 3565 | 0, 3566 | 0, 3567 | 0, 3568 | 0, 3569 | 0, 3570 | 0, 3571 | 0, 3572 | 0, 3573 | 0, 3574 | 0, 3575 | 0, 3576 | 0, 3577 | 0, 3578 | 0, 3579 | 0, 3580 | 0, 3581 | 0, 3582 | 0, 3583 | 0, 3584 | 0, 3585 | 0, 3586 | 0, 3587 | 0, 3588 | 0, 3589 | 0, 3590 | 0, 3591 | 0, 3592 | 0, 3593 | 0, 3594 | 0, 3595 | 0, 3596 | 0, 3597 | 0, 3598 | 0, 3599 | 0, 3600 | 0, 3601 | 0, 3602 | 0, 3603 | 0, 3604 | 0, 3605 | 0, 3606 | 0, 3607 | 0, 3608 | 0, 3609 | 0, 3610 | 0, 3611 | 0, 3612 | 0, 3613 | 0, 3614 | 0, 3615 | 0, 3616 | 0, 3617 | 0, 3618 | 0, 3619 | 0, 3620 | 0, 3621 | 0, 3622 | 0, 3623 | 0, 3624 | 0, 3625 | 0, 3626 | 0, 3627 | 0, 3628 | 0, 3629 | 0, 3630 | 0, 3631 | 0, 3632 | 0, 3633 | 0, 3634 | 0, 3635 | 0, 3636 | 0 3637 | ], 3638 | "likelihoods": [ 3639 | 0, 3640 | 0, 3641 | 1, 3642 | 0, 3643 | 1, 3644 | 1, 3645 | 1, 3646 | 2, 3647 | 1, 3648 | 1, 3649 | 1, 3650 | 1, 3651 | 0, 3652 | 1, 3653 | 1, 3654 | 0, 3655 | 0, 3656 | 1, 3657 | 1, 3658 | 1, 3659 | 0, 3660 | 3, 3661 | 2, 3662 | 1, 3663 | 1, 3664 | 1, 3665 | 2, 3666 | 3, 3667 | 2, 3668 | 2, 3669 | 1, 3670 | 0, 3671 | 0, 3672 | 1, 3673 | 1, 3674 | 1, 3675 | 1, 3676 | 2, 3677 | 2, 3678 | 1, 3679 | 2, 3680 | 1, 3681 | 1, 3682 | 1, 3683 | 2, 3684 | 2, 3685 | 3, 3686 | 2, 3687 | 2, 3688 | 2, 3689 | 2, 3690 | 2, 3691 | 2, 3692 | 1, 3693 | 1, 3694 | 2, 3695 | 1, 3696 | 2, 3697 | 4, 3698 | 3, 3699 | 4, 3700 | 3, 3701 | 5, 3702 | 8, 3703 | 24, 3704 | 27, 3705 | 13, 3706 | 10, 3707 | 11, 3708 | 5, 3709 | 14, 3710 | 18, 3711 | 9, 3712 | 7, 3713 | 4, 3714 | 3, 3715 | 2, 3716 | 3, 3717 | 3, 3718 | 2, 3719 | 1, 3720 | 1, 3721 | 0, 3722 | 0, 3723 | 0, 3724 | 0, 3725 | 3, 3726 | 6, 3727 | 3, 3728 | 5, 3729 | 4, 3730 | 7, 3731 | 5, 3732 | 5, 3733 | 5, 3734 | 6, 3735 | 14, 3736 | 10, 3737 | 11, 3738 | 11, 3739 | 10, 3740 | 7, 3741 | 5, 3742 | 10, 3743 | 8, 3744 | 9, 3745 | 6, 3746 | 9, 3747 | 8, 3748 | 9, 3749 | 7, 3750 | 7, 3751 | 8, 3752 | 9, 3753 | 7, 3754 | 5, 3755 | 5, 3756 | 3, 3757 | 3, 3758 | 4, 3759 | 6, 3760 | 5, 3761 | 4, 3762 | 6, 3763 | 5, 3764 | 3, 3765 | 3, 3766 | 2, 3767 | 2, 3768 | 5, 3769 | 3, 3770 | 4, 3771 | 3, 3772 | 6, 3773 | 3, 3774 | 4, 3775 | 3, 3776 | 3, 3777 | 5, 3778 | 5, 3779 | 4, 3780 | 4, 3781 | 4, 3782 | 3, 3783 | 4, 3784 | 3, 3785 | 3, 3786 | 3, 3787 | 2, 3788 | 5, 3789 | 3, 3790 | 4, 3791 | 8, 3792 | 4, 3793 | 3, 3794 | 3, 3795 | 3, 3796 | 4, 3797 | 3, 3798 | 3, 3799 | 3, 3800 | 4, 3801 | 5, 3802 | 4, 3803 | 3, 3804 | 2 3805 | ] 3806 | }, 3807 | "tests/audio/sample_1.wav": { 3808 | "transitions": [ 3809 | { 3810 | "SpeechStart": { 3811 | "timestamp_ms": 0 3812 | } 3813 | }, 3814 | { 3815 | "SpeechEnd": { 3816 | "start_timestamp_ms": 0, 3817 | "end_timestamp_ms": 1080 3818 | } 3819 | }, 3820 | { 3821 | "SpeechStart": { 3822 | "timestamp_ms": 2820 3823 | } 3824 | } 3825 | ], 3826 | "current_session_samples": [ 3827 | 400, 3828 | 800, 3829 | 1200, 3830 | 1600, 3831 | 2000, 3832 | 2400, 3833 | 2800, 3834 | 3200, 3835 | 3600, 3836 | 4000, 3837 | 4400, 3838 | 4800, 3839 | 5200, 3840 | 5600, 3841 | 6000, 3842 | 6400, 3843 | 6800, 3844 | 7200, 3845 | 7600, 3846 | 8000, 3847 | 8400, 3848 | 8800, 3849 | 9200, 3850 | 9600, 3851 | 10000, 3852 | 10400, 3853 | 10800, 3854 | 11200, 3855 | 11600, 3856 | 12000, 3857 | 12400, 3858 | 12800, 3859 | 13200, 3860 | 13600, 3861 | 5359, 3862 | 5759, 3863 | 6159, 3864 | 6559, 3865 | 6959, 3866 | 7359, 3867 | 7759, 3868 | 8159, 3869 | 8559, 3870 | 8959, 3871 | 9359, 3872 | 9759, 3873 | 10159, 3874 | 10559, 3875 | 10959, 3876 | 11359, 3877 | 11759, 3878 | 12159, 3879 | 12559, 3880 | 12959, 3881 | 13359, 3882 | 13759, 3883 | 14159, 3884 | 14559, 3885 | 14959, 3886 | 15359, 3887 | 15759, 3888 | 16159, 3889 | 16559, 3890 | 16959, 3891 | 17359, 3892 | 17759, 3893 | 18159, 3894 | 18559, 3895 | 18959, 3896 | 19359, 3897 | 19759, 3898 | 20159, 3899 | 20559, 3900 | 20959, 3901 | 21359, 3902 | 21759, 3903 | 22159, 3904 | 22559, 3905 | 22959, 3906 | 23359, 3907 | 23759, 3908 | 24159, 3909 | 24559, 3910 | 24959, 3911 | 25359, 3912 | 25759, 3913 | 26159, 3914 | 26559, 3915 | 26959, 3916 | 27359, 3917 | 28140 3918 | ], 3919 | "current_silence_samples": [ 3920 | 240, 3921 | 720, 3922 | 1200, 3923 | 1440, 3924 | 1920, 3925 | 0, 3926 | 0, 3927 | 0, 3928 | 0, 3929 | 0, 3930 | 0, 3931 | 0, 3932 | 0, 3933 | 0, 3934 | 0, 3935 | 0, 3936 | 0, 3937 | 0, 3938 | 0, 3939 | 0, 3940 | 0, 3941 | 0, 3942 | 480, 3943 | 960, 3944 | 1200, 3945 | 1680, 3946 | 2160, 3947 | 2400, 3948 | 2880, 3949 | 3360, 3950 | 3600, 3951 | 4080, 3952 | 4560, 3953 | 4800, 3954 | 5280, 3955 | 5760, 3956 | 6000, 3957 | 6480, 3958 | 6960, 3959 | 7200, 3960 | 7680, 3961 | 8160, 3962 | 8400, 3963 | 8880, 3964 | 9360, 3965 | 9600, 3966 | 10080, 3967 | 10560, 3968 | 10800, 3969 | 11280, 3970 | 11760, 3971 | 12000, 3972 | 12480, 3973 | 12960, 3974 | 13200, 3975 | 13680, 3976 | 14160, 3977 | 14400, 3978 | 14880, 3979 | 15360, 3980 | 15600, 3981 | 16080, 3982 | 16560, 3983 | 16800, 3984 | 17280, 3985 | 17760, 3986 | 18000, 3987 | 18480, 3988 | 0, 3989 | 0, 3990 | 0, 3991 | 0, 3992 | 0, 3993 | 0, 3994 | 0, 3995 | 0, 3996 | 480, 3997 | 960, 3998 | 0, 3999 | 0, 4000 | 0, 4001 | 240, 4002 | 720, 4003 | 1200, 4004 | 1440, 4005 | 1920, 4006 | 2400, 4007 | 2640, 4008 | 3120, 4009 | 3600, 4010 | 4320 4011 | ], 4012 | "current_speech_samples": [ 4013 | 0, 4014 | 0, 4015 | 0, 4016 | 0, 4017 | 0, 4018 | 0, 4019 | 0, 4020 | 0, 4021 | 3600, 4022 | 4000, 4023 | 4400, 4024 | 4800, 4025 | 5200, 4026 | 5600, 4027 | 6000, 4028 | 6400, 4029 | 6800, 4030 | 7200, 4031 | 7600, 4032 | 8000, 4033 | 8400, 4034 | 8800, 4035 | 9200, 4036 | 9600, 4037 | 10000, 4038 | 10400, 4039 | 10800, 4040 | 11200, 4041 | 11600, 4042 | 12000, 4043 | 12400, 4044 | 12800, 4045 | 13200, 4046 | 13600, 4047 | 8640, 4048 | 8640, 4049 | 8640, 4050 | 8640, 4051 | 8640, 4052 | 8640, 4053 | 8640, 4054 | 8640, 4055 | 8640, 4056 | 8640, 4057 | 8640, 4058 | 8640, 4059 | 8640, 4060 | 8640, 4061 | 8640, 4062 | 8640, 4063 | 8640, 4064 | 8640, 4065 | 8640, 4066 | 8640, 4067 | 8640, 4068 | 8640, 4069 | 8640, 4070 | 8640, 4071 | 8640, 4072 | 8640, 4073 | 8640, 4074 | 8640, 4075 | 8640, 4076 | 8640, 4077 | 8640, 4078 | 8640, 4079 | 8640, 4080 | 8640, 4081 | 8640, 4082 | 8640, 4083 | 8640, 4084 | 6240, 4085 | 6640, 4086 | 7040, 4087 | 7440, 4088 | 7840, 4089 | 8240, 4090 | 8640, 4091 | 9040, 4092 | 9440, 4093 | 9840, 4094 | 10240, 4095 | 10640, 4096 | 11040, 4097 | 11440, 4098 | 11840, 4099 | 12240, 4100 | 12640, 4101 | 13040, 4102 | 13440, 4103 | 14221 4104 | ], 4105 | "likelihoods": [ 4106 | 0, 4107 | 0, 4108 | 15, 4109 | 40, 4110 | 31, 4111 | 83, 4112 | 51, 4113 | 69, 4114 | 44, 4115 | 64, 4116 | 44, 4117 | 56, 4118 | 95, 4119 | 94, 4120 | 97, 4121 | 58, 4122 | 75, 4123 | 81, 4124 | 86, 4125 | 73, 4126 | 78, 4127 | 49, 4128 | 7, 4129 | 2, 4130 | 0, 4131 | 0, 4132 | 0, 4133 | 0, 4134 | 0, 4135 | 0, 4136 | 0, 4137 | 0, 4138 | 0, 4139 | 0, 4140 | 0, 4141 | 0, 4142 | 0, 4143 | 0, 4144 | 0, 4145 | 0, 4146 | 0, 4147 | 0, 4148 | 0, 4149 | 0, 4150 | 0, 4151 | 0, 4152 | 0, 4153 | 0, 4154 | 0, 4155 | 0, 4156 | 0, 4157 | 0, 4158 | 0, 4159 | 0, 4160 | 0, 4161 | 0, 4162 | 0, 4163 | 0, 4164 | 0, 4165 | 0, 4166 | 0, 4167 | 0, 4168 | 0, 4169 | 0, 4170 | 0, 4171 | 0, 4172 | 0, 4173 | 54, 4174 | 83, 4175 | 91, 4176 | 73, 4177 | 76, 4178 | 63, 4179 | 83, 4180 | 35, 4181 | 36, 4182 | 20, 4183 | 64, 4184 | 70, 4185 | 76, 4186 | 58, 4187 | 26, 4188 | 11, 4189 | 5, 4190 | 3, 4191 | 0, 4192 | 0, 4193 | 0, 4194 | 0, 4195 | 0, 4196 | 0 4197 | ] 4198 | }, 4199 | "tests/audio/sample_1_trimmed.wav": { 4200 | "transitions": [ 4201 | { 4202 | "SpeechStart": { 4203 | "timestamp_ms": 0 4204 | } 4205 | } 4206 | ], 4207 | "current_session_samples": [ 4208 | 400, 4209 | 800, 4210 | 1200, 4211 | 1600, 4212 | 2000, 4213 | 2400, 4214 | 2800, 4215 | 3200, 4216 | 3600, 4217 | 4000, 4218 | 4400, 4219 | 4800, 4220 | 5200, 4221 | 5600, 4222 | 6000, 4223 | 6639 4224 | ], 4225 | "current_silence_samples": [ 4226 | 240, 4227 | 0, 4228 | 0, 4229 | 0, 4230 | 0, 4231 | 0, 4232 | 0, 4233 | 0, 4234 | 0, 4235 | 0, 4236 | 0, 4237 | 0, 4238 | 0, 4239 | 0, 4240 | 0, 4241 | 0 4242 | ], 4243 | "current_speech_samples": [ 4244 | 0, 4245 | 0, 4246 | 0, 4247 | 0, 4248 | 2000, 4249 | 2400, 4250 | 2800, 4251 | 3200, 4252 | 3600, 4253 | 4000, 4254 | 4400, 4255 | 4800, 4256 | 5200, 4257 | 5600, 4258 | 6000, 4259 | 6639 4260 | ], 4261 | "likelihoods": [ 4262 | 14, 4263 | 79, 4264 | 97, 4265 | 93, 4266 | 93, 4267 | 88, 4268 | 93, 4269 | 75, 4270 | 79, 4271 | 87, 4272 | 92, 4273 | 96, 4274 | 83, 4275 | 77, 4276 | 86, 4277 | 86 4278 | ] 4279 | }, 4280 | "tests/audio/sample_2.wav": { 4281 | "transitions": [ 4282 | { 4283 | "SpeechStart": { 4284 | "timestamp_ms": 0 4285 | } 4286 | }, 4287 | { 4288 | "SpeechEnd": { 4289 | "start_timestamp_ms": 0, 4290 | "end_timestamp_ms": 690 4291 | } 4292 | }, 4293 | { 4294 | "SpeechStart": { 4295 | "timestamp_ms": 2280 4296 | } 4297 | } 4298 | ], 4299 | "current_session_samples": [ 4300 | 400, 4301 | 800, 4302 | 1200, 4303 | 1600, 4304 | 2000, 4305 | 2400, 4306 | 2800, 4307 | 3200, 4308 | 3600, 4309 | 4000, 4310 | 4400, 4311 | 4800, 4312 | 5200, 4313 | 5600, 4314 | 6000, 4315 | 6400, 4316 | 6800, 4317 | 7200, 4318 | 7600, 4319 | 8000, 4320 | 8400, 4321 | 8800, 4322 | 9200, 4323 | 9600, 4324 | 10000, 4325 | 10400, 4326 | 5279, 4327 | 5679, 4328 | 6079, 4329 | 6479, 4330 | 6879, 4331 | 7279, 4332 | 7679, 4333 | 8079, 4334 | 8479, 4335 | 8879, 4336 | 9279, 4337 | 9679, 4338 | 10079, 4339 | 10479, 4340 | 10879, 4341 | 11279, 4342 | 11679, 4343 | 12079, 4344 | 12479, 4345 | 12879, 4346 | 13279, 4347 | 13679, 4348 | 14079, 4349 | 14479, 4350 | 14879, 4351 | 15279, 4352 | 15679, 4353 | 16079, 4354 | 16479, 4355 | 16879, 4356 | 17279, 4357 | 17679, 4358 | 18079, 4359 | 18479, 4360 | 18879, 4361 | 19279, 4362 | 19679, 4363 | 20079, 4364 | 20479, 4365 | 20879, 4366 | 21279, 4367 | 21679, 4368 | 22079, 4369 | 22479, 4370 | 22879, 4371 | 23279, 4372 | 23679, 4373 | 24079, 4374 | 24479, 4375 | 24879, 4376 | 25279, 4377 | 25679, 4378 | 26079, 4379 | 26479, 4380 | 26879, 4381 | 27279, 4382 | 27679, 4383 | 28079, 4384 | 28479, 4385 | 28879, 4386 | 29279, 4387 | 29679, 4388 | 30079, 4389 | 30479, 4390 | 30879, 4391 | 31279, 4392 | 31679, 4393 | 32079, 4394 | 32479, 4395 | 32879, 4396 | 33279, 4397 | 33679, 4398 | 34079, 4399 | 34479, 4400 | 34879, 4401 | 35279, 4402 | 35679, 4403 | 36079, 4404 | 36484 4405 | ], 4406 | "current_silence_samples": [ 4407 | 240, 4408 | 720, 4409 | 1200, 4410 | 0, 4411 | 0, 4412 | 0, 4413 | 0, 4414 | 0, 4415 | 0, 4416 | 240, 4417 | 720, 4418 | 0, 4419 | 0, 4420 | 0, 4421 | 480, 4422 | 720, 4423 | 1200, 4424 | 1680, 4425 | 1920, 4426 | 2400, 4427 | 2880, 4428 | 3120, 4429 | 3600, 4430 | 4080, 4431 | 4320, 4432 | 4800, 4433 | 5280, 4434 | 5520, 4435 | 6000, 4436 | 6480, 4437 | 6720, 4438 | 7200, 4439 | 7680, 4440 | 7920, 4441 | 8400, 4442 | 8880, 4443 | 9120, 4444 | 9600, 4445 | 10080, 4446 | 10320, 4447 | 10800, 4448 | 11280, 4449 | 11520, 4450 | 12000, 4451 | 12480, 4452 | 12720, 4453 | 13200, 4454 | 13680, 4455 | 13920, 4456 | 14400, 4457 | 14880, 4458 | 15120, 4459 | 15600, 4460 | 16080, 4461 | 16320, 4462 | 16800, 4463 | 17280, 4464 | 0, 4465 | 0, 4466 | 0, 4467 | 0, 4468 | 0, 4469 | 240, 4470 | 480, 4471 | 0, 4472 | 0, 4473 | 240, 4474 | 720, 4475 | 0, 4476 | 0, 4477 | 0, 4478 | 0, 4479 | 0, 4480 | 0, 4481 | 0, 4482 | 0, 4483 | 0, 4484 | 0, 4485 | 0, 4486 | 0, 4487 | 0, 4488 | 0, 4489 | 0, 4490 | 0, 4491 | 0, 4492 | 0, 4493 | 0, 4494 | 0, 4495 | 0, 4496 | 0, 4497 | 0, 4498 | 0, 4499 | 0, 4500 | 0, 4501 | 0, 4502 | 480, 4503 | 720, 4504 | 0, 4505 | 0, 4506 | 0, 4507 | 480, 4508 | 960, 4509 | 1200, 4510 | 1680, 4511 | 2160 4512 | ], 4513 | "current_speech_samples": [ 4514 | 0, 4515 | 0, 4516 | 0, 4517 | 0, 4518 | 0, 4519 | 2400, 4520 | 2800, 4521 | 3200, 4522 | 3600, 4523 | 4000, 4524 | 4400, 4525 | 4800, 4526 | 5200, 4527 | 5600, 4528 | 6000, 4529 | 6400, 4530 | 6800, 4531 | 7200, 4532 | 7600, 4533 | 8000, 4534 | 8400, 4535 | 8800, 4536 | 9200, 4537 | 9600, 4538 | 10000, 4539 | 10400, 4540 | 5520, 4541 | 5520, 4542 | 5520, 4543 | 5520, 4544 | 5520, 4545 | 5520, 4546 | 5520, 4547 | 5520, 4548 | 5520, 4549 | 5520, 4550 | 5520, 4551 | 5520, 4552 | 5520, 4553 | 5520, 4554 | 5520, 4555 | 5520, 4556 | 5520, 4557 | 5520, 4558 | 5520, 4559 | 5520, 4560 | 5520, 4561 | 5520, 4562 | 5520, 4563 | 5520, 4564 | 5520, 4565 | 5520, 4566 | 5520, 4567 | 5520, 4568 | 5520, 4569 | 5520, 4570 | 5520, 4571 | 5520, 4572 | 5520, 4573 | 5520, 4574 | 6160, 4575 | 6560, 4576 | 6960, 4577 | 7360, 4578 | 7760, 4579 | 8160, 4580 | 8560, 4581 | 8960, 4582 | 9360, 4583 | 9760, 4584 | 10160, 4585 | 10560, 4586 | 10960, 4587 | 11360, 4588 | 11760, 4589 | 12160, 4590 | 12560, 4591 | 12960, 4592 | 13360, 4593 | 13760, 4594 | 14160, 4595 | 14560, 4596 | 14960, 4597 | 15360, 4598 | 15760, 4599 | 16160, 4600 | 16560, 4601 | 16960, 4602 | 17360, 4603 | 17760, 4604 | 18160, 4605 | 18560, 4606 | 18960, 4607 | 19360, 4608 | 19760, 4609 | 20160, 4610 | 20560, 4611 | 20960, 4612 | 21360, 4613 | 21760, 4614 | 22160, 4615 | 22560, 4616 | 22960, 4617 | 23360, 4618 | 23765 4619 | ], 4620 | "likelihoods": [ 4621 | 0, 4622 | 5, 4623 | 57, 4624 | 75, 4625 | 81, 4626 | 78, 4627 | 89, 4628 | 65, 4629 | 33, 4630 | 22, 4631 | 13, 4632 | 72, 4633 | 84, 4634 | 57, 4635 | 1, 4636 | 0, 4637 | 0, 4638 | 0, 4639 | 0, 4640 | 0, 4641 | 0, 4642 | 0, 4643 | 0, 4644 | 0, 4645 | 0, 4646 | 0, 4647 | 0, 4648 | 0, 4649 | 0, 4650 | 0, 4651 | 0, 4652 | 0, 4653 | 0, 4654 | 0, 4655 | 0, 4656 | 0, 4657 | 0, 4658 | 0, 4659 | 0, 4660 | 0, 4661 | 0, 4662 | 0, 4663 | 0, 4664 | 0, 4665 | 0, 4666 | 0, 4667 | 0, 4668 | 0, 4669 | 0, 4670 | 0, 4671 | 0, 4672 | 0, 4673 | 0, 4674 | 0, 4675 | 0, 4676 | 0, 4677 | 49, 4678 | 76, 4679 | 62, 4680 | 71, 4681 | 72, 4682 | 41, 4683 | 22, 4684 | 32, 4685 | 34, 4686 | 38, 4687 | 17, 4688 | 16, 4689 | 92, 4690 | 88, 4691 | 87, 4692 | 84, 4693 | 88, 4694 | 72, 4695 | 76, 4696 | 77, 4697 | 78, 4698 | 73, 4699 | 74, 4700 | 65, 4701 | 45, 4702 | 54, 4703 | 83, 4704 | 83, 4705 | 92, 4706 | 78, 4707 | 68, 4708 | 39, 4709 | 73, 4710 | 63, 4711 | 91, 4712 | 66, 4713 | 46, 4714 | 38, 4715 | 38, 4716 | 13, 4717 | 13, 4718 | 65, 4719 | 75, 4720 | 42, 4721 | 0, 4722 | 0, 4723 | 0, 4724 | 0, 4725 | 0 4726 | ] 4727 | }, 4728 | "tests/audio/sample_3.wav": { 4729 | "transitions": [ 4730 | { 4731 | "SpeechStart": { 4732 | "timestamp_ms": 0 4733 | } 4734 | }, 4735 | { 4736 | "SpeechEnd": { 4737 | "start_timestamp_ms": 0, 4738 | "end_timestamp_ms": 450 4739 | } 4740 | } 4741 | ], 4742 | "current_session_samples": [ 4743 | 400, 4744 | 800, 4745 | 1200, 4746 | 1600, 4747 | 2000, 4748 | 2400, 4749 | 2800, 4750 | 3200, 4751 | 3600, 4752 | 4000, 4753 | 4400, 4754 | 4800, 4755 | 5200, 4756 | 5600, 4757 | 6000, 4758 | 6400, 4759 | 6800, 4760 | 7200, 4761 | 7600, 4762 | 8000, 4763 | 8400, 4764 | 5199, 4765 | 5599, 4766 | 5999, 4767 | 6399, 4768 | 6799, 4769 | 7199, 4770 | 7599, 4771 | 7999, 4772 | 8399, 4773 | 8799, 4774 | 9199, 4775 | 9599, 4776 | 9999, 4777 | 10399, 4778 | 10799, 4779 | 11199, 4780 | 11599, 4781 | 11999, 4782 | 12399, 4783 | 12799, 4784 | 13199, 4785 | 13599, 4786 | 13999, 4787 | 14399, 4788 | 14799, 4789 | 15199, 4790 | 15599, 4791 | 15999, 4792 | 16399, 4793 | 16799, 4794 | 17199, 4795 | 17599, 4796 | 17999, 4797 | 18399, 4798 | 18799, 4799 | 19199, 4800 | 19599, 4801 | 19999, 4802 | 20399, 4803 | 20799, 4804 | 21199, 4805 | 21599, 4806 | 21999, 4807 | 22399, 4808 | 22799, 4809 | 23199, 4810 | 23599, 4811 | 23999, 4812 | 24612 4813 | ], 4814 | "current_silence_samples": [ 4815 | 240, 4816 | 720, 4817 | 1200, 4818 | 1440, 4819 | 0, 4820 | 0, 4821 | 0, 4822 | 0, 4823 | 0, 4824 | 240, 4825 | 720, 4826 | 1200, 4827 | 1440, 4828 | 1920, 4829 | 2400, 4830 | 2640, 4831 | 3120, 4832 | 3600, 4833 | 3840, 4834 | 4320, 4835 | 4800, 4836 | 5040, 4837 | 5520, 4838 | 6000, 4839 | 6240, 4840 | 6720, 4841 | 7200, 4842 | 7440, 4843 | 7920, 4844 | 8400, 4845 | 8640, 4846 | 9120, 4847 | 9600, 4848 | 9840, 4849 | 10320, 4850 | 10800, 4851 | 11040, 4852 | 11520, 4853 | 12000, 4854 | 12240, 4855 | 12720, 4856 | 13200, 4857 | 13440, 4858 | 13920, 4859 | 14400, 4860 | 14640, 4861 | 15120, 4862 | 15600, 4863 | 15840, 4864 | 16320, 4865 | 16800, 4866 | 17040, 4867 | 17520, 4868 | 18000, 4869 | 18240, 4870 | 18720, 4871 | 19200, 4872 | 19440, 4873 | 19920, 4874 | 20400, 4875 | 20640, 4876 | 21120, 4877 | 21600, 4878 | 21840, 4879 | 22320, 4880 | 22800, 4881 | 23040, 4882 | 23520, 4883 | 24000, 4884 | 24480 4885 | ], 4886 | "current_speech_samples": [ 4887 | 0, 4888 | 0, 4889 | 0, 4890 | 0, 4891 | 0, 4892 | 0, 4893 | 2800, 4894 | 3200, 4895 | 3600, 4896 | 4000, 4897 | 4400, 4898 | 4800, 4899 | 5200, 4900 | 5600, 4901 | 6000, 4902 | 6400, 4903 | 6800, 4904 | 7200, 4905 | 7600, 4906 | 8000, 4907 | 8400, 4908 | 3600, 4909 | 3600, 4910 | 3600, 4911 | 3600, 4912 | 3600, 4913 | 3600, 4914 | 3600, 4915 | 3600, 4916 | 3600, 4917 | 3600, 4918 | 3600, 4919 | 3600, 4920 | 3600, 4921 | 3600, 4922 | 3600, 4923 | 3600, 4924 | 3600, 4925 | 3600, 4926 | 3600, 4927 | 3600, 4928 | 3600, 4929 | 3600, 4930 | 3600, 4931 | 3600, 4932 | 3600, 4933 | 3600, 4934 | 3600, 4935 | 3600, 4936 | 3600, 4937 | 3600, 4938 | 3600, 4939 | 3600, 4940 | 3600, 4941 | 3600, 4942 | 3600, 4943 | 3600, 4944 | 3600, 4945 | 3600, 4946 | 3600, 4947 | 3600, 4948 | 3600, 4949 | 3600, 4950 | 3600, 4951 | 3600, 4952 | 3600, 4953 | 3600, 4954 | 3600, 4955 | 3600, 4956 | 3600 4957 | ], 4958 | "likelihoods": [ 4959 | 0, 4960 | 0, 4961 | 12, 4962 | 69, 4963 | 79, 4964 | 93, 4965 | 86, 4966 | 65, 4967 | 43, 4968 | 17, 4969 | 4, 4970 | 0, 4971 | 0, 4972 | 0, 4973 | 0, 4974 | 0, 4975 | 0, 4976 | 0, 4977 | 0, 4978 | 0, 4979 | 0, 4980 | 0, 4981 | 0, 4982 | 0, 4983 | 0, 4984 | 0, 4985 | 0, 4986 | 0, 4987 | 0, 4988 | 0, 4989 | 0, 4990 | 0, 4991 | 5, 4992 | 48, 4993 | 19, 4994 | 31, 4995 | 13, 4996 | 4, 4997 | 0, 4998 | 0, 4999 | 0, 5000 | 0, 5001 | 0, 5002 | 0, 5003 | 0, 5004 | 0, 5005 | 0, 5006 | 0, 5007 | 0, 5008 | 0, 5009 | 0, 5010 | 0, 5011 | 0, 5012 | 0, 5013 | 0, 5014 | 0, 5015 | 0, 5016 | 0, 5017 | 0, 5018 | 5, 5019 | 21, 5020 | 32, 5021 | 9, 5022 | 7, 5023 | 4, 5024 | 0, 5025 | 0, 5026 | 0, 5027 | 0, 5028 | 0 5029 | ] 5030 | }, 5031 | "tests/audio/sample_4.wav": { 5032 | "transitions": [ 5033 | { 5034 | "SpeechStart": { 5035 | "timestamp_ms": 0 5036 | } 5037 | } 5038 | ], 5039 | "current_session_samples": [ 5040 | 400, 5041 | 800, 5042 | 1200, 5043 | 1600, 5044 | 2000, 5045 | 2400, 5046 | 2800, 5047 | 3200, 5048 | 3600, 5049 | 4000, 5050 | 4400, 5051 | 4800, 5052 | 5200, 5053 | 5600, 5054 | 6000, 5055 | 6400, 5056 | 6800, 5057 | 7200, 5058 | 7600, 5059 | 8000, 5060 | 8400, 5061 | 8800, 5062 | 9200, 5063 | 9600, 5064 | 10000, 5065 | 10400, 5066 | 10800, 5067 | 11200, 5068 | 11600, 5069 | 12000, 5070 | 12400, 5071 | 12800, 5072 | 13200, 5073 | 13600, 5074 | 14000, 5075 | 14400, 5076 | 14800, 5077 | 15200, 5078 | 15600, 5079 | 16000, 5080 | 16400, 5081 | 16800, 5082 | 17200, 5083 | 17600, 5084 | 18000, 5085 | 18400, 5086 | 18800, 5087 | 19200, 5088 | 19600, 5089 | 20000, 5090 | 20400, 5091 | 20800, 5092 | 21200, 5093 | 21600, 5094 | 22000, 5095 | 22400, 5096 | 22800, 5097 | 23200, 5098 | 23600, 5099 | 24000, 5100 | 24400, 5101 | 24800, 5102 | 25200, 5103 | 25600, 5104 | 26000, 5105 | 26400, 5106 | 26800, 5107 | 27200, 5108 | 27600, 5109 | 28000, 5110 | 28400, 5111 | 28800, 5112 | 29200, 5113 | 29600, 5114 | 30000, 5115 | 30400, 5116 | 30800, 5117 | 31200, 5118 | 31600, 5119 | 32000, 5120 | 32400, 5121 | 32800, 5122 | 33200, 5123 | 33600, 5124 | 34000, 5125 | 34400, 5126 | 34800, 5127 | 35200, 5128 | 35600, 5129 | 36000, 5130 | 36400, 5131 | 36800, 5132 | 37200, 5133 | 37600, 5134 | 38000, 5135 | 38400, 5136 | 38800, 5137 | 39200, 5138 | 39600, 5139 | 40000, 5140 | 40400, 5141 | 40800, 5142 | 41200, 5143 | 41600, 5144 | 42000, 5145 | 42400, 5146 | 42800, 5147 | 43200, 5148 | 43600, 5149 | 44000, 5150 | 44400, 5151 | 44800, 5152 | 45200, 5153 | 45600, 5154 | 46000, 5155 | 46400, 5156 | 46800, 5157 | 47200, 5158 | 47600, 5159 | 48000, 5160 | 48400, 5161 | 48800, 5162 | 49200, 5163 | 49600, 5164 | 50000, 5165 | 50400, 5166 | 50800, 5167 | 51200, 5168 | 51600, 5169 | 52000, 5170 | 52400, 5171 | 52800, 5172 | 53200, 5173 | 53600, 5174 | 54000, 5175 | 54400, 5176 | 54800, 5177 | 55200, 5178 | 55600, 5179 | 56000, 5180 | 56400, 5181 | 56800, 5182 | 57200, 5183 | 57600, 5184 | 58000, 5185 | 58400, 5186 | 58800, 5187 | 59200, 5188 | 59600, 5189 | 60000, 5190 | 60400, 5191 | 60800, 5192 | 61200, 5193 | 61600, 5194 | 62000, 5195 | 62400, 5196 | 62800, 5197 | 63200, 5198 | 63600, 5199 | 64000, 5200 | 64400, 5201 | 64800, 5202 | 65200, 5203 | 65600, 5204 | 66000, 5205 | 66400, 5206 | 66800, 5207 | 67501 5208 | ], 5209 | "current_silence_samples": [ 5210 | 240, 5211 | 720, 5212 | 0, 5213 | 0, 5214 | 0, 5215 | 0, 5216 | 0, 5217 | 0, 5218 | 0, 5219 | 0, 5220 | 0, 5221 | 0, 5222 | 0, 5223 | 0, 5224 | 0, 5225 | 0, 5226 | 0, 5227 | 0, 5228 | 0, 5229 | 0, 5230 | 0, 5231 | 0, 5232 | 0, 5233 | 0, 5234 | 0, 5235 | 0, 5236 | 0, 5237 | 0, 5238 | 0, 5239 | 0, 5240 | 0, 5241 | 0, 5242 | 0, 5243 | 0, 5244 | 480, 5245 | 960, 5246 | 1200, 5247 | 1680, 5248 | 2160, 5249 | 2400, 5250 | 2880, 5251 | 3360, 5252 | 3600, 5253 | 4080, 5254 | 4560, 5255 | 4800, 5256 | 0, 5257 | 0, 5258 | 0, 5259 | 0, 5260 | 0, 5261 | 0, 5262 | 0, 5263 | 0, 5264 | 0, 5265 | 0, 5266 | 0, 5267 | 0, 5268 | 0, 5269 | 0, 5270 | 0, 5271 | 0, 5272 | 0, 5273 | 0, 5274 | 0, 5275 | 0, 5276 | 0, 5277 | 0, 5278 | 0, 5279 | 0, 5280 | 0, 5281 | 0, 5282 | 0, 5283 | 0, 5284 | 240, 5285 | 480, 5286 | 960, 5287 | 1440, 5288 | 1680, 5289 | 2160, 5290 | 2640, 5291 | 2880, 5292 | 3360, 5293 | 3840, 5294 | 4080, 5295 | 0, 5296 | 0, 5297 | 0, 5298 | 0, 5299 | 0, 5300 | 0, 5301 | 0, 5302 | 0, 5303 | 0, 5304 | 0, 5305 | 480, 5306 | 0, 5307 | 0, 5308 | 0, 5309 | 0, 5310 | 240, 5311 | 720, 5312 | 960, 5313 | 0, 5314 | 0, 5315 | 0, 5316 | 0, 5317 | 0, 5318 | 0, 5319 | 0, 5320 | 0, 5321 | 0, 5322 | 0, 5323 | 0, 5324 | 0, 5325 | 0, 5326 | 0, 5327 | 0, 5328 | 0, 5329 | 0, 5330 | 0, 5331 | 0, 5332 | 0, 5333 | 240, 5334 | 0, 5335 | 0, 5336 | 0, 5337 | 0, 5338 | 0, 5339 | 0, 5340 | 0, 5341 | 0, 5342 | 0, 5343 | 0, 5344 | 0, 5345 | 0, 5346 | 0, 5347 | 0, 5348 | 240, 5349 | 0, 5350 | 0, 5351 | 0, 5352 | 0, 5353 | 0, 5354 | 0, 5355 | 0, 5356 | 0, 5357 | 0, 5358 | 480, 5359 | 0, 5360 | 240, 5361 | 720, 5362 | 1200, 5363 | 0, 5364 | 480, 5365 | 0, 5366 | 0, 5367 | 480, 5368 | 0, 5369 | 0, 5370 | 0, 5371 | 0, 5372 | 0, 5373 | 240, 5374 | 720, 5375 | 960, 5376 | 1440, 5377 | 2160 5378 | ], 5379 | "current_speech_samples": [ 5380 | 0, 5381 | 0, 5382 | 0, 5383 | 0, 5384 | 0, 5385 | 2400, 5386 | 2800, 5387 | 3200, 5388 | 3600, 5389 | 4000, 5390 | 4400, 5391 | 4800, 5392 | 5200, 5393 | 5600, 5394 | 6000, 5395 | 6400, 5396 | 6800, 5397 | 7200, 5398 | 7600, 5399 | 8000, 5400 | 8400, 5401 | 8800, 5402 | 9200, 5403 | 9600, 5404 | 10000, 5405 | 10400, 5406 | 10800, 5407 | 11200, 5408 | 11600, 5409 | 12000, 5410 | 12400, 5411 | 12800, 5412 | 13200, 5413 | 13600, 5414 | 14000, 5415 | 14400, 5416 | 14800, 5417 | 15200, 5418 | 15600, 5419 | 16000, 5420 | 16400, 5421 | 16800, 5422 | 17200, 5423 | 17600, 5424 | 18000, 5425 | 18400, 5426 | 18800, 5427 | 19200, 5428 | 19600, 5429 | 20000, 5430 | 20400, 5431 | 20800, 5432 | 21200, 5433 | 21600, 5434 | 22000, 5435 | 22400, 5436 | 22800, 5437 | 23200, 5438 | 23600, 5439 | 24000, 5440 | 24400, 5441 | 24800, 5442 | 25200, 5443 | 25600, 5444 | 26000, 5445 | 26400, 5446 | 26800, 5447 | 27200, 5448 | 27600, 5449 | 28000, 5450 | 28400, 5451 | 28800, 5452 | 29200, 5453 | 29600, 5454 | 30000, 5455 | 30400, 5456 | 30800, 5457 | 31200, 5458 | 31600, 5459 | 32000, 5460 | 32400, 5461 | 32800, 5462 | 33200, 5463 | 33600, 5464 | 34000, 5465 | 34400, 5466 | 34800, 5467 | 35200, 5468 | 35600, 5469 | 36000, 5470 | 36400, 5471 | 36800, 5472 | 37200, 5473 | 37600, 5474 | 38000, 5475 | 38400, 5476 | 38800, 5477 | 39200, 5478 | 39600, 5479 | 40000, 5480 | 40400, 5481 | 40800, 5482 | 41200, 5483 | 41600, 5484 | 42000, 5485 | 42400, 5486 | 42800, 5487 | 43200, 5488 | 43600, 5489 | 44000, 5490 | 44400, 5491 | 44800, 5492 | 45200, 5493 | 45600, 5494 | 46000, 5495 | 46400, 5496 | 46800, 5497 | 47200, 5498 | 47600, 5499 | 48000, 5500 | 48400, 5501 | 48800, 5502 | 49200, 5503 | 49600, 5504 | 50000, 5505 | 50400, 5506 | 50800, 5507 | 51200, 5508 | 51600, 5509 | 52000, 5510 | 52400, 5511 | 52800, 5512 | 53200, 5513 | 53600, 5514 | 54000, 5515 | 54400, 5516 | 54800, 5517 | 55200, 5518 | 55600, 5519 | 56000, 5520 | 56400, 5521 | 56800, 5522 | 57200, 5523 | 57600, 5524 | 58000, 5525 | 58400, 5526 | 58800, 5527 | 59200, 5528 | 59600, 5529 | 60000, 5530 | 60400, 5531 | 60800, 5532 | 61200, 5533 | 61600, 5534 | 62000, 5535 | 62400, 5536 | 62800, 5537 | 63200, 5538 | 63600, 5539 | 64000, 5540 | 64400, 5541 | 64800, 5542 | 65200, 5543 | 65600, 5544 | 66000, 5545 | 66400, 5546 | 66800, 5547 | 67501 5548 | ], 5549 | "likelihoods": [ 5550 | 0, 5551 | 49, 5552 | 97, 5553 | 92, 5554 | 89, 5555 | 79, 5556 | 79, 5557 | 67, 5558 | 93, 5559 | 98, 5560 | 96, 5561 | 96, 5562 | 66, 5563 | 55, 5564 | 90, 5565 | 84, 5566 | 53, 5567 | 66, 5568 | 79, 5569 | 71, 5570 | 65, 5571 | 83, 5572 | 85, 5573 | 96, 5574 | 78, 5575 | 82, 5576 | 52, 5577 | 85, 5578 | 79, 5579 | 91, 5580 | 87, 5581 | 71, 5582 | 35, 5583 | 37, 5584 | 2, 5585 | 0, 5586 | 0, 5587 | 0, 5588 | 0, 5589 | 0, 5590 | 0, 5591 | 0, 5592 | 0, 5593 | 1, 5594 | 22, 5595 | 64, 5596 | 48, 5597 | 26, 5598 | 52, 5599 | 74, 5600 | 68, 5601 | 91, 5602 | 76, 5603 | 84, 5604 | 96, 5605 | 95, 5606 | 79, 5607 | 91, 5608 | 78, 5609 | 87, 5610 | 25, 5611 | 72, 5612 | 97, 5613 | 98, 5614 | 93, 5615 | 98, 5616 | 97, 5617 | 95, 5618 | 84, 5619 | 78, 5620 | 69, 5621 | 63, 5622 | 60, 5623 | 71, 5624 | 11, 5625 | 0, 5626 | 2, 5627 | 2, 5628 | 2, 5629 | 1, 5630 | 0, 5631 | 3, 5632 | 9, 5633 | 8, 5634 | 84, 5635 | 85, 5636 | 83, 5637 | 79, 5638 | 83, 5639 | 82, 5640 | 80, 5641 | 92, 5642 | 80, 5643 | 79, 5644 | 47, 5645 | 68, 5646 | 85, 5647 | 82, 5648 | 82, 5649 | 74, 5650 | 12, 5651 | 25, 5652 | 90, 5653 | 97, 5654 | 75, 5655 | 72, 5656 | 90, 5657 | 84, 5658 | 83, 5659 | 91, 5660 | 91, 5661 | 89, 5662 | 87, 5663 | 97, 5664 | 85, 5665 | 95, 5666 | 81, 5667 | 95, 5668 | 96, 5669 | 92, 5670 | 86, 5671 | 56, 5672 | 59, 5673 | 39, 5674 | 78, 5675 | 85, 5676 | 71, 5677 | 83, 5678 | 82, 5679 | 63, 5680 | 70, 5681 | 76, 5682 | 76, 5683 | 80, 5684 | 84, 5685 | 89, 5686 | 86, 5687 | 34, 5688 | 45, 5689 | 68, 5690 | 68, 5691 | 57, 5692 | 56, 5693 | 61, 5694 | 62, 5695 | 59, 5696 | 49, 5697 | 33, 5698 | 37, 5699 | 33, 5700 | 24, 5701 | 29, 5702 | 52, 5703 | 33, 5704 | 50, 5705 | 58, 5706 | 49, 5707 | 44, 5708 | 33, 5709 | 67, 5710 | 70, 5711 | 67, 5712 | 60, 5713 | 4, 5714 | 0, 5715 | 0, 5716 | 0, 5717 | 0 5718 | ] 5719 | } 5720 | } 5721 | } --------------------------------------------------------------------------------