electro-music.com   Dedicated to experimental electro-acoustic
and electronic music
 
    Front Page  |  Radio
 |  Media  |  Forum  |  Wiki  |  Links
Forum with support of Syndicator RSS
 FAQFAQ   CalendarCalendar   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   LinksLinks
 RegisterRegister   ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in  Chat RoomChat Room 
go to the radio page Live at electro-music.com radio 1 Please visit the chat
  host / artist show at your time
today> Twyndyllyngs - not canceled Chez Mosc
 Forum index » Instruments and Equipment » Chameleon
programming the Chameleon help me on the way
Post new topic   Reply to topic
Page 1 of 2 [30 Posts]
View unread posts
View new posts in the last week
Mark the topic unread :: View previous topic :: View next topic
Goto page: 1, 2 Next
Author Message
arpeggio



Joined: Jan 05, 2010
Posts: 24
Location: the Netherlands

PostPosted: Sun Jun 07, 2015 9:30 am    Post subject: programming the Chameleon help me on the way
Subject description: audio to midi out CC message
Reply with quote  Mark this post and the followings unread

Hello everybody Chameleon fans, i am trying to program the Chameleon,
Basic works good' sending to Chameleon.
Modifying the Levelmeter program to send also send a midi CC message
So i can control a midi synth with the Level of the guitar,
Can someone help me how to combine a midi message out with the Level meter program,
Thanks in advence, Dian from the Netherlands
Back to top
View user's profile Send private message
DrJustice



Joined: Sep 13, 2004
Posts: 2112
Location: Morokulien
Audio files: 4

PostPosted: Sun Jun 07, 2015 12:53 pm    Post subject: Reply with quote  Mark this post and the followings unread

It's many years since I last programmed for the Chameleon, but after a quick dive into some old sources and little editing, the following (untested!) two functions might be useful.

The first one, initialize_midi(), must be called once when you initialize your soundskin. The second is a general function for sending MIDI CC messages.

E.g. to control the volume of the synth, setting the sound on channel 1 to half volume, you'd use MIDI control change 7 (Channel volume), like this:

Code:
  transmit_control_change( 1, 7,  64  );


You'll have to scale the value from the level meter to the MIDI control value range of 0-127. I'm sure you'll be able to figure out that bit.

Also remember to pace your MIDI messages, i.e. in general, don't send messages more often than every few milliseconds.

Code:

short midi_ref;  // a global MidiShare handle

int initialize_midi( void )
{
  midi_ref = MidiOpen( "V1_MIDI" );
  if( !midi_ref )
    {
      TRACE( "MIDI: MidiOpen() error\n" );
      return -1;
    }
  MidiConnect( 0, midi_ref, TRUE );   //  connect receiver
  MidiConnect( midi_ref, 0, TRUE );   //  connect transmitter
}

void transmit_control_change( int channel, int controller_no, int value  )
{
  MidiEvPtr ev;
  ev = MidiNewEv( typeCtrlChange );
  Chan( ev ) = channel;
  MidiSetField( ev, 0, controller_no );
  MidiSetField( ev, 1, value );
  MidiSendIm( midi_ref, ev );
}
Back to top
View user's profile Send private message Visit poster's website
arpeggio



Joined: Jan 05, 2010
Posts: 24
Location: the Netherlands

PostPosted: Sun Jun 07, 2015 3:51 pm    Post subject: Reply with quote  Mark this post and the followings unread

Wow man this is a lot more complicated than Arduino and a little Cplus,
This is as much i already kwow from my reading, and digging in the Chameleon knoledge base, trying the understand the way i, one has to write program pices, and combine everything together in a program as a hole.
But the way of understanding is the same, know what you want and get the right ingredients and put them in the precice order.
I try it in a few days and let you know, have to find a place to put the void that sends the midi message, find the value from the dsp level to use and indeed i can find a way to scale the values to eachother.
Thanks, Dian
Back to top
View user's profile Send private message
DrJustice



Joined: Sep 13, 2004
Posts: 2112
Location: Morokulien
Audio files: 4

PostPosted: Sun Jun 07, 2015 4:51 pm    Post subject: Reply with quote  Mark this post and the followings unread

It's not as complicated as one might first think Smile

Once you have those two functions included in your program, you can "forget about them", and just use a single statement:
Code:
transmit_control_change( 1, 7,  64  );

each time you want to send a MIDI CC.

Regarding the scaling and where to put things; if you're using the original Chameleon level meter example, you should find on line 296:
Code:
level_L >>= 12;

