ML Synth Tools XIAO SAMD Synth

Having listed out a few Arduino Audio and MIDI Frameworks and having spent some time recently with the XIAO SAMD21, I thought I’d take a closer look at the ML Synth Tools XIAO synth.

Important Update: It would appear that the ML_SynthTools and samd21_mini_synth repositories have been fairly significantly updated since I wrote this. I’ve tried it again with the most recent versions but now the mini synth does not appear to build – the library is after FS.h – I’m not sure what library would provide this for a XIAO and the readme doesn’t seem to elaborate…

I might have another look at some point and come back and update this if I do, but it isn’t a priority for me at the moment.

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

These are the key tutorials for the main concepts used in this project:

If you are new to microcontrollers, see the Getting Started pages.

ML SAMD21 Mini Synth

One of the demonstrations for ML_Synth_Tools is the SAMD21 Simple Synth which will run on my XIAO: https://github.com/marcel-licence/samd21_mini_synth.

To install the library requires the following:

  • Download the ZIP from GitHub for ML_SynthTools, expand and copy to the Arduino Libraries folder.
  • Download the ZIP from GitHub for samd21_mini_synth, expand, rename the innermost samd21_mini_synth-main directory to samd21_mini_synth, and move it to the Arduino sketch (src) folder.
  • Open the samd21_mini_synth.ino file, set board to the Seeed XIAO SAMD21 and perform a test build. It should all build ok at this point.

There is a video tutorial on setting everything up here: https://www.youtube.com/watch?v=ZNxGCB-d68g, although this is geared up for the ESP32 version of the synth.

To use the library, there are two configuration steps really.  First, the file config.h contains some high-level configuration options.  By default it is configured for serial MIDI, but you can add USB MIDI host or device functionality here.

The library also comes pre-built for use with Marcel’s Edirol MIDI controller, so some MIDI configuration is required.  This happens in the z_config.ino file from the examples.  The two key structures to be setup are defined in ML_SynthTools/midi_interface.h.

MIDI controllers are defined in midiControllerMapping which is a series of entries in the format:

  • MIDI channel (I believe it is stored as 0-15, I don’t know if it supports OMNI channel).
  • MIDI CC number (0 to 127).
  • Name for the control as a text string.
  • MIDI callback function.
  • Parameter value handling callback function.
  • User data for the parameter callback function.

A second structure, midiMapping_s, is also used that defines the handlers for various MIDI messages with entries for the following:

  • Raw messages.
  • Note on.
  • Note off.
  • Pitch bend.
  • Modulation wheel.
  • Program change.
  • Real-time messages.
  • Song position.
  • MIDI controller map.
  • MIDI controller map size (number of entries).

This is the MIDI Configuration I used (z_config.ino):

struct midiControllerMapping sdempMapping[] =
{
{ 0, 0x10, "R1", NULL, Synth_SetParam, SYNTH_PARAM_WAVEFORM_1},
{ 0, 0x11, "R2", NULL, Synth_SetParam, SYNTH_PARAM_WAVEFORM_2},
{ 0, 0x12, "R3", NULL, Synth_SetParam, SYNTH_PARAM_MODULATION_PITCH},
{ 0, 0x13, "R4", NULL, Synth_SetParam, SYNTH_PARAM_MODULATION_SPEED},

{ 0, 0x14, "R5", NULL, Synth_SetParam, SYNTH_PARAM_PITCH_BEND_RANGE},
{ 0, 0x15, "R7", NULL, Delay_SetFeedback, 0},
{ 0, 0x16, "R8", NULL, Delay_SetLevel, 0},

{ 0, 0x17, "H1", NULL, Synth_ModulationWheel, 0},
};

struct midiMapping_s midiMapping =
{
NULL,
Synth_NoteOn,
Synth_NoteOff,
Synth_PitchBend,
Synth_ModulationWheel,
sdempMapping,
sizeof(sdempMapping) / sizeof(sdempMapping[0]),
};

I used the config (config.h) largely “as is” but had to add the following parameter:

#define MIDI_SERIAL1_BAUDRATE 31250

without this, the midi_interface.h defaults to a MIDI baud rate of 115200 for some reason.

I used this with my Arduino MIDI Multi Pot Controller to give me the 8 MIDI CC pots 0x10-0x17 as required above.  But the way the controls work wasn’t particularly intuitive to me.  In particular, I believe there is a bug in the pitch bend setting, as in mini_synth, it looks to me that both the modulation pitch and pitch bend parameters set the modulation pitch…

case SYNTH_PARAM_PITCH_BEND_RANGE:
  chControl[actCh].modulation.pitch = (value) * MODULATION_PITCH_MAX;
  break;
