Last active
July 9, 2022 22:55
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Do you have the SNG grammar file? I can't find it anywhere.