| 1 | package com.github.dakusui.symfonion.song; | |
| 2 | ||
| 3 | import com.github.dakusui.json.JsonFormatException; | |
| 4 | import com.github.dakusui.json.JsonInvalidPathException; | |
| 5 | import com.github.dakusui.json.JsonTypeMismatchException; | |
| 6 | import com.github.dakusui.json.JsonUtils; | |
| 7 | import com.github.dakusui.symfonion.utils.Fraction; | |
| 8 | import com.github.dakusui.symfonion.exceptions.SymfonionException; | |
| 9 | import com.github.dakusui.symfonion.utils.Utils; | |
| 10 | import com.google.gson.JsonArray; | |
| 11 | import com.google.gson.JsonElement; | |
| 12 | import com.google.gson.JsonObject; | |
| 13 | ||
| 14 | import java.util.LinkedList; | |
| 15 | import java.util.List; | |
| 16 | ||
| 17 | import static com.github.dakusui.symfonion.exceptions.ExceptionThrower.*; | |
| 18 | import static com.github.dakusui.symfonion.exceptions.SymfonionIllegalFormatException.NOTE_LENGTH_EXAMPLE; | |
| 19 | import static com.github.dakusui.symfonion.exceptions.SymfonionTypeMismatchException.OBJECT; | |
| 20 | ||
| 21 | public class Groove { | |
| 22 | public static final Groove DEFAULT_INSTANCE = new Groove(); | |
| 23 | ||
| 24 | record Beat(Fraction length, long ticks, int accent) { | |
| 25 | } | |
| 26 | ||
| 27 | public record Unit(long pos, int accentDelta) { | |
| 28 | ||
| 29 | public int accent() { | |
| 30 |
1
1. accent : replaced int return with 0 for com/github/dakusui/symfonion/song/Groove$Unit::accent → SURVIVED |
return this.accentDelta; |
| 31 | } | |
| 32 | } | |
| 33 | | |
| 34 | List<Beat> beats = new LinkedList<>(); | |
| 35 | | |
| 36 | private final int resolution; | |
| 37 | | |
| 38 | public Groove() { | |
| 39 | this(384); | |
| 40 | } | |
| 41 | | |
| 42 | public Groove(int resolution) { | |
| 43 | this.resolution = resolution; | |
| 44 | } | |
| 45 | | |
| 46 | public Unit resolve(Fraction offset) { | |
| 47 |
1
1. resolve : negated conditional → KILLED |
if (offset == null) { |
| 48 | String msg = "offset cannot be null. (Groove#resolve)"; | |
| 49 | throw runtimeException(msg, null); | |
| 50 | } | |
| 51 |
2
1. resolve : changed conditional boundary → KILLED 2. resolve : negated conditional → KILLED |
if (Fraction.compare(offset, Fraction.zero) < 0) { |
| 52 | String msg = "offset cannot be negative. (Groove#resolve)"; | |
| 53 | throw runtimeException(msg, null); | |
| 54 | } | |
| 55 | long pos = 0; | |
| 56 | | |
| 57 | Fraction rest = offset.clone(); | |
| 58 | int i = 0; | |
| 59 |
2
1. resolve : negated conditional → KILLED 2. resolve : changed conditional boundary → KILLED |
while (Fraction.compare(rest, Fraction.zero) > 0) { |
| 60 |
2
1. resolve : negated conditional → KILLED 2. resolve : changed conditional boundary → KILLED |
if (i >= this.beats.size()) { |
| 61 | break; | |
| 62 | } | |
| 63 | Beat beat = this.beats.get(i); | |
| 64 | rest = Fraction.subtract(rest, beat.length); | |
| 65 |
1
1. resolve : Replaced long addition with subtraction → KILLED |
pos += beat.ticks; |
| 66 |
1
1. resolve : Changed increment from 1 to -1 → KILLED |
i++; |
| 67 | } | |
| 68 | long p; | |
| 69 | int d = 0; | |
| 70 |
2
1. resolve : changed conditional boundary → KILLED 2. resolve : negated conditional → KILLED |
if (Fraction.compare(rest, Fraction.zero) < 0) { |
| 71 |
1
1. resolve : Replaced integer subtraction with addition → SURVIVED |
Beat beat = this.beats.get(i - 1); |
| 72 |
2
1. resolve : Replaced double addition with subtraction → KILLED 2. resolve : Replaced double multiplication with division → KILLED |
p = (long) (pos + Fraction.div(rest, beat.length).doubleValue() * beat.ticks); |
| 73 |
1
1. resolve : negated conditional → KILLED |
} else if (Fraction.compare(rest, Fraction.zero) == 0) { |
| 74 |
2
1. resolve : negated conditional → KILLED 2. resolve : changed conditional boundary → KILLED |
if (i < this.beats.size()) { |
| 75 | d = this.beats.get(i).accent; | |
| 76 | } | |
| 77 | p = pos; | |
| 78 | } else { | |
| 79 |
2
1. resolve : Replaced long addition with subtraction → KILLED 2. resolve : Replaced double multiplication with division → KILLED |
p = (pos + (long) (rest.doubleValue() * this.resolution)); |
| 80 | } | |
| 81 |
1
1. resolve : replaced return value with null for com/github/dakusui/symfonion/song/Groove::resolve → KILLED |
return new Unit(p, d); |
| 82 | } | |
| 83 | | |
| 84 | public void add(Fraction length, long ticks, int accent) { | |
| 85 |
1
1. add : negated conditional → KILLED |
if (this == DEFAULT_INSTANCE) { |
| 86 | throw runtimeException("Groove.DEFAULT_INSTANCE is immutable.", null); | |
| 87 | } | |
| 88 | beats.add(new Beat(length, ticks, accent)); | |
| 89 | } | |
| 90 | | |
| 91 | public static Groove createGroove(JsonArray grooveDef) throws SymfonionException, JsonTypeMismatchException, JsonInvalidPathException, JsonFormatException { | |
| 92 | Groove ret = new Groove(); | |
| 93 | for (JsonElement elem : grooveDef) { | |
| 94 |
1
1. createGroove : negated conditional → KILLED |
if (!elem.isJsonObject()) { |
| 95 | throw typeMismatchException(elem, OBJECT); | |
| 96 | } | |
| 97 | JsonObject cur = elem.getAsJsonObject(); | |
| 98 | String len = JsonUtils.asString(cur, Keyword.$length); | |
| 99 | long ticks = JsonUtils.asLong(cur, Keyword.$ticks); | |
| 100 | int accent = JsonUtils.asInt(cur, Keyword.$accent); | |
| 101 | | |
| 102 | Fraction f = Utils.parseNoteLength(len); | |
| 103 |
1
1. createGroove : negated conditional → KILLED |
if (f == null) { |
| 104 | throw illegalFormatException(JsonUtils.asJsonElement(cur, Keyword.$length), NOTE_LENGTH_EXAMPLE); | |
| 105 | } | |
| 106 |
1
1. createGroove : removed call to com/github/dakusui/symfonion/song/Groove::add → KILLED |
ret.add(f, ticks, accent); |
| 107 | } | |
| 108 |
1
1. createGroove : replaced return value with null for com/github/dakusui/symfonion/song/Groove::createGroove → KILLED |
return ret; |
| 109 | } | |
| 110 | } | |
| 111 | ||
Mutations | ||
| 30 |
1.1 |
|
| 47 |
1.1 |
|
| 51 |
1.1 2.2 |
|
| 59 |
1.1 2.2 |
|
| 60 |
1.1 2.2 |
|
| 65 |
1.1 |
|
| 66 |
1.1 |
|
| 70 |
1.1 2.2 |
|
| 71 |
1.1 |
|
| 72 |
1.1 2.2 |
|
| 73 |
1.1 |
|
| 74 |
1.1 2.2 |
|
| 79 |
1.1 2.2 |
|
| 81 |
1.1 |
|
| 85 |
1.1 |
|
| 94 |
1.1 |
|
| 103 |
1.1 |
|
| 106 |
1.1 |
|
| 108 |
1.1 |