Créer une onde sinusoïdale ou carrée en C#

Comment puis-je générer un sinus audio ou une onde carrée d'une fréquence donnée?

j'espère faire cela pour calibrer l'équipement, alors quelle serait la précision de ces ondes?

20
demandé sur Peter Mortensen 2008-10-15 10:43:00

4 réponses

Vous pouvez utiliser NAudio et créer un WaveStream dérivé qui produit des ondes sinusoïdales ou carrées que vous pouvez afficher sur la carte son ou écrire sur un WAV fichier. Si vous utilisez des échantillons flottants à 32 bits, vous pouvez écrire les valeurs directement à partir de la fonction sin sans avoir à changer d'échelle car elle va déjà entre -1 et 1.

pour ce qui est de la précision, voulez-vous dire exactement la bonne fréquence, ou exactement la bonne forme d'onde? Il n'y a pas une telle chose comme un vrai onde carrée, et même l'onde sinusoïdale aura probablement quelques artefacts très silencieux à d'autres fréquences. Si c'est la précision de la fréquence qui vous sont tributaires de la stabilité et de la précision de l'horloge de votre carte son. Cela dit, j'imagine que la précision serait assez bon pour la plupart des utilisations.

voici un exemple de code qui fait un échantillon de 1 kHz à un taux d'échantillon de 8 kHz et avec des échantillons de 16 bits (c'est-à-dire, pas de point flottant):

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));
}
29
répondu Mark Heath 2014-11-27 18:01:34

cela vous permet de donner la fréquence, la durée, et l'amplitude, et c'est le code CLR 100% .NET. Pas de DLL externe. Il fonctionne en créant un WAV-formaté MemoryStream ce qui est comme créer un fichier en mémoire seulement, sans le stocker sur disque. Ensuite, il joue que MemoryStreamSystem.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)
21
répondu Edward 2013-11-04 16:53:21

Essayer Création de sinus et de l'enregistrer dans un fichier wave en 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);
}
4
répondu Aleks 2014-02-02 13:29:37

(pour quelqu'un d'autre) à l'aide de Mathnet

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

sinusoïdal

génère un tableau D'onde sinusoïdale de la longueur donnée. C'est l'équivalent de application d'une fonction sinus trigonométrique à échelle réduite à un bois de sciage périodique de l'amplitude de 2π.

s(x)=A⋅sin(2nvx+θ)

Générer.Sinusoïdal(longueur,samplingRate,de fréquence,d'amplitude,de phase,retard)

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

retourne un tableau { 0, 5.9, 9.5, 9.5, 5.9, 0, -5.9, ... }

Generate.Square(...

qui

créer une onde carrée périodique...

vous ne pouvez pas parler au sujet de la précision.

0
répondu Declan Taylor 2018-05-17 10:39:33