Browse Source

Initial commit

Signed-off-by: falkTX <falktx@falktx.com>
main
falkTX 7 months ago
commit
ec6fc585ba
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
9 changed files with 650 additions and 0 deletions
  1. +6
    -0
      .gitignore
  2. +2
    -0
      .kdev4/kuriborosu.kdev4
  3. +33
    -0
      Makefile
  4. +345
    -0
      Makefile.base.mk
  5. +16
    -0
      README.md
  6. +4
    -0
      kuriborosu.kdev4
  7. +2
    -0
      src/.kdev_include_paths
  8. +72
    -0
      src/Makefile
  9. +170
    -0
      src/kuriborosu.c

+ 6
- 0
.gitignore View File

@@ -0,0 +1,6 @@
/bin/
/build/

*.mid
*.midi
*.wav

+ 2
- 0
.kdev4/kuriborosu.kdev4 View File

@@ -0,0 +1,2 @@
[Project]
VersionControlSupport=kdevgit

+ 33
- 0
Makefile View File

@@ -0,0 +1,33 @@
#!/usr/bin/make -f
# Makefile for DIE-Plugins #
# ------------------------ #
# Created by falkTX
#

include Makefile.base.mk

PREFIX ?= /usr/local

# --------------------------------------------------------------

all: build

# --------------------------------------------------------------

build:
$(MAKE) -C src

# --------------------------------------------------------------

clean:
$(MAKE) clean -C src

# --------------------------------------------------------------

install:
install -d $(DESTDIR)$(PREFIX)/bin
install -m 755 bin/koriborusu $(DESTDIR)$(PREFIX)/bin/

# --------------------------------------------------------------

.PHONY: build

+ 345
- 0
Makefile.base.mk View File

@@ -0,0 +1,345 @@
#!/usr/bin/make -f
# Makefile for DIE-Plugins #
# ------------------------ #
# Created by falkTX
#

AR ?= ar
CC ?= gcc
CXX ?= g++

# ---------------------------------------------------------------------------------------------------------------------
# Auto-detect OS if not defined

TARGET_MACHINE := $(shell $(CC) -dumpmachine)

ifneq ($(BSD),true)
ifneq ($(HAIKU),true)
ifneq ($(HURD),true)
ifneq ($(LINUX),true)
ifneq ($(MACOS),true)
ifneq ($(WINDOWS),true)

ifneq (,$(findstring bsd,$(TARGET_MACHINE)))
BSD=true
endif
ifneq (,$(findstring haiku,$(TARGET_MACHINE)))
HAIKU=true
endif
ifneq (,$(findstring gnu,$(TARGET_MACHINE)))
HURD=true
endif
ifneq (,$(findstring linux,$(TARGET_MACHINE)))
LINUX=true
endif
ifneq (,$(findstring apple,$(TARGET_MACHINE)))
MACOS=true
endif
ifneq (,$(findstring mingw,$(TARGET_MACHINE)))
WINDOWS=true
endif

endif
endif
endif
endif
endif
endif

# ---------------------------------------------------------------------------------------------------------------------
# Auto-detect the processor

TARGET_PROCESSOR := $(firstword $(subst -, ,$(TARGET_MACHINE)))

ifneq (,$(filter i%86,$(TARGET_PROCESSOR)))
CPU_I386=true
CPU_I386_OR_X86_64=true
endif
ifneq (,$(filter x86_64,$(TARGET_PROCESSOR)))
CPU_X86_64=true
CPU_I386_OR_X86_64=true
endif
ifneq (,$(filter arm%,$(TARGET_PROCESSOR)))
CPU_ARM=true
CPU_ARM_OR_AARCH64=true
endif
ifneq (,$(filter arm64%,$(TARGET_PROCESSOR)))
CPU_ARM64=true
CPU_ARM_OR_AARCH64=true
endif
ifneq (,$(filter aarch64%,$(TARGET_PROCESSOR)))
CPU_AARCH64=true
CPU_ARM_OR_AARCH64=true
endif

# ---------------------------------------------------------------------------------------------------------------------
# Set PKG_CONFIG (can be overridden by environment variable)

ifeq ($(WINDOWS),true)
# Build statically on Windows by default
PKG_CONFIG ?= pkg-config --static
else
PKG_CONFIG ?= pkg-config
endif

# ---------------------------------------------------------------------------------------------------------------------
# Set LINUX_OR_MACOS