That makes the variable "level_L" a 12 bit representation of the level for the left channel. To scale that to a 7 bit MIDI CC value, we just need to shift that value 5 more bits down (same as dividing by 32), like this, e.g. assigning the result to a new integer variable "midi_level_L":
Code:
int midi_level_L = level_L >> 5;

Then you can simply do:
Code:
transmit_control_change( 1, 7, midi_level_L  );

A bit of good news is that as you can see on line 288, the main loop there runs at 20 milli second intervals, so the pacing of data is already taken care of.


In practice, you can just add a single line after line 296, looking like this:
Code:
transmit_control_change( 1, 7, level_L >> 5  );

And that's all! The Chameleon will now send a Channel volume command on MIDI channel 1 every 20ms, with the value of the volume corresponding to the left input level.


FYI: The Chameleon uses MidiShare, which is a very powerful MIDI library. Once you have the two functions from my previous posting in, you could add e.g. a transmit_note_on() function like below. I'm sure you can see the pattern there. When you have the required functions, calling them using a single statement is easy, just like if you use an Arduino library for MIDI.

Code:

void transmit_note_on( int channel, int note_no, int velocity  )
{
  MidiEvPtr ev;
  ev = MidiNewEv( typeKeyOn );
  Chan( ev ) = channel;
  MidiSetField( ev, 0, note_no );
  MidiSetField( ev, 1, velocity );
  MidiSendIm( midi_ref, ev );
}
Back to top
View user's profile Send private message Visit poster's website
arpeggio



Joined: Jan 05, 2010
Posts: 24
Location: the Netherlands

PostPosted: Tue Jun 09, 2015 7:19 am    Post subject: Reply with quote  Mark this post and the followings unread

Hello, the code DrJustice suggested builds well but does not work jet,
This is how i build it up together,
Thanks for your interest and concurn, i apriciate that a lot.
Dian
Code:

/*******************************************************************************
 * C H A M E L E O N    S. D. K.                                               *
 *******************************************************************************
 *  $Archive:: /Chameleon.sdk/src/examples/levelmeter/main.c                   $
 *     $Date:: 14/05/02 17:12                                                  $
 * $Revision:: 4                                                               $
 *-----------------------------------------------------------------------------*
 * This file is part of the Chameleon Software Development Kit                 *
 *                                                                             *
 * Copyright (C) 2001-2002 Soundart                                            *
 * www.soundart-hot.com                                                        *
 * support@soundart-hot.com                                                    *
 ******************************************************************************/


/*
   LEVEL METER application main file.
*/

#include <stdlib>
#include <stdio>
#include <assert>
#include <math>
#include <rtems>
#include <chameleon>
#include <midishare>
#include "lcd.h"
#include "dsp/dsp_code.h"

/******************************************************************************/
#define WORKSPACE_SIZE   128*1024
rtems_unsigned32 rtems_workspace_size = WORKSPACE_SIZE;
rtems_unsigned32 rtems_workspace_start[WORKSPACE_SIZE];
/******************************************************************************/

int      dsp;
int      panel;
rtems_boolean   edit_mode;
rtems_boolean   monitoring_input;


short midi_ref;  // a global MidiShare handle

int initialize_midi( void )
{
midi_ref = MidiOpen( "V1_MIDI" );
  if( !midi_ref )
    {
      TRACE( "MIDI: MidiOpen() error\n" );
      return -1;
    }
  MidiConnect( 0, midi_ref, TRUE );   //  connect receiver
  MidiConnect( midi_ref, 0, TRUE );   //  connect transmitter
}

/*
   Auxiliary functions
*/

void Error(char *error)
{
   TRACE(error);
   rtems_task_delete(RTEMS_SELF);
}


void transmit_control_change( int channel, int controller_no, int value  )
{
  MidiEvPtr ev;
  ev = MidiNewEv( typeCtrlChange );
  Chan( ev ) = channel;
  MidiSetField( ev, 0, controller_no );
  MidiSetField( ev, 1, value );
  MidiSendIm( midi_ref, ev );
}
void start_dsp()
{
   TRACE("Booting DSP...\n");
   dsp = dsp_init(1, dspCode);
   if (!dsp)
      Error("ERROR: cannot access the DSP.\n");
}


/*******************************************************************************

   PANEL TASK      

   Monitors the user actions on the front panel controls

*******************************************************************************/



void panel_redefine_symbols(int panel)
{
   rtems_unsigned8   i;
   for (i=0; i < sizeof(Level_horz_lcd_symbols)/8; i++ )
      if (!panel_out_lcd_redefine(panel, i+1, Level_horz_lcd_symbols[i]))
         Error("ERROR: cannot redefine LCD symbol.\n");
}

