Skip to content

Instantly share code, notes, and snippets.

@bkotov
Last active July 9, 2022 22:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bkotov/71d7dfafebfe775616c4bd17d6ddfe7b to your computer and use it in GitHub Desktop.
Save bkotov/71d7dfafebfe775616c4bd17d6ddfe7b to your computer and use it in GitHub Desktop.
This script allows to convert data stored in SNG files into MID files. It supposed to be executed from Synalaze It hex-editor and requires SNG grammar to be loaded first.
import midi
import time;
#---Class Song---
class Song:
def __init__(self):
print "Song started"
self.track = ''
self.pattern = midi.Pattern()
def processSong(self, result):
resultType = result.getType()
if resultType == RESULT_STRUCTURE_START_TYPE:
structureName = result.getName()
#Start of track data chunk
if structureName == "Track Events":
self.track = ''
self.track = Track(self.pattern)
if hasattr(self.track, 'processTrack'):
self.track.processTrack(result)
def __del__(self):
self.track = ''
midi.write_midifile("/Users/bkotov/Temp/test_" + str(time.time()) + ".mid" , self.pattern)
print "Song ended"
#---Class Song---
#---Class Track---
class Track:
def __init__(self, pattern):
print "Track started"
self.pattern = pattern
self.midiEvents = []
self.lastEvent = []
def processTrack(self, result):
if result.getName() == 'NoteOn':
self.lastEvent = []
self.lastEvent.append('note')
# Append note to events list.
if len(self.lastEvent) and result.getName() in ['note', 'velocity', 'length', 'timeShift']:
value = self.numberFromValue(result.getValue())
self.lastEvent.append(value)
if result.getName() == 'timeShift':
self.midiEvents.append(self.lastEvent)
self.lastEvent = []
def numberFromValue(self, value):
if( value != None ):
type = value.getType()
if type == VALUE_NUMBER_UNSIGNED:
return value.getUnsigned()
elif type == VALUE_NUMBER_SIGNED:
return value.getSigned()
elif type == VALUE_NUMBER_FLOAT:
return value.getFloat()
def appendEvents(self, track):
for event in self.midiEvents:
if event[0] == 'note' and event[3] < 32767 and event[4] < 32767:
on = midi.NoteOnEvent(tick=10, velocity=event[2], pitch=event[1])
track.append(on)
off = midi.NoteOffEvent(tick=event[3], pitch=event[1])
track.append(off)
eot = midi.EndOfTrackEvent(tick=1)
track.append(eot)
def __del__(self):
print "Track ended"
if len(self.midiEvents) > 0:
track = midi.Track()
self.pattern.append(track)
self.appendEvents(track)
#---Class Track---
def init():
print "Init"
song = ''
def processResult(result):
global song
resultType = result.getType()
if resultType == RESULT_STRUCTURE_START_TYPE:
structureName = result.getName()
# Start of song data chunk
if structureName == "MTK1 Chunk":
song = ''
song = Song()
# End of the song data chunk
if structureName == 'TMA1 Chunk':
song = ''
if hasattr(song, 'processSong'):
song.processSong(result)
def terminate():
global song
del(song)
print "terminate"
@User-Typical
Copy link

Do you have the SNG grammar file? I can't find it anywhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment