功能: - 基于 ONNX 的语音识别引擎 - 多语言支持(中文、英文、日语、韩语) - 模型加载器(支持 SenseVoice/Whisper/Paraformer) - 音频采集和处理模块(VAD、重采样、归一化) - 文本输出模块(剪贴板) - CLI 命令行工具 - Electron GUI 界面 - Windows x64 打包配置 文档: - PRD 产品需求文档 - README 项目说明 - 开发指南 - Windows 构建指南 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
91 lines
2.6 KiB
TypeScript
91 lines
2.6 KiB
TypeScript
/**
|
|
* 音频处理器测试
|
|
*/
|
|
|
|
import { describe, it, expect } from 'vitest';
|
|
import { normalizeAudio, resample, SimpleVAD, frameAudio } from '../src/core/audio-processor.js';
|
|
|
|
describe('audio-processor', () => {
|
|
describe('normalizeAudio', () => {
|
|
it('应该归一化 Int16Array 数据', () => {
|
|
const input = new Int16Array([32767, -32768, 0, 16384]);
|
|
const result = normalizeAudio(input, 16000);
|
|
|
|
expect(result).toBeInstanceOf(Float32Array);
|
|
expect(result.length).toBe(input.length);
|
|
expect(result[0]).toBeCloseTo(1, 3);
|
|
expect(result[1]).toBeCloseTo(-1, 3);
|
|
expect(result[2]).toBe(0);
|
|
});
|
|
|
|
it('应该处理 Float32Array 输入', () => {
|
|
const input = new Float32Array([1, -1, 0, 0.5]);
|
|
const result = normalizeAudio(input, 16000);
|
|
|
|
expect(result).toBe(input);
|
|
});
|
|
});
|
|
|
|
describe('resample', () => {
|
|
it('应该保持相同采样率的数据不变', () => {
|
|
const input = new Float32Array([1, 2, 3, 4]);
|
|
const result = resample(input, 16000, 16000);
|
|
|
|
expect(result).toBe(input);
|
|
});
|
|
|
|
it('应该降低采样率', () => {
|
|
const input = new Float32Array([1, 2, 3, 4, 5, 6, 7, 8]);
|
|
const result = resample(input, 16000, 8000);
|
|
|
|
expect(result.length).toBe(4);
|
|
});
|
|
});
|
|
|
|
describe('SimpleVAD', () => {
|
|
it('应该检测到高能量音频', () => {
|
|
const vad = new SimpleVAD({ energyThreshold: 0.01 });
|
|
const loudFrame = new Float32Array([0.5, 0.6, 0.7, 0.8]);
|
|
|
|
const result = vad.process(loudFrame, 16000);
|
|
|
|
expect(result.isSpeaking).toBe(true);
|
|
});
|
|
|
|
it('应该忽略低能量音频', () => {
|
|
const vad = new SimpleVAD({ energyThreshold: 0.01 });
|
|
const quietFrame = new Float32Array([0.001, 0.002, 0.001, 0]);
|
|
|
|
const result = vad.process(quietFrame, 16000);
|
|
|
|
expect(result.isSpeaking).toBe(false);
|
|
});
|
|
|
|
it('应该重置状态', () => {
|
|
const vad = new SimpleVAD();
|
|
vad.process(new Float32Array([0.5, 0.6, 0.7]), 16000);
|
|
vad.reset();
|
|
|
|
expect(vad.process(new Float32Array([0]), 16000).isSpeaking).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('frameAudio', () => {
|
|
it('应该正确分帧', () => {
|
|
const input = new Float32Array([1, 2, 3, 4, 5, 6, 7, 8]);
|
|
const frames = frameAudio(input, 4, 2);
|
|
|
|
expect(frames.length).toBe(4);
|
|
expect(frames[0]).toEqual(new Float32Array([1, 2, 3, 4]));
|
|
expect(frames[1]).toEqual(new Float32Array([3, 4, 5, 6]));
|
|
});
|
|
|
|
it('应该处理不足一帧的数据', () => {
|
|
const input = new Float32Array([1, 2, 3]);
|
|
const frames = frameAudio(input, 4, 2);
|
|
|
|
expect(frames.length).toBe(0);
|
|
});
|
|
});
|
|
});
|