public Form1() { InitializeComponent(); Part part1 = new Part(); Part part2 = new Part(); Part part3 = new Part(); Part part4 = new Part(); part1.Script = "@k 1-g 2-g 3-g 4-g 5-g 6-g 7-g 1g 2g 3G 4G 5G 6G 7G 1+G 2+g 3+g 4+g 5+g 6+g 7+g 1++g"; part2.Script = "1-g 2-g 3-g 4-g 5-g 6-g 7-g 1g 2g 3G 4G 5G 6G 7G 1+G 2+g 3+g 4+g 5+g 6+g 7+g 1++g"; part3.Script = "@0v 1-g 2-g 3-g 4-g 5-g 6-g 7-g 1g 2g 3G 4G 5G 6G 7G 1+G 2+g 3+g 4+g 5+g 6+g 7+g 1++g"; part4.Script = "@1+k 1+ 2+ 3+ 4+ 5+ 6+ 7+ A4"; Tune tune = new Tune(); //tune.Parts[0] = part1; tune.Parts[0] = part4; //tune.Parts[1] = part2; //tune.Parts[2] = part3; Compiler.CompileTune(tune, 1.0); }
public static MemoryStream CompileTune(Tune tune, double masterVolume) { int duration = 0; // equal to the longest part List <List <Beep> > parts = new List <List <Beep> >(); for (int i = 0; i < tune.Parts.Count; i++) { Part rawPart = tune.Parts[i]; if (rawPart.IsMuted || rawPart.Volume == 0) { continue; } parts.Add(CompileScript(rawPart.Script, tune.Key, masterVolume * rawPart.Volume, tune.Bpm, out int temp)); if (temp > duration) { duration = temp; } } MemoryStream stream = new MemoryStream(); using (BinaryWriter writer = new BinaryWriter(stream)) { // awesome code by Shawn Kovac // https://stackoverflow.com/questions/12611982/generate-audio-tone-to-sound-card-in-c-or-c-sharp // thank you Shawn const int formatChunkSize = 16, headerSize = 8, waveSize = 4; const short formatType = 1, tracks = 1, bitsPerSample = 16, frameSize = tracks * ((bitsPerSample + 7) / 8); int bytesPerSecond = Note.SampleRate * frameSize; int dataChunkSize = duration * frameSize; int fileSize = waveSize + headerSize + formatChunkSize + headerSize + dataChunkSize; writer.Write(0x46464952); writer.Write(fileSize); writer.Write(0x45564157); writer.Write(0x20746D66); writer.Write(formatChunkSize); writer.Write(formatType); writer.Write(tracks); writer.Write(Note.SampleRate); writer.Write(bytesPerSecond); writer.Write(frameSize); writer.Write(bitsPerSample); writer.Write(0x61746164); writer.Write(dataChunkSize); short[] buffer = new short[duration]; foreach (List <Beep> part in parts) { int i = 0; foreach (Beep beep in part) { double theta = beep.Freq * 2 * Math.PI / Note.SampleRate; double amplitude = beep.Volume * 32_767; for (int step = 0; step < beep.Duration; step++, i++) { buffer[i] += (short)(amplitude * Math.Sin(theta * step)); } Console.WriteLine($"{beep.Freq}, {beep.Duration}"); } } foreach (short sample in buffer) { writer.Write(sample); } // TODO: move these stream.Seek(0, SeekOrigin.Begin); new System.Media.SoundPlayer(stream).PlaySync(); } return(stream); }