K-Gater, Part 11


West panel.

There’s really not a lot left to talk about. I’ve pretty much covered everything about the gate arpeggiator, and there’s not much new in this section. Originally, I wanted to use an Array for holding the arp patterns, with the first entry specifying the number of notes in the pattern, and then a second array for holding pointers to the start of each pattern. But things got messy when I starting thinking about deleting specific patterns, and arrays don’t let you append more entries at the end. So, I was forced to learn more about ArrayLists, and that turned out to be a blessing in disguise, because they do everything I wanted, plus giving me extra flexibility in pattern lengths by letting me remove the length value from the beginning of the pattern.

What I absolutely hate about ArrayLists and combo boxes, though, is that if I accidentally hit the Add Pattern button, I’ll get a duplicate entry in the list, and if I try to delete it, Java will remove the first matching entry it finds. This isn’t as much of an issue with arp patterns, but it really messes up the relationship between the ArrayList and combo box for the patches (if I have two different patches with the same name). I tried including index numbers at the beginning of the combo box string items, but that only worked for arp patterns, not patches. I then ran into a problem when I did a removeAll() from the combo box prior to updating it – Java started throwing null pointer exceptions. I assume that by emptying the combo box, I set it up for garbage collection, or something. Eventually, I just settled on preventing duplicate entries (duplicated arp patterns or patch names), and requiring the user to keep a minimum of 1 patch or arp pattern at all times.

I don’t know how many times I tried running the gate arp without loading some patterns from a file first, so I put in an error check for that as well. And, there is an issue with getting the gate arp patterns wrong, such as by having a space between the minus sign and the number, or putting the minus sign behind the number, so I created the isInt() function to handle that. Patterns are space-delimited, although I could consider allowing commas.

One thing I dislike about the way K-Gater works right now is that when I change the arp ratio using the slider, it causes the sound to stop as long as the mouse button is held down. This is because the slider state has changed, causing the action listener to fire, but the state remains “changed” and the listener KEEPS firing. I think the only work around is to use the “left” and “right” jButtons, but to increase the step values from 1 to 5 or 10 to make the change in effect more noticeable more quickly.

One last comment, this one about the gate arp rate slider. I incorporated a format similar to what’s used by the K-Pro, and displayed the rate in fractions of seconds (2 sec., 1/2 sec., 1/3 sec.) on the screen, while keeping the actual number in milliseconds in a second array. I think it’s just more readable that way. I don’t have many choices for 1/3 (just 1/3 and 2/3’s) of a second. I could consider 1/6, 1/3, 2/3’s and 5/6’s, which would be easy enough to implement. I’d just need to remember to change the maximum value for the slider.

jButton13ActionPerformed
User turning the gate arpeggiator on and off.

jSlider2StateChanged
User changing the gate arp rate (0-10).

jButton29ActionPerformed
User selecting next slower rate. (Button to left.)

jButton30ActionPerformed
User selecting next faster rate. (Button to right.)

jSlider3StateChanged
User changing the gate arp ratio (1-99).

jButton31ActionPerformed
User selecting next larger ratio. (Button to left.)

jButton32ActionPerformed
User selecting next smaller ratio. (Button to right.)

jTextField2ActionPerformed
I made gate arp bottom note read-only. It’s just the total of keyboard bottom note + keyboard key * keyboard spacing.

jComboBox2ActionPerformed
The list of arpeggiator patterns is displayed in jComboBox2. User selected one of the patterns. Update the pointers to point to this pattern, and copy the pattern string to a textbox for editing.

jTextField5ActionPerformed
Gate arp pattern spacing. If the pattern is 0 1 2 3, then a spacing of 3 will turn it into 0 3 6 9.

jButton33ActionPerformed
User wants to add an edited pattern to the arp pattern list. Check for duplications and anything that is not a number. Pattern is space-delimited.

jButton34ActionPerformed
User wants to delete the current pattern. If we delete the last pattern in the ArrayList, we’ll start getting null pointer exceptions, so force the user to keep at least one pattern at all times.

——————————-

Formatted text file.

// User turned the gate arpeggiator on or off.

private void jButton13ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton13ActionPerformed
if(arpPatternsList.size() > 0) {
if(arp.state) { // Gate Arp ON/Off Button pressed
arp.arpTmr = -1;
jButton13.setBackground(Color.lightGray);
kProAllOff();
} else {
arp.arpTmr = 0;
jButton13.setBackground(Color.red);
}
arp.state = (! arp.state);
} else {
jTextArea1.append(“No apreggiator patterns loaded yet.\n”);
}
}//GEN-LAST:event_jButton13ActionPerformed

// User moved the slider for the gate arp rate setting.

private void jSlider2StateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jSlider2StateChanged
String s[] = {“4 sec.”, “2 sec.”, “1 sec.”, “3/4”, “2/3 sec.”, “1/2 sec.”, “1/3 sec.”, “1/4 sec.”, “1/8 sec.”, “1/16 sec.”, “1/32 sec.”};
int i[] = {4000, 2000, 1000, 750, 666, 500, 333, 250, 125, 62, 31};
jLabel2.setText(“Rate: ” + s[jSlider2.getValue()]);
if(arp.state) {
arp.arpTmr = -1;
kProAllOff();
}
arp.rate = i[jSlider2.getValue()];
arp.onOff = true;
arp.calc();
arp.arpTime = arp.onTime;

