سؤال

كيف يمكنني توليد الصوت شرط أو مربع موجة معين التردد ؟

وأنا على أمل أن تفعل هذا لمعايرة المعدات ، فكيف الدقيق أن هذه الموجات ؟

هل كانت مفيدة؟

المحلول

ويمكنك استخدام NAudio و إنشاء WaveStream اشتقاق نواتج شرط أو مربع الموجات التي يمكن الإخراج إلى كرت الصوت أو الكتابة إلى WAV الملف. إذا كنت تستخدم عينات نقطة عائمة 32 بت يمكن أن تكتب القيم مباشرة من وظيفة الخطيئة دون الحاجة إلى التوسع لأنه غني بالفعل بين -1 و +1.

وأما بالنسبة للدقة، تقصد بالضبط التردد الصحيح، أو بالضبط حق وشكل الموجة؟ ليس هناك شيء مثل موجة مربع حقيقية، وحتى موجة جيبية من المرجح أن يكون عدد قليل من القطع الأثرية هادئة جدا على ترددات أخرى. اذا كان دقة تردد ما يهم، كنت تعتمد على استقرار ودقة على مدار الساعة في بطاقة الصوت. أما وقد قلت ذلك، وأنا أتصور أن دقة ستكون جيدة بما فيه الكفاية بالنسبة لمعظم الاستخدامات.

وإليك بعض رمز المثال الذي يجعل عينة 1 كيلو هرتز بمعدل عينة 8 كيلو هرتز ومع 16 عينة قليلا (وهذا هو، وليس النقطة العائمة):

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));
}

نصائح أخرى

وهذا يتيح لك اعطاء التردد، والمدة، والسعة، وهذا هو 100٪ كود CLR .NET. لا DLL الخارجي. وهو يعمل عن طريق خلق MemoryStream بتنسيق WAV الذي هو مثل إنشاء ملف في الذاكرة فقط، دون تخزين على القرص. بعد ذلك يلعب هذا MemoryStream مع 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)

وحاول من إنشاء شرط، وحفظ لموجة الملف في 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);
}

(على أي شخص آخر) باستخدام Mathnet

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

الجيبية

يولد موجة جيبية مجموعة من معين طول.هذا هو ما يعادل تطبيق تحجيم المثلثية جيب وظيفة الدوري مشرشف مثل سن المنشار من السعة 2π.

s(x)=A⋅الخطيئة(2nvx+θ)

تولد.الجيبية(طول ، samplingRate,تردد,السعة,يعني,المرحلة,تأخير)

هـ.ز

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

إرجاع صفيف { 0, 5.9, 9.5, 9.5, 5.9, 0, -5.9, ...}

و هناك أيضا

Generate.Square(...

والتي سوف

إنشاء الدوري موجة مربع...

لا يمكن الحديث عن الدقة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top