diff --git a/app/src/main/java/com/lukas/music/EditVoiceFragment.kt b/app/src/main/java/com/lukas/music/EditVoiceFragment.kt
deleted file mode 100644
index 56f21e6..0000000
--- a/app/src/main/java/com/lukas/music/EditVoiceFragment.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2022 Lukas Eisenhauer
- *
- * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or(at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program. If not, see .
- */
-
-package com.lukas.music
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TableRow
-import androidx.core.view.setMargins
-import androidx.fragment.app.DialogFragment
-import com.google.android.material.button.MaterialButton
-import com.lukas.music.databinding.FragmentEditVoiceBinding
-import com.lukas.music.song.Song
-import com.lukas.music.song.voice.Voice
-import com.lukas.music.util.ArrayProperty
-import com.lukas.music.util.setupToggle
-
-class EditVoiceFragment(private val voice: Voice) : DialogFragment() {
- private lateinit var binding: FragmentEditVoiceBinding
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- binding = FragmentEditVoiceBinding.inflate(inflater)
- for (row in 0 until voice.noteCount) {
- val rowLayout = TableRow(binding.root.context)
- for (column in 0 until Song.currentSong.beats) {
- val button = MaterialButton(binding.root.context)
- button.layoutParams = buttonLayout
- button.setupToggle(ArrayProperty(voice.noteActive[column], row), R.color.blue)
- rowLayout.addView(button)
- }
- binding.noteGrid.addView(rowLayout)
- }
- binding.noteGrid.isStretchAllColumns = true
- binding.closeButton.setOnClickListener {
- dismiss()
- }
- return binding.root
- }
-
- override fun onStart() {
- super.onStart()
- dialog?.window?.setLayout(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT
- )
- }
-
- companion object {
- val buttonLayout = TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT)
-
- init {
- buttonLayout.setMargins(5)
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/EditVoiceFragment.kt b/app/src/main/java/com/lukas/music/EditVoiceFragment.kt
deleted file mode 100644
index 56f21e6..0000000
--- a/app/src/main/java/com/lukas/music/EditVoiceFragment.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2022 Lukas Eisenhauer
- *
- * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or(at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program. If not, see .
- */
-
-package com.lukas.music
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TableRow
-import androidx.core.view.setMargins
-import androidx.fragment.app.DialogFragment
-import com.google.android.material.button.MaterialButton
-import com.lukas.music.databinding.FragmentEditVoiceBinding
-import com.lukas.music.song.Song
-import com.lukas.music.song.voice.Voice
-import com.lukas.music.util.ArrayProperty
-import com.lukas.music.util.setupToggle
-
-class EditVoiceFragment(private val voice: Voice) : DialogFragment() {
- private lateinit var binding: FragmentEditVoiceBinding
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- binding = FragmentEditVoiceBinding.inflate(inflater)
- for (row in 0 until voice.noteCount) {
- val rowLayout = TableRow(binding.root.context)
- for (column in 0 until Song.currentSong.beats) {
- val button = MaterialButton(binding.root.context)
- button.layoutParams = buttonLayout
- button.setupToggle(ArrayProperty(voice.noteActive[column], row), R.color.blue)
- rowLayout.addView(button)
- }
- binding.noteGrid.addView(rowLayout)
- }
- binding.noteGrid.isStretchAllColumns = true
- binding.closeButton.setOnClickListener {
- dismiss()
- }
- return binding.root
- }
-
- override fun onStart() {
- super.onStart()
- dialog?.window?.setLayout(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT
- )
- }
-
- companion object {
- val buttonLayout = TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT)
-
- init {
- buttonLayout.setMargins(5)
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/Rhythm.kt b/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
index 75c1545..b310c72 100644
--- a/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
@@ -36,6 +36,10 @@
if (this::task.isInitialized) {
task.cancel()
}
- task = timer.schedule((60000 / tempo).toLong(), (60000 / tempo).toLong(), callback)
+ task = timer.schedule(
+ (60000 / tempo / Song.currentSong.subBeats).toLong(),
+ (60000 / tempo / Song.currentSong.subBeats).toLong(),
+ callback
+ )
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/EditVoiceFragment.kt b/app/src/main/java/com/lukas/music/EditVoiceFragment.kt
deleted file mode 100644
index 56f21e6..0000000
--- a/app/src/main/java/com/lukas/music/EditVoiceFragment.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2022 Lukas Eisenhauer
- *
- * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or(at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program. If not, see .
- */
-
-package com.lukas.music
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TableRow
-import androidx.core.view.setMargins
-import androidx.fragment.app.DialogFragment
-import com.google.android.material.button.MaterialButton
-import com.lukas.music.databinding.FragmentEditVoiceBinding
-import com.lukas.music.song.Song
-import com.lukas.music.song.voice.Voice
-import com.lukas.music.util.ArrayProperty
-import com.lukas.music.util.setupToggle
-
-class EditVoiceFragment(private val voice: Voice) : DialogFragment() {
- private lateinit var binding: FragmentEditVoiceBinding
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- binding = FragmentEditVoiceBinding.inflate(inflater)
- for (row in 0 until voice.noteCount) {
- val rowLayout = TableRow(binding.root.context)
- for (column in 0 until Song.currentSong.beats) {
- val button = MaterialButton(binding.root.context)
- button.layoutParams = buttonLayout
- button.setupToggle(ArrayProperty(voice.noteActive[column], row), R.color.blue)
- rowLayout.addView(button)
- }
- binding.noteGrid.addView(rowLayout)
- }
- binding.noteGrid.isStretchAllColumns = true
- binding.closeButton.setOnClickListener {
- dismiss()
- }
- return binding.root
- }
-
- override fun onStart() {
- super.onStart()
- dialog?.window?.setLayout(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT
- )
- }
-
- companion object {
- val buttonLayout = TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT)
-
- init {
- buttonLayout.setMargins(5)
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/Rhythm.kt b/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
index 75c1545..b310c72 100644
--- a/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
@@ -36,6 +36,10 @@
if (this::task.isInitialized) {
task.cancel()
}
- task = timer.schedule((60000 / tempo).toLong(), (60000 / tempo).toLong(), callback)
+ task = timer.schedule(
+ (60000 / tempo / Song.currentSong.subBeats).toLong(),
+ (60000 / tempo / Song.currentSong.subBeats).toLong(),
+ callback
+ )
}
}
\ 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 fc5421b..5046664 100644
--- a/app/src/main/java/com/lukas/music/song/Song.kt
+++ b/app/src/main/java/com/lukas/music/song/Song.kt
@@ -14,11 +14,13 @@
import com.lukas.music.song.chords.ChordProgression
import com.lukas.music.song.note.Note
import com.lukas.music.util.Cycle
+import com.lukas.music.util.MetaCycle
class Song(
root: Note,
- val beats: Int
-) : Cycle(beats) {
+ val beats: Int,
+ val subBeats: Int,
+) : MetaCycle>() {
val chordProgression = ChordProgression()
var soloInstrument: Instrument? = null
set(value) {
@@ -46,7 +48,11 @@
init {
for (i in 0 until beats) {
- this += i
+ val cycle = Cycle()
+ for (j in 0 until subBeats) {
+ cycle += j
+ }
+ this += cycle
}
wraparoundListeners += {
chordProgression.step()
@@ -54,24 +60,25 @@
}
}
- override fun step(): Int {
+ override fun step(): Cycle? {
super.step()
- val chord = chordProgression.currentItem?.currentItem ?: return index
+ val chord = chordProgression.currentItem?.currentItem ?: return currentItem
val chordNotes = chord.getNotes(root)
soloInstrument?.let {
- it.voice.step(root, chordNotes, index)
+ it.voice.step(root, chordNotes, index, currentItem!!.index)
} ?: run {
for (instrument in Instrument.instruments) {
- instrument.voice.step(root, chordNotes, index)
+ instrument.voice.step(root, chordNotes, index, currentItem!!.index)
}
}
- return index
+ return currentItem
}
companion object {
var currentSong = Song(
Note.NOTES[69],
- 4
+ 4,
+ 2,
)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/EditVoiceFragment.kt b/app/src/main/java/com/lukas/music/EditVoiceFragment.kt
deleted file mode 100644
index 56f21e6..0000000
--- a/app/src/main/java/com/lukas/music/EditVoiceFragment.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2022 Lukas Eisenhauer
- *
- * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or(at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program. If not, see .
- */
-
-package com.lukas.music
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TableRow
-import androidx.core.view.setMargins
-import androidx.fragment.app.DialogFragment
-import com.google.android.material.button.MaterialButton
-import com.lukas.music.databinding.FragmentEditVoiceBinding
-import com.lukas.music.song.Song
-import com.lukas.music.song.voice.Voice
-import com.lukas.music.util.ArrayProperty
-import com.lukas.music.util.setupToggle
-
-class EditVoiceFragment(private val voice: Voice) : DialogFragment() {
- private lateinit var binding: FragmentEditVoiceBinding
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- binding = FragmentEditVoiceBinding.inflate(inflater)
- for (row in 0 until voice.noteCount) {
- val rowLayout = TableRow(binding.root.context)
- for (column in 0 until Song.currentSong.beats) {
- val button = MaterialButton(binding.root.context)
- button.layoutParams = buttonLayout
- button.setupToggle(ArrayProperty(voice.noteActive[column], row), R.color.blue)
- rowLayout.addView(button)
- }
- binding.noteGrid.addView(rowLayout)
- }
- binding.noteGrid.isStretchAllColumns = true
- binding.closeButton.setOnClickListener {
- dismiss()
- }
- return binding.root
- }
-
- override fun onStart() {
- super.onStart()
- dialog?.window?.setLayout(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT
- )
- }
-
- companion object {
- val buttonLayout = TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT)
-
- init {
- buttonLayout.setMargins(5)
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/Rhythm.kt b/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
index 75c1545..b310c72 100644
--- a/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
@@ -36,6 +36,10 @@
if (this::task.isInitialized) {
task.cancel()
}
- task = timer.schedule((60000 / tempo).toLong(), (60000 / tempo).toLong(), callback)
+ task = timer.schedule(
+ (60000 / tempo / Song.currentSong.subBeats).toLong(),
+ (60000 / tempo / Song.currentSong.subBeats).toLong(),
+ callback
+ )
}
}
\ 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 fc5421b..5046664 100644
--- a/app/src/main/java/com/lukas/music/song/Song.kt
+++ b/app/src/main/java/com/lukas/music/song/Song.kt
@@ -14,11 +14,13 @@
import com.lukas.music.song.chords.ChordProgression
import com.lukas.music.song.note.Note
import com.lukas.music.util.Cycle
+import com.lukas.music.util.MetaCycle
class Song(
root: Note,
- val beats: Int
-) : Cycle(beats) {
+ val beats: Int,
+ val subBeats: Int,
+) : MetaCycle>() {
val chordProgression = ChordProgression()
var soloInstrument: Instrument? = null
set(value) {
@@ -46,7 +48,11 @@
init {
for (i in 0 until beats) {
- this += i
+ val cycle = Cycle()
+ for (j in 0 until subBeats) {
+ cycle += j
+ }
+ this += cycle
}
wraparoundListeners += {
chordProgression.step()
@@ -54,24 +60,25 @@
}
}
- override fun step(): Int {
+ override fun step(): Cycle? {
super.step()
- val chord = chordProgression.currentItem?.currentItem ?: return index
+ val chord = chordProgression.currentItem?.currentItem ?: return currentItem
val chordNotes = chord.getNotes(root)
soloInstrument?.let {
- it.voice.step(root, chordNotes, index)
+ it.voice.step(root, chordNotes, index, currentItem!!.index)
} ?: run {
for (instrument in Instrument.instruments) {
- instrument.voice.step(root, chordNotes, index)
+ instrument.voice.step(root, chordNotes, index, currentItem!!.index)
}
}
- return index
+ return currentItem
}
companion object {
var currentSong = Song(
Note.NOTES[69],
- 4
+ 4,
+ 2,
)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt b/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt
index 4706068..66650a2 100644
--- a/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt
+++ b/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt
@@ -14,14 +14,7 @@
import com.lukas.music.song.note.Note
class BassVoice(instrument: Instrument) : Voice(instrument) {
- override var noteActive: Array> = arrayOf(
- arrayOf(true),
- arrayOf(false),
- arrayOf(true),
- arrayOf(false)
- )
-
- override val noteCount: Int = 1
+ override val noteCount: Int get() = 1
override fun getNotes(root: Note, chordNotes: Array): Array {
return arrayOf(chordNotes[0] - 24)
diff --git a/app/src/main/java/com/lukas/music/EditVoiceFragment.kt b/app/src/main/java/com/lukas/music/EditVoiceFragment.kt
deleted file mode 100644
index 56f21e6..0000000
--- a/app/src/main/java/com/lukas/music/EditVoiceFragment.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2022 Lukas Eisenhauer
- *
- * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or(at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program. If not, see .
- */
-
-package com.lukas.music
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TableRow
-import androidx.core.view.setMargins
-import androidx.fragment.app.DialogFragment
-import com.google.android.material.button.MaterialButton
-import com.lukas.music.databinding.FragmentEditVoiceBinding
-import com.lukas.music.song.Song
-import com.lukas.music.song.voice.Voice
-import com.lukas.music.util.ArrayProperty
-import com.lukas.music.util.setupToggle
-
-class EditVoiceFragment(private val voice: Voice) : DialogFragment() {
- private lateinit var binding: FragmentEditVoiceBinding
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- binding = FragmentEditVoiceBinding.inflate(inflater)
- for (row in 0 until voice.noteCount) {
- val rowLayout = TableRow(binding.root.context)
- for (column in 0 until Song.currentSong.beats) {
- val button = MaterialButton(binding.root.context)
- button.layoutParams = buttonLayout
- button.setupToggle(ArrayProperty(voice.noteActive[column], row), R.color.blue)
- rowLayout.addView(button)
- }
- binding.noteGrid.addView(rowLayout)
- }
- binding.noteGrid.isStretchAllColumns = true
- binding.closeButton.setOnClickListener {
- dismiss()
- }
- return binding.root
- }
-
- override fun onStart() {
- super.onStart()
- dialog?.window?.setLayout(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT
- )
- }
-
- companion object {
- val buttonLayout = TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT)
-
- init {
- buttonLayout.setMargins(5)
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/Rhythm.kt b/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
index 75c1545..b310c72 100644
--- a/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
@@ -36,6 +36,10 @@
if (this::task.isInitialized) {
task.cancel()
}
- task = timer.schedule((60000 / tempo).toLong(), (60000 / tempo).toLong(), callback)
+ task = timer.schedule(
+ (60000 / tempo / Song.currentSong.subBeats).toLong(),
+ (60000 / tempo / Song.currentSong.subBeats).toLong(),
+ callback
+ )
}
}
\ 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 fc5421b..5046664 100644
--- a/app/src/main/java/com/lukas/music/song/Song.kt
+++ b/app/src/main/java/com/lukas/music/song/Song.kt
@@ -14,11 +14,13 @@
import com.lukas.music.song.chords.ChordProgression
import com.lukas.music.song.note.Note
import com.lukas.music.util.Cycle
+import com.lukas.music.util.MetaCycle
class Song(
root: Note,
- val beats: Int
-) : Cycle(beats) {
+ val beats: Int,
+ val subBeats: Int,
+) : MetaCycle>() {
val chordProgression = ChordProgression()
var soloInstrument: Instrument? = null
set(value) {
@@ -46,7 +48,11 @@
init {
for (i in 0 until beats) {
- this += i
+ val cycle = Cycle()
+ for (j in 0 until subBeats) {
+ cycle += j
+ }
+ this += cycle
}
wraparoundListeners += {
chordProgression.step()
@@ -54,24 +60,25 @@
}
}
- override fun step(): Int {
+ override fun step(): Cycle? {
super.step()
- val chord = chordProgression.currentItem?.currentItem ?: return index
+ val chord = chordProgression.currentItem?.currentItem ?: return currentItem
val chordNotes = chord.getNotes(root)
soloInstrument?.let {
- it.voice.step(root, chordNotes, index)
+ it.voice.step(root, chordNotes, index, currentItem!!.index)
} ?: run {
for (instrument in Instrument.instruments) {
- instrument.voice.step(root, chordNotes, index)
+ instrument.voice.step(root, chordNotes, index, currentItem!!.index)
}
}
- return index
+ return currentItem
}
companion object {
var currentSong = Song(
Note.NOTES[69],
- 4
+ 4,
+ 2,
)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt b/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt
index 4706068..66650a2 100644
--- a/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt
+++ b/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt
@@ -14,14 +14,7 @@
import com.lukas.music.song.note.Note
class BassVoice(instrument: Instrument) : Voice(instrument) {
- override var noteActive: Array> = arrayOf(
- arrayOf(true),
- arrayOf(false),
- arrayOf(true),
- arrayOf(false)
- )
-
- override val noteCount: Int = 1
+ override val noteCount: Int get() = 1
override fun getNotes(root: Note, chordNotes: Array): Array {
return arrayOf(chordNotes[0] - 24)
diff --git a/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt b/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt
index ab7117f..9a075bc 100644
--- a/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt
+++ b/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt
@@ -14,13 +14,7 @@
import com.lukas.music.song.note.Note
class ChordVoice(instrument: Instrument) : Voice(instrument) {
- override var noteActive: Array> = arrayOf(
- Array(3) { false },
- Array(3) { true },
- Array(3) { false },
- Array(3) { true },
- )
- override val noteCount: Int = 3
+ override val noteCount: Int get() = 3
override fun getNotes(root: Note, chordNotes: Array): Array {
return chordNotes
diff --git a/app/src/main/java/com/lukas/music/EditVoiceFragment.kt b/app/src/main/java/com/lukas/music/EditVoiceFragment.kt
deleted file mode 100644
index 56f21e6..0000000
--- a/app/src/main/java/com/lukas/music/EditVoiceFragment.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2022 Lukas Eisenhauer
- *
- * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or(at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program. If not, see .
- */
-
-package com.lukas.music
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TableRow
-import androidx.core.view.setMargins
-import androidx.fragment.app.DialogFragment
-import com.google.android.material.button.MaterialButton
-import com.lukas.music.databinding.FragmentEditVoiceBinding
-import com.lukas.music.song.Song
-import com.lukas.music.song.voice.Voice
-import com.lukas.music.util.ArrayProperty
-import com.lukas.music.util.setupToggle
-
-class EditVoiceFragment(private val voice: Voice) : DialogFragment() {
- private lateinit var binding: FragmentEditVoiceBinding
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- binding = FragmentEditVoiceBinding.inflate(inflater)
- for (row in 0 until voice.noteCount) {
- val rowLayout = TableRow(binding.root.context)
- for (column in 0 until Song.currentSong.beats) {
- val button = MaterialButton(binding.root.context)
- button.layoutParams = buttonLayout
- button.setupToggle(ArrayProperty(voice.noteActive[column], row), R.color.blue)
- rowLayout.addView(button)
- }
- binding.noteGrid.addView(rowLayout)
- }
- binding.noteGrid.isStretchAllColumns = true
- binding.closeButton.setOnClickListener {
- dismiss()
- }
- return binding.root
- }
-
- override fun onStart() {
- super.onStart()
- dialog?.window?.setLayout(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT
- )
- }
-
- companion object {
- val buttonLayout = TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT)
-
- init {
- buttonLayout.setMargins(5)
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/Rhythm.kt b/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
index 75c1545..b310c72 100644
--- a/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
@@ -36,6 +36,10 @@
if (this::task.isInitialized) {
task.cancel()
}
- task = timer.schedule((60000 / tempo).toLong(), (60000 / tempo).toLong(), callback)
+ task = timer.schedule(
+ (60000 / tempo / Song.currentSong.subBeats).toLong(),
+ (60000 / tempo / Song.currentSong.subBeats).toLong(),
+ callback
+ )
}
}
\ 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 fc5421b..5046664 100644
--- a/app/src/main/java/com/lukas/music/song/Song.kt
+++ b/app/src/main/java/com/lukas/music/song/Song.kt
@@ -14,11 +14,13 @@
import com.lukas.music.song.chords.ChordProgression
import com.lukas.music.song.note.Note
import com.lukas.music.util.Cycle
+import com.lukas.music.util.MetaCycle
class Song(
root: Note,
- val beats: Int
-) : Cycle(beats) {
+ val beats: Int,
+ val subBeats: Int,
+) : MetaCycle>() {
val chordProgression = ChordProgression()
var soloInstrument: Instrument? = null
set(value) {
@@ -46,7 +48,11 @@
init {
for (i in 0 until beats) {
- this += i
+ val cycle = Cycle()
+ for (j in 0 until subBeats) {
+ cycle += j
+ }
+ this += cycle
}
wraparoundListeners += {
chordProgression.step()
@@ -54,24 +60,25 @@
}
}
- override fun step(): Int {
+ override fun step(): Cycle? {
super.step()
- val chord = chordProgression.currentItem?.currentItem ?: return index
+ val chord = chordProgression.currentItem?.currentItem ?: return currentItem
val chordNotes = chord.getNotes(root)
soloInstrument?.let {
- it.voice.step(root, chordNotes, index)
+ it.voice.step(root, chordNotes, index, currentItem!!.index)
} ?: run {
for (instrument in Instrument.instruments) {
- instrument.voice.step(root, chordNotes, index)
+ instrument.voice.step(root, chordNotes, index, currentItem!!.index)
}
}
- return index
+ return currentItem
}
companion object {
var currentSong = Song(
Note.NOTES[69],
- 4
+ 4,
+ 2,
)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt b/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt
index 4706068..66650a2 100644
--- a/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt
+++ b/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt
@@ -14,14 +14,7 @@
import com.lukas.music.song.note.Note
class BassVoice(instrument: Instrument) : Voice(instrument) {
- override var noteActive: Array> = arrayOf(
- arrayOf(true),
- arrayOf(false),
- arrayOf(true),
- arrayOf(false)
- )
-
- override val noteCount: Int = 1
+ override val noteCount: Int get() = 1
override fun getNotes(root: Note, chordNotes: Array): Array {
return arrayOf(chordNotes[0] - 24)
diff --git a/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt b/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt
index ab7117f..9a075bc 100644
--- a/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt
+++ b/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt
@@ -14,13 +14,7 @@
import com.lukas.music.song.note.Note
class ChordVoice(instrument: Instrument) : Voice(instrument) {
- override var noteActive: Array> = arrayOf(
- Array(3) { false },
- Array(3) { true },
- Array(3) { false },
- Array(3) { true },
- )
- override val noteCount: Int = 3
+ override val noteCount: Int get() = 3
override fun getNotes(root: Note, chordNotes: Array): Array {
return chordNotes
diff --git a/app/src/main/java/com/lukas/music/song/voice/Voice.kt b/app/src/main/java/com/lukas/music/song/voice/Voice.kt
index 4f56c2a..54cfe7a 100644
--- a/app/src/main/java/com/lukas/music/song/voice/Voice.kt
+++ b/app/src/main/java/com/lukas/music/song/voice/Voice.kt
@@ -11,20 +11,24 @@
package com.lukas.music.song.voice
import com.lukas.music.instruments.Instrument
+import com.lukas.music.song.Song
import com.lukas.music.song.note.Note
import kotlin.reflect.KClass
abstract class Voice(val instrument: Instrument) {
- abstract var noteActive: Array>
abstract val noteCount: Int
+ val noteActive: Array> =
+ Array(Song.currentSong.beats * Song.currentSong.subBeats) { Array(noteCount) { false } }
+ var repeatNote = true // TODO
abstract fun getNotes(root: Note, chordNotes: Array): Array
- fun step(root: Note, chordNotes: Array, beat: Int) {
+ fun step(root: Note, chordNotes: Array, beat: Int, subBeat: Int) {
if (instrument.muted) {
return
}
- val activeNotes = noteActive[beat]
+ val beatIndex = beat * Song.currentSong.subBeats + subBeat
+ val activeNotes = noteActive[beatIndex]
val notes = getNotes(root, chordNotes)
for ((index, active) in activeNotes.withIndex()) {
val note = notes[index]
diff --git a/app/src/main/java/com/lukas/music/EditVoiceFragment.kt b/app/src/main/java/com/lukas/music/EditVoiceFragment.kt
deleted file mode 100644
index 56f21e6..0000000
--- a/app/src/main/java/com/lukas/music/EditVoiceFragment.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2022 Lukas Eisenhauer
- *
- * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or(at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program. If not, see .
- */
-
-package com.lukas.music
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TableRow
-import androidx.core.view.setMargins
-import androidx.fragment.app.DialogFragment
-import com.google.android.material.button.MaterialButton
-import com.lukas.music.databinding.FragmentEditVoiceBinding
-import com.lukas.music.song.Song
-import com.lukas.music.song.voice.Voice
-import com.lukas.music.util.ArrayProperty
-import com.lukas.music.util.setupToggle
-
-class EditVoiceFragment(private val voice: Voice) : DialogFragment() {
- private lateinit var binding: FragmentEditVoiceBinding
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- binding = FragmentEditVoiceBinding.inflate(inflater)
- for (row in 0 until voice.noteCount) {
- val rowLayout = TableRow(binding.root.context)
- for (column in 0 until Song.currentSong.beats) {
- val button = MaterialButton(binding.root.context)
- button.layoutParams = buttonLayout
- button.setupToggle(ArrayProperty(voice.noteActive[column], row), R.color.blue)
- rowLayout.addView(button)
- }
- binding.noteGrid.addView(rowLayout)
- }
- binding.noteGrid.isStretchAllColumns = true
- binding.closeButton.setOnClickListener {
- dismiss()
- }
- return binding.root
- }
-
- override fun onStart() {
- super.onStart()
- dialog?.window?.setLayout(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT
- )
- }
-
- companion object {
- val buttonLayout = TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT)
-
- init {
- buttonLayout.setMargins(5)
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/Rhythm.kt b/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
index 75c1545..b310c72 100644
--- a/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
@@ -36,6 +36,10 @@
if (this::task.isInitialized) {
task.cancel()
}
- task = timer.schedule((60000 / tempo).toLong(), (60000 / tempo).toLong(), callback)
+ task = timer.schedule(
+ (60000 / tempo / Song.currentSong.subBeats).toLong(),
+ (60000 / tempo / Song.currentSong.subBeats).toLong(),
+ callback
+ )
}
}
\ 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 fc5421b..5046664 100644
--- a/app/src/main/java/com/lukas/music/song/Song.kt
+++ b/app/src/main/java/com/lukas/music/song/Song.kt
@@ -14,11 +14,13 @@
import com.lukas.music.song.chords.ChordProgression
import com.lukas.music.song.note.Note
import com.lukas.music.util.Cycle
+import com.lukas.music.util.MetaCycle
class Song(
root: Note,
- val beats: Int
-) : Cycle(beats) {
+ val beats: Int,
+ val subBeats: Int,
+) : MetaCycle>() {
val chordProgression = ChordProgression()
var soloInstrument: Instrument? = null
set(value) {
@@ -46,7 +48,11 @@
init {
for (i in 0 until beats) {
- this += i
+ val cycle = Cycle()
+ for (j in 0 until subBeats) {
+ cycle += j
+ }
+ this += cycle
}
wraparoundListeners += {
chordProgression.step()
@@ -54,24 +60,25 @@
}
}
- override fun step(): Int {
+ override fun step(): Cycle? {
super.step()
- val chord = chordProgression.currentItem?.currentItem ?: return index
+ val chord = chordProgression.currentItem?.currentItem ?: return currentItem
val chordNotes = chord.getNotes(root)
soloInstrument?.let {
- it.voice.step(root, chordNotes, index)
+ it.voice.step(root, chordNotes, index, currentItem!!.index)
} ?: run {
for (instrument in Instrument.instruments) {
- instrument.voice.step(root, chordNotes, index)
+ instrument.voice.step(root, chordNotes, index, currentItem!!.index)
}
}
- return index
+ return currentItem
}
companion object {
var currentSong = Song(
Note.NOTES[69],
- 4
+ 4,
+ 2,
)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt b/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt
index 4706068..66650a2 100644
--- a/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt
+++ b/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt
@@ -14,14 +14,7 @@
import com.lukas.music.song.note.Note
class BassVoice(instrument: Instrument) : Voice(instrument) {
- override var noteActive: Array> = arrayOf(
- arrayOf(true),
- arrayOf(false),
- arrayOf(true),
- arrayOf(false)
- )
-
- override val noteCount: Int = 1
+ override val noteCount: Int get() = 1
override fun getNotes(root: Note, chordNotes: Array): Array {
return arrayOf(chordNotes[0] - 24)
diff --git a/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt b/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt
index ab7117f..9a075bc 100644
--- a/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt
+++ b/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt
@@ -14,13 +14,7 @@
import com.lukas.music.song.note.Note
class ChordVoice(instrument: Instrument) : Voice(instrument) {
- override var noteActive: Array> = arrayOf(
- Array(3) { false },
- Array(3) { true },
- Array(3) { false },
- Array(3) { true },
- )
- override val noteCount: Int = 3
+ override val noteCount: Int get() = 3
override fun getNotes(root: Note, chordNotes: Array): Array {
return chordNotes
diff --git a/app/src/main/java/com/lukas/music/song/voice/Voice.kt b/app/src/main/java/com/lukas/music/song/voice/Voice.kt
index 4f56c2a..54cfe7a 100644
--- a/app/src/main/java/com/lukas/music/song/voice/Voice.kt
+++ b/app/src/main/java/com/lukas/music/song/voice/Voice.kt
@@ -11,20 +11,24 @@
package com.lukas.music.song.voice
import com.lukas.music.instruments.Instrument
+import com.lukas.music.song.Song
import com.lukas.music.song.note.Note
import kotlin.reflect.KClass
abstract class Voice(val instrument: Instrument) {
- abstract var noteActive: Array>
abstract val noteCount: Int
+ val noteActive: Array> =
+ Array(Song.currentSong.beats * Song.currentSong.subBeats) { Array(noteCount) { false } }
+ var repeatNote = true // TODO
abstract fun getNotes(root: Note, chordNotes: Array): Array
- fun step(root: Note, chordNotes: Array, beat: Int) {
+ fun step(root: Note, chordNotes: Array, beat: Int, subBeat: Int) {
if (instrument.muted) {
return
}
- val activeNotes = noteActive[beat]
+ val beatIndex = beat * Song.currentSong.subBeats + subBeat
+ val activeNotes = noteActive[beatIndex]
val notes = getNotes(root, chordNotes)
for ((index, active) in activeNotes.withIndex()) {
val note = notes[index]
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/EditInstrumentFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/EditInstrumentFragment.kt
index 0020ae8..9c76f59 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/EditInstrumentFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditInstrumentFragment.kt
@@ -17,7 +17,6 @@
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.DialogFragment
-import com.lukas.music.EditVoiceFragment
import com.lukas.music.databinding.FragmentEditInstrumentBinding
import com.lukas.music.instruments.Instrument
import com.lukas.music.instruments.Waveform
diff --git a/app/src/main/java/com/lukas/music/EditVoiceFragment.kt b/app/src/main/java/com/lukas/music/EditVoiceFragment.kt
deleted file mode 100644
index 56f21e6..0000000
--- a/app/src/main/java/com/lukas/music/EditVoiceFragment.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2022 Lukas Eisenhauer
- *
- * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or(at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program. If not, see .
- */
-
-package com.lukas.music
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TableRow
-import androidx.core.view.setMargins
-import androidx.fragment.app.DialogFragment
-import com.google.android.material.button.MaterialButton
-import com.lukas.music.databinding.FragmentEditVoiceBinding
-import com.lukas.music.song.Song
-import com.lukas.music.song.voice.Voice
-import com.lukas.music.util.ArrayProperty
-import com.lukas.music.util.setupToggle
-
-class EditVoiceFragment(private val voice: Voice) : DialogFragment() {
- private lateinit var binding: FragmentEditVoiceBinding
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- binding = FragmentEditVoiceBinding.inflate(inflater)
- for (row in 0 until voice.noteCount) {
- val rowLayout = TableRow(binding.root.context)
- for (column in 0 until Song.currentSong.beats) {
- val button = MaterialButton(binding.root.context)
- button.layoutParams = buttonLayout
- button.setupToggle(ArrayProperty(voice.noteActive[column], row), R.color.blue)
- rowLayout.addView(button)
- }
- binding.noteGrid.addView(rowLayout)
- }
- binding.noteGrid.isStretchAllColumns = true
- binding.closeButton.setOnClickListener {
- dismiss()
- }
- return binding.root
- }
-
- override fun onStart() {
- super.onStart()
- dialog?.window?.setLayout(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT
- )
- }
-
- companion object {
- val buttonLayout = TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT)
-
- init {
- buttonLayout.setMargins(5)
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/Rhythm.kt b/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
index 75c1545..b310c72 100644
--- a/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
@@ -36,6 +36,10 @@
if (this::task.isInitialized) {
task.cancel()
}
- task = timer.schedule((60000 / tempo).toLong(), (60000 / tempo).toLong(), callback)
+ task = timer.schedule(
+ (60000 / tempo / Song.currentSong.subBeats).toLong(),
+ (60000 / tempo / Song.currentSong.subBeats).toLong(),
+ callback
+ )
}
}
\ 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 fc5421b..5046664 100644
--- a/app/src/main/java/com/lukas/music/song/Song.kt
+++ b/app/src/main/java/com/lukas/music/song/Song.kt
@@ -14,11 +14,13 @@
import com.lukas.music.song.chords.ChordProgression
import com.lukas.music.song.note.Note
import com.lukas.music.util.Cycle
+import com.lukas.music.util.MetaCycle
class Song(
root: Note,
- val beats: Int
-) : Cycle(beats) {
+ val beats: Int,
+ val subBeats: Int,
+) : MetaCycle>() {
val chordProgression = ChordProgression()
var soloInstrument: Instrument? = null
set(value) {
@@ -46,7 +48,11 @@
init {
for (i in 0 until beats) {
- this += i
+ val cycle = Cycle()
+ for (j in 0 until subBeats) {
+ cycle += j
+ }
+ this += cycle
}
wraparoundListeners += {
chordProgression.step()
@@ -54,24 +60,25 @@
}
}
- override fun step(): Int {
+ override fun step(): Cycle? {
super.step()
- val chord = chordProgression.currentItem?.currentItem ?: return index
+ val chord = chordProgression.currentItem?.currentItem ?: return currentItem
val chordNotes = chord.getNotes(root)
soloInstrument?.let {
- it.voice.step(root, chordNotes, index)
+ it.voice.step(root, chordNotes, index, currentItem!!.index)
} ?: run {
for (instrument in Instrument.instruments) {
- instrument.voice.step(root, chordNotes, index)
+ instrument.voice.step(root, chordNotes, index, currentItem!!.index)
}
}
- return index
+ return currentItem
}
companion object {
var currentSong = Song(
Note.NOTES[69],
- 4
+ 4,
+ 2,
)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt b/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt
index 4706068..66650a2 100644
--- a/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt
+++ b/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt
@@ -14,14 +14,7 @@
import com.lukas.music.song.note.Note
class BassVoice(instrument: Instrument) : Voice(instrument) {
- override var noteActive: Array> = arrayOf(
- arrayOf(true),
- arrayOf(false),
- arrayOf(true),
- arrayOf(false)
- )
-
- override val noteCount: Int = 1
+ override val noteCount: Int get() = 1
override fun getNotes(root: Note, chordNotes: Array): Array {
return arrayOf(chordNotes[0] - 24)
diff --git a/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt b/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt
index ab7117f..9a075bc 100644
--- a/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt
+++ b/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt
@@ -14,13 +14,7 @@
import com.lukas.music.song.note.Note
class ChordVoice(instrument: Instrument) : Voice(instrument) {
- override var noteActive: Array> = arrayOf(
- Array(3) { false },
- Array(3) { true },
- Array(3) { false },
- Array(3) { true },
- )
- override val noteCount: Int = 3
+ override val noteCount: Int get() = 3
override fun getNotes(root: Note, chordNotes: Array): Array {
return chordNotes
diff --git a/app/src/main/java/com/lukas/music/song/voice/Voice.kt b/app/src/main/java/com/lukas/music/song/voice/Voice.kt
index 4f56c2a..54cfe7a 100644
--- a/app/src/main/java/com/lukas/music/song/voice/Voice.kt
+++ b/app/src/main/java/com/lukas/music/song/voice/Voice.kt
@@ -11,20 +11,24 @@
package com.lukas.music.song.voice
import com.lukas.music.instruments.Instrument
+import com.lukas.music.song.Song
import com.lukas.music.song.note.Note
import kotlin.reflect.KClass
abstract class Voice(val instrument: Instrument) {
- abstract var noteActive: Array>
abstract val noteCount: Int
+ val noteActive: Array> =
+ Array(Song.currentSong.beats * Song.currentSong.subBeats) { Array(noteCount) { false } }
+ var repeatNote = true // TODO
abstract fun getNotes(root: Note, chordNotes: Array): Array
- fun step(root: Note, chordNotes: Array, beat: Int) {
+ fun step(root: Note, chordNotes: Array, beat: Int, subBeat: Int) {
if (instrument.muted) {
return
}
- val activeNotes = noteActive[beat]
+ val beatIndex = beat * Song.currentSong.subBeats + subBeat
+ val activeNotes = noteActive[beatIndex]
val notes = getNotes(root, chordNotes)
for ((index, active) in activeNotes.withIndex()) {
val note = notes[index]
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/EditInstrumentFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/EditInstrumentFragment.kt
index 0020ae8..9c76f59 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/EditInstrumentFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditInstrumentFragment.kt
@@ -17,7 +17,6 @@
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.DialogFragment
-import com.lukas.music.EditVoiceFragment
import com.lukas.music.databinding.FragmentEditInstrumentBinding
import com.lukas.music.instruments.Instrument
import com.lukas.music.instruments.Waveform
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/EditVoiceFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/EditVoiceFragment.kt
new file mode 100644
index 0000000..58a856f
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditVoiceFragment.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2022 Lukas Eisenhauer
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or(at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ */
+
+package com.lukas.music.ui.fragments
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TableRow
+import androidx.core.view.setMargins
+import androidx.fragment.app.DialogFragment
+import com.google.android.material.button.MaterialButton
+import com.lukas.music.R
+import com.lukas.music.databinding.FragmentEditVoiceBinding
+import com.lukas.music.song.Song
+import com.lukas.music.song.voice.Voice
+import com.lukas.music.util.ArrayProperty
+import com.lukas.music.util.setupToggle
+
+class EditVoiceFragment(private val voice: Voice) : DialogFragment() {
+ private lateinit var binding: FragmentEditVoiceBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentEditVoiceBinding.inflate(inflater)
+ for (row in voice.noteCount - 1 downTo 0) {
+ val rowLayout = TableRow(binding.root.context)
+ for (column in 0 until Song.currentSong.beats * Song.currentSong.subBeats) {
+ val button = MaterialButton(binding.root.context)
+ button.layoutParams = buttonLayout
+ button.setupToggle(
+ ArrayProperty(voice.noteActive[column], row),
+ R.color.blue,
+ inactiveColor = if (column % Song.currentSong.subBeats == 0) R.color.gray_0x50 else R.color.gray_0x70
+ )
+ rowLayout.addView(button)
+ }
+ binding.noteGrid.addView(rowLayout)
+ }
+ binding.noteGrid.isStretchAllColumns = true
+ binding.closeButton.setOnClickListener {
+ dismiss()
+ }
+ return binding.root
+ }
+
+ override fun onStart() {
+ super.onStart()
+ dialog?.window?.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ companion object {
+ val buttonLayout = TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT)
+
+ init {
+ buttonLayout.setMargins(5)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/EditVoiceFragment.kt b/app/src/main/java/com/lukas/music/EditVoiceFragment.kt
deleted file mode 100644
index 56f21e6..0000000
--- a/app/src/main/java/com/lukas/music/EditVoiceFragment.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2022 Lukas Eisenhauer
- *
- * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or(at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program. If not, see .
- */
-
-package com.lukas.music
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TableRow
-import androidx.core.view.setMargins
-import androidx.fragment.app.DialogFragment
-import com.google.android.material.button.MaterialButton
-import com.lukas.music.databinding.FragmentEditVoiceBinding
-import com.lukas.music.song.Song
-import com.lukas.music.song.voice.Voice
-import com.lukas.music.util.ArrayProperty
-import com.lukas.music.util.setupToggle
-
-class EditVoiceFragment(private val voice: Voice) : DialogFragment() {
- private lateinit var binding: FragmentEditVoiceBinding
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- binding = FragmentEditVoiceBinding.inflate(inflater)
- for (row in 0 until voice.noteCount) {
- val rowLayout = TableRow(binding.root.context)
- for (column in 0 until Song.currentSong.beats) {
- val button = MaterialButton(binding.root.context)
- button.layoutParams = buttonLayout
- button.setupToggle(ArrayProperty(voice.noteActive[column], row), R.color.blue)
- rowLayout.addView(button)
- }
- binding.noteGrid.addView(rowLayout)
- }
- binding.noteGrid.isStretchAllColumns = true
- binding.closeButton.setOnClickListener {
- dismiss()
- }
- return binding.root
- }
-
- override fun onStart() {
- super.onStart()
- dialog?.window?.setLayout(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT
- )
- }
-
- companion object {
- val buttonLayout = TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT)
-
- init {
- buttonLayout.setMargins(5)
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/Rhythm.kt b/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
index 75c1545..b310c72 100644
--- a/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
@@ -36,6 +36,10 @@
if (this::task.isInitialized) {
task.cancel()
}
- task = timer.schedule((60000 / tempo).toLong(), (60000 / tempo).toLong(), callback)
+ task = timer.schedule(
+ (60000 / tempo / Song.currentSong.subBeats).toLong(),
+ (60000 / tempo / Song.currentSong.subBeats).toLong(),
+ callback
+ )
}
}
\ 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 fc5421b..5046664 100644
--- a/app/src/main/java/com/lukas/music/song/Song.kt
+++ b/app/src/main/java/com/lukas/music/song/Song.kt
@@ -14,11 +14,13 @@
import com.lukas.music.song.chords.ChordProgression
import com.lukas.music.song.note.Note
import com.lukas.music.util.Cycle
+import com.lukas.music.util.MetaCycle
class Song(
root: Note,
- val beats: Int
-) : Cycle(beats) {
+ val beats: Int,
+ val subBeats: Int,
+) : MetaCycle>() {
val chordProgression = ChordProgression()
var soloInstrument: Instrument? = null
set(value) {
@@ -46,7 +48,11 @@
init {
for (i in 0 until beats) {
- this += i
+ val cycle = Cycle()
+ for (j in 0 until subBeats) {
+ cycle += j
+ }
+ this += cycle
}
wraparoundListeners += {
chordProgression.step()
@@ -54,24 +60,25 @@
}
}
- override fun step(): Int {
+ override fun step(): Cycle? {
super.step()
- val chord = chordProgression.currentItem?.currentItem ?: return index
+ val chord = chordProgression.currentItem?.currentItem ?: return currentItem
val chordNotes = chord.getNotes(root)
soloInstrument?.let {
- it.voice.step(root, chordNotes, index)
+ it.voice.step(root, chordNotes, index, currentItem!!.index)
} ?: run {
for (instrument in Instrument.instruments) {
- instrument.voice.step(root, chordNotes, index)
+ instrument.voice.step(root, chordNotes, index, currentItem!!.index)
}
}
- return index
+ return currentItem
}
companion object {
var currentSong = Song(
Note.NOTES[69],
- 4
+ 4,
+ 2,
)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt b/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt
index 4706068..66650a2 100644
--- a/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt
+++ b/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt
@@ -14,14 +14,7 @@
import com.lukas.music.song.note.Note
class BassVoice(instrument: Instrument) : Voice(instrument) {
- override var noteActive: Array> = arrayOf(
- arrayOf(true),
- arrayOf(false),
- arrayOf(true),
- arrayOf(false)
- )
-
- override val noteCount: Int = 1
+ override val noteCount: Int get() = 1
override fun getNotes(root: Note, chordNotes: Array): Array {
return arrayOf(chordNotes[0] - 24)
diff --git a/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt b/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt
index ab7117f..9a075bc 100644
--- a/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt
+++ b/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt
@@ -14,13 +14,7 @@
import com.lukas.music.song.note.Note
class ChordVoice(instrument: Instrument) : Voice(instrument) {
- override var noteActive: Array> = arrayOf(
- Array(3) { false },
- Array(3) { true },
- Array(3) { false },
- Array(3) { true },
- )
- override val noteCount: Int = 3
+ override val noteCount: Int get() = 3
override fun getNotes(root: Note, chordNotes: Array): Array {
return chordNotes
diff --git a/app/src/main/java/com/lukas/music/song/voice/Voice.kt b/app/src/main/java/com/lukas/music/song/voice/Voice.kt
index 4f56c2a..54cfe7a 100644
--- a/app/src/main/java/com/lukas/music/song/voice/Voice.kt
+++ b/app/src/main/java/com/lukas/music/song/voice/Voice.kt
@@ -11,20 +11,24 @@
package com.lukas.music.song.voice
import com.lukas.music.instruments.Instrument
+import com.lukas.music.song.Song
import com.lukas.music.song.note.Note
import kotlin.reflect.KClass
abstract class Voice(val instrument: Instrument) {
- abstract var noteActive: Array>
abstract val noteCount: Int
+ val noteActive: Array> =
+ Array(Song.currentSong.beats * Song.currentSong.subBeats) { Array(noteCount) { false } }
+ var repeatNote = true // TODO
abstract fun getNotes(root: Note, chordNotes: Array): Array
- fun step(root: Note, chordNotes: Array, beat: Int) {
+ fun step(root: Note, chordNotes: Array, beat: Int, subBeat: Int) {
if (instrument.muted) {
return
}
- val activeNotes = noteActive[beat]
+ val beatIndex = beat * Song.currentSong.subBeats + subBeat
+ val activeNotes = noteActive[beatIndex]
val notes = getNotes(root, chordNotes)
for ((index, active) in activeNotes.withIndex()) {
val note = notes[index]
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/EditInstrumentFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/EditInstrumentFragment.kt
index 0020ae8..9c76f59 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/EditInstrumentFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditInstrumentFragment.kt
@@ -17,7 +17,6 @@
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.DialogFragment
-import com.lukas.music.EditVoiceFragment
import com.lukas.music.databinding.FragmentEditInstrumentBinding
import com.lukas.music.instruments.Instrument
import com.lukas.music.instruments.Waveform
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/EditVoiceFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/EditVoiceFragment.kt
new file mode 100644
index 0000000..58a856f
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditVoiceFragment.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2022 Lukas Eisenhauer
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or(at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ */
+
+package com.lukas.music.ui.fragments
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TableRow
+import androidx.core.view.setMargins
+import androidx.fragment.app.DialogFragment
+import com.google.android.material.button.MaterialButton
+import com.lukas.music.R
+import com.lukas.music.databinding.FragmentEditVoiceBinding
+import com.lukas.music.song.Song
+import com.lukas.music.song.voice.Voice
+import com.lukas.music.util.ArrayProperty
+import com.lukas.music.util.setupToggle
+
+class EditVoiceFragment(private val voice: Voice) : DialogFragment() {
+ private lateinit var binding: FragmentEditVoiceBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentEditVoiceBinding.inflate(inflater)
+ for (row in voice.noteCount - 1 downTo 0) {
+ val rowLayout = TableRow(binding.root.context)
+ for (column in 0 until Song.currentSong.beats * Song.currentSong.subBeats) {
+ val button = MaterialButton(binding.root.context)
+ button.layoutParams = buttonLayout
+ button.setupToggle(
+ ArrayProperty(voice.noteActive[column], row),
+ R.color.blue,
+ inactiveColor = if (column % Song.currentSong.subBeats == 0) R.color.gray_0x50 else R.color.gray_0x70
+ )
+ rowLayout.addView(button)
+ }
+ binding.noteGrid.addView(rowLayout)
+ }
+ binding.noteGrid.isStretchAllColumns = true
+ binding.closeButton.setOnClickListener {
+ dismiss()
+ }
+ return binding.root
+ }
+
+ override fun onStart() {
+ super.onStart()
+ dialog?.window?.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ companion object {
+ val buttonLayout = TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT)
+
+ init {
+ buttonLayout.setMargins(5)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/util/UIUtil.kt b/app/src/main/java/com/lukas/music/util/UIUtil.kt
index da897c5..e7ba28f 100644
--- a/app/src/main/java/com/lukas/music/util/UIUtil.kt
+++ b/app/src/main/java/com/lukas/music/util/UIUtil.kt
@@ -42,19 +42,24 @@
fun Button.setupToggle(
target: KMutableProperty0,
activeColor: Int,
- callback: (Boolean) -> Unit = {}
+ inactiveColor: Int = R.color.gray_0x60,
+ callback: (Boolean) -> Unit = {},
) {
setOnClickListener {
target.set(!target.get())
- updateToggle(target, activeColor)
+ updateToggle(target, activeColor, inactiveColor)
callback(target.get())
}
- updateToggle(target, activeColor)
+ updateToggle(target, activeColor, inactiveColor)
}
-fun Button.updateToggle(target: KMutableProperty0, activeColor: Int) {
+fun Button.updateToggle(
+ target: KMutableProperty0,
+ activeColor: Int,
+ inactiveColor: Int = R.color.gray_0x60,
+) {
setBackgroundColor(
- ContextCompat.getColor(context, if (target.get()) activeColor else R.color.gray_0x60)
+ ContextCompat.getColor(context, if (target.get()) activeColor else inactiveColor)
)
}
diff --git a/app/src/main/java/com/lukas/music/EditVoiceFragment.kt b/app/src/main/java/com/lukas/music/EditVoiceFragment.kt
deleted file mode 100644
index 56f21e6..0000000
--- a/app/src/main/java/com/lukas/music/EditVoiceFragment.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2022 Lukas Eisenhauer
- *
- * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or(at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program. If not, see .
- */
-
-package com.lukas.music
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TableRow
-import androidx.core.view.setMargins
-import androidx.fragment.app.DialogFragment
-import com.google.android.material.button.MaterialButton
-import com.lukas.music.databinding.FragmentEditVoiceBinding
-import com.lukas.music.song.Song
-import com.lukas.music.song.voice.Voice
-import com.lukas.music.util.ArrayProperty
-import com.lukas.music.util.setupToggle
-
-class EditVoiceFragment(private val voice: Voice) : DialogFragment() {
- private lateinit var binding: FragmentEditVoiceBinding
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- binding = FragmentEditVoiceBinding.inflate(inflater)
- for (row in 0 until voice.noteCount) {
- val rowLayout = TableRow(binding.root.context)
- for (column in 0 until Song.currentSong.beats) {
- val button = MaterialButton(binding.root.context)
- button.layoutParams = buttonLayout
- button.setupToggle(ArrayProperty(voice.noteActive[column], row), R.color.blue)
- rowLayout.addView(button)
- }
- binding.noteGrid.addView(rowLayout)
- }
- binding.noteGrid.isStretchAllColumns = true
- binding.closeButton.setOnClickListener {
- dismiss()
- }
- return binding.root
- }
-
- override fun onStart() {
- super.onStart()
- dialog?.window?.setLayout(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT
- )
- }
-
- companion object {
- val buttonLayout = TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT)
-
- init {
- buttonLayout.setMargins(5)
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/Rhythm.kt b/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
index 75c1545..b310c72 100644
--- a/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Rhythm.kt
@@ -36,6 +36,10 @@
if (this::task.isInitialized) {
task.cancel()
}
- task = timer.schedule((60000 / tempo).toLong(), (60000 / tempo).toLong(), callback)
+ task = timer.schedule(
+ (60000 / tempo / Song.currentSong.subBeats).toLong(),
+ (60000 / tempo / Song.currentSong.subBeats).toLong(),
+ callback
+ )
}
}
\ 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 fc5421b..5046664 100644
--- a/app/src/main/java/com/lukas/music/song/Song.kt
+++ b/app/src/main/java/com/lukas/music/song/Song.kt
@@ -14,11 +14,13 @@
import com.lukas.music.song.chords.ChordProgression
import com.lukas.music.song.note.Note
import com.lukas.music.util.Cycle
+import com.lukas.music.util.MetaCycle
class Song(
root: Note,
- val beats: Int
-) : Cycle(beats) {
+ val beats: Int,
+ val subBeats: Int,
+) : MetaCycle>() {
val chordProgression = ChordProgression()
var soloInstrument: Instrument? = null
set(value) {
@@ -46,7 +48,11 @@
init {
for (i in 0 until beats) {
- this += i
+ val cycle = Cycle()
+ for (j in 0 until subBeats) {
+ cycle += j
+ }
+ this += cycle
}
wraparoundListeners += {
chordProgression.step()
@@ -54,24 +60,25 @@
}
}
- override fun step(): Int {
+ override fun step(): Cycle? {
super.step()
- val chord = chordProgression.currentItem?.currentItem ?: return index
+ val chord = chordProgression.currentItem?.currentItem ?: return currentItem
val chordNotes = chord.getNotes(root)
soloInstrument?.let {
- it.voice.step(root, chordNotes, index)
+ it.voice.step(root, chordNotes, index, currentItem!!.index)
} ?: run {
for (instrument in Instrument.instruments) {
- instrument.voice.step(root, chordNotes, index)
+ instrument.voice.step(root, chordNotes, index, currentItem!!.index)
}
}
- return index
+ return currentItem
}
companion object {
var currentSong = Song(
Note.NOTES[69],
- 4
+ 4,
+ 2,
)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt b/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt
index 4706068..66650a2 100644
--- a/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt
+++ b/app/src/main/java/com/lukas/music/song/voice/BassVoice.kt
@@ -14,14 +14,7 @@
import com.lukas.music.song.note.Note
class BassVoice(instrument: Instrument) : Voice(instrument) {
- override var noteActive: Array> = arrayOf(
- arrayOf(true),
- arrayOf(false),
- arrayOf(true),
- arrayOf(false)
- )
-
- override val noteCount: Int = 1
+ override val noteCount: Int get() = 1
override fun getNotes(root: Note, chordNotes: Array): Array {
return arrayOf(chordNotes[0] - 24)
diff --git a/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt b/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt
index ab7117f..9a075bc 100644
--- a/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt
+++ b/app/src/main/java/com/lukas/music/song/voice/ChordVoice.kt
@@ -14,13 +14,7 @@
import com.lukas.music.song.note.Note
class ChordVoice(instrument: Instrument) : Voice(instrument) {
- override var noteActive: Array> = arrayOf(
- Array(3) { false },
- Array(3) { true },
- Array(3) { false },
- Array(3) { true },
- )
- override val noteCount: Int = 3
+ override val noteCount: Int get() = 3
override fun getNotes(root: Note, chordNotes: Array): Array {
return chordNotes
diff --git a/app/src/main/java/com/lukas/music/song/voice/Voice.kt b/app/src/main/java/com/lukas/music/song/voice/Voice.kt
index 4f56c2a..54cfe7a 100644
--- a/app/src/main/java/com/lukas/music/song/voice/Voice.kt
+++ b/app/src/main/java/com/lukas/music/song/voice/Voice.kt
@@ -11,20 +11,24 @@
package com.lukas.music.song.voice
import com.lukas.music.instruments.Instrument
+import com.lukas.music.song.Song
import com.lukas.music.song.note.Note
import kotlin.reflect.KClass
abstract class Voice(val instrument: Instrument) {
- abstract var noteActive: Array>
abstract val noteCount: Int
+ val noteActive: Array> =
+ Array(Song.currentSong.beats * Song.currentSong.subBeats) { Array(noteCount) { false } }
+ var repeatNote = true // TODO
abstract fun getNotes(root: Note, chordNotes: Array): Array
- fun step(root: Note, chordNotes: Array, beat: Int) {
+ fun step(root: Note, chordNotes: Array, beat: Int, subBeat: Int) {
if (instrument.muted) {
return
}
- val activeNotes = noteActive[beat]
+ val beatIndex = beat * Song.currentSong.subBeats + subBeat
+ val activeNotes = noteActive[beatIndex]
val notes = getNotes(root, chordNotes)
for ((index, active) in activeNotes.withIndex()) {
val note = notes[index]
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/EditInstrumentFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/EditInstrumentFragment.kt
index 0020ae8..9c76f59 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/EditInstrumentFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditInstrumentFragment.kt
@@ -17,7 +17,6 @@
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.DialogFragment
-import com.lukas.music.EditVoiceFragment
import com.lukas.music.databinding.FragmentEditInstrumentBinding
import com.lukas.music.instruments.Instrument
import com.lukas.music.instruments.Waveform
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/EditVoiceFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/EditVoiceFragment.kt
new file mode 100644
index 0000000..58a856f
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditVoiceFragment.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2022 Lukas Eisenhauer
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or(at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with this program. If not, see .
+ */
+
+package com.lukas.music.ui.fragments
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TableRow
+import androidx.core.view.setMargins
+import androidx.fragment.app.DialogFragment
+import com.google.android.material.button.MaterialButton
+import com.lukas.music.R
+import com.lukas.music.databinding.FragmentEditVoiceBinding
+import com.lukas.music.song.Song
+import com.lukas.music.song.voice.Voice
+import com.lukas.music.util.ArrayProperty
+import com.lukas.music.util.setupToggle
+
+class EditVoiceFragment(private val voice: Voice) : DialogFragment() {
+ private lateinit var binding: FragmentEditVoiceBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentEditVoiceBinding.inflate(inflater)
+ for (row in voice.noteCount - 1 downTo 0) {
+ val rowLayout = TableRow(binding.root.context)
+ for (column in 0 until Song.currentSong.beats * Song.currentSong.subBeats) {
+ val button = MaterialButton(binding.root.context)
+ button.layoutParams = buttonLayout
+ button.setupToggle(
+ ArrayProperty(voice.noteActive[column], row),
+ R.color.blue,
+ inactiveColor = if (column % Song.currentSong.subBeats == 0) R.color.gray_0x50 else R.color.gray_0x70
+ )
+ rowLayout.addView(button)
+ }
+ binding.noteGrid.addView(rowLayout)
+ }
+ binding.noteGrid.isStretchAllColumns = true
+ binding.closeButton.setOnClickListener {
+ dismiss()
+ }
+ return binding.root
+ }
+
+ override fun onStart() {
+ super.onStart()
+ dialog?.window?.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+
+ companion object {
+ val buttonLayout = TableRow.LayoutParams(0, TableRow.LayoutParams.WRAP_CONTENT)
+
+ init {
+ buttonLayout.setMargins(5)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/util/UIUtil.kt b/app/src/main/java/com/lukas/music/util/UIUtil.kt
index da897c5..e7ba28f 100644
--- a/app/src/main/java/com/lukas/music/util/UIUtil.kt
+++ b/app/src/main/java/com/lukas/music/util/UIUtil.kt
@@ -42,19 +42,24 @@
fun Button.setupToggle(
target: KMutableProperty0,
activeColor: Int,
- callback: (Boolean) -> Unit = {}
+ inactiveColor: Int = R.color.gray_0x60,
+ callback: (Boolean) -> Unit = {},
) {
setOnClickListener {
target.set(!target.get())
- updateToggle(target, activeColor)
+ updateToggle(target, activeColor, inactiveColor)
callback(target.get())
}
- updateToggle(target, activeColor)
+ updateToggle(target, activeColor, inactiveColor)
}
-fun Button.updateToggle(target: KMutableProperty0, activeColor: Int) {
+fun Button.updateToggle(
+ target: KMutableProperty0,
+ activeColor: Int,
+ inactiveColor: Int = R.color.gray_0x60,
+) {
setBackgroundColor(
- ContextCompat.getColor(context, if (target.get()) activeColor else R.color.gray_0x60)
+ ContextCompat.getColor(context, if (target.get()) activeColor else inactiveColor)
)
}
diff --git a/app/src/main/res/layout/fragment_edit_voice.xml b/app/src/main/res/layout/fragment_edit_voice.xml
index b29b2c7..5380d7d 100644
--- a/app/src/main/res/layout/fragment_edit_voice.xml
+++ b/app/src/main/res/layout/fragment_edit_voice.xml
@@ -14,7 +14,7 @@
android:id="@+id/frameLayout2"
android:layout_width="match_parent"
android:layout_height="match_parent"
- tools:context=".EditVoiceFragment">
+ tools:context=".ui.fragments.EditVoiceFragment">