函数在单步执行时和单步执行时的行为不同

Function behaves differently when stepping through to when stepping over

我在对使用 NAudio 的 PinkNoiseGenerator 的函数进行单元测试时遇到问题。

createPinkNoiseGeneratorLists 函数的行为似乎与单步执行程序时的预期非常一致 - 也就是说,receiverGeneratorList(见下文)填充了 PinkNoiseGenerator 列表,每个列表都包含样本列表其中,至关重要的是,它们都有不同的值:

单步执行函数时出现问题。 receiverGeneratorList 仍然填充有 PinkNoiseGenerators 列表,但样本具有相同的值:

第二种行为是不需要的。我需要粉红噪声发生器在测试和程序为 运行 时具有不同的值。我已将行为缩小为以下嵌套 for 循环(底部的完整代码):

for (int j = 0; j < receiverList[i].AmplitudeCurveList.Count; j++)
{
    // Calculate duration of pink noise in seconds

    double time = receiverList[i].AmplitudeCurveList[j].Count / (double)sampleRate;

    // Instantiate new generator (list of pink noise samples) at given duration

    PinkNoiseGenerator generator = new PinkNoiseGenerator(time, sampleRate, outputFileName, numberOfChannels);

    // Add generator to generator list which will then be added to the list of lists of pink noise generators,

    generatorList.Add(generator);
}

我看不出代码有任何问题 - 这可能是 NAudio 的时间问题吗?我用谷歌搜索了这个问题,这似乎很少见,但有过类似经历的人有时会得到与多线程有关的回应——我自己没有使用任何多线程,但诚然,NAudio 中可能会发生一些事情 'under the hood' .

我也看过侧边栏中的'similar questions',它们大多不相似。 This 问题的最佳答案暗示了播种问题 - 我认为类似的事情可能是我的问题的罪魁祸首,并且理解这个概念,但我不确定如何将它应用到我的具体问题 - 我的问题是做粉红噪声是如何播种的?我真的不知道如何调试这样的错误。

我的系统是运行宁:

Windows 7 64 位

VS2013 v12.0.21005.1

NET v4.6.01055


下面是完整的 test/function 代码,如果它有助于解决问题的话:

这是(删节的)测试 class:

[TestMethod]
public void testPinkNoise()
{
    string outputFileName = @"C:\Users\Mick\Test\Output\Test.wav";
    int numberOfChannels = 1;
    int sampleRate = 1000;

    // Act

    // Problem with identical PinkNoiseGenerators occurs here -> timing issue with NAudio?

    receiverGeneratorList = scene.createPinkNoiseGeneratorLists(sampleRate, outputFileName, numberOfChannels); 
}

这是函数本身(为了记录,我知道变量名称令人困惑,而且函数通常急需重构 clarity/readability,它是曲线列表和诸如此类 - 还没想好):

public List<List<PinkNoiseGenerator>> createPinkNoiseGeneratorLists(int sampleRate, string outputFileName, int numberOfChannels)
{
    // Initialise list of lists of pink noise samples

    List<List<PinkNoiseGenerator>> receiverGeneratorList = new List<List<PinkNoiseGenerator>>();

    for (int i = 0; i < receiverList.Count; i++)
    {
        List<PinkNoiseGenerator> generatorList = new List<PinkNoiseGenerator>();

        // For every amplitude curve within the receiver, generate a corresponding pink noise curve

        for (int j = 0; j < receiverList[i].AmplitudeCurveList.Count; j++)
        {
            // Calculate duration of pink noise in seconds

            double time = receiverList[i].AmplitudeCurveList[j].Count / (double)sampleRate;

            // Instantiate new generator (list of pink noise samples) at given duration

            PinkNoiseGenerator generator = new PinkNoiseGenerator(time, sampleRate, outputFileName, numberOfChannels);

            // Add generator to generator list which will then be added to the list of lists of pink noise curves,

            generatorList.Add(generator);
        }

        // Add list of pink noise curves 

        receiverGeneratorList.Add(generatorList);
    }

    return receiverGeneratorList;
}

NAudio内部生成一个随机数发生器,以时间为种子值。当您跨过该函数时,两次 new PinkNoiseGenerator() 调用发生得如此之快以至于时间没有改变并且使用了相同的种子值。要验证这一点,请尝试在 new PinkNoiseGenerator() 调用之后调用 Thread.Sleep(1000) 并查看它是否有所不同。

如果这确实是问题所在,您可以考虑两种选择:

  1. 在代码中设置一个有意的延迟,以便 PinkNoiseGenerator 的后续构造函数调用发生在不同的时间戳中
  2. 只创建一个生成器(一个随机种子),并从中读取所有缓冲区。