Music theory: intervals in PowerShell

Musicians who aren’t programmers: my aim is at the end of this to have an app that will play an interval, ascending or descending, and ask you to identify the interval. It will run as a minimum on a Windows PC. I don’t know OSX or IOS, so it will not run on Apple. The app will also run on Windows Phone, but as I think I am the only person in the world to have one, that may not help you.  For the phone version, as I want to use it in the car, it needs voice recognition as well as Touch. This very short video on YouTube is the extent of what I have right now… it is way off the finished article as you will see, but I like to note all the steps I make on a journey.


 

While this is perfectly good for a start, it doesn’t quite fit into the random game I thought I would play in the car:

$notes = @{
    GbelowC = 196;
    A      = 220;
    Asharp = 233;
    B      = 247;
    C      = 262;
    CSharp = 277;
    D      = 294;
    DSharp = 311;
    E      = 330;
    F      = 349;
    FSharp = 370;
    G      = 392;
    GSharp = 415; 
}

[System.Console]::Beep($($notes.C), 1000)
[System.Threading.Thread]::Sleep(500)
[System.Console]::Beep($($notes.CSharp), 1000)
[System.Threading.Thread]::Sleep(500)
[System.Console]::Beep($($notes.D), 1000)
PowerShellMusic01

More work needed…
And see this MSDN post for Beep in the Framework.

http://www.phy.mtu.edu/~suits/notefreqs.html


 

So we need an array of full-on objects:

PowerShellMusic02

$newNotes = @()
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “C3”; hertz = [int] 131}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “C3Sharp”; hertz = [int] 139}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “D3”; hertz = [int] 147}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “D3Sharp”; hertz = [int] 156}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “E3”; hertz = [int] 165}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “F3”; hertz = [int] 175}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “F3Sharp”; hertz = [int] 185}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “G3”; hertz = [int] 196}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “G3Sharp”; hertz = [int] 208}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “A3”; hertz = [int] 220}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “A3Sharp”; hertz = [int] 233}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “B3”; hertz = [int] 247}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “C4”; hertz = [int] 262}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “C4Sharp”; hertz = [int] 277}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “D4”; hertz = [int] 294}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “D4Sharp”; hertz = [int] 311}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “E4”; hertz = [int] 330}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “F4”; hertz = [int] 349}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “F4Sharp”; hertz = [int] 370}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “G4”; hertz = [int] 392}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “G4Sharp”; hertz = [int] 415}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “A4”; hertz = [int] 440}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “A4Sharp”; hertz = [int] 466}
$newNotes += New-Object -TypeName PSObject -Property @{noteName = “B4”; hertz = [int] 494}
$newNotes[0]
$newNotes[-1]
$newNotes.Count
foreach ($note in $newNotes ) {
[System.Threading.Thread]::Sleep(250)
[System.Console]::Beep($($note.hertz), 1000)
}

Actually, the low quality of Console.Beep makes it unusable for this. This is much better (credit here – I could not have done the maths off the bat):

using System;
using System.Windows.Forms;
using System.IO;
using System.Media;
using System.Collections.Generic;
 
namespace WindowsFormsApplication1 {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }
 
        private void button1_Click(object sender, EventArgs e) {
            var notes = new List<int>{
                60, 131, 139, 147, 156, 165, 175, 185, 196, 208, 220, 23, 247,
                262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494 };
            foreach (var note in notes) {
                Beep.BeepBeep(1000, note, 1000);
            }
        }
    }
 
    public class Beep {
        public static void BeepBeep(int Amplitude, int Frequency, int Duration) {
            double A = ((Amplitude * (Math.Pow(2, 15))) / 1000) - 1;
            double DeltaFT = 2 * Math.PI * Frequency / 44100.0;
 
            int Samples = 441 * Duration / 10;
            int Bytes = Samples * 4;
            int[] Hdr = { 0X46464952, 36 + Bytes, 0X45564157, 0X20746D66, 16, 0X20001, 44100, 176400, 0X100004, 0X61746164, Bytes };
            using (MemoryStream MS = new MemoryStream(44 + Bytes)) {
                using (BinaryWriter BW = new BinaryWriter(MS)) {
                    for (int I = 0; I < Hdr.Length; I++) {
                        BW.Write(Hdr[I]);
                    }
                    for (int T = 0; T < Samples; T++) {
                        short Sample = System.Convert.ToInt16(A * Math.Sin(DeltaFT * T));
                        BW.Write(Sample);
                        BW.Write(Sample);
                    }
                    BW.Flush();
                    MS.Seek(0, SeekOrigin.Begin);
                    using (SoundPlayer SP = new SoundPlayer(MS)) {
                        SP.PlaySync();
                    }
                }
            }
        }
    }
 
}

PowerShellMusic03

just found this

And this video is a good primer on sound and frequency.

Advertisements