@@ -1,7 +1,6 @@ | |||
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 | |||
LDFLAGS = | |||
@@ -16,20 +15,20 @@ CXX = g++ | |||
SOURCES += lib/noc/noc_file_dialog.c | |||
CFLAGS += -DNOC_FILE_DIALOG_GTK $(shell pkg-config --cflags gtk+-2.0) | |||
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) | |||
TARGET = 5V | |||
TARGET = Rack | |||
endif | |||
# 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 | |||
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 | |||
# Windows | |||
@@ -39,40 +38,19 @@ CXX = x86_64-w64-mingw32-g++ | |||
SOURCES += lib/noc/noc_file_dialog.c | |||
CFLAGS += -DNOC_FILE_DIALOG_WIN32 | |||
CXXFLAGS += -DWINDOWS | |||
LDFLAGS = -lpthread -ljansson \ | |||
LDFLAGS += -lpthread -ljansson \ | |||
./lib/nanovg/build/libnanovg.a -lglfw3 -lgdi32 -lopengl32 -lglew32 \ | |||
./lib/rtaudio/librtaudio.a -lksuser -luuid \ | |||
./lib/rtmidi/librtmidi.a -lwinmm \ | |||
-lcomdlg32 -lole32 \ | |||
-Wl,--export-all-symbols,--out-implib,lib5V.a -mwindows | |||
TARGET = 5V.exe | |||
TARGET = Rack.exe | |||
endif | |||
OBJECTS = $(patsubst %, build/%.o, $(SOURCES)) | |||
DEPS = $(patsubst %, build/%.d, $(SOURCES)) | |||
# Final targets | |||
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. | |||
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; | |||
audio1Buffer[i] = getf(inputs[AUDIO1_INPUT]); | |||
audio2Buffer[i] = getf(inputs[AUDIO2_INPUT]); | |||
std::unique_lock<std::mutex> lock(mutex); | |||
// std::unique_lock<std::mutex> lock(mutex); | |||
bufferFrame++; | |||
if (bufferFrame == audioFrameNeeded) { | |||
lock.unlock(); | |||
// lock.unlock(); | |||
cv.notify_all(); | |||
} | |||
} | |||
@@ -83,7 +83,7 @@ void AudioInterface::openDevice(int deviceId) { | |||
streamParams.nChannels = 2; | |||
streamParams.firstChannel = 0; | |||
unsigned int sampleRate = SAMPLE_RATE; | |||
unsigned int bufferFrames = 256; | |||
unsigned int bufferFrames = 512; | |||
audioFrame = -1; | |||
running = true; | |||
@@ -183,11 +183,11 @@ struct AudioChoice : ChoiceButton { | |||
AudioInterfaceWidget::AudioInterfaceWidget() : ModuleWidget(new AudioInterface()) { | |||
box.size = Vec(15*4, 380); | |||
box.size = Vec(15*8, 380); | |||
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->audioInterface = dynamic_cast<AudioInterface*>(module); | |||
@@ -187,11 +187,11 @@ struct MidiChoice : ChoiceButton { | |||
MidiInterfaceWidget::MidiInterfaceWidget() : ModuleWidget(new MidiInterface()) { | |||
box.size = Vec(15*4, 380); | |||
box.size = Vec(15*8, 380); | |||
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->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) { | |||
Vec mousePos = Vec(xpos, ypos); | |||
Vec mousePos = Vec(xpos, ypos).round(); | |||
Vec mouseRel = mousePos.minus(gMousePos); | |||
gMousePos = mousePos; | |||
@@ -169,15 +169,15 @@ void guiInit() { | |||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); | |||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); | |||
window = glfwCreateWindow(1020, 700, "5V", NULL, NULL); | |||
window = glfwCreateWindow(1020, 700, "Rack", NULL, NULL); | |||
assert(window); | |||
glfwMakeContextCurrent(window); | |||
glfwSetWindowSizeCallback(window, windowSizeCallback); | |||
glfwSetMouseButtonCallback(window, mouseButtonCallback); | |||
// glfwSetCursorPosCallback(window, cursorPosCallback); | |||
// glfwSetCursorPosCallback(window, cursorPosCallback); | |||
glfwSetCursorEnterCallback(window, cursorEnterCallback); | |||
glfwSetScrollCallback(window, scrollCallback); | |||
glfwSetScrollCallback(window, scrollCallback); | |||
glfwSetCharCallback(window, charCallback); | |||
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 <time.h> | |||
#include <unistd.h> | |||
Scene *gScene = NULL; | |||
@@ -74,8 +74,13 @@ void pluginInit() { | |||
loadPlugin("plugins/AudibleInstruments/plugin.dll"); | |||
#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("plugins/*/plugin.so", GLOB_TILDE, NULL, &result); | |||
glob(globPath, GLOB_TILDE, NULL, &result); | |||
for (int i = 0; i < (int) result.gl_pathc; 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 | |||
if (smoothModule) { | |||
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 | |||
float delta = smoothValue - value; | |||
float speed = fmaxf(fabsf(delta) * lpCoeff, minSpeed); | |||
@@ -74,10 +74,9 @@ void rackRun() { | |||
cv.wait_for(lock, std::chrono::milliseconds(1)); | |||
} | |||
frame++; | |||
lock.unlock(); | |||
// 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) { | |||
assert(module); | |||
std::unique_lock<std::mutex> lock(mutex); | |||
// Check that the module is not already added | |||
assert(modules.find(module) == modules.end()); | |||
modules.insert(module); | |||
@@ -106,11 +106,11 @@ void rackAddModule(Module *module) { | |||
void rackRemoveModule(Module *module) { | |||
assert(module); | |||
std::unique_lock<std::mutex> lock(mutex); | |||
// Remove parameter interpolation which point to this module | |||
if (module == smoothModule) { | |||
smoothModule = NULL; | |||
} | |||
// FIXME use a mutex here | |||
// Check that all wires are disconnected | |||
for (Wire *wire : wires) { | |||
assert(wire->outputModule != module); | |||
@@ -124,6 +124,7 @@ void rackRemoveModule(Module *module) { | |||
void rackConnectWire(Wire *wire) { | |||
assert(wire); | |||
std::unique_lock<std::mutex> lock(mutex); | |||
// It would probably be good to reset the wire voltage | |||
wire->value = 0.0; | |||
// Check that the wire is not already added | |||
@@ -144,6 +145,7 @@ void rackConnectWire(Wire *wire) { | |||
void rackDisconnectWire(Wire *wire) { | |||
assert(wire); | |||
std::unique_lock<std::mutex> lock(mutex); | |||
// Disconnect wire from inputModule | |||
wire->inputModule->inputs[wire->inputId] = 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 { | |||
void onAction() { | |||
const char *path = noc_file_dialog_open(NOC_FILE_DIALOG_SAVE, filters, NULL, "Untitled.json"); | |||
printf("Saving patch %s\n", path); | |||
if (path) { | |||
printf("Saving patch %s\n", path); | |||
FILE *file = fopen(path, "w"); | |||
json_t *root = gRackWidget->toJson(); | |||
@@ -35,9 +35,9 @@ struct SaveItem : MenuItem { | |||
struct OpenItem : MenuItem { | |||
void onAction() { | |||
const char *path = noc_file_dialog_open(NOC_FILE_DIALOG_OPEN, filters, NULL, NULL); | |||
printf("Loading patch %s\n", path); | |||
if (path) { | |||
printf("Loading patch %s\n", path); | |||
FILE *file = fopen(path, "r"); | |||
json_error_t error; | |||