case SYNTH_PARAM_MODULATION_PITCH:
  chControl[actCh].modulation.pitch = (value) * MODULATION_PITCH_MAX;
  break;

The delay effect sounded pretty neat, but it took a while to get a feel for how the modulation effect was working.  In particular, I didn’t get much of a difference in modulation waveform.  Also, setting the modulation pitch to zero seems to stop all sound production regardless of modulation speed or level settings.

It is interesting to note that both the sine and triangle waves, when playing chords, will significantly increase the amplitude of the output signal.

Hardware

I’ve installed this onto my XIAO MIDI Proto PCB and have wired up the DAC output (from the pad erroneously labelled “6”) via 1uF coupling capacitors (to remove the DC bias from the DAC output) to a TRS socket for audio output.

Yes, with hindsight, I could probably have gotten away with a single capacitor!

IMG_7165

I’m controlling it using my XIAO MIDI Synth Board PCB running my Arduino MIDI Multi Pot Controller code.  The synth parameters are thus mapped onto the pots as follows:

XIAO-MIDI - MLXIAOSynth

MIDI from my keyboard goes into the controller board and is then merged with the controller’s pot CC messages, so the OUT of the controller board goes into the IN of the synth board.  Both boards are powered via the XIAO USB connectors and audio goes off to an amp.

IMG_7167

Closing Thoughts

The synth itself sounds pretty good and there is a lot going on with this toolkit that would probably reward the time it takes to get to know it.  But there are a few things that hold me back at the moment:

  • The default setup is all geared up for Marcel’s specific MIDI controller, so it takes a while to work out what MIDI functions are available for whatever application is being built and then map that onto your own device.
  • There are no options for localised control so everything has to be over MIDI meaning that the above has to happen before any of the sample applications can be tried.
  • I think I’ve managed to get the SAMD mini synth into a mess every now and again, requiring it needing a reset to wake up again, but I’m not quite sure how I’ve managed it.
  • I’ve not found any documentation of things like the MIDI functions or the synth controls anywhere so far, apart from reading the code.
  • … and certain key parts of the code are unavailable as source.

I guess for me personally, this will take a fair bit of time getting to grips with what the possibilities are, but I’m reluctant to take that time due to the fact that it isn’t fully open source (at the moment at least), yet it also hasn’t got the level of documentation required to be a “product” either.

I’m also not totally sold on the MIDI implementation – having to read the code each time to work out how to set up the MIDI controllers to give access to all the parameters.  I’ll have to attempt to develop a standard mapping for one of my own MIDI controllers to make life easier, seeing as the synth itself doesn’t have a mapping of its own as such.  This is probably something for my Arduino MIDI Multi MUX Controller.

Also, unless I’m missing something, it doesn’t seem to support MIDI OMNI channel mode, and I can’t see anywhere where it will handle a received SysEx message, so I’m wondering if there is still development on the MIDI side to be done.

Having said all that, the idea of significant polyphony is definitely appealing, so I might persevere a little more yet.  The sample videos of Marcel’s excellent playing certainly show off the potential of the code at its best far more than my crummy demo video!

The XIAO SAMD21 is probably the least performant of all the architectures supported by the Synth Library, especially this “chiptune synth” application, so I also need to have a go with some of the others.  In particular the “organ” demonstration is the one Marcel uses to show off the toolkit.

This might also be my cue to properly start playing with an ESP32!

Kevin

IMG_7164