if(arp.state) {
arp.arpTmr = 0;
}
}//GEN-LAST:event_jSlider2StateChanged

// There are two buttons that supplement the gate arp rate slider, for single incrementing or decrementing the slider.

private void jButton29ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton29ActionPerformed
int x = jSlider2.getValue(); // Arp Rate L button
if(x > 0) {
x–;
jSlider2.setValue(x);
}
}//GEN-LAST:event_jButton29ActionPerformed

private void jButton30ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton30ActionPerformed
int x = jSlider2.getValue(); // Arp Rate R button
if(x < jSlider2.getMaximum()) { x++; jSlider2.setValue(x); } }//GEN-LAST:event_jButton30ActionPerformed // User moved the slider for the gate arp ratio setting. private void jSlider3StateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jSlider3StateChanged if(arp.state) { // Gate Arp Ratio arp.arpTmr = -1; kProAllOff(); } jLabel3.setText(“Ratio: ” + jSlider3.getValue() + “%”); arp.onOff = true; arp.ratio = jSlider3.getValue(); arp.calc(); arp.arpTime = arp.onTime; if(arp.state) { arp.arpTmr = 0; } }//GEN-LAST:event_jSlider3StateChanged // There are also two buttons that supplement the gate arp ratio slider, for single incrementing or decrementing the slider. private void jButton31ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton31ActionPerformed int x = jSlider3.getValue(); // Arp Ratio L button if(x > 0) {
x–;
jSlider3.setValue(x);
}
}//GEN-LAST:event_jButton31ActionPerformed

private void jButton32ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton32ActionPerformed
int x = jSlider3.getValue(); // Arp Ratio R button
if(x < jSlider3.getMaximum()) {
x++;
jSlider3.setValue(x);
}
}//GEN-LAST:event_jButton32ActionPerformed

// Gate arp bottom note. Display only (calculated from keyboard bottom note and keyboard spacing.

private void jTextField2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jTextField2ActionPerformed
// keyboardBottomNote = Integer.parseInt(jTextField2.getText()); // Arp bottom note
}//GEN-LAST:event_jTextField2ActionPerformed

// User selected a gate arpeggiator pattern from the combo box. If the gate arp is on, play the pattern. Either way
// put the pattern into a text box to let the user edit it.

private void jComboBox2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jComboBox2ActionPerformed
arp.currentPat = jComboBox2.getSelectedIndex(); // Selecting arp pattern
arp.patLength = arpPatternsList.get(arp.currentPat).size();
String s = (String) jComboBox2.getSelectedItem();
}//GEN-LAST:event_jComboBox2ActionPerformed

// User changed the gate arp pattern step size in the text box.

private void jTextField5ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jTextField5ActionPerformed
if(isInt(jTextField5.getText())) {
arp.stepSize = Integer.parseInt(jTextField5.getText()); // Changing Arp Step Spacing
} else {
jTextArea1.append(jTextField5.getText() + ” is not a number.\n”);
}
}//GEN-LAST:event_jTextField5ActionPerformed

// User is attempting to add a gate arp pattern to the combo box. Fail if the pattern contains something other than integers
// (space delimited), or if the identical pattern already exists.

private void jButton33ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton33ActionPerformed
String s = jTextField6.getText(); // Add new pattern to Arp list
String [] str = s.split(” “);
ArrayList a = new ArrayList();
boolean goodSoFar = true;

for(int i = 0; i < str.length; i++) {
if(isInt(str[i])) {
a.add(Integer.parseInt(str[i])); // Build up new pattern as Integer ArayList
} else {
goodSoFar = false;
}
}
if(goodSoFar) {
for(int i=0; i < jComboBox2.getItemCount(); i++) { if(jComboBox2.getItemAt(i).equals(s)) { goodSoFar = false; } } if(goodSoFar) { arpPatternsList.add(a); // Add to the main patterns list jComboBox2.addItem(s); // Add to combobox jComboBox2.setSelectedIndex(jComboBox2.getItemCount() – 1); } else { jTextArea1.append(“Pattern already exists. Not added to list.\n”); } } else { jTextArea1.append(“Bad string. Contains Not a Number.\n”); } }//GEN-LAST:event_jButton33ActionPerformed // User wants to delete the currently-selected gate arp pattern. Fail if there’s only one pattern. Trying to delete the only // pattern in the combo box will throw an exception. private void jButton34ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton34ActionPerformed int curPatNo = jComboBox2.getSelectedIndex(); // Delete arp pattern int curSize = -1; String s = “”; if(arpPatternsList.size() > 1) {
arpPatternsList.remove(curPatNo);
jComboBox2.removeItemAt(curPatNo);
curSize = arpPatternsList.size();

if(curPatNo <= 0) { // If deleted first in list, select current first pattern jComboBox2.setSelectedIndex(0); } else if(curPatNo >= jComboBox2.getItemCount() – 1) { // If deleted last in list, select current last pattern
jComboBox2.setSelectedIndex(jComboBox2.getItemCount() – 1);
} else { // Select previous pattern instead
jComboBox2.setSelectedIndex(curPatNo – 1);
}

} else {
jTextArea1.append(“Can’t delete remaining patterns without getting a system error.\nPlease add a new pattern before deleting this one.\n”);
}
}//GEN-LAST:event_jButton34ActionPerformed

 

Previous Post
Leave a comment

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.