Browse Source

add pitch shifter

master
Alexandros Theodotou 2 years ago
parent
commit
2736e3f82f
Signed by: alex
GPG Key ID: 022EAE42313D70F3
  1. 1
      ext/Soundpipe/modules/meson.build
  2. 3
      meson_options.txt
  3. 3
      plugins/meson.build
  4. 88
      plugins/pitchsp/common.h
  5. 246
      plugins/pitchsp/dsp.c
  6. 129
      plugins/pitchsp/ttl.h

1
ext/Soundpipe/modules/meson.build vendored

@ -23,6 +23,7 @@ soundpipe_module_files = files([ @@ -23,6 +23,7 @@ soundpipe_module_files = files([
'dist.c',
'peaklim.c',
'phaser.c',
'pshift.c',
'spa.c',
'saturator.c',
'zitarev.c',

3
meson_options.txt

@ -28,7 +28,8 @@ option ( @@ -28,7 +28,8 @@ option (
choices : [
'Chordz', 'Chorus', 'CompressorSP', 'Delay',
'Distortion',
'EQ', 'LFO', 'LimiterSP', 'PhaserSP', 'Saturator',
'EQ', 'LFO', 'LimiterSP', 'PhaserSP',
'PitchSP', 'Saturator',
'VerbSP', 'Saw'
],
description: 'Plugins to build')

3
plugins/meson.build

@ -22,6 +22,7 @@ plugins = [ @@ -22,6 +22,7 @@ plugins = [
['LimiterSP', 'LimiterPlugin', '0.1.0'],
['LFO', 'OscillatorPlugin', '1.0.1'],
['PhaserSP', 'PhaserPlugin', '0.1.0'],
['PitchSP', 'PitchPlugin', '0.1.0'],
#['Saturator', 'DistortionPlugin', '0.1.0'],
['Saw', 'InstrumentPlugin', '1.0.0'],
['VerbSP', 'ReverbPlugin', '0.1.0'],
@ -278,7 +279,7 @@ if get_option ('plugins').contains (pl[0]) @@ -278,7 +279,7 @@ if get_option ('plugins').contains (pl[0])
],
suite: pl[0])
endif
if lv2_validate.found() and sord_validate.found() and false
if lv2_validate.found() and sord_validate.found()
lv2_validate_wrap = find_program (
join_paths ('..', 'scripts', 'lv2_validate_wrap.sh'))
test (

88
plugins/pitchsp/common.h

@ -0,0 +1,88 @@ @@ -0,0 +1,88 @@
/*
* Copyright (C) 2020 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of ZPlugins
*
* ZPlugins is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* ZPlugins 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU General Affero Public License
* along with ZPlugins. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* \file
*
* Common code for both the DSP and the UI.
*/
#ifndef __Z_PITCH_COMMON_H__
#define __Z_PITCH_COMMON_H__
#include PLUGIN_CONFIG
#include "../common.h"
typedef struct PitchUris
{
} PitchUris;
typedef enum PortIndex
{
/** GUI to plugin communication. */
PITCH_CONTROL,
/** Plugin to UI communication. */
PITCH_NOTIFY,
PITCH_STEREO_IN_L,
PITCH_STEREO_IN_R,
PITCH_SHIFT,
PITCH_WINDOW,
PITCH_XFADE,
/** Outputs. */
PITCH_STEREO_OUT_L,
PITCH_STEREO_OUT_R,
NUM_PORTS,
} PortIndex;
/**
* Group of variables needed by both the DSP and
* the UI.
*/
typedef struct PitchCommon
{
/** URIs. */
PitchUris uris;
PluginCommon pl_common;
} PitchCommon;
static inline void
map_uris (
LV2_URID_Map* urid_map,
PitchCommon * pitch_common)
{
map_common_uris (
urid_map, &pitch_common->pl_common.uris);
#define MAP(x,uri) \
pitch_common->uris.x = \
urid_map->map (urid_map->handle, uri)
/* custom URIs */
#undef MAP
}
#endif

246
plugins/pitchsp/dsp.c

@ -0,0 +1,246 @@ @@ -0,0 +1,246 @@
/*
* Copyright (C) 2020 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of ZPlugins
*
* ZPlugins is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* ZPlugins 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU General Affero Public License
* along with ZPlugins. If not, see <https://www.gnu.org/licenses/>.
*/
#include PLUGIN_CONFIG
#include <float.h>
#include <math.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include "../math.h"
#include PLUGIN_COMMON
#include "soundpipe.h"
typedef struct Pitch
{
/** Plugin ports. */
const LV2_Atom_Sequence* control;
LV2_Atom_Sequence* notify;
const float * stereo_in_l;
const float * stereo_in_r;
const float * shift;
const float * window;
const float * xfade;
/* outputs */
float * stereo_out_l;
float * stereo_out_r;
PitchCommon common;
sp_data * sp;
sp_pshift * pshift;
} Pitch;
static LV2_Handle
instantiate (
const LV2_Descriptor* descriptor,
double rate,
const char* bundle_path,
const LV2_Feature* const* features)
{
Pitch * self = calloc (1, sizeof (Pitch));
SET_SAMPLERATE (self, rate);
PluginCommon * pl_common = &self->common.pl_common;
int ret =
plugin_common_instantiate (
pl_common, features, 0);
if (ret)
goto fail;
/* map uris */
map_uris (pl_common->map, &self->common);
/* init atom forge */
lv2_atom_forge_init (
&pl_common->forge, pl_common->map);
/* init logger */
lv2_log_logger_init (
&pl_common->logger, pl_common->map, pl_common->log);
return (LV2_Handle) self;
fail:
free (self);
return NULL;
}
static void
connect_port (
LV2_Handle instance,
uint32_t port,
void * data)
{
Pitch * self = (Pitch *) instance;
switch ((PortIndex) port)
{
case PITCH_CONTROL:
self->control =
(const LV2_Atom_Sequence *) data;
break;
case PITCH_NOTIFY:
self->notify =
(LV2_Atom_Sequence *) data;
break;
case PITCH_STEREO_IN_L:
self->stereo_in_l = (const float *) data;
break;
case PITCH_STEREO_IN_R:
self->stereo_in_r = (const float *) data;
break;
case PITCH_SHIFT:
self->shift = (const float *) data;
break;
case PITCH_WINDOW:
self->window = (const float *) data;
break;
case PITCH_XFADE:
self->xfade = (const float *) data;
break;
case PITCH_STEREO_OUT_L:
self->stereo_out_l = (float *) data;
break;
case PITCH_STEREO_OUT_R:
self->stereo_out_r = (float *) data;
break;
default:
break;
}
}
static void
activate (
LV2_Handle instance)
{
Pitch * self = (Pitch*) instance;
sp_create (&self->sp);
sp_pshift_create (&self->pshift);
sp_pshift_init (self->sp, self->pshift);
}
static void
run (
LV2_Handle instance,
uint32_t n_samples)
{
Pitch * self = (Pitch *) instance;
#ifdef TRIAL_VER
if (get_time_since_instantiation (
&self->common.pl_common) > SECONDS_TO_SILENCE)
return;
#endif
#if 0
struct timeval tp;
gettimeofday(&tp, NULL);
long int ms = tp.tv_sec * 1000000 + tp.tv_usec;
#endif
/* read incoming events from host and UI */
LV2_ATOM_SEQUENCE_FOREACH (
self->control, ev)
{
/* TODO */
}
/* compress */
*self->pshift->shift = *self->shift;
*self->pshift->window = *self->window;
*self->pshift->xfade = *self->xfade;
for (uint32_t i = 0; i < n_samples; i++)
{
float current_in = self->stereo_in_l[i];
sp_pshift_compute (
self->sp, self->pshift,
&current_in, &self->stereo_out_l[i]);
current_in = self->stereo_in_r[i];
sp_pshift_compute (
self->sp, self->pshift,
&current_in, &self->stereo_out_r[i]);
}
#if 0
gettimeofday(&tp, NULL);
ms = (tp.tv_sec * 1000000 + tp.tv_usec) - ms;
printf("us taken %ld\n", ms);
#endif
}
static void
deactivate (
LV2_Handle instance)
{
Pitch * self = (Pitch *) instance;
sp_destroy (&self->sp);
sp_pshift_destroy (&self->pshift);
}
static void
cleanup (
LV2_Handle instance)
{
Pitch * self = (Pitch *) instance;
free (self);
}
static const void*
extension_data (
const char * uri)
{
return NULL;
}
static const LV2_Descriptor descriptor = {
PLUGIN_URI,
instantiate,
connect_port,
activate,
run,
deactivate,
cleanup,
extension_data
};
LV2_SYMBOL_EXPORT
const LV2_Descriptor*
lv2_descriptor (
uint32_t index)
{
switch (index)
{
case 0:
return &descriptor;
default:
return NULL;
}
}

129
plugins/pitchsp/ttl.h

@ -0,0 +1,129 @@ @@ -0,0 +1,129 @@
/*
* Copyright (C) 2020 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of ZPlugins
*
* ZPlugins is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* ZPlugins 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU General Affero Public License
* along with ZPlugins. If not, see <https://www.gnu.org/licenses/>.
*/
static void
print_ttl (FILE * f)
{
fprintf (f,
"@prefix atom: <http://lv2plug.in/ns/ext/atom#> .\n\
@prefix doap: <http://usefulinc.com/ns/doap#> .\n\
@prefix log: <http://lv2plug.in/ns/ext/log#> .\n\
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .\n\
@prefix midi: <http://lv2plug.in/ns/ext/midi#> .\n\
@prefix pg: <http://lv2plug.in/ns/ext/port-groups#> .\n\
@prefix pprop: <http://lv2plug.in/ns/ext/port-props#> .\n\
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n\
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n\
@prefix rsz: <http://lv2plug.in/ns/ext/resize-port#> .\n\
@prefix time: <http://lv2plug.in/ns/ext/time#> .\n\
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .\n\
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .\n\
@prefix units: <http://lv2plug.in/ns/extensions/units#> .\n\
@prefix work: <http://lv2plug.in/ns/ext/worker#> .\n\n");
fprintf (f,
"<" PLUGIN_URI ">\n\
a lv2:Plugin,\n\
lv2:" PLUGIN_TYPE " ;\n\
doap:name \"" PLUGIN_NAME "\" ;\n\
doap:license <https://www.gnu.org/licenses/agpl-3.0.html> ;\n\
lv2:project <" PROJECT_URI "> ;\n\
lv2:requiredFeature urid:map ;\n\
lv2:optionalFeature log:log ,\n\
lv2:hardRTCapable ;\n\
lv2:port [\n\
a lv2:InputPort ,\n\
atom:AtomPort ;\n\
atom:bufferType atom:Sequence ;\n\
lv2:index 0 ;\n\
lv2:designation lv2:control ;\n\
lv2:symbol \"control\" ;\n\
lv2:name \"Control\" ;\n\
rdfs:comment \"GUI/host to plugin communication\" ;\n\
] , [\n\
a lv2:OutputPort ,\n\
atom:AtomPort ;\n\
atom:bufferType atom:Sequence ;\n\
lv2:index 1 ;\n\
lv2:designation lv2:control ;\n\
lv2:symbol \"notify\" ;\n\
lv2:name \"Notify\" ;\n\
rdfs:comment \"Plugin to GUI communication\" ;\n\
] , [\n\
a lv2:InputPort ,\n\
lv2:AudioPort ;\n\
lv2:index 2 ;\n\
lv2:symbol \"stereo_in_l\" ;\n\
lv2:name \"Stereo In L\" ;\n\
] , [\n\
a lv2:InputPort ,\n\
lv2:AudioPort ;\n\
lv2:index 3 ;\n\
lv2:symbol \"stereo_in_r\" ;\n\
lv2:name \"Stereo In R\" ;\n\
] , [\n\
a lv2:InputPort ,\n\
lv2:ControlPort ;\n\
lv2:index 4 ;\n\
lv2:symbol \"shift\" ;\n\
lv2:name \"Shift\" ;\n\
lv2:default 0 ;\n\
lv2:minimum -24 ;\n\
lv2:maximum 24 ;\n\
lv2:portProperty lv2:integer ;\n\
units:unit units:semitone12TET; \n\
rdfs:comment \"Pitch shift\" ;\n\
] , [\n\
a lv2:InputPort ,\n\
lv2:ControlPort ;\n\
lv2:index 5 ;\n\
lv2:symbol \"window\" ;\n\
lv2:name \"Window\" ;\n\
lv2:default 1000 ;\n\
lv2:minimum 1 ;\n\
lv2:maximum 10000 ;\n\
lv2:portProperty lv2:integer ;\n\
units:unit units:frame; \n\
rdfs:comment \"Window size\" ;\n\
] , [\n\
a lv2:InputPort ,\n\
lv2:ControlPort ;\n\
lv2:index 6 ;\n\
lv2:symbol \"xfade\" ;\n\
lv2:name \"Cross-fade\" ;\n\
lv2:default 10 ;\n\
lv2:minimum 0 ;\n\
lv2:maximum 10000 ;\n\
lv2:portProperty lv2:integer ;\n\
units:unit units:frame; \n\
rdfs:comment \"Crossfade\" ;\n\
] , [\n\
a lv2:OutputPort ,\n\
lv2:AudioPort ;\n\
lv2:index 7 ;\n\
lv2:symbol \"stereo_out_l\" ;\n\
lv2:name \"Stereo Out L\" ;\n\
] , [\n\
a lv2:OutputPort ,\n\
lv2:AudioPort ;\n\
lv2:index 8 ;\n\
lv2:symbol \"stereo_out_r\" ;\n\
lv2:name \"Stereo Out R\" ;\n\
] .\n");
}
Loading…
Cancel
Save