Skip to content

Instantly share code, notes, and snippets.

@xoposhiy
Last active January 25, 2016 09:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xoposhiy/fc08d29516b7c13149b9 to your computer and use it in GitHub Desktop.
Save xoposhiy/fc08d29516b7c13149b9 to your computer and use it in GitHub Desktop.
Play C# Theme
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using NAudio.Wave;
namespace StarWarsTheme
{
public class Program
{
private static void Main()
{
var melody = new Melody()
.Add("C#/4 C#/4 C#/4")
.Add("a/8. E/16 C#/4")
.Add("a/8. E/16 C#/2")
.Add("G#/4 G#/4 G#/4")
.Add("A/8. E/16 C/4")
.Add("a/8. E/16 C#/2");
new MelodyPlayer().Octave(0)
.Tempo(2).Play(melody);
}
}
public class Note
{
private readonly int beat;
private readonly bool isLong;
private readonly string name;
public Note(string name, int beat, bool isLong)
{
this.beat = beat;
this.name = name;
this.isLong = isLong;
}
public double GetFrequency(int octave)
{
var notesLine = "c c# d d# e f f# g g# a a# b";
var notes = (notesLine + " " + notesLine.ToUpper()).Split();
var n = Array.IndexOf(notes, name);
return 27.5 * Math.Pow(2, octave + (n + 27) / 12.0);
}
public double GetLength()
{
return (isLong ? 3.0/2 : 1) / beat;
}
public override string ToString()
{
return name + "/" + beat + (isLong ? "." : "");
}
}
public class Melody
{
private readonly List<Note> notes = new List<Note>();
public IReadOnlyList<Note> Notes { get { return notes; } }
public Melody Add(string notesText)
{
notes.AddRange(
from note in notesText.Split()
let parts = note.Split('/', '.')
let name = parts[0]
let len = int.Parse(parts[1])
let isLong = note.EndsWith(".")
select new Note(name, len, isLong));
return this;
}
}
public class MelodyPlayer
{
private int octave;
private double tempo;
public MelodyPlayer Octave(int value)
{
octave = value;
return this;
}
public MelodyPlayer Tempo(double value)
{
tempo = value;
return this;
}
public void Play(Melody melody)
{
foreach (var note in melody.Notes)
{
Console.WriteLine(note);
Beep(note.GetFrequency(octave), tempo * note.GetLength());
}
}
public static void Beep(double freq, double seconds)
{
var sineWaveProvider = new SineWaveProvider32
{
Amplitude = 0.25f,
Frequency = (float) freq
};
var waveOut = new WaveOut(WaveCallbackInfo.FunctionCallback());
waveOut.Init(sineWaveProvider);
waveOut.Play();
Thread.Sleep((int) (seconds*1000));
waveOut.Stop();
waveOut.Dispose();
}
}
public class SineWaveProvider32 : WaveProvider32
{
private int sample;
public SineWaveProvider32()
{
Frequency = 1000;
Amplitude = 0.25f; // Let's not hurt our ears
}
public float Frequency { get; set; }
public float Amplitude { get; set; }
public override int Read(float[] buffer, int offset, int sampleCount)
{
var sampleRate = WaveFormat.SampleRate;
for (var n = 0; n < sampleCount; n++)
{
buffer[n + offset] = (float) (Amplitude*Math.Sin((2*Math.PI*sample*Frequency)/sampleRate));
sample++;
if (sample >= sampleRate)
sample = 0;
}
return sampleCount;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment