SMF_GD.write(smf_data) returns 0 size PoolByteArray
Hi! I’m trying to save a MIDI file, but I have a problem:
print(smf_data)
var bytes: PoolByteArray = SMF_GD.write(smf_data)
print(len(bytes))
And this prints:
{format_type:0, timebase:22, track_count:1, tracks:[{events:[{bpm:2000, channel_number:0, time:0, type:13}, {channel_number:0, note:43, time:148, type:1, velocity:127}, {channel_number:0, note:43, time:162, type:0, velocity:0}, {channel_number:0, note:44, time:101, type:1, velocity:123}, {channel_number:0, note:44, time:114, type:0, velocity:0}, {channel_number:0, note:46, time:70, type:1, velocity:127}, {channel_number:0, note:46, time:81, type:0, velocity:0}, {channel_number:0, note:50, time:165, type:1, velocity:127}, {channel_number:0, note:50, time:176, type:0, velocity:0}, {channel_number:0, note:51, time:52, type:1, velocity:127}, {channel_number:0, note:51, time:68, type:0, velocity:0}, {channel_number:0, note:51, time:81, type:1, velocity:127}, {channel_number:0, note:51, time:96, type:0, velocity:0}, {channel_number:0, note:51, time:117, type:1, velocity:127}, {channel_number:0, note:51, time:138, type:0, velocity:0}, {channel_number:0, note:55, time:5, type:1, velocity:90}, {channel_number:0, note:55, time:15, type:0, velocity:0}, {channel_number:0, note:55, time:21, type:1, velocity:127}, {channel_number:0, note:55, time:43, type:0, velocity:0}, {channel_number:0, note:59, time:175, type:1, velocity:127}, {channel_number:0, note:59, time:192, type:0, velocity:0}, {channel_number:0, time:195, type:12}], track_number:1}]}
0
So I’m using a dictionary, but the returned PoolByteArray is empty.
I’m setting the tempo, adding some notes, and then adding a track end event. (I saw that I don’t need to sort the events, it’s done internally)
I’m using Godot 3.2.4.rc5, but I tried with 3.2.3 once and that yielded a similar result.
(also, as a side note the wiki about https://bitbucket.org/arlez80/godot-midi-player/wiki/struct/SMF seems to be wrong, because it says I’d need to create a note on with something like this: {channel_number:0, time:175, event: {note:59, type:1, velocity:127}}, but it seems to work with this: {channel_number:0, note:59, time:175, type:1, velocity:127} and the previous one throws an error)
Can you/someone please help, what’s going on? Here’s a minimal reproduction project, with godot 3.2.3 this time:
Comments (8)
-
reporter -
reporter - attached midi_save_problem.zip
-
reporter - edited description
-
repo owner writer is not update long time.
I will update to new version data structure.
-
repo owner I fixed at 8aa7a41.
You needs uses data structure that same as reader.
sample:
var smf_rw: = SMF_GD.new() var src = smf_rw.read_file("res://src.mid") var dest = smf_rw.write( src ) var f: = File.new( ) f.open( "write-test.mid", File.WRITE ) f.store_buffer( dest ) f.close( )
-
repo owner anyway thank you for bug report.
-
reporter Thanks a lot! With the help of midicsv and with the new commit, I was able to recreate what I wanted.
So if someone from the future is reading this, here’s (a smaller part of) the example with dictionaries I wrote earlier that actually works, it should create a 65B large, 4s long midi file, playing 4 notes, in probably the easiest way possible:
var SMF_GD = preload("res://addons/midi/SMF.gd").new() func _ready(): var smf_data = {"format_type":1, "timebase":22, "track_count":1, "tracks":[{"track_number":1, "events":[ {"channel_number":0, "time":0, "event": {"type":SMF_GD.MIDIEventType.system_event, "args": {"bpm":500000, "type":SMF_GD.MIDISystemEventType.set_tempo}}}, {"channel_number":0, "time":148, "event": {"note":43, "type":SMF_GD.MIDIEventType.note_on, "velocity":127}}, {"channel_number":0, "time":162, "event": {"note":43, "type":SMF_GD.MIDIEventType.note_off, "velocity":0}}, {"channel_number":0, "time":101, "event": {"note":44, "type":SMF_GD.MIDIEventType.note_on, "velocity":123}}, {"channel_number":0, "time":114, "event": {"note":44, "type":SMF_GD.MIDIEventType.note_off, "velocity":0}}, {"channel_number":0, "time":70, "event": {"note":46, "type":SMF_GD.MIDIEventType.note_on, "velocity":127}}, {"channel_number":0, "time":81, "event": {"note":46, "type":SMF_GD.MIDIEventType.note_off, "velocity":0}}, {"channel_number":0, "time":165, "event": {"note":50, "type":SMF_GD.MIDIEventType.note_on, "velocity":127}}, {"channel_number":0, "time":176, "event": {"note":50, "type":SMF_GD.MIDIEventType.note_off, "velocity":0}}, {"channel_number":0, "time":195, "event": {"type":SMF_GD.MIDIEventType.system_event, "args": {"type":SMF_GD.MIDISystemEventType.end_of_track}}}, ]}]} var bytes = SMF_GD.write(smf_data) var file = File.new() file.open("res://test.mid", File.WRITE) file.store_buffer(bytes) file.close()
Analyzing the output with midicsv, there seem to be some random note_off events when the end_of_track event is missing, so don’t leave that out.
of course you can organize it better, move type to the front, make more line breaks etc.
Timebase is the “the number of clock pulses per quarter note“ where clock pulse is the same as the “time” value
and set_tempo’s bpm is “The tempo is specified as the Number of microseconds per quarter note, between 1 and 16777215. A value of 500000 corresponds to 120 quarter notes (“beats”) per minute. To convert beats per minute to a Tempo value, take the quotient from dividing 60,000,000 by the beats per minute.”
source: https://www.fourmilab.ch/webtools/midicsv/
So I think we can close this, everything works.
-
reporter - changed status to resolved
yay
- Log in to comment
Also, I’m not sure what that means but buf.get_available_bytes( ) are 0 at SMF.gd line 680 in function
_write_track
, and alsostream.get_available_bytes()
is 0 at line 574 in functionwrite
, just before returning the PoolArray. I don’t know though if that’s normal or not.I also tried printing out the
note
values of the note on events from_write_track
and those seemed to be understood correctly.I’ll attach a minimal reproduction project.