Add new DSP plug "Panning".

This commit is contained in:
Themaister 2014-05-20 13:32:34 +02:00
parent b498476531
commit ead69172a2
5 changed files with 145 additions and 43 deletions

View File

@ -1,58 +1,58 @@
compiler := gcc
extra_flags :=
use_neon := 0
release := release
DYLIB := so
build = release
DYLIB := so
ifeq ($(platform),)
platform = unix
ifeq ($(shell uname -a),)
platform = win
else ifneq ($(findstring MINGW,$(shell uname -a)),)
platform = win
else ifneq ($(findstring Darwin,$(shell uname -a)),)
platform = osx
arch = intel
ifeq ($(shell uname -p),powerpc)
arch = ppc
endif
else ifneq ($(findstring win,$(shell uname -a)),)
platform = win
endif
platform = unix
ifeq ($(shell uname -a),)
platform = win
else ifneq ($(findstring MINGW,$(shell uname -a)),)
platform = win
else ifneq ($(findstring Darwin,$(shell uname -a)),)
platform = osx
arch = intel
ifeq ($(shell uname -p),powerpc)
arch = ppc
endif
else ifneq ($(findstring win,$(shell uname -a)),)
platform = win
endif
endif
ifeq ($(platform),gcc)
extra_rules_gcc := $(shell $(compiler) -dumpmachine)
extra_rules_gcc := $(shell $(compiler) -dumpmachine)
endif
ifneq (,$(findstring armv7,$(extra_rules_gcc)))
extra_flags += -mcpu=cortex-a9 -mtune=cortex-a9 -mfpu=neon
use_neon := 1
extra_flags += -mcpu=cortex-a9 -mtune=cortex-a9 -mfpu=neon
use_neon := 1
endif
ifneq (,$(findstring hardfloat,$(extra_rules_gcc)))
extra_flags += -mfloat-abi=hard
extra_flags += -mfloat-abi=hard
endif
ifeq (release,$(build))
extra_flags += -O2
extra_flags += -O2
endif
ifeq (debug,$(build))
extra_flags += -O0 -g
extra_flags += -O0 -g
endif
ldflags := -shared -Wl,--version-script=link.T
ldflags := -shared -lm -Wl,--version-script=link.T
ifeq ($(platform), unix)
DYLIB = so
DYLIB = so
else ifeq ($(platform), osx)
compiler := $(CC)
DYLIB = dylib
ldflags := -dynamiclib
compiler := $(CC)
DYLIB = dylib
ldflags := -dynamiclib
else
extra_flags += -static-libgcc -static-libstdc++
DYLIB = dll
extra_flags += -static-libgcc -static-libstdc++
DYLIB = dll
endif
CC := $(compiler)
@ -60,15 +60,15 @@ CXX := $(subst CC,++,$(compiler)) -std=gnu++0x
flags := -fPIC $(extra_flags)
asflags := -fPIC $(extra_flags)
objects :=
flags += -std=c99
ifeq (1,$(use_neon))
ASMFLAGS := -INEON/asm
asflags += -mfpu=neon
ASMFLAGS := -INEON/asm
asflags += -mfpu=neon
endif
objects += echo.$(DYLIB) eq.$(DYLIB) iir.$(DYLIB) phaser.$(DYLIB) reverb.$(DYLIB) volume.$(DYLIB) wah.$(DYLIB)
plugs := $(wildcard *.c)
objects := $(plugs:.c=.o)
targets := $(objects:.o=.$(DYLIB))
all: build;
@ -81,7 +81,7 @@ all: build;
%.$(DYLIB): %.o
$(CC) -o $@ $(ldflags) $(flags) $^
build: $(objects)
build: $(targets)
clean:
rm -f *.o

20
audio/filters/Panning.dsp Normal file
View File

@ -0,0 +1,20 @@
filters = 1
filter0 = panning
# Gains are linear.
# The default. Left and right channels map to each other.
panning_left_mix = "1.0 0.0"
panning_right_mix = "0.0 1.0"
# Some examples:
#
# Mono:
# panning_left_mix = "0.5 0.5"
# panning_right_mix = "0.5 0.5"
# Swap left and right channels:
# panning_left_mix = "0.0 1.0"
# panning_right_mix = "1.0 0.0"

