mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-07 12:24:58 +10:00
Treble bleed enhancements
This commit is contained in:
@@ -118,4 +118,10 @@ public class Resistance extends AbstractMeasure<ResistanceUnit> {
|
||||
}
|
||||
throw new IllegalArgumentException("Could not parse resistance: " + value);
|
||||
}
|
||||
|
||||
public Double getNormalizedValue() {
|
||||
if (value == null || unit == null)
|
||||
return null;
|
||||
return value * unit.getFactor();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ public class Tree {
|
||||
|
||||
public Set<IDIYComponent<?>> extractComponents(Set<String> types) {
|
||||
Set<IDIYComponent<?>> res = new HashSet<IDIYComponent<?>>();
|
||||
if (leaf != null && types.contains(leaf.getComponent().getClass().getCanonicalName())) {
|
||||
if (leaf != null && (types == null || types.contains(leaf.getComponent().getClass().getCanonicalName()))) {
|
||||
res.add(leaf.getComponent());
|
||||
} else if (children != null) {
|
||||
for (Tree t : children) {
|
||||
|
||||
@@ -389,6 +389,14 @@
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
<description>IEC variations of fuse and potentiometer symbols</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
<description>Detect the style of a treble bleed based on the topology and component values (e.g. Fender, DiMarzio, Kinman, etc)</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>BUG_FIX</changeType>
|
||||
<description>Tone capacitor mistaken for treble bleed when connected to the input lug of the volume pot</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>BUG_FIX</changeType>
|
||||
<description>Dragging a component from the component tree to the canvas sometimes does not work as expected without clicking on it first and then dragging it</description>
|
||||
|
||||
@@ -18,14 +18,7 @@
|
||||
*/
|
||||
package org.diylc.netlist;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
@@ -59,6 +52,7 @@ public class GuitarDiagramAnalyzer extends AbstractNetlistAnalyzer implements IN
|
||||
private static Set<String> CAP_TYPES = new HashSet<String>();
|
||||
private static Set<String> RESISTOR_TYPES = new HashSet<String>();
|
||||
private static Set<String> RC_TYPES = new HashSet<String>();
|
||||
private static Set<String> ALL_TYPES = null;
|
||||
|
||||
static {
|
||||
JACK_TYPES.add(OpenJack1_4.class.getCanonicalName());
|
||||
@@ -273,15 +267,15 @@ public class GuitarDiagramAnalyzer extends AbstractNetlistAnalyzer implements IN
|
||||
|
||||
// locate volume and tone pots
|
||||
Map<IDIYComponent<?>, List<IDIYComponent<?>>> volPotPickupMap =
|
||||
new HashMap<IDIYComponent<?>, List<IDIYComponent<?>>>();
|
||||
Map<IDIYComponent<?>, Set<IDIYComponent<?>>> volPotTrebleBleedMap =
|
||||
new HashMap<IDIYComponent<?>, Set<IDIYComponent<?>>>();
|
||||
new HashMap<>();
|
||||
Map<IDIYComponent<?>, TrebleBleed> volPotTrebleBleedMap =
|
||||
new HashMap<>();
|
||||
Map<IDIYComponent<?>, List<IDIYComponent<?>>> tonePotPickupMap =
|
||||
new HashMap<IDIYComponent<?>, List<IDIYComponent<?>>>();
|
||||
new HashMap<>();
|
||||
Map<IDIYComponent<?>, List<IDIYComponent<?>>> tonePotPickupReverseMap =
|
||||
new HashMap<IDIYComponent<?>, List<IDIYComponent<?>>>();
|
||||
new HashMap<>();
|
||||
Map<IDIYComponent<?>, List<IDIYComponent<?>>> volPotPickupReverseMap =
|
||||
new HashMap<IDIYComponent<?>, List<IDIYComponent<?>>>();
|
||||
new HashMap<>();
|
||||
|
||||
Set<IDIYComponent<?>> pots = tree.extractComponents(POT_TYPES);
|
||||
for (IDIYComponent<?> pot : pots) {
|
||||
@@ -360,12 +354,12 @@ public class GuitarDiagramAnalyzer extends AbstractNetlistAnalyzer implements IN
|
||||
}
|
||||
|
||||
private static void outputVolumePotentiometer(Map.Entry<IDIYComponent<?>, List<IDIYComponent<?>>> e,
|
||||
List<String> notes, Map<IDIYComponent<?>, Set<IDIYComponent<?>>> volPotTrebleBleedMap) {
|
||||
List<String> notes, Map<IDIYComponent<?>, TrebleBleed> volPotTrebleBleedMap) {
|
||||
StringBuilder sb = new StringBuilder(
|
||||
"'" + e.getKey().getName() + "' potentiometer acts as a volume control for ");
|
||||
boolean first = true;
|
||||
List<String> pickupNames =
|
||||
e.getValue().stream().map(x -> x.getName()).sorted().collect(Collectors.toList());
|
||||
e.getValue().stream().map(IDIYComponent::getName).sorted().toList();
|
||||
for (String pickupName : pickupNames) {
|
||||
if (!first)
|
||||
sb.append(pickupNames.size() == 2 ? " and " : ", ");
|
||||
@@ -374,21 +368,31 @@ public class GuitarDiagramAnalyzer extends AbstractNetlistAnalyzer implements IN
|
||||
}
|
||||
notes.add(sb.toString());
|
||||
|
||||
Set<IDIYComponent<?>> trebleBleedComponents = volPotTrebleBleedMap.get(e.getKey());
|
||||
if (trebleBleedComponents != null && trebleBleedComponents.size() > 0) {
|
||||
TrebleBleed trebleBleed = volPotTrebleBleedMap.get(e.getKey());
|
||||
Set<IDIYComponent<?>> trebleBleedComponents = trebleBleed.components();
|
||||
if (trebleBleedComponents != null && !trebleBleedComponents.isEmpty()) {
|
||||
|
||||
String trebleBleadNote = trebleBleedComponents.stream()
|
||||
.sorted(Comparator.comparing(c -> c.getName()))
|
||||
.map(c -> "'" + c.getName() + "'")
|
||||
.collect(Collectors.joining(", ")) + " form a treble bleed network on the '" + e.getKey().getName() + "' volume control";
|
||||
notes.add(trebleBleadNote);
|
||||
TrebleBleed.AnalysisResult analyze = trebleBleed.analyze();
|
||||
|
||||
String strComponents =
|
||||
trebleBleedComponents.stream().sorted(Comparator.comparing(IDIYComponent::getName))
|
||||
.map(c -> "'" + c.getName() + "'").collect(Collectors.joining(", "));
|
||||
String trebleBleedNote = strComponents + (trebleBleedComponents.size() == 1 ? " forms a " : " form a ");
|
||||
if (analyze.circuitType() != null) {
|
||||
trebleBleedNote += analyze.circuitType() + " ";
|
||||
}
|
||||
trebleBleedNote = trebleBleedNote + "treble bleed circuit on the '" + e.getKey().getName() + "' volume control";
|
||||
if (analyze.style() != null) {
|
||||
trebleBleedNote = trebleBleedNote + ", in the style of " + analyze.style();
|
||||
}
|
||||
notes.add(trebleBleedNote);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void processPotentiometer(IDIYComponent<?> pot, Tree tree, Map<IDIYComponent<?>, Tree> pickupRoots,
|
||||
Map<IDIYComponent<?>, List<IDIYComponent<?>>> tonePotPickupReverseMap,
|
||||
Map<IDIYComponent<?>, List<IDIYComponent<?>>> tonePotPickupMap,
|
||||
Map<IDIYComponent<?>, Set<IDIYComponent<?>>> volPotTrebleBleedMap,
|
||||
Map<IDIYComponent<?>, TrebleBleed> volPotTrebleBleedMap,
|
||||
Map<IDIYComponent<?>, List<IDIYComponent<?>>> volPotPickupMap,
|
||||
Map<IDIYComponent<?>, List<IDIYComponent<?>>> volPotPickupReverseMap) {
|
||||
TreeLeaf leaf1 = new TreeLeaf(pot, 0, 1);
|
||||
@@ -459,17 +463,27 @@ public class GuitarDiagramAnalyzer extends AbstractNetlistAnalyzer implements IN
|
||||
}
|
||||
|
||||
private void locateTrebleBleed(Tree tree,
|
||||
Map<IDIYComponent<?>, Set<IDIYComponent<?>>> volPotTrebleBleedMap, IDIYComponent<?> pot,
|
||||
Map<IDIYComponent<?>, TrebleBleed> volPotTrebleBleedMap, IDIYComponent<?> pot,
|
||||
Tree tree1) {
|
||||
Tree parent1 = tree1;
|
||||
do {
|
||||
parent1 = tree.findParent(parent1);
|
||||
} while (parent1 != null && parent1.getChildren().size() <= 1);
|
||||
if (parent1 != null) {
|
||||
Set<IDIYComponent<?>> trebleBleedComponents = parent1.extractComponents(RC_TYPES);
|
||||
if (trebleBleedComponents.stream().anyMatch(c -> CAP_TYPES.contains(c.getClass().getCanonicalName()))) {
|
||||
volPotTrebleBleedMap.computeIfAbsent(pot, k -> new HashSet<IDIYComponent<?>>()).addAll(trebleBleedComponents);
|
||||
}
|
||||
Optional<Tree> trebleTree =
|
||||
parent1.getChildren().stream().filter(t -> !t.equals(tree1)).findFirst();
|
||||
trebleTree.ifPresent(t -> {
|
||||
// transcend one layer down if the tree is nested
|
||||
while (t.getChildren().size() == 1 && t.getChildren().get(0).getLeaf() == null) {
|
||||
t = t.getChildren().get(0);
|
||||
}
|
||||
Set<IDIYComponent<?>> trebleBleedComponents = t.extractComponents(ALL_TYPES);
|
||||
if (trebleBleedComponents.stream().allMatch(c -> RC_TYPES.contains(c.getClass().getCanonicalName())) &&
|
||||
trebleBleedComponents.stream().anyMatch(c -> CAP_TYPES.contains(c.getClass().getCanonicalName()))) {
|
||||
TrebleBleed trebleBleed = new TrebleBleed(trebleBleedComponents, t.getConnectionType());
|
||||
volPotTrebleBleedMap.put(pot, trebleBleed);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
package org.diylc.netlist;
|
||||
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public record TrebleBleed(Set<IDIYComponent<?>> components, TreeConnectionType connectionType) {
|
||||
|
||||
public AnalysisResult analyze() {
|
||||
List<Double> capValues = new ArrayList<>();
|
||||
List<Double> resValues = new ArrayList<>();
|
||||
for (IDIYComponent<?> c : components) {
|
||||
if (c.getValue() instanceof org.diylc.core.measures.Capacitance) {
|
||||
Double nv = ((org.diylc.core.measures.Capacitance) c.getValue()).getNormalizedValue();
|
||||
if (nv != null) capValues.add(nv);
|
||||
} else if (c.getValue() instanceof org.diylc.core.measures.Resistance) {
|
||||
Double nv = ((org.diylc.core.measures.Resistance) c.getValue()).getNormalizedValue();
|
||||
if (nv != null) resValues.add(nv);
|
||||
}
|
||||
}
|
||||
|
||||
String circuitType;
|
||||
String style;
|
||||
if (components.size() == 1) {
|
||||
circuitType = null;
|
||||
style = "PRS, G&L";
|
||||
if (capValues.size() == 1) {
|
||||
Double cVal = capValues.get(0);
|
||||
if (matches(cVal, 180e-6)) {
|
||||
style = "PRS";
|
||||
} else if (matches(cVal, 200e-6)) {
|
||||
style = "G&L";
|
||||
}
|
||||
}
|
||||
} else if (components.size() == 2 && connectionType == TreeConnectionType.Series) {
|
||||
circuitType = "series";
|
||||
style = "Kinman";
|
||||
if (capValues.size() == 1 && resValues.size() == 1) {
|
||||
Double cVal = capValues.get(0);
|
||||
Double rVal = resValues.get(0);
|
||||
if (matches(cVal, 1.2e-3) && matches(rVal, 130e3)) {
|
||||
style = "Kinman";
|
||||
}
|
||||
}
|
||||
} else if (components.size() == 2 && connectionType == TreeConnectionType.Parallel) {
|
||||
circuitType = "parallel";
|
||||
style = "Fender, Suhr, Fralin, Bill Lawrence, Mojo Tone, TV Jones, DiMarzio, Seymour Duncan";
|
||||
if (capValues.size() == 1 && resValues.size() == 1) {
|
||||
Double cVal = capValues.get(0);
|
||||
Double rVal = resValues.get(0);
|
||||
if (matches(cVal, 330e-6) && matches(rVal, 80e3)) {
|
||||
style = "Bill Lawrence";
|
||||
} else if (matches(cVal, 471e-6) && matches(rVal, 220e3)) {
|
||||
style = "Mojo Tone";
|
||||
} else if (matches(cVal, 560e-6) && matches(rVal, 300e3)) {
|
||||
style = "DiMarzio";
|
||||
} else if (matches(cVal, 680e-6) && matches(rVal, 150e3)) {
|
||||
style = "John Suhr";
|
||||
} else if ((matches(cVal, 1e-3) || matches(cVal, 2e-3)) && matches(rVal, 150e3)) {
|
||||
style = "TV Jones";
|
||||
} else if (matches(cVal, 1e-3) && matches(rVal, 100e3)) {
|
||||
style = "Seymour Duncan";
|
||||
} else if (matches(cVal, 2.5e-3) && matches(rVal, 200e3)) {
|
||||
style = "Lindy Fralin";
|
||||
}
|
||||
}
|
||||
} else if (components.size() == 3) {
|
||||
circuitType = null;
|
||||
style = null;
|
||||
if (capValues.size() == 1 && resValues.size() == 2) {
|
||||
Double cVal = capValues.get(0);
|
||||
if (matches(cVal, 1.2e-3) && ((matches(resValues.get(0), 150e3) && matches(resValues.get(1), 20e3)) || (matches(resValues.get(0), 20e3) && matches(resValues.get(1), 150e3)))) {
|
||||
style = "Fender";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
circuitType = null;
|
||||
style = null;
|
||||
}
|
||||
|
||||
return new AnalysisResult(circuitType, style);
|
||||
}
|
||||
|
||||
private static boolean matches(Double val, double expected) {
|
||||
return val != null && Math.abs(val - expected) < expected * 1e-4;
|
||||
}
|
||||
|
||||
public record AnalysisResult(String circuitType, String style) {}
|
||||
}
|
||||
Reference in New Issue
Block a user