aboutsummaryrefslogtreecommitdiff
path: root/src/scale.c
blob: 03f6b5f0f24692f06737b6b64bc9c573ca594963 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/* -------------------------  scale  ------------------------------------------ */
/*                                                                              */
/* Scales input to lie within an output range.                                  */
/* Written by Olaf Matthes <olaf.matthes@gmx.de>                                */
/* Get source at http://www.akustische-kunst.org/puredata/maxlib/               */
/*                                                                              */
/* This program is free software; you can redistribute it and/or                */
/* modify it under the terms of the GNU General Public License                  */
/* as published by the Free Software Foundation; either version 2               */
/* 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 General Public License for more details.                                 */
/*                                                                              */
/* You should have received a copy of the GNU General Public License            */
/* along with this program; if not, write to the Free Software                  */
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.  */
/*                                                                              */
/* Based on PureData by Miller Puckette and others.                             */
/*                                                                              */
/* ---------------------------------------------------------------------------- */

#include "m_pd.h"
#include <stdio.h>
#include <math.h>

static char *version = "scale v0.2, written by Olaf Matthes <olaf.matthes@gmx.de>";
 
typedef struct scale
{
  t_object x_ob;
  t_float  x_f;                    /* current input value */
  t_float  x_il;                   /* low border of input range */
  t_float  x_ih;                   /* high border of input range */
  t_float  x_ol;                   /* low border of output range */
  t_float  x_oh;                   /* high border of output range */
  t_float  x_logcoeff;             /* log-coefficient */
  t_outlet *x_outlet1;             /* result */
} t_scale;

static void scale_float(t_scale *x, t_floatarg f)
{
	t_float ir = x->x_ih - x->x_il;
	t_float or = x->x_oh - x->x_ol;
	double oq;
	double result;
	double k;
	if(ir == 0)
	{
		post("scale: input range must not be 0");
		return;
	}
	/* we accept an output range of 0 in case someone really wants this */
	if(!x->x_logcoeff)	/* linear */
	{
		k = (or / ir);
		result = ((f - x->x_il) * k) + x->x_ol;
	}
	else	/* logarythmical scale */
	{
		oq = x->x_oh / x->x_ol;
	//	k = (log((double)oq)/log(x->x_logcoeff))/((double)ir);
		k = log((double)oq)/((double)ir);

		if(x->x_ol)
		{
		//	result = (double)x->x_ol*exp(k*(double)(f - x->x_il)*log(x->x_logcoeff));
			result = (double)x->x_ol*exp(k*(double)(f - x->x_il));
		}
		else
		{
				/* in case the low output is 0 we have to cheat... */
				/* okay, here's the chating: we calculate for a lower out limit  
				   of 1 and remove this shift after the calculation */
			result = ((double)(x->x_ol+1)*exp(k*(double)(f - x->x_il)))-1.0;
		}
	}

	x->x_f = f;         /* save current input value */

	outlet_float(x->x_outlet1, result);
}

static void scale_bang(t_scale *x)
{
	scale_float(x, x->x_f);	/* recalculate result */
}

static t_class *scale_class;

static void *scale_new(t_floatarg fil, t_floatarg fih, t_floatarg fol, t_floatarg foh, t_floatarg flc)
{
    t_scale *x = (t_scale *)pd_new(scale_class);

	floatinlet_new(&x->x_ob, &x->x_il);
	floatinlet_new(&x->x_ob, &x->x_ih);
	floatinlet_new(&x->x_ob, &x->x_ol);
	floatinlet_new(&x->x_ob, &x->x_oh);
	floatinlet_new(&x->x_ob, &x->x_logcoeff);

	x->x_outlet1 = outlet_new(&x->x_ob, gensym("float"));

		/* default values taken from Max's scale */
	x->x_il = fil;
	x->x_ih = fih;
	if(!x->x_ih)x->x_ih = 127.0;
	x->x_ol = fol;
	x->x_oh = foh;
	if(!x->x_oh)x->x_oh = 1.0;
	x->x_logcoeff = flc;
	x->x_f = 0;

#ifndef MAXLIB
    post(version);
#endif
    return (void *)x;
}

void scale_setup(void)
{
    scale_class = class_new(gensym("scale"), (t_newmethod)scale_new,
    	0, sizeof(t_scale), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0);
    class_addfloat(scale_class, scale_float);
    class_addbang(scale_class, scale_bang);
#ifndef MAXLIB
    class_sethelpsymbol(scale_class, gensym("help-scale.pd"));
#else
    class_sethelpsymbol(scale_class, gensym("maxlib/help-scale.pd"));
#endif
}