문제

주어진 주파수의 오디오 사인 또는 사각형 파를 어떻게 생성합니까?

장비를 교정하기 위해이 작업을 수행하기를 바라고 있습니다. 그러므로 이러한 파도는 얼마나 정확합니까?

도움이 되었습니까?

해결책

당신이 사용할 수있는 나우 디오 사운드 카드에 출력하거나 wav 파일. 32 비트 플로팅 포인트 샘플을 사용한 경우 이미 -1과 1 사이에서 스케일링하지 않고도 SIN 기능에서 직접 값을 쓸 수 있습니다.

정확도에 관해서는 정확히 올바른 주파수 또는 정확한 파동 모양을 의미합니까? 진정한 정사각형 파도와 같은 것은 없으며 사인파조차도 다른 주파수에서 매우 조용한 아티팩트가있을 것입니다. 중요한 주파수의 정확도라면 사운드 카드의 시계의 안정성과 정확성에 의존합니다. 그러나, 나는 정확도가 대부분의 용도에 충분하다고 생각할 것입니다.

다음은 8kHz 샘플 속도와 16 개의 비트 샘플 (즉, 부동 소수점이 아닌)으로 1kHz 샘플을 만드는 몇 가지 예제 코드입니다.

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% .NET CLR 코드입니다. 외부 DLL이 없습니다. WAV 형식을 만들어 작동합니다 MemoryStream 디스크에 저장하지 않고 메모리에서만 파일을 작성하는 것과 같습니다. 그런 다음 그 일을합니다 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⋅sin (2πνx+θ)

Sinusoidal (길이, 샘플링 속도, 주파수, 진폭, 평균, 위상, 지연)

예를 들어

 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