Skip to content

Instantly share code, notes, and snippets.

@nramsbottom
Created July 25, 2019 11:47
Show Gist options
  • Save nramsbottom/0f434782ab2d6cecbfaf61a3590a1bf2 to your computer and use it in GitHub Desktop.
Save nramsbottom/0f434782ab2d6cecbfaf61a3590a1bf2 to your computer and use it in GitHub Desktop.
Generate Audio Tone
using System;
using System.IO;
namespace GenerateTone
{
class Program
{
static void Main(string[] args)
{
// generate one second of 1khz audio
using (var fs = File.Create("output.wav"))
{
const int SampleRate = 8000;
const int BitsPerSample = 16;
const int NumChannels = 1;
short[] samples = new short[SampleRate];
double amplitude = 0.25 * short.MaxValue;
double frequency = 1000; // hz
for (int n = 0; n < SampleRate; n++)
{
samples[n] = (short)(amplitude * Math.Sin((2 * Math.PI * n * frequency) / SampleRate));
}
WriteRiffHeader(fs, NumChannels, BitsPerSample, SampleRate);
for (int n = 0; n < SampleRate; n++)
{
WriteByte(fs, samples[n]);
}
}
}
static void WriteRiffHeader(Stream stream, int numChannels, int bitsPerSample, int sampleRate)
{
// http://soundfile.sapp.org/doc/WaveFormat/
WriteBigEndian(stream, 0x52494646); // ChunkID: RIFF
WriteLittleEndian(stream, 26 + 8000 * (uint)numChannels * (uint)sampleRate / 8); // ChunkSize // TODO: We have to know the length of the data we'll be generating
WriteBigEndian(stream, 0x57415645); // Format: WAVE
WriteBigEndian(stream, 0x666d7420); // SubChunk1ID: fmt
WriteLittleEndian(stream, 16); // SubChunk1Size // note that this is the length of the rest of this subchunk header
WriteLittleEndian(stream, (uint)numChannels); // NumChannels
WriteLittleEndian(stream, (uint)sampleRate); // SampleRate
WriteLittleEndian(stream, (uint)sampleRate * (uint)numChannels * (uint)bitsPerSample / 8); // ByteRate
WriteLittleEndian(stream, (uint)numChannels * (uint)bitsPerSample / 8); // BlockAlign
WriteLittleEndian(stream, (uint)bitsPerSample); // BitsPerSample
WriteBigEndian(stream, 0x64617461); // SubChunk2ID: data
WriteLittleEndian(stream, 8000 * (uint)numChannels * (uint)bitsPerSample / 8); // SubChunk2Size // TODO
}
static void WriteBigEndian(Stream stream, uint value)
{
if (BitConverter.IsLittleEndian)
{
stream.WriteByte((byte)(value >> 24));
stream.WriteByte((byte)(value >> 16));
stream.WriteByte((byte)(value >> 8));
stream.WriteByte((byte)value);
}
else
throw new NotImplementedException("big endian");
}
static void WriteLittleEndian(Stream stream, uint value)
{
if (BitConverter.IsLittleEndian)
{
stream.WriteByte((byte)value);
stream.WriteByte((byte)(value >> 8));
stream.WriteByte((byte)(value >> 16));
stream.WriteByte((byte)(value >> 24));
}
else
throw new NotImplementedException("big endian");
}
static void WriteByte(Stream stream, short value)
{
if (BitConverter.IsLittleEndian)
{
stream.WriteByte((byte)(value >> 8));
stream.WriteByte((byte)value);
}
else
{
stream.WriteByte((byte)value);
stream.WriteByte((byte)(value << 8));
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment