Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Add-Type -TypeDefinition @"
public enum Duration
WHOLE = 1600,
function ConvertTo-NoteFrequency {
Convert note names to MIDI note number and frequency.
This function takes a note name and will convert it to it's MIDI note number
as well as the frequency of the note. It uses the 12-tone scale and
supports both the 'regular', and the 'German' scale where 'H' is used instead of 'B'.
ConvertTo-NoteFrequency 'A#4'
ConvertTo-NoteFrequency 'b5' -UseAlternateScale
(ConvertTo-NoteFrequency 'e5').Play(200)
(ConvertTo-NoteFrequency 'e5').Play([Duration]::QUARTER)
Author: Øyvind Kallstad
Date: 14.12.2014
Version: 1.0
param (
# The name of the note.
[Parameter(Position = 0, Mandatory)]
[string] $Note,
# Default octave to append to note if none are present.
[int] $DefaultOctave = 0,
# Use this switch to use the alternate scale used in parts of northern europe where B = H.
[switch] $UseAlternateScale
# split note input into the note part and the octave part
$noteSplit = $Note -split '(\d)'
$noteName = $noteSplit[0]
[int]$octave = $noteSplit[1]
Write-Verbose "Note Name: $noteName"
# convert to lower case
$noteName = $noteName.ToLower()
# replace flats with sharps
$noteName = $noteName -replace 'db', 'c#'
$noteName = $noteName -replace 'eb', 'd#'
$noteName = $noteName -replace 'gb', 'f#'
# handle alternate scale
if($UseAlternateScale) {
$scale = @('a','a#','h','c','c#','d','d#','e','f','f#','g','g#')
$noteName = $noteName -replace 'b', 'a#'
$regexString = '^[acdefgh]#{0,1}$'
else {
$scale = @('a','a#','b','c','c#','d','d#','e','f','f#','g','g#')
$noteName = $noteName -replace 'bb', 'a#'
$regexString = '^[abcdefg]#{0,1}$'
Write-Verbose "Note Name after conversion: $noteName"
# validate note name
if (-not($noteName -match $regexString)) {
Write-Warning "'$($Note)' is not a valid note name!"
else {
# if no octave information is given, add default octave
if(-not($octave)) {
$octave = $DefaultOctave
Write-Verbose "Ocatave: $octave"
# if note is above 'c', subtract 1 to the octave - since 'c' marks the beginning of the next octave
$inputOctave = $octave
if(-not($scale[0..2] -contains $noteName)) {
if($octave -gt 0) {
Write-Verbose "Octave after conversion: $($octave)"
# find the number of half-steps up from 'A'
$halfSteps = 0
foreach ($scaleNote in $scale) {
if(-not($scaleNote -eq $noteName)) {
else {
Write-Verbose "Number of half-steps up from A: $($halfSteps)"
# we initially set the frequency of A0
# then update it with the frequency of 'A' in the same octave as the Note
$aFrequencyInNoteOctave = 27.5
$aFrequencyInNoteOctave *= (1 -shl $octave)
Write-Verbose "The frequency of 'A' in octave $($octave) is $($aFrequencyInNoteOctave)"
# calculate the note frequency
$noteFrequency = [math]::Pow([math]::Pow(2,(1/12)),$halfSteps) * $aFrequencyInNoteOctave
# calculate the MIDI note number of the note
$midiNoteNumber = [math]::Round(12 * [math]::Log(($noteFrequency/440),2)) + 69
$output = [PSCustomObject] [Ordered] @{
Input = $Note
Note = $noteName + $inputOctave
Frequency = $noteFrequency
MidiNumber = $midiNoteNumber
# add method for playing the note
$output | Add-Member -Name 'Play' -MemberType ScriptMethod -Value {param([int]$Length)[System.Console]::Beep($this.Frequency,$Length)} -Force
Write-Output $output
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment