Browse Source

Init commit

Luciano Dato 7 years ago
parent
commit
bf972c20c9
7 changed files with 520 additions and 0 deletions
  1. 115 0
      Makefile
  2. 7 0
      doxygen.conf
  3. 43 0
      git2lv2.mk
  4. 7 0
      lv2ttl/manifest.ttl.in
  5. 59 0
      lv2ttl/sdenoise.ttl.in
  6. 275 0
      src/sdenoise.c
  7. 14 0
      static_rnnoise.sh

+ 115 - 0
Makefile

@@ -0,0 +1,115 @@
+#!/usr/bin/make -f
+OPTIMIZATIONS ?= -msse -msse2 -mfpmath=sse -ffast-math -fomit-frame-pointer -O3 -fno-finite-math-only
+PREFIX ?= /usr/local
+CFLAGS ?= $(OPTIMIZATIONS) -Wall
+
+STRIP?=strip
+STRIPFLAGS?=-s
+DEBUG?=0
+
+sdenoise_VERSION?=$(shell git describe --tags HEAD 2>/dev/null | sed 's/-g.*$$//;s/^v//' || echo "LV2")
+###############################################################################
+LIB_EXT=.so
+
+LV2DIR ?= $(PREFIX)/lib/lv2
+LV2NAME=sdenoise
+BUNDLE=sdenoise.lv2
+BUILDDIR=build/
+SRCDIR=src/
+TTLDIR=lv2ttl/
+targets=
+
+UNAME=$(shell uname)
+ifeq ($(UNAME),Darwin)
+  LV2LDFLAGS=-dynamiclib
+  LIB_EXT=.dylib
+  EXTENDED_RE=-E
+  STRIPFLAGS=-u -r -arch all -s lv2syms
+  targets+=lv2syms
+else
+  LV2LDFLAGS=-Wl,-Bstatic -Wl,-Bdynamic
+  LIB_EXT=.so
+  EXTENDED_RE=-r
+endif
+
+ifneq ($(XWIN),)
+  CC=$(XWIN)-gcc
+  STRIP=$(XWIN)-strip
+  LV2LDFLAGS=-Wl,-Bstatic -Wl,-Bdynamic -Wl,--as-needed
+  LIB_EXT=.dll
+  override LDFLAGS += -static-libgcc -static-libstdc++
+endif
+
+targets+=$(BUILDDIR)$(LV2NAME)$(LIB_EXT)
+
+###############################################################################
+# extract versions
+LV2VERSION=$(snrepel_VERSION)
+include git2lv2.mk
+
+# check for build-dependencies
+ifeq ($(shell pkg-config --exists lv2 || echo no), no)
+  $(error "LV2 SDK was not found")
+endif
+
+override CFLAGS += -fPIC -std=c99
+override CFLAGS += `pkg-config --cflags lv2`
+
+#compiling against a static build of rnnoise
+ifneq ($(shell test -f rnnoise/.libs/librnnoise.a || echo no), no)
+  LV2CFLAGS=$(CFLAGS) -Irnnoise/include
+  LOADLIBES=rnnoise/.libs/librnnoise.a -lm
+endif
+
+#for debug building
+ifeq ($(DEBUG), 1)
+  override CFLAGS += -g3 -DDEBUG
+else
+  override CFLAGS += -DNDEBUG
+endif
+
+# build target definitions
+default: all
+
+all: $(BUILDDIR)manifest.ttl $(BUILDDIR)$(LV2NAME).ttl $(targets)
+
+lv2syms:
+	echo "_lv2_descriptor" > lv2syms
+
+$(BUILDDIR)manifest.ttl: $(TTLDIR)manifest.ttl.in
+	@mkdir -p $(BUILDDIR)
+	sed "s/@LV2NAME@/$(LV2NAME)/;s/@LIB_EXT@/$(LIB_EXT)/" \
+	  $(TTLDIR)manifest.ttl.in > $(BUILDDIR)manifest.ttl
+
+$(BUILDDIR)$(LV2NAME).ttl: $(TTLDIR)$(LV2NAME).ttl.in
+	@mkdir -p $(BUILDDIR)
+	sed "s/@VERSION@/lv2:microVersion $(LV2MIC) ;lv2:minorVersion $(LV2MIN) ;/g" \
+		$(TTLDIR)$(LV2NAME).ttl.in > $(BUILDDIR)$(LV2NAME).ttl
+
+$(BUILDDIR)$(LV2NAME)$(LIB_EXT): $(SRCDIR)$(LV2NAME).c
+	@mkdir -p $(BUILDDIR)
+	$(CC) $(CPPFLAGS) $(CFLAGS) $(LV2CFLAGS) \
+		-o $(BUILDDIR)$(LV2NAME)$(LIB_EXT) $(SRCDIR)$(LV2NAME).c \
+		-shared $(LV2LDFLAGS) $(LDFLAGS) $(LOADLIBES)
+
+ifeq ($(DEBUG), 0)
+	$(STRIP) $(STRIPFLAGS) $(BUILDDIR)$(LV2NAME)$(LIB_EXT)
+endif
+
+# install/uninstall/clean target definitions
+install: all
+	install -d $(DESTDIR)$(LV2DIR)/$(BUNDLE)
+	install -m644 $(BUILDDIR)$(LV2NAME)$(LIB_EXT) $(DESTDIR)$(LV2DIR)/$(BUNDLE)
+	install -m644 $(BUILDDIR)manifest.ttl $(BUILDDIR)$(LV2NAME).ttl $(DESTDIR)$(LV2DIR)/$(BUNDLE)
+
+uninstall:
+	rm -f $(DESTDIR)$(LV2DIR)/$(BUNDLE)/manifest.ttl
+	rm -f $(DESTDIR)$(LV2DIR)/$(BUNDLE)/$(LV2NAME).ttl
+	rm -f $(DESTDIR)$(LV2DIR)/$(BUNDLE)/$(LV2NAME)$(LIB_EXT)
+	-rmdir $(DESTDIR)$(LV2DIR)/$(BUNDLE)
+
+clean:
+	rm -f $(BUILDDIR)manifest.ttl $(BUILDDIR)$(LV2NAME).ttl $(BUILDDIR)$(LV2NAME)$(LIB_EXT) lv2syms
+	-test -d $(BUILDDIR) && rmdir $(BUILDDIR) || true
+
+.PHONY: clean all install uninstall

