Author Topic: Raspberry Pi Zero and Midi In  (Read 605 times)

aquinch

  • Posts: 17
Raspberry Pi Zero and Midi In
« on: 16 Mar '19 - 01:02 »
I have a midi device (Teensy 3.2) sending midi messages in to a Raspberry Pi Zero running the app with BASS library. But while trying to play the samples through the received Midi message I'm just getting gibberish out through the audio channel.

Code: [Select]
#include <unistd.h>
#include <sstream>
#include "bass.h"
#include "bassmidi.h"

using namespace std;

HSTREAM stream1;

int audio_device;
int midi_device;

void CALLBACK MidiInProc(DWORD device, double time, const BYTE *buffer, DWORD length, void *user) {
    BASS_MIDI_StreamEvents(stream1, BASS_MIDI_EVENTS_RAW, buffer, length);
    printf("MIDI Received\n");
}


int main() {

    int B, count=0;
    BASS_DEVICEINFO info;
    for (B=1; BASS_GetDeviceInfo(B, &info); B++) {
        if (info.flags&BASS_DEVICE_ENABLED) { // device is enabled
            //printf("BASS_GetDeviceInfo: %s\n", info.name);
            if (info.name = "ROCCAT Juke: USB Audio") {
                audio_device = B;
            }
            count++; // count it
        }
    }
    //audio_device = 1;
    BASS_GetDeviceInfo(audio_device, &info);
    printf("BASS_GetDeviceInfo Initialized: %s\n", info.name);

    //BASS_SetConfig(BASS_CONFIG_VISTA_TRUEPOS,0);
    if (BASS_Init(audio_device, 44100, BASS_DEVICE_STEREO, 0, NULL)) {
        printf("BASS_Init: %d\n", BASS_ErrorGetCode());
    }
   
    midi_device = 2;
    bool ini = BASS_MIDI_InInit(midi_device, MidiInProc, 0);
    printf("BASS_MIDI_InInit: %d\n", BASS_ErrorGetCode());

    BASS_MIDI_DEVICEINFO di;
    bool dev = BASS_MIDI_InGetDeviceInfo(midi_device, &di);
    printf("BASS_MIDI_InGetDeviceInfo - Name: %s\n", di.name);

    HSOUNDFONT sfz = BASS_MIDI_FontInit("SFZ/myDrum.sfz", 0);
    printf("BASS_MIDI_FontInit: %d\n", BASS_ErrorGetCode());

    printf("Loading Fonts ...\n");
    bool ld = BASS_MIDI_FontLoad(sfz, 0, 0);
    printf("BASS_MIDI_FontLoad: %d", BASS_ErrorGetCode());
    printf(" ... Done\n");


    stream1 = BASS_MIDI_StreamCreate(1, BASS_SAMPLE_FLOAT, 0);
    BASS_ChannelPlay(stream1,0);
    //BASS_MIDI_StreamSetFilter(stream1, 0, MidiFilterProc, 0);

    if (!BASS_ChannelSetAttribute(stream1, BASS_ATTRIB_BUFFER, 0)) {
        printf("BASS_ChannelSetAttribute: %s\n", "Failed");
    }
    else {
        printf("BASS_ChannelSetAttribute: %s\n", "Success");
    }

    BASS_MIDI_FONT config[1];
    config[0].font = sfz;
    config[0].preset = -1; // use all presets
    config[0].bank = 0; // use default bank(s)
    BASS_MIDI_StreamSetFonts(stream1, &config, 1);
    printf("BASS_MIDI_StreamSetFonts: %d\n", BASS_ErrorGetCode());



    printf("Testing Audio...\n");
    sleep(1);

    BASS_MIDI_StreamEvent(stream1, 0, MIDI_EVENT_NOTE, MAKEWORD(36, 127));
    BASS_MIDI_StreamEvent(stream1, 0, MIDI_EVENT_NOTE, MAKEWORD(52, 50));
    sleep(1);

    BASS_MIDI_StreamEvent(stream1, 0, MIDI_EVENT_NOTE, MAKEWORD(38, 127));
    BASS_MIDI_StreamEvent(stream1, 0, MIDI_EVENT_NOTE, MAKEWORD(52, 90));
    sleep(1);

    BASS_MIDI_StreamEvent(stream1, 0, MIDI_EVENT_NOTE, MAKEWORD(36, 127));
    BASS_MIDI_StreamEvent(stream1, 0, MIDI_EVENT_NOTE, MAKEWORD(52, 100));
    sleep(1);

    BASS_MIDI_StreamEvent(stream1, 0, MIDI_EVENT_NOTE, MAKEWORD(38, 127));
    BASS_MIDI_StreamEvent(stream1, 0, MIDI_EVENT_NOTE, MAKEWORD(52, 127));
    sleep(1);


    bool in = BASS_MIDI_InStart(midi_device);
    printf("BASS_MIDI_InStart: %d\n", BASS_ErrorGetCode());
    printf("Reading...\n");
   
    sleep(10);
    printf("Done\n");

    // free the stream
    BASS_MIDI_InFree(midi_device);
    BASS_StreamFree(stream1);

    // free BASS
    BASS_Free();

    return 0;
}