void change_monitor_source()
{
   monitoring_input = !monitoring_input;
   
   if (!dsp_write_flag0(dsp, monitoring_input))
      Error("DSP Write Flag Error.\n");

   if (monitoring_input)
      panel_out_lcd_print(panel, 1, 0, "    <Input>    ");
   else
      panel_out_lcd_print(panel, 1, 0, "    <Output>    ");
}

void change_edit_mode()
{

   /*
      Possible edit states:
         - Showing the level meter bars (edit mode off)
         - Changing the level meter source between input or output (edit mode on)
   */

   char   text[17];

   edit_mode = !edit_mode;
   
   if (edit_mode)
   {
      /*  Turn the EDIT led on */
      panel_out_led(panel, PANEL01_LED_EDIT);

      /* Display the edit options */
      panel_out_lcd_print(panel, 0, 0, "   Monitoring   ");

      if (monitoring_input)
         panel_out_lcd_print(panel, 1, 0, "    <Input>    ");
      else
         panel_out_lcd_print(panel, 1, 0, "    <Output>    ");
   }
   else
   {
      /* Turn the EDIT led off */
      panel_out_led(panel, 0);

      /* Show the level meter bars */
      sprintf(text,"%c", 4);
      panel_out_lcd_print(panel, 0, 0, text);

      sprintf(text,"%c", 5);
      panel_out_lcd_print(panel, 1, 0, text);
   }
}

/* The PANEL task itself */

static rtems_task panel_task(rtems_task_argument argument)
{
   static rtems_unsigned32   volume_table[128];
   rtems_unsigned8      potentiometer;
   rtems_unsigned8      value;
   rtems_unsigned32   key_bits;
   rtems_unsigned8      encoder;
   rtems_signed8      increment;
   int         i;
   float         dB;

   /* Initialization */

   edit_mode = FALSE;
   monitoring_input = FALSE;

   TRACE("Starting panel_task...\n");

   /* Fill volume_table with a variable gain from -60 dB to 0dB */
   for (i=0; i<128 ;i++)
   {
      if (i <27>>= 12;
         transmit_control_change( 1, 7, level_L >> 5  );   
         level_L = log10(level_L + 1)/norm;

         /* Extract R value from the readed word */

         level_R = level & 0x00000FFF;
         level_R = log10(level_R + 1)/norm;
         

         if (!edit_mode)
         {
/*
            // Non graphic way to display data:

            sprintf(text,"Level R: %04d",level_R);
            panel_out_lcd_print (panel, 0, 1, text);
            sprintf(text,"Level L: %04d",level_L);
            panel_out_lcd_print (panel, 1, 1, text);
*/
            /* Display the Level Meter data */
            panel_out_lcd_print (panel, 0, 1, Level_horz_lcd_symbol_table[level_R]);
            panel_out_lcd_print (panel, 1, 1, Level_horz_lcd_symbol_table[level_L]);

         }
      }
   }

   /* Should never be here... */
   TRACE("Ending level_meter_task...\n");
   rtems_task_delete(RTEMS_SELF);
}


/* Task specific parameters initialization & task start */

rtems_boolean create_level_meter_task(void)
{
   rtems_id      task_id;
   rtems_status_code   status;

   status = rtems_task_create(
      rtems_build_name('V', 'U', 'M', 'E'),
      60,
      RTEMS_MINIMUM_STACK_SIZE,
      RTEMS_DEFAULT_MODES,
      RTEMS_DEFAULT_ATTRIBUTES,
      &task_id
   );

   if (status != RTEMS_SUCCESSFUL)
      Error("ERROR: cannot create level_meter_task.\n");

   status = rtems_task_start(task_id, level_meter_task, 0);
   if (status != RTEMS_SUCCESSFUL)
      Error("ERROR: cannot start level_meter_task.\n");

   return TRUE;
}

/******************************************************************************
   MAIN TASK      
 ******************************************************************************/

rtems_task rtems_main(rtems_task_argument ignored)
{
   TRACE("******************************************************************************\n");
   TRACE("Audio level meter example\n");
   TRACE("******************************************************************************\n");

   start_dsp();
   create_panel_task();
   create_level_meter_task();

   rtems_task_delete(RTEMS_SELF);
}

The code builds when i save it and load it, no errors and NO warnings
But when i make it or do something (meaningless)in the code it makes warnings:

In function initialize_midi
main.c 54 control reaches end of non-void function
I hope someone gets this warning, Thanks Dian
Back to top
View user's profile Send private message
blue hell
Site Admin


