And here it is, no editing, but a proof of concept. Sound-Samples have to be fixed. Maybe ripping it from the original later
// Project: FL_MarioPaintComposer_Loader
// Created: 2018-12-08
// show all errors
SetErrorMode(2)
// set window properties
SetWindowTitle( "FL_MarioPaintComposer_Loader" )
SetWindowSize( 1280, 720, 0 )
SetWindowAllowResize( 1 ) // allow the user to resize the window
// set display properties
SetVirtualResolution( 1280, 720 ) // doesn't have to match the window
SetOrientationAllowed( 1, 1, 1, 1 ) // allow both portrait and landscape on mobile devices
SetSyncRate( 30, 0 ) // 30fps instead of 60 to save battery
SetScissor( 0,0,0,0 ) // use the maximum available screen space, no black borders
UseNewDefaultFonts( 1 ) // since version 2.0.22 we can use nicer default fonts
musicString$ as String
musicString$ = "4/4*ef+jm+++++q:ef+jm+++++q::ef+jm+++++q::eh+jo+++++q:ef+jm+++++q::ed+jk+++++q::::ci+ok+bm++++q::::lf+lh+bo++++q::oo+md+++++q:lf+oo+md++++q:le+lh+bo++++q::md+ol+++++q:md+ok+le++++q:ld+lg+++++q::md+ok+++++q:oo+ld+fk++++q:fj+fl+le++++q:fl+fn+bj++++q:fj+fl+bn++++q:fi+fk+++++q:af+oo+mp++++q::bd++++++q:be+oo+++++q:om+ah+mp++++q::bd++++++q:be+ak+om++++q:aj+ol+mp++++q:ah++++++q:ol+bd+++++q:be+oj+ah++++q:mp++++++q:bd++++++q::be+ok+aj++++q:mp+ak+++++q:ok++++++q:ah+bd+ol++++q:be++++++q:ah+mp+om++++q::ad+on+++++q:++++++q:af+ok+++++q:ek++++++q:ej++++++q:ei+ol+ag++++q:+eh+++++q:eg+bj+++++q:ef++++++q:ee+bk+++++q:ef+bn+oo++++q:ak++++++q:ah+if+++++q:ak+bn+oo++++q:eh+bn+om++++q:ak+if+++++q:ah++++++q:ai+ek+om++++q:ol+ej+bn++++q:aj+eh+kl++++q:ah++++++q:eh+ae+oj++++q:bl++++++q:bh+ie+af++++q:bh+ag+++++q:bi+ej+++++q:bn+ek+++++q:od+af+ak++++q:eh++++++q:ae++ak+ai+++q:ee+ok+++++q:ef++++++q:eg++++++q::eh++++++q:oh+bf+++++q::oo++bh++++q:oo++bi++++q::bo+bi+++++q::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::%358%358"
// this is the standard file from Mario Paint Composer, Mario Bros. Theme
// will ignore 4/4* and count ":" for array lenght
// 5 by 96 notes, but 6 by 96 because one for volume
Type MarioPC_Voice
SoundID as integer
ImageID as integer
name$ as String
EndType
// global for the moment, to test the prototype
MarioPCMusic as MarioPC_Note[96,5] // not save, if music-string has errors
// 0 is for volume, 1..5 are the notes
global MPC_voice as MarioPC_Voice[19] // 0 not used
global MPC_voice_names$ as String[19]=["empty", "Mario", "Mushroom", "Yoshi", "Star", "Flower", "Gameboy", "Dog", "Cat", "Pig", "Swan", "Baby", "Plane", "Boat", "Car", "Heart", "Piranha", "Coin", "ShyGuy", "Ghost"]
// this could be calculated, but so we are sure, we do not introduce another possible mistake
// a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q
// p, o, n, m, l, k, j, i, h, g, f, e, d, c, b, a // how they are saved
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, // asc()-96
// h/b',C',D',E',F',G',A',HB,C'',D'',E'',F'',G'',A'',HB ,C''' // no half-tunes, no # or b, no CIS / DES etc.
global MPC_voice_tunes as float[17]=[246.9, 261.6,293.7, 329.6, 349.2,392.0,440.0, 493.9, 523.3, 587.3, 659.3,698.5,784.0,880.0,987.8,1047]
// easy peasy for copying: https://www.seventhstring.com/resources/notefrequencies.html
// http://pages.mtu.edu/~suits/notefreqs.html
Print ("Load Voices")
Sync()
img = LoadImage("MarioPCBG.png")
spr = CreateSprite(img)
SetSpritePosition(spr, 100,100)
for i = 1 to 19
MPC_voice[i].name$ = MPC_voice_names$[i]
MPC_voice[i].SoundID = LoadSoundOGG("voices/"+MPC_voice[i].name$+".ogg")
MPC_voice[i].ImageID = LoadImage("images/"+MPC_voice_names$[i]+".png")
next
Type StringRef
S as String // don't understand why I can't ref directly a string
EndType
b_left = 1
AddVirtualButton(b_left, 600,520,70)
b_right = 2
AddVirtualButton(b_right, 820,520,70)
b_play_note = 3
AddVirtualButton(b_play_note, 700,550,80)
SetVirtualButtonColor(b_play_note,100,250,100)
b_play_song = 4
AddVirtualButton(b_play_song, 700,650,100)
SetVirtualButtonColor(b_play_song,100,250,100)
DebugS$ as StringRef
DecodeMarioPCMusicToArray(musicString$, MarioPCMusic, DebugS$ )
DrawMusicSprites(MarioPCMusic , -1)
pos = 0
playsong = 0
timer# = 0
ResetTimer()
do
Print( Str(ScreenFPS(),2) )
DrawMusicGUI(MarioPCMusic, 1)
// DrawMusicSprites(MarioPCMusic , 64 * 4 * 0) // Start
DrawMusicSprites(MarioPCMusic , pos * 64) //
Print(DebugS$.s)
If GetVirtualButtonState(b_right) // not framerate independend!!!
inc pos, 1
if pos > 95*1
pos = 95*1
endif
EndIf
If GetVirtualButtonState(b_left) // not framerate independend!!!
dec pos, 1
If pos <0
pos = 0
endif
EndIf
If GetVirtualButtonReleased(b_play_note)
PlayTick(MarioPCMusic,pos+1)
endif
If GetVirtualButtonReleased(b_play_song) // play_tick(), change pos at tempo-interval
playsong = 1-playsong
if playsong = 0
pos = 0
timer# = 0
else
// ResetTimer() // maybe "damages" other parts of a game, if used here
ResetTimer()
endif
endif
if playsong = 1
Print(""):Print(""):Print(""):Print(""):Print(""):Print(""):Print(""):Print("")
Print ("Is playing ...")
//Print (Str(timer()))
if timer() - timer# > 0.150 // depends on speed / tempo
PlayTick(MarioPCMusic,pos+1)
timer#=timer()
inc pos, 1
if pos > 95
pos = 0
playsong = 0
timer# = 0
endif
endif
endif
Sync()
loop
//--------------------------------
// We need 20 voices as instruments and somehow we have to make sure, that also 5 notes with the same instrument could be played
// Mario, Mushroom, Yoshi, Star, Flower, Gameboy, Dog, Cat, Pig, Swan, Baby, Plane, Boat, Car, Heart, Piranha, Coin, ShyGuy, Ghost
// sounds like (Sound Club 2 instruments used):
// Hard_Block, Low_Tom, Noisy_Escape-Melody, Glockenspiel-Melody, Short_Brass_Beep (C2), Slap_Brass_2 (C2), Dog, Cow (C2), OuchVoice, Orch_Hit_4, Ouch, Acustic_Guitar2, Open_HiHat_1, Fingered_El_Bass, Solo_Guitar, Grand_Piano, String_Swell, Muted_Guitar2
// Mushroom: Drum
// Gameboy: Beep-Sound
// Dog, Cat, Pig, Baby: like they sound
// Boat: drums and hihat
// Swan: Orchester hit
// Flower: Trumpet
// ShyGuy, Piranha, Heart, Ghost, Plane: Piano and Guitars
//--------------------------------
Type MarioPC_Note // I guess, I will save it in a large array, ( a..p + volume ) * 96, but different voices can have the same tune, so maybe not in a large array ...
tune as integer // Y-Pos
voice as integer // SoundID
sprite as integer // SpriteID
volume as integer // but it is set for all notes at the same moment, X-pos would matter for volume
EndType
Function DrawMusicSprites(MarioPC_Array ref as MarioPC_Note[][], PosX as integer) // PosX =-1 for Creating-Sprites first time
for ix = 1 to 96
for iy = 1 to 5
if MarioPC_Array[ix,iy].voice >0
if PosX=-1
MarioPC_Array[ix,iy].sprite = CreateSprite(MPC_voice[MarioPC_Array[ix,iy].voice].ImageID)
endIf
SetSpritePosition(MarioPC_Array[ix,iy].sprite, 64*ix+177 - PosX, MarioPC_Array[ix,iy].tune*16 + 110)
// the tune has to be converted into "pitch"
// a for 440, that is also the base tune the preview-voices are playing in the voice-select-menu
// 220, 440, 880 and between we have 12 steps
endif
next
Next
EndFunction
Function DrawMusicGUI(MarioPC_Array ref as MarioPC_Note[][], pos as integer)
Print(Str(MarioPC_Array[1,2].voice))
Print(Str(MarioPC_Array[1,2].tune))
Print(Str(MarioPC_Array[1,2].volume))
EndFunction
Function PlayTick(MarioPC_Array ref as MarioPC_Note[][], pos as integer)
// 5 notes, get tune, do pitch, do volume, and play
for n = 1 to 5
if MarioPC_Array[pos,n].voice>0
//MarioPC_Array[pos,n].volume
sound_id=PlaySound(MPC_voice[MarioPC_Array[pos,n].voice].SoundID,100)
// maybe the samples are "recorded with the base of C and not A, so the calculation is a little bit different
// more to find here
// https://de.wikipedia.org/wiki/Frequenzen_der_gleichstufigen_Stimmung
pitch# = 1.0 * (MPC_voice_tunes[17-MarioPC_Array[pos,n].tune] / 440)
SetSoundInstanceRate(sound_id, pitch# ) //sound_id,MarioPC_Array[pos,n].tune )
// the highest pitch is letter "a" or 1, the lowest pitch is "p" or 17
Endif
Next
EndFunction
Function DecodeMarioPCMusicToArray(Music$, MarioPC_Array ref as MarioPC_Note[][], DebugStr$ ref as StringRef )
Mus$ = Right(Music$, Len(Music$)-4) // cuts "4/4*" or "3/4*" at the beginning // NO checking if valid!
offchr = 96 // a:97
for i = 1 to 96
Tick$ = GetStringToken2( Mus$, ":", i ) // 5 notes + 1 volume
DebugStr$.S = Tick$
volume = asc(GetStringToken2(Tick$,"+",7)) - offchr
MarioPC_Array[i,0].volume = volume // ATTENTION, 0 is used, but it is from the sixth note-position in the string
for n = 1 to 5 // "note" 6 has to be empty
chars$ = GetStringToken2(Tick$,"+",n) // gets two chars
tune = asc(right(chars$,1)) - offchr // ap is Mario-Voice lowest tune
voice = asc(Left(chars$,1)) - offchr // aa is Mario-Voice highest tune
MarioPC_Array[i,n].voice = voice
MarioPC_Array[i,n].tune = tune
MarioPC_Array[i,n].volume = volume
next
next
EndFunction
Function LoadMarioPCMusic()
// load a text file, read the first String, convert the String
EndFunction
/*
Function StringField(stringly, seperator, index) // returns String
// GetStringToken2( str, delimiter, token )
EndFunction
*/
feel free, to try it out. Sound samples are from SoundClub. I used C as base, not A, so the tune is not quite right. But it is here now 5:33 am, so I have to go to bed