如何在c#中计算波信号的混响时间
本文关键字:信号 时间 计算 | 更新日期: 2023-09-27 17:49:17
我正在尝试在c#中开发一个控制台应用程序,该应用程序使用wav文件进行输入。应用程序应该按顺序完成几件事情,如下所示。首先,完整的代码:
class Program
{
static List<double> points = new List<double>();
static double maxValue = 0;
static double minValue = 1;
static int num = 0;
static int num2 = 0;
static List<double> values = new List<double>();
private static object akima;
static void Main(string[] args)
{
string[] fileLines = File.ReadAllLines(args[0]);
int count = 0;
foreach (string fileLine in fileLines)
{
if (!fileLine.Contains(";"))
{
string processLine = fileLine.Trim();
processLine = Regex.Replace(processLine, @"'s+", " ");
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
processLine = processLine.Replace(".", ",");
}
string[] dataParts = processLine.Split(Char.Parse(" "));
points.Add(double.Parse(dataParts[0]));
double value = Math.Pow(double.Parse(dataParts[1]), 2);
if (value > maxValue)
{
maxValue = value;
num = count;
}
values.Add(value);
}
count++;
}
for (int i = num; i < values.Count; i++)
{
if (values[i] < minValue)
{
minValue = values[i];
num2 = i;
}
}
Console.WriteLine(num + " " + num2);
int between = num2 - num;
points = points.GetRange(num, between);
values = values.GetRange(num, between);
List<double> defVal = new List<double>();
List<double> defValPoints = new List<double>();
alglib.spline1dinterpolant c;
alglib.spline1dbuildakima(points.ToArray(), values.ToArray(), out c);
double baseInt = alglib.spline1dintegrate(c, points[points.Count - 1]);
List<double> defETC = new List<double>();
for (int i = 0; i < points.Count; i += 10)
{
double toVal = points[i];
defETC.Add(10 * Math.Log10(values[i]));
defVal.Add(10 * Math.Log10((baseInt - alglib.spline1dintegrate(c, toVal)) / baseInt));
defValPoints.Add(points[i]);
}
WriteDoubleArrayToFile(defValPoints.ToArray(), defVal.ToArray(), "test.dat");
WriteDoubleArrayToFile(defValPoints.ToArray(), defETC.ToArray(), "etc.dat");
int end = 0;
for (int i = 0; i < points.Count; i++)
{
if (defVal[i] < -10)
{
end = i;
break;
}
}
//Console.WriteLine(num + " " + end);
int beginEDT = num;
int endEDT = num + end;
double timeBetween = (defValPoints[endEDT] - defValPoints[beginEDT]) * 6;
Console.WriteLine(timeBetween);
for (int i = 0; i < points.Count; i++)
{
}
Console.ReadLine();
}
static void WriteDoubleArrayToFile(double[] points, double[] values, string filename)
{
string[] defStr = new string[values.Length];
for (int i = 0; i < values.Length; i++)
{
defStr[i] = String.Format("{0,10}{1,25}", points[i], values[i]);
}
File.WriteAllLines(filename, defStr);
}
}
- 从wave文件中提取十进制/浮点数/双精度值
- 从提取的数据创建数组
- 创建一个能量时间曲线,以类似分贝的方式显示噪音/声音的衰减
- 从步骤3中创建的ETC创建衰减曲线
- 从这个衰减曲线中计算出早期衰减时间(EDT), T15/T20和RT60。
- 在标准输出中显示这些混响时间
此刻,我似乎已经完成了一半的过程。我将解释我所做的:
- 我使用Sox将音频文件转换为带有数字 的。dat文件
- 我使用c#创建了一个数组,通过简单地分割上面文件中的每一行,并将时间放在TimesArray中,并将这些点的值放在ValuesArray中。
- 我通过GNUPlot显示一个图形,使用这个函数处理的数据:10 * Math.Log10(values[I]);(其中i是for循环中迭代ValuesArray中所有项的迭代整数)
- 这就是我开始卡住的地方。我的意思是,在这一步中,我使用了一个Akima样条函数从Alglib来积分一条线。我用的是施罗德积分(反向),通过数学计算:10 *数学。Log10((baseInt - alglib);spline1 dinintegrate (c, toVal))/baseInt);(其中baseInt是作为完整曲线的基积分计算的值,因此我有一个反向施罗德积分的计算底部部分。c是在使用函数函数库时可用的样条插值。spline1dbuildakima,它将timeArray作为x值,valueArray作为y值,c作为向外spline1dinterpolant。Toval是来自points数组的x值。使用for循环选择特定的值。)从这些新保存的值中,我想创建一条插值线,并从该线计算RT60,但我不知道如何做到这一点。
- 尝试了,但没有成功。
- 和上面一样,我没有实际值显示
我现在很困,因为我不确定这是不是正确的方法。如果有人能告诉我如何在c#中以快速响应的方式计算混响时间,我会很高兴听到。做这件事的方法可能和我现在的完全不同,没关系,告诉我就行了!
也许你需要用不同的方式来处理这个问题:
- 从基础数学开始。找出这些函数的数学公式。
- 使用简单的数学函数并手动计算(在excel或matlab中)值应该是什么(所有这些东西,ETC, DC, EDC, T15, T20, RT60)(一个函数,如正弦波只是你需要的最小点数)
- 然后编写一个单独的过程来评估c#中的每个过程,并验证您的结果与excel/matlab的一致性。
,可能将数据存储在一个类中,然后传递给每个方法进行计算。
你的main函数应该像这样结束:
main(){
data = new Data();
//1, 2:
extract_data(data, filename);
//3:
energy_time_curve(data)
//...4, 5
//6:
display_results(data);
}