c# - XNA动态音频的C#环绕弧度角

标签 c# audio xna trigonometry sampling

编辑2 +回答

原来我需要在0Frequency*2*Math.pi之间换行。

发布的每个人都为弄清这个问题做出了贡献。由于客人的声誉最低,所以我只把他的帖子标记为答案。非常感谢大家,这让我发疯了!

编辑1

这是我的WrapValue方法,应该考虑在此之前发布。它不像克里斯·泰勒(Chris Taylor)那样复杂,但对我的影响相同。

public static double WrapValue(double value, double min, double max)
{
    if (value > max)
        return (value - max) + min;
    if (value < min)
        return max - (min - value);
    return value;
}

这可能适用于Gamedev,但它在游戏上少一些,在代码和数学上少一些,因此我将其放在这里。

我正在尝试使用新的XNA 4.0 DynamicSoundEffectInstance类将Xbox转变为数字乐器,并且每秒获得一次单击。我确定这是由于尝试将域值包装在0到2 * pi之间引起的。

我编写了一个名为SineGenerator的小类,该类仅维护DynamicSoundEffectInstance并将其提供给Math.Sin()生成的样本缓冲区。

由于我想保持精确并使用44.1或48k采样率,因此我保留了double x(我向Math.Sin()馈入的 Angular )和double step(其中step2 * Math.PI / SAMPLING_FREQUENCY)。每次为DynamicSoundEffectInstance.SubmitBuffer()生成数据时,我都会按x递增step并将sin(frequency * x)添加到我的样本缓冲区(由于XNA仅支持16位样本深度,因此被截断为short)。

我认为我最好将 Angular 包裹在0到2 * pi之间,以便在x变大时不要降低精度。但是,这样做会引入点击。我写了自己的double WrapValue(double val, double min, double max)方法,以防MathHelper.WrapAngle()陷入困境。 Math.PI和-Math.PI之间的换行以及0和2 * Math.PI之间的换行都不会消除单击。但是,如果我不花心去包装值,而只是让它增长,点击就消失了。

我在想它与.NET trig函数的准确性有关,即sin(0)!= sin(2 * pi)的准确性如何,但是我不知道该如何判断。

我的问题:为什么会发生这种情况,我是否还要打扰一下 Angular ?

编码:
using System;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework;

namespace TestDynAudio
{
    class SineGenerator
    {
  // Sample rate and sample depth variables
  private const int BUFFER_SAMPLE_CAPACITY = 1024;
  private const int BIT_RATE = 16;
  private const int SAMPLING_FREQUENCY = 48000;
  private readonly int BYTES_PER_SAMPLE;
  private readonly int SAMPLE_BUFFER_SIZE;

        private DynamicSoundEffectInstance dynSound = new DynamicSoundEffectInstance(SAMPLING_FREQUENCY, AudioChannels.Mono);
  private double x = 0; // The domain or angle value
  private double step;  // 48k / 2pi, increment x by this for each sample generated
  private byte[] sampleData; // The sample buffer
  private double volume = 1.0f; // Volume scale value

  // Property for volume
  public double Volume
  {
   get { return volume; }
   set { if (value <= 1.0 && value >= 0.0) volume = value; }
  }

  // Property for frequency
  public double Frequency { get; set; }

        public SineGenerator()
        {
   Frequency = 440; // Default pitch set to A above middle C
   step = Math.PI * 2 / SAMPLING_FREQUENCY;
   BYTES_PER_SAMPLE = BIT_RATE / 8;
   SAMPLE_BUFFER_SIZE = BUFFER_SAMPLE_CAPACITY * BYTES_PER_SAMPLE;
   sampleData = new byte[SAMPLE_BUFFER_SIZE];

   // Use the pull-method, DynamicSoundEffectInstance will
   // raise an event when more samples are needed
   dynSound.BufferNeeded += GenerateAudioData;
        }

  private void buildSampleData()
  {
   // Generate a sample with sin(frequency * domain),
   //   Convert the sample from a double to a short,
   //   Then write the bytes to the sample buffer
   for (int i = 0; i < BUFFER_SAMPLE_CAPACITY; i++)
   {
    BitConverter.GetBytes((short)((Math.Sin(Frequency * x) * (double)short.MaxValue) * volume)).CopyTo(sampleData, i * 2);

    // Simple value wrapper method that takes into account the
    // different between the min/max and the passed value
    x = MichaelMath.WrapValue(x + step, 0, 2f * (Single)Math.PI);
   }
  }

  // Delegate for DynamicSoundInstance, generates samples then submits them
  public void GenerateAudioData(Object sender, EventArgs args)
  {
   buildSampleData();
   dynSound.SubmitBuffer(sampleData);
  }

  // Preloads a 3 sample buffers then plays the DynamicSoundInstance
  public void play()
  {
   for (int i = 0; i < 3; i++)
   {
    buildSampleData();
    dynSound.SubmitBuffer(sampleData);
   }
   dynSound.Play();
  }

  public void stop()
  {
   dynSound.Stop();
  }
    }
}

最佳答案

我想您的Wrap函数可以正常工作,但是您没有采用Sine(x),而是采用Sine(Frequency * x)-如果Frequency * x的乘积不是2 * PI的整数倍,那么您会得到。尝试包装Frequency * x摆脱流行音乐。

关于c# - XNA动态音频的C#环绕弧度角,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4553708/

相关文章:

c# - 当列表包含 x,y,z 时,为什么 list.Contains(x) 找不到 x

android - "Missed SL_PLAYEVENT_HEADATNEWPOS for position"消息

javascript - Rails 将 js 加载资源与实际路径混淆,并将其处理为 Controller 操作

c# - 旋转方 block 的 6 个面

c# - XNA 3D 碰撞矩阵不起作用

c# - 将无向图转换为网格

c# - 遍历 .json 文件中的每个项目

c# - 关于类中字符串的 Getter 或 Const 的设计建议 - 其他人在做什么?

java - URL代码求助请短代码(新手Java程序员)

c# - XNA/Mono 效果抛出运行时转换异常