Author Topic: Non-realtime sequenced music playback using BASS_MIDI_StreamCreate?  (Read 730 times)


  • Posts: 4

I'm new to BASS and BASSMIDI, but I have kinda figured out how to use it.

When I use
Code: [Select]
BASS_MIDI_StreamCreateFile(filename, 0, 0, BASS_SAMPLE_FLOAT | BASS_STREAM_DECODE | BASS_MIDI_DECAYEND | BASS_SAMPLE_MONO, samplerate);, everything works as expected when repeatedly calling
Code: [Select]
BASS_ChannelGetData(handle, buf, buflen);.

However, if I use
Code: [Select]
BASS_MIDI_StreamCreate(16, BASS_SAMPLE_FLOAT | BASS_STREAM_DECODE | BASS_SAMPLE_MONO, samplerate); and do some
Code: [Select]
BASS_MIDI_StreamEvents(handle, BASS_MIDI_EVENTS_STRUCT, bufcopy), I always get -1 when doing
Code: [Select]
BASS_ChannelGetData(handle, buf, buflen);, and the error is
Code: [Select]

I can't figure out what I'm doing wrong, because all I changed is I replaced StreamCreateFile with StreamCreate, and I'm manually sending the data instead of BASSMIDI handling the MIDI file parsing for me.
I used a debugger, and the events sent via StreamEvents are correct.

I'm using BASS.NET, BASS, and BASSMIDI on Windows x86_64, if that matters.

Ian @ un4seen

  • Administrator
  • Posts: 22606
I suspect there is a MIDI_EVENT_END event in the array passed to BASS_MIDI_StreamEvents, which is ending the stream and resulting in the BASS_ERROR_ENDED error from BASS_ChannelGetData. MIDI_EVENT_END is defined as 0, so it could be that one of the events in the array is uninitialized.


  • Posts: 4
Oh, I haven't thought of that.

But then again, I used a debugger to look at each element, and none of them were null or MIDI_EVENT_END, so it doesn't make too much sense :/


  • Posts: 4
I've been debugging for hours, and the only conclusion I came to is that somehow BASS.NET is somehow broken. When using
Code: [Select]
public static int BASS_MIDI_StreamEvents(int handle, BASSMIDIEventMode flags, BASS_MIDI_EVENT[] events); I would not only get weird results, but also sometimes I'd get AccessViolationException with a non-null and non-empty array.

After looking at BASS_MIDI_EVENT, I noticed that it has been defined as a class for some reason instead of a struct, which makes stuff even more suspicios as to why it's been crashing.

After copypasting some code, I concluded that BASS.NET has this error where BASS_MIDI_EVENT is defined as a class, which is causing Marshaling issues due to a class having an undocumented structure in memory.
My version which calls into bassmidi directly works perfectly, so it turns out I was using BASS.NET right  ;D

Here's what I'm using to make stuff work
Code: [Select]
private struct BASSMIDI_EVENT
    public int eventtype;
    public int param;
    public int chan;
    public int tick;
    public int pos;

    public BASSMIDI_EVENT(BASSMIDIEvent EventType, int Param, int Chan, int Tick, int Pos)
        this.eventtype = (int)EventType;
        this.param = Param;
        this.chan = Chan;
        this.tick = Tick;
        this.pos = Pos;

    public override string ToString()
        return string.Format("Event={0}, Param={1}, Chan={2}, Tick={3} ({4})", new object[]

private static extern int BASS_MIDI_StreamEvents(int handle, int mode, IntPtr events, int length);

private static int BassStreamEvents(int handle, BASSMIDIEventMode mode, BASSMIDI_EVENT[] events)
    GCHandle h = GCHandle.Alloc(events, GCHandleType.Pinned);
    IntPtr addr = h.AddrOfPinnedObject();
    int ret = BASS_MIDI_StreamEvents(handle, (int)mode, addr, events.Length);
    return ret;

You *could* use pointers too, but I wanted to avoid using the /unsafe flag just for this one function call. I hope this helps in fixing this issue!

But be aware that changing the type of BASS_MIDI_EVENT from a class to a struct will break previously built programs, so all of them will have to be rebuilt with a newer dll.

Also, in my opinion I'd love to see some privately declared functions (like in this example, BASS_MIDI_StreamEvents with the IntPtr overload) to be opened up the public, so we wouldn't have to copypaste the private DllImport declaration into our programs with a different name to cause confusion on why we can't find the function we just declared. This is just an opinion though.

Besides this minor problem I love BASSMIDI, especially that you can use the BASS_MIDI_EVENT struct to recreate what a proprietary file format does, including preparsed MIDI files :)


  • Posts: 4675
What BASS.NET version are you using? - as in the lastest BASS.NET version (related to BASS v2.4.14.x), BASS_MIDI_EVENT is already defined as a struct!
So might it be, that you are using an older Bass.Net version?

Note: I just realized, that I accidentially never updated the v2.4.14.0 BASS.NET version to the FTP!
I just did right now ... so please redownload and try again.
Sorry for the confusion.
« Last Edit: 12 Apr '19 - 08:05 by radio42 »


  • Posts: 4
Thank you for the update, the new BASS.NET dll works perfectly!

Also, as I stated in the first post, I was using BASS.NET, but it doesn't matter anymore, because this new update works :P