示例#1
0
static enum nz_pull_rc sequencer_pull(struct nz_port * port) {
    struct nz_node * node = port->port_node; 

    nz_obj_p inp_time = NZ_NODE_PULL(node, 0);
    nz_obj_p inp_stream = NZ_NODE_PULL(node, 1);

    if (inp_time == NULL || inp_stream == NULL) {
        return NZ_PULL_RC_NULL;
    }

    int t = (int) NZ_CAST(double, inp_time);

    size_t stream_idx = t % nz_vector_get_size(inp_stream);
    nz_obj_p* sequence = NZ_CAST(nz_obj_p*, inp_stream);
    nz_obj_p out = nz_obj_swap(&port->port_value, sequence[stream_idx]);

    return (out == NULL) ? NZ_PULL_RC_NULL : NZ_PULL_RC_OBJECT;
}
示例#2
0
文件: test.c 项目: EQ4/noise
int record_and_write(struct nz_node * recorder_node, const char * filename, double time_seconds) {
    DSL_DECLS;
    MAKE_LONG_CONSTANT(recorder_len, nz_frame_rate * time_seconds);
    CONNECT(recorder_node, 1, recorder_len, 0);

    // Trigger the computation
    struct nz_obj * sample = nz_port_pull(&recorder_node->node_outputs[0]);
    printf("Writing %lu frames to %s", nz_vector_get_size(sample), filename);

    SF_INFO fdata = {
        .frames = nz_vector_get_size(sample),
        .samplerate = nz_frame_rate,
        .channels = 1,
        .format = SF_FORMAT_WAV | SF_FORMAT_PCM_16,
        .sections = 1,
        .seekable = 0,
    };

    SNDFILE * f = sf_open(filename, SFM_WRITE, &fdata);
    sf_write_double(f, NZ_CAST(double *, sample), nz_vector_get_size(sample));
    sf_write_sync(f);
    sf_close(f);
    return 0;
}

