refactor : 重构TTS的文字分割方式,队列请求/播放方式, fix : asr录制音频的音量波纹显示
This commit is contained in:
@@ -95,43 +95,81 @@ export function useRealtimeRecorderOnce() {
|
||||
|
||||
// --- 音量计算函数 ---
|
||||
const calculateVolumeFromFloat32 = (float32Array) => {
|
||||
if (!float32Array || float32Array.length === 0) return 0;
|
||||
|
||||
let sum = 0;
|
||||
const length = float32Array.length;
|
||||
|
||||
// 计算RMS (均方根)
|
||||
for (let i = 0; i < length; i++) {
|
||||
sum += float32Array[i] * float32Array[i];
|
||||
// 绝对值方法更敏感
|
||||
const absValue = Math.abs(float32Array[i]);
|
||||
sum += absValue * absValue;
|
||||
}
|
||||
|
||||
const rms = Math.sqrt(sum / length);
|
||||
|
||||
|
||||
// 调试:打印原始RMS值
|
||||
// console.log('Float32 RMS:', rms);
|
||||
|
||||
// 转换为0-100的值
|
||||
// 通常对话语音的RMS在0.01-0.1之间,尖叫可达0.3
|
||||
let volume = Math.min(100, Math.floor(rms * 300));
|
||||
// 使用对数刻度,使小音量变化更明显
|
||||
let volume = 0;
|
||||
|
||||
if (rms > 0) {
|
||||
// 使用对数转换:-60dB到0dB映射到0-100
|
||||
const db = 20 * Math.log10(rms);
|
||||
// 静音阈值约-60dB
|
||||
if (db > -60) {
|
||||
volume = Math.min(100, Math.max(0, (db + 60) / 0.6));
|
||||
}
|
||||
}
|
||||
|
||||
// 设置最小阈值,避免静音时完全为0
|
||||
if (volume < 5) volume = 0;
|
||||
// 如果没有计算到值,使用旧方法作为fallback
|
||||
if (volume === 0 && rms > 0) {
|
||||
volume = Math.min(100, Math.floor(rms * 500));
|
||||
}
|
||||
|
||||
return volume;
|
||||
// 确保最小值为0
|
||||
return Math.max(0, volume);
|
||||
}
|
||||
|
||||
const calculateVolumeFromInt16 = (int16Array) => {
|
||||
if (!int16Array || int16Array.length === 0) return 0;
|
||||
|
||||
let sum = 0;
|
||||
const length = int16Array.length;
|
||||
|
||||
|
||||
// 计算RMS
|
||||
for (let i = 0; i < length; i++) {
|
||||
const normalized = int16Array[i] / 32768; // 归一化到[-1, 1]
|
||||
sum += normalized * normalized;
|
||||
const absValue = Math.abs(normalized);
|
||||
sum += absValue * absValue;
|
||||
}
|
||||
|
||||
const rms = Math.sqrt(sum / length);
|
||||
|
||||
|
||||
// 调试:打印原始RMS值
|
||||
// console.log('Int16 RMS:', rms);
|
||||
|
||||
// 转换为0-100的值
|
||||
let volume = Math.min(100, Math.floor(rms * 300));
|
||||
|
||||
// 设置最小阈值
|
||||
if (volume < 5) volume = 0;
|
||||
|
||||
return volume;
|
||||
// 使用对数刻度
|
||||
let volume = 0;
|
||||
|
||||
if (rms > 0) {
|
||||
const db = 20 * Math.log10(rms);
|
||||
if (db > -60) {
|
||||
volume = Math.min(100, Math.max(0, (db + 60) / 0.6));
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有计算到值,使用旧方法作为fallback
|
||||
if (volume === 0 && rms > 0) {
|
||||
volume = Math.min(100, Math.floor(rms * 500));
|
||||
}
|
||||
|
||||
// 确保最小值为0
|
||||
return Math.max(0, volume);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -377,29 +415,67 @@ export function useRealtimeRecorderOnce() {
|
||||
return;
|
||||
}
|
||||
|
||||
// 生成波形数据,基于当前音量
|
||||
const baseValue = volumeLevel.value / 100;
|
||||
// 获取当前音量值
|
||||
const currentVolume = volumeLevel.value;
|
||||
|
||||
// 调试:打印音量值
|
||||
// console.log('Current Volume:', currentVolume);
|
||||
|
||||
// 生成适合 WaveDisplay 的数据
|
||||
const data = [];
|
||||
|
||||
// 生成31个数据点
|
||||
const center = 15; // 中心索引
|
||||
const timeFactor = Date.now() / 150; // 更快的动画
|
||||
|
||||
// 根据音量动态调整波形强度
|
||||
const volumeFactor = currentVolume / 100;
|
||||
|
||||
// 添加基础噪声,使波形在安静时也有轻微活动
|
||||
const baseNoise = Math.random() * 0.1;
|
||||
|
||||
for (let i = 0; i < 31; i++) {
|
||||
// 使用正弦波生成波形效果,中间高两边低
|
||||
const position = i / 30;
|
||||
const centerDistance = Math.abs(position - 0.5);
|
||||
const waveValue = Math.sin(Date.now() / 200 + i * 0.3) * 0.4 + 0.5;
|
||||
|
||||
// 音量因子确保最小显示高度
|
||||
const volumeFactor = baseValue * 0.7 + 0.3;
|
||||
|
||||
// 综合计算最终值
|
||||
let finalValue = waveValue * (1 - centerDistance) * volumeFactor;
|
||||
finalValue = Math.max(0.1, Math.min(1, finalValue));
|
||||
|
||||
data.push(finalValue);
|
||||
// 距离中心的位置
|
||||
const distanceFromCenter = Math.abs(i - center) / center;
|
||||
|
||||
// 基础波形模式
|
||||
const basePattern = 1 - Math.pow(distanceFromCenter, 1.2);
|
||||
|
||||
// 动态效果
|
||||
const dynamicEffect = Math.sin(timeFactor + i * 0.3) * 0.3;
|
||||
|
||||
// 计算基础值
|
||||
let value;
|
||||
|
||||
if (volumeFactor > 0.1) {
|
||||
// 有音量时:音量因子占主导
|
||||
value = volumeFactor * 0.8 * basePattern +
|
||||
volumeFactor * 0.4 +
|
||||
dynamicEffect * volumeFactor * 0.5;
|
||||
} else {
|
||||
// 安静时:使用动态效果和基础噪声
|
||||
value = basePattern * 0.2 +
|
||||
dynamicEffect * 0.1 +
|
||||
baseNoise;
|
||||
}
|
||||
|
||||
// 确保值在有效范围内
|
||||
value = Math.max(0.15, Math.min(1, value));
|
||||
|
||||
// 随机微调
|
||||
const randomVariance = volumeFactor > 0.1 ? 0.15 : 0.05;
|
||||
value += (Math.random() - 0.5) * randomVariance;
|
||||
value = Math.max(0.15, Math.min(1, value));
|
||||
|
||||
data.push(value);
|
||||
}
|
||||
|
||||
|
||||
audioDataForDisplay.value = data;
|
||||
}, 50); // 更快的刷新率,更流畅
|
||||
|
||||
// 调试:检查生成的数据范围
|
||||
// const min = Math.min(...data);
|
||||
// const max = Math.max(...data);
|
||||
// console.log(`Data range: ${min.toFixed(3)} - ${max.toFixed(3)}`);
|
||||
|
||||
}, 50);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user