|
View:
New views
4 Messages
—
Rating Filter:
Alert me
|
|
|
comments please? midi parser code and SerialPort interface for infusionsystems usbmicrodig
by loriend
::
Rate this Message:
Reply (Restricted by the Administrator) | Reply to Author | View Threaded | Show Only this Message 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; } } } |
|
|
Re: comments please? midi parser code and SerialPort interface for infusionsystems usbmicrodig
by Fredrik Olofsson
::
Rate this Message:
Reply (Restricted by the Administrator) | Reply to Author | View Threaded | Show Only this Message 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/ |
|
|
Re: comments please? midi parser code and SerialPort interface for infusionsystems usbmicrodig
by loriend
::
Rate this Message:
Reply (Restricted by the Administrator) | Reply to Author | View Threaded | Show Only this Message 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/ |
|
|
Re: comments please? midi parser code and SerialPort interface for infusionsystems usbmicrodig
by loriend
::
Rate this Message:
Reply (Restricted by the Administrator) | Reply to Author | View Threaded | Show Only this Message Hi 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 |