9 thoughts on “ML Synth Tools XIAO SAMD Synth

  1. Hi, Kevin,

    Could you give a little more detail about how you wired up the two electrolytic capacitors for the audio out in the XIAO MIDI Proto PCB photo you show above, please? And, how/why is it different from the audio out circuit you used in the XIAO MIDI Synth Board PCB?

    Thanks,

    Peter

    Like

    1. Yes, I should probably have explained that a little shouldn’t I! Digging out my board again and having a look, I think it was because of that jumper – it gives me the option of keeping the L/R channels separate if I choose to, although I can’t think why I would given the wiring I’ve used and the XIAO only has a single DAC output anyway 🙂 I could have put the jumper after a single capacitor and still pretty much achieved the same end result.

      So, the MIDI Synth Board circuit should be fine here too, with a single capacitor feeding both the T and R connections of the TRS socket.

      Kevin

      Like

      1. Thanks! I’m still a bit confused about the orientation of the electrolytic capacitor…the + should be on the XIAO side of circuit, right? I think I’ve seen some examples where the coupling capacitor is used the opposite of what you’d expect (and I’m aware that the coupling capacitor’s orientation was misprinted on the XIAO MIDI Synth Board PCB).

        Like

      2. Yes, the + is on the XIAO side as that is 0 to 5V and the TRS side will be -2.5 to 2.5V.

        Looking again, the jumper actually disconnects the DAC entirely – it isn’t about L+R at all. The circuit goes like this:
        DAC – jumper – +ve side of capacitors|-ve side – TRS socket outer pins.

        Update: I’ve added a small schematic of this bit! 🙂

        Like

      3. OK. That’s the way I’ve soldered it up. I haven’t been able to get the ML Synth Tools XIAO SAMD Synth working, though. I know my board is OK, because the Mozzi sketch runs as expected. The ML Synth test tone works, too, but something’s definitely not right with MIDI. I’ve watched the YouTube video, followed your suggested edits, and worked my way through the code…everything seems right, but there’s no response to the MIDI input from my keyboard. I think some of the code has changed since you initially wrote this up (and I haven’t tried enabling any of the USB Host functions), but it seems that it should just work and it doesn’t.

        Like

      4. Hmm. With MIDI I tend to find myself always going back to first principles – things like MIDI channel, checking pin 4/5 connections (and then rechecking as I still get it wrong even after checking!), looking for a pull-up signal on both sides of the optocoupler and so on.

        Can you try a simpler MIDI test to prove the hardware is ok? Maybe flashing the LED in response to MIDI data or something (I have a simple MIDI monitor elsewhere on my blog)?

        I seem to recall the XIAO has many options for configuring serial ports too, but its been a while since I last looked at it…

        If you have a photo of your hardware, I’d be happy to take a look (email diyelectromusic at gmail) if you think that might be useful?

        Kevin

        Like

      5. Thanks, Kevin, but still no luck with this. I know MIDI in is working (on the board, at least…my hardware is exactly like yours) and the test tone works. I’m aware that it’s been nearly a year since you looked at this, but it seems that you must have set up MIDI on Serial1 (“#define MIDI_SERIAL1_BAUDRATE 31250” in config.h)? Well, anyway, if I’ve piqued your interest in this, I’d be curious if you could get it going again.

        Peter

        Like

      6. Hmm. Looks like the project has been updated since I downloaded and used it. The only thing I’d changed apart from the MIDI controller configuration was the line you’ve highlighted. This was using Serial1 using his own MIDI implementation in a file midi_interface.h which is no longer part of the repository but instead now in the main ML_SynthTools library.

        Looking in the new midi_interface.h file it would still appear to be using Serial1 if ARDUINO_SEEED_XIAO_M0 is defined. This does seem to be defined in my test build when the Seeed XIAO is selected in the board manager in Arduino, so that ought to be ok if you’re using the Seeed SAMD Arduino core.

        As I say the ML tools are not using the standard Arduino MIDI library, but those pins (the standard XIAO hardware UART pins according to Arduino) used by my board are mapped onto what the Arduino environment is calling Serial1. Serial is the USB link. This is defined in the Arduino variant.h file for the XIAO here: https://github.com/Seeed-Studio/ArduinoCore-samd/blob/master/variants/XIAO_m0/variant.h

        One thing I did notice, is that the default baud once again is 115200 in this library, but that can be changed in config.h again, althoug it is now just called SERIAL_BAUDRATE (see https://github.com/marcel-licence/samd21_mini_synth/blob/main/config.h#L58).

        If I get a chance, I’ll dig my board out, update everything, and see if I can rebuild with the new version of the libraries!

        Update: Ok, a default build is currently failing. It appears that a build for the XIAO requires a FS.h which I think is an ESP32 thing… I’ll need to investigate, but given the limitations of this specific library (mostly the non-open source nature of elements of it) I’m not sure it will be a particular priority for me I’m afraid.

        I guess you could try going back to an earlier version from the GitHub repositories…? Not sure what else to suggest I’m afraid.

        Kevin

        Like

      7. Thanks for the reply…I wasn’t aware of the difference between Serial and Serial1 that you described. As best I could figure out it seemed that switching to midi on Serial1 could be achieved with this series of defines in config.h:

        #define SERIAL_BAUDRATE 115200
        //#define MIDI_RECV_FROM_SERIAL
        #define MIDI_PORT1_ACTIVE
        #define SAMPLE_RATE 44100
        #define SAMPLE_BUFFER_SIZE 100
        #define SIMPLE_DELAY_BUFFER_SIZE 6000

        This compiled and after uploading, the serial monitor showed:

        SerUSB Started!
        Setup Serial1 with 31250 baud with rx: RX1 pin
        SetupTimer
        Setup DAC
        SetupDone!
        UDR0

        That all seems right, but still no response to midi from the Xiao. Is RX1 the same as PIN_SERIAL1_RX?

        Peter

        Like

Leave a comment