/* Copyright (C) 2014 DaikonForge */
namespace DaikonForge.VoIP
{
using UnityEngine;
///
/// 定义音频采样的频率模式枚举
///
public enum FrequencyMode
{
///
/// 窄频模式
///
Narrow,
///
/// 宽频模式
///
Wide,
///
/// 超宽频模式
///
UltraWide
}
///
/// 定义一个频率提供器接口,用于根据不同的频率模式提供对应的采样频率
///
public interface IFrequencyProvider
{
///
/// 根据指定的频率模式获取对应的采样频率
///
/// 频率模式
/// 采样频率
int GetFrequency(FrequencyMode mode);
}
///
/// 音频处理的工具类,包含音频重采样、增益调整、获取最大振幅等实用方法
///
public class AudioUtils
{
///
/// 频率提供器实例,使用SpeexCodec中的频率提供器实现
///
public static IFrequencyProvider FrequencyProvider = new SpeexCodec.FrequencyProvider();
///
/// 临时存储音频采样数据的快速列表,用于音频重采样时的数据处理
///
private static FastList temp = new FastList();
///
/// 根据指定的频率模式获取对应的采样频率
///
/// 频率模式
/// 采样频率
public static int GetFrequency(FrequencyMode mode)
{
return FrequencyProvider.GetFrequency(mode);
}
///
/// 对音频采样数据进行重采样,将其从旧的采样频率转换为新的采样频率
///
/// 音频采样数据数组
/// 旧的采样频率
/// 新的采样频率
public static void Resample(BigArray samples, int oldFrequency, int newFrequency)
{
// 如果新旧采样频率相同,则无需进行重采样操作
if (oldFrequency == newFrequency) return;
// 清空临时存储列表,为新的重采样数据做准备
temp.Clear();
// 计算新旧采样频率的比率,用于后续索引计算
float ratio = (float)oldFrequency / (float)newFrequency;
int outSample = 0;
// 循环处理,直到超出原采样数据的长度
while (true)
{
// 根据比率计算在原采样数据中的索引
int inBufferIndex = (int)(outSample++ * ratio);
if (inBufferIndex < samples.Length)
// 如果索引在原采样数据长度范围内,则将对应的数据添加到临时列表中
temp.Add(samples[inBufferIndex]);
else
// 超出原采样数据长度,退出循环
break;
}
// 调整采样数据数组的大小,使其与重采样后的数据长度一致
samples.Resize(temp.Count);
// 将临时列表中的重采样数据复制回采样数据数组中
samples.CopyFrom(temp.Items, 0, 0, temp.Count * 4);
}
///
/// 对音频采样数据应用增益,即对每个采样值乘以增益系数
///
/// 音频采样数据数组
/// 增益系数
public static void ApplyGain(float[] samples, float gain)
{
// 遍历每个采样值,乘以增益系数
for (int i = 0; i < samples.Length; i++)
samples[i] *= gain;
}
///
/// 获取音频采样数据中的最大振幅
///
/// 音频采样数据数组
/// 最大振幅
public static float GetMaxAmplitude(float[] samples)
{
float max = 0f;
// 遍历每个采样值,更新最大振幅
for (int i = 0; i < samples.Length; i++)
max = Mathf.Max(max, Mathf.Abs(samples[i]));
return max;
}
}
}