It doesn't use the same syntax, but its the same basic concept.
L1 = whole note
L2 = half note
L4 = quarter note
L8 = 8th note
L16 = 16th note
The very first command must be tempo, "T" followed by a number.
T120 = tempo of 120bpm.
Next, comes the note data. Each note is preceeded by its length.
L2B4 = a half note of B4
Notes were matched with their frequencies using this page.
http://www.phys.unsw.edu.au/~jw/notes.html
Original code by Ric and a few others, post can be found here.
http://forum.thegamecreators.com/?m=forum_view&t=49008&b=6&p=0
What this code does exactly is writes all the notes to a single sound file. Until someone manages to figure out how to use different channels, only 1 note can be played at a time.
The song I put in for a demo is suppose to be moonlight sonata. But it doesn't sound like much without chords, since the intro is mostly the same 3 notes over and over with just a different bass note under it.
type NoteMapping
key as string
value as float
endtype
type Note
freq as float
length as float
endtype
dim notes(52) as NoteMapping
dim songData(0) as Note
RESTORE KEYS_VALUES
for i = 1 to 52
read notes(i).key
read notes(i).value
next i
parseSongData("T120L4A1L4A4L4C5L4B3L4A4L4C5L4B3L4A4L4C5L4B3L4A4L4C5L4G1L4A4L4C5L4B3L4A4L4C5L4B3L4A4L4C5L4B3L4A4L4C5L4F3L4A4L4C5L4F3L4A4L4C5L4F3L4B4L4D5L4F3L4B4L4D5")
createMusic(1)
play sound 1
wait key
function parseSongData(song$)
start = _findIndex(song$,"L")-1
temp$ = left$(song$,start)
tempo = val(right$(temp$, len(temp$)-1))
song$ = right$(song$, len(song$)-start)
rem note_count = len(song$)/4 (excluding the T120)
r# = tempo/60.0
for i = 0 to len(song$)-4 step 4
L = val(subString$(song$,i+1,i+2))
k$ = subString$(song$,i+2,i+4)
length# = ((4.0/L)/r#)* 1000
freq# = getValue#(k$)
addNote(freq#, length#)
next i
endfunction
rem length in seconds
function addNote(frequency#, length#)
array insert at bottom songData()
c = array count(songData())
songData(c).freq = frequency#
songData(c).length = length#
endfunction
REM Returns a chunk of a whole string
REM startp = starting index (zero-based)
REM endp = ending index, exclusive
function subString$(s$ as string, startp as integer, endp as integer)
l = len(s$)
s$ = right$(s$,l-startp)
s$ = left$(s$, endp-startp)
endfunction s$
function _findIndex(s$,v$)
for i = 1 to len(s$)
if mid$(s$,i) = v$
exitfunction i
endif
next i
l = len(s$)
endfunction l
function getValue#(key$)
v# = 0.0
for i = 1 to 52
if notes(i).key = key$ then v# = notes(i).value : break
next i
endfunction v#
function createMusic(soundnumber)
loudness# = 8000
bend# = 0
decay# = 10
vibratospeed# = 0
vibratodepth# = 0
tremelospeed# = 0
tremelodepth# = 0
attack# = 0
outWord as word
dword1 as dword: dword2 as dword: dword3 as dword: dword4 as dword
dword5 as dword: dword6 as dword: dword7 as dword
length# = 0.0
for i = 1 to array count(songData())
length# = length# + songData(i).length
next i
samples=int((length#/1000)*44100)
if memblock exist(1) then delete memblock 1
make memblock 1,samples*2+28
` write 28 memblock header bytes
dword1=1 ` gg query: is this the number of channels?
dword2=2 ` gg query: is this the number of bytes per sample?
dword3=22050 ` gg query: seems to be half the number of samples per second - why?
dword4=88200 ` gg query: is this the number of bytes per second?
dword5=4 ` gg query: what does this represent?
dword6=16 ` gg query: (ditto) ?
dword7=0 ` gg query: (ditto) ?
position=0
write memblock dword 1, position, dword1 : inc position,4
write memblock dword 1, position, dword2 : inc position,4
write memblock dword 1, position, dword3 : inc position,4
write memblock dword 1, position, dword4 : inc position,4
write memblock dword 1, position, dword5 : inc position,4
write memblock dword 1, position, dword6 : inc position,4
write memblock dword 1, position, dword7 : inc position,4
rem loop here
for i = 1 to array count(songData())
length# = songData(i).length
frequency# = songData(i).freq
samples = int((length#/1000)*44100)
rem generate and write wave
riseinloudness#=loudness#
for x=1 to samples
outInteger=int(sin((x/122.5)*(frequency#+vibratodepth#*sin(theta#)))*(loudness#-fallinloudness#-riseinloudness#+tremelodepth#*sin(phi#)))*3.0
if outInteger <-32767 then outInteger=-32767 ` gg query: is this the valid range?
if outInteger>32767 then outInteger=32767 ` gg query: (ditto) ?
outWord = outInteger
inc theta#,vibratospeed#
inc phi#,tremelospeed#
dec frequency#,bend#
if fallinloudness#<loudness#
inc fallinloudness#,decay#
endif
if riseinloudness#>0
dec riseinloudness#,attack#
endif
write memblock word 1, position, outWord : inc position,2
next x
next i
if sound exist(soundnumber)=1 then delete sound soundnumber
make sound from memblock 999, 1 ` assumes you won't need sound number 999!
clone sound soundnumber, 999
delete sound 999
` memblock no longer required
delete memblock 1
endfunction
KEYS_VALUES:
DATA "A0",27.500,"B0",30.868,"C1",32.703,"D1",36.708,"E1",41.203,"F1",43.654,"G1",48.999,"A1",55.000,"B1",61.735
DATA "C2",65.406,"D2",73.416,"E2",82.407,"F2",87.307,"G2",97.999,"A2",110.00,"B2",123.47,"C3",130.81,"D3",146.83
DATA "E3",164.81,"F3",174.61,"G3",196.00,"A3",220.00,"B3",246.94,"C4",261.6,"D4",293.67,"E4",329.63,"F4",349.23
DATA "G4",392.00,"A4",440.0,"B4",493.88,"C5",523.25,"D5",587.33,"E5",659.26,"F5",698.46,"G5",783.99,"A5",880.00
DATA "B5",987.77,"C6",1046.5,"D6",1174.7,"E6",1318.5,"F6",1396.9,"G6",1568.0,"A6",1760.0,"B6",1975.5,"C7",2093.0
DATA "D7",2349.3,"E7",2637.0,"F7",2793.8,"G7",3136.0,"A7",3520.0,"B6",3951.1,"C8",4186.0
"Using Unix is the computing equivalent of listening only to music by David Cassidy" - Rob Pike