Day 6: More work on the ChromaBank class. I was pondering how best to handle data for the conversion methods. I realized that, looking forward to when I get to a patch librarian and, later, an editor, this class should be able to store patch bank data in different formats simultaneously: for example, Syntech sysex; EES sysex; audio for the cassette interface; and textual data–for which I hope to do an HTML template in addition to the simple listing provided by the original tape2txt
. So I’m thinking that, in converting say from sysex to tape, I should initialize with sysex data from the input file(s) and then simply ask the object for audio patch data. (This could potentially ease conversions from multiple formats simultaneously, as well: the user might drag a couple of different kinds of files to the app, with HTML as the desired final output for all.) The fact that the tape data doesn’t exist would trigger an internal conversion and return the data in the requested format. This would also be an advantage in future for saving to files owned by the application, as only the data of interest to the user would be saved; perhaps there could also be a user preference. So syx2tape becomes a method of ChromaBank, called when tape data is requested and the tape
instance variable is empty, or when the sysex data has ben modified. Perhaps the designated initializer should put “scratch patch” data in the sysex
instance variable and leave the others null: this will be the most useful format for most people, and is also used by the new CPU Plus instrument upgrade.
One interesting stylistic limitation I have found is that a method which calls other instance methods seems to require variables that are in the scope of the object, rather than just the method. Which seems messy. Specifically, as I write bytes to the data format I’m converting to, I have to maintain counts and the converted data object-in-progress as well. Would it be better to pass these values back and forth between methods? What is the overhead for that? Perhaps in this case I don’t have to worry about this, as I can convert straight into the tape
instance variable; this would presumably work also if it was already populated with data (for instance if the sysex
variable was changed and another conversion was requested–which makes me think I need to convert other existing bank formats automatically when any of the format instance variables is set, to keep all data in sync within a ChromaBank object).
Day 8: Posted a question reflecting some of the above to the Cocoa-Dev list.
Day 9: Received a thoughtful reply from Rush Manbert, who suggested that with respect to using instance variables for efficiency, “the answer in 99.999% of the cases is no.” Also, the old adage, “first make it run, then make it fast.”
Day 10-12: Started putting together method arguments for passing back and forth a conversion flag; I’m using the form wasUp = [self writePre:inputSyx withFlag:wasUp];
and it seems this will work pretty well. Trying an instance of NSMutableData
with appendBytes:length
for compiling the converted data, but there’s something I don’t understand about the void pointer form for the bytes themselves I have to investigate.
Another problem I’ve had is finding a Cocoa equivalent for fgetc()
used in the original code. This C function gets the next character from an input stream. So I am putting the data to be converted into an instance of NSInputStream
. No results yet.
Day 13: Installed the CPU Plus upgrade in my Chroma, which will make it easier (more like modern synths) to implement an editor/librarian for the instrument.
Day 14: How do you inspect object instance variables in the Xcode debugger? I’m in an instance method on the stack. Globals doesn’t show them.