@@ -1,7 +1,6 @@ | |||||
ARCH ?= linux | ARCH ?= linux | ||||
CFLAGS = -MMD -g -Wall -O0 \ | |||||
-DNOC_FILE_DIALOG_IMPLEMENTATION | |||||
CXXFLAGS = -MMD -g -Wall -std=c++11 -O0 -ffast-math \ | |||||
CFLAGS = -MMD -g -Wall -O2 | |||||
CXXFLAGS = -MMD -g -Wall -std=c++11 -O2 -ffast-math \ | |||||
-I./lib -I./src | -I./lib -I./src | ||||
LDFLAGS = | LDFLAGS = | ||||
@@ -16,20 +15,20 @@ CXX = g++ | |||||
SOURCES += lib/noc/noc_file_dialog.c | SOURCES += lib/noc/noc_file_dialog.c | ||||
CFLAGS += -DNOC_FILE_DIALOG_GTK $(shell pkg-config --cflags gtk+-2.0) | CFLAGS += -DNOC_FILE_DIALOG_GTK $(shell pkg-config --cflags gtk+-2.0) | ||||
CXXFLAGS += -DLINUX | CXXFLAGS += -DLINUX | ||||
LDFLAGS = -lpthread -lGL -lGLEW -lglfw -ldl -lrtaudio -lrtmidi -lprofiler -ljansson \ | |||||
LDFLAGS += -lpthread -lGL -lGLEW -lglfw -ldl -lrtaudio -lrtmidi -lprofiler -ljansson \ | |||||
$(shell pkg-config --libs gtk+-2.0) | $(shell pkg-config --libs gtk+-2.0) | ||||
TARGET = 5V | |||||
TARGET = Rack | |||||
endif | endif | ||||
# Apple | # Apple | ||||
ifeq ($(ARCH), apple) | ifeq ($(ARCH), apple) | ||||
OSXCROSS = $(HOME)/pkg/osxcross/target/bin | |||||
CC = $(OSXCROSS)/x86_64-apple-darwin15-cc | |||||
CXX = $(OSXCROSS)/x86_64-apple-darwin15-c++ | |||||
CC = clang | |||||
CXX = clang++ | |||||
SOURCES += lib/noc/noc_file_dialog.m | SOURCES += lib/noc/noc_file_dialog.m | ||||
CFLAGS += -DNOC_FILE_DIALOG_OSX | CFLAGS += -DNOC_FILE_DIALOG_OSX | ||||
CXXFLAGS += -DAPPLE -stdlib=libc++ | |||||
TARGET = 5V | |||||
CXXFLAGS += -DAPPLE -stdlib=libc++ -I$(HOME)/local/include | |||||
LDFLAGS += -stdlib=libc++ -L$(HOME)/local/lib -lpthread -lglew -lglfw3 -framework Cocoa -framework OpenGL -framework IOKit -framework CoreVideo -ldl -lrtaudio -lrtmidi -ljansson | |||||
TARGET = Rack | |||||
endif | endif | ||||
# Windows | # Windows | ||||
@@ -39,40 +38,19 @@ CXX = x86_64-w64-mingw32-g++ | |||||
SOURCES += lib/noc/noc_file_dialog.c | SOURCES += lib/noc/noc_file_dialog.c | ||||
CFLAGS += -DNOC_FILE_DIALOG_WIN32 | CFLAGS += -DNOC_FILE_DIALOG_WIN32 | ||||
CXXFLAGS += -DWINDOWS | CXXFLAGS += -DWINDOWS | ||||
LDFLAGS = -lpthread -ljansson \ | |||||
LDFLAGS += -lpthread -ljansson \ | |||||
./lib/nanovg/build/libnanovg.a -lglfw3 -lgdi32 -lopengl32 -lglew32 \ | ./lib/nanovg/build/libnanovg.a -lglfw3 -lgdi32 -lopengl32 -lglew32 \ | ||||
./lib/rtaudio/librtaudio.a -lksuser -luuid \ | ./lib/rtaudio/librtaudio.a -lksuser -luuid \ | ||||
./lib/rtmidi/librtmidi.a -lwinmm \ | ./lib/rtmidi/librtmidi.a -lwinmm \ | ||||
-lcomdlg32 -lole32 \ | -lcomdlg32 -lole32 \ | ||||
-Wl,--export-all-symbols,--out-implib,lib5V.a -mwindows | -Wl,--export-all-symbols,--out-implib,lib5V.a -mwindows | ||||
TARGET = 5V.exe | |||||
TARGET = Rack.exe | |||||
endif | endif | ||||
OBJECTS = $(patsubst %, build/%.o, $(SOURCES)) | |||||
DEPS = $(patsubst %, build/%.d, $(SOURCES)) | |||||
# Final targets | |||||
all: $(TARGET) | all: $(TARGET) | ||||
$(MAKE) -C plugins/Simple | |||||
$(MAKE) -C plugins/AudibleInstruments | |||||
$(TARGET): $(OBJECTS) | |||||
$(CXX) -o $@ $^ $(LDFLAGS) | |||||
# Object targets | |||||
-include $(DEPS) | |||||
build/%.c.o: %.c | |||||
@mkdir -p $(@D) | |||||
$(CC) $(CFLAGS) -c -o $@ $< | |||||
build/%.cpp.o: %.cpp | |||||
@mkdir -p $(@D) | |||||
$(CXX) $(CXXFLAGS) -c -o $@ $< | |||||
# Utilities | |||||
clean: | |||||
rm -rf build | |||||
include Makefile.inc |
@@ -0,0 +1,34 @@ | |||||
OBJECTS = $(patsubst %, build/%.o, $(SOURCES)) | |||||
DEPS = $(patsubst %, build/%.d, $(SOURCES)) | |||||
# Final targets | |||||
$(TARGET): $(OBJECTS) | |||||
$(CXX) -o $@ $^ $(LDFLAGS) | |||||
# Object targets | |||||
-include $(DEPS) | |||||
build/%.c.o: %.c | |||||
@mkdir -p $(@D) | |||||
$(CC) $(CFLAGS) -c -o $@ $< | |||||
build/%.cpp.o: %.cpp | |||||
@mkdir -p $(@D) | |||||
$(CXX) $(CXXFLAGS) -c -o $@ $< | |||||
build/%.cc.o: %.cc | |||||
@mkdir -p $(@D) | |||||
$(CXX) $(CXXFLAGS) -c -o $@ $< | |||||
build/%.m.o: %.m | |||||
@mkdir -p $(@D) | |||||
$(CC) $(CFLAGS) -c -o $@ $< | |||||
# Utilities | |||||
clean: | |||||
rm -rf build $(TARGET) |
@@ -12,4 +12,4 @@ The build system is a mess, but I'll add instructions before I announce the soft | |||||
All source code in this repository is licensed under the LGPLv3. | All source code in this repository is licensed under the LGPLv3. | ||||
LGPL was chosen over GPL to allow plugins to call functions and inherit object classes from this source code without being forced to use the GPL license. You are thus free to develop proprietary plugins which link to and use the API of this software. | |||||
LGPL was chosen over GPL to allow plugins to call functions and inherit object classes from this source code without being forced to use the GPL license. You are thus free to develop open source or commercial plugins which link to and use the API of this software. |
@@ -58,10 +58,10 @@ void AudioInterface::step() { | |||||
int i = bufferFrame % AUDIO_BUFFER_SIZE; | int i = bufferFrame % AUDIO_BUFFER_SIZE; | ||||
audio1Buffer[i] = getf(inputs[AUDIO1_INPUT]); | audio1Buffer[i] = getf(inputs[AUDIO1_INPUT]); | ||||
audio2Buffer[i] = getf(inputs[AUDIO2_INPUT]); | audio2Buffer[i] = getf(inputs[AUDIO2_INPUT]); | ||||
std::unique_lock<std::mutex> lock(mutex); | |||||
// std::unique_lock<std::mutex> lock(mutex); | |||||
bufferFrame++; | bufferFrame++; | ||||
if (bufferFrame == audioFrameNeeded) { | if (bufferFrame == audioFrameNeeded) { | ||||
lock.unlock(); | |||||
// lock.unlock(); | |||||
cv.notify_all(); | cv.notify_all(); | ||||
} | } | ||||
} | } | ||||
@@ -83,7 +83,7 @@ void AudioInterface::openDevice(int deviceId) { | |||||
streamParams.nChannels = 2; | streamParams.nChannels = 2; | ||||
streamParams.firstChannel = 0; | streamParams.firstChannel = 0; | ||||
unsigned int sampleRate = SAMPLE_RATE; | unsigned int sampleRate = SAMPLE_RATE; | ||||
unsigned int bufferFrames = 256; | |||||
unsigned int bufferFrames = 512; | |||||
audioFrame = -1; | audioFrame = -1; | ||||
running = true; | running = true; | ||||
@@ -183,11 +183,11 @@ struct AudioChoice : ChoiceButton { | |||||
AudioInterfaceWidget::AudioInterfaceWidget() : ModuleWidget(new AudioInterface()) { | AudioInterfaceWidget::AudioInterfaceWidget() : ModuleWidget(new AudioInterface()) { | ||||
box.size = Vec(15*4, 380); | |||||
box.size = Vec(15*8, 380); | |||||
inputs.resize(AudioInterface::NUM_INPUTS); | inputs.resize(AudioInterface::NUM_INPUTS); | ||||
createInputPort(this, AudioInterface::AUDIO1_INPUT, Vec(15, 120)); | |||||
createInputPort(this, AudioInterface::AUDIO2_INPUT, Vec(15, 170)); | |||||
createInputPort(this, AudioInterface::AUDIO1_INPUT, Vec(15, 100)); | |||||
createInputPort(this, AudioInterface::AUDIO2_INPUT, Vec(70, 100)); | |||||
AudioChoice *audioChoice = new AudioChoice(); | AudioChoice *audioChoice = new AudioChoice(); | ||||
audioChoice->audioInterface = dynamic_cast<AudioInterface*>(module); | audioChoice->audioInterface = dynamic_cast<AudioInterface*>(module); | ||||
@@ -187,11 +187,11 @@ struct MidiChoice : ChoiceButton { | |||||
MidiInterfaceWidget::MidiInterfaceWidget() : ModuleWidget(new MidiInterface()) { | MidiInterfaceWidget::MidiInterfaceWidget() : ModuleWidget(new MidiInterface()) { | ||||
box.size = Vec(15*4, 380); | |||||
box.size = Vec(15*8, 380); | |||||
outputs.resize(MidiInterface::NUM_OUTPUTS); | outputs.resize(MidiInterface::NUM_OUTPUTS); | ||||
createOutputPort(this, MidiInterface::GATE_OUTPUT, Vec(15, 120)); | |||||
createOutputPort(this, MidiInterface::PITCH_OUTPUT, Vec(15, 170)); | |||||
createOutputPort(this, MidiInterface::GATE_OUTPUT, Vec(15, 100)); | |||||
createOutputPort(this, MidiInterface::PITCH_OUTPUT, Vec(70, 100)); | |||||
MidiChoice *midiChoice = new MidiChoice(); | MidiChoice *midiChoice = new MidiChoice(); | ||||
midiChoice->midiInterface = dynamic_cast<MidiInterface*>(module); | midiChoice->midiInterface = dynamic_cast<MidiInterface*>(module); | ||||
@@ -56,7 +56,7 @@ void mouseButtonCallback(GLFWwindow *window, int button, int action, int mods) { | |||||
} | } | ||||
void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) { | void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) { | ||||
Vec mousePos = Vec(xpos, ypos); | |||||
Vec mousePos = Vec(xpos, ypos).round(); | |||||
Vec mouseRel = mousePos.minus(gMousePos); | Vec mouseRel = mousePos.minus(gMousePos); | ||||
gMousePos = mousePos; | gMousePos = mousePos; | ||||
@@ -169,15 +169,15 @@ void guiInit() { | |||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); | ||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); | ||||
window = glfwCreateWindow(1020, 700, "5V", NULL, NULL); | |||||
window = glfwCreateWindow(1020, 700, "Rack", NULL, NULL); | |||||
assert(window); | assert(window); | ||||
glfwMakeContextCurrent(window); | glfwMakeContextCurrent(window); | ||||
glfwSetWindowSizeCallback(window, windowSizeCallback); | glfwSetWindowSizeCallback(window, windowSizeCallback); | ||||
glfwSetMouseButtonCallback(window, mouseButtonCallback); | glfwSetMouseButtonCallback(window, mouseButtonCallback); | ||||
// glfwSetCursorPosCallback(window, cursorPosCallback); | |||||
// glfwSetCursorPosCallback(window, cursorPosCallback); | |||||
glfwSetCursorEnterCallback(window, cursorEnterCallback); | glfwSetCursorEnterCallback(window, cursorEnterCallback); | ||||
glfwSetScrollCallback(window, scrollCallback); | |||||
glfwSetScrollCallback(window, scrollCallback); | |||||
glfwSetCharCallback(window, charCallback); | glfwSetCharCallback(window, charCallback); | ||||
glfwSetKeyCallback(window, keyCallback); | glfwSetKeyCallback(window, keyCallback); | ||||
@@ -1,4 +0,0 @@ | |||||
../src/gui.cpp.o: ../src/gui.cpp ../src/5V.hpp ../src/widgets.hpp \ | |||||
../src/../lib/nanovg/src/nanovg.h ../src/../lib/oui/blendish.h \ | |||||
../src/rack.hpp ../src/util.hpp ../src/../lib/nanovg/src/nanovg_gl.h \ | |||||
../src/../lib/nanovg/src/nanovg.h |
@@ -1,5 +1,6 @@ | |||||
#include "5V.hpp" | #include "5V.hpp" | ||||
#include <time.h> | #include <time.h> | ||||
#include <unistd.h> | |||||
Scene *gScene = NULL; | Scene *gScene = NULL; | ||||
@@ -74,8 +74,13 @@ void pluginInit() { | |||||
loadPlugin("plugins/AudibleInstruments/plugin.dll"); | loadPlugin("plugins/AudibleInstruments/plugin.dll"); | ||||
#elif defined(LINUX) || defined(APPLE) | #elif defined(LINUX) || defined(APPLE) | ||||
#if defined(LINUX) | |||||
const char *globPath = "plugins/*/plugin.so"; | |||||
#elif defined(APPLE) | |||||
const char *globPath = "plugins/*/plugin.dylib"; | |||||
#endif | |||||
glob_t result; | glob_t result; | ||||
glob("plugins/*/plugin.so", GLOB_TILDE, NULL, &result); | |||||
glob(globPath, GLOB_TILDE, NULL, &result); | |||||
for (int i = 0; i < (int) result.gl_pathc; i++) { | for (int i = 0; i < (int) result.gl_pathc; i++) { | ||||
loadPlugin(result.gl_pathv[i]); | loadPlugin(result.gl_pathv[i]); | ||||
} | } | ||||
@@ -1,3 +0,0 @@ | |||||
../src/plugin.cpp.o: ../src/plugin.cpp ../src/5V.hpp ../src/widgets.hpp \ | |||||
../src/../lib/nanovg/src/nanovg.h ../src/../lib/oui/blendish.h \ | |||||
../src/rack.hpp ../src/util.hpp ../src/core/core.hpp |
@@ -39,7 +39,7 @@ void rackStep() { | |||||
// Param interpolation | // Param interpolation | ||||
if (smoothModule) { | if (smoothModule) { | ||||
float value = smoothModule->params[smoothParamId]; | float value = smoothModule->params[smoothParamId]; | ||||
const float minSpeed = 0.01 * 60.0 / SAMPLE_RATE; // Roughly 0.01 every graphics frame | |||||
const float minSpeed = 0.001 * 60.0 / SAMPLE_RATE; | |||||
const float lpCoeff = 60.0 / SAMPLE_RATE / 1.0; // decay rate is 1 graphics frame | const float lpCoeff = 60.0 / SAMPLE_RATE / 1.0; // decay rate is 1 graphics frame | ||||
float delta = smoothValue - value; | float delta = smoothValue - value; | ||||
float speed = fmaxf(fabsf(delta) * lpCoeff, minSpeed); | float speed = fmaxf(fabsf(delta) * lpCoeff, minSpeed); | ||||
@@ -74,10 +74,9 @@ void rackRun() { | |||||
cv.wait_for(lock, std::chrono::milliseconds(1)); | cv.wait_for(lock, std::chrono::milliseconds(1)); | ||||
} | } | ||||
frame++; | frame++; | ||||
lock.unlock(); | |||||
// Speed up | // Speed up | ||||
// for (int i = 0; i < 16; i++) | |||||
rackStep(); | |||||
for (int i = 0; i < 16; i++) | |||||
rackStep(); | |||||
} | } | ||||
} | } | ||||
@@ -99,6 +98,7 @@ void rackStop() { | |||||
void rackAddModule(Module *module) { | void rackAddModule(Module *module) { | ||||
assert(module); | assert(module); | ||||
std::unique_lock<std::mutex> lock(mutex); | |||||
// Check that the module is not already added | // Check that the module is not already added | ||||
assert(modules.find(module) == modules.end()); | assert(modules.find(module) == modules.end()); | ||||
modules.insert(module); | modules.insert(module); | ||||
@@ -106,11 +106,11 @@ void rackAddModule(Module *module) { | |||||
void rackRemoveModule(Module *module) { | void rackRemoveModule(Module *module) { | ||||
assert(module); | assert(module); | ||||
std::unique_lock<std::mutex> lock(mutex); | |||||
// Remove parameter interpolation which point to this module | // Remove parameter interpolation which point to this module | ||||
if (module == smoothModule) { | if (module == smoothModule) { | ||||
smoothModule = NULL; | smoothModule = NULL; | ||||
} | } | ||||
// FIXME use a mutex here | |||||
// Check that all wires are disconnected | // Check that all wires are disconnected | ||||
for (Wire *wire : wires) { | for (Wire *wire : wires) { | ||||
assert(wire->outputModule != module); | assert(wire->outputModule != module); | ||||
@@ -124,6 +124,7 @@ void rackRemoveModule(Module *module) { | |||||
void rackConnectWire(Wire *wire) { | void rackConnectWire(Wire *wire) { | ||||
assert(wire); | assert(wire); | ||||
std::unique_lock<std::mutex> lock(mutex); | |||||
// It would probably be good to reset the wire voltage | // It would probably be good to reset the wire voltage | ||||
wire->value = 0.0; | wire->value = 0.0; | ||||
// Check that the wire is not already added | // Check that the wire is not already added | ||||
@@ -144,6 +145,7 @@ void rackConnectWire(Wire *wire) { | |||||
void rackDisconnectWire(Wire *wire) { | void rackDisconnectWire(Wire *wire) { | ||||
assert(wire); | assert(wire); | ||||
std::unique_lock<std::mutex> lock(mutex); | |||||
// Disconnect wire from inputModule | // Disconnect wire from inputModule | ||||
wire->inputModule->inputs[wire->inputId] = NULL; | wire->inputModule->inputs[wire->inputId] = NULL; | ||||
wire->outputModule->outputs[wire->outputId] = NULL; | wire->outputModule->outputs[wire->outputId] = NULL; | ||||
@@ -1 +0,0 @@ | |||||
../src/rack.cpp.o: ../src/rack.cpp ../src/rack.hpp |
@@ -17,9 +17,9 @@ struct NewItem : MenuItem { | |||||
struct SaveItem : MenuItem { | struct SaveItem : MenuItem { | ||||
void onAction() { | void onAction() { | ||||
const char *path = noc_file_dialog_open(NOC_FILE_DIALOG_SAVE, filters, NULL, "Untitled.json"); | const char *path = noc_file_dialog_open(NOC_FILE_DIALOG_SAVE, filters, NULL, "Untitled.json"); | ||||
printf("Saving patch %s\n", path); | |||||
if (path) { | if (path) { | ||||
printf("Saving patch %s\n", path); | |||||
FILE *file = fopen(path, "w"); | FILE *file = fopen(path, "w"); | ||||
json_t *root = gRackWidget->toJson(); | json_t *root = gRackWidget->toJson(); | ||||
@@ -35,9 +35,9 @@ struct SaveItem : MenuItem { | |||||
struct OpenItem : MenuItem { | struct OpenItem : MenuItem { | ||||
void onAction() { | void onAction() { | ||||
const char *path = noc_file_dialog_open(NOC_FILE_DIALOG_OPEN, filters, NULL, NULL); | const char *path = noc_file_dialog_open(NOC_FILE_DIALOG_OPEN, filters, NULL, NULL); | ||||
printf("Loading patch %s\n", path); | |||||
if (path) { | if (path) { | ||||
printf("Loading patch %s\n", path); | |||||
FILE *file = fopen(path, "r"); | FILE *file = fopen(path, "r"); | ||||
json_error_t error; | json_error_t error; | ||||