View File

@ -57,12 +57,11 @@ struct dspfilter_info
struct dspfilter_output
{
// The DSP plugin has to provide the buffering for the output samples.
// This is for performance reasons to avoid redundant copying of data.
// The DSP plugin has to provide the buffering for the output samples or reuse the input buffer directly.
// The samples are laid out in interleaving order: LRLRLRLR
// The range of the samples are [-1.0, 1.0].
// This range cannot be exceeded without horrible audio glitches.
const float *samples;
// It is not necessary to manually clip values.
float *samples;
// Frames which the DSP plugin outputted for the current process.
// One frame is here defined as a combined sample of
@ -75,7 +74,11 @@ struct dspfilter_output
struct dspfilter_input
{
// Input data for the DSP. The samples are interleaved in order: LRLRLRLR
const float *samples;
// It is valid for a DSP plug to use this buffer for output as long as the output size is less or equal to the input.
// This is useful for filters which can output one sample for each input sample and do not need to maintain its own buffers.
// Block based filters must provide their own buffering scheme.
// The input size is not bound, but it can be safely assumed that it will not exceed ~100ms worth of audio at a time.
float *samples;
// Number of frames for input data.
// One frame is here defined as a combined sample of
@ -101,7 +104,7 @@ typedef int (*dspfilter_config_get_int_array_t)(void *userdata, const char *key,
typedef int (*dspfilter_config_get_string_t)(void *userdata, const char *key, char **output, const char *default_output);
// Calls free() in host runtime. Sometimes needed on Windows. free() on NULL is fine.
typedef void (*dspfilter_config_free_t)(void *userdata, void *ptr);
typedef void (*dspfilter_config_free_t)(void *ptr);
struct dspfilter_config
{

View File

@ -1,4 +1,4 @@
{
global: rarch_dsp_*;
global: dspfilter_get_implementation;
local: *;
};

79
audio/filters/panning.c Normal file
View File

@ -0,0 +1,79 @@
#include "dspfilter.h"
#include <math.h>
#include <stdlib.h>
#include <string.h>
struct panning_data
{
float left[2];
float right[2];
};
static void panning_free(void *data)
{
free(data);
}
static void panning_process(void *data, struct dspfilter_output *output,
const struct dspfilter_input *input)
{
unsigned i;
struct panning_data *pan = (struct panning_data*)data;
output->samples = input->samples;
output->frames = input->frames;
float *out = output->samples;
for (i = 0; i < input->frames; i++, out += 2)
{
float left = out[0];
float right = out[1];
out[0] = left * pan->left[0] + right * pan->left[1];
out[1] = left * pan->right[0] + right * pan->right[1];
}
}
static void *panning_init(const struct dspfilter_info *info,
const struct dspfilter_config *config, void *userdata)
{
struct panning_data *pan = (struct panning_data*)calloc(1, sizeof(*pan));
if (!pan)
return NULL;
float *left = NULL, *right = NULL;
unsigned num_left = 0, num_right = 0;
static const float default_left[] = { 1.0f, 0.0f };
static const float default_right[] = { 0.0f, 1.0f };
config->get_float_array(userdata, "left_mix", &left, &num_left, default_left, 2);
config->get_float_array(userdata, "right_mix", &right, &num_right, default_right, 2);
if (num_left == 2)
memcpy(pan->left, left, sizeof(pan->left));
if (num_right == 2)
memcpy(pan->right, right, sizeof(pan->right));
config->free(left);
config->free(right);
return pan;
}
static const struct dspfilter_implementation panning = {
panning_init,
panning_process,
panning_free,
DSPFILTER_API_VERSION,
"Panning",
"panning",
};
const struct dspfilter_implementation *dspfilter_get_implementation(dspfilter_simd_mask_t mask)
{
(void)mask;
return &panning;
}