Frage

Wie erzeugte ich eine Audio -Sinus oder eine quadratische Welle einer bestimmten Frequenz?

Ich hoffe, dass ich dies tun kann, um die Geräte zu kalibrieren. Wie präzise wären diese Wellen?

War es hilfreich?

Lösung

Sie können verwenden Naudio und erstellen Sie einen abgeleiteten WaveTream, der Sinus- oder Quadratwellen ausgibt, die Sie an der Soundkarte ausgeben oder an a schreiben können Wave Datei. Wenn Sie 32 -Bit -schwimmende Punktproben verwendet haben, können Sie die Werte direkt aus der Sin -Funktion herausschreiben, ohne dass sie sich skalieren lassen, da sie bereits zwischen -1 und 1 liegt.

Meinst du genau die richtige Frequenz oder genau die richtige Wellenform? Es gibt keine echte Quadratwelle, und selbst die Sinuswelle wird wahrscheinlich einige sehr ruhige Artefakte bei anderen Frequenzen haben. Wenn es sich um die Genauigkeit der Frequenz handelt, sind Sie auf die Stabilität und Genauigkeit der Uhr in Ihrer Soundkarte angewiesen. Trotzdem würde ich mir vorstellen, dass die Genauigkeit für die meisten Verwendungen gut genug wäre.

Hier ist ein Beispielcode, der eine 1 -kHz -Probe mit einer Stichprobenrate von 8 kHz und mit 16 Bit -Proben (dh nicht schwimmender Punkt) erstellt:

int sampleRate = 8000;
short[] buffer = new short[8000];
double amplitude = 0.25 * short.MaxValue;
double frequency = 1000;
for (int n = 0; n < buffer.Length; n++)
{
    buffer[n] = (short)(amplitude * Math.Sin((2 * Math.PI * n * frequency) / sampleRate));
}

Andere Tipps

Auf diese Weise ermöglichen Sie Häufigkeit, Dauer und Amplitude, und es ist 100% .NET CLR -Code. Keine externen DLLs. Es funktioniert, indem es ein WAV-formatiert erstellt MemoryStream Dies ist wie das Erstellen einer Datei nur im Speicher, ohne sie auf Festplatte zu speichern. Dann spielt es das MemoryStream mit System.Media.SoundPlayer.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;

public static void PlayBeep(UInt16 frequency, int msDuration, UInt16 volume = 16383)
{
    var mStrm = new MemoryStream();
    BinaryWriter writer = new BinaryWriter(mStrm);

    const double TAU = 2 * Math.PI;
    int formatChunkSize = 16;
    int headerSize = 8;
    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 samples = (int)((decimal)samplesPerSecond * msDuration / 1000);
    int dataChunkSize = samples * frameSize;
    int fileSize = waveSize + headerSize + formatChunkSize + headerSize + dataChunkSize;
    // var encoding = new System.Text.UTF8Encoding();
    writer.Write(0x46464952); // = encoding.GetBytes("RIFF")
    writer.Write(fileSize);
    writer.Write(0x45564157); // = encoding.GetBytes("WAVE")
    writer.Write(0x20746D66); // = encoding.GetBytes("fmt ")
    writer.Write(formatChunkSize);
    writer.Write(formatType);
    writer.Write(tracks);
    writer.Write(samplesPerSecond);
    writer.Write(bytesPerSecond);
    writer.Write(frameSize);
    writer.Write(bitsPerSample);
    writer.Write(0x61746164); // = encoding.GetBytes("data")
    writer.Write(dataChunkSize);
    {
        double theta = frequency * TAU / (double)samplesPerSecond;
        // 'volume' is UInt16 with range 0 thru Uint16.MaxValue ( = 65 535)
        // we need 'amp' to have the range of 0 thru Int16.MaxValue ( = 32 767)
        double amp = volume >> 2; // so we simply set amp = volume / 2
        for (int step = 0; step < samples; step++)
        {
            short s = (short)(amp * Math.Sin(theta * (double)step));
            writer.Write(s);
        }
    }

    mStrm.Seek(0, SeekOrigin.Begin);
    new System.Media.SoundPlayer(mStrm).Play();
    writer.Close();
    mStrm.Close();
} // public static void PlayBeep(UInt16 frequency, int msDuration, UInt16 volume = 16383)

Versuchen Sie Erstellen von Sinus und Speichern in Wellendatei in C#

private void TestSine()
{
    IntPtr format;
    byte[] data;
    GetSineWave(1000, 100, 44100, -1, out format, out data);
    WaveWriter ww = new WaveWriter(File.Create(@"d:\work\sine.wav"),
        AudioCompressionManager.FormatBytes(format));
    ww.WriteData(data);
    ww.Close();
}

private void GetSineWave(double freq, int durationMs, int sampleRate, short decibel, out IntPtr format, out byte[] data)
{
    short max = dB2Short(decibel);//short.MaxValue
    double fs = sampleRate; // sample freq
    int len = sampleRate * durationMs / 1000;
    short[] data16Bit = new short[len];
    for (int i = 0; i < len; i++)
    {
        double t = (double)i / fs; // current time
        data16Bit[i] = (short)(Math.Sin(2 * Math.PI * t * freq) * max);
    }
    IntPtr format1 = AudioCompressionManager.GetPcmFormat(1, 16, (int)fs);
    byte[] data1 = new byte[data16Bit.Length * 2];
    Buffer.BlockCopy(data16Bit, 0, data1, 0, data1.Length);
    format = format1;
    data = data1;
}

private static short dB2Short(double dB)
{
    double times = Math.Pow(10, dB / 10);
    return (short)(short.MaxValue * times);
}

(für alle anderen) verwenden Mathnet

https://numerics.mathdotnet.com/generate.html

Sinusförmig

Erzeugt ein Sinus -Wellenarray der angegebenen Länge. Dies entspricht der Anwendung einer skalierten trigonometrischen Sinusfunktion auf eine periodische Sägezahn -Amplitude 2π.

s (x) = a · sin (2πνx+θ)

Erzeugen.sinusoidal (Länge, Probenahme, Frequenz, Amplitude, Mittelwert, Phase, Verzögerung)

z.B

 Generate.Sinusoidal(15, 1000.0, 100.0, 10.0);

Gibt Array {0, 5.9, 9,5, 9,5, 5,9, 0, -5,9, ...} zurück

Und da gibt es auch

Generate.Square(...

welches wird

Erstellen Sie eine periodische Quadratwelle ...

kann nicht über Präzision sprechen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top