« Return to Thread: comments please? midi parser code and SerialPort interface for infusionsystems usbmicrodig

Re: comments please? midi parser code and SerialPort interface for infusionsystems usbmicrodig

by loriend :: Rate this Message:

Reply to Author | View in Thread

Hi Frederik,
    closing on cmdperiod is a neat idea and I was unaware of that
logical AND. It certainly does shave quite some time in the loops, will
see later what it does in situ.

thanks :)
Lorien

Fredrik Olofsson wrote:

> hello Lorien,
> i don't know this device, but after a quick glance at your code, i
> spot one possible optimisation...
> {var byte= 0xFF; 1000000.do{if((byte>=0xF8).and(byte<=0xFF), {11},
> {22})}}.bench;""
> {var byte= 0xFF; 1000000.do{if((byte>=0xF8) and:{byte<=0xFF}, {11},
> {22})}}.bench;""
> ie replace all .and() with and:{} and it'll save a few cpu cycles.
>
> also did you consider closing the serial port at command period?  
> something like CmdPeriod.doOnce{this.stop}.  your task will be killed
> anyway so there's no way - as it looks to me now - to recover a
> cmdperiod without manually closing the port and reinstantiating.  so
> why not also stop+close at cmdperiod i mean.  just a suggestion.
>
> _f
>
> 15 apr 2009 kl. 10.02 skrev Lorien Dunn:
>
>> Hi all,
>>   this code allows me to use my infusionsystems usbmicrodig in
>> standalone mode without having the icubex editor running (the
>> usbmicrodig is a usb serial device rather than usb midi device). It
>> works very well indeed on my macbook, and should work on Linux (and
>> Windows if SerialPort works). But I'm still a comparative newbie to
>> supercollider and would appreciate some constructive criticism.
>> Advice for optimisation would be nice too- under heavy sensor load
>> with a 1ms sampling rate it's taken 20% of one core of a 2gHz core2,
>> though under normal usage it's between 2 and 4%.
>>   the midi parser is loosely based on libmidi++ by Paul Davis.
>>
>> thanks,
>> Lorien
>>
>> LowLevelMidiParser
>> {
>>     classvar noteOffStat=0x80, noteOnStat=0x90, polytouchStat=0xA0,
>> controlStat=0xB0;
>>     classvar programStat=0xC0, touchStat=0xD0, bendStat=0xE0;    
>> classvar sysexStat=0xF0, qFrameStat=0xF1, songPositionStat=0xF2,
>> songSelectStat=0xF3;
>>     classvar tuneRequestStat=0xF6, eoxStat=0xF7;
>>     classvar bufferSize=16;
>>     var parserState, runnable, msgType, msgBuffer;
>>     var <noteOn, <noteOff;
>>     var <polytouch, <control;
>>     var <program, <touch;
>>     var <bend;
>>     var <>sysex;
>>    
>>     *new
>>     {
>>         var self = super.new;
>>         self.initLLMP;
>>         ^self;
>>     }
>>    
>>     initLLMP
>>     {
>>         noteOn = Array.fill(16,{|i| nil});
>>         noteOff = Array.fill(16,{|i| nil});
>>         polytouch = Array.fill(16,{|i| nil});
>>         control = Array.fill(16,{|i| Array.fill(128,{|j| nil})});
>>         program = Array.fill(16,{|i| nil});
>>         touch = Array.fill(16,{|i| nil});
>>         bend = Array.fill(16,{|i| nil});
>>         sysex = nil;      
>>         parserState = \needStatus;
>>         runnable = true;
>>         msgType = noteOnStat;
>>         msgBuffer = Int16Array.new(bufferSize);
>>         msgBuffer.add(noteOnStat);
>>     }
>>    
>>     emit
>>     {
>>         var chan = msgBuffer[0] & 0xF;
>>         switch(msgType,
>>             controlStat, { //bandwidth hungry (i.e. lots of them)
>> msgs first
>>                 control[chan][msgBuffer[1]].value(msgBuffer[2]) },
>>             bendStat, {
>>                 bend[chan].value(msgBuffer[2]<<7|msgBuffer[1]) },
>>             polytouchStat, {
>>                 polytouch[chan].value(msgBuffer[1],msgBuffer[2]) },
>>             touchStat, {
>>                 touch[chan].value(msgBuffer[1]) },
>>             noteOnStat, {
>>                 noteOn[chan].value(msgBuffer[1],msgBuffer[2]) },
>>             noteOffStat, {
>>                 noteOff[chan].value(msgBuffer[1],msgBuffer[2]) },
>>             programStat, {
>>                 program[chan].value(msgBuffer[1]) }
>>         );
>>     }
>>    
>>     channelMessage
>>     {     arg byte;
>>         switch((byte&0xF0),
>>             controlStat, {
>>                 msgType = controlStat;
>>                 parserState = \needTwoBytes },
>>             bendStat, {
>>                 msgType = bendStat;
>>                 parserState = \needTwoBytes },
>>             polytouchStat, {
>>                 msgType = polytouchStat;
>>                 parserState = \needTwoBytes },
>>             touchStat, {
>>                 msgType = touchStat;
>>                 parserState = \needOneByte },
>>             noteOnStat, {
>>                 msgType = noteOnStat;
>>                 parserState = \needTwoBytes },
>>             noteOffStat, {
>>                 msgType = noteOffStat;
>>                 parserState = \needTwoBytes },
>>             programStat, {
>>                 msgType = programStat;
>>                 parserState = \needOneByte }
>>            
>>         );  
>>     }
>>    
>>     systemMessage
>>     {    arg byte;
>>         msgType = byte;
>>         switch(byte,
>>             sysexStat, {
>>                 parserState = \variableLength; },
>>             qFrameStat, {
>>                 parserState = \needOneByte; },
>>             songPositionStat, {
>>                 parserState = \needTwoBytes; },
>>             songSelectStat, {
>>                 parserState = \needOneByte; },
>>             tuneRequestStat, {
>>                 parserState = \needStatus; },
>>             eoxStat, {
>>                 parserState = \needStatus; }
>>         );
>>     }
>>    
>>     parseByte
>>     {    arg byte;        
>>         var statusBit;
>>         var size;
>>         if((byte >= 0xF8).and(byte <= 0xFF)) {^nil}; //it's a
>> realtime message, ignore it
>>         statusBit = byte & noteOffStat;
>>         if((statusBit != 0).and(parserState == \variableLength))
>>         {
>>             if(byte==eoxStat)
>>             {
>>                 msgBuffer = msgBuffer.add(byte);
>>                 sysex.value(msgBuffer);  
>>             }
>>             {
>>                 "Incorrectly terminated system exclusive
>> message".postln;
>>             };      
>>         };
>>         if(statusBit != 0)
>>         {
>>             msgBuffer = Int16Array.new(bufferSize);
>>             msgBuffer.add(byte);
>>             if((byte&sysexStat) == sysexStat)
>>             {
>>                 runnable = false;
>>                 this.systemMessage(byte);
>>             }
>>             {
>>                 runnable = true;
>>                 this.channelMessage(byte);
>>             };
>>             ^nil;
>>         };
>>         //it's a data byte
>>         msgBuffer = msgBuffer.add(byte);
>>         if(parserState == \needTwoBytes)
>>         {
>>             if(msgBuffer.size<3) {^nil};
>>             parserState = \needOneByte;
>>         };
>>         if(parserState == \needOneByte)
>>         {
>>             this.emit();
>>             if(runnable)
>>             {
>>                 if(msgBuffer.size==3)
>>                 {
>>                     msgBuffer.pop();
>>                     msgBuffer.pop();
>>                 }
>>                 {
>>                     msgBuffer.pop();
>>                 };
>>             }
>>             {
>>                 parserState = \needStatus;
>>             };
>>         };  
>>     }  
>> }
>> UsbMicroDig : LowLevelMidiParser
>> {
>>     var port;
>>     var device;
>>     var task;
>>    
>>     *new
>>     {    arg dev="/dev/tty.SLAB_USBtoUART";
>>         var self = super.new;
>>         self.initUsbMD(dev);
>>         ^self;
>>     }
>>    
>>     initUsbMD
>>     {    arg dev;
>>         device = dev;
>>         UI.registerForShutdown({this.stop()});
>>     }
>>    
>>     play
>>     {
>>         if(port.isNil)
>>         {
>>             port = SerialPort.new(
>>                 port: device,
>>                 baudrate: 115200,
>>                 databits: 8,
>>                 stopbit: true,
>>                 parity: nil,
>>                 crtscts: true,
>>                 exclusive: true
>>             );
>>             task = fork { loop { this.parseByte(port.read()); } };
>>         };
>>     }
>>    
>>     stop
>>     {
>>         if(port.notNil)
>>         {
>>             task.stop;
>>             task = nil;
>>             port.close;
>>             port = nil;
>>         }
>>     }
>>                
>> }
>
>
>   #|
>      fredrikolofsson.com     klippav.org     musicalfieldsforever.com
>   |#
>
>
> _______________________________________________
> sc-users mailing list
>
> info (subscription, etc.):
> http://www.beast.bham.ac.uk/research/sc_mailing_lists.shtml
> archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
> search: http://www.listarc.bham.ac.uk/lists/sc-users/search/
>


_______________________________________________
sc-users mailing list

info (subscription, etc.): http://www.beast.bham.ac.uk/research/sc_mailing_lists.shtml
archive: http://www.listarc.bham.ac.uk/marchives/sc-users/
search: http://www.listarc.bham.ac.uk/lists/sc-users/search/

 « Return to Thread: comments please? midi parser code and SerialPort interface for infusionsystems usbmicrodig