6 ///// Simple additive mixer /////
7 ///// TODO: handle different input formats /////
12 struct graphpin
*out_pin
;
16 static bool is_acceptable_input_format(struct graphnode
*node
, struct graphpin
*pin
, const struct aformat
*af
)
18 struct mixer
*m
= node
->extra
;
19 assert(pin
!= m
->out_pin
);
20 if (m
->format_is_set
){
21 return af
->media
== m
->af
.media
22 && af
->srate
== m
->af
.srate
23 && af
->channels
== m
->af
.channels
;
29 static err_t
get_output_format(struct graphnode
*node
, struct graphpin
*pin
, struct aformat
*af
)
31 struct mixer
*m
= node
->extra
;
32 assert(pin
== m
->out_pin
);
34 if (m
->format_is_set
){
38 return make_error(ECANNOT_GUESS_FORMAT
, node
, "mixer module is not yet bound to a format");
42 static err_t
set_buffer(struct graphnode
*node
, struct graphpin
*pin
, struct buffer
*buf
)
44 struct mixer
*m
= node
->extra
;
45 if (m
->format_is_set
){
46 if (buf
->format
.media
== m
->af
.media
47 && buf
->format
.srate
== m
->af
.srate
48 && buf
->format
.channels
== m
->af
.channels
){
51 return make_error(EBAD_FORMAT
, node
, "mixer module is being connected to a bad media format");
55 m
->format_is_set
= true;
60 static size_t longest_in_buf_len(struct graphnode
*restrict node
)
62 struct graphpin
*in_pin
;
65 for (in_pin
=node
->pins
; in_pin
; in_pin
=in_pin
->next
){
66 if (in_pin
->dir
!= DIR_IN
){
69 if (in_pin
->edge
->buf
.n_samples
> sz
){
70 sz
= in_pin
->edge
->buf
.n_samples
;
76 static err_t
run(struct graphnode
*node
)
79 T *restrict s_ptr, *restrict d_ptr; \
81 /* clear the output buffer */ \
82 d_ptr = d_buf->data; \
87 for (in_pin=node->pins; in_pin; in_pin=in_pin->next){ \
88 s_ptr = in_pin->edge->buf.data; \
89 d_ptr = d_buf->data; \
92 *d_ptr++ += *s_ptr++ / m->n_inputs; /* *boggle* */ \
97 struct mixer
*restrict m
= node
->extra
;
98 struct graphpin
*in_pin
;
99 struct buffer
*restrict d_buf
= &m
->out_pin
->edge
->buf
;
103 sz
= longest_in_buf_len(node
);
104 err
= buffer_alloc(d_buf
, sz
);
109 sz
*= m
->out_pin
->edge
->buf
.format
.channels
;
111 switch (m
->out_pin
->edge
->buf
.format
.media
){
119 return make_error(ENOTIMPL
, NULL
, "mixing these media types is not implemented");
122 static const struct graphnode_functab functab
= {
123 is_acceptable_input_format
,
124 NULL
, // get_ideal_input_format
130 err_t
mixer_create(struct graphnode
**node_out
, int n_inputs
)
132 struct graphnode
*node
;
134 struct graphpin
*in_pin
;
138 err
= graphnode_create(&node
, &functab
, sizeof *m
);
144 m
->n_inputs
= n_inputs
;
145 m
->format_is_set
= false;
148 err
= graphnode_add_pin(node
, &m
->out_pin
);
152 m
->out_pin
->dir
= DIR_OUT
;
153 m
->out_pin
->name
= "out";
156 for (i
=0; i
<n_inputs
; ++i
){
157 err
= graphnode_add_pin(node
, &in_pin
);
161 in_pin
->dir
= DIR_IN
;
162 in_pin
->name
= "in"; // how original