PCM audio
16,000 Hz、單聲道、signed 16-bit。Linux 使用 SHORT*,Android 使用 short[]。
Cyberon Linux / Android integration guide
DSpotter KWS 負責找到 trigger phrase;CNSV VID 負責訓練或驗證說話者。 兩套 engine 共用音訊,由應用程式在命中時串起結果。
Interactive architecture
這張圖把兩個 engine、模型資產、應用層協調者與命中結果放在同一個可探索視圖。可切換 guided view、搜尋節點、追蹤路徑或匯出圖片。
圖中文字使用繁體中文;Archify 固定 Viewer 控制項目前顯示英文。
全頁開啟互動架構 ↗01 / interaction
Cyberon 沒有合併的 VID+KWS API。Sample app 持有兩個 handle,將每批 PCM 同時送入兩套 engine。
16,000 Hz、單聲道、signed 16-bit。Linux 使用 SHORT*,Android 使用 short[]。
DSpotter 回傳命中區間;CNSV 擷取該段音訊,執行 TrainSpeaker 或 GetResult。
02 / lifecycle
以下順序對應 Linux sample。Android 的初始化先後相反,但開始處理前同樣需要兩個有效 handle。
初始化需要 Cyberon license、DSpotter command pack、CNSV pretrained model。驗證模式另載入已註冊的 speaker models。
Linux sample 設 10 秒 ring buffer、最多 10 位 speaker、1 個 ONNX thread,並使用 batch mode。數值 10 是 sample 設定,不是 SDK 保證的硬上限。
hCNSV = CNSVApi_Init(
license, 10, 10, svModel,
1, FALSE, &err, NULL, NULL
);
CNSVApi_SetThreshold(hCNSV, threshold);
先從 pack 取得 group 數並選擇要啟用的 group,再建立 KWS engine。建立後可以列舉 pack 內的 commands。
int groups = DSpotterGetNumGroup(packBin);
// enableGroup[0..groups-1] = TRUE
hKWS = DSpotterInitMultiWithPackBin(
packBin, enableGroup, 500,
NULL, 0, &err, license, NULL
);
nNumSample 是 sample 數,不是 byte 數。應用程式必須維持相同的連續音訊與順序。
int kwsRet = DSpotterAddSample(hKWS, pcm, sampleCount);
int svRet = CNSVApi_AddSample(hCNSV, pcm, sampleCount);
if (kwsRet == DSPOTTER_SUCCESS) {
// retrieve result and verify speaker
}
DSpotter 回傳 word duration、end silence 與 network latency。Sample 將它們直接組成 CNSV 的回溯座標。
nStart = wordDura + endSil + latency
nEnd = endSil + latency
DSpotterGetUTF8Result(hKWS, &cmd, result,
&wordDura, &endSil, &latency,
&confidence, &sgDiff, &fil);
// Enrollment
CNSVApi_TrainSpeaker(hCNSV, nStart, nEnd, &speakerModel);
// Verification
CNSVApi_GetResult(hCNSV, nStart, nEnd,
&speakerId, speakerName, &score);
每次 hit 處理後清除 CNSV 的音訊狀態,並讓 DSpotter 進入下一輪。程式結束時分別釋放兩個 handle。
CNSVApi_Reset(hCNSV);
DSpotterContinue(hKWS);
// shutdown
CNSVApi_Release(hCNSV);
DSpotterRelease(hKWS);
03 / audio contract
CNSV 與 DSpotter sample 使用同一種格式,所以能直接 dual-feed,不需要 resample 或型別轉換。
| 項目 | 契約 | 整合提醒 |
|---|---|---|
| Sample rate | 16,000 Hz | Android recognizer 由 DSpotterGetSampleRate() 建 recorder |
| Channel | Mono | 不要直接餵 interleaved stereo |
| Sample type | Signed PCM16 | Linux SHORT*;Android short[] |
| Input count | Sample 數 | Linux sample 使用 bytes / sizeof(SHORT) |
| Frame size | API 未規定固定大小 | Android demo 自選 30 ms=480 samples=960 bytes |
nStart/nEnd | 相對最新 sample 的回溯距離 | 不是絕對 timestamp |
CNSVApi_AddSample() 只累積資料,通常回 CNSVApi_Err_NeedMoreSample。Inference 在 TrainSpeaker、GetResult 或 GetBestResult 發生。
若初始化開啟 streaming,CNSV 可在 AddSample 期間執行 inference;觸發 inference 時回 success。目前 Linux 與 Android demo 都沒有採用此模式。
04 / public surface
實作時以交付的 header 或 Java JNI facade 為準;Programming Guide 主要用來確認 CNSV 的行為語意。
Init、Reset、Release、GetVersionAddSample、GetResult、GetBestResult、SetThresholdTrainSpeakerSaveSpeakerToFile、LoadSpeakerFromFile| 平台 | CNSV | DSpotter | 主要差異 |
|---|---|---|---|
| Linux x86-64 | C API/libCNSV.so | C API/libDSpotter.so | 提供 UTF-16 result 與 command APIs |
| Android arm64-v8a | Java/JNI/long handle | Java/JNI/long handle | 保留 deprecated tuning,另有 result ID mapping setter |
| Android armeabi-v7a | 有 CNSV native library | 交付物中沒有 DSpotter native library | 不能視為完整 KWS+VID 組合 |
05 / verify before production
PDF 的 Init 帶 VAD runtime/model,並列出 SetNormalize 與 ByID APIs;實際 CNSV.java 使用 ONNX thread、streaming flag 與 ByIndex APIs。
Sample 把 timing 當成 CNSV sample offsets,但 DSpotter header 沒有正式定義單位、範圍或跨版本穩定性。
TrainSpeaker() 成功值有衝突Guide 寫 success 為 0;Linux sample 將正值當成累積 reference-vector 數量。正式 wrapper 應先向 vendor 確認。
SDK 還有 exceed-max-speaker 與 license-count-exceeded 錯誤。生產上限、thread safety 與 instance 數量都需要正式規格。
Evidence map
Official guides:Windows/Linux CNSV Programming Guide §3;Android CNSV Programming Guide §3;Android CNSVDemo User Guide §1、§3。
Linux source:CNSVApi.h、DSpotterApi.h、DSpotterApi_Const.h、CNSVDemo.c。
Android source:CNSV.java、DSpotter.java、SVTrainer.java、SVRecognizer.java。
範圍:文件與原始碼分析;沒有宣稱已完成 live microphone、準確率、延遲或 thread-safety 驗證。