julienvoirin Posted December 2, 2011 Report Share Posted December 2, 2011 (edited) Here is my first custom app using the "new" mios32 environment. :thumbsup: It only uses a STM 32 board : Juno 106 is connected to Midi in/out 1 and the core32 can be connected to your computer via USB or Midi in/out 2 The purpose is to convert the sysex from the Juno 106 to Control change messages (CC) (and vice versa), in order to edit automations in DAW that don't support sysex (e.g Ableton Live). Moreover it is really easier to edit CC messages (curves) than sysex ones (list of numbers) ! It does also convert CC messages received on USB and Midi in/out 2 to juno 106 sysex. In Control mode (meaning just moving the faders of the Juno), it sends simple CC. In Patch mode (e.g recalling patch A45 on the Juno), it sends a program change message and all the data of the controls via 18 CC so that you will ever get the patch parameters ; playing the record will transmit those CC and your Juno will return to its original tone :thumbsup: [*]In Manual mode it only sends all 18 parameters when you press the Manual button on the Juno. Moving faders sends sysex as in Control mode. Notice that you have to be in Midi Mode III on the Juno. (the only mode that produce sysex) Control change messages are the following : Control number of control change message 00 = LFO rate CC 102 01 = LFO delay time CC 103 02 = DCO LFO CC 104 03 = DCO PWM CC 105 04 = DCO Noise CC 106 05 = VCF Freq CC 107 06 = VCF Res etc ... 07 = VCF Env 08 = VCF LFO 09 = VCF Kybd 0A = VCA Level 0B = ENV A 0C = ENV D 0D = ENV S ... 0E = ENV R CC 116 0F = DCO SUB CC 117 10 = Switches 1 (see below) CC 118 11 = Switches 2 (see below) CC 119 You can change it in app.h by editing CC_Offset. The 102 value has been retained because I needed 18 adjacent numbers. Enjoy ! Rq : For those curious of some code routines : /* * Juno 106 SysEx Translator v1.0 * * ========================================================================== * * Copyright (C) 2011 Julien Voirin (julien.voirin@free.fr) * Licensed for personal non-commercial use only. * All other rights reserved. * * ========================================================================== */ ///////////////////////////////////////////////////////////////////////////// // Include files ///////////////////////////////////////////////////////////////////////////// #include <mios32.h> #include "app.h" #include "mios32_config.h" ///////////////////////////////////////////////////////////////////////////// // Translate a DAW CC string from a Juno 106 SysEx string on a destination port ///////////////////////////////////////////////////////////////////////////// void Translate_CC_SysEx(mios32_midi_package_t midi_package, mios32_midi_port_t port) { static u8 stream_sysex[7]; // convert CC:USB0 -> Sysex:UART0 : translate CC to SysEx if( midi_package.type == 0xb){ // define sysex stream stream_sysex[0] = 0xf0; // header stream_sysex[1] = 0x41; // Roland stream_sysex[2] = 0x32; // Juno 106 Control mode stream_sysex[3] = midi_package.evnt0 & 0x0f; // midi channel : 0n stream_sysex[4] = midi_package.evnt1 - CC_Offset; // Control number stream_sysex[5] = midi_package.evnt2; // Control value stream_sysex[6] = 0xf7; // EOX // send stream to midi out1 MIOS32_MIDI_SendSysEx(port, stream_sysex, 7); //MIOS32_MIDI_SendSysEx(USB0, stream_sysex, 7); // DEBUG :°) } } ///////////////////////////////////////////////////////////////////////////// // Translate a Juno SysEx string from a midi port to a Control change string ///////////////////////////////////////////////////////////////////////////// void Translate_SysEx_CC(mios32_midi_port_t port, mios32_midi_package_t midi_package) { static u8 editbufferstatus; static u8 midi_channel; static u8 cc_param; static u8 cc_value; // static u8 patch_param[24]; // 24 bytes for a patch static u8 bank_patch_number; // for PC static u8 patch_value[24]; // Header + midi channel + PgChg + 18 values of controller + EOX // convert Sysex:UART0 -> CC:USB0 & CC:UART1 switch(editbufferstatus){ unsigned char i; // for the loop case 0: // Juno 106 Header // Control mode if( midi_package.type == 0x4 && midi_package.evnt0 == 0xf0 && midi_package.evnt1 == 0x41 && midi_package.evnt2 == 0x32){ #if DEBUG MIOS32_MIDI_SendCC(USB0, 15, 50, 50); #endif editbufferstatus = 1; } // Patch mode else if( midi_package.type == 0x4 && midi_package.evnt0 == 0xf0 && midi_package.evnt1 == 0x41 && midi_package.evnt2 == 0x30){ #if DEBUG MIOS32_MIDI_SendCC(USB0, 15, 40, 40); #endif editbufferstatus = 30; //editbufferstatus = 4; } // Manual mode else if( midi_package.type == 0x4 && midi_package.evnt0 == 0xf0 && midi_package.evnt1 == 0x41 && midi_package.evnt2 == 0x31){ #if DEBUG MIOS32_MIDI_SendCC(USB0, 15, 30, 30); #endif editbufferstatus = 40; //editbufferstatus = 4; } else editbufferstatus = 0; break; case 1: // 2nd block (3 bytes) : Control if( midi_package.type == 0x4) { midi_channel = midi_package.evnt0; // CC 1st byte cc_param = midi_package.evnt1; // CC 2nd byte (+2 avoid pb with bender) cc_value = midi_package.evnt2; // CC 3rd byte #if DEBUG MIOS32_MIDI_SendCC(USB0, 15, 60, 60); // debug OK #endif editbufferstatus = 2; } else editbufferstatus = 0; break; case 2: // EOX Control if( midi_package.type == 0x5 && midi_package.evnt0 == 0xF7){ MIOS32_MIDI_SendCC(USB0, midi_channel, cc_param + CC_Offset, cc_value); // USB Port MIOS32_MIDI_SendCC(UART1, midi_channel, cc_param + CC_Offset, cc_value); // Midi Out2 Port #if DEBUG MIOS32_MIDI_SendCC(USB0, 15, 70, 70); // debug OK :) #endif editbufferstatus = 0; } else editbufferstatus = 0; break; case 30: // blocks patch 0n pp dd if(midi_package.type == 0x04){ patch_value[3] = midi_package.evnt0; // midi channel patch_value[4] = midi_package.evnt1; // bank patch number patch_value[5] = midi_package.evnt2; // ctrl 01 LFO Rate // notice that : midi_channel = patch_value[3]; bank_patch_number = patch_value[4]; // send PC over USB et midi out2 MIOS32_MIDI_SendProgramChange(USB0, midi_channel, bank_patch_number); MIOS32_MIDI_SendProgramChange(UART1, midi_channel, bank_patch_number); // next step editbufferstatus = 31; } else editbufferstatus = 0; break; case 31: // blocks patch dd dd dd if(midi_package.type == 0x04){ patch_value[6] = midi_package.evnt0; // ctrl 02 LFO delay time patch_value[7] = midi_package.evnt1; // ctrl 03 DCO LFO patch_value[8] = midi_package.evnt2; // ctrl 04 DCO PWM // next step editbufferstatus = 32; } else editbufferstatus = 0; break; case 32: // blocks patch dd dd dd if(midi_package.type == 0x04){ patch_value[9] = midi_package.evnt0; // ctrl 05 DCO noise patch_value[10] = midi_package.evnt1; // ctrl 06 VCF Freq patch_value[11] = midi_package.evnt2; // ctrl 07 VCF Res // next step editbufferstatus = 33; } else editbufferstatus = 0; break; case 33: // blocks patch dd dd dd if(midi_package.type == 0x04){ patch_value[12] = midi_package.evnt0; // ctrl 08 VCF env patch_value[13] = midi_package.evnt1; // ctrl 09 VCF LFO patch_value[14] = midi_package.evnt2; // ctrl 10 BCF kbd // next step editbufferstatus = 34; } else editbufferstatus = 0; break; case 34: // blocks patch dd dd dd if(midi_package.type == 0x04){ patch_value[15] = midi_package.evnt0; // ctrl 11 VCA Level patch_value[16] = midi_package.evnt1; // ctrl 12 Env A patch_value[17] = midi_package.evnt2; // ctrl 13 Env D // next step editbufferstatus = 35; } else editbufferstatus = 0; break; case 35: // blocks patch dd dd dd if(midi_package.type == 0x04){ patch_value[18] = midi_package.evnt0; // ctrl 14 Env S patch_value[19] = midi_package.evnt1; // ctrl 15 Env R patch_value[20] = midi_package.evnt2; // ctrl 16 DCO Sub // next step editbufferstatus = 36; } else editbufferstatus = 0; break; case 36: // blocks patch dd dd F7 if(midi_package.type == 0x07){ patch_value[21] = midi_package.evnt0; // ctrl 17 Switches 1 patch_value[22] = midi_package.evnt1; // ctrl 18 Switches 2 patch_value[23] = midi_package.evnt2; // ctrl EOX /* // send PC over USB et midi out2 MIOS32_MIDI_SendProgramChange(USB0, midi_channel, bank_patch_number); MIOS32_MIDI_SendProgramChange(UART1, midi_channel, bank_patch_number); */ // send the patch param via CC for(i=5; i < 23; i++){ MIOS32_MIDI_SendCC(USB0, midi_channel, (i-5)+CC_Offset, patch_value[i]); MIOS32_MIDI_SendCC(UART1, midi_channel, (i-5)+CC_Offset, patch_value[i]); editbufferstatus = 0; } // return to start editbufferstatus = 0; } else editbufferstatus = 0; break; case 40: // blocks MANUAL 0n pp dd !NO PROGRAM CHANGE! if(midi_package.type == 0x04){ patch_value[3] = midi_package.evnt0; // midi channel patch_value[4] = midi_package.evnt1; // bank patch number patch_value[5] = midi_package.evnt2; // ctrl 01 LFO Rate // notice that : midi_channel = patch_value[3]; bank_patch_number = patch_value[4]; // DON'T send PC over USB et midi out2 //MIOS32_MIDI_SendProgramChange(USB0, midi_channel, bank_patch_number); //MIOS32_MIDI_SendProgramChange(UART1, midi_channel, bank_patch_number); // next step editbufferstatus = 31; } else editbufferstatus = 0; break; case 4 : // end of Blocks break; } } ///////////////////////////////////////////////////////////////////////////// // This hook is called after startup to initialize the application ///////////////////////////////////////////////////////////////////////////// void APP_Init(void) { // initialize all LEDs MIOS32_BOARD_LED_Init(0xffffffff); } ///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { /* // endless loop while( 1 ) { // toggle the state of all LEDs (allows to measure the execution speed with a scope) MIOS32_BOARD_LED_Set(0xffffffff, ~MIOS32_BOARD_LED_Get()); } */ } ///////////////////////////////////////////////////////////////////////////// // This hook is called when a MIDI package has been received ///////////////////////////////////////////////////////////////////////////// void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package) { // toggle Status LED on each incoming MIDI package MIOS32_BOARD_LED_Set(1, ~MIOS32_BOARD_LED_Get()); #if TERM_DEBUG // send received MIDI package to MIOS Terminal MIOS32_MIDI_SendDebugMessage("Port:%02X Type:%X Evnt0:%02X Evnt1:%02X Evnt2:%02X\n", port, midi_package.type, midi_package.evnt0, midi_package.evnt1, midi_package.evnt2); #endif // forward USB0->UART0 and UART0->USB0 switch( port ) { case USB0: // convert CC:USB0 -> Sysex:UART0 : translate CC to SysEx Translate_CC_SysEx(midi_package, UART0); MIOS32_MIDI_SendPackage( UART0, midi_package); // forward all messages break; case UART1: // convert CC:UART1 -> Sysex:UART0 : translate CC to SysEx Translate_CC_SysEx(midi_package, UART0); MIOS32_MIDI_SendPackage( UART0, midi_package); // forward all messages break; case UART0: // translate sysex Translate_SysEx_CC( port, midi_package); // passthrough midi messages except SysEx if (midi_package.type > 0x7 && midi_package.type < 0xf) // all except SysEx MIOS32_MIDI_SendPackage(USB0, midi_package); // USB Port MIOS32_MIDI_SendPackage(UART1, midi_package); // Midi Out2 Port break; } } Juno_106_Translator_v1.0.zip Edited December 4, 2011 by julienvoirin 1 Quote Link to comment Share on other sites More sharing options...
cit Posted December 2, 2011 Report Share Posted December 2, 2011 wow nice. i have no clue to programm codes like this but this is verry nice. i whis i had this for my juno1 and live :-) Quote Link to comment Share on other sites More sharing options...
julienvoirin Posted December 2, 2011 Author Report Share Posted December 2, 2011 juno1 and live :-) next step but i need to create a control surface first Quote Link to comment Share on other sites More sharing options...
jojjelito Posted December 3, 2011 Report Share Posted December 3, 2011 Brilliance! Combine the above with a control surface and we get Sysex to the MKS-50/JU-1/2 etc plus CCs to anything reasonably modern :flowers: This could be full of so much win. Quote Link to comment Share on other sites More sharing options...
julienvoirin Posted December 4, 2011 Author Report Share Posted December 4, 2011 (edited) Brilliance! Combine the above with a control surface and we get Sysex to the MKS-50/JU-1/2 etc plus CCs to anything reasonably modern :flowers: This could be full of so much win. I quickly started the new application for my Juno 2 : it converts CC to Alpha Juno2 sysex, as i wanted to know if there is scales effect while moving parameters (I got that on my Oberheim Matrix 1000 and it is shit!). There is no scale effect ! :frantics: so the next step is to build a dedicated control surface. This application does convert Control Change messages to Juno 2 sysex messages so that you can control your synth with a DAW that doesn't support sysex (e.g Ableton live). Connect your Juno to Midi in/out sockets 1 of STM32 and USB to your computer. Midi in/out 2 is the same as USB (e.g to connect to an Akai MPC). See tables below to edit your Juno parameters (CC84 to CC119). Have fun ! PS : Am I right we all posess Juno 106 AND Juno2 ?! /* * Roland Juno 2 SysEx Translator * * =============================================================================== * Copyright (C) 2011 Julien Voirin (julien.voirin@free.fr) * * Licensed for personal non-commercial use only. * All other rights reserved. * * ========================================================================== */ ///////////////////////////////////////////////////////////////////////////// // Include files ///////////////////////////////////////////////////////////////////////////// #include <mios32.h> #include "app.h" #include "mios32_config.h" ///////////////////////////////////////////////////////////////////////////// // Translate a DAW CC string from a Juno 2 SysEx string on a destination port ///////////////////////////////////////////////////////////////////////////// void Translate_CC_SysEx(mios32_midi_package_t midi_package, mios32_midi_port_t port) { static u8 stream_sysex[10]; // convert CC:USB0 -> Sysex:UART0 : translate CC to SysEx if( midi_package.type == 0xb){ // define sysex stream stream_sysex[0] = 0xf0; // header stream_sysex[1] = 0x41; // Roland stream_sysex[2] = 0x36; // Juno 2 in Individual Tone Parameters mode stream_sysex[3] = midi_package.evnt0 & 0x0f; // midi channel : 0n stream_sysex[4] = 0x23; // format type stream_sysex[5] = 0x20; // unknown stream_sysex[6] = 0x01; // unknown stream_sysex[7] = midi_package.evnt1 - CC_Offset; // Parameter number stream_sysex[8] = midi_package.evnt2; // Parameter value stream_sysex[9] = 0xf7; // EOX // send stream to midi out1 MIOS32_MIDI_SendSysEx(port, stream_sysex, 10); //MIOS32_MIDI_SendSysEx(USB0, stream_sysex, 7); // DEBUG :°) } } ///////////////////////////////////////////////////////////////////////////// // This hook is called after startup to initialize the application ///////////////////////////////////////////////////////////////////////////// void APP_Init(void) { // initialize all LEDs MIOS32_BOARD_LED_Init(0xffffffff); } ///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { /* // endless loop while( 1 ) { // toggle the state of all LEDs (allows to measure the execution speed with a scope) MIOS32_BOARD_LED_Set(0xffffffff, ~MIOS32_BOARD_LED_Get()); } */ } ///////////////////////////////////////////////////////////////////////////// // This hook is called when a MIDI package has been received ///////////////////////////////////////////////////////////////////////////// void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package) { // toggle Status LED on each incoming MIDI package MIOS32_BOARD_LED_Set(1, ~MIOS32_BOARD_LED_Get()); #if TERM_DEBUG // send received MIDI package to MIOS Terminal MIOS32_MIDI_SendDebugMessage("Port:%02X Type:%X Evnt0:%02X Evnt1:%02X Evnt2:%02X\n", port, midi_package.type, midi_package.evnt0, midi_package.evnt1, midi_package.evnt2); #endif // forward USB0->UART0 and UART0->USB0 switch( port ) { case USB0: // convert CC:USB0 -> Sysex:UART0 : translate CC to SysEx Translate_CC_SysEx(midi_package, UART0); MIOS32_MIDI_SendPackage( UART0, midi_package); // forward all messages break; case UART1: // convert CC:UART1 -> Sysex:UART0 : translate CC to SysEx Translate_CC_SysEx(midi_package, UART0); MIOS32_MIDI_SendPackage( UART0, midi_package); // forward all messages break; case UART0: // translate sysex from Juno to CC : not yet implemented //Translate_SysEx_CC( port, midi_package); // passthrough midi messages except SysEx if (midi_package.type > 0x7 && midi_package.type < 0xf) // all except SysEx MIOS32_MIDI_SendPackage(USB0, midi_package); // USB Port MIOS32_MIDI_SendPackage(UART1, midi_package); // Midi Out2 Port break; } } Juno_2_SysEx_Translator_v0.1.zip Edited December 4, 2011 by julienvoirin Quote Link to comment Share on other sites More sharing options...
Sebo Posted December 8, 2011 Report Share Posted December 8, 2011 I have a Juno-106, a Juno-1 and a Matrix-1000, but no experience with MIOS 32, I have make a board, or two... Thank you. Quote Link to comment Share on other sites More sharing options...
julienvoirin Posted June 26, 2012 Author Report Share Posted June 26, 2012 (edited) here is the final applications moreover i did a controller on arduino/ethernet/wifi and iPad/touchOSC for Roland Juno2 ARDUINO CODE for Juno2 sysex translator : ////////////////////////////////////////////////////////////////////// // OSCClass iOSC(iPhone App) test sketch // OSCClass version 1.0.1 (Arduino ver0014) // Copyright (c) recotana(http://recotana.com). All right reserved. ////////////////////////////////////////////////////////////////////// /* TouchOSC is OSCsend Application for iPad OSC setting example : OSCMessage type value on off button1 /Juno2/button_name float 1 0 :info-AlternateMode "ON" = toggle sw slider1 /Juno2/button_name float 1 0 Arduino setting IP address 192.168.1.10 , incoming port : 8000 (server) Arduino setting IP address 192.168.1.10 , outgoing port : 8008 iPad setting IP address 192.168.1.4 , incoming port : 8008 (client) iPad setting IP address 192.168.1.4 , outgoing port : 8000 Parameters on the Juno2 : I. First scroll through the MIDI menu and turn Exclusive Messages ON. II. These are the components of the system exclusive message: F0 [Exclusive] 41 [Roland ID#] 36 [Individual Tone Parameters] 0N [N=MIDI channel (N=0-F, Chan 1=00 Chan 16=0F)] 23 [Format type] 20 [unknown] 01 [unknown] XX [Parameter number (0-23)] see table below YY [Value (0-127)] Can be left at 00 F7 [End of Exclusive] III. Here is an example: A SysEx message for editing the VCF Resonance Parameter on MIDI channel 1: F0 41 36 00 23 20 01 11 00 F7 "11" Is the SysEx code for the VCF Resonance edit parameter. "00" Is the SysEx code for the variable start value of the current edit parameter. Parameter Numbers (XX) For The Alpha Juno Synths: 37 parameters (Parentheses indicated range of variable values 'YY' possible for the parameter.) CODE (XX) EDIT PARAMETER COMPLETE SYSEX CODE CC# 00 DCO Env. Mode (0=Normal, 1=Inverted, 2=Normal-Dynamic, 3=Inv.-Dynamic) F0 41 36 00 23 20 01 00 00 F7 84 01 VCF Env. Mode (0=Normal, 1=Inverted, 2=Normal-Dynamic, 3=Dynamic) F0 41 36 00 23 20 01 01 00 F7 85 02 VCA Env. Mode (0=Normal, 1=Gate, 2=Normal-Dynamic, 3=Gate-Dynamic) F0 41 36 00 23 20 01 02 00 F7 86 03 DCO Wave Pulse (0..3) F0 41 36 00 23 20 01 03 00 F7 87 04 DCO Wave Saw (0..5) F0 41 36 00 23 20 01 04 00 F7 88 05 DCO Wave Sub (0..5) F0 41 36 00 23 20 01 05 00 F7 89 06 DCO Range (0=4', 1=8', 2=16', 3=32') F0 41 36 00 23 20 01 06 00 F7 90 07 DCO Sub Level (0..3) F0 41 36 00 23 20 01 07 00 F7 91 08 DCO Noise (0..3) F0 41 36 00 23 20 01 08 00 F7 92 09 HPF Cutoff (0..3) F0 41 36 00 23 20 01 09 00 F7 93 0A Chorus Switch (0=Off, 1=On) F0 41 36 00 23 20 01 0A 00 F7 94 0B DCO LFO Mod. (0..7F) F0 41 36 00 23 20 01 0B 00 F7 95 0C DCO ENV Mod. (0..7F) F0 41 36 00 23 20 01 0C 00 F7 96 0D DCO After Mod. (0..7F) F0 41 36 00 23 20 01 0D 00 F7 97 0E DCO PWM Depth (0..7F) F0 41 36 00 23 20 01 0E 00 F7 98 0F DCO PWM Rate (0..7F) 0 = Pulse Width Manual 1..7F = PW LFO Rate F0 41 36 00 23 20 01 0F 00 F7 99 10 VCF Cutoff (0..7F) F0 41 36 00 23 20 01 10 00 F7 100 11 VCF Resonance (0..7F) F0 41 36 00 23 20 01 11 00 F7 101 12 VCF LFO Mod. (0..7F) F0 41 36 00 23 20 01 12 00 F7 102 13 VCF ENV Mod. (0..7F) F0 41 36 00 23 20 01 13 00 F7 103 14 VCF Key Follow (0..7F) F0 41 36 00 23 20 01 14 00 F7 104 15 VCF Aftertouch (0..7F) F0 41 36 00 23 20 01 15 00 F7 105 16 VCA Level (0..7F) F0 41 36 00 23 20 01 16 00 F7 106 17 VCA Aftertouch (0..7F) F0 41 36 00 23 20 01 17 00 F7 107 18 LFO Rate (0..7F) F0 41 36 00 23 20 01 18 00 F7 108 19 LFO Delay (0..7F) F0 41 36 00 23 20 01 19 00 F7 109 1A ENV T1 (0..7F) Attack Time F0 41 36 00 23 20 01 1A 00 F7 110 1B ENV L1 (0..7F) Attack Level F0 41 36 00 23 20 01 1B 00 F7 111 1C ENV T2 (0..7F) Break Time F0 41 36 00 23 20 01 1C 00 F7 112 1D ENV L2 (0..7F) Break Level F0 41 36 00 23 20 01 1D 00 F7 113 1E ENV T3 (0..7F) Decay Time F0 41 36 00 23 20 01 1E 00 F7 114 1F ENV L3 (0..7F) Sustain Level F0 41 36 00 23 20 01 1F 00 F7 115 20 ENV T4 (0..7F) Release Time F0 41 36 00 23 20 01 20 00 F7 116 21 ENV Key Follow (0..78) F0 41 36 00 23 20 01 21 00 F7 117 22 Chorus Rate (0..7F) F0 41 36 00 23 20 01 22 00 F7 118 23 Bender Range (0..C) F0 41 36 00 23 20 01 23 00 F7 119 */ #include "Ethernet.h" #include <OSCClass_018.h> #include "MIDI.h" #define _POT_DEBUG_ 0 // set to 1 to debug with pot #define LED_PWM 6 // red led of midi shield #define POT_PIN 0 #define SW_PIN 3 #define note_offset 36 #define midi_channel 1 OSCMessage recMes; OSCMessage sendMes; OSCClass osc(&recMes); // server cfg (arduino) byte serverMac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; byte serverIp[] = { // arduino IP 192, 168, 0, 13 }; int serverPort = 8000; // outgoing from iPad, incoming to arduino // byte gateway[] = { 192, 168, 1, 2 }; // byte subnet[] = { 255, 255, 255, 0 }; // client cfg byte destIp[] = { 192, 168, 0, 19}; // iPad IP int destPort = 8008; // outgoing from arduino, incoming to iPad char *Juno2_OSC_name[3] = { "/jun", "/note", "/ctrl" }; char *Juno2_OSC_param_name[37] = { // 36 parameters "/DCO_Env_Mode", // $00 "/VCF_Env_Mode", // $01 "/VCA_Env_Mode", // $02 "/DCO_Wave_Pulse", // $03 "/DCO_Wave_Saw", // $04 "/DCO_Wave_Sub", // $05 "/DCO_Range", // $06 "/DCO_Sub_Level", // $07 "/DCO_Noise_Level",// $08 "/HPF_CutOff", // $09 "/Chorus_Switch", // $0a "/DCO_Lfo_Mod", // $0b "/DCO_Env_Mod", // $0c "/DCO_After_Mod", // $0d "/DCO_Pwm_Depth", // $0e "/DCO_Pwm_Rate", // $0f "/VCF_CutOff", // $10 d16 "/VCF_Resonance", // $11 "/VCF_Lfo_Mod", // $12 "/VCF_Env_Mod", // $13 "/VCF_Key_Follow", // $14 "/VCF_Aftertouch", // $15 "/VCA_Level", // $16 "/VCA_Aftertouch", // $17 "/LFO_Rate", // $18 "/LFO_Delay", // $19 "/ENV_T1", // $1a "/ENV_L1", // $1b "/ENV_T2", // $1c "/ENV_L2", // $1d "/ENV_T3", // $1e "/ENV_L3", // $1f "/ENV_T4", // $20 "/ENV_Key_Follow", // $21 "/Chorus_Rate", // $22 "/Bender_Range", // $23 }; // Arrays of patch parameters values byte Juno2_SysEx_Patch_APR[54]; // whole patch byte Juno2_SysEx_Patch_IPR[10]; // single parameter char *midi_note[12] = { "/key_0", "/key_1", "/key_2", "/key_3", "/key_4", "/key_5", "/key_6", "/key_7", "/key_8", "/key_9", "/key_10", "/key_11",/* "/key_12", "/key_13", "/key_14", "/key_15", "/key_16", "/key_17", "/key_18", "/key_19", "/key_20", "/key_21", "/key_22", "/key_23", "/key_24", "/key_25", "/key_26", "/key_27", "/key_28", "/key_29", "/key_30", "/key_31", "/key_32", "/key_33", "/key_34", "/key_35", "/key_36", "/key_37", "/key_38", "/key_39", "/key_40", "/key_41", "/key_42", "/key_43", "/key_44", "/key_45", "/key_46", "/key_47", "/key_48", "/key_49", */ }; // pot, led & switch flags boolean ledFlag; boolean swFlag; long oldPotValue; ////////////////////////////////////////////////// // Init ////////////////////////////////////////////////// void setup() { // set midi baudsrate // Serial.begin(31250); // old method without midi.h --> don't use // Serial.print("reset"); // Initiate MIDI communications, listen to all channels MIDI.begin(MIDI_CHANNEL_OMNI); // Connect the HandleSysex function to the library, so it is called upon reception of a sysex. MIDI.setHandleSystemExclusive(HandleSystemExclusive); // Put only the name of the function Ethernet.begin(serverMac ,serverIp); // Ethernet.begin(serverMac ,serverIp ,gateway ,subnet); // setting osc recieve server osc.begin(serverPort); // init osc send < --- pose pb si logMessage est compilé sendMes.setIp( destIp ); sendMes.setPort( destPort ); // LED OFF pinMode(LED_PWM, OUTPUT); digitalWrite(LED_PWM, HIGH); // switch and pot pinMode(SW_PIN, INPUT); ledFlag = false; swFlag = false; analogReference(DEFAULT); oldPotValue = (long)analogRead(POT_PIN); // osc message buffer clear osc.flush(); } ///////////////////////////////////////////////////// // Mainloop ///////////////////////////////////////////////////// void loop() { // osc arrive check if ( osc.available() ){ OSC_SYSEX(); OSC_NOTE(recMes); } else{ // } // midi arrive check if (MIDI.read()) { // Is there a MIDI message incoming ? switch(MIDI.getType()) { // Get the type of the message we caught case SystemExclusive: // If it is a sysex SYSEX_OSC( MIDI.getData1(), MIDI.getSysExArray() ); // call SYSEX_OSC function break; // See the online reference for other message types default: break; } } #ifdef _POT_DEBUG_ // pot active send VCF CutOff POT_OSC(); #endif } ///////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////// void HandleSystemExclusive(byte *array, byte size) { } /////////////////////////////////////////////////////// // Convert OSC to Sysex /////////////////////////////////////////////////////// void OSC_SYSEX(void) { // toplevel address matching if( !strcmp( recMes.getAddress(0) , Juno2_OSC_name[0] ) ){ // "/jun" // second level address matching if( !strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[0] ) ){ MIDI_SEND_IPR(0, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[1])){ MIDI_SEND_IPR(1, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[2])){ MIDI_SEND_IPR(2, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[3])){ MIDI_SEND_IPR(3, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[4])){ MIDI_SEND_IPR(4, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[5])){ MIDI_SEND_IPR(5, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[6])){ MIDI_SEND_IPR(6, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[7])){ MIDI_SEND_IPR(7, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[8])){ MIDI_SEND_IPR(8, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[9])){ MIDI_SEND_IPR(9, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[10])){ MIDI_SEND_IPR(10, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[11])){ MIDI_SEND_IPR(11, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[12])){ MIDI_SEND_IPR(12, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[13])){ MIDI_SEND_IPR(13, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[14])){ MIDI_SEND_IPR(14, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[15])){ MIDI_SEND_IPR(15, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[16])){ MIDI_SEND_IPR(16, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[17])){ MIDI_SEND_IPR(17, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[18])){ MIDI_SEND_IPR(18, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[19])){ MIDI_SEND_IPR(19, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[20])){ MIDI_SEND_IPR(20, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[21])){ MIDI_SEND_IPR(21, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[22])){ MIDI_SEND_IPR(22, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[23])){ MIDI_SEND_IPR(23, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[24])){ MIDI_SEND_IPR(24, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[25])){ MIDI_SEND_IPR(25, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[26])){ MIDI_SEND_IPR(26, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[27])){ MIDI_SEND_IPR(27, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[28])){ MIDI_SEND_IPR(28, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[29])){ MIDI_SEND_IPR(29, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[30])){ MIDI_SEND_IPR(30, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[31])){ MIDI_SEND_IPR(31, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[32])){ MIDI_SEND_IPR(32, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[33])){ MIDI_SEND_IPR(33, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[34])){ MIDI_SEND_IPR(34, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[35])){ MIDI_SEND_IPR(35, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[36])){ MIDI_SEND_IPR(36, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[37])){ MIDI_SEND_IPR(37, recMes.getArgFloat(0)); } else if(!strcmp( recMes.getAddress(1) , Juno2_OSC_param_name[37])){ MIDI_SEND_IPR(37, recMes.getArgFloat(0)); } else{ // rien } } else if( !strcmp( recMes.getAddress(0) , Juno2_OSC_name[1] ) ){ // Note On OSC message } else{ // to complete } } ////////////////////////////////////////////////////////////// // Send Juno2 SysEx string ////////////////////////////////////////////////////////////// void MIDI_SEND_IPR( char osc_param_name, double osc_param_value) { //byte sysex_param_value = (byte)osc_param_value; // transform that shit ! // visual feedback LED analogWrite(LED_PWM, floor(255 - osc_param_value)); // set IPR sysex bytes : F0 41 36 00 23 20 01 name value F7 Juno2_SysEx_Patch_IPR[0] = 0xf0; Juno2_SysEx_Patch_IPR[1] = 0x41; Juno2_SysEx_Patch_IPR[2] = 0x36; Juno2_SysEx_Patch_IPR[3] = 0x00; Juno2_SysEx_Patch_IPR[4] = 0x23; Juno2_SysEx_Patch_IPR[5] = 0x20; Juno2_SysEx_Patch_IPR[6] = 0x01; Juno2_SysEx_Patch_IPR[7] = (byte)osc_param_name; Juno2_SysEx_Patch_IPR[8] = (byte)osc_param_value; // sysex_param_value Juno2_SysEx_Patch_IPR[9] = 0xf7; // send 10 bytes sysex array, including F0 & F7 (true) MIDI.sendSysEx( 10, Juno2_SysEx_Patch_IPR, true ); // ça marche :) } /////////////////////////////////////////////////////// // convert SYSEX in OSC /////////////////////////////////////////////////////// void SYSEX_OSC( byte size, byte *sysex_array ) { // if it is a 54 bytes sysex string = APR if (size == 54){ for (char i=0; i<55; i++) Juno2_SysEx_Patch_APR[i] = sysex_array[i]; // extract param values from sysex // convert APR to 38xIPR message for (char p=0; p<39; p++){ sendMes.setTopAddress(Juno2_OSC_name[0]); // "/jun" sendMes.setSubAddress( (char*)Juno2_OSC_param_name[p] ); // e.g "/VCF_CutOff" float f = sysex_array[ 7 + p ] + 0.000; // transform to float shit sendMes.setArgs( "f", &(f) ); osc.sendOsc( &sendMes ); delay(10); // small delay to see faders moving ;) } } // if it is a 38 bytes sysex string = not implemented else if (size == 38){ // do stuff } // if it is a 10 bytes sysex string = IPR else if (size == 10){ // transform array for (char j=0; j<11; j++) Juno2_SysEx_Patch_IPR[j] = sysex_array[j]; //OSC send IPR sendMes.setTopAddress(Juno2_OSC_name[0]); // "/jun" sendMes.setSubAddress( (char*)Juno2_OSC_param_name[Juno2_SysEx_Patch_IPR[7]] ); // e.g "//VCF_CutOff" float f = Juno2_SysEx_Patch_IPR[8] + 0.000; // convert in float sendMes.setArgs( "f", &(f) ); // e.g "120." osc.sendOsc( &sendMes ); } } #ifdef _POT_DEBUG_ //////////////////////////////////////////////////// // Convert POT to OSC VCF_CutOff message ///////////////////////////////////////////////////// void POT_OSC(void) { int pot=analogRead(POT_PIN); //adc data = 10bit data long value = (long)(pot >> 3); // 1024 -> 127 if( oldPotValue != value ){ sendMes.setTopAddress(Juno2_OSC_name[0]); sendMes.setSubAddress(Juno2_OSC_param_name[16] ); // "/jun/VCF_CutOff" sendMes.setArgs( "i", &value ); osc.sendOsc( &sendMes ); // Serial.print("pot:"); // Serial.println(value); } oldPotValue = value; } #endif //////////////////////////////////////////////////// // Convert OSC Note message ///////////////////////////////////////////////////// void OSC_NOTE(OSCMessage recMes) { // toplevel address matching if( !strcmp( recMes.getAddress(0) , Juno2_OSC_name[1] ) ){ // "/note" // second level address matching for(char k=0; k<12; k++){ if( !strcmp( recMes.getAddress(1) , midi_note[k] ) ){ MIDI.sendNoteOn((byte)( k + note_offset), (byte)recMes.getArgFloat(0), midi_channel); //MIDI.sendNoteOn((byte)(i + 60), (byte)recMes.getArgFloat(0), 1); } } } } ////////////////////////////////////////////////////// //// Send Note from OSC /////////////////////////////////////////////////////// //void MIDI_SEND_NOTE(long note, double velocity) //{ // MIDI.sendNoteOn((byte)note, (byte)velocity, 1); //}Juno_106_Translator_v1.1.zip Edited June 26, 2012 by julienvoirin Quote Link to comment Share on other sites More sharing options...
bastadave Posted September 4, 2014 Report Share Posted September 4, 2014 Hey Julien, Big thanks for that stuff.. i was searching for it since a while.. now i just have to find how to compile the code... any idea ? ;) Best Regards, Dave Quote Link to comment Share on other sites More sharing options...
Phatline Posted October 14, 2016 Report Share Posted October 14, 2016 yes that helps ,thx Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.