diff --git a/build/rtbuf_signal/Makefile b/build/rtbuf_signal/Makefile
index f5a839c..5dc2446 100644
--- a/build/rtbuf_signal/Makefile
+++ b/build/rtbuf_signal/Makefile
@@ -8,7 +8,7 @@ CFLAGS = -O0 -ggdb -W -Wall -Werror -fpic
LDFLAGS = -fPIC -shared
LIBS = -lm
HEADERS = rtbuf.h rtbuf_lib.h rtbuf_signal.h
-OBJECTS = rtbuf_signal.o rtbuf_signal_sinus.o
+OBJECTS = rtbuf_signal.o rtbuf_signal_sinus.o rtbuf_signal_square.o
SRC = ${HEADERS} ${OBJECTS:%.o=%.c}
diff --git a/rtbuf_signal.c b/rtbuf_signal.c
index ae51ffc..3327233 100644
--- a/rtbuf_signal.c
+++ b/rtbuf_signal.c
@@ -12,5 +12,24 @@ s_rtbuf_lib_fun rtbuf_lib_fun[] = {
sizeof(s_rtbuf_signal_sinus_data) / sizeof(double),
sizeof(double),
(const char*[]) { "frequency", "amplitude", 0 } },
+ { "square", rtbuf_signal_square, rtbuf_signal_square_start, 0,
+ sizeof(s_rtbuf_signal_square_data) / sizeof(double),
+ sizeof(double),
+ (const char*[]) { "frequency", "amplitude", "pulse", 0 } },
{ 0, 0, 0, 0, 0, 0, 0 }
};
+
+double min (double a, double b)
+{
+ return a < b ? a : b;
+}
+
+double max (double a, double b)
+{
+ return a < b ? b : a;
+}
+
+double clamp (double inf, double x, double sup)
+{
+ return max(inf, min(x, sup));
+}
diff --git a/rtbuf_signal.h b/rtbuf_signal.h
index 23dc781..85de005 100644
--- a/rtbuf_signal.h
+++ b/rtbuf_signal.h
@@ -4,6 +4,10 @@
#define RTBUF_SIGNAL_SAMPLES 256
#define RTBUF_SIGNAL_SAMPLERATE 44100
+double min (double a, double b);
+double max (double a, double b);
+double clamp (double inf, double x, double sup);
+
/* sinus */
enum {
@@ -20,6 +24,21 @@ typedef struct rtbuf_signal_sinus_data {
int rtbuf_signal_sinus (s_rtbuf *rtb);
int rtbuf_signal_sinus_start (s_rtbuf *rtb);
-const char **g_rtbuf_signal_sinus_vars;
+/* square */
+
+enum {
+ RTBUF_SIGNAL_SQUARE_VAR_FREQUENCY = 0,
+ RTBUF_SIGNAL_SQUARE_VAR_AMPLITUDE,
+ RTBUF_SIGNAL_SQUARE_VAR_PULSE,
+ RTBUF_SIGNAL_SQUARE_VAR_N
+};
+
+typedef struct rtbuf_signal_square_data {
+ double samples[RTBUF_SIGNAL_SAMPLES];
+ double phase;
+} s_rtbuf_signal_square_data;
+
+int rtbuf_signal_square (s_rtbuf *rtb);
+int rtbuf_signal_square_start (s_rtbuf *rtb);
#endif /* RTBUF_SIGNAL_H */
diff --git a/rtbuf_signal_square.c b/rtbuf_signal_square.c
new file mode 100644
index 0000000..ffa43d5
--- /dev/null
+++ b/rtbuf_signal_square.c
@@ -0,0 +1,51 @@
+
+#include <math.h>
+#include <stdio.h>
+#include "rtbuf.h"
+#include "rtbuf_lib.h"
+#include "rtbuf_signal.h"
+
+double square (double amp, double phase, double pulse)
+{
+ return phase < pulse ? amp : -amp;
+}
+
+int rtbuf_signal_square (s_rtbuf *rtb)
+{
+ double phase;
+ unsigned int i = 0;
+ s_rtbuf_signal_square_data *data;
+ int freq = rtb->var[RTBUF_SIGNAL_SQUARE_VAR_FREQUENCY];
+ int amp = rtb->var[RTBUF_SIGNAL_SQUARE_VAR_AMPLITUDE];
+ int pulse = rtb->var[RTBUF_SIGNAL_SQUARE_VAR_PULSE];
+ double *freq_samples = freq < 0 ? 0 : (double*) g_rtbuf[freq].data;
+ double *amp_samples = amp < 0 ? 0 : (double*) g_rtbuf[amp].data;
+ double *pulse_samples = pulse < 0 ? 0 : (double*) g_rtbuf[pulse].data;
+ data = (s_rtbuf_signal_square_data*) rtb->data;
+ phase = data->phase;
+ while (i < RTBUF_SIGNAL_SAMPLES) {
+ double f = freq_samples ? freq_samples[i] : 220.0;
+ double a = amp_samples ? amp_samples[i] : 1.0;
+ double p = pulse_samples ? pulse_samples[i] : 0.5;
+ f = max(0.0, f);
+ a = max(0.0, a);
+ p = clamp(0.0, p, 1.0);
+ //printf(" i=%u freq=%f amp=%f pulse=%f", i, f, a, p);
+ f /= (double) RTBUF_SIGNAL_SAMPLERATE;
+ phase = phase + f;
+ phase = phase - floor(phase);
+ data->samples[i] = square(a, phase, p);
+ //printf(" f=%f a=%f p=%f square=%f", f, a, p, data->samples[i]);
+ i++;
+ }
+ data->phase = phase;
+ return 0;
+}
+
+int rtbuf_signal_square_start (s_rtbuf *rtb)
+{
+ s_rtbuf_signal_square_data *data;
+ data = (s_rtbuf_signal_square_data*) rtb->data;
+ data->phase = 0;
+ return 0;
+}