ifeq ($(LINUX),true)
LINUX_OR_MACOS=true
endif

ifeq ($(MACOS),true)
LINUX_OR_MACOS=true
endif

# ---------------------------------------------------------------------------------------------------------------------
# Set MACOS_OR_WINDOWS and HAIKU_OR_MACOS_OR_WINDOWS

ifeq ($(HAIKU),true)
HAIKU_OR_MACOS_OR_WINDOWS=true
endif

ifeq ($(MACOS),true)
MACOS_OR_WINDOWS=true
HAIKU_OR_MACOS_OR_WINDOWS=true
endif

ifeq ($(WINDOWS),true)
MACOS_OR_WINDOWS=true
HAIKU_OR_MACOS_OR_WINDOWS=true
endif

# ---------------------------------------------------------------------------------------------------------------------
# Set UNIX

ifeq ($(BSD),true)
UNIX=true
endif

ifeq ($(HURD),true)
UNIX=true
endif

ifeq ($(LINUX),true)
UNIX=true
endif

ifeq ($(MACOS),true)
UNIX=true
endif

# ---------------------------------------------------------------------------------------------------------------------
# Set build and link flags

BASE_FLAGS = -Wall -Wextra -pipe -MD -MP
BASE_OPTS = -O3 -ffast-math -fdata-sections -ffunction-sections

ifeq ($(CPU_I386_OR_X86_64),true)
BASE_OPTS += -mtune=generic -msse -msse2 -mfpmath=sse
endif

ifeq ($(CPU_ARM),true)
ifneq ($(CPU_ARM64),true)
BASE_OPTS += -mfpu=neon-vfpv4 -mfloat-abi=hard
endif
endif

ifeq ($(MACOS),true)
# MacOS linker flags
LINK_OPTS = -fdata-sections -ffunction-sections -Wl,-dead_strip -Wl,-dead_strip_dylibs
else
# Common linker flags
LINK_OPTS = -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-O1 -Wl,--as-needed
ifneq ($(SKIP_STRIPPING),true)
LINK_OPTS += -Wl,--strip-all
endif
endif

ifeq ($(NOOPT),true)
# No CPU-specific optimization flags
BASE_OPTS = -O2 -ffast-math -fdata-sections -ffunction-sections
endif

ifeq ($(WINDOWS),true)
# mingw has issues with this specific optimization
# See https://github.com/falkTX/Carla/issues/696
BASE_OPTS += -fno-rerun-cse-after-loop
# See https://github.com/falkTX/Carla/issues/855
BASE_OPTS += -mstackrealign
else
# Not needed for Windows
BASE_FLAGS += -fPIC -DPIC
endif

ifeq ($(DEBUG),true)
BASE_FLAGS += -DDEBUG -O0 -g
LINK_OPTS =
else
BASE_FLAGS += -DNDEBUG $(BASE_OPTS) -fvisibility=hidden
CXXFLAGS += -fvisibility-inlines-hidden
endif

BUILD_C_FLAGS = $(BASE_FLAGS) -std=gnu99 $(CFLAGS)
BUILD_CXX_FLAGS = $(BASE_FLAGS) -std=gnu++0x $(CXXFLAGS)
LINK_FLAGS = $(LINK_OPTS) $(LDFLAGS)

ifneq ($(MACOS),true)
# Not available on MacOS
LINK_FLAGS += -Wl,--no-undefined
endif

ifeq ($(MACOS_OLD),true)
BUILD_CXX_FLAGS = $(BASE_FLAGS) $(CXXFLAGS) -DHAVE_CPP11_SUPPORT=0
endif

ifeq ($(WINDOWS),true)
# Always build statically on windows
LINK_FLAGS += -static
endif

# ---------------------------------------------------------------------------------------------------------------------
# Strict test build

ifeq ($(TESTBUILD),true)
BASE_FLAGS += -Werror -Wcast-qual -Wconversion -Wformat -Wformat-security -Wredundant-decls -Wshadow -Wstrict-overflow -fstrict-overflow -Wundef -Wwrite-strings
BASE_FLAGS += -Wpointer-arith -Wabi -Winit-self -Wuninitialized -Wstrict-overflow=5
# BASE_FLAGS += -Wfloat-equal
ifeq ($(CC),clang)
BASE_FLAGS += -Wdocumentation -Wdocumentation-unknown-command
BASE_FLAGS += -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded -Wno-exit-time-destructors -Wno-float-equal
else
BASE_FLAGS += -Wcast-align -Wunsafe-loop-optimizations
endif
ifneq ($(MACOS),true)
BASE_FLAGS += -Wmissing-declarations -Wsign-conversion
ifneq ($(CC),clang)
BASE_FLAGS += -Wlogical-op
endif
endif
CFLAGS += -Wold-style-definition -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes
CXXFLAGS += -Weffc++ -Wnon-virtual-dtor -Woverloaded-virtual
endif

