TAP LADSPA plugins: updated to version 0.7.1
After (exactly) 5 years of silence, there's a new relase of TAP LADSPA
plugins. It fixes issues on 64 bit machines, uninitialised variables
and denormal issues.
(cherry picked from commit 6a9e45f733)
This commit is contained in:
@@ -49,6 +49,15 @@ Fractal Doubler would have never been written. He also helped a lot
|
||||
with the CPU runaway problems in TAP Reverberator, by reporting the
|
||||
problem and trying out my solutions.
|
||||
|
||||
Maarten Maathuis <madman2003@gmail.com> contributed the Bauer
|
||||
stereophonic-to-binaural DSP plugin. NOTE: this plugin only existed in
|
||||
CVS between releases 0.7.0 and 0.7.1; it has been agreed to be removed
|
||||
from TAP-plugins and released separately.
|
||||
|
||||
Damon Chaplin <damon@karuna.eclipse.co.uk> tracked down issues that
|
||||
caused problems on 64-bit machines, found uninitialised variables via
|
||||
Valgrind, and also pinned down long lurking denormal issues. Thanks!
|
||||
|
||||
|
||||
And, of course, special thanks to the Ardour [http://ardour.org] and
|
||||
JACK [http://jackit.sf.net] development teams for their tireless
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: tap_echo.c,v 1.6 2004/08/05 16:18:44 tszilagyi Exp $
|
||||
$Id: tap_echo.c,v 1.7 2004/12/06 09:32:41 tszilagyi Exp $
|
||||
*/
|
||||
|
||||
|
||||
@@ -103,6 +103,24 @@ instantiate_Echo(const LADSPA_Descriptor * Descriptor,
|
||||
if ((ptr = malloc(sizeof(Echo))) != NULL) {
|
||||
((Echo *)ptr)->sample_rate = SampleRate;
|
||||
((Echo *)ptr)->run_adding_gain = 1.0f;
|
||||
|
||||
/* allocate memory for ringbuffers and related dynamic vars */
|
||||
if ((((Echo *)ptr)->ringbuffer_L =
|
||||
calloc(MAX_DELAY * ((Echo *)ptr)->sample_rate / 1000,
|
||||
sizeof(LADSPA_Data))) == NULL)
|
||||
exit(1);
|
||||
if ((((Echo *)ptr)->ringbuffer_R =
|
||||
calloc(MAX_DELAY * ((Echo *)ptr)->sample_rate / 1000,
|
||||
sizeof(LADSPA_Data))) == NULL)
|
||||
exit(1);
|
||||
if ((((Echo *)ptr)->buffer_pos_L = calloc(1, sizeof(unsigned long))) == NULL)
|
||||
exit(1);
|
||||
if ((((Echo *)ptr)->buffer_pos_R = calloc(1, sizeof(unsigned long))) == NULL)
|
||||
exit(1);
|
||||
|
||||
*(((Echo *)ptr)->buffer_pos_L) = 0;
|
||||
*(((Echo *)ptr)->buffer_pos_R) = 0;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@@ -114,45 +132,19 @@ instantiate_Echo(const LADSPA_Descriptor * Descriptor,
|
||||
void
|
||||
activate_Echo(LADSPA_Handle Instance) {
|
||||
|
||||
Echo * ptr;
|
||||
|
||||
ptr = (Echo *)Instance;
|
||||
Echo * ptr = (Echo *)Instance;
|
||||
int i;
|
||||
|
||||
ptr->mpx_out_L = 0;
|
||||
ptr->mpx_out_R = 0;
|
||||
|
||||
/* allocate memory for ringbuffers and related dynamic vars */
|
||||
if ((ptr->ringbuffer_L =
|
||||
calloc(MAX_DELAY * ptr->sample_rate / 1000,
|
||||
sizeof(LADSPA_Data))) == NULL)
|
||||
exit(1);
|
||||
if ((ptr->ringbuffer_R =
|
||||
calloc(MAX_DELAY * ptr->sample_rate / 1000,
|
||||
sizeof(LADSPA_Data))) == NULL)
|
||||
exit(1);
|
||||
if ((ptr->buffer_pos_L = calloc(1, sizeof(unsigned long))) == NULL)
|
||||
exit(1);
|
||||
if ((ptr->buffer_pos_R = calloc(1, sizeof(unsigned long))) == NULL)
|
||||
exit(1);
|
||||
|
||||
*(ptr->buffer_pos_L) = 0;
|
||||
*(ptr->buffer_pos_R) = 0;
|
||||
}
|
||||
*(ptr->buffer_pos_R) = 0;
|
||||
|
||||
|
||||
/* deactivate a plugin instance */
|
||||
void
|
||||
deactivate_Echo(LADSPA_Handle Instance) {
|
||||
|
||||
Echo * ptr;
|
||||
|
||||
ptr = (Echo *)Instance;
|
||||
|
||||
/* free memory allocated for ringbuffers & co. in activate_Echo() */
|
||||
free(ptr->ringbuffer_L);
|
||||
free(ptr->ringbuffer_R);
|
||||
free(ptr->buffer_pos_L);
|
||||
free(ptr->buffer_pos_R);
|
||||
for (i = 0; i < MAX_DELAY * ptr->sample_rate / 1000; i++) {
|
||||
ptr->ringbuffer_L[i] = 0.0f;
|
||||
ptr->ringbuffer_R[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -428,6 +420,13 @@ run_adding_gain_Echo(LADSPA_Handle Instance,
|
||||
void
|
||||
cleanup_Echo(LADSPA_Handle Instance) {
|
||||
|
||||
Echo * ptr = (Echo *)Instance;
|
||||
|
||||
free(ptr->ringbuffer_L);
|
||||
free(ptr->ringbuffer_R);
|
||||
free(ptr->buffer_pos_L);
|
||||
free(ptr->buffer_pos_R);
|
||||
|
||||
free(Instance);
|
||||
}
|
||||
|
||||
@@ -584,7 +583,7 @@ __attribute__((constructor)) _init() {
|
||||
stereo_descriptor->run = run_Echo;
|
||||
stereo_descriptor->run_adding = run_adding_gain_Echo;
|
||||
stereo_descriptor->set_run_adding_gain = set_run_adding_gain;
|
||||
stereo_descriptor->deactivate = deactivate_Echo;
|
||||
stereo_descriptor->deactivate = NULL;
|
||||
stereo_descriptor->cleanup = cleanup_Echo;
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: tap_eq.c,v 1.6 2004/04/18 19:56:56 tszilagyi Exp $
|
||||
$Id: tap_eq.c,v 1.7 2006/08/09 12:03:24 tszilagyi Exp $
|
||||
*/
|
||||
|
||||
|
||||
@@ -224,6 +224,8 @@ instantiate_eq(const LADSPA_Descriptor *descriptor, unsigned long s_rate) {
|
||||
float fs;
|
||||
|
||||
fs = s_rate;
|
||||
|
||||
memset(ptr, 0, sizeof(eq));
|
||||
|
||||
filters = calloc(8, sizeof(biquad));
|
||||
|
||||
@@ -231,6 +233,30 @@ instantiate_eq(const LADSPA_Descriptor *descriptor, unsigned long s_rate) {
|
||||
ptr->fs = fs;
|
||||
ptr->run_adding_gain = 1.0f;
|
||||
|
||||
ptr->old_ch0f = 100.0f;
|
||||
ptr->old_ch0g = 0;
|
||||
|
||||
ptr->old_ch1f = 200.0f;
|
||||
ptr->old_ch1g = 0;
|
||||
|
||||
ptr->old_ch2f = 400.0f;
|
||||
ptr->old_ch2g = 0;
|
||||
|
||||
ptr->old_ch3f = 1000.0f;
|
||||
ptr->old_ch3g = 0;
|
||||
|
||||
ptr->old_ch4f = 3000.0f;
|
||||
ptr->old_ch4g = 0;
|
||||
|
||||
ptr->old_ch5f = 6000.0f;
|
||||
ptr->old_ch5g = 0;
|
||||
|
||||
ptr->old_ch6f = 12000.0f;
|
||||
ptr->old_ch6g = 0;
|
||||
|
||||
ptr->old_ch7f = 15000.0f;
|
||||
ptr->old_ch7g = 0;
|
||||
|
||||
eq_set_params(&filters[0], 100.0f, 0.0f, BWIDTH, fs);
|
||||
eq_set_params(&filters[1], 200.0f, 0.0f, BWIDTH, fs);
|
||||
eq_set_params(&filters[2], 400.0f, 0.0f, BWIDTH, fs);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: tap_eqbw.c,v 1.4 2004/04/18 19:56:56 tszilagyi Exp $
|
||||
$Id: tap_eqbw.c,v 1.5 2006/08/09 12:03:24 tszilagyi Exp $
|
||||
*/
|
||||
|
||||
|
||||
@@ -271,12 +271,46 @@ instantiate_eq(const LADSPA_Descriptor *descriptor, unsigned long s_rate) {
|
||||
|
||||
fs = s_rate;
|
||||
|
||||
memset(ptr, 0, sizeof(eq));
|
||||
|
||||
filters = calloc(8, sizeof(biquad));
|
||||
|
||||
ptr->filters = filters;
|
||||
ptr->fs = fs;
|
||||
ptr->run_adding_gain = 1.0f;
|
||||
|
||||
ptr->old_ch0f = 100.0f;
|
||||
ptr->old_ch0g = 0.0f;
|
||||
ptr->old_ch0b = BWIDTH;
|
||||
|
||||
ptr->old_ch1f = 200.0f;
|
||||
ptr->old_ch1g = 0.0f;
|
||||
ptr->old_ch1b = BWIDTH;
|
||||
|
||||
ptr->old_ch2f = 400.0f;
|
||||
ptr->old_ch2g = 0.0f;
|
||||
ptr->old_ch2b = BWIDTH;
|
||||
|
||||
ptr->old_ch3f = 1000.0f;
|
||||
ptr->old_ch3g = 0.0f;
|
||||
ptr->old_ch3b = BWIDTH;
|
||||
|
||||
ptr->old_ch4f = 3000.0f;
|
||||
ptr->old_ch4g = 0.0f;
|
||||
ptr->old_ch4b = BWIDTH;
|
||||
|
||||
ptr->old_ch5f = 6000.0f;
|
||||
ptr->old_ch5g = 0.0f;
|
||||
ptr->old_ch5b = BWIDTH;
|
||||
|
||||
ptr->old_ch6f = 12000.0f;
|
||||
ptr->old_ch6g = 0.0f;
|
||||
ptr->old_ch6b = BWIDTH;
|
||||
|
||||
ptr->old_ch7f = 15000.0f;
|
||||
ptr->old_ch7g = 0.0f;
|
||||
ptr->old_ch7b = BWIDTH;
|
||||
|
||||
eq_set_params(&filters[0], 100.0f, 0.0f, BWIDTH, fs);
|
||||
eq_set_params(&filters[1], 200.0f, 0.0f, BWIDTH, fs);
|
||||
eq_set_params(&filters[2], 400.0f, 0.0f, BWIDTH, fs);
|
||||
|
||||
@@ -17,6 +17,11 @@
|
||||
|
||||
$Id: tap_reverb.h,v 1.10 2004/06/14 16:43:55 tszilagyi Exp $
|
||||
*/
|
||||
#ifndef _ISOC99_SOURCE
|
||||
#define _ISOC99_SOURCE
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
|
||||
@@ -117,7 +122,6 @@ write_buffer(rev_t insample, rev_t * buffer, unsigned long buflen,
|
||||
#define db2lin(x) ((x) > -90.0f ? powf(10.0f, (x) * 0.05f) : 0.0f)
|
||||
#define ABS(x) (x)>0.0f?(x):-1.0f*(x)
|
||||
#define LN_2_2 0.34657359f
|
||||
#define FLUSH_TO_ZERO(x) (((*(unsigned int*)&(x))&0x7f800000)==0)?0.0f:(x)
|
||||
#define LIMIT(v,l,u) ((v)<(l)?(l):((v)>(u)?(u):(v)))
|
||||
|
||||
#define BIQUAD_TYPE float
|
||||
@@ -195,19 +199,23 @@ static inline
|
||||
rev_t
|
||||
biquad_run(biquad *f, rev_t x) {
|
||||
|
||||
rev_t y;
|
||||
union {
|
||||
rev_t y;
|
||||
uint32_t y_int;
|
||||
} u;
|
||||
|
||||
y = f->b0 * x + f->b1 * f->x1 + f->b2 * f->x2
|
||||
+ f->a1 * f->y1 + f->a2 * f->y2;
|
||||
u.y = f->b0 * x + f->b1 * f->x1 + f->b2 * f->x2
|
||||
+ f->a1 * f->y1 + f->a2 * f->y2;
|
||||
#ifdef REVERB_CALC_FLOAT
|
||||
y = FLUSH_TO_ZERO(y);
|
||||
if ((u.y_int & 0x7f800000) == 0)
|
||||
u.y = 0.0f;
|
||||
#endif
|
||||
f->x2 = f->x1;
|
||||
f->x1 = x;
|
||||
f->y2 = f->y1;
|
||||
f->y1 = y;
|
||||
f->y1 = u.y;
|
||||
|
||||
return y;
|
||||
return u.y;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: tap_sigmoid.c,v 1.1 2004/08/02 18:14:50 tszilagyi Exp $
|
||||
$Id: tap_sigmoid.c,v 1.3 2005/08/30 11:19:14 tszilagyi Exp $
|
||||
*/
|
||||
|
||||
|
||||
@@ -40,11 +40,14 @@
|
||||
#define OUTPUT 3
|
||||
|
||||
/* Total number of ports */
|
||||
|
||||
|
||||
#define PORTCOUNT_MONO 4
|
||||
|
||||
|
||||
/* The closer this is to 1.0, the slower the input parameter
|
||||
interpolation will be. */
|
||||
#define INTERP 0.99f
|
||||
|
||||
|
||||
/* The structure used to hold port connection information and state */
|
||||
|
||||
typedef struct {
|
||||
@@ -53,12 +56,14 @@ typedef struct {
|
||||
LADSPA_Data * input;
|
||||
LADSPA_Data * output;
|
||||
|
||||
LADSPA_Data pregain_i;
|
||||
LADSPA_Data postgain_i;
|
||||
|
||||
unsigned long sample_rate;
|
||||
LADSPA_Data run_adding_gain;
|
||||
} Sigmoid;
|
||||
|
||||
|
||||
|
||||
/* Construct a new plugin instance. */
|
||||
LADSPA_Handle
|
||||
instantiate_Sigmoid(const LADSPA_Descriptor * Descriptor,
|
||||
@@ -76,9 +81,6 @@ instantiate_Sigmoid(const LADSPA_Descriptor * Descriptor,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Connect a port to a data location. */
|
||||
void
|
||||
connect_port_Sigmoid(LADSPA_Handle Instance,
|
||||
@@ -90,9 +92,11 @@ connect_port_Sigmoid(LADSPA_Handle Instance,
|
||||
switch (Port) {
|
||||
case PREGAIN:
|
||||
ptr->pregain = DataLocation;
|
||||
ptr->pregain_i = db2lin(LIMIT(*DataLocation,-90.0f,20.0f));
|
||||
break;
|
||||
case POSTGAIN:
|
||||
ptr->postgain = DataLocation;
|
||||
ptr->postgain_i = db2lin(LIMIT(*DataLocation,-90.0f,20.0f));
|
||||
break;
|
||||
case INPUT:
|
||||
ptr->input = DataLocation;
|
||||
@@ -104,7 +108,6 @@ connect_port_Sigmoid(LADSPA_Handle Instance,
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
run_Sigmoid(LADSPA_Handle Instance,
|
||||
unsigned long SampleCount) {
|
||||
@@ -114,6 +117,8 @@ run_Sigmoid(LADSPA_Handle Instance,
|
||||
LADSPA_Data * output = ptr->output;
|
||||
LADSPA_Data pregain = db2lin(LIMIT(*(ptr->pregain),-90.0f,20.0f));
|
||||
LADSPA_Data postgain = db2lin(LIMIT(*(ptr->postgain),-90.0f,20.0f));
|
||||
LADSPA_Data pregain_i = ptr->pregain_i;
|
||||
LADSPA_Data postgain_i = ptr->postgain_i;
|
||||
|
||||
unsigned long sample_index;
|
||||
unsigned long sample_count = SampleCount;
|
||||
@@ -121,19 +126,39 @@ run_Sigmoid(LADSPA_Handle Instance,
|
||||
LADSPA_Data in = 0.0f;
|
||||
LADSPA_Data out = 0.0f;
|
||||
|
||||
if ((pregain_i != pregain) || (postgain_i != postgain)) {
|
||||
|
||||
for (sample_index = 0; sample_index < sample_count; sample_index++) {
|
||||
for (sample_index = 0; sample_index < sample_count; sample_index++) {
|
||||
|
||||
in = *(input++) * pregain;
|
||||
pregain_i = pregain_i * INTERP + pregain * (1.0f - INTERP);
|
||||
postgain_i = postgain_i * INTERP + postgain * (1.0f - INTERP);
|
||||
|
||||
in = *(input++) * pregain_i;
|
||||
|
||||
out = 2.0f / (1.0f + exp(-5.0*in)) - 1.0f;
|
||||
out = 2.0f / (1.0f + exp(-5.0*in)) - 1.0f;
|
||||
|
||||
*(output++) = out * postgain;
|
||||
*(output++) = out * postgain_i;
|
||||
}
|
||||
|
||||
ptr->pregain_i = pregain_i;
|
||||
ptr->postgain_i = postgain_i;
|
||||
|
||||
} else {
|
||||
for (sample_index = 0; sample_index < sample_count; sample_index++) {
|
||||
|
||||
in = *(input++) * pregain_i;
|
||||
|
||||
out = 2.0f / (1.0f + exp(-5.0*in)) - 1.0f;
|
||||
|
||||
*(output++) = out * postgain_i;
|
||||
}
|
||||
|
||||
ptr->pregain_i = pregain_i;
|
||||
ptr->postgain_i = postgain_i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
set_run_adding_gain_Sigmoid(LADSPA_Handle Instance, LADSPA_Data gain) {
|
||||
|
||||
@@ -143,7 +168,6 @@ set_run_adding_gain_Sigmoid(LADSPA_Handle Instance, LADSPA_Data gain) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
run_adding_Sigmoid(LADSPA_Handle Instance,
|
||||
unsigned long SampleCount) {
|
||||
@@ -153,6 +177,8 @@ run_adding_Sigmoid(LADSPA_Handle Instance,
|
||||
LADSPA_Data * output = ptr->output;
|
||||
LADSPA_Data pregain = db2lin(LIMIT(*(ptr->pregain),-90.0f,20.0f));
|
||||
LADSPA_Data postgain = db2lin(LIMIT(*(ptr->postgain),-90.0f,20.0f));
|
||||
LADSPA_Data pregain_i = ptr->pregain_i;
|
||||
LADSPA_Data postgain_i = ptr->postgain_i;
|
||||
|
||||
unsigned long sample_index;
|
||||
unsigned long sample_count = SampleCount;
|
||||
@@ -161,19 +187,36 @@ run_adding_Sigmoid(LADSPA_Handle Instance,
|
||||
LADSPA_Data out = 0.0f;
|
||||
|
||||
|
||||
for (sample_index = 0; sample_index < sample_count; sample_index++) {
|
||||
if ((pregain_i != pregain) || (postgain_i != postgain)) {
|
||||
|
||||
in = *(input++) * pregain;
|
||||
for (sample_index = 0; sample_index < sample_count; sample_index++) {
|
||||
|
||||
pregain_i = pregain_i * INTERP + pregain * (1.0f - INTERP);
|
||||
postgain_i = postgain_i * INTERP + postgain * (1.0f - INTERP);
|
||||
|
||||
in = *(input++) * pregain_i;
|
||||
|
||||
out = 2.0f / (1.0f + exp(-5.0*in)) - 1.0f;
|
||||
out = 2.0f / (1.0f + exp(-5.0*in)) - 1.0f;
|
||||
|
||||
*(output++) += out * postgain * ptr->run_adding_gain;
|
||||
}
|
||||
*(output++) = out * postgain_i * ptr->run_adding_gain;
|
||||
}
|
||||
|
||||
ptr->pregain_i = pregain_i;
|
||||
ptr->postgain_i = postgain_i;
|
||||
|
||||
} else {
|
||||
for (sample_index = 0; sample_index < sample_count; sample_index++) {
|
||||
|
||||
in = *(input++) * pregain_i;
|
||||
|
||||
out = 2.0f / (1.0f + exp(-5.0*in)) - 1.0f;
|
||||
|
||||
*(output++) = out * postgain_i * ptr->run_adding_gain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Throw away a Sigmoid effect instance. */
|
||||
void
|
||||
cleanup_Sigmoid(LADSPA_Handle Instance) {
|
||||
@@ -182,11 +225,9 @@ cleanup_Sigmoid(LADSPA_Handle Instance) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
LADSPA_Descriptor * mono_descriptor = NULL;
|
||||
|
||||
|
||||
|
||||
/* __attribute__((constructor)) _init() is called automatically when the plugin library is first
|
||||
loaded. */
|
||||
void
|
||||
|
||||
@@ -17,7 +17,11 @@
|
||||
|
||||
$Id: tap_utils.h,v 1.5 2004/02/21 17:33:36 tszilagyi Exp $
|
||||
*/
|
||||
#ifndef _ISOC99_SOURCE
|
||||
#define _ISOC99_SOURCE
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846264338327
|
||||
@@ -92,7 +96,6 @@ for any bugs or malfunction. */
|
||||
|
||||
|
||||
#define LN_2_2 0.34657359f
|
||||
#define FLUSH_TO_ZERO(x) (((*(unsigned int*)&(x))&0x7f800000)==0)?0.0f:(x)
|
||||
#define LIMIT(v,l,u) ((v)<(l)?(l):((v)>(u)?(u):(v)))
|
||||
|
||||
#define BIQUAD_TYPE float
|
||||
@@ -246,15 +249,19 @@ static inline
|
||||
bq_t
|
||||
biquad_run(biquad *f, bq_t x) {
|
||||
|
||||
bq_t y;
|
||||
union {
|
||||
bq_t y;
|
||||
uint32_t y_int;
|
||||
} u;
|
||||
|
||||
y = f->b0 * x + f->b1 * f->x1 + f->b2 * f->x2
|
||||
+ f->a1 * f->y1 + f->a2 * f->y2;
|
||||
y = FLUSH_TO_ZERO(y);
|
||||
u.y = f->b0 * x + f->b1 * f->x1 + f->b2 * f->x2
|
||||
+ f->a1 * f->y1 + f->a2 * f->y2;
|
||||
if ((u.y_int & 0x7f800000) == 0)
|
||||
u.y = 0.0f;
|
||||
f->x2 = f->x1;
|
||||
f->x1 = x;
|
||||
f->y2 = f->y1;
|
||||
f->y1 = y;
|
||||
f->y1 = u.y;
|
||||
|
||||
return y;
|
||||
return u.y;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user