diff --git a/.idea/misc.xml b/.idea/misc.xml
index 447e0d3..5c9d3cd 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -8,10 +8,11 @@
+
-
+
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 447e0d3..5c9d3cd 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -8,10 +8,11 @@
+
-
+
diff --git a/app/src/main/java/com/lukas/music/song/Scale.kt b/app/src/main/java/com/lukas/music/song/Scale.kt
new file mode 100644
index 0000000..bc016cb
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/song/Scale.kt
@@ -0,0 +1,19 @@
+package com.lukas.music.song
+
+import com.lukas.music.song.chords.ChordType
+
+enum class Scale(val identifier: String, val steps: Array, val chordTypes: Array) {
+ MAJOR(
+ "major",
+ arrayOf(0, 2, 4, 5, 7, 9, 11, 12),
+ arrayOf(
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.MINOR,
+ ChordType.MAJOR,
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.DIMINISHED
+ )
+ )
+}
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 447e0d3..5c9d3cd 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -8,10 +8,11 @@
+
-
+
diff --git a/app/src/main/java/com/lukas/music/song/Scale.kt b/app/src/main/java/com/lukas/music/song/Scale.kt
new file mode 100644
index 0000000..bc016cb
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/song/Scale.kt
@@ -0,0 +1,19 @@
+package com.lukas.music.song
+
+import com.lukas.music.song.chords.ChordType
+
+enum class Scale(val identifier: String, val steps: Array, val chordTypes: Array) {
+ MAJOR(
+ "major",
+ arrayOf(0, 2, 4, 5, 7, 9, 11, 12),
+ arrayOf(
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.MINOR,
+ ChordType.MAJOR,
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.DIMINISHED
+ )
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/Song.kt b/app/src/main/java/com/lukas/music/song/Song.kt
index 9dd3cb8..4b23eac 100644
--- a/app/src/main/java/com/lukas/music/song/Song.kt
+++ b/app/src/main/java/com/lukas/music/song/Song.kt
@@ -3,6 +3,7 @@
import android.os.Handler
import android.os.Looper
import android.widget.RadioButton
+import android.widget.TextView
import com.lukas.music.instruments.Instrument
import com.lukas.music.song.chords.Chord
import com.lukas.music.song.chords.ChordProgression
@@ -16,6 +17,7 @@
private var beat = 0
private var chord: Chord = chordProgression.step()
val stepButtons = mutableListOf()
+ lateinit var chordDisplay: TextView
fun step() {
Handler(Looper.getMainLooper()).post {
@@ -31,6 +33,7 @@
for (voice in Instrument.voice) {
voice.step(root, chordNotes)
}
+ chordDisplay.text = chord.toString(true, root)
}
}
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 447e0d3..5c9d3cd 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -8,10 +8,11 @@
+
-
+
diff --git a/app/src/main/java/com/lukas/music/song/Scale.kt b/app/src/main/java/com/lukas/music/song/Scale.kt
new file mode 100644
index 0000000..bc016cb
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/song/Scale.kt
@@ -0,0 +1,19 @@
+package com.lukas.music.song
+
+import com.lukas.music.song.chords.ChordType
+
+enum class Scale(val identifier: String, val steps: Array, val chordTypes: Array) {
+ MAJOR(
+ "major",
+ arrayOf(0, 2, 4, 5, 7, 9, 11, 12),
+ arrayOf(
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.MINOR,
+ ChordType.MAJOR,
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.DIMINISHED
+ )
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/Song.kt b/app/src/main/java/com/lukas/music/song/Song.kt
index 9dd3cb8..4b23eac 100644
--- a/app/src/main/java/com/lukas/music/song/Song.kt
+++ b/app/src/main/java/com/lukas/music/song/Song.kt
@@ -3,6 +3,7 @@
import android.os.Handler
import android.os.Looper
import android.widget.RadioButton
+import android.widget.TextView
import com.lukas.music.instruments.Instrument
import com.lukas.music.song.chords.Chord
import com.lukas.music.song.chords.ChordProgression
@@ -16,6 +17,7 @@
private var beat = 0
private var chord: Chord = chordProgression.step()
val stepButtons = mutableListOf()
+ lateinit var chordDisplay: TextView
fun step() {
Handler(Looper.getMainLooper()).post {
@@ -31,6 +33,7 @@
for (voice in Instrument.voice) {
voice.step(root, chordNotes)
}
+ chordDisplay.text = chord.toString(true, root)
}
}
diff --git a/app/src/main/java/com/lukas/music/song/chords/Chord.kt b/app/src/main/java/com/lukas/music/song/chords/Chord.kt
index 61dac11..e0dd8fc 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Chord.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Chord.kt
@@ -2,8 +2,13 @@
import com.lukas.music.song.note.Note
-class Chord(val note: Int, private val chordType: ChordType) {
- private val interval = Interval(note)
+class Chord(note: Int, var chordType: ChordType) {
+ var note: Int = note
+ set(value) {
+ field = value
+ interval = Interval(value)
+ }
+ var interval = Interval(note)
fun getNotes(root: Note): Array {
return Array(chordType.notes.size) { root + note + chordType.notes[it] }
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 447e0d3..5c9d3cd 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -8,10 +8,11 @@
+
-
+
diff --git a/app/src/main/java/com/lukas/music/song/Scale.kt b/app/src/main/java/com/lukas/music/song/Scale.kt
new file mode 100644
index 0000000..bc016cb
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/song/Scale.kt
@@ -0,0 +1,19 @@
+package com.lukas.music.song
+
+import com.lukas.music.song.chords.ChordType
+
+enum class Scale(val identifier: String, val steps: Array, val chordTypes: Array) {
+ MAJOR(
+ "major",
+ arrayOf(0, 2, 4, 5, 7, 9, 11, 12),
+ arrayOf(
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.MINOR,
+ ChordType.MAJOR,
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.DIMINISHED
+ )
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/Song.kt b/app/src/main/java/com/lukas/music/song/Song.kt
index 9dd3cb8..4b23eac 100644
--- a/app/src/main/java/com/lukas/music/song/Song.kt
+++ b/app/src/main/java/com/lukas/music/song/Song.kt
@@ -3,6 +3,7 @@
import android.os.Handler
import android.os.Looper
import android.widget.RadioButton
+import android.widget.TextView
import com.lukas.music.instruments.Instrument
import com.lukas.music.song.chords.Chord
import com.lukas.music.song.chords.ChordProgression
@@ -16,6 +17,7 @@
private var beat = 0
private var chord: Chord = chordProgression.step()
val stepButtons = mutableListOf()
+ lateinit var chordDisplay: TextView
fun step() {
Handler(Looper.getMainLooper()).post {
@@ -31,6 +33,7 @@
for (voice in Instrument.voice) {
voice.step(root, chordNotes)
}
+ chordDisplay.text = chord.toString(true, root)
}
}
diff --git a/app/src/main/java/com/lukas/music/song/chords/Chord.kt b/app/src/main/java/com/lukas/music/song/chords/Chord.kt
index 61dac11..e0dd8fc 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Chord.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Chord.kt
@@ -2,8 +2,13 @@
import com.lukas.music.song.note.Note
-class Chord(val note: Int, private val chordType: ChordType) {
- private val interval = Interval(note)
+class Chord(note: Int, var chordType: ChordType) {
+ var note: Int = note
+ set(value) {
+ field = value
+ interval = Interval(value)
+ }
+ var interval = Interval(note)
fun getNotes(root: Note): Array {
return Array(chordType.notes.size) { root + note + chordType.notes[it] }
diff --git a/app/src/main/java/com/lukas/music/song/chords/ChordType.kt b/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
index e53189a..95b69a0 100644
--- a/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
@@ -5,11 +5,16 @@
private val asString: String,
val transform: (String) -> String
) {
- Major(arrayOf(0, 4, 7), "major", { it.uppercase() }),
- Minor(arrayOf(0, 3, 7), "minor", { it.lowercase() }),
+ MAJOR(arrayOf(0, 4, 7), "major", { it.uppercase() }),
+ MINOR(arrayOf(0, 3, 7), "minor", { it.lowercase() }),
+ DIMINISHED(arrayOf(0, 3, 6), "diminished", { it.lowercase() + "0" }),
;
override fun toString(): String {
return asString
}
+
+ companion object {
+ val VALUES = values()
+ }
}
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 447e0d3..5c9d3cd 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -8,10 +8,11 @@
+
-
+
diff --git a/app/src/main/java/com/lukas/music/song/Scale.kt b/app/src/main/java/com/lukas/music/song/Scale.kt
new file mode 100644
index 0000000..bc016cb
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/song/Scale.kt
@@ -0,0 +1,19 @@
+package com.lukas.music.song
+
+import com.lukas.music.song.chords.ChordType
+
+enum class Scale(val identifier: String, val steps: Array, val chordTypes: Array) {
+ MAJOR(
+ "major",
+ arrayOf(0, 2, 4, 5, 7, 9, 11, 12),
+ arrayOf(
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.MINOR,
+ ChordType.MAJOR,
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.DIMINISHED
+ )
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/Song.kt b/app/src/main/java/com/lukas/music/song/Song.kt
index 9dd3cb8..4b23eac 100644
--- a/app/src/main/java/com/lukas/music/song/Song.kt
+++ b/app/src/main/java/com/lukas/music/song/Song.kt
@@ -3,6 +3,7 @@
import android.os.Handler
import android.os.Looper
import android.widget.RadioButton
+import android.widget.TextView
import com.lukas.music.instruments.Instrument
import com.lukas.music.song.chords.Chord
import com.lukas.music.song.chords.ChordProgression
@@ -16,6 +17,7 @@
private var beat = 0
private var chord: Chord = chordProgression.step()
val stepButtons = mutableListOf()
+ lateinit var chordDisplay: TextView
fun step() {
Handler(Looper.getMainLooper()).post {
@@ -31,6 +33,7 @@
for (voice in Instrument.voice) {
voice.step(root, chordNotes)
}
+ chordDisplay.text = chord.toString(true, root)
}
}
diff --git a/app/src/main/java/com/lukas/music/song/chords/Chord.kt b/app/src/main/java/com/lukas/music/song/chords/Chord.kt
index 61dac11..e0dd8fc 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Chord.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Chord.kt
@@ -2,8 +2,13 @@
import com.lukas.music.song.note.Note
-class Chord(val note: Int, private val chordType: ChordType) {
- private val interval = Interval(note)
+class Chord(note: Int, var chordType: ChordType) {
+ var note: Int = note
+ set(value) {
+ field = value
+ interval = Interval(value)
+ }
+ var interval = Interval(note)
fun getNotes(root: Note): Array {
return Array(chordType.notes.size) { root + note + chordType.notes[it] }
diff --git a/app/src/main/java/com/lukas/music/song/chords/ChordType.kt b/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
index e53189a..95b69a0 100644
--- a/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
@@ -5,11 +5,16 @@
private val asString: String,
val transform: (String) -> String
) {
- Major(arrayOf(0, 4, 7), "major", { it.uppercase() }),
- Minor(arrayOf(0, 3, 7), "minor", { it.lowercase() }),
+ MAJOR(arrayOf(0, 4, 7), "major", { it.uppercase() }),
+ MINOR(arrayOf(0, 3, 7), "minor", { it.lowercase() }),
+ DIMINISHED(arrayOf(0, 3, 6), "diminished", { it.lowercase() + "0" }),
;
override fun toString(): String {
return asString
}
+
+ companion object {
+ val VALUES = values()
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/chords/Interval.kt b/app/src/main/java/com/lukas/music/song/chords/Interval.kt
index b3b4480..60a6ced 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Interval.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Interval.kt
@@ -1,7 +1,7 @@
package com.lukas.music.song.chords
class Interval(private val distance: Int) {
- private val name: IntervalName = when (distance) {
+ val name: IntervalName = when (distance) {
0 -> IntervalName.UNISON
1, 2 -> IntervalName.SECOND
3, 4 -> IntervalName.THIRD
@@ -13,7 +13,7 @@
else -> throw IllegalArgumentException("cannot make interval from distance $distance")
}
private val modifier: Modifier = when (distance) {
- 0, 5, 12 -> Modifier.PERFECT
+ 0, 7, 12 -> Modifier.PERFECT
1, 3, 5, 8, 10 -> Modifier.MINOR
else -> Modifier.MAJOR
}
@@ -36,12 +36,20 @@
override fun toString(): String {
return romanVersion
}
+
+ companion object {
+ val VALUES = values()
+ val NAMES = Array(VALUES.size) { VALUES[it].romanVersion }
+ }
}
enum class Modifier(val descriptor: String, val offset: Int) {
PERFECT("", 0),
MINOR("", 0),
MAJOR("", 1);
- }
+ companion object {
+ val VALUES = values()
+ }
+ }
}
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 447e0d3..5c9d3cd 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -8,10 +8,11 @@
+
-
+
diff --git a/app/src/main/java/com/lukas/music/song/Scale.kt b/app/src/main/java/com/lukas/music/song/Scale.kt
new file mode 100644
index 0000000..bc016cb
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/song/Scale.kt
@@ -0,0 +1,19 @@
+package com.lukas.music.song
+
+import com.lukas.music.song.chords.ChordType
+
+enum class Scale(val identifier: String, val steps: Array, val chordTypes: Array) {
+ MAJOR(
+ "major",
+ arrayOf(0, 2, 4, 5, 7, 9, 11, 12),
+ arrayOf(
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.MINOR,
+ ChordType.MAJOR,
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.DIMINISHED
+ )
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/Song.kt b/app/src/main/java/com/lukas/music/song/Song.kt
index 9dd3cb8..4b23eac 100644
--- a/app/src/main/java/com/lukas/music/song/Song.kt
+++ b/app/src/main/java/com/lukas/music/song/Song.kt
@@ -3,6 +3,7 @@
import android.os.Handler
import android.os.Looper
import android.widget.RadioButton
+import android.widget.TextView
import com.lukas.music.instruments.Instrument
import com.lukas.music.song.chords.Chord
import com.lukas.music.song.chords.ChordProgression
@@ -16,6 +17,7 @@
private var beat = 0
private var chord: Chord = chordProgression.step()
val stepButtons = mutableListOf()
+ lateinit var chordDisplay: TextView
fun step() {
Handler(Looper.getMainLooper()).post {
@@ -31,6 +33,7 @@
for (voice in Instrument.voice) {
voice.step(root, chordNotes)
}
+ chordDisplay.text = chord.toString(true, root)
}
}
diff --git a/app/src/main/java/com/lukas/music/song/chords/Chord.kt b/app/src/main/java/com/lukas/music/song/chords/Chord.kt
index 61dac11..e0dd8fc 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Chord.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Chord.kt
@@ -2,8 +2,13 @@
import com.lukas.music.song.note.Note
-class Chord(val note: Int, private val chordType: ChordType) {
- private val interval = Interval(note)
+class Chord(note: Int, var chordType: ChordType) {
+ var note: Int = note
+ set(value) {
+ field = value
+ interval = Interval(value)
+ }
+ var interval = Interval(note)
fun getNotes(root: Note): Array {
return Array(chordType.notes.size) { root + note + chordType.notes[it] }
diff --git a/app/src/main/java/com/lukas/music/song/chords/ChordType.kt b/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
index e53189a..95b69a0 100644
--- a/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
@@ -5,11 +5,16 @@
private val asString: String,
val transform: (String) -> String
) {
- Major(arrayOf(0, 4, 7), "major", { it.uppercase() }),
- Minor(arrayOf(0, 3, 7), "minor", { it.lowercase() }),
+ MAJOR(arrayOf(0, 4, 7), "major", { it.uppercase() }),
+ MINOR(arrayOf(0, 3, 7), "minor", { it.lowercase() }),
+ DIMINISHED(arrayOf(0, 3, 6), "diminished", { it.lowercase() + "0" }),
;
override fun toString(): String {
return asString
}
+
+ companion object {
+ val VALUES = values()
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/chords/Interval.kt b/app/src/main/java/com/lukas/music/song/chords/Interval.kt
index b3b4480..60a6ced 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Interval.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Interval.kt
@@ -1,7 +1,7 @@
package com.lukas.music.song.chords
class Interval(private val distance: Int) {
- private val name: IntervalName = when (distance) {
+ val name: IntervalName = when (distance) {
0 -> IntervalName.UNISON
1, 2 -> IntervalName.SECOND
3, 4 -> IntervalName.THIRD
@@ -13,7 +13,7 @@
else -> throw IllegalArgumentException("cannot make interval from distance $distance")
}
private val modifier: Modifier = when (distance) {
- 0, 5, 12 -> Modifier.PERFECT
+ 0, 7, 12 -> Modifier.PERFECT
1, 3, 5, 8, 10 -> Modifier.MINOR
else -> Modifier.MAJOR
}
@@ -36,12 +36,20 @@
override fun toString(): String {
return romanVersion
}
+
+ companion object {
+ val VALUES = values()
+ val NAMES = Array(VALUES.size) { VALUES[it].romanVersion }
+ }
}
enum class Modifier(val descriptor: String, val offset: Int) {
PERFECT("", 0),
MINOR("", 0),
MAJOR("", 1);
- }
+ companion object {
+ val VALUES = values()
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/chords/Phrase.kt b/app/src/main/java/com/lukas/music/song/chords/Phrase.kt
index 76d4259..611d1b8 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Phrase.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Phrase.kt
@@ -2,20 +2,21 @@
class Phrase {
val chords = mutableListOf(
- Chord(0, ChordType.Major),
- Chord(5, ChordType.Major),
- Chord(2, ChordType.Minor),
- Chord(7, ChordType.Major),
+ Chord(0, ChordType.MAJOR),
+ Chord(5, ChordType.MAJOR),
+ Chord(2, ChordType.MINOR),
+ Chord(7, ChordType.MAJOR),
)
var position = 0
fun step(parent: ChordProgression): Chord {
var parent: ChordProgression = parent
+ val result = chords[position]
position++
if (position >= chords.size) {
position = 0
parent++
}
- return chords[position]
+ return result
}
}
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 447e0d3..5c9d3cd 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -8,10 +8,11 @@
+
-
+
diff --git a/app/src/main/java/com/lukas/music/song/Scale.kt b/app/src/main/java/com/lukas/music/song/Scale.kt
new file mode 100644
index 0000000..bc016cb
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/song/Scale.kt
@@ -0,0 +1,19 @@
+package com.lukas.music.song
+
+import com.lukas.music.song.chords.ChordType
+
+enum class Scale(val identifier: String, val steps: Array, val chordTypes: Array) {
+ MAJOR(
+ "major",
+ arrayOf(0, 2, 4, 5, 7, 9, 11, 12),
+ arrayOf(
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.MINOR,
+ ChordType.MAJOR,
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.DIMINISHED
+ )
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/Song.kt b/app/src/main/java/com/lukas/music/song/Song.kt
index 9dd3cb8..4b23eac 100644
--- a/app/src/main/java/com/lukas/music/song/Song.kt
+++ b/app/src/main/java/com/lukas/music/song/Song.kt
@@ -3,6 +3,7 @@
import android.os.Handler
import android.os.Looper
import android.widget.RadioButton
+import android.widget.TextView
import com.lukas.music.instruments.Instrument
import com.lukas.music.song.chords.Chord
import com.lukas.music.song.chords.ChordProgression
@@ -16,6 +17,7 @@
private var beat = 0
private var chord: Chord = chordProgression.step()
val stepButtons = mutableListOf()
+ lateinit var chordDisplay: TextView
fun step() {
Handler(Looper.getMainLooper()).post {
@@ -31,6 +33,7 @@
for (voice in Instrument.voice) {
voice.step(root, chordNotes)
}
+ chordDisplay.text = chord.toString(true, root)
}
}
diff --git a/app/src/main/java/com/lukas/music/song/chords/Chord.kt b/app/src/main/java/com/lukas/music/song/chords/Chord.kt
index 61dac11..e0dd8fc 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Chord.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Chord.kt
@@ -2,8 +2,13 @@
import com.lukas.music.song.note.Note
-class Chord(val note: Int, private val chordType: ChordType) {
- private val interval = Interval(note)
+class Chord(note: Int, var chordType: ChordType) {
+ var note: Int = note
+ set(value) {
+ field = value
+ interval = Interval(value)
+ }
+ var interval = Interval(note)
fun getNotes(root: Note): Array {
return Array(chordType.notes.size) { root + note + chordType.notes[it] }
diff --git a/app/src/main/java/com/lukas/music/song/chords/ChordType.kt b/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
index e53189a..95b69a0 100644
--- a/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
@@ -5,11 +5,16 @@
private val asString: String,
val transform: (String) -> String
) {
- Major(arrayOf(0, 4, 7), "major", { it.uppercase() }),
- Minor(arrayOf(0, 3, 7), "minor", { it.lowercase() }),
+ MAJOR(arrayOf(0, 4, 7), "major", { it.uppercase() }),
+ MINOR(arrayOf(0, 3, 7), "minor", { it.lowercase() }),
+ DIMINISHED(arrayOf(0, 3, 6), "diminished", { it.lowercase() + "0" }),
;
override fun toString(): String {
return asString
}
+
+ companion object {
+ val VALUES = values()
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/chords/Interval.kt b/app/src/main/java/com/lukas/music/song/chords/Interval.kt
index b3b4480..60a6ced 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Interval.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Interval.kt
@@ -1,7 +1,7 @@
package com.lukas.music.song.chords
class Interval(private val distance: Int) {
- private val name: IntervalName = when (distance) {
+ val name: IntervalName = when (distance) {
0 -> IntervalName.UNISON
1, 2 -> IntervalName.SECOND
3, 4 -> IntervalName.THIRD
@@ -13,7 +13,7 @@
else -> throw IllegalArgumentException("cannot make interval from distance $distance")
}
private val modifier: Modifier = when (distance) {
- 0, 5, 12 -> Modifier.PERFECT
+ 0, 7, 12 -> Modifier.PERFECT
1, 3, 5, 8, 10 -> Modifier.MINOR
else -> Modifier.MAJOR
}
@@ -36,12 +36,20 @@
override fun toString(): String {
return romanVersion
}
+
+ companion object {
+ val VALUES = values()
+ val NAMES = Array(VALUES.size) { VALUES[it].romanVersion }
+ }
}
enum class Modifier(val descriptor: String, val offset: Int) {
PERFECT("", 0),
MINOR("", 0),
MAJOR("", 1);
- }
+ companion object {
+ val VALUES = values()
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/chords/Phrase.kt b/app/src/main/java/com/lukas/music/song/chords/Phrase.kt
index 76d4259..611d1b8 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Phrase.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Phrase.kt
@@ -2,20 +2,21 @@
class Phrase {
val chords = mutableListOf(
- Chord(0, ChordType.Major),
- Chord(5, ChordType.Major),
- Chord(2, ChordType.Minor),
- Chord(7, ChordType.Major),
+ Chord(0, ChordType.MAJOR),
+ Chord(5, ChordType.MAJOR),
+ Chord(2, ChordType.MINOR),
+ Chord(7, ChordType.MAJOR),
)
var position = 0
fun step(parent: ChordProgression): Chord {
var parent: ChordProgression = parent
+ val result = chords[position]
position++
if (position >= chords.size) {
position = 0
parent++
}
- return chords[position]
+ return result
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
new file mode 100644
index 0000000..2f3bbb2
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
@@ -0,0 +1,92 @@
+package com.lukas.music.ui.fragments
+
+import android.R
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import androidx.fragment.app.DialogFragment
+import com.lukas.music.databinding.FragmentEditChordBinding
+import com.lukas.music.song.Scale
+import com.lukas.music.song.Song
+import com.lukas.music.song.chords.Chord
+import com.lukas.music.song.chords.ChordType
+import com.lukas.music.song.chords.Interval
+
+class EditChordFragment(val chord: Chord, val songFragment: SongFragment) : DialogFragment() {
+ lateinit var binding: FragmentEditChordBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentEditChordBinding.inflate(inflater)
+ setupPitchSpinner()
+ setupTypeSpinner()
+ binding.exitButton.setOnClickListener {
+ dismiss()
+ }
+ return binding.root
+ }
+
+ private fun setupPitchSpinner() {
+ val pitches = if (songFragment.displayChordNames) {
+ Array(Scale.MAJOR.steps.size) { (Song.currentSong.root + Scale.MAJOR.steps[it]).noteName.toString() }
+ } else Interval.IntervalName.NAMES
+ val pitchAdapter = ArrayAdapter(
+ binding.root.context,
+ R.layout.simple_spinner_dropdown_item, pitches
+ )
+ binding.pitchSpinner.adapter = pitchAdapter
+ binding.pitchSpinner.setSelection(chord.interval.name.ordinal)
+ binding.pitchSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ override fun onItemSelected(
+ parent: AdapterView<*>?,
+ view: View?,
+ position: Int,
+ id: Long
+ ) {
+ chord.note = Scale.MAJOR.steps[position]
+ songFragment.updateChords()
+ }
+
+ override fun onNothingSelected(parent: AdapterView<*>?) {}
+ }
+ }
+
+ private fun setupTypeSpinner() {
+ val values = mutableListOf("default")
+ for (chordType in ChordType.VALUES) {
+ values += chordType.toString()
+ }
+ val modifierAdapter = ArrayAdapter(
+ binding.root.context,
+ R.layout.simple_spinner_dropdown_item, values
+ )
+ binding.typeSpinner.adapter = modifierAdapter
+ binding.typeSpinner.setSelection(
+ if (chord.chordType == Scale.MAJOR.chordTypes[chord.interval.name.ordinal])
+ 0
+ else chord.chordType.ordinal + 1
+ )
+ binding.typeSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ override fun onItemSelected(
+ parent: AdapterView<*>?,
+ view: View?,
+ position: Int,
+ id: Long
+ ) {
+ if (position == 0) {
+ chord.chordType = Scale.MAJOR.chordTypes[chord.interval.name.ordinal]
+ } else {
+ chord.chordType = ChordType.VALUES[position - 1]
+ }
+ songFragment.updateChords()
+ }
+
+ override fun onNothingSelected(parent: AdapterView<*>?) {}
+ }
+ }
+}
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 447e0d3..5c9d3cd 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -8,10 +8,11 @@
+
-
+
diff --git a/app/src/main/java/com/lukas/music/song/Scale.kt b/app/src/main/java/com/lukas/music/song/Scale.kt
new file mode 100644
index 0000000..bc016cb
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/song/Scale.kt
@@ -0,0 +1,19 @@
+package com.lukas.music.song
+
+import com.lukas.music.song.chords.ChordType
+
+enum class Scale(val identifier: String, val steps: Array, val chordTypes: Array) {
+ MAJOR(
+ "major",
+ arrayOf(0, 2, 4, 5, 7, 9, 11, 12),
+ arrayOf(
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.MINOR,
+ ChordType.MAJOR,
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.DIMINISHED
+ )
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/Song.kt b/app/src/main/java/com/lukas/music/song/Song.kt
index 9dd3cb8..4b23eac 100644
--- a/app/src/main/java/com/lukas/music/song/Song.kt
+++ b/app/src/main/java/com/lukas/music/song/Song.kt
@@ -3,6 +3,7 @@
import android.os.Handler
import android.os.Looper
import android.widget.RadioButton
+import android.widget.TextView
import com.lukas.music.instruments.Instrument
import com.lukas.music.song.chords.Chord
import com.lukas.music.song.chords.ChordProgression
@@ -16,6 +17,7 @@
private var beat = 0
private var chord: Chord = chordProgression.step()
val stepButtons = mutableListOf()
+ lateinit var chordDisplay: TextView
fun step() {
Handler(Looper.getMainLooper()).post {
@@ -31,6 +33,7 @@
for (voice in Instrument.voice) {
voice.step(root, chordNotes)
}
+ chordDisplay.text = chord.toString(true, root)
}
}
diff --git a/app/src/main/java/com/lukas/music/song/chords/Chord.kt b/app/src/main/java/com/lukas/music/song/chords/Chord.kt
index 61dac11..e0dd8fc 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Chord.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Chord.kt
@@ -2,8 +2,13 @@
import com.lukas.music.song.note.Note
-class Chord(val note: Int, private val chordType: ChordType) {
- private val interval = Interval(note)
+class Chord(note: Int, var chordType: ChordType) {
+ var note: Int = note
+ set(value) {
+ field = value
+ interval = Interval(value)
+ }
+ var interval = Interval(note)
fun getNotes(root: Note): Array {
return Array(chordType.notes.size) { root + note + chordType.notes[it] }
diff --git a/app/src/main/java/com/lukas/music/song/chords/ChordType.kt b/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
index e53189a..95b69a0 100644
--- a/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
@@ -5,11 +5,16 @@
private val asString: String,
val transform: (String) -> String
) {
- Major(arrayOf(0, 4, 7), "major", { it.uppercase() }),
- Minor(arrayOf(0, 3, 7), "minor", { it.lowercase() }),
+ MAJOR(arrayOf(0, 4, 7), "major", { it.uppercase() }),
+ MINOR(arrayOf(0, 3, 7), "minor", { it.lowercase() }),
+ DIMINISHED(arrayOf(0, 3, 6), "diminished", { it.lowercase() + "0" }),
;
override fun toString(): String {
return asString
}
+
+ companion object {
+ val VALUES = values()
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/chords/Interval.kt b/app/src/main/java/com/lukas/music/song/chords/Interval.kt
index b3b4480..60a6ced 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Interval.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Interval.kt
@@ -1,7 +1,7 @@
package com.lukas.music.song.chords
class Interval(private val distance: Int) {
- private val name: IntervalName = when (distance) {
+ val name: IntervalName = when (distance) {
0 -> IntervalName.UNISON
1, 2 -> IntervalName.SECOND
3, 4 -> IntervalName.THIRD
@@ -13,7 +13,7 @@
else -> throw IllegalArgumentException("cannot make interval from distance $distance")
}
private val modifier: Modifier = when (distance) {
- 0, 5, 12 -> Modifier.PERFECT
+ 0, 7, 12 -> Modifier.PERFECT
1, 3, 5, 8, 10 -> Modifier.MINOR
else -> Modifier.MAJOR
}
@@ -36,12 +36,20 @@
override fun toString(): String {
return romanVersion
}
+
+ companion object {
+ val VALUES = values()
+ val NAMES = Array(VALUES.size) { VALUES[it].romanVersion }
+ }
}
enum class Modifier(val descriptor: String, val offset: Int) {
PERFECT("", 0),
MINOR("", 0),
MAJOR("", 1);
- }
+ companion object {
+ val VALUES = values()
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/chords/Phrase.kt b/app/src/main/java/com/lukas/music/song/chords/Phrase.kt
index 76d4259..611d1b8 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Phrase.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Phrase.kt
@@ -2,20 +2,21 @@
class Phrase {
val chords = mutableListOf(
- Chord(0, ChordType.Major),
- Chord(5, ChordType.Major),
- Chord(2, ChordType.Minor),
- Chord(7, ChordType.Major),
+ Chord(0, ChordType.MAJOR),
+ Chord(5, ChordType.MAJOR),
+ Chord(2, ChordType.MINOR),
+ Chord(7, ChordType.MAJOR),
)
var position = 0
fun step(parent: ChordProgression): Chord {
var parent: ChordProgression = parent
+ val result = chords[position]
position++
if (position >= chords.size) {
position = 0
parent++
}
- return chords[position]
+ return result
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
new file mode 100644
index 0000000..2f3bbb2
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
@@ -0,0 +1,92 @@
+package com.lukas.music.ui.fragments
+
+import android.R
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import androidx.fragment.app.DialogFragment
+import com.lukas.music.databinding.FragmentEditChordBinding
+import com.lukas.music.song.Scale
+import com.lukas.music.song.Song
+import com.lukas.music.song.chords.Chord
+import com.lukas.music.song.chords.ChordType
+import com.lukas.music.song.chords.Interval
+
+class EditChordFragment(val chord: Chord, val songFragment: SongFragment) : DialogFragment() {
+ lateinit var binding: FragmentEditChordBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentEditChordBinding.inflate(inflater)
+ setupPitchSpinner()
+ setupTypeSpinner()
+ binding.exitButton.setOnClickListener {
+ dismiss()
+ }
+ return binding.root
+ }
+
+ private fun setupPitchSpinner() {
+ val pitches = if (songFragment.displayChordNames) {
+ Array(Scale.MAJOR.steps.size) { (Song.currentSong.root + Scale.MAJOR.steps[it]).noteName.toString() }
+ } else Interval.IntervalName.NAMES
+ val pitchAdapter = ArrayAdapter(
+ binding.root.context,
+ R.layout.simple_spinner_dropdown_item, pitches
+ )
+ binding.pitchSpinner.adapter = pitchAdapter
+ binding.pitchSpinner.setSelection(chord.interval.name.ordinal)
+ binding.pitchSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ override fun onItemSelected(
+ parent: AdapterView<*>?,
+ view: View?,
+ position: Int,
+ id: Long
+ ) {
+ chord.note = Scale.MAJOR.steps[position]
+ songFragment.updateChords()
+ }
+
+ override fun onNothingSelected(parent: AdapterView<*>?) {}
+ }
+ }
+
+ private fun setupTypeSpinner() {
+ val values = mutableListOf("default")
+ for (chordType in ChordType.VALUES) {
+ values += chordType.toString()
+ }
+ val modifierAdapter = ArrayAdapter(
+ binding.root.context,
+ R.layout.simple_spinner_dropdown_item, values
+ )
+ binding.typeSpinner.adapter = modifierAdapter
+ binding.typeSpinner.setSelection(
+ if (chord.chordType == Scale.MAJOR.chordTypes[chord.interval.name.ordinal])
+ 0
+ else chord.chordType.ordinal + 1
+ )
+ binding.typeSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ override fun onItemSelected(
+ parent: AdapterView<*>?,
+ view: View?,
+ position: Int,
+ id: Long
+ ) {
+ if (position == 0) {
+ chord.chordType = Scale.MAJOR.chordTypes[chord.interval.name.ordinal]
+ } else {
+ chord.chordType = ChordType.VALUES[position - 1]
+ }
+ songFragment.updateChords()
+ }
+
+ override fun onNothingSelected(parent: AdapterView<*>?) {}
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt
index 899cefe..e72a20d 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt
@@ -64,6 +64,7 @@
Song.currentSong.stepButtons += child
binding.beatIndicator.addView(child)
}
+ Song.currentSong.chordDisplay = binding.currentChord
return binding.root
}
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 447e0d3..5c9d3cd 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -8,10 +8,11 @@
+
-
+
diff --git a/app/src/main/java/com/lukas/music/song/Scale.kt b/app/src/main/java/com/lukas/music/song/Scale.kt
new file mode 100644
index 0000000..bc016cb
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/song/Scale.kt
@@ -0,0 +1,19 @@
+package com.lukas.music.song
+
+import com.lukas.music.song.chords.ChordType
+
+enum class Scale(val identifier: String, val steps: Array, val chordTypes: Array) {
+ MAJOR(
+ "major",
+ arrayOf(0, 2, 4, 5, 7, 9, 11, 12),
+ arrayOf(
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.MINOR,
+ ChordType.MAJOR,
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.DIMINISHED
+ )
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/Song.kt b/app/src/main/java/com/lukas/music/song/Song.kt
index 9dd3cb8..4b23eac 100644
--- a/app/src/main/java/com/lukas/music/song/Song.kt
+++ b/app/src/main/java/com/lukas/music/song/Song.kt
@@ -3,6 +3,7 @@
import android.os.Handler
import android.os.Looper
import android.widget.RadioButton
+import android.widget.TextView
import com.lukas.music.instruments.Instrument
import com.lukas.music.song.chords.Chord
import com.lukas.music.song.chords.ChordProgression
@@ -16,6 +17,7 @@
private var beat = 0
private var chord: Chord = chordProgression.step()
val stepButtons = mutableListOf()
+ lateinit var chordDisplay: TextView
fun step() {
Handler(Looper.getMainLooper()).post {
@@ -31,6 +33,7 @@
for (voice in Instrument.voice) {
voice.step(root, chordNotes)
}
+ chordDisplay.text = chord.toString(true, root)
}
}
diff --git a/app/src/main/java/com/lukas/music/song/chords/Chord.kt b/app/src/main/java/com/lukas/music/song/chords/Chord.kt
index 61dac11..e0dd8fc 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Chord.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Chord.kt
@@ -2,8 +2,13 @@
import com.lukas.music.song.note.Note
-class Chord(val note: Int, private val chordType: ChordType) {
- private val interval = Interval(note)
+class Chord(note: Int, var chordType: ChordType) {
+ var note: Int = note
+ set(value) {
+ field = value
+ interval = Interval(value)
+ }
+ var interval = Interval(note)
fun getNotes(root: Note): Array {
return Array(chordType.notes.size) { root + note + chordType.notes[it] }
diff --git a/app/src/main/java/com/lukas/music/song/chords/ChordType.kt b/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
index e53189a..95b69a0 100644
--- a/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
@@ -5,11 +5,16 @@
private val asString: String,
val transform: (String) -> String
) {
- Major(arrayOf(0, 4, 7), "major", { it.uppercase() }),
- Minor(arrayOf(0, 3, 7), "minor", { it.lowercase() }),
+ MAJOR(arrayOf(0, 4, 7), "major", { it.uppercase() }),
+ MINOR(arrayOf(0, 3, 7), "minor", { it.lowercase() }),
+ DIMINISHED(arrayOf(0, 3, 6), "diminished", { it.lowercase() + "0" }),
;
override fun toString(): String {
return asString
}
+
+ companion object {
+ val VALUES = values()
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/chords/Interval.kt b/app/src/main/java/com/lukas/music/song/chords/Interval.kt
index b3b4480..60a6ced 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Interval.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Interval.kt
@@ -1,7 +1,7 @@
package com.lukas.music.song.chords
class Interval(private val distance: Int) {
- private val name: IntervalName = when (distance) {
+ val name: IntervalName = when (distance) {
0 -> IntervalName.UNISON
1, 2 -> IntervalName.SECOND
3, 4 -> IntervalName.THIRD
@@ -13,7 +13,7 @@
else -> throw IllegalArgumentException("cannot make interval from distance $distance")
}
private val modifier: Modifier = when (distance) {
- 0, 5, 12 -> Modifier.PERFECT
+ 0, 7, 12 -> Modifier.PERFECT
1, 3, 5, 8, 10 -> Modifier.MINOR
else -> Modifier.MAJOR
}
@@ -36,12 +36,20 @@
override fun toString(): String {
return romanVersion
}
+
+ companion object {
+ val VALUES = values()
+ val NAMES = Array(VALUES.size) { VALUES[it].romanVersion }
+ }
}
enum class Modifier(val descriptor: String, val offset: Int) {
PERFECT("", 0),
MINOR("", 0),
MAJOR("", 1);
- }
+ companion object {
+ val VALUES = values()
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/chords/Phrase.kt b/app/src/main/java/com/lukas/music/song/chords/Phrase.kt
index 76d4259..611d1b8 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Phrase.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Phrase.kt
@@ -2,20 +2,21 @@
class Phrase {
val chords = mutableListOf(
- Chord(0, ChordType.Major),
- Chord(5, ChordType.Major),
- Chord(2, ChordType.Minor),
- Chord(7, ChordType.Major),
+ Chord(0, ChordType.MAJOR),
+ Chord(5, ChordType.MAJOR),
+ Chord(2, ChordType.MINOR),
+ Chord(7, ChordType.MAJOR),
)
var position = 0
fun step(parent: ChordProgression): Chord {
var parent: ChordProgression = parent
+ val result = chords[position]
position++
if (position >= chords.size) {
position = 0
parent++
}
- return chords[position]
+ return result
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
new file mode 100644
index 0000000..2f3bbb2
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
@@ -0,0 +1,92 @@
+package com.lukas.music.ui.fragments
+
+import android.R
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import androidx.fragment.app.DialogFragment
+import com.lukas.music.databinding.FragmentEditChordBinding
+import com.lukas.music.song.Scale
+import com.lukas.music.song.Song
+import com.lukas.music.song.chords.Chord
+import com.lukas.music.song.chords.ChordType
+import com.lukas.music.song.chords.Interval
+
+class EditChordFragment(val chord: Chord, val songFragment: SongFragment) : DialogFragment() {
+ lateinit var binding: FragmentEditChordBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentEditChordBinding.inflate(inflater)
+ setupPitchSpinner()
+ setupTypeSpinner()
+ binding.exitButton.setOnClickListener {
+ dismiss()
+ }
+ return binding.root
+ }
+
+ private fun setupPitchSpinner() {
+ val pitches = if (songFragment.displayChordNames) {
+ Array(Scale.MAJOR.steps.size) { (Song.currentSong.root + Scale.MAJOR.steps[it]).noteName.toString() }
+ } else Interval.IntervalName.NAMES
+ val pitchAdapter = ArrayAdapter(
+ binding.root.context,
+ R.layout.simple_spinner_dropdown_item, pitches
+ )
+ binding.pitchSpinner.adapter = pitchAdapter
+ binding.pitchSpinner.setSelection(chord.interval.name.ordinal)
+ binding.pitchSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ override fun onItemSelected(
+ parent: AdapterView<*>?,
+ view: View?,
+ position: Int,
+ id: Long
+ ) {
+ chord.note = Scale.MAJOR.steps[position]
+ songFragment.updateChords()
+ }
+
+ override fun onNothingSelected(parent: AdapterView<*>?) {}
+ }
+ }
+
+ private fun setupTypeSpinner() {
+ val values = mutableListOf("default")
+ for (chordType in ChordType.VALUES) {
+ values += chordType.toString()
+ }
+ val modifierAdapter = ArrayAdapter(
+ binding.root.context,
+ R.layout.simple_spinner_dropdown_item, values
+ )
+ binding.typeSpinner.adapter = modifierAdapter
+ binding.typeSpinner.setSelection(
+ if (chord.chordType == Scale.MAJOR.chordTypes[chord.interval.name.ordinal])
+ 0
+ else chord.chordType.ordinal + 1
+ )
+ binding.typeSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ override fun onItemSelected(
+ parent: AdapterView<*>?,
+ view: View?,
+ position: Int,
+ id: Long
+ ) {
+ if (position == 0) {
+ chord.chordType = Scale.MAJOR.chordTypes[chord.interval.name.ordinal]
+ } else {
+ chord.chordType = ChordType.VALUES[position - 1]
+ }
+ songFragment.updateChords()
+ }
+
+ override fun onNothingSelected(parent: AdapterView<*>?) {}
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt
index 899cefe..e72a20d 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt
@@ -64,6 +64,7 @@
Song.currentSong.stepButtons += child
binding.beatIndicator.addView(child)
}
+ Song.currentSong.chordDisplay = binding.currentChord
return binding.root
}
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/SongFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/SongFragment.kt
index 1791310..ef0af81 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/SongFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/SongFragment.kt
@@ -45,7 +45,7 @@
return binding.root
}
- private fun updateChords() {
+ fun updateChords() {
binding.chords.removeAllViews()
for (phrase in Song.currentSong.chordProgression.phrases) {
val row = TableRow(binding.root.context)
@@ -53,6 +53,9 @@
val card = CardView(binding.root.context)
card.radius = 10f
card.layoutParams = layout
+ card.setOnClickListener {
+ EditChordFragment(chord, this).showNow(childFragmentManager, "")
+ }
val text = TextView(binding.root.context)
text.text = chord.toString(displayChordNames, Song.currentSong.root)
text.layoutParams = layout
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 447e0d3..5c9d3cd 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -8,10 +8,11 @@
+
-
+
diff --git a/app/src/main/java/com/lukas/music/song/Scale.kt b/app/src/main/java/com/lukas/music/song/Scale.kt
new file mode 100644
index 0000000..bc016cb
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/song/Scale.kt
@@ -0,0 +1,19 @@
+package com.lukas.music.song
+
+import com.lukas.music.song.chords.ChordType
+
+enum class Scale(val identifier: String, val steps: Array, val chordTypes: Array) {
+ MAJOR(
+ "major",
+ arrayOf(0, 2, 4, 5, 7, 9, 11, 12),
+ arrayOf(
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.MINOR,
+ ChordType.MAJOR,
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.DIMINISHED
+ )
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/Song.kt b/app/src/main/java/com/lukas/music/song/Song.kt
index 9dd3cb8..4b23eac 100644
--- a/app/src/main/java/com/lukas/music/song/Song.kt
+++ b/app/src/main/java/com/lukas/music/song/Song.kt
@@ -3,6 +3,7 @@
import android.os.Handler
import android.os.Looper
import android.widget.RadioButton
+import android.widget.TextView
import com.lukas.music.instruments.Instrument
import com.lukas.music.song.chords.Chord
import com.lukas.music.song.chords.ChordProgression
@@ -16,6 +17,7 @@
private var beat = 0
private var chord: Chord = chordProgression.step()
val stepButtons = mutableListOf()
+ lateinit var chordDisplay: TextView
fun step() {
Handler(Looper.getMainLooper()).post {
@@ -31,6 +33,7 @@
for (voice in Instrument.voice) {
voice.step(root, chordNotes)
}
+ chordDisplay.text = chord.toString(true, root)
}
}
diff --git a/app/src/main/java/com/lukas/music/song/chords/Chord.kt b/app/src/main/java/com/lukas/music/song/chords/Chord.kt
index 61dac11..e0dd8fc 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Chord.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Chord.kt
@@ -2,8 +2,13 @@
import com.lukas.music.song.note.Note
-class Chord(val note: Int, private val chordType: ChordType) {
- private val interval = Interval(note)
+class Chord(note: Int, var chordType: ChordType) {
+ var note: Int = note
+ set(value) {
+ field = value
+ interval = Interval(value)
+ }
+ var interval = Interval(note)
fun getNotes(root: Note): Array {
return Array(chordType.notes.size) { root + note + chordType.notes[it] }
diff --git a/app/src/main/java/com/lukas/music/song/chords/ChordType.kt b/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
index e53189a..95b69a0 100644
--- a/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
@@ -5,11 +5,16 @@
private val asString: String,
val transform: (String) -> String
) {
- Major(arrayOf(0, 4, 7), "major", { it.uppercase() }),
- Minor(arrayOf(0, 3, 7), "minor", { it.lowercase() }),
+ MAJOR(arrayOf(0, 4, 7), "major", { it.uppercase() }),
+ MINOR(arrayOf(0, 3, 7), "minor", { it.lowercase() }),
+ DIMINISHED(arrayOf(0, 3, 6), "diminished", { it.lowercase() + "0" }),
;
override fun toString(): String {
return asString
}
+
+ companion object {
+ val VALUES = values()
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/chords/Interval.kt b/app/src/main/java/com/lukas/music/song/chords/Interval.kt
index b3b4480..60a6ced 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Interval.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Interval.kt
@@ -1,7 +1,7 @@
package com.lukas.music.song.chords
class Interval(private val distance: Int) {
- private val name: IntervalName = when (distance) {
+ val name: IntervalName = when (distance) {
0 -> IntervalName.UNISON
1, 2 -> IntervalName.SECOND
3, 4 -> IntervalName.THIRD
@@ -13,7 +13,7 @@
else -> throw IllegalArgumentException("cannot make interval from distance $distance")
}
private val modifier: Modifier = when (distance) {
- 0, 5, 12 -> Modifier.PERFECT
+ 0, 7, 12 -> Modifier.PERFECT
1, 3, 5, 8, 10 -> Modifier.MINOR
else -> Modifier.MAJOR
}
@@ -36,12 +36,20 @@
override fun toString(): String {
return romanVersion
}
+
+ companion object {
+ val VALUES = values()
+ val NAMES = Array(VALUES.size) { VALUES[it].romanVersion }
+ }
}
enum class Modifier(val descriptor: String, val offset: Int) {
PERFECT("", 0),
MINOR("", 0),
MAJOR("", 1);
- }
+ companion object {
+ val VALUES = values()
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/chords/Phrase.kt b/app/src/main/java/com/lukas/music/song/chords/Phrase.kt
index 76d4259..611d1b8 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Phrase.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Phrase.kt
@@ -2,20 +2,21 @@
class Phrase {
val chords = mutableListOf(
- Chord(0, ChordType.Major),
- Chord(5, ChordType.Major),
- Chord(2, ChordType.Minor),
- Chord(7, ChordType.Major),
+ Chord(0, ChordType.MAJOR),
+ Chord(5, ChordType.MAJOR),
+ Chord(2, ChordType.MINOR),
+ Chord(7, ChordType.MAJOR),
)
var position = 0
fun step(parent: ChordProgression): Chord {
var parent: ChordProgression = parent
+ val result = chords[position]
position++
if (position >= chords.size) {
position = 0
parent++
}
- return chords[position]
+ return result
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
new file mode 100644
index 0000000..2f3bbb2
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
@@ -0,0 +1,92 @@
+package com.lukas.music.ui.fragments
+
+import android.R
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import androidx.fragment.app.DialogFragment
+import com.lukas.music.databinding.FragmentEditChordBinding
+import com.lukas.music.song.Scale
+import com.lukas.music.song.Song
+import com.lukas.music.song.chords.Chord
+import com.lukas.music.song.chords.ChordType
+import com.lukas.music.song.chords.Interval
+
+class EditChordFragment(val chord: Chord, val songFragment: SongFragment) : DialogFragment() {
+ lateinit var binding: FragmentEditChordBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentEditChordBinding.inflate(inflater)
+ setupPitchSpinner()
+ setupTypeSpinner()
+ binding.exitButton.setOnClickListener {
+ dismiss()
+ }
+ return binding.root
+ }
+
+ private fun setupPitchSpinner() {
+ val pitches = if (songFragment.displayChordNames) {
+ Array(Scale.MAJOR.steps.size) { (Song.currentSong.root + Scale.MAJOR.steps[it]).noteName.toString() }
+ } else Interval.IntervalName.NAMES
+ val pitchAdapter = ArrayAdapter(
+ binding.root.context,
+ R.layout.simple_spinner_dropdown_item, pitches
+ )
+ binding.pitchSpinner.adapter = pitchAdapter
+ binding.pitchSpinner.setSelection(chord.interval.name.ordinal)
+ binding.pitchSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ override fun onItemSelected(
+ parent: AdapterView<*>?,
+ view: View?,
+ position: Int,
+ id: Long
+ ) {
+ chord.note = Scale.MAJOR.steps[position]
+ songFragment.updateChords()
+ }
+
+ override fun onNothingSelected(parent: AdapterView<*>?) {}
+ }
+ }
+
+ private fun setupTypeSpinner() {
+ val values = mutableListOf("default")
+ for (chordType in ChordType.VALUES) {
+ values += chordType.toString()
+ }
+ val modifierAdapter = ArrayAdapter(
+ binding.root.context,
+ R.layout.simple_spinner_dropdown_item, values
+ )
+ binding.typeSpinner.adapter = modifierAdapter
+ binding.typeSpinner.setSelection(
+ if (chord.chordType == Scale.MAJOR.chordTypes[chord.interval.name.ordinal])
+ 0
+ else chord.chordType.ordinal + 1
+ )
+ binding.typeSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ override fun onItemSelected(
+ parent: AdapterView<*>?,
+ view: View?,
+ position: Int,
+ id: Long
+ ) {
+ if (position == 0) {
+ chord.chordType = Scale.MAJOR.chordTypes[chord.interval.name.ordinal]
+ } else {
+ chord.chordType = ChordType.VALUES[position - 1]
+ }
+ songFragment.updateChords()
+ }
+
+ override fun onNothingSelected(parent: AdapterView<*>?) {}
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt
index 899cefe..e72a20d 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt
@@ -64,6 +64,7 @@
Song.currentSong.stepButtons += child
binding.beatIndicator.addView(child)
}
+ Song.currentSong.chordDisplay = binding.currentChord
return binding.root
}
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/SongFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/SongFragment.kt
index 1791310..ef0af81 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/SongFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/SongFragment.kt
@@ -45,7 +45,7 @@
return binding.root
}
- private fun updateChords() {
+ fun updateChords() {
binding.chords.removeAllViews()
for (phrase in Song.currentSong.chordProgression.phrases) {
val row = TableRow(binding.root.context)
@@ -53,6 +53,9 @@
val card = CardView(binding.root.context)
card.radius = 10f
card.layoutParams = layout
+ card.setOnClickListener {
+ EditChordFragment(chord, this).showNow(childFragmentManager, "")
+ }
val text = TextView(binding.root.context)
text.text = chord.toString(displayChordNames, Song.currentSong.root)
text.layoutParams = layout
diff --git a/app/src/main/res/layout/fragment_edit_chord.xml b/app/src/main/res/layout/fragment_edit_chord.xml
new file mode 100644
index 0000000..8de2950
--- /dev/null
+++ b/app/src/main/res/layout/fragment_edit_chord.xml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 447e0d3..5c9d3cd 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -8,10 +8,11 @@
+
-
+
diff --git a/app/src/main/java/com/lukas/music/song/Scale.kt b/app/src/main/java/com/lukas/music/song/Scale.kt
new file mode 100644
index 0000000..bc016cb
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/song/Scale.kt
@@ -0,0 +1,19 @@
+package com.lukas.music.song
+
+import com.lukas.music.song.chords.ChordType
+
+enum class Scale(val identifier: String, val steps: Array, val chordTypes: Array) {
+ MAJOR(
+ "major",
+ arrayOf(0, 2, 4, 5, 7, 9, 11, 12),
+ arrayOf(
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.MINOR,
+ ChordType.MAJOR,
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.DIMINISHED
+ )
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/Song.kt b/app/src/main/java/com/lukas/music/song/Song.kt
index 9dd3cb8..4b23eac 100644
--- a/app/src/main/java/com/lukas/music/song/Song.kt
+++ b/app/src/main/java/com/lukas/music/song/Song.kt
@@ -3,6 +3,7 @@
import android.os.Handler
import android.os.Looper
import android.widget.RadioButton
+import android.widget.TextView
import com.lukas.music.instruments.Instrument
import com.lukas.music.song.chords.Chord
import com.lukas.music.song.chords.ChordProgression
@@ -16,6 +17,7 @@
private var beat = 0
private var chord: Chord = chordProgression.step()
val stepButtons = mutableListOf()
+ lateinit var chordDisplay: TextView
fun step() {
Handler(Looper.getMainLooper()).post {
@@ -31,6 +33,7 @@
for (voice in Instrument.voice) {
voice.step(root, chordNotes)
}
+ chordDisplay.text = chord.toString(true, root)
}
}
diff --git a/app/src/main/java/com/lukas/music/song/chords/Chord.kt b/app/src/main/java/com/lukas/music/song/chords/Chord.kt
index 61dac11..e0dd8fc 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Chord.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Chord.kt
@@ -2,8 +2,13 @@
import com.lukas.music.song.note.Note
-class Chord(val note: Int, private val chordType: ChordType) {
- private val interval = Interval(note)
+class Chord(note: Int, var chordType: ChordType) {
+ var note: Int = note
+ set(value) {
+ field = value
+ interval = Interval(value)
+ }
+ var interval = Interval(note)
fun getNotes(root: Note): Array {
return Array(chordType.notes.size) { root + note + chordType.notes[it] }
diff --git a/app/src/main/java/com/lukas/music/song/chords/ChordType.kt b/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
index e53189a..95b69a0 100644
--- a/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
@@ -5,11 +5,16 @@
private val asString: String,
val transform: (String) -> String
) {
- Major(arrayOf(0, 4, 7), "major", { it.uppercase() }),
- Minor(arrayOf(0, 3, 7), "minor", { it.lowercase() }),
+ MAJOR(arrayOf(0, 4, 7), "major", { it.uppercase() }),
+ MINOR(arrayOf(0, 3, 7), "minor", { it.lowercase() }),
+ DIMINISHED(arrayOf(0, 3, 6), "diminished", { it.lowercase() + "0" }),
;
override fun toString(): String {
return asString
}
+
+ companion object {
+ val VALUES = values()
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/chords/Interval.kt b/app/src/main/java/com/lukas/music/song/chords/Interval.kt
index b3b4480..60a6ced 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Interval.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Interval.kt
@@ -1,7 +1,7 @@
package com.lukas.music.song.chords
class Interval(private val distance: Int) {
- private val name: IntervalName = when (distance) {
+ val name: IntervalName = when (distance) {
0 -> IntervalName.UNISON
1, 2 -> IntervalName.SECOND
3, 4 -> IntervalName.THIRD
@@ -13,7 +13,7 @@
else -> throw IllegalArgumentException("cannot make interval from distance $distance")
}
private val modifier: Modifier = when (distance) {
- 0, 5, 12 -> Modifier.PERFECT
+ 0, 7, 12 -> Modifier.PERFECT
1, 3, 5, 8, 10 -> Modifier.MINOR
else -> Modifier.MAJOR
}
@@ -36,12 +36,20 @@
override fun toString(): String {
return romanVersion
}
+
+ companion object {
+ val VALUES = values()
+ val NAMES = Array(VALUES.size) { VALUES[it].romanVersion }
+ }
}
enum class Modifier(val descriptor: String, val offset: Int) {
PERFECT("", 0),
MINOR("", 0),
MAJOR("", 1);
- }
+ companion object {
+ val VALUES = values()
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/chords/Phrase.kt b/app/src/main/java/com/lukas/music/song/chords/Phrase.kt
index 76d4259..611d1b8 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Phrase.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Phrase.kt
@@ -2,20 +2,21 @@
class Phrase {
val chords = mutableListOf(
- Chord(0, ChordType.Major),
- Chord(5, ChordType.Major),
- Chord(2, ChordType.Minor),
- Chord(7, ChordType.Major),
+ Chord(0, ChordType.MAJOR),
+ Chord(5, ChordType.MAJOR),
+ Chord(2, ChordType.MINOR),
+ Chord(7, ChordType.MAJOR),
)
var position = 0
fun step(parent: ChordProgression): Chord {
var parent: ChordProgression = parent
+ val result = chords[position]
position++
if (position >= chords.size) {
position = 0
parent++
}
- return chords[position]
+ return result
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
new file mode 100644
index 0000000..2f3bbb2
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
@@ -0,0 +1,92 @@
+package com.lukas.music.ui.fragments
+
+import android.R
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import androidx.fragment.app.DialogFragment
+import com.lukas.music.databinding.FragmentEditChordBinding
+import com.lukas.music.song.Scale
+import com.lukas.music.song.Song
+import com.lukas.music.song.chords.Chord
+import com.lukas.music.song.chords.ChordType
+import com.lukas.music.song.chords.Interval
+
+class EditChordFragment(val chord: Chord, val songFragment: SongFragment) : DialogFragment() {
+ lateinit var binding: FragmentEditChordBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentEditChordBinding.inflate(inflater)
+ setupPitchSpinner()
+ setupTypeSpinner()
+ binding.exitButton.setOnClickListener {
+ dismiss()
+ }
+ return binding.root
+ }
+
+ private fun setupPitchSpinner() {
+ val pitches = if (songFragment.displayChordNames) {
+ Array(Scale.MAJOR.steps.size) { (Song.currentSong.root + Scale.MAJOR.steps[it]).noteName.toString() }
+ } else Interval.IntervalName.NAMES
+ val pitchAdapter = ArrayAdapter(
+ binding.root.context,
+ R.layout.simple_spinner_dropdown_item, pitches
+ )
+ binding.pitchSpinner.adapter = pitchAdapter
+ binding.pitchSpinner.setSelection(chord.interval.name.ordinal)
+ binding.pitchSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ override fun onItemSelected(
+ parent: AdapterView<*>?,
+ view: View?,
+ position: Int,
+ id: Long
+ ) {
+ chord.note = Scale.MAJOR.steps[position]
+ songFragment.updateChords()
+ }
+
+ override fun onNothingSelected(parent: AdapterView<*>?) {}
+ }
+ }
+
+ private fun setupTypeSpinner() {
+ val values = mutableListOf("default")
+ for (chordType in ChordType.VALUES) {
+ values += chordType.toString()
+ }
+ val modifierAdapter = ArrayAdapter(
+ binding.root.context,
+ R.layout.simple_spinner_dropdown_item, values
+ )
+ binding.typeSpinner.adapter = modifierAdapter
+ binding.typeSpinner.setSelection(
+ if (chord.chordType == Scale.MAJOR.chordTypes[chord.interval.name.ordinal])
+ 0
+ else chord.chordType.ordinal + 1
+ )
+ binding.typeSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ override fun onItemSelected(
+ parent: AdapterView<*>?,
+ view: View?,
+ position: Int,
+ id: Long
+ ) {
+ if (position == 0) {
+ chord.chordType = Scale.MAJOR.chordTypes[chord.interval.name.ordinal]
+ } else {
+ chord.chordType = ChordType.VALUES[position - 1]
+ }
+ songFragment.updateChords()
+ }
+
+ override fun onNothingSelected(parent: AdapterView<*>?) {}
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt
index 899cefe..e72a20d 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt
@@ -64,6 +64,7 @@
Song.currentSong.stepButtons += child
binding.beatIndicator.addView(child)
}
+ Song.currentSong.chordDisplay = binding.currentChord
return binding.root
}
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/SongFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/SongFragment.kt
index 1791310..ef0af81 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/SongFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/SongFragment.kt
@@ -45,7 +45,7 @@
return binding.root
}
- private fun updateChords() {
+ fun updateChords() {
binding.chords.removeAllViews()
for (phrase in Song.currentSong.chordProgression.phrases) {
val row = TableRow(binding.root.context)
@@ -53,6 +53,9 @@
val card = CardView(binding.root.context)
card.radius = 10f
card.layoutParams = layout
+ card.setOnClickListener {
+ EditChordFragment(chord, this).showNow(childFragmentManager, "")
+ }
val text = TextView(binding.root.context)
text.text = chord.toString(displayChordNames, Song.currentSong.root)
text.layoutParams = layout
diff --git a/app/src/main/res/layout/fragment_edit_chord.xml b/app/src/main/res/layout/fragment_edit_chord.xml
new file mode 100644
index 0000000..8de2950
--- /dev/null
+++ b/app/src/main/res/layout/fragment_edit_chord.xml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_play.xml b/app/src/main/res/layout/fragment_play.xml
index 5b0cc4a..136de13 100644
--- a/app/src/main/res/layout/fragment_play.xml
+++ b/app/src/main/res/layout/fragment_play.xml
@@ -58,5 +58,15 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/masterVolumeSlider" />
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 447e0d3..5c9d3cd 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -8,10 +8,11 @@
+
-
+
diff --git a/app/src/main/java/com/lukas/music/song/Scale.kt b/app/src/main/java/com/lukas/music/song/Scale.kt
new file mode 100644
index 0000000..bc016cb
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/song/Scale.kt
@@ -0,0 +1,19 @@
+package com.lukas.music.song
+
+import com.lukas.music.song.chords.ChordType
+
+enum class Scale(val identifier: String, val steps: Array, val chordTypes: Array) {
+ MAJOR(
+ "major",
+ arrayOf(0, 2, 4, 5, 7, 9, 11, 12),
+ arrayOf(
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.MINOR,
+ ChordType.MAJOR,
+ ChordType.MAJOR,
+ ChordType.MINOR,
+ ChordType.DIMINISHED
+ )
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/Song.kt b/app/src/main/java/com/lukas/music/song/Song.kt
index 9dd3cb8..4b23eac 100644
--- a/app/src/main/java/com/lukas/music/song/Song.kt
+++ b/app/src/main/java/com/lukas/music/song/Song.kt
@@ -3,6 +3,7 @@
import android.os.Handler
import android.os.Looper
import android.widget.RadioButton
+import android.widget.TextView
import com.lukas.music.instruments.Instrument
import com.lukas.music.song.chords.Chord
import com.lukas.music.song.chords.ChordProgression
@@ -16,6 +17,7 @@
private var beat = 0
private var chord: Chord = chordProgression.step()
val stepButtons = mutableListOf()
+ lateinit var chordDisplay: TextView
fun step() {
Handler(Looper.getMainLooper()).post {
@@ -31,6 +33,7 @@
for (voice in Instrument.voice) {
voice.step(root, chordNotes)
}
+ chordDisplay.text = chord.toString(true, root)
}
}
diff --git a/app/src/main/java/com/lukas/music/song/chords/Chord.kt b/app/src/main/java/com/lukas/music/song/chords/Chord.kt
index 61dac11..e0dd8fc 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Chord.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Chord.kt
@@ -2,8 +2,13 @@
import com.lukas.music.song.note.Note
-class Chord(val note: Int, private val chordType: ChordType) {
- private val interval = Interval(note)
+class Chord(note: Int, var chordType: ChordType) {
+ var note: Int = note
+ set(value) {
+ field = value
+ interval = Interval(value)
+ }
+ var interval = Interval(note)
fun getNotes(root: Note): Array {
return Array(chordType.notes.size) { root + note + chordType.notes[it] }
diff --git a/app/src/main/java/com/lukas/music/song/chords/ChordType.kt b/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
index e53189a..95b69a0 100644
--- a/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/ChordType.kt
@@ -5,11 +5,16 @@
private val asString: String,
val transform: (String) -> String
) {
- Major(arrayOf(0, 4, 7), "major", { it.uppercase() }),
- Minor(arrayOf(0, 3, 7), "minor", { it.lowercase() }),
+ MAJOR(arrayOf(0, 4, 7), "major", { it.uppercase() }),
+ MINOR(arrayOf(0, 3, 7), "minor", { it.lowercase() }),
+ DIMINISHED(arrayOf(0, 3, 6), "diminished", { it.lowercase() + "0" }),
;
override fun toString(): String {
return asString
}
+
+ companion object {
+ val VALUES = values()
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/chords/Interval.kt b/app/src/main/java/com/lukas/music/song/chords/Interval.kt
index b3b4480..60a6ced 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Interval.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Interval.kt
@@ -1,7 +1,7 @@
package com.lukas.music.song.chords
class Interval(private val distance: Int) {
- private val name: IntervalName = when (distance) {
+ val name: IntervalName = when (distance) {
0 -> IntervalName.UNISON
1, 2 -> IntervalName.SECOND
3, 4 -> IntervalName.THIRD
@@ -13,7 +13,7 @@
else -> throw IllegalArgumentException("cannot make interval from distance $distance")
}
private val modifier: Modifier = when (distance) {
- 0, 5, 12 -> Modifier.PERFECT
+ 0, 7, 12 -> Modifier.PERFECT
1, 3, 5, 8, 10 -> Modifier.MINOR
else -> Modifier.MAJOR
}
@@ -36,12 +36,20 @@
override fun toString(): String {
return romanVersion
}
+
+ companion object {
+ val VALUES = values()
+ val NAMES = Array(VALUES.size) { VALUES[it].romanVersion }
+ }
}
enum class Modifier(val descriptor: String, val offset: Int) {
PERFECT("", 0),
MINOR("", 0),
MAJOR("", 1);
- }
+ companion object {
+ val VALUES = values()
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/chords/Phrase.kt b/app/src/main/java/com/lukas/music/song/chords/Phrase.kt
index 76d4259..611d1b8 100644
--- a/app/src/main/java/com/lukas/music/song/chords/Phrase.kt
+++ b/app/src/main/java/com/lukas/music/song/chords/Phrase.kt
@@ -2,20 +2,21 @@
class Phrase {
val chords = mutableListOf(
- Chord(0, ChordType.Major),
- Chord(5, ChordType.Major),
- Chord(2, ChordType.Minor),
- Chord(7, ChordType.Major),
+ Chord(0, ChordType.MAJOR),
+ Chord(5, ChordType.MAJOR),
+ Chord(2, ChordType.MINOR),
+ Chord(7, ChordType.MAJOR),
)
var position = 0
fun step(parent: ChordProgression): Chord {
var parent: ChordProgression = parent
+ val result = chords[position]
position++
if (position >= chords.size) {
position = 0
parent++
}
- return chords[position]
+ return result
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
new file mode 100644
index 0000000..2f3bbb2
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
@@ -0,0 +1,92 @@
+package com.lukas.music.ui.fragments
+
+import android.R
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import androidx.fragment.app.DialogFragment
+import com.lukas.music.databinding.FragmentEditChordBinding
+import com.lukas.music.song.Scale
+import com.lukas.music.song.Song
+import com.lukas.music.song.chords.Chord
+import com.lukas.music.song.chords.ChordType
+import com.lukas.music.song.chords.Interval
+
+class EditChordFragment(val chord: Chord, val songFragment: SongFragment) : DialogFragment() {
+ lateinit var binding: FragmentEditChordBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentEditChordBinding.inflate(inflater)
+ setupPitchSpinner()
+ setupTypeSpinner()
+ binding.exitButton.setOnClickListener {
+ dismiss()
+ }
+ return binding.root
+ }
+
+ private fun setupPitchSpinner() {
+ val pitches = if (songFragment.displayChordNames) {
+ Array(Scale.MAJOR.steps.size) { (Song.currentSong.root + Scale.MAJOR.steps[it]).noteName.toString() }
+ } else Interval.IntervalName.NAMES
+ val pitchAdapter = ArrayAdapter(
+ binding.root.context,
+ R.layout.simple_spinner_dropdown_item, pitches
+ )
+ binding.pitchSpinner.adapter = pitchAdapter
+ binding.pitchSpinner.setSelection(chord.interval.name.ordinal)
+ binding.pitchSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ override fun onItemSelected(
+ parent: AdapterView<*>?,
+ view: View?,
+ position: Int,
+ id: Long
+ ) {
+ chord.note = Scale.MAJOR.steps[position]
+ songFragment.updateChords()
+ }
+
+ override fun onNothingSelected(parent: AdapterView<*>?) {}
+ }
+ }
+
+ private fun setupTypeSpinner() {
+ val values = mutableListOf("default")
+ for (chordType in ChordType.VALUES) {
+ values += chordType.toString()
+ }
+ val modifierAdapter = ArrayAdapter(
+ binding.root.context,
+ R.layout.simple_spinner_dropdown_item, values
+ )
+ binding.typeSpinner.adapter = modifierAdapter
+ binding.typeSpinner.setSelection(
+ if (chord.chordType == Scale.MAJOR.chordTypes[chord.interval.name.ordinal])
+ 0
+ else chord.chordType.ordinal + 1
+ )
+ binding.typeSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ override fun onItemSelected(
+ parent: AdapterView<*>?,
+ view: View?,
+ position: Int,
+ id: Long
+ ) {
+ if (position == 0) {
+ chord.chordType = Scale.MAJOR.chordTypes[chord.interval.name.ordinal]
+ } else {
+ chord.chordType = ChordType.VALUES[position - 1]
+ }
+ songFragment.updateChords()
+ }
+
+ override fun onNothingSelected(parent: AdapterView<*>?) {}
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt
index 899cefe..e72a20d 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/PlayFragment.kt
@@ -64,6 +64,7 @@
Song.currentSong.stepButtons += child
binding.beatIndicator.addView(child)
}
+ Song.currentSong.chordDisplay = binding.currentChord
return binding.root
}
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/SongFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/SongFragment.kt
index 1791310..ef0af81 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/SongFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/SongFragment.kt
@@ -45,7 +45,7 @@
return binding.root
}
- private fun updateChords() {
+ fun updateChords() {
binding.chords.removeAllViews()
for (phrase in Song.currentSong.chordProgression.phrases) {
val row = TableRow(binding.root.context)
@@ -53,6 +53,9 @@
val card = CardView(binding.root.context)
card.radius = 10f
card.layoutParams = layout
+ card.setOnClickListener {
+ EditChordFragment(chord, this).showNow(childFragmentManager, "")
+ }
val text = TextView(binding.root.context)
text.text = chord.toString(displayChordNames, Song.currentSong.root)
text.layoutParams = layout
diff --git a/app/src/main/res/layout/fragment_edit_chord.xml b/app/src/main/res/layout/fragment_edit_chord.xml
new file mode 100644
index 0000000..8de2950
--- /dev/null
+++ b/app/src/main/res/layout/fragment_edit_chord.xml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_play.xml b/app/src/main/res/layout/fragment_play.xml
index 5b0cc4a..136de13 100644
--- a/app/src/main/res/layout/fragment_play.xml
+++ b/app/src/main/res/layout/fragment_play.xml
@@ -58,5 +58,15 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/masterVolumeSlider" />
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index a200009..1ba02a4 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -13,4 +13,10 @@
Add a new phrase
Actual chords
select the song\'s key
+ Edit chord
+ Edit this chord\'s pitch
+ Edit this chord\'s type
+ Chord pitch
+ Chord type
+ Exit this menu
\ No newline at end of file