拙网论坛

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 213|回复: 0

Creating sine or square wave in C#

[复制链接]

949

主题

1001

帖子

3736

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3736
发表于 2018-11-27 13:55:50 | 显示全部楼层 |阅读模式
https://stackoverflow.com/questi ... are-wave-in-c-sharp

You can use NAudio and create a derived WaveStream that outputs sine or square waves which you could output to the soundcard or write to a WAV file. If you used 32-bit floating point samples you could write the values directly out of the sin function without having to scale as it already goes between -1 and 1.
As for accuracy, do you mean exactly the right frequency, or exactly the right wave shape? There is no such thing as a true square wave, and even the sine wave will likely have a few very quiet artifacts at other frequencies. If it's accuracy of frequency that matters, you are reliant on the stability and accuracy of the clock in your sound card. Having said that, I would imagine that the accuracy would be good enough for most uses.
Here's some example code that makes a 1 kHz sample at a 8 kHz sample rate and with 16 bit samples (that is, not floating point):
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));}

[url=]down vote[/url]


This lets you give frequency, duration, and amplitude, and it is 100% .NET CLR code. No external DLL's. It works by creating a WAV-formatted MemoryStream which is like creating a file in memory only, without storing it to disk. Then it plays that MemoryStream with 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)

shareimprove this answer




回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|抱朴守拙BBS

GMT+8, 2025-5-26 01:42 , Processed in 0.206513 second(s), 18 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表