2 Copyright (C) 2003-2008 Fons Adriaensen <fons@kokkinizita.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 // --------------------------------------------------------------------------------
25 #include <jack/jack.h>
48 struct Freq _freq
[13];
52 struct MTDM
* mtdm_new (double fsamp
)
57 struct MTDM
*retval
= (MTDM
*)malloc( sizeof(struct MTDM
) );
65 retval
->_freq
[0].f
= 4096;
66 retval
->_freq
[1].f
= 2048;
67 retval
->_freq
[2].f
= 3072;
68 retval
->_freq
[3].f
= 2560;
69 retval
->_freq
[4].f
= 2304;
70 retval
->_freq
[5].f
= 2176;
71 retval
->_freq
[6].f
= 1088;
72 retval
->_freq
[7].f
= 1312;
73 retval
->_freq
[8].f
= 1552;
74 retval
->_freq
[9].f
= 1800;
75 retval
->_freq
[10].f
= 3332;
76 retval
->_freq
[11].f
= 3586;
77 retval
->_freq
[12].f
= 3841;
78 retval
->_wlp
= 200.0f
/ fsamp
;
79 for (i
= 0, F
= retval
->_freq
; i
< 13; i
++, F
++) {
89 int mtdm_process (struct MTDM
*self
, size_t len
, float *ip
, float *op
)
92 float vip
, vop
, a
, c
, s
;
99 for (i
= 0, F
= self
->_freq
; i
< 13; i
++, F
++)
101 a
= 2 * (float) M_PI
* (F
->p
& 65535) / 65536.0;
105 vop
+= (i
? 0.01f
: 0.20f
) * s
;
110 if (++self
->_cnt
== 16)
112 for (i
= 0, F
= self
->_freq
; i
< 13; i
++, F
++)
114 F
->x1
+= self
->_wlp
* (F
->xa
- F
->x1
+ 1e-20);
115 F
->y1
+= self
->_wlp
* (F
->ya
- F
->y1
+ 1e-20);
116 F
->x2
+= self
->_wlp
* (F
->x1
- F
->x2
+ 1e-20);
117 F
->y2
+= self
->_wlp
* (F
->y1
- F
->y2
+ 1e-20);
118 F
->xa
= F
->ya
= 0.0f
;
127 int mtdm_resolve (struct MTDM
*self
)
131 struct Freq
*F
= self
->_freq
;
133 if (hypot (F
->x2
, F
->y2
) < 0.001) return -1;
134 d
= atan2 (F
->y2
, F
->x2
) / (2 * M_PI
);
135 if (self
->_inv
) d
+= 0.5;
136 if (d
> 0.5) d
-= 1.0;
137 f0
= self
->_freq
[0].f
;
140 for (i
= 0; i
< 12; i
++)
143 p
= atan2 (F
->y2
, F
->x2
) / (2 * M_PI
) - d
* F
->f
/ f0
;
144 if (self
->_inv
) p
+= 0.5;
147 k
= (int)(floor (p
+ 0.5));
149 if (e
> self
->_err
) self
->_err
= e
;
150 if (e
> 0.4) return 1;
159 void mtdm_invert (struct MTDM
*self
)
163 // --------------------------------------------------------------------------------
165 static struct MTDM
*mtdm
;
166 static jack_client_t
*jack_handle
;
167 static jack_port_t
*jack_capt
;
168 static jack_port_t
*jack_play
;
170 jack_latency_range_t capture_latency
= {-1, -1};
171 jack_latency_range_t playback_latency
= {-1, -1};
174 latency_cb (jack_latency_callback_mode_t mode
, void *arg
)
176 jack_latency_range_t range
;
178 range
.min
= range
.max
= 0;
180 if (mode
== JackCaptureLatency
) {
181 jack_port_set_latency_range (jack_play
, mode
, &range
);
182 jack_port_get_latency_range (jack_capt
, mode
, &range
);
183 if ((range
.min
!= capture_latency
.min
) || (range
.max
!= capture_latency
.max
)) {
184 capture_latency
= range
;
185 printf ("new capture latency: [%d, %d]\n", range
.min
, range
.max
);
188 jack_port_set_latency_range (jack_capt
, mode
, &range
);
189 jack_port_get_latency_range (jack_play
, mode
, &range
);
190 if ((range
.min
!= playback_latency
.min
) || (range
.max
!= playback_latency
.max
)) {
191 playback_latency
= range
;
192 printf ("new playback latency: [%d, %d]\n", range
.min
, range
.max
);
198 int jack_callback (jack_nframes_t nframes
, void *arg
)
202 ip
= (float *)(jack_port_get_buffer (jack_capt
, nframes
));
203 op
= (float *)(jack_port_get_buffer (jack_play
, nframes
));
204 mtdm_process (mtdm
, nframes
, ip
, op
);
208 int main (int ac
, char *av
[])
213 jack_handle
= jack_client_open ("jack_delay", JackNoStartServer
, &s
);
214 if (jack_handle
== 0)
216 fprintf (stderr
, "Can't connect to Jack, is the server running ?\n");
220 mtdm
= mtdm_new(jack_get_sample_rate(jack_handle
));
222 jack_set_process_callback (jack_handle
, jack_callback
, 0);
224 if (jack_set_latency_callback
)
225 jack_set_latency_callback (jack_handle
, latency_cb
, 0);
227 jack_capt
= jack_port_register (jack_handle
, "in", JACK_DEFAULT_AUDIO_TYPE
, JackPortIsInput
, 0);
228 jack_play
= jack_port_register (jack_handle
, "out", JACK_DEFAULT_AUDIO_TYPE
, JackPortIsOutput
, 0);
230 t
= 1000.0f
/ jack_get_sample_rate (jack_handle
);
232 if (jack_activate (jack_handle
))
234 fprintf(stderr
, "Can't activate Jack");
246 if (mtdm_resolve (mtdm
) < 0) printf ("Signal below threshold...\n");
249 jack_nframes_t systemic_latency
;
251 if (mtdm
->_err
> 0.3)
253 mtdm_invert ( mtdm
);
254 mtdm_resolve ( mtdm
);
256 systemic_latency
= (jack_nframes_t
) floor (mtdm
->_del
- (capture_latency
.max
+ playback_latency
.max
));
258 printf ("%10.3lf frames %10.3lf ms total roundtrip latency\n\textra loopback latency: %u frames\n\tuse %u for the backend arguments -I and -O", mtdm
->_del
, mtdm
->_del
* t
,
259 systemic_latency
, systemic_latency
/2);
260 if (mtdm
->_err
> 0.2) printf (" ??");
261 if (mtdm
->_inv
) printf (" Inv");
269 // --------------------------------------------------------------------------------