124 lines
4.5 KiB
C#
124 lines
4.5 KiB
C#
/* Copyright (C) 2014 DaikonForge */
|
||
|
||
namespace DaikonForge.VoIP
|
||
{
|
||
using UnityEngine;
|
||
|
||
/// <summary>
|
||
/// 定义音频采样的频率模式枚举
|
||
/// </summary>
|
||
public enum FrequencyMode
|
||
{
|
||
/// <summary>
|
||
/// 窄频模式
|
||
/// </summary>
|
||
Narrow,
|
||
/// <summary>
|
||
/// 宽频模式
|
||
/// </summary>
|
||
Wide,
|
||
/// <summary>
|
||
/// 超宽频模式
|
||
/// </summary>
|
||
UltraWide
|
||
}
|
||
|
||
/// <summary>
|
||
/// 定义一个频率提供器接口,用于根据不同的频率模式提供对应的采样频率
|
||
/// </summary>
|
||
public interface IFrequencyProvider
|
||
{
|
||
/// <summary>
|
||
/// 根据指定的频率模式获取对应的采样频率
|
||
/// </summary>
|
||
/// <param name="mode">频率模式</param>
|
||
/// <returns>采样频率</returns>
|
||
int GetFrequency(FrequencyMode mode);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 音频处理的工具类,包含音频重采样、增益调整、获取最大振幅等实用方法
|
||
/// </summary>
|
||
public class AudioUtils
|
||
{
|
||
/// <summary>
|
||
/// 频率提供器实例,使用SpeexCodec中的频率提供器实现
|
||
/// </summary>
|
||
public static IFrequencyProvider FrequencyProvider = new SpeexCodec.FrequencyProvider();
|
||
/// <summary>
|
||
/// 临时存储音频采样数据的快速列表,用于音频重采样时的数据处理
|
||
/// </summary>
|
||
private static FastList<float> temp = new FastList<float>();
|
||
|
||
/// <summary>
|
||
/// 根据指定的频率模式获取对应的采样频率
|
||
/// </summary>
|
||
/// <param name="mode">频率模式</param>
|
||
/// <returns>采样频率</returns>
|
||
public static int GetFrequency(FrequencyMode mode)
|
||
{
|
||
return FrequencyProvider.GetFrequency(mode);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 对音频采样数据进行重采样,将其从旧的采样频率转换为新的采样频率
|
||
/// </summary>
|
||
/// <param name="samples">音频采样数据数组</param>
|
||
/// <param name="oldFrequency">旧的采样频率</param>
|
||
/// <param name="newFrequency">新的采样频率</param>
|
||
public static void Resample(BigArray<float> 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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 对音频采样数据应用增益,即对每个采样值乘以增益系数
|
||
/// </summary>
|
||
/// <param name="samples">音频采样数据数组</param>
|
||
/// <param name="gain">增益系数</param>
|
||
public static void ApplyGain(float[] samples, float gain)
|
||
{
|
||
// 遍历每个采样值,乘以增益系数
|
||
for (int i = 0; i < samples.Length; i++)
|
||
samples[i] *= gain;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取音频采样数据中的最大振幅
|
||
/// </summary>
|
||
/// <param name="samples">音频采样数据数组</param>
|
||
/// <returns>最大振幅</returns>
|
||
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;
|
||
}
|
||
}
|
||
} |