From: Michael H. <kor...@ya...> - 2009-08-25 15:56:43
|
Pete, I had a look at the Roland TD6 driver and I have been able to get basic patch names working in JSynthLib. THANKS FOR THE TIP! So to explain, JSynthLib assumes that somewhere inside of a single patch sysex message there will be the text for the patch name. So the convention of JSynthLib was that you would set up an offset pointer and patch name size that would point at the start of the string in the sysex data array. Well, we all know that there are many synth's that never supported patch names at all so what I did was extended the size of the sysex array to be 262 bytes (for the actual sysex patch dump data) + 20 bytes for the patch name (character string). But then, the patch send routines have to send just the first 262 bytes. The 20 bytes for the patch name are just text stored for JSynthLib patch names. And also, the create new patch routine needed to include defining the patch sysex as being the larger size (282 bytes) and define some text in the last 20 bytes as shown below. public Patch createNewPatch() { // define sysex byte array with 262 bytes for sysex patch dump data message and 20 bytes for JSynthLib stored patch name text byte [] sysex = new byte[262+20]; // set up sysex patch dump data with SOX,manufacturer,device, patch and EOX values sysex[0]=(byte)0xF0; sysex[1]=(byte)0x42; sysex[2]=(byte)0x21; sysex[3]=(byte)0x06; sysex[261]=(byte)0xF7; // create the patch object Patch p = new Patch(sysex, this); // set the patch name for a new patch setPatchName(p,"**** New Patch ****"); calculateChecksum(p); return p; } Also, I noticed that you were absolutely correct about a "single" patch being able to hold more than one sysex message at a time. But of course, you have to define the sysex array size in the patch object as being large enough to hold all of the messages. So, I could extend the size of the sysex data array to allow storing the bank change acknowledgment message along with the actual single patch dump message. But that is an awfully bad way to write a single driver because the acknowledgment message is of no use to a patch whatsoever and would just be wasting memory. So, I am still looking for a way to rewrite the patch receiver code so that it can ignore such unwanted received data. It would be nice if a developer on JSynthLib could provide a hint. In the meantime, I'll go back to trudging through other drivers to see if someone else has already done something similar. The snippet below is my tweaked version of the generic single editor that shows the captured sysex message. In my version, the the sysex message is displayed and the additional 20 bytes are printed out as text underneath showing that they are being used by JSynthLib to provide a local patch name. public KorgHAWK800SingleEditor(Patch p) { this(); SysexMessage[] messages = p.getMessages(); for(int i=0; i<messages.length; i++) { append("Message " + i + ":\n"); appendBytes(messages[i].getMessage()); } // now display the patch name below the sysex message by printing bytes from 262 to 282 as a string append("Patch name: " + new String(((Patch)p).sysex, 262, 20) ); } Message 0: 0000 - f0 42 21 06 00 00 00 00 00 00 00 00 00 00 00 00 - .B!............. 0010 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - ................ 0020 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - ................ 0030 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - ................ 0040 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - ................ 0050 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - ................ 0060 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - ................ 0070 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - ................ 0080 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - ................ 0090 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - ................ 00a0 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - ................ 00b0 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - ................ 00c0 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - ................ 00d0 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - ................ 00e0 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - ................ 00f0 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - ................ 0100 - 00 00 00 00 00 f7 - ...... Patch name: **** New Patch **** ________________________________ From: Peter Geirnaert <pet...@gm...> To: Michael Hawkins <kor...@ya...> Cc: JSynthLib Developers <Jsy...@li...> Sent: Tuesday, August 25, 2009 5:29:41 AM Subject: Re: [Jsynthlib-devel] Got something going but... Hmm, I forgot to "reply all", so Mike, sorry if you get this twice ;-) Anyway, I added some more thoughts .. On Tue, Aug 25, 2009 at 2:00 AM, Michael Hawkins <kor...@ya...> wrote: Hi JSynthLib fans, > >>Well, after hours (3 to be exact) of careful troubleshooting and tinkering, I was able to pull in a patch from my Korg Poly-800. > >>But as with most things in life, I now have more questions than I started with. I am hoping that someone who has more experience with JSynthLib than me can help me out. > >>To get the patch "get" and "paste" to work required that a) I set sysexID = "F0422106*"; this is the header for a patch dump coming from the Poly-800. and b) that I comment out sending a bank change in requestPatchDump. > >>The Poly-800 sends an acknowledgement sysex message after it receives a bank change. So the "Get" code seems to have choked on the 7 bytes that it receives just prior to receiving the patch sysex message itself. > >>So, I could just rewrite the sysex implementation on the Poly-800 so that it doesn't send an acknowledgment sysex message but that seems to be a bit of a cop out and especially so if there is a way that I could rewrite the requestPatchDump so that it would intercept that ack. message and ignore it instead of choking on it? Maybe you should to make the KorgHAWK800SingleDriver extends BankDriver, like I did with my SPD11PatchDriver , and use a 'bankChangeDriver' and 'K800SingleDriver', like I used a SPD11PadDriver and SPD11SettingsDriver. I'm not really understanding the difference between a singleDriver, bankDriver, converter I'm reading the programmer's guide again, and I'm wondering if a Single Patch really is a set of sysex messages like described there. I first thought a Single Patch would hold just one Single SysEx Message. Because a single patch of my drumsynth is composed of 32 sysexmessages describing each drumpad + 1 sysexmessage describing the effects and pedal settings. In your case a patch is 1 bank ack sysexmessage + a 262 bytes patch sysexmessage > >>Now, I don't want to be too pushy here because I like JSynthLib and I like the idea of an open source patch editor but hopefully someone on this list can answer a question or two because it has taken me hours to get this far and I have many more questions that need answering. Four hands do three times more work than two hands, I guess it's good to ask questions to many heads too, instead of keeping the questions for yourself. > >>Here is another question, the Poly-800 does not support patch names in its sysex implementation nor programming but does that stop me from using patch names in JSynthLib itself? Is it possible to save patch names outside of the sysex message but inside the patch when stored in JSynthLib? My drum kits are named numbers 1~64, and I'd like to give 'em names too, so I actually have the same question. I think maybe we should take a look at how e.g. the TD-6 driver stores settings for padInfo in the prefs file, it keeps info about if a pad is active or not, look at how it's done in RolandTD6Device (line 56 & 75). The same trick may work to keep patch names in a preferences.node("Name(s)") > >>Anyway, in advance, I would like to thank anyone that might provide me with some assistance. > >>If I don't hear anything from anybody, I may have to consider an alternative to JSynthLib because the learning curve might be just too steep while going at this completely alone. > >>Here's my singledriver below: > >>/* >> * @version $Id: KorgHAWK800SingleDriver.java 111 2009-08-20 04:05:40Z hawkins $ >> */ >>package synthdrivers.KorgHAWK800; > >>import core.Driver; >>import core.ErrorMsg; >>import core.JSLFrame; >>import core.Patch; >>import core.SysexHandler; > >>public class KorgHAWK800SingleDriver extends Driver >>{ >> private int curBank = 0, curPatch = 0; You don't use these variables anywhere ? > >> public KorgHAWK800SingleDriver() { >> super("Single", "Michael Hawkins"); >> sysexID = "F0422106*"; >> sysexRequestDump=new SysexHandler("F0 42 21 07 *patchNum* F7"); > >> patchSize=262; This is why it chokes on the first returned ack message >> deviceIDoffset=-1; > >> bankNumbers = new String[] { >> "0-Bank1", "1-Bank2","2-Bank3", "3-Bank4" >> }; >> // patch numbers use octal representation with no zeroes (11-88) >> patchNumbers=new String[] {"11","12","13","14","15","16","17","18", >> "21","22","23","24","25","26","27","28", >> "31","32","33","34","35","36","37","38", >> "41","42","43","44","45","46","47","48", >> "51","52","53","54","55","56","57","58", >> "61","62","63","64","65","66","67","68", >> "71","72","73","74","75","76","77","78", >> "81","82","83","84","85","86","87","88"}; >> } > >> public void setBankNum(int bankNum) >> { >> try { >> send(new byte[] { >> (byte)0xF0,(byte)0x42,(byte)0x21,(byte)0x0E, >> (byte)bankNum,(byte)0xF7 >> }); >> } catch (Exception e) {} >> } > >> public void requestPatchDump(int bankNum, int patchNum) { Maybe here add patchSize = SIZE_OF_ACK; //the number of bytes that comprise the returned ack message patchNameSize = 0; >> //setBankNum(bankNum); uncomment >> try {Thread.sleep(250); } catch (Exception e){} and now set patchSize = SIZE_OF_PATCH; //the number of bytes that comprise the returned patch message >> byte sysex[] = { >> (byte)0xF0, (byte) 0x42, (byte) 0x21, (byte) 0x07, (byte)patchNum, (byte) 0xF7 >> }; >> send(sysex); >> } > >> public void storePatch (Patch p, int bankNum,int patchNum) >> { >> setBankNum(bankNum); >> try {Thread.sleep(250); } catch (Exception e){} >> //patchNum=patchNum&0x3F; >> ((Patch)p).sysex[4]=(byte)patchNum; >> sendPatchWorker(p); >> setPatchNum(patchNum); >> } > >> public void sendPatch (Patch p) >> { >> byte [] newsysex = new byte[262]; >> System.arraycopy(((Patch)p).sysex,0,newsysex,0,262); >> newsysex[4] = (byte)(0x40); >> try { >> send(newsysex); >> }catch (Exception e) {ErrorMsg.reportStatus(e);} >> } > >> public Patch createNewPatch() >> { >> byte [] sysex = new byte[262]; >> sysex[0]=(byte)0xF0; sysex[1]=(byte)0x42; sysex[2]=(byte)0x21; >> sysex[3]=(byte)0x06; sysex[261]=(byte)0xF7; >> Patch p = new Patch(sysex, this); >> //setPatchName(p,"NewPatch"); >> calculateChecksum(p); >> return p; >> } > >>protected void calculateChecksum(Patch p,int start,int end,int ofs) >> { >> // no checksum >> } > >>//public JSLFrame editPatch(Patch p) { >>// return new KorgHAWK800SingleEditor((Patch)p); >>protected JSLFrame editPatch(Patch p) { >> return (new synthdrivers.Generic.HexDumpEditorFrame(p)); >> } > >>} > It would be easier to help if you added more //comments to explain what's happening and why. |