/* 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; } } }