Microsoft Small Basic

Program Listing: JCC750
' Chord Wave Form 0.1
' Copyright (c) 2014 Nonki Takahashi. All rights reserved.
'
' History
' 0.1 2014-01-11 Created. (TDT768)
'
gw = 598
gh = 428
title = "Chord Wave Form 0.1"
GraphicsWindow.Title = title
GraphicsWindow.Width = gw
GraphicsWindow.Height = gh
GraphicsWindow.BackgroundColor = "Black"
GraphicsWindow.BrushColor = "SteelBlue"
r = 150
x0 = gw / 2 - r / 2 + 20
y0 = gh / 2
param["x"] = x0 - 1.25 * r
param["y"] = y0 - 1.25 * r
param["width"] = r * 2.5
param["height"] = r * 2.5
param["border-radius"] = r * 0.1
FillRoundRectangle()
DrawGrid()
GraphicsWindow.FontSize = 20
GraphicsWindow.BrushColor = "White"
oChord = Shapes.AddText("")
Shapes.Move(oChord, param["x"] + param["width"] + 20, param["y"])
InitChord()
n = Array.GetItemCount(chord)
index = Array.GetAllIndices(chord)
nj = Array.GetItemCount(incr)
ij = Array.GetAllIndices(incr)
base = "C"
While "True"
For i = 1 To n
If index[i] = "_" Then
name = base
Else
name = base + index[i]
EndIf
PlayChord()
DrawChord()
Program.Delay(4000)
GraphicsWindow.BrushColor = "SteelBlue"
FillRoundRectangle()
DrawGrid()
EndFor
EndWhile
Sub DrawChord
Shapes.SetText(oChord, name)
GraphicsWindow.PenColor = "MediumAquamarine"
For t = 0 To 1 Step 1 / (4 * r)
x2 = x0 - r + (2 * r) * t
a = 0
For is = 1 To ns
a = a + Math.Sin(2 * Math.Pi * t * fs[is])
EndFor
y2 = y0 + r * a / ns
If 0 < t Then
GraphicsWindow.DrawLine(x1, y1, x2, y2)
EndIf
x1 = x2
y1 = y2
EndFor
EndSub
Sub PlayChord
incrs = chord[index[i]]
b1 = Text.GetSubText(base, 1, 1)
b2 = Text.GetSubText(base, 2, 1)
s = Text.GetIndexOf(chord, b1)
If b2 = "#" Or b2 = "+" Then
s = s + 1
ElseIf b2 = "b" Or b2 = "-" Then
s = s - 1
EndIf
GetScale()
fs = ""
ns = 1
fs[ns] = f[s + 1]
mml = "L16O3" + retval
While incrs <> ""
For j = 1 To nj
If Text.StartsWith(incrs, incr[ij[j]]) Then
s = s + ij[j]
GetScale()
ns = ns + 1
fs[ns] = f[s + 1]
mml = mml + retval
incrs = Text.GetSubTextToEnd(incrs, 4)
Goto found
EndIf
EndFor
found:
EndWhile
Sound.PlayMusic(mml)
EndSub
Sub GetScale
' param s - index for scale (0 origin)
_i = s + 1 ' 1 origin
retval = ""
If 12 < _i Then
_i = _i - 12
retval = "O4"
EndIf
_s = Text.GetSubText(scale, _i, 1)
If _s = "#" Then
_s = Text.GetSubText(scale, _i - 1, 2)
EndIf
retval = retval + _s
EndSub
Sub InitChord
scale = "C#D#EF#G#A#B"
incr = "2=M2;3=m3;4=M3;5=P4;"
chord["_"] = "M3,m3" ' major
chord["m"] = "m3,M3" ' minor
chord["aug"] = "M3,M3" ' augument
chord["dim"] = "m3,m3" ' diminish
chord["7"] = "M3,m3,m3" ' dominant seventh
chord["maj7"] = "M3,m3,M3" ' major seventh
chord["m7"] = "m3,M3,m3" ' minor seventh
chord["dim7"] = "m3,m3,m3" ' diminish seventh
chord["sus4"] = "P4,M2" ' suspended fourth
chord["7sus4"] = "P4,M2,m3" ' seventhe suspended fourth
chord["9"] = "M3,m3,m3,M3" ' dominant ninth
chord["m9"] = "m3,M3,m3,M3" ' minor ninth
For s = 1 To Text.GetLength(scale) * 2
f[s] = 220 * Math.Power(2, (s - 10) / 12)
EndFor
EndSub
Sub DrawGrid
GraphicsWindow.PenWidth = 1
GraphicsWindow.PenColor = "Black"
For y = y0 - (r / 2) * 2 To y0 + (r / 2) * 2 Step r / 2
GraphicsWindow.DrawLine(40, y 490, y)
EndFor
For x = x0 - (r / 2) * 2 To x0 + (r / 2) * 2 Step r / 2
GraphicsWindow.DrawLine(x, 20, x, 460)
EndFor
EndSub
Sub DrawRoundRectangle
Stack.PushValue("local", param)
Stack.PushValue("local", local)
local = param
param = ""
param["r"] = local["border-radius"]
If (local["width"] / 2 < param["r"]) Or (local["height"] / 2 < param["r"]) Then
param["r"] = Math.Min(local["width"] / 2, local["height"] / 2)
EndIf
param["da"] = 5
param["x"] = local["x"] + param["r"]
param["y"] = local["y"] + param["r"]
param["a1"] = 180
param["a2"] = 270
DrawArc()
GraphicsWindow.DrawLine(local["x"] + param["r"], local["y"], local["x"] + local["width"] - param["r"], local["y"])
param["x"] = local["x"] + local["width"] - param["r"]
param["y"] = local["y"] + param["r"]
param["a1"] = 270
param["a2"] = 360
DrawArc()
GraphicsWindow.DrawLine(local["x"] + local["width"], local["y"] + param["r"], local["x"] + local["width"], local["y"] + local["height"] - param["r"])
param["x"] = local["x"] + local["width"] - param["r"]
param["y"] = local["y"] + local["height"] - param["r"]
param["a1"] = 0
param["a2"] = 90
DrawArc()
GraphicsWindow.DrawLine(local["x"] + param["r"], local["y"] + local["height"], local["x"] + local["width"] - param["r"], local["y"] + local["height"])
param["x"] = local["x"] + param["r"]
param["y"] = local["y"] + local["height"] - param["r"]
param["a1"] = 90
param["a2"] = 180
DrawArc()
GraphicsWindow.DrawLine(local["x"], local["y"] + param["r"], local["x"], local["y"] + local["height"] - param["r"])
local = Stack.PopValue("local")
param = Stack.PopValue("local")
EndSub
Sub FillRoundRectangle
Stack.PushValue("local", param)
If (param["width"] / 2 < param["border-radius"]) Or (param["height"] / 2 < param["border-radius"]) Then
param["border-radius"] = Math.Min(param["width"] / 2, param["height"] / 2)
EndIf
GraphicsWindow.FillEllipse(param["x"], param["y"], param["border-radius"] * 2, param["border-radius"] * 2)
GraphicsWindow.FillRectangle(param["x"] + param["border-radius"], param["y"], param["width"] - param["border-radius"] * 2, param["height"])
GraphicsWindow.FillEllipse(param["x"] + param["width"] - param["border-radius"] * 2, param["y"], param["border-radius"] * 2, param["border-radius"] * 2)
GraphicsWindow.FillRectangle(param["x"], param["y"] + param["border-radius"], param["width"], param["height"] - param["border-radius"] * 2)
GraphicsWindow.FillEllipse(param["x"], param["y"] + param["height"] - param["border-radius"] * 2, param["border-radius"] * 2, param["border-radius"] * 2)
GraphicsWindow.FillEllipse(param["x"] + param["width"] - param["border-radius"] * 2, param["y"] + param["height"] - param["border-radius"] * 2, param["border-radius"] * 2, param["border-radius"] * 2)
param = Stack.PopValue("local")
EndSub
Sub DrawArc
Stack.PushValue("local", param)
Stack.PushValue("local", local)
Stack.PushValue("local", a)
local = param
param = ""
local["pw"] = GraphicsWindow.PenWidth
local["pc"] = GraphicsWindow.PenColor
local["bc"] = GraphicsWindow.BrushColor
GraphicsWindow.BrushColor = local["pc"]
local["r1"] = local["r"] - local["pw"] / 2
local["r2"] = local["r"] + local["pw"] / 2
For a = local["a1"] To local["a2"] Step local["da"]
local["rad"] = Math.GetRadians(a)
param["x1"] = local["x"] + local["r1"] * Math.Cos(local["rad"])
param["y1"] = local["y"] + local["r1"] * Math.Sin(local["rad"])
param["x2"] = local["x"] + local["r2"] * Math.Cos(local["rad"])
param["y2"] = local["y"] + local["r2"] * Math.Sin(local["rad"])
If local["a1"] < a Then
FillQuadrangle()
EndIf
param["x4"] = param["x1"]
param["y4"] = param["y1"]
param["x3"] = param["x2"]
param["y3"] = param["y2"]
EndFor
GraphicsWindow.BrushColor = local["bc"]
a = Stack.PopValue("local")
local = Stack.PopValue("local")
param = Stack.PopValue("local")
EndSub
Sub FillQuadrangle
GraphicsWindow.FillTriangle(param["x1"], param["y1"], param["x2"], param["y2"], param["x3"], param["y3"])
GraphicsWindow.FillTriangle(param["x3"], param["y3"], param["x4"], param["y4"], param["x1"], param["y1"])
EndSub