+ 7 - 0
doxygen.conf

@@ -0,0 +1,7 @@
+PROJECT_NAME = "Noise Repellent"
+PROJECT_BRIEF = "An lv2 plugin for broadband noise reduction"
+OUTPUT_DIRECTORY = "doc"
+INPUT = "src"
+EXTRACT_STATIC = YES
+GENERATE_LATEX = NO
+OPTIMIZE_OUTPUT_FOR_C = YES

+ 43 - 0
git2lv2.mk

@@ -0,0 +1,43 @@
+
+###############################################################################
+# extract versions
+GIT_REV_REGEXP="([0-9][0-9]*)\.([0-9][0-9]*)(\.([0-9][0-9]*))?(-([0-9][0-9]*))?(-g([a-f0-9]+))?"
+
+override MAJOR=$(shell echo $(LV2VERSION) | sed $(EXTENDED_RE) -e s/$(GIT_REV_REGEXP)/\\1/)
+override MINOR=$(shell echo $(LV2VERSION) | sed $(EXTENDED_RE) -e s/$(GIT_REV_REGEXP)/\\2/)
+override MICRO=$(shell echo $(LV2VERSION) | sed $(EXTENDED_RE) -e s/$(GIT_REV_REGEXP)/\\4/)
+override GITREV=$(shell echo $(LV2VERSION) | sed $(EXTENDED_RE) -e s/$(GIT_REV_REGEXP)/\\6/)
+
+ifeq ($(MAJOR),)
+  override MAJOR=0
+endif
+ifeq ($(MINOR),)
+  override MINOR=0
+endif
+ifeq ($(MICRO),)
+  override MICRO=0
+endif
+
+$(info Version: $(LV2VERSION) -> $(MAJOR) $(MINOR) $(MICRO) $(GITREV))
+
+# version requirements, see
+# http://lv2plug.in/ns/lv2core/#minorVersion
+# http://lv2plug.in/ns/lv2core/#microVersion
+ifeq ($(GITREV),)
+# even numbers for tagged releases
+  override LV2MIN = $(shell expr $(MAJOR) \* 65536 + $(MINOR) \* 256 + $(MICRO) \* 2 )
+  override LV2MIC = 0
+else
+# odd-numbers for all non tagged git versions
+  override LV2MIN = $(shell expr $(MAJOR) \* 65536 + $(MINOR) \* 256 + $(MICRO) \* 2 + 1 )
+  override LV2MIC = $(shell expr $(GITREV) \* 2 + 1)
+endif
+
+ifeq ($(LV2MIN),)
+  $(error "Cannot extract required LV2 minor-version parameter")
+endif
+ifeq ($(LV2MIC),)
+  $(error "Cannot extract required LV2 micro-version parameter")
+endif
+
+$(info LV2 Version: $(LV2MIN) $(LV2MIC))

