diff --git a/.idea/misc.xml b/.idea/misc.xml
index bf86c48..1a41dfa 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/.idea/misc.xml b/.idea/misc.xml
index bf86c48..1a41dfa 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/app/src/main/cpp/AudioHost.cpp b/app/src/main/cpp/AudioHost.cpp
index 8e98b44..6727405 100644
--- a/app/src/main/cpp/AudioHost.cpp
+++ b/app/src/main/cpp/AudioHost.cpp
@@ -1,7 +1,9 @@
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
+#include
const uint32_t bufferSize = 2;
aaudio_data_callback_result_t dataCallback(
diff --git a/.idea/misc.xml b/.idea/misc.xml
index bf86c48..1a41dfa 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/app/src/main/cpp/AudioHost.cpp b/app/src/main/cpp/AudioHost.cpp
index 8e98b44..6727405 100644
--- a/app/src/main/cpp/AudioHost.cpp
+++ b/app/src/main/cpp/AudioHost.cpp
@@ -1,7 +1,9 @@
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
+#include
const uint32_t bufferSize = 2;
aaudio_data_callback_result_t dataCallback(
diff --git a/app/src/main/cpp/AudioHost.h b/app/src/main/cpp/AudioHost.h
index f439fdc..97446ea 100644
--- a/app/src/main/cpp/AudioHost.h
+++ b/app/src/main/cpp/AudioHost.h
@@ -3,7 +3,8 @@
class AudioHost;
-#include "Instrument.h"
+class Instrument;
+
#include
#include
diff --git a/.idea/misc.xml b/.idea/misc.xml
index bf86c48..1a41dfa 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/app/src/main/cpp/AudioHost.cpp b/app/src/main/cpp/AudioHost.cpp
index 8e98b44..6727405 100644
--- a/app/src/main/cpp/AudioHost.cpp
+++ b/app/src/main/cpp/AudioHost.cpp
@@ -1,7 +1,9 @@
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
+#include
const uint32_t bufferSize = 2;
aaudio_data_callback_result_t dataCallback(
diff --git a/app/src/main/cpp/AudioHost.h b/app/src/main/cpp/AudioHost.h
index f439fdc..97446ea 100644
--- a/app/src/main/cpp/AudioHost.h
+++ b/app/src/main/cpp/AudioHost.h
@@ -3,7 +3,8 @@
class AudioHost;
-#include "Instrument.h"
+class Instrument;
+
#include
#include
diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
index b94b511..8588bed 100644
--- a/app/src/main/cpp/CMakeLists.txt
+++ b/app/src/main/cpp/CMakeLists.txt
@@ -17,6 +17,8 @@
Instrument.cpp
effects/Envelope.cpp
effects/Processable.cpp
+ effects/Effect.cpp
+ effects/LowPass.cpp
)
find_library(
diff --git a/.idea/misc.xml b/.idea/misc.xml
index bf86c48..1a41dfa 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/app/src/main/cpp/AudioHost.cpp b/app/src/main/cpp/AudioHost.cpp
index 8e98b44..6727405 100644
--- a/app/src/main/cpp/AudioHost.cpp
+++ b/app/src/main/cpp/AudioHost.cpp
@@ -1,7 +1,9 @@
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
+#include
const uint32_t bufferSize = 2;
aaudio_data_callback_result_t dataCallback(
diff --git a/app/src/main/cpp/AudioHost.h b/app/src/main/cpp/AudioHost.h
index f439fdc..97446ea 100644
--- a/app/src/main/cpp/AudioHost.h
+++ b/app/src/main/cpp/AudioHost.h
@@ -3,7 +3,8 @@
class AudioHost;
-#include "Instrument.h"
+class Instrument;
+
#include
#include
diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
index b94b511..8588bed 100644
--- a/app/src/main/cpp/CMakeLists.txt
+++ b/app/src/main/cpp/CMakeLists.txt
@@ -17,6 +17,8 @@
Instrument.cpp
effects/Envelope.cpp
effects/Processable.cpp
+ effects/Effect.cpp
+ effects/LowPass.cpp
)
find_library(
diff --git a/app/src/main/cpp/Instrument.cpp b/app/src/main/cpp/Instrument.cpp
index d7263ed..985e93e 100644
--- a/app/src/main/cpp/Instrument.cpp
+++ b/app/src/main/cpp/Instrument.cpp
@@ -9,6 +9,7 @@
wave = new Sine();
wave->host = host;
envelope->initialize(host);
+ lowPass->host = host;
}
void multiply(float *target, float *modulation, uint32_t size) {
@@ -27,12 +28,16 @@
float *modulation = envelope->render(count);
float *waveform = wave->render(count);
multiply(waveform, modulation, count);
- add(buffer, waveform, count);
+ lowPass->input = waveform;
+ float *filtered = lowPass->render(count);
+ add(buffer, filtered, count);
}
void Instrument::startNote(float frequency) {
wave->setFrequency(frequency);
envelope->startNote();
+ lowPass->frequency = frequency;
+ lowPass->update();
}
void Instrument::endNote() {
diff --git a/.idea/misc.xml b/.idea/misc.xml
index bf86c48..1a41dfa 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/app/src/main/cpp/AudioHost.cpp b/app/src/main/cpp/AudioHost.cpp
index 8e98b44..6727405 100644
--- a/app/src/main/cpp/AudioHost.cpp
+++ b/app/src/main/cpp/AudioHost.cpp
@@ -1,7 +1,9 @@
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
+#include
const uint32_t bufferSize = 2;
aaudio_data_callback_result_t dataCallback(
diff --git a/app/src/main/cpp/AudioHost.h b/app/src/main/cpp/AudioHost.h
index f439fdc..97446ea 100644
--- a/app/src/main/cpp/AudioHost.h
+++ b/app/src/main/cpp/AudioHost.h
@@ -3,7 +3,8 @@
class AudioHost;
-#include "Instrument.h"
+class Instrument;
+
#include
#include
diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
index b94b511..8588bed 100644
--- a/app/src/main/cpp/CMakeLists.txt
+++ b/app/src/main/cpp/CMakeLists.txt
@@ -17,6 +17,8 @@
Instrument.cpp
effects/Envelope.cpp
effects/Processable.cpp
+ effects/Effect.cpp
+ effects/LowPass.cpp
)
find_library(
diff --git a/app/src/main/cpp/Instrument.cpp b/app/src/main/cpp/Instrument.cpp
index d7263ed..985e93e 100644
--- a/app/src/main/cpp/Instrument.cpp
+++ b/app/src/main/cpp/Instrument.cpp
@@ -9,6 +9,7 @@
wave = new Sine();
wave->host = host;
envelope->initialize(host);
+ lowPass->host = host;
}
void multiply(float *target, float *modulation, uint32_t size) {
@@ -27,12 +28,16 @@
float *modulation = envelope->render(count);
float *waveform = wave->render(count);
multiply(waveform, modulation, count);
- add(buffer, waveform, count);
+ lowPass->input = waveform;
+ float *filtered = lowPass->render(count);
+ add(buffer, filtered, count);
}
void Instrument::startNote(float frequency) {
wave->setFrequency(frequency);
envelope->startNote();
+ lowPass->frequency = frequency;
+ lowPass->update();
}
void Instrument::endNote() {
diff --git a/app/src/main/cpp/Instrument.h b/app/src/main/cpp/Instrument.h
index f15d631..3ab90a8 100644
--- a/app/src/main/cpp/Instrument.h
+++ b/app/src/main/cpp/Instrument.h
@@ -6,6 +6,7 @@
#include "effects/Envelope.h"
#include "waveforms/Waveform.h"
#include "AudioHost.h"
+#include "effects/LowPass.h"
class Instrument {
private:
@@ -15,6 +16,7 @@
Envelope *const envelope = new Envelope();
Waveform *wave;
+ LowPass *lowPass = new LowPass();
void render(float *buffer, uint32_t count);
void startNote(float frequency);
diff --git a/.idea/misc.xml b/.idea/misc.xml
index bf86c48..1a41dfa 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/app/src/main/cpp/AudioHost.cpp b/app/src/main/cpp/AudioHost.cpp
index 8e98b44..6727405 100644
--- a/app/src/main/cpp/AudioHost.cpp
+++ b/app/src/main/cpp/AudioHost.cpp
@@ -1,7 +1,9 @@
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
+#include
const uint32_t bufferSize = 2;
aaudio_data_callback_result_t dataCallback(
diff --git a/app/src/main/cpp/AudioHost.h b/app/src/main/cpp/AudioHost.h
index f439fdc..97446ea 100644
--- a/app/src/main/cpp/AudioHost.h
+++ b/app/src/main/cpp/AudioHost.h
@@ -3,7 +3,8 @@
class AudioHost;
-#include "Instrument.h"
+class Instrument;
+
#include
#include
diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
index b94b511..8588bed 100644
--- a/app/src/main/cpp/CMakeLists.txt
+++ b/app/src/main/cpp/CMakeLists.txt
@@ -17,6 +17,8 @@
Instrument.cpp
effects/Envelope.cpp
effects/Processable.cpp
+ effects/Effect.cpp
+ effects/LowPass.cpp
)
find_library(
diff --git a/app/src/main/cpp/Instrument.cpp b/app/src/main/cpp/Instrument.cpp
index d7263ed..985e93e 100644
--- a/app/src/main/cpp/Instrument.cpp
+++ b/app/src/main/cpp/Instrument.cpp
@@ -9,6 +9,7 @@
wave = new Sine();
wave->host = host;
envelope->initialize(host);
+ lowPass->host = host;
}
void multiply(float *target, float *modulation, uint32_t size) {
@@ -27,12 +28,16 @@
float *modulation = envelope->render(count);
float *waveform = wave->render(count);
multiply(waveform, modulation, count);
- add(buffer, waveform, count);
+ lowPass->input = waveform;
+ float *filtered = lowPass->render(count);
+ add(buffer, filtered, count);
}
void Instrument::startNote(float frequency) {
wave->setFrequency(frequency);
envelope->startNote();
+ lowPass->frequency = frequency;
+ lowPass->update();
}
void Instrument::endNote() {
diff --git a/app/src/main/cpp/Instrument.h b/app/src/main/cpp/Instrument.h
index f15d631..3ab90a8 100644
--- a/app/src/main/cpp/Instrument.h
+++ b/app/src/main/cpp/Instrument.h
@@ -6,6 +6,7 @@
#include "effects/Envelope.h"
#include "waveforms/Waveform.h"
#include "AudioHost.h"
+#include "effects/LowPass.h"
class Instrument {
private:
@@ -15,6 +16,7 @@
Envelope *const envelope = new Envelope();
Waveform *wave;
+ LowPass *lowPass = new LowPass();
void render(float *buffer, uint32_t count);
void startNote(float frequency);
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index d26ee2b..cb732f2 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -1,6 +1,7 @@
#include
#include
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
@@ -92,4 +93,19 @@
envelope->release = release;
envelope->update();
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_applyEffectAttributes(JNIEnv *env, jobject thiz,
+ jint id,
+ jint effect_number,
+ jfloat parameter1) {
+ Instrument *instrument = getInstrument(id);
+ Effect *effect;
+ switch (effect_number) {
+ case 0:
+ effect = instrument->lowPass;
+ break;
+ }
+ effect->parameter1 = parameter1;
+}
}
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index bf86c48..1a41dfa 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/app/src/main/cpp/AudioHost.cpp b/app/src/main/cpp/AudioHost.cpp
index 8e98b44..6727405 100644
--- a/app/src/main/cpp/AudioHost.cpp
+++ b/app/src/main/cpp/AudioHost.cpp
@@ -1,7 +1,9 @@
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
+#include
const uint32_t bufferSize = 2;
aaudio_data_callback_result_t dataCallback(
diff --git a/app/src/main/cpp/AudioHost.h b/app/src/main/cpp/AudioHost.h
index f439fdc..97446ea 100644
--- a/app/src/main/cpp/AudioHost.h
+++ b/app/src/main/cpp/AudioHost.h
@@ -3,7 +3,8 @@
class AudioHost;
-#include "Instrument.h"
+class Instrument;
+
#include
#include
diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
index b94b511..8588bed 100644
--- a/app/src/main/cpp/CMakeLists.txt
+++ b/app/src/main/cpp/CMakeLists.txt
@@ -17,6 +17,8 @@
Instrument.cpp
effects/Envelope.cpp
effects/Processable.cpp
+ effects/Effect.cpp
+ effects/LowPass.cpp
)
find_library(
diff --git a/app/src/main/cpp/Instrument.cpp b/app/src/main/cpp/Instrument.cpp
index d7263ed..985e93e 100644
--- a/app/src/main/cpp/Instrument.cpp
+++ b/app/src/main/cpp/Instrument.cpp
@@ -9,6 +9,7 @@
wave = new Sine();
wave->host = host;
envelope->initialize(host);
+ lowPass->host = host;
}
void multiply(float *target, float *modulation, uint32_t size) {
@@ -27,12 +28,16 @@
float *modulation = envelope->render(count);
float *waveform = wave->render(count);
multiply(waveform, modulation, count);
- add(buffer, waveform, count);
+ lowPass->input = waveform;
+ float *filtered = lowPass->render(count);
+ add(buffer, filtered, count);
}
void Instrument::startNote(float frequency) {
wave->setFrequency(frequency);
envelope->startNote();
+ lowPass->frequency = frequency;
+ lowPass->update();
}
void Instrument::endNote() {
diff --git a/app/src/main/cpp/Instrument.h b/app/src/main/cpp/Instrument.h
index f15d631..3ab90a8 100644
--- a/app/src/main/cpp/Instrument.h
+++ b/app/src/main/cpp/Instrument.h
@@ -6,6 +6,7 @@
#include "effects/Envelope.h"
#include "waveforms/Waveform.h"
#include "AudioHost.h"
+#include "effects/LowPass.h"
class Instrument {
private:
@@ -15,6 +16,7 @@
Envelope *const envelope = new Envelope();
Waveform *wave;
+ LowPass *lowPass = new LowPass();
void render(float *buffer, uint32_t count);
void startNote(float frequency);
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index d26ee2b..cb732f2 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -1,6 +1,7 @@
#include
#include
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
@@ -92,4 +93,19 @@
envelope->release = release;
envelope->update();
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_applyEffectAttributes(JNIEnv *env, jobject thiz,
+ jint id,
+ jint effect_number,
+ jfloat parameter1) {
+ Instrument *instrument = getInstrument(id);
+ Effect *effect;
+ switch (effect_number) {
+ case 0:
+ effect = instrument->lowPass;
+ break;
+ }
+ effect->parameter1 = parameter1;
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.cpp b/app/src/main/cpp/effects/Effect.cpp
new file mode 100644
index 0000000..881e413
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.cpp
@@ -0,0 +1 @@
+#include "Effect.h"
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index bf86c48..1a41dfa 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/app/src/main/cpp/AudioHost.cpp b/app/src/main/cpp/AudioHost.cpp
index 8e98b44..6727405 100644
--- a/app/src/main/cpp/AudioHost.cpp
+++ b/app/src/main/cpp/AudioHost.cpp
@@ -1,7 +1,9 @@
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
+#include
const uint32_t bufferSize = 2;
aaudio_data_callback_result_t dataCallback(
diff --git a/app/src/main/cpp/AudioHost.h b/app/src/main/cpp/AudioHost.h
index f439fdc..97446ea 100644
--- a/app/src/main/cpp/AudioHost.h
+++ b/app/src/main/cpp/AudioHost.h
@@ -3,7 +3,8 @@
class AudioHost;
-#include "Instrument.h"
+class Instrument;
+
#include
#include
diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
index b94b511..8588bed 100644
--- a/app/src/main/cpp/CMakeLists.txt
+++ b/app/src/main/cpp/CMakeLists.txt
@@ -17,6 +17,8 @@
Instrument.cpp
effects/Envelope.cpp
effects/Processable.cpp
+ effects/Effect.cpp
+ effects/LowPass.cpp
)
find_library(
diff --git a/app/src/main/cpp/Instrument.cpp b/app/src/main/cpp/Instrument.cpp
index d7263ed..985e93e 100644
--- a/app/src/main/cpp/Instrument.cpp
+++ b/app/src/main/cpp/Instrument.cpp
@@ -9,6 +9,7 @@
wave = new Sine();
wave->host = host;
envelope->initialize(host);
+ lowPass->host = host;
}
void multiply(float *target, float *modulation, uint32_t size) {
@@ -27,12 +28,16 @@
float *modulation = envelope->render(count);
float *waveform = wave->render(count);
multiply(waveform, modulation, count);
- add(buffer, waveform, count);
+ lowPass->input = waveform;
+ float *filtered = lowPass->render(count);
+ add(buffer, filtered, count);
}
void Instrument::startNote(float frequency) {
wave->setFrequency(frequency);
envelope->startNote();
+ lowPass->frequency = frequency;
+ lowPass->update();
}
void Instrument::endNote() {
diff --git a/app/src/main/cpp/Instrument.h b/app/src/main/cpp/Instrument.h
index f15d631..3ab90a8 100644
--- a/app/src/main/cpp/Instrument.h
+++ b/app/src/main/cpp/Instrument.h
@@ -6,6 +6,7 @@
#include "effects/Envelope.h"
#include "waveforms/Waveform.h"
#include "AudioHost.h"
+#include "effects/LowPass.h"
class Instrument {
private:
@@ -15,6 +16,7 @@
Envelope *const envelope = new Envelope();
Waveform *wave;
+ LowPass *lowPass = new LowPass();
void render(float *buffer, uint32_t count);
void startNote(float frequency);
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index d26ee2b..cb732f2 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -1,6 +1,7 @@
#include
#include
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
@@ -92,4 +93,19 @@
envelope->release = release;
envelope->update();
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_applyEffectAttributes(JNIEnv *env, jobject thiz,
+ jint id,
+ jint effect_number,
+ jfloat parameter1) {
+ Instrument *instrument = getInstrument(id);
+ Effect *effect;
+ switch (effect_number) {
+ case 0:
+ effect = instrument->lowPass;
+ break;
+ }
+ effect->parameter1 = parameter1;
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.cpp b/app/src/main/cpp/effects/Effect.cpp
new file mode 100644
index 0000000..881e413
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.cpp
@@ -0,0 +1 @@
+#include "Effect.h"
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.h b/app/src/main/cpp/effects/Effect.h
new file mode 100644
index 0000000..d4777f9
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.h
@@ -0,0 +1,19 @@
+#ifndef MUSIC_EFFECT_H
+#define MUSIC_EFFECT_H
+
+#include
+#include "Processable.h"
+#include "../AudioHost.h"
+
+class Effect : public Processable {
+public:
+ float parameter1, frequency;
+ float *input;
+ AudioHost *host;
+
+ virtual void doRender(uint32_t sampleCount) = 0;
+
+ virtual void update() = 0;
+};
+
+#endif
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index bf86c48..1a41dfa 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/app/src/main/cpp/AudioHost.cpp b/app/src/main/cpp/AudioHost.cpp
index 8e98b44..6727405 100644
--- a/app/src/main/cpp/AudioHost.cpp
+++ b/app/src/main/cpp/AudioHost.cpp
@@ -1,7 +1,9 @@
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
+#include
const uint32_t bufferSize = 2;
aaudio_data_callback_result_t dataCallback(
diff --git a/app/src/main/cpp/AudioHost.h b/app/src/main/cpp/AudioHost.h
index f439fdc..97446ea 100644
--- a/app/src/main/cpp/AudioHost.h
+++ b/app/src/main/cpp/AudioHost.h
@@ -3,7 +3,8 @@
class AudioHost;
-#include "Instrument.h"
+class Instrument;
+
#include
#include
diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
index b94b511..8588bed 100644
--- a/app/src/main/cpp/CMakeLists.txt
+++ b/app/src/main/cpp/CMakeLists.txt
@@ -17,6 +17,8 @@
Instrument.cpp
effects/Envelope.cpp
effects/Processable.cpp
+ effects/Effect.cpp
+ effects/LowPass.cpp
)
find_library(
diff --git a/app/src/main/cpp/Instrument.cpp b/app/src/main/cpp/Instrument.cpp
index d7263ed..985e93e 100644
--- a/app/src/main/cpp/Instrument.cpp
+++ b/app/src/main/cpp/Instrument.cpp
@@ -9,6 +9,7 @@
wave = new Sine();
wave->host = host;
envelope->initialize(host);
+ lowPass->host = host;
}
void multiply(float *target, float *modulation, uint32_t size) {
@@ -27,12 +28,16 @@
float *modulation = envelope->render(count);
float *waveform = wave->render(count);
multiply(waveform, modulation, count);
- add(buffer, waveform, count);
+ lowPass->input = waveform;
+ float *filtered = lowPass->render(count);
+ add(buffer, filtered, count);
}
void Instrument::startNote(float frequency) {
wave->setFrequency(frequency);
envelope->startNote();
+ lowPass->frequency = frequency;
+ lowPass->update();
}
void Instrument::endNote() {
diff --git a/app/src/main/cpp/Instrument.h b/app/src/main/cpp/Instrument.h
index f15d631..3ab90a8 100644
--- a/app/src/main/cpp/Instrument.h
+++ b/app/src/main/cpp/Instrument.h
@@ -6,6 +6,7 @@
#include "effects/Envelope.h"
#include "waveforms/Waveform.h"
#include "AudioHost.h"
+#include "effects/LowPass.h"
class Instrument {
private:
@@ -15,6 +16,7 @@
Envelope *const envelope = new Envelope();
Waveform *wave;
+ LowPass *lowPass = new LowPass();
void render(float *buffer, uint32_t count);
void startNote(float frequency);
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index d26ee2b..cb732f2 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -1,6 +1,7 @@
#include
#include
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
@@ -92,4 +93,19 @@
envelope->release = release;
envelope->update();
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_applyEffectAttributes(JNIEnv *env, jobject thiz,
+ jint id,
+ jint effect_number,
+ jfloat parameter1) {
+ Instrument *instrument = getInstrument(id);
+ Effect *effect;
+ switch (effect_number) {
+ case 0:
+ effect = instrument->lowPass;
+ break;
+ }
+ effect->parameter1 = parameter1;
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.cpp b/app/src/main/cpp/effects/Effect.cpp
new file mode 100644
index 0000000..881e413
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.cpp
@@ -0,0 +1 @@
+#include "Effect.h"
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.h b/app/src/main/cpp/effects/Effect.h
new file mode 100644
index 0000000..d4777f9
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.h
@@ -0,0 +1,19 @@
+#ifndef MUSIC_EFFECT_H
+#define MUSIC_EFFECT_H
+
+#include
+#include "Processable.h"
+#include "../AudioHost.h"
+
+class Effect : public Processable {
+public:
+ float parameter1, frequency;
+ float *input;
+ AudioHost *host;
+
+ virtual void doRender(uint32_t sampleCount) = 0;
+
+ virtual void update() = 0;
+};
+
+#endif
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/LowPass.cpp b/app/src/main/cpp/effects/LowPass.cpp
new file mode 100644
index 0000000..8336798
--- /dev/null
+++ b/app/src/main/cpp/effects/LowPass.cpp
@@ -0,0 +1,18 @@
+#include "../Instrument.h"
+#include
+
+// direct model of a RC-filter, R = 1 Ohm for convenience
+
+void LowPass::update() {
+ charge = 0;
+ inverseCapacitance = 2 * M_PI * frequency * pow(2, parameter1);
+ capacitance = 1 / inverseCapacitance;
+ timeStep = 1 / (float) host->sampleRate;
+}
+
+void LowPass::doRender(uint32_t sampleCount) {
+ for (uint32_t i = 0; i < sampleCount; i++) {
+ charge += (input[i] - charge * inverseCapacitance) * timeStep;
+ buffer[i] = charge * inverseCapacitance;
+ }
+}
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index bf86c48..1a41dfa 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/app/src/main/cpp/AudioHost.cpp b/app/src/main/cpp/AudioHost.cpp
index 8e98b44..6727405 100644
--- a/app/src/main/cpp/AudioHost.cpp
+++ b/app/src/main/cpp/AudioHost.cpp
@@ -1,7 +1,9 @@
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
+#include
const uint32_t bufferSize = 2;
aaudio_data_callback_result_t dataCallback(
diff --git a/app/src/main/cpp/AudioHost.h b/app/src/main/cpp/AudioHost.h
index f439fdc..97446ea 100644
--- a/app/src/main/cpp/AudioHost.h
+++ b/app/src/main/cpp/AudioHost.h
@@ -3,7 +3,8 @@
class AudioHost;
-#include "Instrument.h"
+class Instrument;
+
#include
#include
diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
index b94b511..8588bed 100644
--- a/app/src/main/cpp/CMakeLists.txt
+++ b/app/src/main/cpp/CMakeLists.txt
@@ -17,6 +17,8 @@
Instrument.cpp
effects/Envelope.cpp
effects/Processable.cpp
+ effects/Effect.cpp
+ effects/LowPass.cpp
)
find_library(
diff --git a/app/src/main/cpp/Instrument.cpp b/app/src/main/cpp/Instrument.cpp
index d7263ed..985e93e 100644
--- a/app/src/main/cpp/Instrument.cpp
+++ b/app/src/main/cpp/Instrument.cpp
@@ -9,6 +9,7 @@
wave = new Sine();
wave->host = host;
envelope->initialize(host);
+ lowPass->host = host;
}
void multiply(float *target, float *modulation, uint32_t size) {
@@ -27,12 +28,16 @@
float *modulation = envelope->render(count);
float *waveform = wave->render(count);
multiply(waveform, modulation, count);
- add(buffer, waveform, count);
+ lowPass->input = waveform;
+ float *filtered = lowPass->render(count);
+ add(buffer, filtered, count);
}
void Instrument::startNote(float frequency) {
wave->setFrequency(frequency);
envelope->startNote();
+ lowPass->frequency = frequency;
+ lowPass->update();
}
void Instrument::endNote() {
diff --git a/app/src/main/cpp/Instrument.h b/app/src/main/cpp/Instrument.h
index f15d631..3ab90a8 100644
--- a/app/src/main/cpp/Instrument.h
+++ b/app/src/main/cpp/Instrument.h
@@ -6,6 +6,7 @@
#include "effects/Envelope.h"
#include "waveforms/Waveform.h"
#include "AudioHost.h"
+#include "effects/LowPass.h"
class Instrument {
private:
@@ -15,6 +16,7 @@
Envelope *const envelope = new Envelope();
Waveform *wave;
+ LowPass *lowPass = new LowPass();
void render(float *buffer, uint32_t count);
void startNote(float frequency);
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index d26ee2b..cb732f2 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -1,6 +1,7 @@
#include
#include
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
@@ -92,4 +93,19 @@
envelope->release = release;
envelope->update();
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_applyEffectAttributes(JNIEnv *env, jobject thiz,
+ jint id,
+ jint effect_number,
+ jfloat parameter1) {
+ Instrument *instrument = getInstrument(id);
+ Effect *effect;
+ switch (effect_number) {
+ case 0:
+ effect = instrument->lowPass;
+ break;
+ }
+ effect->parameter1 = parameter1;
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.cpp b/app/src/main/cpp/effects/Effect.cpp
new file mode 100644
index 0000000..881e413
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.cpp
@@ -0,0 +1 @@
+#include "Effect.h"
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.h b/app/src/main/cpp/effects/Effect.h
new file mode 100644
index 0000000..d4777f9
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.h
@@ -0,0 +1,19 @@
+#ifndef MUSIC_EFFECT_H
+#define MUSIC_EFFECT_H
+
+#include
+#include "Processable.h"
+#include "../AudioHost.h"
+
+class Effect : public Processable {
+public:
+ float parameter1, frequency;
+ float *input;
+ AudioHost *host;
+
+ virtual void doRender(uint32_t sampleCount) = 0;
+
+ virtual void update() = 0;
+};
+
+#endif
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/LowPass.cpp b/app/src/main/cpp/effects/LowPass.cpp
new file mode 100644
index 0000000..8336798
--- /dev/null
+++ b/app/src/main/cpp/effects/LowPass.cpp
@@ -0,0 +1,18 @@
+#include "../Instrument.h"
+#include
+
+// direct model of a RC-filter, R = 1 Ohm for convenience
+
+void LowPass::update() {
+ charge = 0;
+ inverseCapacitance = 2 * M_PI * frequency * pow(2, parameter1);
+ capacitance = 1 / inverseCapacitance;
+ timeStep = 1 / (float) host->sampleRate;
+}
+
+void LowPass::doRender(uint32_t sampleCount) {
+ for (uint32_t i = 0; i < sampleCount; i++) {
+ charge += (input[i] - charge * inverseCapacitance) * timeStep;
+ buffer[i] = charge * inverseCapacitance;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/LowPass.h b/app/src/main/cpp/effects/LowPass.h
new file mode 100644
index 0000000..a285154
--- /dev/null
+++ b/app/src/main/cpp/effects/LowPass.h
@@ -0,0 +1,18 @@
+#ifndef MUSIC_LOWPASS_H
+#define MUSIC_LOWPASS_H
+
+#include "Effect.h"
+
+class LowPass : public Effect {
+private:
+ float charge = 0;
+ float capacitance = 0;
+ float inverseCapacitance = 0;
+ float timeStep = 0;
+public:
+ void update();
+
+ void doRender(uint32_t sampleCount);
+};
+
+#endif
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index bf86c48..1a41dfa 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/app/src/main/cpp/AudioHost.cpp b/app/src/main/cpp/AudioHost.cpp
index 8e98b44..6727405 100644
--- a/app/src/main/cpp/AudioHost.cpp
+++ b/app/src/main/cpp/AudioHost.cpp
@@ -1,7 +1,9 @@
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
+#include
const uint32_t bufferSize = 2;
aaudio_data_callback_result_t dataCallback(
diff --git a/app/src/main/cpp/AudioHost.h b/app/src/main/cpp/AudioHost.h
index f439fdc..97446ea 100644
--- a/app/src/main/cpp/AudioHost.h
+++ b/app/src/main/cpp/AudioHost.h
@@ -3,7 +3,8 @@
class AudioHost;
-#include "Instrument.h"
+class Instrument;
+
#include
#include
diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
index b94b511..8588bed 100644
--- a/app/src/main/cpp/CMakeLists.txt
+++ b/app/src/main/cpp/CMakeLists.txt
@@ -17,6 +17,8 @@
Instrument.cpp
effects/Envelope.cpp
effects/Processable.cpp
+ effects/Effect.cpp
+ effects/LowPass.cpp
)
find_library(
diff --git a/app/src/main/cpp/Instrument.cpp b/app/src/main/cpp/Instrument.cpp
index d7263ed..985e93e 100644
--- a/app/src/main/cpp/Instrument.cpp
+++ b/app/src/main/cpp/Instrument.cpp
@@ -9,6 +9,7 @@
wave = new Sine();
wave->host = host;
envelope->initialize(host);
+ lowPass->host = host;
}
void multiply(float *target, float *modulation, uint32_t size) {
@@ -27,12 +28,16 @@
float *modulation = envelope->render(count);
float *waveform = wave->render(count);
multiply(waveform, modulation, count);
- add(buffer, waveform, count);
+ lowPass->input = waveform;
+ float *filtered = lowPass->render(count);
+ add(buffer, filtered, count);
}
void Instrument::startNote(float frequency) {
wave->setFrequency(frequency);
envelope->startNote();
+ lowPass->frequency = frequency;
+ lowPass->update();
}
void Instrument::endNote() {
diff --git a/app/src/main/cpp/Instrument.h b/app/src/main/cpp/Instrument.h
index f15d631..3ab90a8 100644
--- a/app/src/main/cpp/Instrument.h
+++ b/app/src/main/cpp/Instrument.h
@@ -6,6 +6,7 @@
#include "effects/Envelope.h"
#include "waveforms/Waveform.h"
#include "AudioHost.h"
+#include "effects/LowPass.h"
class Instrument {
private:
@@ -15,6 +16,7 @@
Envelope *const envelope = new Envelope();
Waveform *wave;
+ LowPass *lowPass = new LowPass();
void render(float *buffer, uint32_t count);
void startNote(float frequency);
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index d26ee2b..cb732f2 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -1,6 +1,7 @@
#include
#include
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
@@ -92,4 +93,19 @@
envelope->release = release;
envelope->update();
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_applyEffectAttributes(JNIEnv *env, jobject thiz,
+ jint id,
+ jint effect_number,
+ jfloat parameter1) {
+ Instrument *instrument = getInstrument(id);
+ Effect *effect;
+ switch (effect_number) {
+ case 0:
+ effect = instrument->lowPass;
+ break;
+ }
+ effect->parameter1 = parameter1;
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.cpp b/app/src/main/cpp/effects/Effect.cpp
new file mode 100644
index 0000000..881e413
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.cpp
@@ -0,0 +1 @@
+#include "Effect.h"
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.h b/app/src/main/cpp/effects/Effect.h
new file mode 100644
index 0000000..d4777f9
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.h
@@ -0,0 +1,19 @@
+#ifndef MUSIC_EFFECT_H
+#define MUSIC_EFFECT_H
+
+#include
+#include "Processable.h"
+#include "../AudioHost.h"
+
+class Effect : public Processable {
+public:
+ float parameter1, frequency;
+ float *input;
+ AudioHost *host;
+
+ virtual void doRender(uint32_t sampleCount) = 0;
+
+ virtual void update() = 0;
+};
+
+#endif
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/LowPass.cpp b/app/src/main/cpp/effects/LowPass.cpp
new file mode 100644
index 0000000..8336798
--- /dev/null
+++ b/app/src/main/cpp/effects/LowPass.cpp
@@ -0,0 +1,18 @@
+#include "../Instrument.h"
+#include
+
+// direct model of a RC-filter, R = 1 Ohm for convenience
+
+void LowPass::update() {
+ charge = 0;
+ inverseCapacitance = 2 * M_PI * frequency * pow(2, parameter1);
+ capacitance = 1 / inverseCapacitance;
+ timeStep = 1 / (float) host->sampleRate;
+}
+
+void LowPass::doRender(uint32_t sampleCount) {
+ for (uint32_t i = 0; i < sampleCount; i++) {
+ charge += (input[i] - charge * inverseCapacitance) * timeStep;
+ buffer[i] = charge * inverseCapacitance;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/LowPass.h b/app/src/main/cpp/effects/LowPass.h
new file mode 100644
index 0000000..a285154
--- /dev/null
+++ b/app/src/main/cpp/effects/LowPass.h
@@ -0,0 +1,18 @@
+#ifndef MUSIC_LOWPASS_H
+#define MUSIC_LOWPASS_H
+
+#include "Effect.h"
+
+class LowPass : public Effect {
+private:
+ float charge = 0;
+ float capacitance = 0;
+ float inverseCapacitance = 0;
+ float timeStep = 0;
+public:
+ void update();
+
+ void doRender(uint32_t sampleCount);
+};
+
+#endif
\ 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 53ec4ad..46957ee 100644
--- a/app/src/main/java/com/lukas/music/instruments/Instrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
@@ -20,7 +20,7 @@
var voice: Voice = BassVoice(this)
var envelope = Envelope(this)
val effects = Array(EffectType.VALUES.size) {
- Effect(EffectType.VALUES[it])
+ Effect(EffectType.VALUES[it], this)
}
abstract var waveform: Waveform
@@ -32,6 +32,7 @@
abstract fun stopNote(note: Note)
abstract fun destroy()
abstract fun updateEnvelope()
+ abstract fun updateEffects()
companion object {
val instruments = mutableListOf()
diff --git a/.idea/misc.xml b/.idea/misc.xml
index bf86c48..1a41dfa 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/app/src/main/cpp/AudioHost.cpp b/app/src/main/cpp/AudioHost.cpp
index 8e98b44..6727405 100644
--- a/app/src/main/cpp/AudioHost.cpp
+++ b/app/src/main/cpp/AudioHost.cpp
@@ -1,7 +1,9 @@
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
+#include
const uint32_t bufferSize = 2;
aaudio_data_callback_result_t dataCallback(
diff --git a/app/src/main/cpp/AudioHost.h b/app/src/main/cpp/AudioHost.h
index f439fdc..97446ea 100644
--- a/app/src/main/cpp/AudioHost.h
+++ b/app/src/main/cpp/AudioHost.h
@@ -3,7 +3,8 @@
class AudioHost;
-#include "Instrument.h"
+class Instrument;
+
#include
#include
diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
index b94b511..8588bed 100644
--- a/app/src/main/cpp/CMakeLists.txt
+++ b/app/src/main/cpp/CMakeLists.txt
@@ -17,6 +17,8 @@
Instrument.cpp
effects/Envelope.cpp
effects/Processable.cpp
+ effects/Effect.cpp
+ effects/LowPass.cpp
)
find_library(
diff --git a/app/src/main/cpp/Instrument.cpp b/app/src/main/cpp/Instrument.cpp
index d7263ed..985e93e 100644
--- a/app/src/main/cpp/Instrument.cpp
+++ b/app/src/main/cpp/Instrument.cpp
@@ -9,6 +9,7 @@
wave = new Sine();
wave->host = host;
envelope->initialize(host);
+ lowPass->host = host;
}
void multiply(float *target, float *modulation, uint32_t size) {
@@ -27,12 +28,16 @@
float *modulation = envelope->render(count);
float *waveform = wave->render(count);
multiply(waveform, modulation, count);
- add(buffer, waveform, count);
+ lowPass->input = waveform;
+ float *filtered = lowPass->render(count);
+ add(buffer, filtered, count);
}
void Instrument::startNote(float frequency) {
wave->setFrequency(frequency);
envelope->startNote();
+ lowPass->frequency = frequency;
+ lowPass->update();
}
void Instrument::endNote() {
diff --git a/app/src/main/cpp/Instrument.h b/app/src/main/cpp/Instrument.h
index f15d631..3ab90a8 100644
--- a/app/src/main/cpp/Instrument.h
+++ b/app/src/main/cpp/Instrument.h
@@ -6,6 +6,7 @@
#include "effects/Envelope.h"
#include "waveforms/Waveform.h"
#include "AudioHost.h"
+#include "effects/LowPass.h"
class Instrument {
private:
@@ -15,6 +16,7 @@
Envelope *const envelope = new Envelope();
Waveform *wave;
+ LowPass *lowPass = new LowPass();
void render(float *buffer, uint32_t count);
void startNote(float frequency);
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index d26ee2b..cb732f2 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -1,6 +1,7 @@
#include
#include
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
@@ -92,4 +93,19 @@
envelope->release = release;
envelope->update();
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_applyEffectAttributes(JNIEnv *env, jobject thiz,
+ jint id,
+ jint effect_number,
+ jfloat parameter1) {
+ Instrument *instrument = getInstrument(id);
+ Effect *effect;
+ switch (effect_number) {
+ case 0:
+ effect = instrument->lowPass;
+ break;
+ }
+ effect->parameter1 = parameter1;
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.cpp b/app/src/main/cpp/effects/Effect.cpp
new file mode 100644
index 0000000..881e413
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.cpp
@@ -0,0 +1 @@
+#include "Effect.h"
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.h b/app/src/main/cpp/effects/Effect.h
new file mode 100644
index 0000000..d4777f9
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.h
@@ -0,0 +1,19 @@
+#ifndef MUSIC_EFFECT_H
+#define MUSIC_EFFECT_H
+
+#include
+#include "Processable.h"
+#include "../AudioHost.h"
+
+class Effect : public Processable {
+public:
+ float parameter1, frequency;
+ float *input;
+ AudioHost *host;
+
+ virtual void doRender(uint32_t sampleCount) = 0;
+
+ virtual void update() = 0;
+};
+
+#endif
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/LowPass.cpp b/app/src/main/cpp/effects/LowPass.cpp
new file mode 100644
index 0000000..8336798
--- /dev/null
+++ b/app/src/main/cpp/effects/LowPass.cpp
@@ -0,0 +1,18 @@
+#include "../Instrument.h"
+#include
+
+// direct model of a RC-filter, R = 1 Ohm for convenience
+
+void LowPass::update() {
+ charge = 0;
+ inverseCapacitance = 2 * M_PI * frequency * pow(2, parameter1);
+ capacitance = 1 / inverseCapacitance;
+ timeStep = 1 / (float) host->sampleRate;
+}
+
+void LowPass::doRender(uint32_t sampleCount) {
+ for (uint32_t i = 0; i < sampleCount; i++) {
+ charge += (input[i] - charge * inverseCapacitance) * timeStep;
+ buffer[i] = charge * inverseCapacitance;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/LowPass.h b/app/src/main/cpp/effects/LowPass.h
new file mode 100644
index 0000000..a285154
--- /dev/null
+++ b/app/src/main/cpp/effects/LowPass.h
@@ -0,0 +1,18 @@
+#ifndef MUSIC_LOWPASS_H
+#define MUSIC_LOWPASS_H
+
+#include "Effect.h"
+
+class LowPass : public Effect {
+private:
+ float charge = 0;
+ float capacitance = 0;
+ float inverseCapacitance = 0;
+ float timeStep = 0;
+public:
+ void update();
+
+ void doRender(uint32_t sampleCount);
+};
+
+#endif
\ 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 53ec4ad..46957ee 100644
--- a/app/src/main/java/com/lukas/music/instruments/Instrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
@@ -20,7 +20,7 @@
var voice: Voice = BassVoice(this)
var envelope = Envelope(this)
val effects = Array(EffectType.VALUES.size) {
- Effect(EffectType.VALUES[it])
+ Effect(EffectType.VALUES[it], this)
}
abstract var waveform: Waveform
@@ -32,6 +32,7 @@
abstract fun stopNote(note: Note)
abstract fun destroy()
abstract fun updateEnvelope()
+ abstract fun updateEffects()
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 946e653..f7983ad 100644
--- a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
@@ -10,6 +10,7 @@
package com.lukas.music.instruments
+import com.lukas.music.instruments.effect.Effect
import com.lukas.music.song.note.Note
class InternalInstrument {
@@ -77,6 +78,10 @@
)
}
+ fun applyEffectAttributes(effect: Effect) {
+ applyEffectAttributes(id, effect.type.ordinal, effect.parameter1)
+ }
+
private external fun createInstrument(): Int
private external fun setInstrumentWaveform(id: Int, waveform: Int)
private external fun startNote(id: Int, frequency: Double)
@@ -90,4 +95,6 @@
sustain: Float,
release: Float
)
+
+ private external fun applyEffectAttributes(id: Int, effectNumber: Int, parameter1: Float)
}
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index bf86c48..1a41dfa 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/app/src/main/cpp/AudioHost.cpp b/app/src/main/cpp/AudioHost.cpp
index 8e98b44..6727405 100644
--- a/app/src/main/cpp/AudioHost.cpp
+++ b/app/src/main/cpp/AudioHost.cpp
@@ -1,7 +1,9 @@
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
+#include
const uint32_t bufferSize = 2;
aaudio_data_callback_result_t dataCallback(
diff --git a/app/src/main/cpp/AudioHost.h b/app/src/main/cpp/AudioHost.h
index f439fdc..97446ea 100644
--- a/app/src/main/cpp/AudioHost.h
+++ b/app/src/main/cpp/AudioHost.h
@@ -3,7 +3,8 @@
class AudioHost;
-#include "Instrument.h"
+class Instrument;
+
#include
#include
diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
index b94b511..8588bed 100644
--- a/app/src/main/cpp/CMakeLists.txt
+++ b/app/src/main/cpp/CMakeLists.txt
@@ -17,6 +17,8 @@
Instrument.cpp
effects/Envelope.cpp
effects/Processable.cpp
+ effects/Effect.cpp
+ effects/LowPass.cpp
)
find_library(
diff --git a/app/src/main/cpp/Instrument.cpp b/app/src/main/cpp/Instrument.cpp
index d7263ed..985e93e 100644
--- a/app/src/main/cpp/Instrument.cpp
+++ b/app/src/main/cpp/Instrument.cpp
@@ -9,6 +9,7 @@
wave = new Sine();
wave->host = host;
envelope->initialize(host);
+ lowPass->host = host;
}
void multiply(float *target, float *modulation, uint32_t size) {
@@ -27,12 +28,16 @@
float *modulation = envelope->render(count);
float *waveform = wave->render(count);
multiply(waveform, modulation, count);
- add(buffer, waveform, count);
+ lowPass->input = waveform;
+ float *filtered = lowPass->render(count);
+ add(buffer, filtered, count);
}
void Instrument::startNote(float frequency) {
wave->setFrequency(frequency);
envelope->startNote();
+ lowPass->frequency = frequency;
+ lowPass->update();
}
void Instrument::endNote() {
diff --git a/app/src/main/cpp/Instrument.h b/app/src/main/cpp/Instrument.h
index f15d631..3ab90a8 100644
--- a/app/src/main/cpp/Instrument.h
+++ b/app/src/main/cpp/Instrument.h
@@ -6,6 +6,7 @@
#include "effects/Envelope.h"
#include "waveforms/Waveform.h"
#include "AudioHost.h"
+#include "effects/LowPass.h"
class Instrument {
private:
@@ -15,6 +16,7 @@
Envelope *const envelope = new Envelope();
Waveform *wave;
+ LowPass *lowPass = new LowPass();
void render(float *buffer, uint32_t count);
void startNote(float frequency);
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index d26ee2b..cb732f2 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -1,6 +1,7 @@
#include
#include
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
@@ -92,4 +93,19 @@
envelope->release = release;
envelope->update();
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_applyEffectAttributes(JNIEnv *env, jobject thiz,
+ jint id,
+ jint effect_number,
+ jfloat parameter1) {
+ Instrument *instrument = getInstrument(id);
+ Effect *effect;
+ switch (effect_number) {
+ case 0:
+ effect = instrument->lowPass;
+ break;
+ }
+ effect->parameter1 = parameter1;
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.cpp b/app/src/main/cpp/effects/Effect.cpp
new file mode 100644
index 0000000..881e413
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.cpp
@@ -0,0 +1 @@
+#include "Effect.h"
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.h b/app/src/main/cpp/effects/Effect.h
new file mode 100644
index 0000000..d4777f9
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.h
@@ -0,0 +1,19 @@
+#ifndef MUSIC_EFFECT_H
+#define MUSIC_EFFECT_H
+
+#include
+#include "Processable.h"
+#include "../AudioHost.h"
+
+class Effect : public Processable {
+public:
+ float parameter1, frequency;
+ float *input;
+ AudioHost *host;
+
+ virtual void doRender(uint32_t sampleCount) = 0;
+
+ virtual void update() = 0;
+};
+
+#endif
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/LowPass.cpp b/app/src/main/cpp/effects/LowPass.cpp
new file mode 100644
index 0000000..8336798
--- /dev/null
+++ b/app/src/main/cpp/effects/LowPass.cpp
@@ -0,0 +1,18 @@
+#include "../Instrument.h"
+#include
+
+// direct model of a RC-filter, R = 1 Ohm for convenience
+
+void LowPass::update() {
+ charge = 0;
+ inverseCapacitance = 2 * M_PI * frequency * pow(2, parameter1);
+ capacitance = 1 / inverseCapacitance;
+ timeStep = 1 / (float) host->sampleRate;
+}
+
+void LowPass::doRender(uint32_t sampleCount) {
+ for (uint32_t i = 0; i < sampleCount; i++) {
+ charge += (input[i] - charge * inverseCapacitance) * timeStep;
+ buffer[i] = charge * inverseCapacitance;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/LowPass.h b/app/src/main/cpp/effects/LowPass.h
new file mode 100644
index 0000000..a285154
--- /dev/null
+++ b/app/src/main/cpp/effects/LowPass.h
@@ -0,0 +1,18 @@
+#ifndef MUSIC_LOWPASS_H
+#define MUSIC_LOWPASS_H
+
+#include "Effect.h"
+
+class LowPass : public Effect {
+private:
+ float charge = 0;
+ float capacitance = 0;
+ float inverseCapacitance = 0;
+ float timeStep = 0;
+public:
+ void update();
+
+ void doRender(uint32_t sampleCount);
+};
+
+#endif
\ 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 53ec4ad..46957ee 100644
--- a/app/src/main/java/com/lukas/music/instruments/Instrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
@@ -20,7 +20,7 @@
var voice: Voice = BassVoice(this)
var envelope = Envelope(this)
val effects = Array(EffectType.VALUES.size) {
- Effect(EffectType.VALUES[it])
+ Effect(EffectType.VALUES[it], this)
}
abstract var waveform: Waveform
@@ -32,6 +32,7 @@
abstract fun stopNote(note: Note)
abstract fun destroy()
abstract fun updateEnvelope()
+ abstract fun updateEffects()
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 946e653..f7983ad 100644
--- a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
@@ -10,6 +10,7 @@
package com.lukas.music.instruments
+import com.lukas.music.instruments.effect.Effect
import com.lukas.music.song.note.Note
class InternalInstrument {
@@ -77,6 +78,10 @@
)
}
+ fun applyEffectAttributes(effect: Effect) {
+ applyEffectAttributes(id, effect.type.ordinal, effect.parameter1)
+ }
+
private external fun createInstrument(): Int
private external fun setInstrumentWaveform(id: Int, waveform: Int)
private external fun startNote(id: Int, frequency: Double)
@@ -90,4 +95,6 @@
sustain: Float,
release: Float
)
+
+ private external fun applyEffectAttributes(id: Int, effectNumber: Int, parameter1: 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 a9b5c53..3526e60 100644
--- a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
@@ -57,4 +57,10 @@
override fun updateEnvelope() {
internalInstrument.applyEnvelope(envelope)
}
+
+ override fun updateEffects() {
+ for (effect in effects) {
+ internalInstrument.applyEffectAttributes(effect)
+ }
+ }
}
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index bf86c48..1a41dfa 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/app/src/main/cpp/AudioHost.cpp b/app/src/main/cpp/AudioHost.cpp
index 8e98b44..6727405 100644
--- a/app/src/main/cpp/AudioHost.cpp
+++ b/app/src/main/cpp/AudioHost.cpp
@@ -1,7 +1,9 @@
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
+#include
const uint32_t bufferSize = 2;
aaudio_data_callback_result_t dataCallback(
diff --git a/app/src/main/cpp/AudioHost.h b/app/src/main/cpp/AudioHost.h
index f439fdc..97446ea 100644
--- a/app/src/main/cpp/AudioHost.h
+++ b/app/src/main/cpp/AudioHost.h
@@ -3,7 +3,8 @@
class AudioHost;
-#include "Instrument.h"
+class Instrument;
+
#include
#include
diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
index b94b511..8588bed 100644
--- a/app/src/main/cpp/CMakeLists.txt
+++ b/app/src/main/cpp/CMakeLists.txt
@@ -17,6 +17,8 @@
Instrument.cpp
effects/Envelope.cpp
effects/Processable.cpp
+ effects/Effect.cpp
+ effects/LowPass.cpp
)
find_library(
diff --git a/app/src/main/cpp/Instrument.cpp b/app/src/main/cpp/Instrument.cpp
index d7263ed..985e93e 100644
--- a/app/src/main/cpp/Instrument.cpp
+++ b/app/src/main/cpp/Instrument.cpp
@@ -9,6 +9,7 @@
wave = new Sine();
wave->host = host;
envelope->initialize(host);
+ lowPass->host = host;
}
void multiply(float *target, float *modulation, uint32_t size) {
@@ -27,12 +28,16 @@
float *modulation = envelope->render(count);
float *waveform = wave->render(count);
multiply(waveform, modulation, count);
- add(buffer, waveform, count);
+ lowPass->input = waveform;
+ float *filtered = lowPass->render(count);
+ add(buffer, filtered, count);
}
void Instrument::startNote(float frequency) {
wave->setFrequency(frequency);
envelope->startNote();
+ lowPass->frequency = frequency;
+ lowPass->update();
}
void Instrument::endNote() {
diff --git a/app/src/main/cpp/Instrument.h b/app/src/main/cpp/Instrument.h
index f15d631..3ab90a8 100644
--- a/app/src/main/cpp/Instrument.h
+++ b/app/src/main/cpp/Instrument.h
@@ -6,6 +6,7 @@
#include "effects/Envelope.h"
#include "waveforms/Waveform.h"
#include "AudioHost.h"
+#include "effects/LowPass.h"
class Instrument {
private:
@@ -15,6 +16,7 @@
Envelope *const envelope = new Envelope();
Waveform *wave;
+ LowPass *lowPass = new LowPass();
void render(float *buffer, uint32_t count);
void startNote(float frequency);
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index d26ee2b..cb732f2 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -1,6 +1,7 @@
#include
#include
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
@@ -92,4 +93,19 @@
envelope->release = release;
envelope->update();
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_applyEffectAttributes(JNIEnv *env, jobject thiz,
+ jint id,
+ jint effect_number,
+ jfloat parameter1) {
+ Instrument *instrument = getInstrument(id);
+ Effect *effect;
+ switch (effect_number) {
+ case 0:
+ effect = instrument->lowPass;
+ break;
+ }
+ effect->parameter1 = parameter1;
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.cpp b/app/src/main/cpp/effects/Effect.cpp
new file mode 100644
index 0000000..881e413
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.cpp
@@ -0,0 +1 @@
+#include "Effect.h"
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.h b/app/src/main/cpp/effects/Effect.h
new file mode 100644
index 0000000..d4777f9
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.h
@@ -0,0 +1,19 @@
+#ifndef MUSIC_EFFECT_H
+#define MUSIC_EFFECT_H
+
+#include
+#include "Processable.h"
+#include "../AudioHost.h"
+
+class Effect : public Processable {
+public:
+ float parameter1, frequency;
+ float *input;
+ AudioHost *host;
+
+ virtual void doRender(uint32_t sampleCount) = 0;
+
+ virtual void update() = 0;
+};
+
+#endif
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/LowPass.cpp b/app/src/main/cpp/effects/LowPass.cpp
new file mode 100644
index 0000000..8336798
--- /dev/null
+++ b/app/src/main/cpp/effects/LowPass.cpp
@@ -0,0 +1,18 @@
+#include "../Instrument.h"
+#include
+
+// direct model of a RC-filter, R = 1 Ohm for convenience
+
+void LowPass::update() {
+ charge = 0;
+ inverseCapacitance = 2 * M_PI * frequency * pow(2, parameter1);
+ capacitance = 1 / inverseCapacitance;
+ timeStep = 1 / (float) host->sampleRate;
+}
+
+void LowPass::doRender(uint32_t sampleCount) {
+ for (uint32_t i = 0; i < sampleCount; i++) {
+ charge += (input[i] - charge * inverseCapacitance) * timeStep;
+ buffer[i] = charge * inverseCapacitance;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/LowPass.h b/app/src/main/cpp/effects/LowPass.h
new file mode 100644
index 0000000..a285154
--- /dev/null
+++ b/app/src/main/cpp/effects/LowPass.h
@@ -0,0 +1,18 @@
+#ifndef MUSIC_LOWPASS_H
+#define MUSIC_LOWPASS_H
+
+#include "Effect.h"
+
+class LowPass : public Effect {
+private:
+ float charge = 0;
+ float capacitance = 0;
+ float inverseCapacitance = 0;
+ float timeStep = 0;
+public:
+ void update();
+
+ void doRender(uint32_t sampleCount);
+};
+
+#endif
\ 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 53ec4ad..46957ee 100644
--- a/app/src/main/java/com/lukas/music/instruments/Instrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
@@ -20,7 +20,7 @@
var voice: Voice = BassVoice(this)
var envelope = Envelope(this)
val effects = Array(EffectType.VALUES.size) {
- Effect(EffectType.VALUES[it])
+ Effect(EffectType.VALUES[it], this)
}
abstract var waveform: Waveform
@@ -32,6 +32,7 @@
abstract fun stopNote(note: Note)
abstract fun destroy()
abstract fun updateEnvelope()
+ abstract fun updateEffects()
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 946e653..f7983ad 100644
--- a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
@@ -10,6 +10,7 @@
package com.lukas.music.instruments
+import com.lukas.music.instruments.effect.Effect
import com.lukas.music.song.note.Note
class InternalInstrument {
@@ -77,6 +78,10 @@
)
}
+ fun applyEffectAttributes(effect: Effect) {
+ applyEffectAttributes(id, effect.type.ordinal, effect.parameter1)
+ }
+
private external fun createInstrument(): Int
private external fun setInstrumentWaveform(id: Int, waveform: Int)
private external fun startNote(id: Int, frequency: Double)
@@ -90,4 +95,6 @@
sustain: Float,
release: Float
)
+
+ private external fun applyEffectAttributes(id: Int, effectNumber: Int, parameter1: 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 a9b5c53..3526e60 100644
--- a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
@@ -57,4 +57,10 @@
override fun updateEnvelope() {
internalInstrument.applyEnvelope(envelope)
}
+
+ override fun updateEffects() {
+ for (effect in effects) {
+ internalInstrument.applyEffectAttributes(effect)
+ }
+ }
}
\ 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 8f055d0..70ba98a 100644
--- a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
@@ -81,4 +81,12 @@
instrument.applyEnvelope(envelope)
}
}
+
+ override fun updateEffects() {
+ for (instrument in internalInstruments) {
+ for (effect in effects) {
+ instrument.applyEffectAttributes(effect)
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index bf86c48..1a41dfa 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/app/src/main/cpp/AudioHost.cpp b/app/src/main/cpp/AudioHost.cpp
index 8e98b44..6727405 100644
--- a/app/src/main/cpp/AudioHost.cpp
+++ b/app/src/main/cpp/AudioHost.cpp
@@ -1,7 +1,9 @@
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
+#include
const uint32_t bufferSize = 2;
aaudio_data_callback_result_t dataCallback(
diff --git a/app/src/main/cpp/AudioHost.h b/app/src/main/cpp/AudioHost.h
index f439fdc..97446ea 100644
--- a/app/src/main/cpp/AudioHost.h
+++ b/app/src/main/cpp/AudioHost.h
@@ -3,7 +3,8 @@
class AudioHost;
-#include "Instrument.h"
+class Instrument;
+
#include
#include
diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
index b94b511..8588bed 100644
--- a/app/src/main/cpp/CMakeLists.txt
+++ b/app/src/main/cpp/CMakeLists.txt
@@ -17,6 +17,8 @@
Instrument.cpp
effects/Envelope.cpp
effects/Processable.cpp
+ effects/Effect.cpp
+ effects/LowPass.cpp
)
find_library(
diff --git a/app/src/main/cpp/Instrument.cpp b/app/src/main/cpp/Instrument.cpp
index d7263ed..985e93e 100644
--- a/app/src/main/cpp/Instrument.cpp
+++ b/app/src/main/cpp/Instrument.cpp
@@ -9,6 +9,7 @@
wave = new Sine();
wave->host = host;
envelope->initialize(host);
+ lowPass->host = host;
}
void multiply(float *target, float *modulation, uint32_t size) {
@@ -27,12 +28,16 @@
float *modulation = envelope->render(count);
float *waveform = wave->render(count);
multiply(waveform, modulation, count);
- add(buffer, waveform, count);
+ lowPass->input = waveform;
+ float *filtered = lowPass->render(count);
+ add(buffer, filtered, count);
}
void Instrument::startNote(float frequency) {
wave->setFrequency(frequency);
envelope->startNote();
+ lowPass->frequency = frequency;
+ lowPass->update();
}
void Instrument::endNote() {
diff --git a/app/src/main/cpp/Instrument.h b/app/src/main/cpp/Instrument.h
index f15d631..3ab90a8 100644
--- a/app/src/main/cpp/Instrument.h
+++ b/app/src/main/cpp/Instrument.h
@@ -6,6 +6,7 @@
#include "effects/Envelope.h"
#include "waveforms/Waveform.h"
#include "AudioHost.h"
+#include "effects/LowPass.h"
class Instrument {
private:
@@ -15,6 +16,7 @@
Envelope *const envelope = new Envelope();
Waveform *wave;
+ LowPass *lowPass = new LowPass();
void render(float *buffer, uint32_t count);
void startNote(float frequency);
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index d26ee2b..cb732f2 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -1,6 +1,7 @@
#include
#include
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
@@ -92,4 +93,19 @@
envelope->release = release;
envelope->update();
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_applyEffectAttributes(JNIEnv *env, jobject thiz,
+ jint id,
+ jint effect_number,
+ jfloat parameter1) {
+ Instrument *instrument = getInstrument(id);
+ Effect *effect;
+ switch (effect_number) {
+ case 0:
+ effect = instrument->lowPass;
+ break;
+ }
+ effect->parameter1 = parameter1;
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.cpp b/app/src/main/cpp/effects/Effect.cpp
new file mode 100644
index 0000000..881e413
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.cpp
@@ -0,0 +1 @@
+#include "Effect.h"
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.h b/app/src/main/cpp/effects/Effect.h
new file mode 100644
index 0000000..d4777f9
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.h
@@ -0,0 +1,19 @@
+#ifndef MUSIC_EFFECT_H
+#define MUSIC_EFFECT_H
+
+#include
+#include "Processable.h"
+#include "../AudioHost.h"
+
+class Effect : public Processable {
+public:
+ float parameter1, frequency;
+ float *input;
+ AudioHost *host;
+
+ virtual void doRender(uint32_t sampleCount) = 0;
+
+ virtual void update() = 0;
+};
+
+#endif
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/LowPass.cpp b/app/src/main/cpp/effects/LowPass.cpp
new file mode 100644
index 0000000..8336798
--- /dev/null
+++ b/app/src/main/cpp/effects/LowPass.cpp
@@ -0,0 +1,18 @@
+#include "../Instrument.h"
+#include
+
+// direct model of a RC-filter, R = 1 Ohm for convenience
+
+void LowPass::update() {
+ charge = 0;
+ inverseCapacitance = 2 * M_PI * frequency * pow(2, parameter1);
+ capacitance = 1 / inverseCapacitance;
+ timeStep = 1 / (float) host->sampleRate;
+}
+
+void LowPass::doRender(uint32_t sampleCount) {
+ for (uint32_t i = 0; i < sampleCount; i++) {
+ charge += (input[i] - charge * inverseCapacitance) * timeStep;
+ buffer[i] = charge * inverseCapacitance;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/LowPass.h b/app/src/main/cpp/effects/LowPass.h
new file mode 100644
index 0000000..a285154
--- /dev/null
+++ b/app/src/main/cpp/effects/LowPass.h
@@ -0,0 +1,18 @@
+#ifndef MUSIC_LOWPASS_H
+#define MUSIC_LOWPASS_H
+
+#include "Effect.h"
+
+class LowPass : public Effect {
+private:
+ float charge = 0;
+ float capacitance = 0;
+ float inverseCapacitance = 0;
+ float timeStep = 0;
+public:
+ void update();
+
+ void doRender(uint32_t sampleCount);
+};
+
+#endif
\ 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 53ec4ad..46957ee 100644
--- a/app/src/main/java/com/lukas/music/instruments/Instrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
@@ -20,7 +20,7 @@
var voice: Voice = BassVoice(this)
var envelope = Envelope(this)
val effects = Array(EffectType.VALUES.size) {
- Effect(EffectType.VALUES[it])
+ Effect(EffectType.VALUES[it], this)
}
abstract var waveform: Waveform
@@ -32,6 +32,7 @@
abstract fun stopNote(note: Note)
abstract fun destroy()
abstract fun updateEnvelope()
+ abstract fun updateEffects()
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 946e653..f7983ad 100644
--- a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
@@ -10,6 +10,7 @@
package com.lukas.music.instruments
+import com.lukas.music.instruments.effect.Effect
import com.lukas.music.song.note.Note
class InternalInstrument {
@@ -77,6 +78,10 @@
)
}
+ fun applyEffectAttributes(effect: Effect) {
+ applyEffectAttributes(id, effect.type.ordinal, effect.parameter1)
+ }
+
private external fun createInstrument(): Int
private external fun setInstrumentWaveform(id: Int, waveform: Int)
private external fun startNote(id: Int, frequency: Double)
@@ -90,4 +95,6 @@
sustain: Float,
release: Float
)
+
+ private external fun applyEffectAttributes(id: Int, effectNumber: Int, parameter1: 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 a9b5c53..3526e60 100644
--- a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
@@ -57,4 +57,10 @@
override fun updateEnvelope() {
internalInstrument.applyEnvelope(envelope)
}
+
+ override fun updateEffects() {
+ for (effect in effects) {
+ internalInstrument.applyEffectAttributes(effect)
+ }
+ }
}
\ 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 8f055d0..70ba98a 100644
--- a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
@@ -81,4 +81,12 @@
instrument.applyEnvelope(envelope)
}
}
+
+ override fun updateEffects() {
+ for (instrument in internalInstruments) {
+ for (effect in effects) {
+ instrument.applyEffectAttributes(effect)
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/effect/Effect.kt b/app/src/main/java/com/lukas/music/instruments/effect/Effect.kt
index ebc64d1..8a3c4eb 100644
--- a/app/src/main/java/com/lukas/music/instruments/effect/Effect.kt
+++ b/app/src/main/java/com/lukas/music/instruments/effect/Effect.kt
@@ -10,4 +10,17 @@
package com.lukas.music.instruments.effect
-class Effect(val type: EffectType)
\ No newline at end of file
+import com.lukas.music.instruments.Instrument
+
+class Effect(val type: EffectType, private val instrument: Instrument) {
+ var parameter1: Float = 1.0f
+ set(value) {
+ field = value
+ instrument.updateEffects()
+ }
+ var parameter1Percent: Int
+ get() = (parameter1 * 100).toInt()
+ set(value) {
+ parameter1 = value.toFloat() / 100f
+ }
+}
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index bf86c48..1a41dfa 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/app/src/main/cpp/AudioHost.cpp b/app/src/main/cpp/AudioHost.cpp
index 8e98b44..6727405 100644
--- a/app/src/main/cpp/AudioHost.cpp
+++ b/app/src/main/cpp/AudioHost.cpp
@@ -1,7 +1,9 @@
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
+#include
const uint32_t bufferSize = 2;
aaudio_data_callback_result_t dataCallback(
diff --git a/app/src/main/cpp/AudioHost.h b/app/src/main/cpp/AudioHost.h
index f439fdc..97446ea 100644
--- a/app/src/main/cpp/AudioHost.h
+++ b/app/src/main/cpp/AudioHost.h
@@ -3,7 +3,8 @@
class AudioHost;
-#include "Instrument.h"
+class Instrument;
+
#include
#include
diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
index b94b511..8588bed 100644
--- a/app/src/main/cpp/CMakeLists.txt
+++ b/app/src/main/cpp/CMakeLists.txt
@@ -17,6 +17,8 @@
Instrument.cpp
effects/Envelope.cpp
effects/Processable.cpp
+ effects/Effect.cpp
+ effects/LowPass.cpp
)
find_library(
diff --git a/app/src/main/cpp/Instrument.cpp b/app/src/main/cpp/Instrument.cpp
index d7263ed..985e93e 100644
--- a/app/src/main/cpp/Instrument.cpp
+++ b/app/src/main/cpp/Instrument.cpp
@@ -9,6 +9,7 @@
wave = new Sine();
wave->host = host;
envelope->initialize(host);
+ lowPass->host = host;
}
void multiply(float *target, float *modulation, uint32_t size) {
@@ -27,12 +28,16 @@
float *modulation = envelope->render(count);
float *waveform = wave->render(count);
multiply(waveform, modulation, count);
- add(buffer, waveform, count);
+ lowPass->input = waveform;
+ float *filtered = lowPass->render(count);
+ add(buffer, filtered, count);
}
void Instrument::startNote(float frequency) {
wave->setFrequency(frequency);
envelope->startNote();
+ lowPass->frequency = frequency;
+ lowPass->update();
}
void Instrument::endNote() {
diff --git a/app/src/main/cpp/Instrument.h b/app/src/main/cpp/Instrument.h
index f15d631..3ab90a8 100644
--- a/app/src/main/cpp/Instrument.h
+++ b/app/src/main/cpp/Instrument.h
@@ -6,6 +6,7 @@
#include "effects/Envelope.h"
#include "waveforms/Waveform.h"
#include "AudioHost.h"
+#include "effects/LowPass.h"
class Instrument {
private:
@@ -15,6 +16,7 @@
Envelope *const envelope = new Envelope();
Waveform *wave;
+ LowPass *lowPass = new LowPass();
void render(float *buffer, uint32_t count);
void startNote(float frequency);
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index d26ee2b..cb732f2 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -1,6 +1,7 @@
#include
#include
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
@@ -92,4 +93,19 @@
envelope->release = release;
envelope->update();
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_applyEffectAttributes(JNIEnv *env, jobject thiz,
+ jint id,
+ jint effect_number,
+ jfloat parameter1) {
+ Instrument *instrument = getInstrument(id);
+ Effect *effect;
+ switch (effect_number) {
+ case 0:
+ effect = instrument->lowPass;
+ break;
+ }
+ effect->parameter1 = parameter1;
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.cpp b/app/src/main/cpp/effects/Effect.cpp
new file mode 100644
index 0000000..881e413
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.cpp
@@ -0,0 +1 @@
+#include "Effect.h"
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.h b/app/src/main/cpp/effects/Effect.h
new file mode 100644
index 0000000..d4777f9
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.h
@@ -0,0 +1,19 @@
+#ifndef MUSIC_EFFECT_H
+#define MUSIC_EFFECT_H
+
+#include
+#include "Processable.h"
+#include "../AudioHost.h"
+
+class Effect : public Processable {
+public:
+ float parameter1, frequency;
+ float *input;
+ AudioHost *host;
+
+ virtual void doRender(uint32_t sampleCount) = 0;
+
+ virtual void update() = 0;
+};
+
+#endif
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/LowPass.cpp b/app/src/main/cpp/effects/LowPass.cpp
new file mode 100644
index 0000000..8336798
--- /dev/null
+++ b/app/src/main/cpp/effects/LowPass.cpp
@@ -0,0 +1,18 @@
+#include "../Instrument.h"
+#include
+
+// direct model of a RC-filter, R = 1 Ohm for convenience
+
+void LowPass::update() {
+ charge = 0;
+ inverseCapacitance = 2 * M_PI * frequency * pow(2, parameter1);
+ capacitance = 1 / inverseCapacitance;
+ timeStep = 1 / (float) host->sampleRate;
+}
+
+void LowPass::doRender(uint32_t sampleCount) {
+ for (uint32_t i = 0; i < sampleCount; i++) {
+ charge += (input[i] - charge * inverseCapacitance) * timeStep;
+ buffer[i] = charge * inverseCapacitance;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/LowPass.h b/app/src/main/cpp/effects/LowPass.h
new file mode 100644
index 0000000..a285154
--- /dev/null
+++ b/app/src/main/cpp/effects/LowPass.h
@@ -0,0 +1,18 @@
+#ifndef MUSIC_LOWPASS_H
+#define MUSIC_LOWPASS_H
+
+#include "Effect.h"
+
+class LowPass : public Effect {
+private:
+ float charge = 0;
+ float capacitance = 0;
+ float inverseCapacitance = 0;
+ float timeStep = 0;
+public:
+ void update();
+
+ void doRender(uint32_t sampleCount);
+};
+
+#endif
\ 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 53ec4ad..46957ee 100644
--- a/app/src/main/java/com/lukas/music/instruments/Instrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
@@ -20,7 +20,7 @@
var voice: Voice = BassVoice(this)
var envelope = Envelope(this)
val effects = Array(EffectType.VALUES.size) {
- Effect(EffectType.VALUES[it])
+ Effect(EffectType.VALUES[it], this)
}
abstract var waveform: Waveform
@@ -32,6 +32,7 @@
abstract fun stopNote(note: Note)
abstract fun destroy()
abstract fun updateEnvelope()
+ abstract fun updateEffects()
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 946e653..f7983ad 100644
--- a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
@@ -10,6 +10,7 @@
package com.lukas.music.instruments
+import com.lukas.music.instruments.effect.Effect
import com.lukas.music.song.note.Note
class InternalInstrument {
@@ -77,6 +78,10 @@
)
}
+ fun applyEffectAttributes(effect: Effect) {
+ applyEffectAttributes(id, effect.type.ordinal, effect.parameter1)
+ }
+
private external fun createInstrument(): Int
private external fun setInstrumentWaveform(id: Int, waveform: Int)
private external fun startNote(id: Int, frequency: Double)
@@ -90,4 +95,6 @@
sustain: Float,
release: Float
)
+
+ private external fun applyEffectAttributes(id: Int, effectNumber: Int, parameter1: 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 a9b5c53..3526e60 100644
--- a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
@@ -57,4 +57,10 @@
override fun updateEnvelope() {
internalInstrument.applyEnvelope(envelope)
}
+
+ override fun updateEffects() {
+ for (effect in effects) {
+ internalInstrument.applyEffectAttributes(effect)
+ }
+ }
}
\ 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 8f055d0..70ba98a 100644
--- a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
@@ -81,4 +81,12 @@
instrument.applyEnvelope(envelope)
}
}
+
+ override fun updateEffects() {
+ for (instrument in internalInstruments) {
+ for (effect in effects) {
+ instrument.applyEffectAttributes(effect)
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/effect/Effect.kt b/app/src/main/java/com/lukas/music/instruments/effect/Effect.kt
index ebc64d1..8a3c4eb 100644
--- a/app/src/main/java/com/lukas/music/instruments/effect/Effect.kt
+++ b/app/src/main/java/com/lukas/music/instruments/effect/Effect.kt
@@ -10,4 +10,17 @@
package com.lukas.music.instruments.effect
-class Effect(val type: EffectType)
\ No newline at end of file
+import com.lukas.music.instruments.Instrument
+
+class Effect(val type: EffectType, private val instrument: Instrument) {
+ var parameter1: Float = 1.0f
+ set(value) {
+ field = value
+ instrument.updateEffects()
+ }
+ var parameter1Percent: Int
+ get() = (parameter1 * 100).toInt()
+ set(value) {
+ parameter1 = value.toFloat() / 100f
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/effect/EffectType.kt b/app/src/main/java/com/lukas/music/instruments/effect/EffectType.kt
index 8b7767b..98edbbb 100644
--- a/app/src/main/java/com/lukas/music/instruments/effect/EffectType.kt
+++ b/app/src/main/java/com/lukas/music/instruments/effect/EffectType.kt
@@ -10,8 +10,13 @@
package com.lukas.music.instruments.effect
-enum class EffectType(val description: String, val parameter1Name: String) {
- LowPass("low pass filter", "cutoff frequency"),
+import kotlin.math.roundToInt
+
+enum class EffectType(
+ val description: String,
+ val parameter1Text: (Int) -> String,
+) {
+ LowPass("low pass filter", { "cutoff: ${(it.toFloat() / 100f).roundToInt()} octaves" }),
;
companion object {
diff --git a/.idea/misc.xml b/.idea/misc.xml
index bf86c48..1a41dfa 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/app/src/main/cpp/AudioHost.cpp b/app/src/main/cpp/AudioHost.cpp
index 8e98b44..6727405 100644
--- a/app/src/main/cpp/AudioHost.cpp
+++ b/app/src/main/cpp/AudioHost.cpp
@@ -1,7 +1,9 @@
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
+#include
const uint32_t bufferSize = 2;
aaudio_data_callback_result_t dataCallback(
diff --git a/app/src/main/cpp/AudioHost.h b/app/src/main/cpp/AudioHost.h
index f439fdc..97446ea 100644
--- a/app/src/main/cpp/AudioHost.h
+++ b/app/src/main/cpp/AudioHost.h
@@ -3,7 +3,8 @@
class AudioHost;
-#include "Instrument.h"
+class Instrument;
+
#include
#include
diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
index b94b511..8588bed 100644
--- a/app/src/main/cpp/CMakeLists.txt
+++ b/app/src/main/cpp/CMakeLists.txt
@@ -17,6 +17,8 @@
Instrument.cpp
effects/Envelope.cpp
effects/Processable.cpp
+ effects/Effect.cpp
+ effects/LowPass.cpp
)
find_library(
diff --git a/app/src/main/cpp/Instrument.cpp b/app/src/main/cpp/Instrument.cpp
index d7263ed..985e93e 100644
--- a/app/src/main/cpp/Instrument.cpp
+++ b/app/src/main/cpp/Instrument.cpp
@@ -9,6 +9,7 @@
wave = new Sine();
wave->host = host;
envelope->initialize(host);
+ lowPass->host = host;
}
void multiply(float *target, float *modulation, uint32_t size) {
@@ -27,12 +28,16 @@
float *modulation = envelope->render(count);
float *waveform = wave->render(count);
multiply(waveform, modulation, count);
- add(buffer, waveform, count);
+ lowPass->input = waveform;
+ float *filtered = lowPass->render(count);
+ add(buffer, filtered, count);
}
void Instrument::startNote(float frequency) {
wave->setFrequency(frequency);
envelope->startNote();
+ lowPass->frequency = frequency;
+ lowPass->update();
}
void Instrument::endNote() {
diff --git a/app/src/main/cpp/Instrument.h b/app/src/main/cpp/Instrument.h
index f15d631..3ab90a8 100644
--- a/app/src/main/cpp/Instrument.h
+++ b/app/src/main/cpp/Instrument.h
@@ -6,6 +6,7 @@
#include "effects/Envelope.h"
#include "waveforms/Waveform.h"
#include "AudioHost.h"
+#include "effects/LowPass.h"
class Instrument {
private:
@@ -15,6 +16,7 @@
Envelope *const envelope = new Envelope();
Waveform *wave;
+ LowPass *lowPass = new LowPass();
void render(float *buffer, uint32_t count);
void startNote(float frequency);
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index d26ee2b..cb732f2 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -1,6 +1,7 @@
#include
#include
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
@@ -92,4 +93,19 @@
envelope->release = release;
envelope->update();
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_applyEffectAttributes(JNIEnv *env, jobject thiz,
+ jint id,
+ jint effect_number,
+ jfloat parameter1) {
+ Instrument *instrument = getInstrument(id);
+ Effect *effect;
+ switch (effect_number) {
+ case 0:
+ effect = instrument->lowPass;
+ break;
+ }
+ effect->parameter1 = parameter1;
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.cpp b/app/src/main/cpp/effects/Effect.cpp
new file mode 100644
index 0000000..881e413
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.cpp
@@ -0,0 +1 @@
+#include "Effect.h"
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.h b/app/src/main/cpp/effects/Effect.h
new file mode 100644
index 0000000..d4777f9
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.h
@@ -0,0 +1,19 @@
+#ifndef MUSIC_EFFECT_H
+#define MUSIC_EFFECT_H
+
+#include
+#include "Processable.h"
+#include "../AudioHost.h"
+
+class Effect : public Processable {
+public:
+ float parameter1, frequency;
+ float *input;
+ AudioHost *host;
+
+ virtual void doRender(uint32_t sampleCount) = 0;
+
+ virtual void update() = 0;
+};
+
+#endif
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/LowPass.cpp b/app/src/main/cpp/effects/LowPass.cpp
new file mode 100644
index 0000000..8336798
--- /dev/null
+++ b/app/src/main/cpp/effects/LowPass.cpp
@@ -0,0 +1,18 @@
+#include "../Instrument.h"
+#include
+
+// direct model of a RC-filter, R = 1 Ohm for convenience
+
+void LowPass::update() {
+ charge = 0;
+ inverseCapacitance = 2 * M_PI * frequency * pow(2, parameter1);
+ capacitance = 1 / inverseCapacitance;
+ timeStep = 1 / (float) host->sampleRate;
+}
+
+void LowPass::doRender(uint32_t sampleCount) {
+ for (uint32_t i = 0; i < sampleCount; i++) {
+ charge += (input[i] - charge * inverseCapacitance) * timeStep;
+ buffer[i] = charge * inverseCapacitance;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/LowPass.h b/app/src/main/cpp/effects/LowPass.h
new file mode 100644
index 0000000..a285154
--- /dev/null
+++ b/app/src/main/cpp/effects/LowPass.h
@@ -0,0 +1,18 @@
+#ifndef MUSIC_LOWPASS_H
+#define MUSIC_LOWPASS_H
+
+#include "Effect.h"
+
+class LowPass : public Effect {
+private:
+ float charge = 0;
+ float capacitance = 0;
+ float inverseCapacitance = 0;
+ float timeStep = 0;
+public:
+ void update();
+
+ void doRender(uint32_t sampleCount);
+};
+
+#endif
\ 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 53ec4ad..46957ee 100644
--- a/app/src/main/java/com/lukas/music/instruments/Instrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
@@ -20,7 +20,7 @@
var voice: Voice = BassVoice(this)
var envelope = Envelope(this)
val effects = Array(EffectType.VALUES.size) {
- Effect(EffectType.VALUES[it])
+ Effect(EffectType.VALUES[it], this)
}
abstract var waveform: Waveform
@@ -32,6 +32,7 @@
abstract fun stopNote(note: Note)
abstract fun destroy()
abstract fun updateEnvelope()
+ abstract fun updateEffects()
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 946e653..f7983ad 100644
--- a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
@@ -10,6 +10,7 @@
package com.lukas.music.instruments
+import com.lukas.music.instruments.effect.Effect
import com.lukas.music.song.note.Note
class InternalInstrument {
@@ -77,6 +78,10 @@
)
}
+ fun applyEffectAttributes(effect: Effect) {
+ applyEffectAttributes(id, effect.type.ordinal, effect.parameter1)
+ }
+
private external fun createInstrument(): Int
private external fun setInstrumentWaveform(id: Int, waveform: Int)
private external fun startNote(id: Int, frequency: Double)
@@ -90,4 +95,6 @@
sustain: Float,
release: Float
)
+
+ private external fun applyEffectAttributes(id: Int, effectNumber: Int, parameter1: 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 a9b5c53..3526e60 100644
--- a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
@@ -57,4 +57,10 @@
override fun updateEnvelope() {
internalInstrument.applyEnvelope(envelope)
}
+
+ override fun updateEffects() {
+ for (effect in effects) {
+ internalInstrument.applyEffectAttributes(effect)
+ }
+ }
}
\ 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 8f055d0..70ba98a 100644
--- a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
@@ -81,4 +81,12 @@
instrument.applyEnvelope(envelope)
}
}
+
+ override fun updateEffects() {
+ for (instrument in internalInstruments) {
+ for (effect in effects) {
+ instrument.applyEffectAttributes(effect)
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/effect/Effect.kt b/app/src/main/java/com/lukas/music/instruments/effect/Effect.kt
index ebc64d1..8a3c4eb 100644
--- a/app/src/main/java/com/lukas/music/instruments/effect/Effect.kt
+++ b/app/src/main/java/com/lukas/music/instruments/effect/Effect.kt
@@ -10,4 +10,17 @@
package com.lukas.music.instruments.effect
-class Effect(val type: EffectType)
\ No newline at end of file
+import com.lukas.music.instruments.Instrument
+
+class Effect(val type: EffectType, private val instrument: Instrument) {
+ var parameter1: Float = 1.0f
+ set(value) {
+ field = value
+ instrument.updateEffects()
+ }
+ var parameter1Percent: Int
+ get() = (parameter1 * 100).toInt()
+ set(value) {
+ parameter1 = value.toFloat() / 100f
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/effect/EffectType.kt b/app/src/main/java/com/lukas/music/instruments/effect/EffectType.kt
index 8b7767b..98edbbb 100644
--- a/app/src/main/java/com/lukas/music/instruments/effect/EffectType.kt
+++ b/app/src/main/java/com/lukas/music/instruments/effect/EffectType.kt
@@ -10,8 +10,13 @@
package com.lukas.music.instruments.effect
-enum class EffectType(val description: String, val parameter1Name: String) {
- LowPass("low pass filter", "cutoff frequency"),
+import kotlin.math.roundToInt
+
+enum class EffectType(
+ val description: String,
+ val parameter1Text: (Int) -> String,
+) {
+ LowPass("low pass filter", { "cutoff: ${(it.toFloat() / 100f).roundToInt()} octaves" }),
;
companion object {
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/EffectFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/EffectFragment.kt
index b040f9d..c004620 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/EffectFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EffectFragment.kt
@@ -17,6 +17,7 @@
import androidx.fragment.app.Fragment
import com.lukas.music.databinding.FragmentEffectBinding
import com.lukas.music.instruments.effect.Effect
+import com.lukas.music.util.smartSetup
class EffectFragment(private val effect: Effect) : Fragment() {
lateinit var binding: FragmentEffectBinding
@@ -27,6 +28,9 @@
): View? {
binding = FragmentEffectBinding.inflate(inflater)
binding.effectName.text = effect.type.description
+ binding.parameter1SeekBar.smartSetup(-100, 300, effect::parameter1Percent) {
+ binding.parameter1Text.text = effect.type.parameter1Text(it)
+ }
return binding.root
}
}
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index bf86c48..1a41dfa 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/app/src/main/cpp/AudioHost.cpp b/app/src/main/cpp/AudioHost.cpp
index 8e98b44..6727405 100644
--- a/app/src/main/cpp/AudioHost.cpp
+++ b/app/src/main/cpp/AudioHost.cpp
@@ -1,7 +1,9 @@
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
+#include
const uint32_t bufferSize = 2;
aaudio_data_callback_result_t dataCallback(
diff --git a/app/src/main/cpp/AudioHost.h b/app/src/main/cpp/AudioHost.h
index f439fdc..97446ea 100644
--- a/app/src/main/cpp/AudioHost.h
+++ b/app/src/main/cpp/AudioHost.h
@@ -3,7 +3,8 @@
class AudioHost;
-#include "Instrument.h"
+class Instrument;
+
#include
#include
diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
index b94b511..8588bed 100644
--- a/app/src/main/cpp/CMakeLists.txt
+++ b/app/src/main/cpp/CMakeLists.txt
@@ -17,6 +17,8 @@
Instrument.cpp
effects/Envelope.cpp
effects/Processable.cpp
+ effects/Effect.cpp
+ effects/LowPass.cpp
)
find_library(
diff --git a/app/src/main/cpp/Instrument.cpp b/app/src/main/cpp/Instrument.cpp
index d7263ed..985e93e 100644
--- a/app/src/main/cpp/Instrument.cpp
+++ b/app/src/main/cpp/Instrument.cpp
@@ -9,6 +9,7 @@
wave = new Sine();
wave->host = host;
envelope->initialize(host);
+ lowPass->host = host;
}
void multiply(float *target, float *modulation, uint32_t size) {
@@ -27,12 +28,16 @@
float *modulation = envelope->render(count);
float *waveform = wave->render(count);
multiply(waveform, modulation, count);
- add(buffer, waveform, count);
+ lowPass->input = waveform;
+ float *filtered = lowPass->render(count);
+ add(buffer, filtered, count);
}
void Instrument::startNote(float frequency) {
wave->setFrequency(frequency);
envelope->startNote();
+ lowPass->frequency = frequency;
+ lowPass->update();
}
void Instrument::endNote() {
diff --git a/app/src/main/cpp/Instrument.h b/app/src/main/cpp/Instrument.h
index f15d631..3ab90a8 100644
--- a/app/src/main/cpp/Instrument.h
+++ b/app/src/main/cpp/Instrument.h
@@ -6,6 +6,7 @@
#include "effects/Envelope.h"
#include "waveforms/Waveform.h"
#include "AudioHost.h"
+#include "effects/LowPass.h"
class Instrument {
private:
@@ -15,6 +16,7 @@
Envelope *const envelope = new Envelope();
Waveform *wave;
+ LowPass *lowPass = new LowPass();
void render(float *buffer, uint32_t count);
void startNote(float frequency);
diff --git a/app/src/main/cpp/JavaFunctions.cpp b/app/src/main/cpp/JavaFunctions.cpp
index d26ee2b..cb732f2 100644
--- a/app/src/main/cpp/JavaFunctions.cpp
+++ b/app/src/main/cpp/JavaFunctions.cpp
@@ -1,6 +1,7 @@
#include
#include
#include "AudioHost.h"
+#include "Instrument.h"
#include
#include
#include
@@ -92,4 +93,19 @@
envelope->release = release;
envelope->update();
}
+
+JNIEXPORT void JNICALL
+Java_com_lukas_music_instruments_InternalInstrument_applyEffectAttributes(JNIEnv *env, jobject thiz,
+ jint id,
+ jint effect_number,
+ jfloat parameter1) {
+ Instrument *instrument = getInstrument(id);
+ Effect *effect;
+ switch (effect_number) {
+ case 0:
+ effect = instrument->lowPass;
+ break;
+ }
+ effect->parameter1 = parameter1;
+}
}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.cpp b/app/src/main/cpp/effects/Effect.cpp
new file mode 100644
index 0000000..881e413
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.cpp
@@ -0,0 +1 @@
+#include "Effect.h"
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/Effect.h b/app/src/main/cpp/effects/Effect.h
new file mode 100644
index 0000000..d4777f9
--- /dev/null
+++ b/app/src/main/cpp/effects/Effect.h
@@ -0,0 +1,19 @@
+#ifndef MUSIC_EFFECT_H
+#define MUSIC_EFFECT_H
+
+#include
+#include "Processable.h"
+#include "../AudioHost.h"
+
+class Effect : public Processable {
+public:
+ float parameter1, frequency;
+ float *input;
+ AudioHost *host;
+
+ virtual void doRender(uint32_t sampleCount) = 0;
+
+ virtual void update() = 0;
+};
+
+#endif
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/LowPass.cpp b/app/src/main/cpp/effects/LowPass.cpp
new file mode 100644
index 0000000..8336798
--- /dev/null
+++ b/app/src/main/cpp/effects/LowPass.cpp
@@ -0,0 +1,18 @@
+#include "../Instrument.h"
+#include
+
+// direct model of a RC-filter, R = 1 Ohm for convenience
+
+void LowPass::update() {
+ charge = 0;
+ inverseCapacitance = 2 * M_PI * frequency * pow(2, parameter1);
+ capacitance = 1 / inverseCapacitance;
+ timeStep = 1 / (float) host->sampleRate;
+}
+
+void LowPass::doRender(uint32_t sampleCount) {
+ for (uint32_t i = 0; i < sampleCount; i++) {
+ charge += (input[i] - charge * inverseCapacitance) * timeStep;
+ buffer[i] = charge * inverseCapacitance;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/cpp/effects/LowPass.h b/app/src/main/cpp/effects/LowPass.h
new file mode 100644
index 0000000..a285154
--- /dev/null
+++ b/app/src/main/cpp/effects/LowPass.h
@@ -0,0 +1,18 @@
+#ifndef MUSIC_LOWPASS_H
+#define MUSIC_LOWPASS_H
+
+#include "Effect.h"
+
+class LowPass : public Effect {
+private:
+ float charge = 0;
+ float capacitance = 0;
+ float inverseCapacitance = 0;
+ float timeStep = 0;
+public:
+ void update();
+
+ void doRender(uint32_t sampleCount);
+};
+
+#endif
\ 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 53ec4ad..46957ee 100644
--- a/app/src/main/java/com/lukas/music/instruments/Instrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/Instrument.kt
@@ -20,7 +20,7 @@
var voice: Voice = BassVoice(this)
var envelope = Envelope(this)
val effects = Array(EffectType.VALUES.size) {
- Effect(EffectType.VALUES[it])
+ Effect(EffectType.VALUES[it], this)
}
abstract var waveform: Waveform
@@ -32,6 +32,7 @@
abstract fun stopNote(note: Note)
abstract fun destroy()
abstract fun updateEnvelope()
+ abstract fun updateEffects()
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 946e653..f7983ad 100644
--- a/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/InternalInstrument.kt
@@ -10,6 +10,7 @@
package com.lukas.music.instruments
+import com.lukas.music.instruments.effect.Effect
import com.lukas.music.song.note.Note
class InternalInstrument {
@@ -77,6 +78,10 @@
)
}
+ fun applyEffectAttributes(effect: Effect) {
+ applyEffectAttributes(id, effect.type.ordinal, effect.parameter1)
+ }
+
private external fun createInstrument(): Int
private external fun setInstrumentWaveform(id: Int, waveform: Int)
private external fun startNote(id: Int, frequency: Double)
@@ -90,4 +95,6 @@
sustain: Float,
release: Float
)
+
+ private external fun applyEffectAttributes(id: Int, effectNumber: Int, parameter1: 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 a9b5c53..3526e60 100644
--- a/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/MonoInstrument.kt
@@ -57,4 +57,10 @@
override fun updateEnvelope() {
internalInstrument.applyEnvelope(envelope)
}
+
+ override fun updateEffects() {
+ for (effect in effects) {
+ internalInstrument.applyEffectAttributes(effect)
+ }
+ }
}
\ 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 8f055d0..70ba98a 100644
--- a/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
+++ b/app/src/main/java/com/lukas/music/instruments/PolyInstrument.kt
@@ -81,4 +81,12 @@
instrument.applyEnvelope(envelope)
}
}
+
+ override fun updateEffects() {
+ for (instrument in internalInstruments) {
+ for (effect in effects) {
+ instrument.applyEffectAttributes(effect)
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/effect/Effect.kt b/app/src/main/java/com/lukas/music/instruments/effect/Effect.kt
index ebc64d1..8a3c4eb 100644
--- a/app/src/main/java/com/lukas/music/instruments/effect/Effect.kt
+++ b/app/src/main/java/com/lukas/music/instruments/effect/Effect.kt
@@ -10,4 +10,17 @@
package com.lukas.music.instruments.effect
-class Effect(val type: EffectType)
\ No newline at end of file
+import com.lukas.music.instruments.Instrument
+
+class Effect(val type: EffectType, private val instrument: Instrument) {
+ var parameter1: Float = 1.0f
+ set(value) {
+ field = value
+ instrument.updateEffects()
+ }
+ var parameter1Percent: Int
+ get() = (parameter1 * 100).toInt()
+ set(value) {
+ parameter1 = value.toFloat() / 100f
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lukas/music/instruments/effect/EffectType.kt b/app/src/main/java/com/lukas/music/instruments/effect/EffectType.kt
index 8b7767b..98edbbb 100644
--- a/app/src/main/java/com/lukas/music/instruments/effect/EffectType.kt
+++ b/app/src/main/java/com/lukas/music/instruments/effect/EffectType.kt
@@ -10,8 +10,13 @@
package com.lukas.music.instruments.effect
-enum class EffectType(val description: String, val parameter1Name: String) {
- LowPass("low pass filter", "cutoff frequency"),
+import kotlin.math.roundToInt
+
+enum class EffectType(
+ val description: String,
+ val parameter1Text: (Int) -> String,
+) {
+ LowPass("low pass filter", { "cutoff: ${(it.toFloat() / 100f).roundToInt()} octaves" }),
;
companion object {
diff --git a/app/src/main/java/com/lukas/music/ui/fragments/EffectFragment.kt b/app/src/main/java/com/lukas/music/ui/fragments/EffectFragment.kt
index b040f9d..c004620 100644
--- a/app/src/main/java/com/lukas/music/ui/fragments/EffectFragment.kt
+++ b/app/src/main/java/com/lukas/music/ui/fragments/EffectFragment.kt
@@ -17,6 +17,7 @@
import androidx.fragment.app.Fragment
import com.lukas.music.databinding.FragmentEffectBinding
import com.lukas.music.instruments.effect.Effect
+import com.lukas.music.util.smartSetup
class EffectFragment(private val effect: Effect) : Fragment() {
lateinit var binding: FragmentEffectBinding
@@ -27,6 +28,9 @@
): View? {
binding = FragmentEffectBinding.inflate(inflater)
binding.effectName.text = effect.type.description
+ binding.parameter1SeekBar.smartSetup(-100, 300, effect::parameter1Percent) {
+ binding.parameter1Text.text = effect.type.parameter1Text(it)
+ }
return binding.root
}
}
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_effect.xml b/app/src/main/res/layout/fragment_effect.xml
index ff90aa8..7e88115 100644
--- a/app/src/main/res/layout/fragment_effect.xml
+++ b/app/src/main/res/layout/fragment_effect.xml
@@ -11,13 +11,10 @@
-
-
+
+
+
+