如何根据频率生成声音?

isp*_*iro 13 .net c# audio

可能重复:
在C#中创建正弦波或方波

我想生成声音.要么像:

MakeSound(frequency, duration);
Run Code Online (Sandbox Code Playgroud)

要么:

MakeSound(MyArrayOfSamples);
Run Code Online (Sandbox Code Playgroud)

我找到了一些叫做的东西:Microsoft.Directx.DirectSound但是已经知道它已经停止了.我无法在Visual Studio(2010)中找到它作为参考的选项.根据我读过的内容,我发现这个链接应该包括它,但是因为它可能不再受支持而犹豫是否使用2006年的东西.而这一次说,这是C/C++(尽管也说:"托管代码"),我不想浪费几周试图了解如何来包装成托管代码,只是为了找出我不能这样做.我发现最有希望的链接是WaveFormat,但我找不到如何使用它.

不是在问如何获得声波的数学表示.我也不会问如何播放mp3文件等.我也不是在寻找第三方软件或包装器.仅针对特定目标的C#/ .net解决方案.

Mik*_*oud 19

无论哪种方式,你看它,除非你想使用非托管代码,你将不得不建立一个WAV播放.然而,下面是从代码片段埃里克利珀的博客会告诉你如何使用频率推出自己的WAV文件.

namespace Wave
{
   using System;
   using System.IO;
   class MainClass {
      public static void Main() {
         FileStream stream = new FileStream("test.wav", FileMode.Create);
         BinaryWriter writer = new BinaryWriter(stream);
         int RIFF = 0x46464952;
         int WAVE = 0x45564157;
         int formatChunkSize = 16;
         int headerSize = 8;
         int format = 0x20746D66;
         short formatType = 1;
         short tracks = 1;
         int samplesPerSecond = 44100;
         short bitsPerSample = 16;
         short frameSize = (short)(tracks * ((bitsPerSample + 7)/8));
         int bytesPerSecond = samplesPerSecond * frameSize;
         int waveSize = 4;
         int data = 0x61746164;
         int samples = 88200 * 4;
         int dataChunkSize = samples * frameSize;
         int fileSize = waveSize + headerSize + formatChunkSize + headerSize + dataChunkSize;
         writer.Write(RIFF);
         writer.Write(fileSize);
         writer.Write(WAVE);
         writer.Write(format);
         writer.Write(formatChunkSize);
         writer.Write(formatType);
         writer.Write(tracks); 
         writer.Write(samplesPerSecond);
         writer.Write(bytesPerSecond);
         writer.Write(frameSize);
         writer.Write(bitsPerSample); 
         writer.Write(data);
         writer.Write(dataChunkSize);
         double aNatural = 220.0;
         double ampl = 10000;
         double perfect = 1.5;
         double concert = 1.498307077;
         double freq = aNatural * perfect;
         for (int i = 0; i < samples / 4; i++) {
            double t = (double)i / (double)samplesPerSecond;
            short s = (short)(ampl * (Math.Sin(t * freq * 2.0 * Math.PI)));
            writer.Write(s);
         }
         freq = aNatural * concert;
         for (int i = 0; i < samples / 4; i++) {
            double t = (double)i / (double)samplesPerSecond;
            short s = (short)(ampl * (Math.Sin(t * freq * 2.0 * Math.PI)));
            writer.Write(s);
         }
         for (int i = 0; i < samples / 4; i++) {
            double t = (double)i / (double)samplesPerSecond;
            short s = (short)(ampl * (Math.Sin(t * freq * 2.0 * Math.PI) + Math.Sin(t * freq * perfect * 2.0 * Math.PI)));
            writer.Write(s);
         }
         for (int i = 0; i < samples / 4; i++) {
            double t = (double)i / (double)samplesPerSecond;
            short s = (short)(ampl * (Math.Sin(t * freq * 2.0 * Math.PI) + Math.Sin(t * freq * concert * 2.0 * Math.PI)));
            writer.Write(s);
         }
         writer.Close();
         stream.Close();
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

根据您的需要将其分开,但请注意aNatural变量 - 这是一个频率 - 就像您正在寻找的那样.

现在,您可以将其放入a中MemoryStream,然后根据需要进行播放SoundPlayer.

  • @ispiro,我提供的代码是一个`raw`.net解决方案,可以完全满足您的需求.***此外,***`DirectSound`**将**使用非托管代码与*声卡*和任何其他低级设备通信.我会说用上述代码滚动一个简单的WAV文件将产生你想要的结果,没有开销,也没有你需要担心的依赖. (2认同)

ren*_*ene 10

这是内核中Beep函数的包装器,包含持续时间和频率.现在Beep使用声卡; 在我的日子里,它使用了一些粘在主板上的压电设备.

using System;
using System.Runtime.InteropServices;

class BeepSample
{
    [DllImport("kernel32.dll", SetLastError=true)]
    static extern bool Beep(uint dwFreq, uint dwDuration);

    static void Main()
    {
        Console.WriteLine("Testing PC speaker...");
        for (uint i = 100; i <= 20000; i++)
        {
            Beep(i, 5);
        }
        Console.WriteLine("Testing complete.");
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的Win10盒子上,我需要将持续时间(最后一个参数)设置为远大于此处的5毫秒,更长达50毫秒但是为了得到合理的东西,我必须使其达到100毫秒.

或者,如果您想采用简单的路线,请使用Console.Beep(Int32,Int32)方法.该方法是在.Net 2.0中引入的.

  • @KvanTTT你可以用证据支持这种说法吗?Msdn说它从win xp x64和vista一起被删除(x86和x64),但在Windows 7中使用默认声卡完全重新实现.我松散地引用了该功能的实现者,[Larry Osterman](http://blogs.msdn.com/b/larryosterman/archive/2010/01/04/what-s-up-with-the-beep-driver-在窗口,7.aspx) (3认同)
  • 我刚刚在win7 x64上验证了它,这确实像宣传的那样工作.我想我必须赞成Larry Osterman. (3认同)

归档时间:

查看次数:

26734 次

最近记录:

9 年,5 月 前