Twinkle Twinkle Little Star
QBasic (56)
A$="CCGGAAG2FFEEDDC2"
B$="GGFFEED2"
PLAY "L4"+A$+B$+B$+A$
Focus is on reminiscence :)
(Don't have a QBasic to test this though)
JavaScript (214 212 211 characters)
Open Safari, Opera, or Google Chrome to JavaScript Shell, then enter the code below:
for(s="",y=192e3;x=--y/4e3|0;)s+="~ "[(y%4e3>800|x%8==1)&Math.pow(2,"024579702457245702457970"[x>>1]/12)*y/31%2];open("data:audio/wav;base64,UklGRiXuAgBXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQHuAgCA"+btoa(s))
Unminified for readability (even then it may be hard to understand):
for(s = "", y = 192E3; x = --y / 4E3 | 0;) {
s += "~ "[(y % 4E3 > 800 | x % 8 == 1) & Math.pow(2, "024579702457245702457970"[x >> 1] / 12) * y / 31 % 2];
}
open("data:audio/wav;base64,UklGRiXuAgBXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQHuAgCA" + btoa(s));
With several more characters, it could work on Firefox as well, but you can change the audio/wav
part to at least save the WAV file.
C# (Length: LOL)
So, what I did here was implement support for generating a .wav file from the string used for the QBasic solution in C# (single octave, no accidentals). Emphasis was on:
- Avoiding
unsafe
code blocks - Not wasting too much of my time doing it
- Making it relatively simple to extend
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.IO;
namespace ConsoleApplication1
{
public static class Extension
{
public static byte[] ToByteArray(this object o)
{
return o.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
.SelectMany(x =>
{
var value = x.GetValue(o, null);
if (value.GetType().Equals(typeof (UInt16)))
{
return BitConverter.GetBytes((UInt16) value);
}
if (value.GetType().Equals(typeof (UInt32)))
{
return BitConverter.GetBytes((UInt32) value);
}
if (value.GetType().Equals(typeof(char[])))
{
return ((char[]) value).Select(y => Convert.ToByte(y));
}
if (value.GetType().Equals(typeof(byte[])))
{
return (byte[]) value;
}
throw new NotImplementedException();
}).ToArray();
}
}
public class Wave
{
public readonly byte[] WavFile;
public Wave(string notes)
{
var header = new Header();
var data = new List<Chunk>();
var f = new Fmt(8000);
data.Add(f);
data.Add(new WavData(notes, f));
var thefile = data.SelectMany(x => x.ToByteArray()).ToArray();
header.Size = (uint)thefile.Length + 4;
WavFile = header.ToByteArray().Concat(thefile).ToArray();
}
class WavData: Chunk
{
private static IEnumerable<byte> RenderNote(string note, int length, Fmt fmt)
{
double frequency;
switch (note)
{
case "A":
frequency = 440;
break;
case "B":
frequency = 493.883;
break;
case "C":
frequency = 261.626;
break;
case "D":
frequency = 293.665;
break;
case "E":
frequency = 329.628;
break;
case "F":
frequency = 349.228;
break;
case "G":
frequency = 391.995;
break;
default:
throw new NotImplementedException("Unsupported Note");
}
var result = new byte[fmt.SampleRate / length * 2]; // For 120BPM tempo
for (int i = 0; i < result.Length; i++)
{
double time = (i % fmt.SampleRate) / (double)fmt.SampleRate;
double position = time * frequency;
if (result.Length - i <= fmt.SampleRate / 16)
result[i] = 127;
else
result[i] = (byte)Math.Round((Math.Sin(position * 2 * Math.PI) + 1) * 127);
}
return result;
}
public WavData(string notes, Fmt fmt)
{
Samples = new byte[0];
foreach (var note in Regex.Matches(notes, @"[A-G][1|2|4|8]?").OfType<Match>().Select(x => x.Value))
{
Samples = Samples.Concat(RenderNote(note[0] + "", note.Length > 1 ? note[1] - '0' : 4, fmt)).ToArray();
}
}
public override char[] Id
{
get { return "data".ToCharArray(); }
}
public override uint DataSize
{
get { return (uint)Samples.Length; }
}
public byte[] Samples { get; private set; }
}
class Fmt : Chunk
{
public Fmt(UInt32 sampleRate)
{
CompressionCode = 1; // Unknown/PCM
Channels = 1;
SampleRate = sampleRate;
SignificantBits = 8;
}
public override char[] Id
{
get { return "fmt ".ToCharArray();}
}
public override uint DataSize
{
get { return 16; }
}
public UInt16 CompressionCode { get; private set; }
public UInt16 Channels { get; private set; }
public UInt32 SampleRate { get; private set; }
public UInt32 AvgBytesPerSecond { get { return SampleRate*BlockAlign; } }
public UInt16 BlockAlign { get { return (UInt16) (SignificantBits/8*Channels); } }
public UInt16 SignificantBits { get; private set; }
}
class Header
{
public Header()
{
Type = "RIFF".ToCharArray();
RiffType = "WAVE".ToCharArray();
Size = 0;
}
public char[] Type { get; private set; }
public UInt32 Size { get; set; }
public char[] RiffType { get; private set; }
}
abstract class Chunk
{
public abstract char[] Id { get; }
public abstract UInt32 DataSize { get; }
}
}
class Program
{
public static void Main(string[] args)
{
var p1 = "CCGGAAG2";
var p2 = "FFEEDDC2";
var p3 = "GGFFEED2";
var w = new Wave(p1+p2+p3+p3+p1+p2);
using (var f = new FileStream("testfile.wav", FileMode.Create))
f.Write(w.WavFile, 0, w.WavFile.Length);
}
}
}