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 134 135 136 137 138
|
/*
* Pure Data Packet module. Standard sync rates.
* Copyright (c) by Tom Schouten <tom@zwizwa.be>
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* pdp_metro
this is the main audio/video sync module. use this if
you need to produce synchronized raw output. this uses
'industry standard' integer sampling ratios.
it works like this. for example, the most awkward 30 * 999/1000 Hz rate.
*/
#include "pdp.h"
typedef struct _metro_struct
{
t_object x_obj;
t_float x_f;
t_clock *x_clock;
t_outlet *x_outlet;
t_int x_count; // current count for (upsampled) audio ticks
t_int x_den; // video framerate denominator and nominator
t_int x_nom;
} t_metro;
static t_int *metro_perform(t_int *w);
#define DSP_ARG(type, name, source) type name = (type)source
static void metro_dsp(t_metro *x, t_signal **sp)
{
dsp_add(metro_perform, 3, x, sp[0]->s_n, (int)sys_getsr());
}
static t_int *metro_perform(t_int *w){
DSP_ARG(t_metro*, x, w[1]);
DSP_ARG(t_int, n, w[2]);
DSP_ARG(t_int, sr, w[3]);
t_int period = sr * x->x_nom;
t_int upsample = x->x_den;
t_int dobang = 0;
//fprintf(stderr, "%d/%d\t%d\t%d\n", x->x_den, x->x_nom, x->x_count, period);
x->x_count += n * upsample;
while (x->x_count > period) {
dobang = 1;
x->x_count -= period;
}
if (dobang) clock_set(x->x_clock, 0);
return w+4;
}
static void metro_tick(t_metro *x)
{
outlet_bang(x->x_outlet);
}
static void metro_reset(t_metro *x){
x->x_count = 0;
}
static void metro_fps(t_metro *x, t_float fden, t_float fnom)
{
int den = (int)fden;
int nom = (int)fnom;
if (den < 1) den = 1;
if (nom < 1) nom = 1;
x->x_den = den;
x->x_nom = nom;
}
static void metro_free(t_metro *x)
{
clock_unset(x->x_clock);
}
static t_class *metro_class;
static void *metro_new(t_symbol __attribute__((unused)) *s,
int __attribute__((unused)) argc,
__attribute__((unused)) t_atom *argv)
{
t_metro *x = (t_metro *)pd_new(metro_class);
x->x_outlet = outlet_new(&x->x_obj, &s_bang);
x->x_clock = clock_new(x, (t_method)metro_tick);
x->x_count = 0;
metro_fps(x, 1, 1);
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_metro_setup(void)
{
metro_class = class_new(gensym("pdp_metro~"), (t_newmethod)metro_new,
(t_method)metro_free, sizeof(t_metro), 0, A_NULL);
CLASS_MAINSIGNALIN(metro_class, t_metro, x_f);
class_addmethod(metro_class, (t_method)metro_tick, gensym("tick"), A_NULL);
class_addmethod(metro_class, (t_method)metro_dsp, gensym("dsp"), A_NULL);
class_addmethod(metro_class, (t_method)metro_fps, gensym("fps"), A_FLOAT, A_DEFFLOAT, A_NULL);
}
#ifdef __cplusplus
}
#endif
|