diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3d886c4..66c49ef 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -11,6 +11,7 @@
+
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3d886c4..66c49ef 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -11,6 +11,7 @@
+
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index 5505a35..d26ee2b 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -76,4 +76,20 @@
listSet(audioHost->instruments->begin(), id, nullptr);
delete getInstrument(id);
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_updateEnvelopeParameters(JNIEnv *env,
+ jobject thiz, jint id,
+ jfloat attack,
+ jfloat delay,
+ jfloat sustain,
+ jfloat release) {
+ Instrument *instrument = getInstrument((id));
+ Envelope *envelope = instrument->envelope;
+ envelope->attack = attack;
+ envelope->delay = delay;
+ envelope->sustain = sustain;
+ envelope->release = release;
+ envelope->update();
+}
}
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3d886c4..66c49ef 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -11,6 +11,7 @@
+
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index 5505a35..d26ee2b 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -76,4 +76,20 @@
listSet(audioHost->instruments->begin(), id, nullptr);
delete getInstrument(id);
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_updateEnvelopeParameters(JNIEnv *env,
+ jobject thiz, jint id,
+ jfloat attack,
+ jfloat delay,
+ jfloat sustain,
+ jfloat release) {
+ Instrument *instrument = getInstrument((id));
+ Envelope *envelope = instrument->envelope;
+ envelope->attack = attack;
+ envelope->delay = delay;
+ envelope->sustain = sustain;
+ envelope->release = release;
+ envelope->update();
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Envelope.cpp b/app/src/main/cpp/effects/Envelope.cpp
index f8dfd61..5400548 100644
--- a/app/src/main/cpp/effects/Envelope.cpp
+++ b/app/src/main/cpp/effects/Envelope.cpp
@@ -3,6 +3,11 @@
#include "Envelope.h"
void Envelope::initialize(AudioHost *host) {
+ this->host = host;
+ update();
+}
+
+void Envelope::update() {
attackIncrement = 1 / attack / host->sampleRate;
delayIncrement = 1 / delay / host->sampleRate;
releaseIncrement = 1 / release / host->sampleRate;
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3d886c4..66c49ef 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -11,6 +11,7 @@
+
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index 5505a35..d26ee2b 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -76,4 +76,20 @@
listSet(audioHost->instruments->begin(), id, nullptr);
delete getInstrument(id);
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_updateEnvelopeParameters(JNIEnv *env,
+ jobject thiz, jint id,
+ jfloat attack,
+ jfloat delay,
+ jfloat sustain,
+ jfloat release) {
+ Instrument *instrument = getInstrument((id));
+ Envelope *envelope = instrument->envelope;
+ envelope->attack = attack;
+ envelope->delay = delay;
+ envelope->sustain = sustain;
+ envelope->release = release;
+ envelope->update();
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Envelope.cpp b/app/src/main/cpp/effects/Envelope.cpp
index f8dfd61..5400548 100644
--- a/app/src/main/cpp/effects/Envelope.cpp
+++ b/app/src/main/cpp/effects/Envelope.cpp
@@ -3,6 +3,11 @@
#include "Envelope.h"
void Envelope::initialize(AudioHost *host) {
+ this->host = host;
+ update();
+}
+
+void Envelope::update() {
attackIncrement = 1 / attack / host->sampleRate;
delayIncrement = 1 / delay / host->sampleRate;
releaseIncrement = 1 / release / host->sampleRate;
diff --git a/app/src/main/cpp/effects/Envelope.h b/app/src/main/cpp/effects/Envelope.h
index 7076f8f..dbb5575 100644
--- a/app/src/main/cpp/effects/Envelope.h
+++ b/app/src/main/cpp/effects/Envelope.h
@@ -16,15 +16,16 @@
EnvelopePhase phase;
float attackIncrement, delayIncrement, releaseIncrement;
float value = 0;
+ AudioHost *host;
public:
- float attack = 0.05, delay = 0.2, sustain = 0.75, release = 1;
+ float attack = 0.05, delay = 0.05, sustain = 0.7, release = 0.1;
void initialize(AudioHost *host);
+ void update();
+
void startNote();
-
void endNote();
-
void doRender(uint32_t sampleCount);
};
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3d886c4..66c49ef 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -11,6 +11,7 @@
+
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index 5505a35..d26ee2b 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -76,4 +76,20 @@
listSet(audioHost->instruments->begin(), id, nullptr);
delete getInstrument(id);
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_updateEnvelopeParameters(JNIEnv *env,
+ jobject thiz, jint id,
+ jfloat attack,
+ jfloat delay,
+ jfloat sustain,
+ jfloat release) {
+ Instrument *instrument = getInstrument((id));
+ Envelope *envelope = instrument->envelope;
+ envelope->attack = attack;
+ envelope->delay = delay;
+ envelope->sustain = sustain;
+ envelope->release = release;
+ envelope->update();
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Envelope.cpp b/app/src/main/cpp/effects/Envelope.cpp
index f8dfd61..5400548 100644
--- a/app/src/main/cpp/effects/Envelope.cpp
+++ b/app/src/main/cpp/effects/Envelope.cpp
@@ -3,6 +3,11 @@
#include "Envelope.h"
void Envelope::initialize(AudioHost *host) {
+ this->host = host;
+ update();
+}
+
+void Envelope::update() {
attackIncrement = 1 / attack / host->sampleRate;
delayIncrement = 1 / delay / host->sampleRate;
releaseIncrement = 1 / release / host->sampleRate;
diff --git a/app/src/main/cpp/effects/Envelope.h b/app/src/main/cpp/effects/Envelope.h
index 7076f8f..dbb5575 100644
--- a/app/src/main/cpp/effects/Envelope.h
+++ b/app/src/main/cpp/effects/Envelope.h
@@ -16,15 +16,16 @@
EnvelopePhase phase;
float attackIncrement, delayIncrement, releaseIncrement;
float value = 0;
+ AudioHost *host;
public:
- float attack = 0.05, delay = 0.2, sustain = 0.75, release = 1;
+ float attack = 0.05, delay = 0.05, sustain = 0.7, release = 0.1;
void initialize(AudioHost *host);
+ void update();
+
void startNote();
-
void endNote();
-
void doRender(uint32_t sampleCount);
};
diff --git a/app/src/main/java/com/lukas/music/instruments/Envelope.kt b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
new file mode 100644
index 0000000..6603611
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.instruments
+
+class Envelope(val instrument: Instrument) {
+ var attack: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var delay: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var sustain: Int = 70
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var release: Int = 100
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+}
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3d886c4..66c49ef 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -11,6 +11,7 @@
+
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index 5505a35..d26ee2b 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -76,4 +76,20 @@
listSet(audioHost->instruments->begin(), id, nullptr);
delete getInstrument(id);
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_updateEnvelopeParameters(JNIEnv *env,
+ jobject thiz, jint id,
+ jfloat attack,
+ jfloat delay,
+ jfloat sustain,
+ jfloat release) {
+ Instrument *instrument = getInstrument((id));
+ Envelope *envelope = instrument->envelope;
+ envelope->attack = attack;
+ envelope->delay = delay;
+ envelope->sustain = sustain;
+ envelope->release = release;
+ envelope->update();
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Envelope.cpp b/app/src/main/cpp/effects/Envelope.cpp
index f8dfd61..5400548 100644
--- a/app/src/main/cpp/effects/Envelope.cpp
+++ b/app/src/main/cpp/effects/Envelope.cpp
@@ -3,6 +3,11 @@
#include "Envelope.h"
void Envelope::initialize(AudioHost *host) {
+ this->host = host;
+ update();
+}
+
+void Envelope::update() {
attackIncrement = 1 / attack / host->sampleRate;
delayIncrement = 1 / delay / host->sampleRate;
releaseIncrement = 1 / release / host->sampleRate;
diff --git a/app/src/main/cpp/effects/Envelope.h b/app/src/main/cpp/effects/Envelope.h
index 7076f8f..dbb5575 100644
--- a/app/src/main/cpp/effects/Envelope.h
+++ b/app/src/main/cpp/effects/Envelope.h
@@ -16,15 +16,16 @@
EnvelopePhase phase;
float attackIncrement, delayIncrement, releaseIncrement;
float value = 0;
+ AudioHost *host;
public:
- float attack = 0.05, delay = 0.2, sustain = 0.75, release = 1;
+ float attack = 0.05, delay = 0.05, sustain = 0.7, release = 0.1;
void initialize(AudioHost *host);
+ void update();
+
void startNote();
-
void endNote();
-
void doRender(uint32_t sampleCount);
};
diff --git a/app/src/main/java/com/lukas/music/instruments/Envelope.kt b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
new file mode 100644
index 0000000..6603611
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.instruments
+
+class Envelope(val instrument: Instrument) {
+ var attack: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var delay: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var sustain: Int = 70
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var release: Int = 100
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/Instrument.kt b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
index 92a896c..3013335 100644
--- a/app/src/main/java/com/lukas/music/instruments/Instrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
@@ -16,6 +16,7 @@
abstract class Instrument(var name: String) {
var voice: Voice = BassVoice(this)
+ var envelope = Envelope(this)
abstract var waveform: Waveform
abstract var volume: Float
abstract var muted: Boolean
@@ -24,6 +25,7 @@
abstract fun stop()
abstract fun stopNote(note: Note)
abstract fun destroy()
+ abstract fun updateEnvelope()
companion object {
val instruments = mutableListOf()
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3d886c4..66c49ef 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -11,6 +11,7 @@
+
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index 5505a35..d26ee2b 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -76,4 +76,20 @@
listSet(audioHost->instruments->begin(), id, nullptr);
delete getInstrument(id);
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_updateEnvelopeParameters(JNIEnv *env,
+ jobject thiz, jint id,
+ jfloat attack,
+ jfloat delay,
+ jfloat sustain,
+ jfloat release) {
+ Instrument *instrument = getInstrument((id));
+ Envelope *envelope = instrument->envelope;
+ envelope->attack = attack;
+ envelope->delay = delay;
+ envelope->sustain = sustain;
+ envelope->release = release;
+ envelope->update();
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Envelope.cpp b/app/src/main/cpp/effects/Envelope.cpp
index f8dfd61..5400548 100644
--- a/app/src/main/cpp/effects/Envelope.cpp
+++ b/app/src/main/cpp/effects/Envelope.cpp
@@ -3,6 +3,11 @@
#include "Envelope.h"
void Envelope::initialize(AudioHost *host) {
+ this->host = host;
+ update();
+}
+
+void Envelope::update() {
attackIncrement = 1 / attack / host->sampleRate;
delayIncrement = 1 / delay / host->sampleRate;
releaseIncrement = 1 / release / host->sampleRate;
diff --git a/app/src/main/cpp/effects/Envelope.h b/app/src/main/cpp/effects/Envelope.h
index 7076f8f..dbb5575 100644
--- a/app/src/main/cpp/effects/Envelope.h
+++ b/app/src/main/cpp/effects/Envelope.h
@@ -16,15 +16,16 @@
EnvelopePhase phase;
float attackIncrement, delayIncrement, releaseIncrement;
float value = 0;
+ AudioHost *host;
public:
- float attack = 0.05, delay = 0.2, sustain = 0.75, release = 1;
+ float attack = 0.05, delay = 0.05, sustain = 0.7, release = 0.1;
void initialize(AudioHost *host);
+ void update();
+
void startNote();
-
void endNote();
-
void doRender(uint32_t sampleCount);
};
diff --git a/app/src/main/java/com/lukas/music/instruments/Envelope.kt b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
new file mode 100644
index 0000000..6603611
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.instruments
+
+class Envelope(val instrument: Instrument) {
+ var attack: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var delay: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var sustain: Int = 70
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var release: Int = 100
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/Instrument.kt b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
index 92a896c..3013335 100644
--- a/app/src/main/java/com/lukas/music/instruments/Instrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
@@ -16,6 +16,7 @@
abstract class Instrument(var name: String) {
var voice: Voice = BassVoice(this)
+ var envelope = Envelope(this)
abstract var waveform: Waveform
abstract var volume: Float
abstract var muted: Boolean
@@ -24,6 +25,7 @@
abstract fun stop()
abstract fun stopNote(note: Note)
abstract fun destroy()
+ abstract fun updateEnvelope()
companion object {
val instruments = mutableListOf()
diff --git a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
index b4c68a4..946e653 100644
--- a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
@@ -13,7 +13,7 @@
import com.lukas.music.song.note.Note
class InternalInstrument {
- private val id = createInstrument()
+ val id = createInstrument()
var note: Note? = null
var waveform: Waveform = Waveform.SINE
@@ -67,10 +67,27 @@
destroy(id)
}
+ fun applyEnvelope(envelope: Envelope) {
+ updateEnvelopeParameters(
+ id,
+ envelope.attack.toFloat() / 1000f,
+ envelope.delay.toFloat() / 1000f,
+ envelope.sustain.toFloat() / 100f,
+ envelope.release.toFloat() / 1000f,
+ )
+ }
+
private external fun createInstrument(): Int
private external fun setInstrumentWaveform(id: Int, waveform: Int)
private external fun startNote(id: Int, frequency: Double)
private external fun endNote(id: Int)
private external fun setVolume(id: Int, volume: Float)
private external fun destroy(id: Int)
+ private external fun updateEnvelopeParameters(
+ id: Int,
+ attack: Float,
+ delay: Float,
+ sustain: Float,
+ release: Float
+ )
}
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3d886c4..66c49ef 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -11,6 +11,7 @@
+
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index 5505a35..d26ee2b 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -76,4 +76,20 @@
listSet(audioHost->instruments->begin(), id, nullptr);
delete getInstrument(id);
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_updateEnvelopeParameters(JNIEnv *env,
+ jobject thiz, jint id,
+ jfloat attack,
+ jfloat delay,
+ jfloat sustain,
+ jfloat release) {
+ Instrument *instrument = getInstrument((id));
+ Envelope *envelope = instrument->envelope;
+ envelope->attack = attack;
+ envelope->delay = delay;
+ envelope->sustain = sustain;
+ envelope->release = release;
+ envelope->update();
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Envelope.cpp b/app/src/main/cpp/effects/Envelope.cpp
index f8dfd61..5400548 100644
--- a/app/src/main/cpp/effects/Envelope.cpp
+++ b/app/src/main/cpp/effects/Envelope.cpp
@@ -3,6 +3,11 @@
#include "Envelope.h"
void Envelope::initialize(AudioHost *host) {
+ this->host = host;
+ update();
+}
+
+void Envelope::update() {
attackIncrement = 1 / attack / host->sampleRate;
delayIncrement = 1 / delay / host->sampleRate;
releaseIncrement = 1 / release / host->sampleRate;
diff --git a/app/src/main/cpp/effects/Envelope.h b/app/src/main/cpp/effects/Envelope.h
index 7076f8f..dbb5575 100644
--- a/app/src/main/cpp/effects/Envelope.h
+++ b/app/src/main/cpp/effects/Envelope.h
@@ -16,15 +16,16 @@
EnvelopePhase phase;
float attackIncrement, delayIncrement, releaseIncrement;
float value = 0;
+ AudioHost *host;
public:
- float attack = 0.05, delay = 0.2, sustain = 0.75, release = 1;
+ float attack = 0.05, delay = 0.05, sustain = 0.7, release = 0.1;
void initialize(AudioHost *host);
+ void update();
+
void startNote();
-
void endNote();
-
void doRender(uint32_t sampleCount);
};
diff --git a/app/src/main/java/com/lukas/music/instruments/Envelope.kt b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
new file mode 100644
index 0000000..6603611
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.instruments
+
+class Envelope(val instrument: Instrument) {
+ var attack: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var delay: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var sustain: Int = 70
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var release: Int = 100
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/Instrument.kt b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
index 92a896c..3013335 100644
--- a/app/src/main/java/com/lukas/music/instruments/Instrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
@@ -16,6 +16,7 @@
abstract class Instrument(var name: String) {
var voice: Voice = BassVoice(this)
+ var envelope = Envelope(this)
abstract var waveform: Waveform
abstract var volume: Float
abstract var muted: Boolean
@@ -24,6 +25,7 @@
abstract fun stop()
abstract fun stopNote(note: Note)
abstract fun destroy()
+ abstract fun updateEnvelope()
companion object {
val instruments = mutableListOf()
diff --git a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
index b4c68a4..946e653 100644
--- a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
@@ -13,7 +13,7 @@
import com.lukas.music.song.note.Note
class InternalInstrument {
- private val id = createInstrument()
+ val id = createInstrument()
var note: Note? = null
var waveform: Waveform = Waveform.SINE
@@ -67,10 +67,27 @@
destroy(id)
}
+ fun applyEnvelope(envelope: Envelope) {
+ updateEnvelopeParameters(
+ id,
+ envelope.attack.toFloat() / 1000f,
+ envelope.delay.toFloat() / 1000f,
+ envelope.sustain.toFloat() / 100f,
+ envelope.release.toFloat() / 1000f,
+ )
+ }
+
private external fun createInstrument(): Int
private external fun setInstrumentWaveform(id: Int, waveform: Int)
private external fun startNote(id: Int, frequency: Double)
private external fun endNote(id: Int)
private external fun setVolume(id: Int, volume: Float)
private external fun destroy(id: Int)
+ private external fun updateEnvelopeParameters(
+ id: Int,
+ attack: Float,
+ delay: Float,
+ sustain: Float,
+ release: Float
+ )
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
index 2b43524..a9b5c53 100644
--- a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
@@ -53,4 +53,8 @@
override fun destroy() {
internalInstrument.destroy()
}
+
+ override fun updateEnvelope() {
+ internalInstrument.applyEnvelope(envelope)
+ }
}
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3d886c4..66c49ef 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -11,6 +11,7 @@
+
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index 5505a35..d26ee2b 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -76,4 +76,20 @@
listSet(audioHost->instruments->begin(), id, nullptr);
delete getInstrument(id);
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_updateEnvelopeParameters(JNIEnv *env,
+ jobject thiz, jint id,
+ jfloat attack,
+ jfloat delay,
+ jfloat sustain,
+ jfloat release) {
+ Instrument *instrument = getInstrument((id));
+ Envelope *envelope = instrument->envelope;
+ envelope->attack = attack;
+ envelope->delay = delay;
+ envelope->sustain = sustain;
+ envelope->release = release;
+ envelope->update();
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Envelope.cpp b/app/src/main/cpp/effects/Envelope.cpp
index f8dfd61..5400548 100644
--- a/app/src/main/cpp/effects/Envelope.cpp
+++ b/app/src/main/cpp/effects/Envelope.cpp
@@ -3,6 +3,11 @@
#include "Envelope.h"
void Envelope::initialize(AudioHost *host) {
+ this->host = host;
+ update();
+}
+
+void Envelope::update() {
attackIncrement = 1 / attack / host->sampleRate;
delayIncrement = 1 / delay / host->sampleRate;
releaseIncrement = 1 / release / host->sampleRate;
diff --git a/app/src/main/cpp/effects/Envelope.h b/app/src/main/cpp/effects/Envelope.h
index 7076f8f..dbb5575 100644
--- a/app/src/main/cpp/effects/Envelope.h
+++ b/app/src/main/cpp/effects/Envelope.h
@@ -16,15 +16,16 @@
EnvelopePhase phase;
float attackIncrement, delayIncrement, releaseIncrement;
float value = 0;
+ AudioHost *host;
public:
- float attack = 0.05, delay = 0.2, sustain = 0.75, release = 1;
+ float attack = 0.05, delay = 0.05, sustain = 0.7, release = 0.1;
void initialize(AudioHost *host);
+ void update();
+
void startNote();
-
void endNote();
-
void doRender(uint32_t sampleCount);
};
diff --git a/app/src/main/java/com/lukas/music/instruments/Envelope.kt b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
new file mode 100644
index 0000000..6603611
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.instruments
+
+class Envelope(val instrument: Instrument) {
+ var attack: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var delay: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var sustain: Int = 70
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var release: Int = 100
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/Instrument.kt b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
index 92a896c..3013335 100644
--- a/app/src/main/java/com/lukas/music/instruments/Instrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
@@ -16,6 +16,7 @@
abstract class Instrument(var name: String) {
var voice: Voice = BassVoice(this)
+ var envelope = Envelope(this)
abstract var waveform: Waveform
abstract var volume: Float
abstract var muted: Boolean
@@ -24,6 +25,7 @@
abstract fun stop()
abstract fun stopNote(note: Note)
abstract fun destroy()
+ abstract fun updateEnvelope()
companion object {
val instruments = mutableListOf()
diff --git a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
index b4c68a4..946e653 100644
--- a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
@@ -13,7 +13,7 @@
import com.lukas.music.song.note.Note
class InternalInstrument {
- private val id = createInstrument()
+ val id = createInstrument()
var note: Note? = null
var waveform: Waveform = Waveform.SINE
@@ -67,10 +67,27 @@
destroy(id)
}
+ fun applyEnvelope(envelope: Envelope) {
+ updateEnvelopeParameters(
+ id,
+ envelope.attack.toFloat() / 1000f,
+ envelope.delay.toFloat() / 1000f,
+ envelope.sustain.toFloat() / 100f,
+ envelope.release.toFloat() / 1000f,
+ )
+ }
+
private external fun createInstrument(): Int
private external fun setInstrumentWaveform(id: Int, waveform: Int)
private external fun startNote(id: Int, frequency: Double)
private external fun endNote(id: Int)
private external fun setVolume(id: Int, volume: Float)
private external fun destroy(id: Int)
+ private external fun updateEnvelopeParameters(
+ id: Int,
+ attack: Float,
+ delay: Float,
+ sustain: Float,
+ release: Float
+ )
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
index 2b43524..a9b5c53 100644
--- a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
@@ -53,4 +53,8 @@
override fun destroy() {
internalInstrument.destroy()
}
+
+ override fun updateEnvelope() {
+ internalInstrument.applyEnvelope(envelope)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
index 26e4fbb..8f055d0 100644
--- a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
@@ -75,4 +75,10 @@
instrument.destroy()
}
}
+
+ override fun updateEnvelope() {
+ for (instrument in internalInstruments) {
+ instrument.applyEnvelope(envelope)
+ }
+ }
}
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3d886c4..66c49ef 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -11,6 +11,7 @@
+
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index 5505a35..d26ee2b 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -76,4 +76,20 @@
listSet(audioHost->instruments->begin(), id, nullptr);
delete getInstrument(id);
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_updateEnvelopeParameters(JNIEnv *env,
+ jobject thiz, jint id,
+ jfloat attack,
+ jfloat delay,
+ jfloat sustain,
+ jfloat release) {
+ Instrument *instrument = getInstrument((id));
+ Envelope *envelope = instrument->envelope;
+ envelope->attack = attack;
+ envelope->delay = delay;
+ envelope->sustain = sustain;
+ envelope->release = release;
+ envelope->update();
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Envelope.cpp b/app/src/main/cpp/effects/Envelope.cpp
index f8dfd61..5400548 100644
--- a/app/src/main/cpp/effects/Envelope.cpp
+++ b/app/src/main/cpp/effects/Envelope.cpp
@@ -3,6 +3,11 @@
#include "Envelope.h"
void Envelope::initialize(AudioHost *host) {
+ this->host = host;
+ update();
+}
+
+void Envelope::update() {
attackIncrement = 1 / attack / host->sampleRate;
delayIncrement = 1 / delay / host->sampleRate;
releaseIncrement = 1 / release / host->sampleRate;
diff --git a/app/src/main/cpp/effects/Envelope.h b/app/src/main/cpp/effects/Envelope.h
index 7076f8f..dbb5575 100644
--- a/app/src/main/cpp/effects/Envelope.h
+++ b/app/src/main/cpp/effects/Envelope.h
@@ -16,15 +16,16 @@
EnvelopePhase phase;
float attackIncrement, delayIncrement, releaseIncrement;
float value = 0;
+ AudioHost *host;
public:
- float attack = 0.05, delay = 0.2, sustain = 0.75, release = 1;
+ float attack = 0.05, delay = 0.05, sustain = 0.7, release = 0.1;
void initialize(AudioHost *host);
+ void update();
+
void startNote();
-
void endNote();
-
void doRender(uint32_t sampleCount);
};
diff --git a/app/src/main/java/com/lukas/music/instruments/Envelope.kt b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
new file mode 100644
index 0000000..6603611
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.instruments
+
+class Envelope(val instrument: Instrument) {
+ var attack: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var delay: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var sustain: Int = 70
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var release: Int = 100
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/Instrument.kt b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
index 92a896c..3013335 100644
--- a/app/src/main/java/com/lukas/music/instruments/Instrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
@@ -16,6 +16,7 @@
abstract class Instrument(var name: String) {
var voice: Voice = BassVoice(this)
+ var envelope = Envelope(this)
abstract var waveform: Waveform
abstract var volume: Float
abstract var muted: Boolean
@@ -24,6 +25,7 @@
abstract fun stop()
abstract fun stopNote(note: Note)
abstract fun destroy()
+ abstract fun updateEnvelope()
companion object {
val instruments = mutableListOf()
diff --git a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
index b4c68a4..946e653 100644
--- a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
@@ -13,7 +13,7 @@
import com.lukas.music.song.note.Note
class InternalInstrument {
- private val id = createInstrument()
+ val id = createInstrument()
var note: Note? = null
var waveform: Waveform = Waveform.SINE
@@ -67,10 +67,27 @@
destroy(id)
}
+ fun applyEnvelope(envelope: Envelope) {
+ updateEnvelopeParameters(
+ id,
+ envelope.attack.toFloat() / 1000f,
+ envelope.delay.toFloat() / 1000f,
+ envelope.sustain.toFloat() / 100f,
+ envelope.release.toFloat() / 1000f,
+ )
+ }
+
private external fun createInstrument(): Int
private external fun setInstrumentWaveform(id: Int, waveform: Int)
private external fun startNote(id: Int, frequency: Double)
private external fun endNote(id: Int)
private external fun setVolume(id: Int, volume: Float)
private external fun destroy(id: Int)
+ private external fun updateEnvelopeParameters(
+ id: Int,
+ attack: Float,
+ delay: Float,
+ sustain: Float,
+ release: Float
+ )
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
index 2b43524..a9b5c53 100644
--- a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
@@ -53,4 +53,8 @@
override fun destroy() {
internalInstrument.destroy()
}
+
+ override fun updateEnvelope() {
+ internalInstrument.applyEnvelope(envelope)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
index 26e4fbb..8f055d0 100644
--- a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
@@ -75,4 +75,10 @@
instrument.destroy()
}
}
+
+ override fun updateEnvelope() {
+ for (instrument in internalInstruments) {
+ instrument.applyEnvelope(envelope)
+ }
+ }
}
\ 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
index bd7a3d9..f01d9e4 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
@@ -23,7 +23,7 @@
import com.lukas.music.song.chords.Interval
import com.lukas.music.util.setup
-class EditChordFragment(val chord: Chord, private val songFragment: SongFragment) :
+class EditChordFragment(private val chord: Chord, private val songFragment: SongFragment) :
DialogFragment() {
lateinit var binding: FragmentEditChordBinding
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3d886c4..66c49ef 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -11,6 +11,7 @@
+
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index 5505a35..d26ee2b 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -76,4 +76,20 @@
listSet(audioHost->instruments->begin(), id, nullptr);
delete getInstrument(id);
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_updateEnvelopeParameters(JNIEnv *env,
+ jobject thiz, jint id,
+ jfloat attack,
+ jfloat delay,
+ jfloat sustain,
+ jfloat release) {
+ Instrument *instrument = getInstrument((id));
+ Envelope *envelope = instrument->envelope;
+ envelope->attack = attack;
+ envelope->delay = delay;
+ envelope->sustain = sustain;
+ envelope->release = release;
+ envelope->update();
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Envelope.cpp b/app/src/main/cpp/effects/Envelope.cpp
index f8dfd61..5400548 100644
--- a/app/src/main/cpp/effects/Envelope.cpp
+++ b/app/src/main/cpp/effects/Envelope.cpp
@@ -3,6 +3,11 @@
#include "Envelope.h"
void Envelope::initialize(AudioHost *host) {
+ this->host = host;
+ update();
+}
+
+void Envelope::update() {
attackIncrement = 1 / attack / host->sampleRate;
delayIncrement = 1 / delay / host->sampleRate;
releaseIncrement = 1 / release / host->sampleRate;
diff --git a/app/src/main/cpp/effects/Envelope.h b/app/src/main/cpp/effects/Envelope.h
index 7076f8f..dbb5575 100644
--- a/app/src/main/cpp/effects/Envelope.h
+++ b/app/src/main/cpp/effects/Envelope.h
@@ -16,15 +16,16 @@
EnvelopePhase phase;
float attackIncrement, delayIncrement, releaseIncrement;
float value = 0;
+ AudioHost *host;
public:
- float attack = 0.05, delay = 0.2, sustain = 0.75, release = 1;
+ float attack = 0.05, delay = 0.05, sustain = 0.7, release = 0.1;
void initialize(AudioHost *host);
+ void update();
+
void startNote();
-
void endNote();
-
void doRender(uint32_t sampleCount);
};
diff --git a/app/src/main/java/com/lukas/music/instruments/Envelope.kt b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
new file mode 100644
index 0000000..6603611
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.instruments
+
+class Envelope(val instrument: Instrument) {
+ var attack: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var delay: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var sustain: Int = 70
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var release: Int = 100
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/Instrument.kt b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
index 92a896c..3013335 100644
--- a/app/src/main/java/com/lukas/music/instruments/Instrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
@@ -16,6 +16,7 @@
abstract class Instrument(var name: String) {
var voice: Voice = BassVoice(this)
+ var envelope = Envelope(this)
abstract var waveform: Waveform
abstract var volume: Float
abstract var muted: Boolean
@@ -24,6 +25,7 @@
abstract fun stop()
abstract fun stopNote(note: Note)
abstract fun destroy()
+ abstract fun updateEnvelope()
companion object {
val instruments = mutableListOf()
diff --git a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
index b4c68a4..946e653 100644
--- a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
@@ -13,7 +13,7 @@
import com.lukas.music.song.note.Note
class InternalInstrument {
- private val id = createInstrument()
+ val id = createInstrument()
var note: Note? = null
var waveform: Waveform = Waveform.SINE
@@ -67,10 +67,27 @@
destroy(id)
}
+ fun applyEnvelope(envelope: Envelope) {
+ updateEnvelopeParameters(
+ id,
+ envelope.attack.toFloat() / 1000f,
+ envelope.delay.toFloat() / 1000f,
+ envelope.sustain.toFloat() / 100f,
+ envelope.release.toFloat() / 1000f,
+ )
+ }
+
private external fun createInstrument(): Int
private external fun setInstrumentWaveform(id: Int, waveform: Int)
private external fun startNote(id: Int, frequency: Double)
private external fun endNote(id: Int)
private external fun setVolume(id: Int, volume: Float)
private external fun destroy(id: Int)
+ private external fun updateEnvelopeParameters(
+ id: Int,
+ attack: Float,
+ delay: Float,
+ sustain: Float,
+ release: Float
+ )
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
index 2b43524..a9b5c53 100644
--- a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
@@ -53,4 +53,8 @@
override fun destroy() {
internalInstrument.destroy()
}
+
+ override fun updateEnvelope() {
+ internalInstrument.applyEnvelope(envelope)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
index 26e4fbb..8f055d0 100644
--- a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
@@ -75,4 +75,10 @@
instrument.destroy()
}
}
+
+ override fun updateEnvelope() {
+ for (instrument in internalInstruments) {
+ instrument.applyEnvelope(envelope)
+ }
+ }
}
\ 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
index bd7a3d9..f01d9e4 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
@@ -23,7 +23,7 @@
import com.lukas.music.song.chords.Interval
import com.lukas.music.util.setup
-class EditChordFragment(val chord: Chord, private val songFragment: SongFragment) :
+class EditChordFragment(private val chord: Chord, private val songFragment: SongFragment) :
DialogFragment() {
lateinit var binding: FragmentEditChordBinding
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/EditEnvelopeFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/EditEnvelopeFragment.kt
new file mode 100644
index 0000000..ea6a855
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditEnvelopeFragment.kt
@@ -0,0 +1,55 @@
+/*
+ * 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 androidx.fragment.app.DialogFragment
+import com.lukas.music.databinding.FragmentEditEnvelopeBinding
+import com.lukas.music.instruments.Envelope
+import com.lukas.music.util.smartSetup
+
+class EditEnvelopeFragment(private val envelope: Envelope) : DialogFragment() {
+ lateinit var binding: FragmentEditEnvelopeBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentEditEnvelopeBinding.inflate(inflater)
+ binding.attackSeek.smartSetup(5, 200, envelope::attack) {
+ binding.attackText.text = "Attack: $it ms"
+ }
+ binding.delaySeek.smartSetup(5, 200, envelope::delay) {
+ binding.delayText.text = "Delay: $it ms"
+ }
+ binding.sustainSeek.smartSetup(0, 100, envelope::sustain) {
+ binding.sustainText.text = "Sustain: $it%"
+ }
+ binding.releaseSeek.smartSetup(5, 200, envelope::release) {
+ binding.releaseText.text = "Release: $it ms"
+ }
+ binding.closeButton.setOnClickListener {
+ dismiss()
+ }
+ return binding.root
+ }
+
+ override fun onStart() {
+ super.onStart()
+ dialog?.window?.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+}
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3d886c4..66c49ef 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -11,6 +11,7 @@
+
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index 5505a35..d26ee2b 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -76,4 +76,20 @@
listSet(audioHost->instruments->begin(), id, nullptr);
delete getInstrument(id);
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_updateEnvelopeParameters(JNIEnv *env,
+ jobject thiz, jint id,
+ jfloat attack,
+ jfloat delay,
+ jfloat sustain,
+ jfloat release) {
+ Instrument *instrument = getInstrument((id));
+ Envelope *envelope = instrument->envelope;
+ envelope->attack = attack;
+ envelope->delay = delay;
+ envelope->sustain = sustain;
+ envelope->release = release;
+ envelope->update();
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Envelope.cpp b/app/src/main/cpp/effects/Envelope.cpp
index f8dfd61..5400548 100644
--- a/app/src/main/cpp/effects/Envelope.cpp
+++ b/app/src/main/cpp/effects/Envelope.cpp
@@ -3,6 +3,11 @@
#include "Envelope.h"
void Envelope::initialize(AudioHost *host) {
+ this->host = host;
+ update();
+}
+
+void Envelope::update() {
attackIncrement = 1 / attack / host->sampleRate;
delayIncrement = 1 / delay / host->sampleRate;
releaseIncrement = 1 / release / host->sampleRate;
diff --git a/app/src/main/cpp/effects/Envelope.h b/app/src/main/cpp/effects/Envelope.h
index 7076f8f..dbb5575 100644
--- a/app/src/main/cpp/effects/Envelope.h
+++ b/app/src/main/cpp/effects/Envelope.h
@@ -16,15 +16,16 @@
EnvelopePhase phase;
float attackIncrement, delayIncrement, releaseIncrement;
float value = 0;
+ AudioHost *host;
public:
- float attack = 0.05, delay = 0.2, sustain = 0.75, release = 1;
+ float attack = 0.05, delay = 0.05, sustain = 0.7, release = 0.1;
void initialize(AudioHost *host);
+ void update();
+
void startNote();
-
void endNote();
-
void doRender(uint32_t sampleCount);
};
diff --git a/app/src/main/java/com/lukas/music/instruments/Envelope.kt b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
new file mode 100644
index 0000000..6603611
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.instruments
+
+class Envelope(val instrument: Instrument) {
+ var attack: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var delay: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var sustain: Int = 70
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var release: Int = 100
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/Instrument.kt b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
index 92a896c..3013335 100644
--- a/app/src/main/java/com/lukas/music/instruments/Instrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
@@ -16,6 +16,7 @@
abstract class Instrument(var name: String) {
var voice: Voice = BassVoice(this)
+ var envelope = Envelope(this)
abstract var waveform: Waveform
abstract var volume: Float
abstract var muted: Boolean
@@ -24,6 +25,7 @@
abstract fun stop()
abstract fun stopNote(note: Note)
abstract fun destroy()
+ abstract fun updateEnvelope()
companion object {
val instruments = mutableListOf()
diff --git a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
index b4c68a4..946e653 100644
--- a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
@@ -13,7 +13,7 @@
import com.lukas.music.song.note.Note
class InternalInstrument {
- private val id = createInstrument()
+ val id = createInstrument()
var note: Note? = null
var waveform: Waveform = Waveform.SINE
@@ -67,10 +67,27 @@
destroy(id)
}
+ fun applyEnvelope(envelope: Envelope) {
+ updateEnvelopeParameters(
+ id,
+ envelope.attack.toFloat() / 1000f,
+ envelope.delay.toFloat() / 1000f,
+ envelope.sustain.toFloat() / 100f,
+ envelope.release.toFloat() / 1000f,
+ )
+ }
+
private external fun createInstrument(): Int
private external fun setInstrumentWaveform(id: Int, waveform: Int)
private external fun startNote(id: Int, frequency: Double)
private external fun endNote(id: Int)
private external fun setVolume(id: Int, volume: Float)
private external fun destroy(id: Int)
+ private external fun updateEnvelopeParameters(
+ id: Int,
+ attack: Float,
+ delay: Float,
+ sustain: Float,
+ release: Float
+ )
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
index 2b43524..a9b5c53 100644
--- a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
@@ -53,4 +53,8 @@
override fun destroy() {
internalInstrument.destroy()
}
+
+ override fun updateEnvelope() {
+ internalInstrument.applyEnvelope(envelope)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
index 26e4fbb..8f055d0 100644
--- a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
@@ -75,4 +75,10 @@
instrument.destroy()
}
}
+
+ override fun updateEnvelope() {
+ for (instrument in internalInstruments) {
+ instrument.applyEnvelope(envelope)
+ }
+ }
}
\ 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
index bd7a3d9..f01d9e4 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
@@ -23,7 +23,7 @@
import com.lukas.music.song.chords.Interval
import com.lukas.music.util.setup
-class EditChordFragment(val chord: Chord, private val songFragment: SongFragment) :
+class EditChordFragment(private val chord: Chord, private val songFragment: SongFragment) :
DialogFragment() {
lateinit var binding: FragmentEditChordBinding
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/EditEnvelopeFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/EditEnvelopeFragment.kt
new file mode 100644
index 0000000..ea6a855
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditEnvelopeFragment.kt
@@ -0,0 +1,55 @@
+/*
+ * 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 androidx.fragment.app.DialogFragment
+import com.lukas.music.databinding.FragmentEditEnvelopeBinding
+import com.lukas.music.instruments.Envelope
+import com.lukas.music.util.smartSetup
+
+class EditEnvelopeFragment(private val envelope: Envelope) : DialogFragment() {
+ lateinit var binding: FragmentEditEnvelopeBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentEditEnvelopeBinding.inflate(inflater)
+ binding.attackSeek.smartSetup(5, 200, envelope::attack) {
+ binding.attackText.text = "Attack: $it ms"
+ }
+ binding.delaySeek.smartSetup(5, 200, envelope::delay) {
+ binding.delayText.text = "Delay: $it ms"
+ }
+ binding.sustainSeek.smartSetup(0, 100, envelope::sustain) {
+ binding.sustainText.text = "Sustain: $it%"
+ }
+ binding.releaseSeek.smartSetup(5, 200, envelope::release) {
+ binding.releaseText.text = "Release: $it ms"
+ }
+ binding.closeButton.setOnClickListener {
+ dismiss()
+ }
+ return binding.root
+ }
+
+ override fun onStart() {
+ super.onStart()
+ dialog?.window?.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+}
\ No newline at end of file
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 9c76f59..45d84b9 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
@@ -64,6 +64,9 @@
binding.editVoiceButton.setOnClickListener {
EditVoiceFragment(instrument.voice).showNow(childFragmentManager, "")
}
+ binding.editEnvelopeButton.setOnClickListener {
+ EditEnvelopeFragment(instrument.envelope).showNow(childFragmentManager, "")
+ }
binding.closeButton.setOnClickListener {
dismiss()
}
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3d886c4..66c49ef 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -11,6 +11,7 @@
+
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index 5505a35..d26ee2b 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -76,4 +76,20 @@
listSet(audioHost->instruments->begin(), id, nullptr);
delete getInstrument(id);
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_updateEnvelopeParameters(JNIEnv *env,
+ jobject thiz, jint id,
+ jfloat attack,
+ jfloat delay,
+ jfloat sustain,
+ jfloat release) {
+ Instrument *instrument = getInstrument((id));
+ Envelope *envelope = instrument->envelope;
+ envelope->attack = attack;
+ envelope->delay = delay;
+ envelope->sustain = sustain;
+ envelope->release = release;
+ envelope->update();
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Envelope.cpp b/app/src/main/cpp/effects/Envelope.cpp
index f8dfd61..5400548 100644
--- a/app/src/main/cpp/effects/Envelope.cpp
+++ b/app/src/main/cpp/effects/Envelope.cpp
@@ -3,6 +3,11 @@
#include "Envelope.h"
void Envelope::initialize(AudioHost *host) {
+ this->host = host;
+ update();
+}
+
+void Envelope::update() {
attackIncrement = 1 / attack / host->sampleRate;
delayIncrement = 1 / delay / host->sampleRate;
releaseIncrement = 1 / release / host->sampleRate;
diff --git a/app/src/main/cpp/effects/Envelope.h b/app/src/main/cpp/effects/Envelope.h
index 7076f8f..dbb5575 100644
--- a/app/src/main/cpp/effects/Envelope.h
+++ b/app/src/main/cpp/effects/Envelope.h
@@ -16,15 +16,16 @@
EnvelopePhase phase;
float attackIncrement, delayIncrement, releaseIncrement;
float value = 0;
+ AudioHost *host;
public:
- float attack = 0.05, delay = 0.2, sustain = 0.75, release = 1;
+ float attack = 0.05, delay = 0.05, sustain = 0.7, release = 0.1;
void initialize(AudioHost *host);
+ void update();
+
void startNote();
-
void endNote();
-
void doRender(uint32_t sampleCount);
};
diff --git a/app/src/main/java/com/lukas/music/instruments/Envelope.kt b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
new file mode 100644
index 0000000..6603611
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.instruments
+
+class Envelope(val instrument: Instrument) {
+ var attack: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var delay: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var sustain: Int = 70
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var release: Int = 100
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/Instrument.kt b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
index 92a896c..3013335 100644
--- a/app/src/main/java/com/lukas/music/instruments/Instrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
@@ -16,6 +16,7 @@
abstract class Instrument(var name: String) {
var voice: Voice = BassVoice(this)
+ var envelope = Envelope(this)
abstract var waveform: Waveform
abstract var volume: Float
abstract var muted: Boolean
@@ -24,6 +25,7 @@
abstract fun stop()
abstract fun stopNote(note: Note)
abstract fun destroy()
+ abstract fun updateEnvelope()
companion object {
val instruments = mutableListOf()
diff --git a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
index b4c68a4..946e653 100644
--- a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
@@ -13,7 +13,7 @@
import com.lukas.music.song.note.Note
class InternalInstrument {
- private val id = createInstrument()
+ val id = createInstrument()
var note: Note? = null
var waveform: Waveform = Waveform.SINE
@@ -67,10 +67,27 @@
destroy(id)
}
+ fun applyEnvelope(envelope: Envelope) {
+ updateEnvelopeParameters(
+ id,
+ envelope.attack.toFloat() / 1000f,
+ envelope.delay.toFloat() / 1000f,
+ envelope.sustain.toFloat() / 100f,
+ envelope.release.toFloat() / 1000f,
+ )
+ }
+
private external fun createInstrument(): Int
private external fun setInstrumentWaveform(id: Int, waveform: Int)
private external fun startNote(id: Int, frequency: Double)
private external fun endNote(id: Int)
private external fun setVolume(id: Int, volume: Float)
private external fun destroy(id: Int)
+ private external fun updateEnvelopeParameters(
+ id: Int,
+ attack: Float,
+ delay: Float,
+ sustain: Float,
+ release: Float
+ )
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
index 2b43524..a9b5c53 100644
--- a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
@@ -53,4 +53,8 @@
override fun destroy() {
internalInstrument.destroy()
}
+
+ override fun updateEnvelope() {
+ internalInstrument.applyEnvelope(envelope)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
index 26e4fbb..8f055d0 100644
--- a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
@@ -75,4 +75,10 @@
instrument.destroy()
}
}
+
+ override fun updateEnvelope() {
+ for (instrument in internalInstruments) {
+ instrument.applyEnvelope(envelope)
+ }
+ }
}
\ 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
index bd7a3d9..f01d9e4 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
@@ -23,7 +23,7 @@
import com.lukas.music.song.chords.Interval
import com.lukas.music.util.setup
-class EditChordFragment(val chord: Chord, private val songFragment: SongFragment) :
+class EditChordFragment(private val chord: Chord, private val songFragment: SongFragment) :
DialogFragment() {
lateinit var binding: FragmentEditChordBinding
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/EditEnvelopeFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/EditEnvelopeFragment.kt
new file mode 100644
index 0000000..ea6a855
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditEnvelopeFragment.kt
@@ -0,0 +1,55 @@
+/*
+ * 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 androidx.fragment.app.DialogFragment
+import com.lukas.music.databinding.FragmentEditEnvelopeBinding
+import com.lukas.music.instruments.Envelope
+import com.lukas.music.util.smartSetup
+
+class EditEnvelopeFragment(private val envelope: Envelope) : DialogFragment() {
+ lateinit var binding: FragmentEditEnvelopeBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentEditEnvelopeBinding.inflate(inflater)
+ binding.attackSeek.smartSetup(5, 200, envelope::attack) {
+ binding.attackText.text = "Attack: $it ms"
+ }
+ binding.delaySeek.smartSetup(5, 200, envelope::delay) {
+ binding.delayText.text = "Delay: $it ms"
+ }
+ binding.sustainSeek.smartSetup(0, 100, envelope::sustain) {
+ binding.sustainText.text = "Sustain: $it%"
+ }
+ binding.releaseSeek.smartSetup(5, 200, envelope::release) {
+ binding.releaseText.text = "Release: $it ms"
+ }
+ binding.closeButton.setOnClickListener {
+ dismiss()
+ }
+ return binding.root
+ }
+
+ override fun onStart() {
+ super.onStart()
+ dialog?.window?.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+}
\ No newline at end of file
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 9c76f59..45d84b9 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
@@ -64,6 +64,9 @@
binding.editVoiceButton.setOnClickListener {
EditVoiceFragment(instrument.voice).showNow(childFragmentManager, "")
}
+ binding.editEnvelopeButton.setOnClickListener {
+ EditEnvelopeFragment(instrument.envelope).showNow(childFragmentManager, "")
+ }
binding.closeButton.setOnClickListener {
dismiss()
}
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 e7ba28f..9e2c520 100644
--- a/app/src/main/java/com/lukas/music/util/UIUtil.kt
+++ b/app/src/main/java/com/lukas/music/util/UIUtil.kt
@@ -39,6 +39,18 @@
this.progress = initialProgress
}
+fun SeekBar.smartSetup(
+ min: Int,
+ max: Int,
+ target: KMutableProperty0,
+ callback: (Int) -> Unit
+) {
+ setup(min, max, target.get()) {
+ target.set(it)
+ callback(it)
+ }
+}
+
fun Button.setupToggle(
target: KMutableProperty0,
activeColor: Int,
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3d886c4..66c49ef 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -11,6 +11,7 @@
+
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index 5505a35..d26ee2b 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -76,4 +76,20 @@
listSet(audioHost->instruments->begin(), id, nullptr);
delete getInstrument(id);
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_updateEnvelopeParameters(JNIEnv *env,
+ jobject thiz, jint id,
+ jfloat attack,
+ jfloat delay,
+ jfloat sustain,
+ jfloat release) {
+ Instrument *instrument = getInstrument((id));
+ Envelope *envelope = instrument->envelope;
+ envelope->attack = attack;
+ envelope->delay = delay;
+ envelope->sustain = sustain;
+ envelope->release = release;
+ envelope->update();
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Envelope.cpp b/app/src/main/cpp/effects/Envelope.cpp
index f8dfd61..5400548 100644
--- a/app/src/main/cpp/effects/Envelope.cpp
+++ b/app/src/main/cpp/effects/Envelope.cpp
@@ -3,6 +3,11 @@
#include "Envelope.h"
void Envelope::initialize(AudioHost *host) {
+ this->host = host;
+ update();
+}
+
+void Envelope::update() {
attackIncrement = 1 / attack / host->sampleRate;
delayIncrement = 1 / delay / host->sampleRate;
releaseIncrement = 1 / release / host->sampleRate;
diff --git a/app/src/main/cpp/effects/Envelope.h b/app/src/main/cpp/effects/Envelope.h
index 7076f8f..dbb5575 100644
--- a/app/src/main/cpp/effects/Envelope.h
+++ b/app/src/main/cpp/effects/Envelope.h
@@ -16,15 +16,16 @@
EnvelopePhase phase;
float attackIncrement, delayIncrement, releaseIncrement;
float value = 0;
+ AudioHost *host;
public:
- float attack = 0.05, delay = 0.2, sustain = 0.75, release = 1;
+ float attack = 0.05, delay = 0.05, sustain = 0.7, release = 0.1;
void initialize(AudioHost *host);
+ void update();
+
void startNote();
-
void endNote();
-
void doRender(uint32_t sampleCount);
};
diff --git a/app/src/main/java/com/lukas/music/instruments/Envelope.kt b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
new file mode 100644
index 0000000..6603611
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.instruments
+
+class Envelope(val instrument: Instrument) {
+ var attack: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var delay: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var sustain: Int = 70
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var release: Int = 100
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/Instrument.kt b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
index 92a896c..3013335 100644
--- a/app/src/main/java/com/lukas/music/instruments/Instrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
@@ -16,6 +16,7 @@
abstract class Instrument(var name: String) {
var voice: Voice = BassVoice(this)
+ var envelope = Envelope(this)
abstract var waveform: Waveform
abstract var volume: Float
abstract var muted: Boolean
@@ -24,6 +25,7 @@
abstract fun stop()
abstract fun stopNote(note: Note)
abstract fun destroy()
+ abstract fun updateEnvelope()
companion object {
val instruments = mutableListOf()
diff --git a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
index b4c68a4..946e653 100644
--- a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
@@ -13,7 +13,7 @@
import com.lukas.music.song.note.Note
class InternalInstrument {
- private val id = createInstrument()
+ val id = createInstrument()
var note: Note? = null
var waveform: Waveform = Waveform.SINE
@@ -67,10 +67,27 @@
destroy(id)
}
+ fun applyEnvelope(envelope: Envelope) {
+ updateEnvelopeParameters(
+ id,
+ envelope.attack.toFloat() / 1000f,
+ envelope.delay.toFloat() / 1000f,
+ envelope.sustain.toFloat() / 100f,
+ envelope.release.toFloat() / 1000f,
+ )
+ }
+
private external fun createInstrument(): Int
private external fun setInstrumentWaveform(id: Int, waveform: Int)
private external fun startNote(id: Int, frequency: Double)
private external fun endNote(id: Int)
private external fun setVolume(id: Int, volume: Float)
private external fun destroy(id: Int)
+ private external fun updateEnvelopeParameters(
+ id: Int,
+ attack: Float,
+ delay: Float,
+ sustain: Float,
+ release: Float
+ )
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
index 2b43524..a9b5c53 100644
--- a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
@@ -53,4 +53,8 @@
override fun destroy() {
internalInstrument.destroy()
}
+
+ override fun updateEnvelope() {
+ internalInstrument.applyEnvelope(envelope)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
index 26e4fbb..8f055d0 100644
--- a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
@@ -75,4 +75,10 @@
instrument.destroy()
}
}
+
+ override fun updateEnvelope() {
+ for (instrument in internalInstruments) {
+ instrument.applyEnvelope(envelope)
+ }
+ }
}
\ 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
index bd7a3d9..f01d9e4 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
@@ -23,7 +23,7 @@
import com.lukas.music.song.chords.Interval
import com.lukas.music.util.setup
-class EditChordFragment(val chord: Chord, private val songFragment: SongFragment) :
+class EditChordFragment(private val chord: Chord, private val songFragment: SongFragment) :
DialogFragment() {
lateinit var binding: FragmentEditChordBinding
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/EditEnvelopeFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/EditEnvelopeFragment.kt
new file mode 100644
index 0000000..ea6a855
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditEnvelopeFragment.kt
@@ -0,0 +1,55 @@
+/*
+ * 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 androidx.fragment.app.DialogFragment
+import com.lukas.music.databinding.FragmentEditEnvelopeBinding
+import com.lukas.music.instruments.Envelope
+import com.lukas.music.util.smartSetup
+
+class EditEnvelopeFragment(private val envelope: Envelope) : DialogFragment() {
+ lateinit var binding: FragmentEditEnvelopeBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentEditEnvelopeBinding.inflate(inflater)
+ binding.attackSeek.smartSetup(5, 200, envelope::attack) {
+ binding.attackText.text = "Attack: $it ms"
+ }
+ binding.delaySeek.smartSetup(5, 200, envelope::delay) {
+ binding.delayText.text = "Delay: $it ms"
+ }
+ binding.sustainSeek.smartSetup(0, 100, envelope::sustain) {
+ binding.sustainText.text = "Sustain: $it%"
+ }
+ binding.releaseSeek.smartSetup(5, 200, envelope::release) {
+ binding.releaseText.text = "Release: $it ms"
+ }
+ binding.closeButton.setOnClickListener {
+ dismiss()
+ }
+ return binding.root
+ }
+
+ override fun onStart() {
+ super.onStart()
+ dialog?.window?.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+}
\ No newline at end of file
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 9c76f59..45d84b9 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
@@ -64,6 +64,9 @@
binding.editVoiceButton.setOnClickListener {
EditVoiceFragment(instrument.voice).showNow(childFragmentManager, "")
}
+ binding.editEnvelopeButton.setOnClickListener {
+ EditEnvelopeFragment(instrument.envelope).showNow(childFragmentManager, "")
+ }
binding.closeButton.setOnClickListener {
dismiss()
}
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 e7ba28f..9e2c520 100644
--- a/app/src/main/java/com/lukas/music/util/UIUtil.kt
+++ b/app/src/main/java/com/lukas/music/util/UIUtil.kt
@@ -39,6 +39,18 @@
this.progress = initialProgress
}
+fun SeekBar.smartSetup(
+ min: Int,
+ max: Int,
+ target: KMutableProperty0,
+ callback: (Int) -> Unit
+) {
+ setup(min, max, target.get()) {
+ target.set(it)
+ callback(it)
+ }
+}
+
fun Button.setupToggle(
target: KMutableProperty0,
activeColor: Int,
diff --git a/app/src/main/res/layout/fragment_edit_envelope.xml b/app/src/main/res/layout/fragment_edit_envelope.xml
new file mode 100644
index 0000000..9e45d05
--- /dev/null
+++ b/app/src/main/res/layout/fragment_edit_envelope.xml
@@ -0,0 +1,135 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3d886c4..66c49ef 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -11,6 +11,7 @@
+
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index 5505a35..d26ee2b 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -76,4 +76,20 @@
listSet(audioHost->instruments->begin(), id, nullptr);
delete getInstrument(id);
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_updateEnvelopeParameters(JNIEnv *env,
+ jobject thiz, jint id,
+ jfloat attack,
+ jfloat delay,
+ jfloat sustain,
+ jfloat release) {
+ Instrument *instrument = getInstrument((id));
+ Envelope *envelope = instrument->envelope;
+ envelope->attack = attack;
+ envelope->delay = delay;
+ envelope->sustain = sustain;
+ envelope->release = release;
+ envelope->update();
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Envelope.cpp b/app/src/main/cpp/effects/Envelope.cpp
index f8dfd61..5400548 100644
--- a/app/src/main/cpp/effects/Envelope.cpp
+++ b/app/src/main/cpp/effects/Envelope.cpp
@@ -3,6 +3,11 @@
#include "Envelope.h"
void Envelope::initialize(AudioHost *host) {
+ this->host = host;
+ update();
+}
+
+void Envelope::update() {
attackIncrement = 1 / attack / host->sampleRate;
delayIncrement = 1 / delay / host->sampleRate;
releaseIncrement = 1 / release / host->sampleRate;
diff --git a/app/src/main/cpp/effects/Envelope.h b/app/src/main/cpp/effects/Envelope.h
index 7076f8f..dbb5575 100644
--- a/app/src/main/cpp/effects/Envelope.h
+++ b/app/src/main/cpp/effects/Envelope.h
@@ -16,15 +16,16 @@
EnvelopePhase phase;
float attackIncrement, delayIncrement, releaseIncrement;
float value = 0;
+ AudioHost *host;
public:
- float attack = 0.05, delay = 0.2, sustain = 0.75, release = 1;
+ float attack = 0.05, delay = 0.05, sustain = 0.7, release = 0.1;
void initialize(AudioHost *host);
+ void update();
+
void startNote();
-
void endNote();
-
void doRender(uint32_t sampleCount);
};
diff --git a/app/src/main/java/com/lukas/music/instruments/Envelope.kt b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
new file mode 100644
index 0000000..6603611
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.instruments
+
+class Envelope(val instrument: Instrument) {
+ var attack: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var delay: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var sustain: Int = 70
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var release: Int = 100
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/Instrument.kt b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
index 92a896c..3013335 100644
--- a/app/src/main/java/com/lukas/music/instruments/Instrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
@@ -16,6 +16,7 @@
abstract class Instrument(var name: String) {
var voice: Voice = BassVoice(this)
+ var envelope = Envelope(this)
abstract var waveform: Waveform
abstract var volume: Float
abstract var muted: Boolean
@@ -24,6 +25,7 @@
abstract fun stop()
abstract fun stopNote(note: Note)
abstract fun destroy()
+ abstract fun updateEnvelope()
companion object {
val instruments = mutableListOf()
diff --git a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
index b4c68a4..946e653 100644
--- a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
@@ -13,7 +13,7 @@
import com.lukas.music.song.note.Note
class InternalInstrument {
- private val id = createInstrument()
+ val id = createInstrument()
var note: Note? = null
var waveform: Waveform = Waveform.SINE
@@ -67,10 +67,27 @@
destroy(id)
}
+ fun applyEnvelope(envelope: Envelope) {
+ updateEnvelopeParameters(
+ id,
+ envelope.attack.toFloat() / 1000f,
+ envelope.delay.toFloat() / 1000f,
+ envelope.sustain.toFloat() / 100f,
+ envelope.release.toFloat() / 1000f,
+ )
+ }
+
private external fun createInstrument(): Int
private external fun setInstrumentWaveform(id: Int, waveform: Int)
private external fun startNote(id: Int, frequency: Double)
private external fun endNote(id: Int)
private external fun setVolume(id: Int, volume: Float)
private external fun destroy(id: Int)
+ private external fun updateEnvelopeParameters(
+ id: Int,
+ attack: Float,
+ delay: Float,
+ sustain: Float,
+ release: Float
+ )
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
index 2b43524..a9b5c53 100644
--- a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
@@ -53,4 +53,8 @@
override fun destroy() {
internalInstrument.destroy()
}
+
+ override fun updateEnvelope() {
+ internalInstrument.applyEnvelope(envelope)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
index 26e4fbb..8f055d0 100644
--- a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
@@ -75,4 +75,10 @@
instrument.destroy()
}
}
+
+ override fun updateEnvelope() {
+ for (instrument in internalInstruments) {
+ instrument.applyEnvelope(envelope)
+ }
+ }
}
\ 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
index bd7a3d9..f01d9e4 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
@@ -23,7 +23,7 @@
import com.lukas.music.song.chords.Interval
import com.lukas.music.util.setup
-class EditChordFragment(val chord: Chord, private val songFragment: SongFragment) :
+class EditChordFragment(private val chord: Chord, private val songFragment: SongFragment) :
DialogFragment() {
lateinit var binding: FragmentEditChordBinding
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/EditEnvelopeFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/EditEnvelopeFragment.kt
new file mode 100644
index 0000000..ea6a855
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditEnvelopeFragment.kt
@@ -0,0 +1,55 @@
+/*
+ * 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 androidx.fragment.app.DialogFragment
+import com.lukas.music.databinding.FragmentEditEnvelopeBinding
+import com.lukas.music.instruments.Envelope
+import com.lukas.music.util.smartSetup
+
+class EditEnvelopeFragment(private val envelope: Envelope) : DialogFragment() {
+ lateinit var binding: FragmentEditEnvelopeBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentEditEnvelopeBinding.inflate(inflater)
+ binding.attackSeek.smartSetup(5, 200, envelope::attack) {
+ binding.attackText.text = "Attack: $it ms"
+ }
+ binding.delaySeek.smartSetup(5, 200, envelope::delay) {
+ binding.delayText.text = "Delay: $it ms"
+ }
+ binding.sustainSeek.smartSetup(0, 100, envelope::sustain) {
+ binding.sustainText.text = "Sustain: $it%"
+ }
+ binding.releaseSeek.smartSetup(5, 200, envelope::release) {
+ binding.releaseText.text = "Release: $it ms"
+ }
+ binding.closeButton.setOnClickListener {
+ dismiss()
+ }
+ return binding.root
+ }
+
+ override fun onStart() {
+ super.onStart()
+ dialog?.window?.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+}
\ No newline at end of file
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 9c76f59..45d84b9 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
@@ -64,6 +64,9 @@
binding.editVoiceButton.setOnClickListener {
EditVoiceFragment(instrument.voice).showNow(childFragmentManager, "")
}
+ binding.editEnvelopeButton.setOnClickListener {
+ EditEnvelopeFragment(instrument.envelope).showNow(childFragmentManager, "")
+ }
binding.closeButton.setOnClickListener {
dismiss()
}
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 e7ba28f..9e2c520 100644
--- a/app/src/main/java/com/lukas/music/util/UIUtil.kt
+++ b/app/src/main/java/com/lukas/music/util/UIUtil.kt
@@ -39,6 +39,18 @@
this.progress = initialProgress
}
+fun SeekBar.smartSetup(
+ min: Int,
+ max: Int,
+ target: KMutableProperty0,
+ callback: (Int) -> Unit
+) {
+ setup(min, max, target.get()) {
+ target.set(it)
+ callback(it)
+ }
+}
+
fun Button.setupToggle(
target: KMutableProperty0,
activeColor: Int,
diff --git a/app/src/main/res/layout/fragment_edit_envelope.xml b/app/src/main/res/layout/fragment_edit_envelope.xml
new file mode 100644
index 0000000..9e45d05
--- /dev/null
+++ b/app/src/main/res/layout/fragment_edit_envelope.xml
@@ -0,0 +1,135 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_edit_instrument.xml b/app/src/main/res/layout/fragment_edit_instrument.xml
index b5578fc..55e667b 100644
--- a/app/src/main/res/layout/fragment_edit_instrument.xml
+++ b/app/src/main/res/layout/fragment_edit_instrument.xml
@@ -14,8 +14,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".EditInstrumentFragment">
-
-
+ app:layout_constraintTop_toBottomOf="@+id/editEnvelopeButton" />
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3d886c4..66c49ef 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -11,6 +11,7 @@
+
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index 5505a35..d26ee2b 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -76,4 +76,20 @@
listSet(audioHost->instruments->begin(), id, nullptr);
delete getInstrument(id);
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_updateEnvelopeParameters(JNIEnv *env,
+ jobject thiz, jint id,
+ jfloat attack,
+ jfloat delay,
+ jfloat sustain,
+ jfloat release) {
+ Instrument *instrument = getInstrument((id));
+ Envelope *envelope = instrument->envelope;
+ envelope->attack = attack;
+ envelope->delay = delay;
+ envelope->sustain = sustain;
+ envelope->release = release;
+ envelope->update();
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Envelope.cpp b/app/src/main/cpp/effects/Envelope.cpp
index f8dfd61..5400548 100644
--- a/app/src/main/cpp/effects/Envelope.cpp
+++ b/app/src/main/cpp/effects/Envelope.cpp
@@ -3,6 +3,11 @@
#include "Envelope.h"
void Envelope::initialize(AudioHost *host) {
+ this->host = host;
+ update();
+}
+
+void Envelope::update() {
attackIncrement = 1 / attack / host->sampleRate;
delayIncrement = 1 / delay / host->sampleRate;
releaseIncrement = 1 / release / host->sampleRate;
diff --git a/app/src/main/cpp/effects/Envelope.h b/app/src/main/cpp/effects/Envelope.h
index 7076f8f..dbb5575 100644
--- a/app/src/main/cpp/effects/Envelope.h
+++ b/app/src/main/cpp/effects/Envelope.h
@@ -16,15 +16,16 @@
EnvelopePhase phase;
float attackIncrement, delayIncrement, releaseIncrement;
float value = 0;
+ AudioHost *host;
public:
- float attack = 0.05, delay = 0.2, sustain = 0.75, release = 1;
+ float attack = 0.05, delay = 0.05, sustain = 0.7, release = 0.1;
void initialize(AudioHost *host);
+ void update();
+
void startNote();
-
void endNote();
-
void doRender(uint32_t sampleCount);
};
diff --git a/app/src/main/java/com/lukas/music/instruments/Envelope.kt b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
new file mode 100644
index 0000000..6603611
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.instruments
+
+class Envelope(val instrument: Instrument) {
+ var attack: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var delay: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var sustain: Int = 70
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var release: Int = 100
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/Instrument.kt b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
index 92a896c..3013335 100644
--- a/app/src/main/java/com/lukas/music/instruments/Instrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
@@ -16,6 +16,7 @@
abstract class Instrument(var name: String) {
var voice: Voice = BassVoice(this)
+ var envelope = Envelope(this)
abstract var waveform: Waveform
abstract var volume: Float
abstract var muted: Boolean
@@ -24,6 +25,7 @@
abstract fun stop()
abstract fun stopNote(note: Note)
abstract fun destroy()
+ abstract fun updateEnvelope()
companion object {
val instruments = mutableListOf()
diff --git a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
index b4c68a4..946e653 100644
--- a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
@@ -13,7 +13,7 @@
import com.lukas.music.song.note.Note
class InternalInstrument {
- private val id = createInstrument()
+ val id = createInstrument()
var note: Note? = null
var waveform: Waveform = Waveform.SINE
@@ -67,10 +67,27 @@
destroy(id)
}
+ fun applyEnvelope(envelope: Envelope) {
+ updateEnvelopeParameters(
+ id,
+ envelope.attack.toFloat() / 1000f,
+ envelope.delay.toFloat() / 1000f,
+ envelope.sustain.toFloat() / 100f,
+ envelope.release.toFloat() / 1000f,
+ )
+ }
+
private external fun createInstrument(): Int
private external fun setInstrumentWaveform(id: Int, waveform: Int)
private external fun startNote(id: Int, frequency: Double)
private external fun endNote(id: Int)
private external fun setVolume(id: Int, volume: Float)
private external fun destroy(id: Int)
+ private external fun updateEnvelopeParameters(
+ id: Int,
+ attack: Float,
+ delay: Float,
+ sustain: Float,
+ release: Float
+ )
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
index 2b43524..a9b5c53 100644
--- a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
@@ -53,4 +53,8 @@
override fun destroy() {
internalInstrument.destroy()
}
+
+ override fun updateEnvelope() {
+ internalInstrument.applyEnvelope(envelope)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
index 26e4fbb..8f055d0 100644
--- a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
@@ -75,4 +75,10 @@
instrument.destroy()
}
}
+
+ override fun updateEnvelope() {
+ for (instrument in internalInstruments) {
+ instrument.applyEnvelope(envelope)
+ }
+ }
}
\ 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
index bd7a3d9..f01d9e4 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
@@ -23,7 +23,7 @@
import com.lukas.music.song.chords.Interval
import com.lukas.music.util.setup
-class EditChordFragment(val chord: Chord, private val songFragment: SongFragment) :
+class EditChordFragment(private val chord: Chord, private val songFragment: SongFragment) :
DialogFragment() {
lateinit var binding: FragmentEditChordBinding
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/EditEnvelopeFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/EditEnvelopeFragment.kt
new file mode 100644
index 0000000..ea6a855
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditEnvelopeFragment.kt
@@ -0,0 +1,55 @@
+/*
+ * 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 androidx.fragment.app.DialogFragment
+import com.lukas.music.databinding.FragmentEditEnvelopeBinding
+import com.lukas.music.instruments.Envelope
+import com.lukas.music.util.smartSetup
+
+class EditEnvelopeFragment(private val envelope: Envelope) : DialogFragment() {
+ lateinit var binding: FragmentEditEnvelopeBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentEditEnvelopeBinding.inflate(inflater)
+ binding.attackSeek.smartSetup(5, 200, envelope::attack) {
+ binding.attackText.text = "Attack: $it ms"
+ }
+ binding.delaySeek.smartSetup(5, 200, envelope::delay) {
+ binding.delayText.text = "Delay: $it ms"
+ }
+ binding.sustainSeek.smartSetup(0, 100, envelope::sustain) {
+ binding.sustainText.text = "Sustain: $it%"
+ }
+ binding.releaseSeek.smartSetup(5, 200, envelope::release) {
+ binding.releaseText.text = "Release: $it ms"
+ }
+ binding.closeButton.setOnClickListener {
+ dismiss()
+ }
+ return binding.root
+ }
+
+ override fun onStart() {
+ super.onStart()
+ dialog?.window?.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+}
\ No newline at end of file
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 9c76f59..45d84b9 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
@@ -64,6 +64,9 @@
binding.editVoiceButton.setOnClickListener {
EditVoiceFragment(instrument.voice).showNow(childFragmentManager, "")
}
+ binding.editEnvelopeButton.setOnClickListener {
+ EditEnvelopeFragment(instrument.envelope).showNow(childFragmentManager, "")
+ }
binding.closeButton.setOnClickListener {
dismiss()
}
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 e7ba28f..9e2c520 100644
--- a/app/src/main/java/com/lukas/music/util/UIUtil.kt
+++ b/app/src/main/java/com/lukas/music/util/UIUtil.kt
@@ -39,6 +39,18 @@
this.progress = initialProgress
}
+fun SeekBar.smartSetup(
+ min: Int,
+ max: Int,
+ target: KMutableProperty0,
+ callback: (Int) -> Unit
+) {
+ setup(min, max, target.get()) {
+ target.set(it)
+ callback(it)
+ }
+}
+
fun Button.setupToggle(
target: KMutableProperty0,
activeColor: Int,
diff --git a/app/src/main/res/layout/fragment_edit_envelope.xml b/app/src/main/res/layout/fragment_edit_envelope.xml
new file mode 100644
index 0000000..9e45d05
--- /dev/null
+++ b/app/src/main/res/layout/fragment_edit_envelope.xml
@@ -0,0 +1,135 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_edit_instrument.xml b/app/src/main/res/layout/fragment_edit_instrument.xml
index b5578fc..55e667b 100644
--- a/app/src/main/res/layout/fragment_edit_instrument.xml
+++ b/app/src/main/res/layout/fragment_edit_instrument.xml
@@ -14,8 +14,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".EditInstrumentFragment">
-
-
+ app:layout_constraintTop_toBottomOf="@+id/editEnvelopeButton" />
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_edit_voice.xml b/app/src/main/res/layout/fragment_edit_voice.xml
index 5380d7d..d9f8eaf 100644
--- a/app/src/main/res/layout/fragment_edit_voice.xml
+++ b/app/src/main/res/layout/fragment_edit_voice.xml
@@ -16,7 +16,6 @@
android:layout_height="match_parent"
tools:context=".ui.fragments.EditVoiceFragment">
-
+
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index 5505a35..d26ee2b 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -76,4 +76,20 @@
listSet(audioHost->instruments->begin(), id, nullptr);
delete getInstrument(id);
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_updateEnvelopeParameters(JNIEnv *env,
+ jobject thiz, jint id,
+ jfloat attack,
+ jfloat delay,
+ jfloat sustain,
+ jfloat release) {
+ Instrument *instrument = getInstrument((id));
+ Envelope *envelope = instrument->envelope;
+ envelope->attack = attack;
+ envelope->delay = delay;
+ envelope->sustain = sustain;
+ envelope->release = release;
+ envelope->update();
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Envelope.cpp b/app/src/main/cpp/effects/Envelope.cpp
index f8dfd61..5400548 100644
--- a/app/src/main/cpp/effects/Envelope.cpp
+++ b/app/src/main/cpp/effects/Envelope.cpp
@@ -3,6 +3,11 @@
#include "Envelope.h"
void Envelope::initialize(AudioHost *host) {
+ this->host = host;
+ update();
+}
+
+void Envelope::update() {
attackIncrement = 1 / attack / host->sampleRate;
delayIncrement = 1 / delay / host->sampleRate;
releaseIncrement = 1 / release / host->sampleRate;
diff --git a/app/src/main/cpp/effects/Envelope.h b/app/src/main/cpp/effects/Envelope.h
index 7076f8f..dbb5575 100644
--- a/app/src/main/cpp/effects/Envelope.h
+++ b/app/src/main/cpp/effects/Envelope.h
@@ -16,15 +16,16 @@
EnvelopePhase phase;
float attackIncrement, delayIncrement, releaseIncrement;
float value = 0;
+ AudioHost *host;
public:
- float attack = 0.05, delay = 0.2, sustain = 0.75, release = 1;
+ float attack = 0.05, delay = 0.05, sustain = 0.7, release = 0.1;
void initialize(AudioHost *host);
+ void update();
+
void startNote();
-
void endNote();
-
void doRender(uint32_t sampleCount);
};
diff --git a/app/src/main/java/com/lukas/music/instruments/Envelope.kt b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
new file mode 100644
index 0000000..6603611
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/instruments/Envelope.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.instruments
+
+class Envelope(val instrument: Instrument) {
+ var attack: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var delay: Int = 50
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var sustain: Int = 70
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+
+ var release: Int = 100
+ set(value) {
+ field = value
+ instrument.updateEnvelope()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/Instrument.kt b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
index 92a896c..3013335 100644
--- a/app/src/main/java/com/lukas/music/instruments/Instrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
@@ -16,6 +16,7 @@
abstract class Instrument(var name: String) {
var voice: Voice = BassVoice(this)
+ var envelope = Envelope(this)
abstract var waveform: Waveform
abstract var volume: Float
abstract var muted: Boolean
@@ -24,6 +25,7 @@
abstract fun stop()
abstract fun stopNote(note: Note)
abstract fun destroy()
+ abstract fun updateEnvelope()
companion object {
val instruments = mutableListOf()
diff --git a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
index b4c68a4..946e653 100644
--- a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
@@ -13,7 +13,7 @@
import com.lukas.music.song.note.Note
class InternalInstrument {
- private val id = createInstrument()
+ val id = createInstrument()
var note: Note? = null
var waveform: Waveform = Waveform.SINE
@@ -67,10 +67,27 @@
destroy(id)
}
+ fun applyEnvelope(envelope: Envelope) {
+ updateEnvelopeParameters(
+ id,
+ envelope.attack.toFloat() / 1000f,
+ envelope.delay.toFloat() / 1000f,
+ envelope.sustain.toFloat() / 100f,
+ envelope.release.toFloat() / 1000f,
+ )
+ }
+
private external fun createInstrument(): Int
private external fun setInstrumentWaveform(id: Int, waveform: Int)
private external fun startNote(id: Int, frequency: Double)
private external fun endNote(id: Int)
private external fun setVolume(id: Int, volume: Float)
private external fun destroy(id: Int)
+ private external fun updateEnvelopeParameters(
+ id: Int,
+ attack: Float,
+ delay: Float,
+ sustain: Float,
+ release: Float
+ )
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
index 2b43524..a9b5c53 100644
--- a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
@@ -53,4 +53,8 @@
override fun destroy() {
internalInstrument.destroy()
}
+
+ override fun updateEnvelope() {
+ internalInstrument.applyEnvelope(envelope)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
index 26e4fbb..8f055d0 100644
--- a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
@@ -75,4 +75,10 @@
instrument.destroy()
}
}
+
+ override fun updateEnvelope() {
+ for (instrument in internalInstruments) {
+ instrument.applyEnvelope(envelope)
+ }
+ }
}
\ 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
index bd7a3d9..f01d9e4 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditChordFragment.kt
@@ -23,7 +23,7 @@
import com.lukas.music.song.chords.Interval
import com.lukas.music.util.setup
-class EditChordFragment(val chord: Chord, private val songFragment: SongFragment) :
+class EditChordFragment(private val chord: Chord, private val songFragment: SongFragment) :
DialogFragment() {
lateinit var binding: FragmentEditChordBinding
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/EditEnvelopeFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/EditEnvelopeFragment.kt
new file mode 100644
index 0000000..ea6a855
--- /dev/null
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EditEnvelopeFragment.kt
@@ -0,0 +1,55 @@
+/*
+ * 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 androidx.fragment.app.DialogFragment
+import com.lukas.music.databinding.FragmentEditEnvelopeBinding
+import com.lukas.music.instruments.Envelope
+import com.lukas.music.util.smartSetup
+
+class EditEnvelopeFragment(private val envelope: Envelope) : DialogFragment() {
+ lateinit var binding: FragmentEditEnvelopeBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentEditEnvelopeBinding.inflate(inflater)
+ binding.attackSeek.smartSetup(5, 200, envelope::attack) {
+ binding.attackText.text = "Attack: $it ms"
+ }
+ binding.delaySeek.smartSetup(5, 200, envelope::delay) {
+ binding.delayText.text = "Delay: $it ms"
+ }
+ binding.sustainSeek.smartSetup(0, 100, envelope::sustain) {
+ binding.sustainText.text = "Sustain: $it%"
+ }
+ binding.releaseSeek.smartSetup(5, 200, envelope::release) {
+ binding.releaseText.text = "Release: $it ms"
+ }
+ binding.closeButton.setOnClickListener {
+ dismiss()
+ }
+ return binding.root
+ }
+
+ override fun onStart() {
+ super.onStart()
+ dialog?.window?.setLayout(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ }
+}
\ No newline at end of file
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 9c76f59..45d84b9 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
@@ -64,6 +64,9 @@
binding.editVoiceButton.setOnClickListener {
EditVoiceFragment(instrument.voice).showNow(childFragmentManager, "")
}
+ binding.editEnvelopeButton.setOnClickListener {
+ EditEnvelopeFragment(instrument.envelope).showNow(childFragmentManager, "")
+ }
binding.closeButton.setOnClickListener {
dismiss()
}
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 e7ba28f..9e2c520 100644
--- a/app/src/main/java/com/lukas/music/util/UIUtil.kt
+++ b/app/src/main/java/com/lukas/music/util/UIUtil.kt
@@ -39,6 +39,18 @@
this.progress = initialProgress
}
+fun SeekBar.smartSetup(
+ min: Int,
+ max: Int,
+ target: KMutableProperty0,
+ callback: (Int) -> Unit
+) {
+ setup(min, max, target.get()) {
+ target.set(it)
+ callback(it)
+ }
+}
+
fun Button.setupToggle(
target: KMutableProperty0,
activeColor: Int,
diff --git a/app/src/main/res/layout/fragment_edit_envelope.xml b/app/src/main/res/layout/fragment_edit_envelope.xml
new file mode 100644
index 0000000..9e45d05
--- /dev/null
+++ b/app/src/main/res/layout/fragment_edit_envelope.xml
@@ -0,0 +1,135 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_edit_instrument.xml b/app/src/main/res/layout/fragment_edit_instrument.xml
index b5578fc..55e667b 100644
--- a/app/src/main/res/layout/fragment_edit_instrument.xml
+++ b/app/src/main/res/layout/fragment_edit_instrument.xml
@@ -14,8 +14,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".EditInstrumentFragment">
-
-
+ app:layout_constraintTop_toBottomOf="@+id/editEnvelopeButton" />
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_edit_voice.xml b/app/src/main/res/layout/fragment_edit_voice.xml
index 5380d7d..d9f8eaf 100644
--- a/app/src/main/res/layout/fragment_edit_voice.xml
+++ b/app/src/main/res/layout/fragment_edit_voice.xml
@@ -16,7 +16,6 @@
android:layout_height="match_parent"
tools:context=".ui.fragments.EditVoiceFragment">
-
Add a new instrument
Delete this instrument
Edit voice
+ Edit envelope
\ No newline at end of file