|
View:
New views
4 Messages
—
Rating Filter:
Alert me
|
|
|
comments please? midi parser code and SerialPort interface for infusionsystems usbmicrodigHi 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; } } } |
|
|
Re: comments please? midi parser code and SerialPort interface for infusionsystems usbmicrodighello 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/ |
|
|
Re: comments please? midi parser code and SerialPort interface for infusionsystems usbmicrodigHi 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/ |
|
|
Re: comments please? midi parser code and SerialPort interface for infusionsystems usbmicrodigHi Fredrik,
the and: thing made little difference, though it makes sense to me that SC was always evaluating both conditions. It's not so bad so long as I have a moving average filter on every sensor to make the icube firmware data reduction really kick in, so I doubt it's worth writing as a primitive. The CmdPeriod thing is really neat. 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/ |
| Free embeddable forum powered by Nabble | Forum Help |