# ---------------------------------------------------------------------------------------------------------------------
# Check for required libraries

HAVE_CAIRO = $(shell $(PKG_CONFIG) --exists cairo && echo true)

ifeq ($(HAIKU_OR_MACOS_OR_WINDOWS),true)
HAVE_OPENGL = true
else
HAVE_OPENGL = $(shell $(PKG_CONFIG) --exists gl && echo true)
HAVE_X11 = $(shell $(PKG_CONFIG) --exists x11 && echo true)
endif

# ---------------------------------------------------------------------------------------------------------------------
# Check for optional libraries

HAVE_JACK = $(shell $(PKG_CONFIG) --exists jack && echo true)
HAVE_LIBLO = $(shell $(PKG_CONFIG) --exists liblo && echo true)

# ---------------------------------------------------------------------------------------------------------------------
# Set Generic DGL stuff

ifeq ($(HAIKU),true)
DGL_SYSTEM_LIBS += -lbe
endif

ifeq ($(MACOS),true)
DGL_SYSTEM_LIBS += -framework Cocoa
endif

ifeq ($(WINDOWS),true)
DGL_SYSTEM_LIBS += -lgdi32 -lcomdlg32
endif

ifneq ($(HAIKU_OR_MACOS_OR_WINDOWS),true)
ifeq ($(HAVE_X11),true)
DGL_FLAGS += $(shell $(PKG_CONFIG) --cflags x11)
DGL_SYSTEM_LIBS += $(shell $(PKG_CONFIG) --libs x11)
endif
endif

# ---------------------------------------------------------------------------------------------------------------------
# Set Cairo specific stuff

ifeq ($(HAVE_CAIRO),true)

DGL_FLAGS += -DHAVE_CAIRO

CAIRO_FLAGS = $(shell $(PKG_CONFIG) --cflags cairo)
CAIRO_LIBS = $(shell $(PKG_CONFIG) --libs cairo)

HAVE_CAIRO_OR_OPENGL = true

endif

# ---------------------------------------------------------------------------------------------------------------------
# Set OpenGL specific stuff

ifeq ($(HAVE_OPENGL),true)

DGL_FLAGS += -DHAVE_OPENGL

ifeq ($(HAIKU),true)
OPENGL_FLAGS = $(shell $(PKG_CONFIG) --cflags gl)
OPENGL_LIBS = $(shell $(PKG_CONFIG) --libs gl)
endif

ifeq ($(MACOS),true)
OPENGL_LIBS = -framework OpenGL
endif

ifeq ($(WINDOWS),true)
OPENGL_LIBS = -lopengl32
endif

ifneq ($(HAIKU_OR_MACOS_OR_WINDOWS),true)
OPENGL_FLAGS = $(shell $(PKG_CONFIG) --cflags gl x11)
OPENGL_LIBS = $(shell $(PKG_CONFIG) --libs gl x11)
endif

HAVE_CAIRO_OR_OPENGL = true

endif

# ---------------------------------------------------------------------------------------------------------------------
# Set app extension

ifeq ($(WINDOWS),true)
APP_EXT = .exe
endif

# ---------------------------------------------------------------------------------------------------------------------
# Set shared lib extension

LIB_EXT = .so

ifeq ($(MACOS),true)
LIB_EXT = .dylib
endif

ifeq ($(WINDOWS),true)
LIB_EXT = .dll
endif

# ---------------------------------------------------------------------------------------------------------------------
# Set shared library CLI arg

ifeq ($(MACOS),true)
SHARED = -dynamiclib
else
SHARED = -shared
endif

# ---------------------------------------------------------------------------------------------------------------------
# Handle the verbosity switch

ifeq ($(VERBOSE),true)
SILENT =
else
SILENT = @
endif

# ---------------------------------------------------------------------------------------------------------------------