int main(void) {
    DSL_DECLS;
    // Timebase
    // (frames / chunk) / (frames / second) * (beats / minute) / (seconds / minute) 
    // = (frames * second * beats * minute) / (chunk * frames * minute * second) 
    // = (beats / chunk)

    BLOCK(timebase, accumulator);
    MAKE_DOUBLE_CONSTANT(delta_t, nz_chunk_size / nz_frame_rate * 280 / 60.);
    CONNECT(_blk, 0, _cons, 0);

    BLOCK(time_tee, tee, 4);
    CONNECT(time_tee, 0, _pipe, 0);

    // Debug
    BLOCK(debug_time, debug, "time", 0);
    CONNECT(_blk, 0, _pipe, 0);

    BLOCK(time_wye, wye, 2);
    CONNECT(time_wye, 1, _pipe, 0);

    // Melody
    // TODO: Come up with a better way of specifying these
    double unison[] = {None, None, None, 65, 75, None, 72, 67, 67, 68, None, 65, 70, 72, 70, 65, 65, None, None, 65, 75, None, 72, 67, 67, 68, 65, 72, 75, None, 72, 77};
    size_t unison_len = sizeof(unison) / sizeof(*unison);

    struct nz_obj * melody_obj = make_double_vector(unison,  unison_len);
    BLOCK(melody, constant, melody_obj);

    // Sequencer
    BLOCK(seq, sequencer);
    CONNECT(_blk, 0, time_tee, 1);
    CONNECT(_blk, 1, melody, 0);

    // Debug
    BLOCK(debug_seq, debug, "seq", 0);
    CONNECT(_blk, 0, seq, 0);

    BLOCK(lpf, lpf);
    CONNECT(_blk, 0, _pipe, 0);
    MAKE_CONSTANT(lpf_alpha, nz_double_type, double, 2);
    CONNECT(_blk, 1, _cons, 0);

    // Debug
    BLOCK(debug_lpf, debug, "lpf", 0);
    CONNECT(_blk, 0, _pipe, 0);

    // Math
    BLOCK(n2f, math, NZ_MATH_NOTE_TO_FREQ);
    CONNECT(_blk, 0, _pipe, 0);

    // Instrument
    BLOCK(wave, wave);
    CONNECT(_blk, 0, _pipe, 0);
    MAKE_CONSTANT(wtype, nz_long_type, long, NZ_WAVE_SAW);
    CONNECT(_blk, 1, _cons, 0);

    // --- Percussion ---

    // -- Snare --
    BLOCK(snare_imp, impulse);

    BLOCK(snare_lpf, clpf);
    CONNECT(_blk, 0, snare_imp, 0);
    MAKE_DOUBLE_CONSTANT(snare_tau, 8.5);
    CONNECT(_blk, 1, _cons, 0);

    BLOCK(snare_wav, white);

    BLOCK(snare_mix, cmixer, 1);
    CONNECT(_blk, 0, snare_wav, 0);
    CONNECT(_blk, 1, snare_lpf, 0);

    BLOCK(snare_rec, recorder);
    CONNECT(_blk, 0, _pipe, 0);
    MAKE_LONG_CONSTANT(snare_len, nz_frame_rate * 0.5);
    CONNECT(_blk, 1, _cons, 0);
    //nz_record_and_write(snare_rec, "snare.wav", 0.5);

    // -- Kick --
    BLOCK(kick_imp, impulse);

    MAKE_DOUBLE_CONSTANT(kick_tau, 8.5);
    BLOCK(kick_lpf, clpf);
    CONNECT(_blk, 0, kick_imp, 0);
    CONNECT(_blk, 1, kick_tau, 0);

    BLOCK(kick_wav, wave);
    MAKE_DOUBLE_CONSTANT(kick_freq, 80);
    CONNECT(_blk, 0, _cons, 0);
    MAKE_LONG_CONSTANT(kick_wtype, NZ_WAVE_SINE);
    CONNECT(_blk, 1, _cons, 0);

    BLOCK(kick_mix, cmixer, 1);
    CONNECT(_blk, 0, kick_wav, 0);
    CONNECT(_blk, 1, kick_lpf, 0);

    BLOCK(kick_rec, recorder);
    CONNECT(_blk, 0, _pipe, 0);
    MAKE_LONG_CONSTANT(kick_len, nz_frame_rate * 0.5);
    CONNECT(_blk, 1, _cons, 0);

    // Kick & Snare sampling
    long snare_pat[] = {NZ_SAMPLER_COMMAND_PLAY, NZ_SAMPLER_COMMAND_PLAY, NZ_SAMPLER_COMMAND_STOP, NZ_SAMPLER_COMMAND_STOP};
    long kick_pat[]  = {NZ_SAMPLER_COMMAND_STOP, NZ_SAMPLER_COMMAND_STOP, NZ_SAMPLER_COMMAND_PLAY, NZ_SAMPLER_COMMAND_PLAY};

    struct nz_node * snare = make_drum(snare_rec, snare_pat, 4, time_tee, 2);
    struct nz_node * kick = make_drum(kick_rec, kick_pat, 4, time_tee, 3);

    // Mixer
    BLOCK(mixer, mixer, 3);

    MAKE_DOUBLE_CONSTANT(wave_vol, 0.40);
    MAKE_DOUBLE_CONSTANT(snare_vol, 0.80);
    MAKE_DOUBLE_CONSTANT(kick_vol, 2.0);

    CONNECT(mixer, 0, wave, 0);
    CONNECT(mixer, 1, wave_vol, 0);
    CONNECT(mixer, 2, snare, 0);
    CONNECT(mixer, 3, snare_vol, 0);
    CONNECT(mixer, 4, kick, 0);
    CONNECT(mixer, 5, kick_vol, 0);

    CONNECT(time_wye, 0, mixer, 0);
    
    // Debug
    BLOCK(debug_ch, debug, "ch", 0);
    CONNECT(_blk, 0, _pipe, 0);

    // Compressor
    BLOCK(compressor, compressor);
    CONNECT(_blk, 0, _pipe, 0);

    // Recorder
    BLOCK(recorder, recorder);
    CONNECT(_blk, 0, _pipe, 0);

    nz_debug_print_graph(recorder);
    nz_debug_print_dot(recorder, "unison.dot");

    // This triggers everything!
    record_and_write(recorder, "unison.wav", 10);


    /*
    // Soundcard 
    printf("Initing soundcard\n");
    struct nz_node * soundcard = soundcard_get();
    node_connect(soundcard, 0, time_wye, 0);
    printf("soundcard inited\n");

    debug_print_graph(soundcard);
    soundcard_run();

    node_destroy(delta_t);
    node_destroy(melody);
    node_destroy(mixer);
    node_destroy(n2f);
    node_destroy(seq);
    node_destroy(soundcard);
    node_destroy(time_tee);
    node_destroy(time_wye);
    node_destroy(timebase);
    node_destroy(wave);
    node_destroy(wave_vol);
    node_destroy(wtype);

    printf("Successfully destroyed everything!\n");
    */

    return 0;
}