+ 7 - 0
lv2ttl/manifest.ttl.in

@@ -0,0 +1,7 @@
+@prefix lv2:  <http://lv2plug.in/ns/lv2core#>.
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
+
+<https://github.com/lucianodato/speech-denoise>
+  a lv2:Plugin;
+  lv2:binary <sdenoise.so> ;
+  rdfs:seeAlso <sdenoise.ttl> .

+ 59 - 0
lv2ttl/sdenoise.ttl.in

@@ -0,0 +1,59 @@
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix param: <http://lv2plug.in/ns/ext/parameters#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix pg: <http://lv2plug.in/ns/ext/port-groups#> .
+@prefix pprop: <http://lv2plug.in/ns/ext/port-props#> .
+@prefix units: <http://lv2plug.in/ns/extensions/units#> .
+
+
+<http://example.com/lucianodato#me>
+  a foaf:Person ;
+  foaf:name "Luciano Dato" ;
+  foaf:homepage <https://github.com/lucianodato> ;
+  foaf:mbox <mailto:lucianodato@gmail.com> .
+
+<https://github.com/lucianodato/speech-denoise>
+  a lv2:Plugin, lv2:SpectralPlugin, lv2:UtilityPlugin, doap:Project ;
+  doap:maintainer <http://example.com/lucianodato#me> ;
+  doap:license <https://opensource.org/licenses/LGPL-3.0> ;
+  doap:name "Speech Denoise";
+  @VERSION@
+  lv2:optionalFeature lv2:hardRTCapable ;
+
+  lv2:port [
+    a lv2:InputPort, lv2:ControlPort ;
+    lv2:index 0 ;
+    lv2:name "Enable" ;
+    lv2:symbol "enable" ;
+    lv2:default 1.0 ;
+    lv2:minimum 0.0 ;
+    lv2:maximum 1.0 ;
+    lv2:portProperty lv2:toggled, pprop:notOnGUI;
+    lv2:designation <http://ardour.org/lv2/processing#enable>;
+  ], [
+    a lv2:OutputPort,
+      lv2:ControlPort ;
+    lv2:name "latency" ;
+    lv2:index 1 ;
+    lv2:symbol "latency" ;
+    lv2:minimum 0 ;
+    lv2:maximum 8192 ;
+    lv2:portProperty lv2:reportsLatency, lv2:integer, pprop:notOnGUI ;
+    units:unit units:samples ;
+  ], [
+    a lv2:AudioPort,
+      lv2:InputPort ;
+    lv2:index 2 ;
+    lv2:symbol "input" ;
+    lv2:name "Input" ;
+  ], [
+    a lv2:AudioPort,
+      lv2:OutputPort ;
+    lv2:index 3 ;
+    lv2:symbol "output" ;
+    lv2:name "Output" ;
+  ];
+.

