struct nz_node * make_drum(struct nz_node * record, const long * hits, size_t hits_len, struct nz_node * time_tee, size_t tinp) { struct nz_obj * hits_obj = nz_obj_create(nz_object_vector_type); DSL_DECLS; nz_vector_set_size(hits_obj, hits_len); for (size_t i = 0; i < hits_len; i++) { struct nz_obj * v = nz_obj_create(nz_long_type); NZ_CAST(long, v) = hits[i]; NZ_CAST(struct nz_obj **, hits_obj)[i] = v; } MBLOCK(hits_node, constant, hits_obj); MBLOCK(hits_seq, sequencer); CONNECT(hits_seq, 0, time_tee, tinp); CONNECT(hits_seq, 1, hits_node, 0); MBLOCK(debug, debug, "hit", 1); CONNECT(debug, 0, record, 0); MBLOCK(voice, sampler); CONNECT(voice, 0, debug, 0); CONNECT(voice, 1, hits_seq, 0); return voice; }
struct nz_obj * make_double_vector(double * array, size_t len) { DSL_DECLS; struct nz_obj * obj = nz_obj_create(nz_object_vector_type); nz_vector_set_size(obj, len); for (size_t i = 0; i < len; i++) { if (array[i] == None) continue; struct nz_obj * v = nz_obj_create(nz_double_type); NZ_CAST(double, v) = array[i]; NZ_CAST(struct nz_obj **, obj)[i] = v; } return obj; }
int nz_fungen_init(struct nz_node * node) { int rc = nz_node_alloc_ports(node, 1, 1); if (rc != 0) return rc; node->node_term = &nz_node_term_generic; node->node_name = strdup("Sine"); // Define inputs node->node_inputs[0] = (struct nz_inport) { .inport_type = nz_double_type, .inport_name = strdup("time"), }; // Define outputs node->node_outputs[0] = (struct nz_port) { .port_node = node, .port_name = strdup("sin(t)"), .port_pull = &fungen_pull, .port_type = nz_double_type, .port_value = nz_obj_create(nz_double_type), }; if (node->node_outputs[0].port_value == NULL) return (nz_node_term(node), -1); return 0; }
int nz_impulse_init(struct nz_node * node) { int rc = nz_node_alloc_ports(node, 1, 1); if (rc != 0) return rc; node->node_name = strdup("Impulse"); node->node_term = &nz_node_term_generic; // Define inputs node->node_inputs[0] = (struct nz_inport) { .inport_type = nz_double_type, .inport_name = strdup("trigger"), }; // Define outputs node->node_outputs[0] = (struct nz_port) { .port_node = node, .port_name = strdup("impulse"), .port_pull = &impulse_pull, .port_type = nz_chunk_type, .port_value = nz_obj_create(nz_chunk_type), }; if (node->node_outputs[0].port_value == NULL) return (nz_node_term(node), -1); // Initialize state node->node_state = calloc(1, sizeof(struct state)); struct state * state = (struct state *) node->node_state; if (node->node_state == NULL) return (nz_node_term(node), -1); state->status = STATUS_NEW; return 0; }
static enum nz_pull_rc recorder_pull(struct nz_port * port) { struct nz_node * node = port->port_node; struct nz_obj * inp_len = NZ_NODE_PULL(node, 1); if (inp_len == NULL) return NZ_PULL_RC_NULL; size_t length = NZ_CAST(long, inp_len); size_t t = 0; free(port->port_value); port->port_value = nz_obj_create(nz_sample_type); // Resize sample size & fail if there's a problem size_t new_length = nz_vector_set_size(port->port_value, length); if (new_length != length) return NZ_PULL_RC_ERROR; double * samples = NZ_CAST(double *, port->port_value); int count = 0; while (t < length) { struct nz_obj * inp_chunk = NZ_NODE_PULL(node, 0); if (inp_chunk == NULL) { // We don't want to loop forever, if `inp_chunk` continues to be NULL // TODO: how should this be handled? fprintf(stderr, "Recorder pulled a null chunk; could loop forever; returning error.\n"); return NZ_PULL_RC_ERROR; //assert(0); continue; } double * chunk = &NZ_CAST(double, inp_chunk); if (t + nz_chunk_size < length) { memcpy(&samples[t], chunk, sizeof(double) * nz_chunk_size); t += nz_chunk_size; } else { while(t < length) samples[t++] = *chunk++; } } return NZ_PULL_RC_OBJECT; }