Joined: Apr 03, 2004
Posts: 24544
Location: The Netherlands, Enschede
Audio files: 299
G2 patch files: 320

PostPosted: Tue Jun 09, 2015 9:45 am    Post subject: Reply with quote  Mark this post and the followings unread

initialize_midi only returns a value (-1) when:

(! midi_ref) is true .. so when midi_ref == false, and so the function result is s undefined then ... should prolly add something like

return 0;

just before the last }

that would make the compiler happy, not sure if it would be enough to make you happy ...

_________________
Jan
also .. could someone please turn down the thermostat a bit.
Posted Image, might have been reduced in size. Click Image to view fullscreen.
Back to top
View user's profile Send private message Visit poster's website
DrJustice



Joined: Sep 13, 2004
Posts: 2112
Location: Morokulien
Audio files: 4

PostPosted: Tue Jun 09, 2015 6:17 pm    Post subject: Reply with quote  Mark this post and the followings unread

Yes, Jan is right! Just add a "return 0;" at the end of the "initialize_midi()" function.

As mentioned, that function also needs to be called once when you initialize things. I suggest adding it after "start_dsp();" in the "rtems_main()" function.

However, and more importantly, the source you posted is not the one I was thinking of, or more precisely, it is incomplete/modified/garbled (there are e.g. missing variables and erroneous constructs - it will not compile without many errors).

The original level meter I was thinking about can be found here.

If you use that, then we have a common reference, and the example in my 2nd posting is applicable. Since it only took a couple of minutes to do, I have attached "main.c", modified as discussed in the previous postings. It's still untested, so no guarantees, but that's the principle.

On line 65 and 78, the "initialize_midi()" and "transmit_control_change()" functions have been inserted. I put the "midi_ref" variable on line 40, together with the other global variables.

On line 325 you will see the call that transmits the control changes:
Code:
transmit_control_change( 1, 7, level_L >> 5  );


On line 394 you will see the call to initialize the MIDI sub system:
Code:
initialize_midi();