While testing the audio output I get perfect results:
Code: [Select]
   printf("Testing Audio...\n");
    sleep(1);

    BASS_MIDI_StreamEvent(stream1, 0, MIDI_EVENT_NOTE, MAKEWORD(36, 127));
    BASS_MIDI_StreamEvent(stream1, 0, MIDI_EVENT_NOTE, MAKEWORD(52, 50));
    sleep(1);

    BASS_MIDI_StreamEvent(stream1, 0, MIDI_EVENT_NOTE, MAKEWORD(38, 127));
    BASS_MIDI_StreamEvent(stream1, 0, MIDI_EVENT_NOTE, MAKEWORD(52, 90));
    sleep(1);

    BASS_MIDI_StreamEvent(stream1, 0, MIDI_EVENT_NOTE, MAKEWORD(36, 127));
    BASS_MIDI_StreamEvent(stream1, 0, MIDI_EVENT_NOTE, MAKEWORD(52, 100));
    sleep(1);

    BASS_MIDI_StreamEvent(stream1, 0, MIDI_EVENT_NOTE, MAKEWORD(38, 127));
    BASS_MIDI_StreamEvent(stream1, 0, MIDI_EVENT_NOTE, MAKEWORD(52, 127));
    sleep(1);

The problem is only on the playing the sounds received through the Midi device on the Raspberry Pi Zero. This same code works perfectly on both Windows 10 and Linux Ubuntu.

Ian @ un4seen

  • Administrator
  • Posts: 21987
Re: Raspberry Pi Zero and Midi In
« Reply #1 on: 18 Mar '19 - 14:36 »
When you say "While testing the audio output I get perfect results", do you mean with other software or just with different code? Are you only having the problem when playing MIDI events (as in the code above), not when playing MIDI files or other file formats (eg. WAV) with BASS? If it's affecting all BASS output, one thing you could try is increasing the device buffer length via the BASS_CONFIG_DEV_BUFFER option. Please see the documentation for details on that.

aquinch

  • Posts: 17
Re: Raspberry Pi Zero and Midi In
« Reply #2 on: 18 Mar '19 - 14:41 »
Hi Ian,

Yes, my issue is only when playing midi events through the MidiInProc callback on the Raspberry Pi zero. But yet, on the Pi Zero if I call the BASS_MIDI_StreamEvent directly from the program I do get the sound output.

Ian @ un4seen

  • Administrator
  • Posts: 21987
Re: Raspberry Pi Zero and Midi In
« Reply #3 on: 19 Mar '19 - 17:57 »
To perhaps narrow down what the problem is, what happens if you just play a fixed event (eg. a note on) in your MidiInProc function? For example:

Code: [Select]
void CALLBACK MidiInProc(DWORD device, double time, const BYTE *buffer, DWORD length, void *user) {
// BASS_MIDI_StreamEvents(stream1, BASS_MIDI_EVENTS_RAW, buffer, length);
BASS_MIDI_StreamEvent(stream1, 0, MIDI_EVENT_NOTE, MAKEWORD(52, 50));
    printf("MIDI Received\n");
}

Do you hear the note playing then, and does it sound OK?

aquinch

  • Posts: 17
Re: Raspberry Pi Zero and Midi In
« Reply #4 on: 19 Mar '19 - 22:40 »
Hi Ian,

I've tried that and I get the same result which is like a "tick" sound instead of the sample. I've also tried modifying the BASS_CONFIG_DEV_BUFFER up to 500ms but nothing changed.

aquinch

  • Posts: 17
Re: Raspberry Pi Zero and Midi In
« Reply #5 on: 20 Mar '19 - 09:50 »
I've just tested this on a Pi 3B+ and it works fine. It looks like the issue is specific to the Pi Zero.

Ian @ un4seen

  • Administrator
  • Posts: 21987
Re: Raspberry Pi Zero and Midi In
« Reply #6 on: 20 Mar '19 - 12:12 »
Perhaps it's a CPU power issue. What is the system load when your test is running? Does using a lower sample rate in the BASS_Init call help at all? Another thing to check... what happens if you move the BASS_MIDI_InStart call to before the "Testing Audio..." section and have the MidiInProc function do nothing? Do the test notes still sound OK then?

aquinch

  • Posts: 17
Re: Raspberry Pi Zero and Midi In
« Reply #7 on: 21 Mar '19 - 13:05 »
My SFZ file has a quite large number of files, so the CPU does gets maxed out while loading the fonts. And that was the reason I moved the BASS_MIDI_InStart after it. Apart from that, the CPU runs around 50%.

Reducing the sample rate to 20000 made no changes.

Moving the BASS_MIDI_InStart before the "Testing Audio..." did ruin the test notes and I got the same noises I was getting during the MidiInProc.

One thing that I've noticed is that while making the MidiInProc do nothing, I do get some very low volume noise while the MidiInProc is running (and doing absolutely nothing).

Ian @ un4seen

  • Administrator
  • Posts: 21987
Re: Raspberry Pi Zero and Midi In
« Reply #8 on: 21 Mar '19 - 17:05 »
50% CPU usage is pretty high. Is that before or after the BASS_MIDI_InStart call? Does the CPU usage change after that call? Perhaps the MIDI input is taking the load over the edge, although I wouldn't normally expect MIDI input to use much CPU. Is your MidiInProc function getting called (and frequently) even when you don't do do anything on the attached MIDI device? The MIDI input processing is entirely separate from the MIDI stream processing, so they can't really interfere with each other besides using CPU.

If you attach a WAV writer to the MIDI stream (eg. using BASS_Encode_Start with BASS_ENCODE_PCM), I guess the problem isn't present in the written WAV file?