+ 16
- 0
README.md View File

@@ -0,0 +1,16 @@
# 🌰 koriborosu 🌰

A simple Audio and MIDI file render, powered by [Carla Plugin Host](https://github.com/falkTX/Carla)

Still very much work-in-progress, but the idea is simply:

* Specify 1 input file to read (can be an audio or MIDI file, optionally also just a number of seconds)
* Specify what plugins to run after, in order of processing

Koriborosu will run the plugins and generate an audio file at the end with its output.

This can be used to:

* Simple render of a MIDI file to WAV via softsynth
* Render a MIDI file, with added MIDI filters on top, then synths, then some FX because why not
* Apply some FX on an audio file

+ 4
- 0
kuriborosu.kdev4 View File

@@ -0,0 +1,4 @@
[Project]
CreatedFrom=Makefile
Manager=KDevCustomMakeManager
Name=kuriborosu

+ 2
- 0
src/.kdev_include_paths View File

@@ -0,0 +1,2 @@
/usr/include/carla/
/usr/include/carla/includes/

+ 72
- 0
src/Makefile View File

@@ -0,0 +1,72 @@
#!/usr/bin/make -f
# Makefile for ACE #
# ---------------- #
# Created by falkTX
#

include ../Makefile.base.mk

# --------------------------------------------------------------
# Project name, used for binaries

NAME = kuriborosu

# --------------------------------------------------------------
# Files to build

FILES = \
kuriborosu.c

# ---------------------------------------------------------------------------------------------------------------------
# Basic setup

TARGET_DIR = ../bin
BUILD_DIR = ../build/$(NAME)

# BASE_FLAGS += -I.
BASE_FLAGS += $(shell pkg-config --cflags carla-host-plugin sndfile)
LINK_FLAGS += $(shell pkg-config --libs carla-host-plugin sndfile)

# BUILD_C_FLAGS += -I.
# BUILD_CXX_FLAGS += -I.

# ---------------------------------------------------------------------------------------------------------------------
# Set files to build

OBJS = $(FILES:%=$(BUILD_DIR)/%.o)

# ---------------------------------------------------------------------------------------------------------------------
# Default build target

TARGET = $(TARGET_DIR)/$(NAME)

all: build

build: $(TARGET)

# ---------------------------------------------------------------------------------------------------------------------
# Build commands

$(TARGET): $(OBJS)
-@mkdir -p $(shell dirname $@)
@echo "Linking $(NAME)"
$(SILENT)$(CXX) $^ $(LINK_FLAGS) -o $@

$(BUILD_DIR)/%.c.o: %.c
-@mkdir -p "$(shell dirname $(BUILD_DIR)/$<)"
@echo "Compiling $<"
$(SILENT)$(CC) $< $(BUILD_C_FLAGS) -c -o $@

$(BUILD_DIR)/%.cpp.o: %.cpp
-@mkdir -p "$(shell dirname $(BUILD_DIR)/$<)"
@echo "Compiling $<"
$(SILENT)$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@

clean:
rm -rf $(BUILD_DIR)

# ---------------------------------------------------------------------------------------------------------------------

-include $(OBJS:%.o=%.d)

# ---------------------------------------------------------------------------------------------------------------------

+ 170
- 0
src/kuriborosu.c View File

@@ -0,0 +1,170 @@
// TODO license header here

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sndfile.h>

#include "CarlaNativePlugin.h"

typedef struct {
uint32_t buffer_size;
double sample_rate;
NativeTimeInfo time;
} Koriborosu;

#define koriborosu ((Koriborosu*)handle)

static uint32_t get_buffer_size(NativeHostHandle handle)
{
return koriborosu->buffer_size;
}

static double get_sample_rate(NativeHostHandle handle)
{
return koriborosu->sample_rate;
}

static bool is_offline(NativeHostHandle handle)
{
return true;
}

static const NativeTimeInfo* get_time_info(NativeHostHandle handle)
{
return &koriborosu->time;
}

static bool write_midi_event(NativeHostHandle handle, const NativeMidiEvent* event)
{
return false;
}

static void ui_parameter_changed(NativeHostHandle handle, uint32_t index, float value)
{
}

static void ui_midi_program_changed(NativeHostHandle handle, uint8_t channel, uint32_t bank, uint32_t program)
{
}

static void ui_custom_data_changed(NativeHostHandle handle, const char* key, const char* value)
{
}

static void ui_closed(NativeHostHandle handle)
{
}

static const char* ui_open_file(NativeHostHandle handle, bool isDir, const char* title, const char* filter)
{
// not supported
return NULL;
}

static const char* ui_save_file(NativeHostHandle handle, bool isDir, const char* title, const char* filter)
{
// not supported
return NULL;
}

static intptr_t dispatcher(NativeHostHandle handle,
NativeHostDispatcherOpcode opcode, int32_t index, intptr_t value, void* ptr, float opt)
{
return 0;
}

#undef koriborosu

// TODO argument handling
int main()
{
// TODO read from CLI args
uint32_t opts_buffer_size = 1024;
uint32_t opts_sample_rate = 48000;
const char* inmidi = "/home/falktx/Personal/Muzyks/Projects/MIDI-Classic/clairdelune.mid";
const char* outwav = "/Shared/Personal/FOSS/GIT/falkTX/kuriborosu/testfile.wav";
const char* pluginuri1 = "http://drobilla.net/plugins/mda/Piano";
const char* pluginuri2 = "https://github.com/michaelwillis/dragonfly-reverb";

Koriborosu kori;
memset(&kori, 0, sizeof(kori));
kori.buffer_size = opts_buffer_size;
kori.sample_rate = opts_sample_rate;

NativeHostDescriptor hdesc;
memset(&hdesc, 0, sizeof(hdesc));
hdesc.handle = &kori;
hdesc.resourceDir = carla_get_library_folder();
hdesc.get_buffer_size = get_buffer_size;
hdesc.get_sample_rate = get_sample_rate;
hdesc.is_offline = is_offline;
hdesc.get_time_info = get_time_info;
hdesc.write_midi_event = write_midi_event;
hdesc.ui_parameter_changed = ui_parameter_changed;
hdesc.ui_midi_program_changed = ui_midi_program_changed;
hdesc.ui_custom_data_changed = ui_custom_data_changed;
hdesc.ui_closed = ui_closed;
hdesc.ui_open_file = ui_open_file;
hdesc.ui_save_file = ui_save_file;
hdesc.dispatcher = dispatcher;

const NativePluginDescriptor* const pdesc = carla_get_native_rack_plugin();
const NativePluginHandle phandle = pdesc->instantiate(&hdesc);
pdesc->activate(&hdesc);

const CarlaHostHandle hhandle = carla_create_native_plugin_host_handle(pdesc, phandle);

carla_load_file(hhandle, inmidi);
carla_add_plugin(hhandle, BINARY_NATIVE, PLUGIN_LV2, "", "", pluginuri1, 0, NULL, 0x0);
carla_add_plugin(hhandle, BINARY_NATIVE, PLUGIN_LV2, "", "", pluginuri2, 0, NULL, 0x0);

// TODO read from audio/midi plugin
uint32_t file_frames = 100 * opts_sample_rate;

SF_INFO sf_fmt = {
.frames = 0,
.samplerate = opts_sample_rate,
.channels = 2,
.format = SF_FORMAT_WAV|SF_FORMAT_PCM_16,
.sections = 0,
.seekable = 0,
};
SNDFILE* const file = sf_open(outwav, SFM_WRITE, &sf_fmt);

float* bufN = calloc(1, sizeof(float)*opts_buffer_size);
float* bufL = malloc(sizeof(float)*opts_buffer_size);
float* bufR = malloc(sizeof(float)*opts_buffer_size);
float* bufI = malloc(sizeof(float)*opts_buffer_size*2);

float* inbuf[2] = { bufN, bufN };
float* outbuf[2] = { bufL, bufR };

kori.time.playing = true;

for (uint32_t i = 0; i < file_frames; i += opts_buffer_size)
{
kori.time.frame = i;
pdesc->process(phandle, inbuf, outbuf, opts_buffer_size, NULL, 0);

// interleave
for (uint32_t j = 0, k = 0; j < opts_buffer_size*2; j += 2, ++k)
{
bufI[j+0] = bufL[k];
bufI[j+1] = bufR[k];
}

sf_writef_float(file, bufI, opts_buffer_size);
}

free(bufN);
free(bufL);
free(bufR);
sf_close(file);
pdesc->deactivate(phandle);
pdesc->cleanup(phandle);
carla_host_handle_free(hhandle);
return EXIT_SUCCESS;
}

Loading…
Cancel
Save