I hope there are no silly mistakes there (if there are, Jan's eagle eye will spot it... Laughing)

Give it a try Smile


main.c
 Description:
Level Meter example, "main.c", modified as discussed.

Download (listen)
 Filename:  main.c
 Filesize:  9.91 KB
 Downloaded:  960 Time(s)

Back to top
View user's profile Send private message Visit poster's website
blue hell
Site Admin


Joined: Apr 03, 2004
Posts: 24544
Location: The Netherlands, Enschede
Audio files: 299
G2 patch files: 320

PostPosted: Wed Jun 10, 2015 2:55 am    Post subject: Reply with quote  Mark this post and the followings unread

DrJustice wrote:
However, and more importantly, the source you posted is not the one I was thinking of, or more precisely, it is incomplete/modified/garbled (there are e.g. missing variables and erroneous constructs - it will not compile without many errors).


Looks like "Disable HTML in this post" was not in effect (an option below the message composition window).

_________________
Jan
also .. could someone please turn down the thermostat a bit.
Posted Image, might have been reduced in size. Click Image to view fullscreen.
Back to top
View user's profile Send private message Visit poster's website
DrJustice



Joined: Sep 13, 2004
Posts: 2112
Location: Morokulien
Audio files: 4

PostPosted: Wed Jun 10, 2015 3:36 am    Post subject: Reply with quote  Mark this post and the followings unread

You're right again, Jan! Smile

One would have thought that the code tags took care of things, but they don't... I tried a few edit/preview cycles with the source in and out of code tags, and only the "Disable HTML in this post" avoided mangling the source.
Back to top
View user's profile Send private message Visit poster's website
arpeggio



Joined: Jan 05, 2010
Posts: 24
Location: the Netherlands

PostPosted: Wed Jun 10, 2015 10:36 am    Post subject: Reply with quote  Mark this post and the followings unread

Hello again, still trying the put things together, this is the best way the learn for me, try and make things work, thinkening, thanks for the tips and tricks,
and the help, i could not do without it in this languese, it's alot the take care about, but when you get the way off doing things, i will like that,
Anyway, the code builds without errors and no warnings, i had the first put midishare.h in the beginning, but it sends no midi CC messages out, still not.
Does one have to define a MIDIPHYS_IO 0 kind of thing, i read in the midishar docs, or open up something for midi to work,
And i build the levelmeter ELF file in another folder where the levelmeter zip extraction went, so maybe i mangled thing up a bit,
Indeed i used a wrong levelmeter code, the one in debug, and i had to use the one in the src map, so i put it there your main.c file, drJustice, but the Elf file came in debug,
Question: is puting the right adres in the make file a good way to handle this, what. will be a good way the know you put the right thing together,
Or do i make it to complicated for myself, just follow the steps and it will be okay, and the levelmeterMIDI code not working thing lies in another issue,
So thanks again for the help, and i will make a nice code, audio level to midi CC and i can control the volume, or filter intencity level with my guitar playing level, looks very nice
Dian
Back to top
View user's profile Send private message
arpeggio



Joined: Jan 05, 2010
Posts: 24
Location: the Netherlands

PostPosted: Wed Jun 10, 2015 10:44 am    Post subject: midiconnect Reply with quote  Mark this post and the followings unread

What i meant by the midi thing was midiconnect, and make a define for PHYSMIDI_IO 0, that was what i read in the midishare docs,
Maybe this is needed to,
Dian
Back to top
View user's profile Send private message
arpeggio



Joined: Jan 05, 2010
Posts: 24
Location: the Netherlands

PostPosted: Wed Jun 10, 2015 3:43 pm    Post subject: Working audio control to Midi Reply with quote  Mark this post and the followings unread

Hello again, got it working, made a new Elf-file, called it levelmeter1, 2, etc.
This for knowing whats new and finding back things.
Included MidiShare.h, did the PHYSMIDI_IO 0 thing, and ofcource used the good begin code with drJustice thing in it, see above.
Then it sended midi CC 7 to channel 2, midi channels go from 0 to15, changed channel to 0, is 1 for real.
And then the values akt strange, so i changed the >> 5 to >>4, and it got
better but still akting strange, so i put transmit_control_change...etc
after Level_L=log10......etc and use just level_l for value, and it was beter,
And then level_l * 3 for value and that was good, the CC value on the screen in PD moved in the same way the bargraph meter on the Chameleon was moving.
Thanks for all the help and advice, and i will post a midi-file soon for the people who wants to try it out, and play with audio control to midi.
Dian
Back to top
View user's profile Send private message
DrJustice



Joined: Sep 13, 2004
Posts: 2112
Location: Morokulien
Audio files: 4

PostPosted: Thu Jun 11, 2015 4:18 pm    Post subject: Reply with quote  Mark this post and the followings unread

Nice, Dian Smile

You're abolutely right, there should be a
Code:
#include <MidiShare>

at the start of main.c, among the other "#include" - sorry I forgot, that's the drawback of not testing here... Embarassed As for the PHYSMIDI_IO thing, I can't remember having to deal with that. A good thing here is that you're obviously getting some experience and learning more of C/C++, the Chameleon and MIDI thumleft

The idea of using "level_L >> 5" is that it should yield a 7 bit value which has a range of 0-127, the range of a MIDI CC value. If you look at the code below, there's a new integer variable "cc_value" for clarity, and then it is printed out in the debug console using TRACE() (so you need to do a debug build for this). That allows you to look at the actual value that is sent. While it's good that you get it working using the log value, it isn't really right... I suggest you use some TRACE statements and experiment a little bit to see if you can get a value in the range 0-127. I'd love to try the code here, but I don't have a complete setup with the Chami SDK at the moment.

Anyway, you're doing well and you will soon be in full control!

Code:
level_L = level & 0x00FFF000; // use a bit mask to get only bits 12 to 23                                   
level_L >>= 12;               // shift down so it becomes a 12 bit number                     
int cc_value = level_L >> 5;  // shifting 5 more bits down gives a 7 bit number

TRACE("cc value = %d\n", cc_value );

transmit_control_change( 0, 7, cc_value  );                                                       
Back to top
View user's profile Send private message Visit poster's website
arpeggio



Joined: Jan 05, 2010
Posts: 24
Location: the Netherlands

PostPosted: Mon Jun 15, 2015 10:14 am    Post subject: toolkit Reply with quote  Mark this post and the followings unread

Debugging with values for midi CC messages on the screen,
Goes very fast, how can i get the autoscroll to stop and view the values
i will scroll to,
Dian
Back to top
View user's profile Send private message
DrJustice



Joined: Sep 13, 2004
Posts: 2112
Location: Morokulien
Audio files: 4

PostPosted: Tue Jun 16, 2015 4:54 am    Post subject: Reply with quote  Mark this post and the followings unread

You can change the update rate in this line:
Code:
while (rtems_rate_monotonic_period(period_id, 20) != RTEMS_TIMEOUT)

which currently causes an update every 20ms.

However you might miss peak values that last only for a short moment.

So, an alternative solution would be to detect when a front panel button is held down and only output the debug text when that happens. That way you could e.g. press the button at the moment of striking a string to catch the peak without everything scrolling away. This could be done by defining a global variable (near the definition of "midi_ref" and the other globals):
Code:
unsigned int shift_pressed = 0;


Then in the panel_task() function's while() loop, you could add code to track the state of a key, the SHIFT key is used in this example:
Code:

   while (TRUE)
   {
    ...
    ...
      else if (panel_in_keypad(panel, &key_bits))
      {
        shift_pressed = key_bits & PANEL01_KEY_SHIFT;    
        ...
        ...
     }   
   }


And in the level_meter_task() function, you could then wrap the TRACE() statement in an if() {...} construct like this:
Code:

  if( shift_pressed )
    {
      TRACE("cc value = %d\n", cc_value );
    }


Considering that you're working on the source, I don't specify line numbers since they may no longer match. Hopefully you'll recognize the places I'm talking about.

As usual, this is untested and may not work, may cause compilation errors and so on - but I think you get the idea, and you'll be able to correct any errors in t he example above Smile
Back to top
View user's profile Send private message Visit poster's website
arpeggio



Joined: Jan 05, 2010
Posts: 24
Location: the Netherlands

PostPosted: Wed Jun 17, 2015 6:21 am    Post subject: Works great Reply with quote  Mark this post and the followings unread

Joepie, thats dutch for Laughing and nice.
Works great,
Still i get the best results using the CC_value after Level_L=log10,
then the values produced look the same as the values on the Chameleon bargraph.
And a little question for further programming with Midi in and Midi out,
Midi out i can do now, but Midi in
what will be a a general function for recieving MIDI CC messages and Midi-Notes
Thanks people, you have helped me a lot, and this would keep the coding and DIY stuff alive, Dian
Back to top
View user's profile Send private message
DrJustice



Joined: Sep 13, 2004
Posts: 2112
Location: Morokulien
Audio files: 4

PostPosted: Wed Jun 17, 2015 9:44 am    Post subject: Reply with quote  Mark this post and the followings unread

Glad to hear that you get things working! Smile

I'd still be looking a bit at the values you're getting, that log value isn't really what should be used in normal circumstances. I might look at both values in the TRACE statement to figure out what's going on. As mentioned you should normally be using a value between 0 and 127 when dealing with MIDI:
Code:
TRACE("cc value = %d log value = %d\n", cc_value, level_L );

I'll leave further experimentation with that to you.

As for receiving MIDI, that can be done either by a "callback" from MidiShare, or by polling MidiShare using the MidiGetEv() function. I think it may be best if you use the polling method for now. To do this, add the midi_poll() example function below to your source code, then call that from the level_meter_task() function, inside the while() loop, something like this

Code:

  while (rtems_rate_monotonic_period(period_id, 20) != RTEMS_TIMEOUT)
  {
    poll_midi();
    ...
    ...
  }


The poll_midi() function then checks if there is any received MIDI events, and acts upon them depending on the type of the event. The example below will monitor incoming note on, note off and control change events. Please refer to the MidiShare documentation for more details, such as the different event types. Hopefully this should be enough to get you started.

Code:

void poll_midi( void )
{
  MidiEvPtr ev;
  int       event_type;

  // See if there is a received event ready in the queue.
  ev = MidiGetEv( midi_ref );

  while( ev != NULL )
    {
      // Find the type of this event so we can process it accordingly.
      event_type = EvType( ev );

      switch( event_type )
        {
          case typeKeyOn:
            TRACE("typeKeyOn: chan = %d, note = %d, velocity = %d\n", (int) Chan( ev ), (int) MidiGetField( ev, 0 ), (int) MidiGetField( ev, 1 ) );
            break;

          case typeKeyOff:
            TRACE("typeKeyOff: chan = %d, note = %d, velocity = %d\n", (int) Chan( ev ),(int) MidiGetField( ev, 0 ), (int) MidiGetField( ev, 1 ) );
            break;

          case typeCtrlChange:
            TRACE("CtrlChange: chan = %d, cc num = %d, cc value = %d\n", (int) Chan( ev ), (int) MidiGetField( ev, 0 ), (int) MidiGetField( ev, 1 ) );
            break;
        }

      // Free this event when we are done with it.
      MidiFreeEv( ev );

      // See if there is another event in the queue.
      ev = MidiGetEv( midi_ref );
    }
}


The usual caveat of "untested code, blah, blah.." applies - but you know that by now Laughing

A word of warning here: The panel_task() and level_meter_task() are running as two different threads. That means you have multi threading going on, and it's not always safe to acces the same data from both threads since they run "simultaneously". It works for the previous example using the "shift_pressed" variable since it is written by one thread (panel_task) and read by another thread (level_meter_task). It's too much to go into the subtleties of multi threading and thread safety here, but you should at least be aware of it.

You can read about multi threading here:
https://en.wikipedia.org/wiki/Thread_(computing)#Multithreading
(the whole line above is the link - the forum software has trouble with link with parentheses in them...)

Edit: fixed typos, removed ")"

Last edited by DrJustice on Sat Jun 20, 2015 4:59 pm; edited 1 time in total
Back to top
View user's profile Send private message Visit poster's website
arpeggio



Joined: Jan 05, 2010
Posts: 24
Location: the Netherlands

PostPosted: Sat Jun 20, 2015 8:11 am    Post subject: midi in works but............ Reply with quote  Mark this post and the followings unread

Hello, i got midi in working, but as suggested, the multithreading thing, the
level meter task stops when i put in a few midi-message together, when it is not a lot together' then it works fine, so the Midi-in code is good, by the way, had to remove a few, 3, ")" at the end of the midigetfield sentence, i kind of get used to the coding and finding a way to build things, a little, but the beginning is there and it's fun for me and it payes of a great deal, for me and for the
diy community. And you spoke about midi-callback, i know that from the arduino midi-library, can you tell me how that works, so how the code basics looks like. So i can try to find a way to handle the midi-in thing, maybe put the midi_poll thing in the main loop, or at the end of the whil()loop, or some other place, or do you think i have to get another approce for handling this multithreading thing,
By the way, left out the PHYSMIDI_IO 0 thing and that builded fine too, so you had it right that it was not needed.
And later on i will drop some test results for the level_L value, that keeps puzzling me, a 12 digit is 4095 max, so it should work the way you suggested, but it does not, i will let you know.
Thanks again, Dian
Back to top
View user's profile Send private message
DrJustice



Joined: Sep 13, 2004
Posts: 2112
Location: Morokulien
Audio files: 4

PostPosted: Sun Jun 21, 2015 12:03 pm    Post subject: Reply with quote  Mark this post and the followings unread

I'm not sure what you mean by "level meter task stops when i put in a few midi-message together, when it is not a lot together' then it works fine...". Normally there's no problem sending and receiving any number of MIDI messages - could it be an error elsewhere (not caused by MidiShare as such)?

The callback method is implemented by calling the MidiShare function MidiSetRcvAlarm() with the midi_ref and a pointer to a function that you define. Your function will then be called when there's incoming MIDI data in the receive buffer, and the you can read the MIDI event in basically the same way as the midi_poll() example.

Regarding the multithreading, it's not 'dangerous' unless two threads try to modify the same data; then the dilemma is which change should be the latest valid one... If that's not resolved, the program may become 'confused', and at worst crash (depending on what the program, does with the data that is shared between threads). If two threads want to change the same data, you must use thread synchronization mechanisms such as a 'mutex' (mutual exclusion). Don't worry about that before you have that need.

As for the 0-127 range problem, I can't see any obvious explanations - at this point you're in a better position that me to find out since you run and debug the code Smile
Back to top
View user's profile Send private message Visit poster's website
arpeggio



Joined: Jan 05, 2010
Posts: 24
Location: the Netherlands

PostPosted: Mon Aug 10, 2015 5:27 pm    Post subject: Reply with quote  Mark this post and the followings unread

The while loop where the level_meter_task runs has this message at the end, look at the source code, after the 'should never be here' sentence, and this happens when i put in a lot of midi data,
And when i put in a few data, then the code runs fine and the meter moves
good and the incoming midi-data is monitored in the debug-window,
so i will get experinenting with this in a while, let you know.

Thanks for the callback midi info, will try this in a while, let you know.
Thanks again, happy coding, Dian
Back to top
View user's profile Send private message
DrJustice



Joined: Sep 13, 2004
Posts: 2112
Location: Morokulien
Audio files: 4

PostPosted: Tue Aug 11, 2015 9:30 am    Post subject: Reply with quote  Mark this post and the followings unread

Ending up at "Should never be here" most likely happens because the Chameleon gets so busy processing incoming MIDI for a moment, that it misses a timer period - this happens either internally in MidiShare or in poll_midi() (I suspect the latter is most plausible, with the TRACE statements possibly taking a bit of time). See the snippet from level_meter_task() below:

Code:
static rtems_task level_meter_task(rtems_task_argument argument)
{
  ...
 
  /* Periodic reads & Display updates (20ms) */
  while (rtems_rate_monotonic_period(period_id, 20) != RTEMS_TIMEOUT)
  {
    ...
  }
 
  /* Should never be here... */
  TRACE("Ending level_meter_task...\n");
  rtems_task_delete(RTEMS_SELF);
}


You can see that when rtems_rate_monotonic_period() returns RTEMS_TIMEOUT, the level meter task is terminated. You can avoid this by rewriting that while loop as shown here, i.e. let the task run forever with "while ( TRUE )" just like the panel task does, then do the delay inside the loop. It's not critical if you miss a timer period there, so this is an acceptable solution:

Code:
static rtems_task level_meter_task(rtems_task_argument argument)
{
  ...
 
  /* Periodic reads & Display updates (20ms) */
  while ( TRUE )
  {
    rtems_rate_monotonic_period(period_id, 20);
    ...
  }
 
  /* Should never be here... */
  TRACE("Ending level_meter_task...\n");
  rtems_task_delete(RTEMS_SELF);
}


You could also make a separate MIDI task, or use the callback method to get the incoming MIDI. However, there's no need to complicate things too much - better get the basics right first, simple is good etc. Smile
Back to top
View user's profile Send private message Visit poster's website
arpeggio



Joined: Jan 05, 2010
Posts: 24
Location: the Netherlands

PostPosted: Wed Oct 14, 2015 3:22 pm    Post subject: Reply with quote  Mark this post and the followings unread

Hello, try to install a reveive alarm for midi in the levelmeter example
But get errors,
in Function OneSecDelay
Parse error before character 0321
Parse error before }
and Types defaults to int in function ......
Conflicting types in function.....

