audioUtil.js
2.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**
* 音频处理工具类
* 用于语音对讲功能的 PCM 格式转换与编码
*/
// 【修改】降采样并转换函数:Float32(44.1k/48k) -> Int16(8k)
export function resampleTo8kInt16(audioData, sampleRate) {
const targetSampleRate = 8000; // 目标采样率
const ratio = sampleRate / targetSampleRate;
const newLength = Math.round(audioData.length / ratio);
const result = new Int16Array(newLength);
for (let i = 0; i < newLength; i++) {
// 简单的线性插值或直接抽取
const index = Math.floor(i * ratio);
let s = audioData[index];
// 限幅处理,防止爆音
s = Math.max(-1, Math.min(1, s));
// 转换到 Int16 范围: s < 0 ? s * 0x8000 : s * 0x7FFF
result[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;
}
return result;
}
/**
* 将 Web Audio API 的 Float32Array (采样率 44.1k/48k/8k) 转换为 PCM Int16
* @param {Float32Array} float32Array - 原始音频数据
* @returns {Int16Array} - 转换后的 16位 PCM 数据
*/
export function floatTo16BitPCM(float32Array) {
var l = float32Array.length
var buffer = new ArrayBuffer(l * 2)
var view = new DataView(buffer)
for (var i = 0; i < l; i++) {
// 限制范围在 -1 到 1 之间
var s = Math.max(-1, Math.min(1, float32Array[i]))
// 转换公式:负数 * 0x8000,正数 * 0x7FFF,并使用小端序 (little-endian)
view.setInt16(i * 2, s < 0 ? s * 0x8000 : s * 0x7fff, true)
}
return new Int16Array(buffer)
}
/**
* 将 Uint8Array 二进制数据转换为 Base64 字符串
* @param {Uint8Array} u8 - 二进制数据
* @returns {string} - Base64 字符串
*/
export function uint8ArrayToBase64(u8) {
var CHUNK_SIZE = 0x8000 // 32768
var index = 0
var length = u8.length
var result = ''
var slice
// 分块处理防止栈溢出
while (index < length) {
slice = u8.subarray(index, Math.min(index + CHUNK_SIZE, length))
result += String.fromCharCode.apply(null, slice)
index += CHUNK_SIZE
}
return btoa(result)
}
/**
* 快捷组合函数:直接将 Float32Array 音频数据转为 Base64 字符串
* (常用于语音对讲发送)
* @param {Float32Array} float32Array
* @returns {string}
*/
export function pcmToG711Base64(float32Array) {
const pcm16 = floatTo16BitPCM(float32Array)
const u8 = new Uint8Array(pcm16.buffer)
return uint8ArrayToBase64(u8)
}
export default {
floatTo16BitPCM,
uint8ArrayToBase64,
pcmToG711Base64
}