+ 275 - 0
src/sdenoise.c

@@ -0,0 +1,275 @@
+/*
+noise-repellent -- Noise Reduction LV2
+
+Copyright 2016 Luciano Dato <lucianodato@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/
+*/
+
+/**
+* \file snrepel.c
+* \author Luciano Dato
+* \brief The main file for host interaction
+*/
+
+#include <math.h>
+#include <float.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+
+#include <rnnoise.h>
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+
+#define SDENOISE_URI "https://github.com/lucianodato/speech-denoise"
+
+#define FRAME_SIZE 480 //Frame default size
+
+#define M_PI 3.14159265358979323846f
+
+///---------------------------------------------------------------------
+
+/**
+* Enumeration of LV2 ports.
+*/
+typedef enum
+{
+	NREPEL_ENABLE = 0,
+	NREPEL_LATENCY = 1,
+	NREPEL_INPUT = 2,
+	NREPEL_OUTPUT = 3,
+} PortIndex;
+
+/**
+* Struct for THE noise repellent instance, the host is going to use.
+*/
+typedef struct
+{
+	const float* input; //input of samples from host (changing size)
+	float* output; //output of samples to host (changing size)
+	float samp_rate; //Sample rate received from the host
+
+	//Parameters for the algorithm (user input)
+	float* enable; //For soft bypass (click free bypass)
+	float* report_latency; //Latency necessary
+
+	//Parameters values and arrays for the STFT
+	int frame_size; //RNNOISE frame input size
+
+	//Algorithm exta variables
+	float tau; //time constant for soft bypass
+	float wet_dry_target; //softbypass target for softbypass
+	float wet_dry; //softbypass coeff
+
+	//Buffers for processing and outputting
+	int input_latency;
+	float* in_fifo; //internal input buffer
+	float* out_fifo; //internal output buffer
+	float* input_frame;
+	float* processed_frame; //FFT output accumulator
+	int read_ptr; //buffers read pointer
+	int write_ptr; //buffers write pointer
+
+	DenoiseState *st;
+
+} SDenoise;
+
+/**
+* Instantiates the plugin.
+*/
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor, double rate, const char* bundle_path,
+						const LV2_Feature* const* features)
+{
+	//Actual struct declaration
+	SDenoise* self = (SDenoise*)calloc(1,sizeof(SDenoise));
+
+	//Sampling related
+	self->samp_rate = (float)rate;
+
+	//FFT related
+	self->frame_size = FRAME_SIZE;
+
+	//buffers for OLA
+	self->in_fifo = (float*)calloc(self->frame_size, sizeof(float));
+	self->out_fifo = (float*)calloc(self->frame_size, sizeof(float));
+	self->input_frame = (float*)calloc(self->frame_size, sizeof(float));
+	self->processed_frame = (float*)calloc(self->frame_size, sizeof(float));
+	self->input_latency = self->frame_size;
+	self->read_ptr = self->input_latency; //the initial position because we are that many samples ahead
+	self->write_ptr = 0; //the initial position because we are that many samples ahead
+
+	//soft bypass
+	self->tau = (1.f - expf(-2.f * M_PI * 25.f * 64.f  / self->samp_rate));
+	self->wet_dry = 0.f;
+
+	self->st = rnnoise_create();
+
+	return (LV2_Handle)self;
+}
+
+/**
+* Used by the host to connect the ports of this plugin.
+*/
+static void
+connect_port(LV2_Handle instance, uint32_t port, void* data)
+{
+	SDenoise* self = (SDenoise*)instance;
+
+	switch ((PortIndex)port)
+	{
+		case NREPEL_ENABLE:
+		self->enable = (float*)data;
+		break;
+		case NREPEL_LATENCY:
+		self->report_latency = (float*)data;
+		break;
+		case NREPEL_INPUT:
+		self->input = (const float*)data;
+		break;
+		case NREPEL_OUTPUT:
+		self->output = (float*)data;
+		break;
+	}
+}
+
+/**
+* Main process function of the plugin.
+*/
+static void
+run(LV2_Handle instance, uint32_t n_samples)
+{
+	SDenoise* self = (SDenoise*)instance;
+
+	//handy variables
+	int k;
+	unsigned int pos;
+
+	//Inform latency at run call
+	*(self->report_latency) = (float) self->input_latency;
+
+	//Softbypass targets in case of disabled or enabled
+	if(*(self->enable) == 0.f)
+	{ //if disabled
+		self->wet_dry_target = 0.f;
+	}
+	else
+	{ //if enabled
+		self->wet_dry_target = 1.f;
+	}
+	//Interpolate parameters over time softly to bypass without clicks or pops
+	self->wet_dry += self->tau * (self->wet_dry_target - self->wet_dry) + FLT_MIN;
+
+	//main loop for processing
+	for (pos = 0; pos < n_samples; pos++)
+	{
+		//Store samples in the input buffer
+		self->in_fifo[self->write_ptr] = self->input[pos];
+		//Output samples in the output buffer (even zeros introduced by latency)
+		self->output[pos] = self->out_fifo[self->read_ptr - self->input_latency];
+		//Now move the read pointer
+		self->read_ptr++;
+		self->write_ptr++;
+
+
+		//Once the buffer is full we can do stuff
+		if (self->read_ptr >= self->frame_size)
+		{
+			//Reset the input buffer position
+			self->read_ptr = self->input_latency;
+			self->write_ptr = 0;
+
+			for (k = 0; k < self->frame_size; k++)
+			{
+				self->input_frame[k] = self->in_fifo[k];
+			}
+
+			//------------PROCESSING-------------
+
+			//Process input_frame
+			rnnoise_process_frame(self->st, self->processed_frame, self->input_frame);
+
+			// //Test
+			// for (k = 0; k < self->frame_size; k++)
+			// {
+			// 	self->processed_frame[k] = self->input_frame[k];
+			// }
+			//-----------------------------------
+
+			//Output samples
+			for (k = 0; k < self->frame_size; k++)
+			{
+				self->out_fifo[k] = self->processed_frame[k];
+			}
+
+			//-------------------------------
+		}//if
+	}//main loop
+}
+
+
+/**
+* Cleanup and freeing memory.
+*/
+static void
+cleanup(LV2_Handle instance)
+{
+	SDenoise* self = (SDenoise*)instance;
+
+	rnnoise_destroy(self->st);
+	free(instance);
+}
+
+/**
+* extension for additional interfaces.
+*/
+static const void*
+extension_data(const char* uri)
+{
+	return NULL;
+}
+
+/**
+* Descriptor for linking methods.
+*/
+static const
+LV2_Descriptor descriptor =
+{
+	SDENOISE_URI,
+	instantiate,
+	connect_port,
+	NULL,
+	run,
+	NULL,
+	cleanup,
+	extension_data
+};
+
+/**
+* Symbol export using the descriptor above.
+*/
+LV2_SYMBOL_EXPORT
+const LV2_Descriptor*
+lv2_descriptor(uint32_t index)
+{
+	switch (index)
+	{
+		case 0:
+		return &descriptor;
+		default:
+		return NULL;
+	}
+}

+ 14 - 0
static_rnnoise.sh

@@ -0,0 +1,14 @@
+#!/bin/sh
+if [ -d "rnnoise" ]; then
+  rm -rf ./rnnoise
+fi
+git clone https://git.xiph.org/rnnoise.git
+cd rnnoise/
+./autogen.sh
+CFLAGS="-fvisibility=hidden -fPIC -Wl,--exclude-libs,ALL" \
+	./configure \
+  --disable-examples --disable-doc \
+	#--enable-single --enable-sse --enable-avx --disable-mpi \
+	#--disable-shared --enable-static
+  -enable-sse --enable-avx 
+make -j2