The piece of code is this I put it near Midi functions

Code:
 
void OneSecDelay (short refNum)
{
    MidiEvPtr    e;
    long n;

    for ( n = MidiCountEvs(refNum); n > 0; Ñn )
    {                               
        e = MidiGetEv(refNum);/* Get an event from the FIFO */
        Date(e) += 1000;        /* Add 1000 ms to its date */
        MidiSend(refNum,e);        /* Then send the event */
    }
}
MidiSetRcvAlarm(myRefNum,OneSecDelay);


Can one help me out here,
Ps disabled all the other midi stuff, for clarety, but that did not help
Thanks again, Dian
Back to top
View user's profile Send private message
blue hell
Site Admin


Joined: Apr 03, 2004
Posts: 24544
Location: The Netherlands, Enschede
Audio files: 299
G2 patch files: 320

PostPosted: Wed Oct 14, 2015 3:31 pm    Post subject: Reply with quote  Mark this post and the followings unread

Quote:
Ñn


Id expect to read n++ there?

edit : hmm .. or n-- maybe.

edit more : hmm .. or even just nothing .. as in ; )

_________________
Jan
also .. could someone please turn down the thermostat a bit.
Posted Image, might have been reduced in size. Click Image to view fullscreen.
Back to top
View user's profile Send private message Visit poster's website
arpeggio



