18

重複の可能性:
C#で正弦波または方形波を作成する

音を出したい。次のようなもの:

MakeSound(frequency, duration);

または:

MakeSound(MyArrayOfSamples);

私はと呼ばれるものを見つけました:Microsoft.Directx.DirectSoundしかし、それが中止されたことを読みました。そして、Visual Studio(2010)で参照用のオプションとしてそれを見つけることができませんでした。私が読んだことによると、それが含まれているはずのこのリンクを見つけましたが、それがもうサポートされていない可能性があるため、2006年からのものを使用することを躊躇しています。そしてこれはC/C ++用だと言っています(「マネージコード」とも言っていますが)。それをマネージコードにラップする方法を理解しようとして何週間も無駄にしたくありません。私が見つけた最も有望なリンクはWaveFormatですが、それを使用する方法を見つけることができませんでした。

音波の数学的表現を取得する方法を尋ねているのではありません。また、mp3ファイルなどの再生方法も尋ねていません。また、サードパーティのソフトウェアやラッパーも探していません。非常に具体的な目的のためのC#/.netソリューションのためだけに。

4

2 に答える 2

28

いずれにせよ、アンマネージ コードを使用する場合を除き、それを再生するには WAV を作成する必要があります。ただし、以下はEric Lippert のブログのコード スニペットで、周波数を使用して独自の 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();
      }
   }
}

必要に応じて分割しますが、aNatural変数に注意してください-それは周波数です-探しているものと同じです。

これを に配置して、必要MemoryStreamに応じて再生SoundPlayerできます。

于 2012-12-26T15:40:53.810 に答える
16

これは、カーネル内の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.");
    }
}

私のWin10ボックスでは、期間(最後のパラメーター)をここの5ミリ秒よりもはるかに大きく、最大50ミリ秒に設定する必要がありますが、合理的なものを得るには100ミリ秒にする必要があります。

または、簡単な方法を使用する場合は、Console.Beep(Int32, Int32)メソッドを使用します。そのメソッドは .Net 2.0 で導入されました。

于 2012-12-26T15:44:07.820 に答える