Joined: Jan 05, 2010
Posts: 24
Location: the Netherlands

PostPosted: Wed Oct 14, 2015 4:13 pm    Post subject: Reply with quote  Mark this post and the followings unread

Hello, i got this from the MIDIshare site, in the example they gave for the
MidiSetRecAlarm, looks strange though.
Looking further, Dian
Back to top
View user's profile Send private message
DrJustice



Joined: Sep 13, 2004
Posts: 2112
Location: Morokulien
Audio files: 4

PostPosted: Sat Oct 17, 2015 5:03 am    Post subject: Reply with quote  Mark this post and the followings unread

I agree with Jan on using n--, as in:

Code:
for ( n = MidiCountEvs(refNum); n > 0; n-- )
{ ... }

That will then process the number of events available at the time of starting the loop. An alternative would be:

Code:
while ( MidiCountEvs(refNum) > 0 )
{ ... }

Which would go on for as long as there are more events available. However, if you call OneSecDelay() in a polling fashion, I'd go for the 'for' loop.

Apart from the "Ñn" I can't see any errors in the OneSecDelay() function.
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic
Page 1 of 2 [30 Posts]
View unread posts
View new posts in the last week
Goto page: 1, 2 Next
Mark the topic unread :: View previous topic :: View next topic
 Forum index » Instruments and Equipment » Chameleon
Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Forum with support of Syndicator RSS
Powered by phpBB © 2001, 2005 phpBB Group
Copyright © 2003 through 2009 by electro-music.com - Conditions Of Use