📄 yin.c
字号:
* interesting thing can happen here. snd_list_create, which * we just called, MAY have invoked the garbage collector, and * the GC MAY have freed all references to this channel, in which * case yin_free(susp) will have been called, and susp->chan[0] * will now be NULL! */ if (!susp->chan[0]) { ffree_snd_list(snd_list, "yin_fetch"); } else { susp->chan[0]->u.next = snd_list; } } /* see the note above: we don't know if susp->chan still exists */ /* Note: We DO know that susp still exists because even if we lost * some channels in a GC, someone is still calling SND_get_next on * some channel. I suppose that there might be some very pathological * code that could free a global reference to a sound that is in the * midst of being computed, perhaps by doing something bizarre in the * closure that snd_seq activates at the logical stop time of its first * sound, but I haven't thought that one through. */ if (susp->chan[0]) { susp->chan[0]->block = f0; /* check some assertions */ if (susp->chan[0]->u.next->u.susp != (snd_susp_type) susp) { nyquist_printf("didn't find susp at end of list for chan 0\n"); } } else if (f0) { /* we allocated f0, but don't need it anymore due to GC */ ffree_sample_block(f0, "yin_fetch"); f0_ptr = NULL; } } /* Now, repeat for channel 1 (comments omitted) */ if (susp->chan[1]) { falloc_sample_block(harmonicity, "yin_fetch"); harmonicity_ptr = harmonicity->samples; if (!susp->chan[1]) { ffree_sample_block(harmonicity, "yin_fetch"); harmonicity = NULL; /* make sure we don't free it again */ harmonicity_ptr = NULL; } else if (!susp->chan[1]->block) { snd_list_type snd_list = snd_list_create((snd_susp_type) susp); if (!susp->chan[1]) { ffree_snd_list(snd_list, "yin_fetch"); } else { susp->chan[1]->u.next = snd_list; } } if (susp->chan[1]) { susp->chan[1]->block = harmonicity; if (susp->chan[1]->u.next->u.susp != (snd_susp_type) susp) { nyquist_printf("didn't find susp at end of list for chan 1\n"); } } else if (harmonicity) { /* we allocated harmonicity, but don't need it anymore due to GC */ ffree_sample_block(harmonicity, "yin_fetch"); harmonicity_ptr = NULL; } } while (cnt < max_sample_block_len) { /* outer loop */ /* first, compute how many samples to generate in inner loop: */ /* don't overflow the output sample block */ togo = (max_sample_block_len - cnt) * susp->stepsize; /* don't run past the s input sample block */ susp_check_term_log_samples(s, s_ptr, s_cnt); togo = min(togo, susp->s_cnt); /* don't run past terminate time */ if (susp->terminate_cnt != UNKNOWN && susp->terminate_cnt <= susp->susp.current + cnt + togo/susp->stepsize) { togo = (susp->terminate_cnt - (susp->susp.current + cnt)) * susp->stepsize; if (togo == 0) break; } /* don't run past logical stop time */ if (!susp->logically_stopped && susp->susp.log_stop_cnt != UNKNOWN) { int to_stop = susp->susp.log_stop_cnt - (susp->susp.current + cnt); /* break if to_stop = 0 (we're at the logical stop) * AND cnt > 0 (we're not at the beginning of the output block) */ if (to_stop < togo/susp->stepsize) { if (to_stop == 0) { if (cnt) { togo = 0; break; } else /* keep togo as is: since cnt == 0, we can set * the logical stop flag on this output block */ susp->logically_stopped = true; } else /* limit togo so we can start a new block a the LST */ togo = to_stop * susp->stepsize; } } n = togo; s_ptr_reg = susp->s_ptr; fillptr_reg = susp->fillptr; if (n) do { /* the inner sample computation loop */ *fillptr_reg++ = *s_ptr_reg++; if (fillptr_reg >= endptr_reg) { float f0; float harmonicity; yin_compute(susp, &f0, &harmonicity); if (f0_ptr) *f0_ptr++ = f0; if (harmonicity_ptr) *harmonicity_ptr++ = harmonicity; cnt++; fillptr_reg -= susp->stepsize; } } while (--n); /* inner loop */ /* using s_ptr_reg is a bad idea on RS/6000: */ susp->s_ptr += togo; susp->fillptr = fillptr_reg; susp_took(s_cnt, togo); } /* outer loop */ /* test for termination */ if (togo == 0 && cnt == 0) { snd_list_terminate(snd_list); } else { snd_list->block_len = cnt; susp->susp.current += cnt; } /* test for logical stop */ if (susp->logically_stopped) { snd_list->logically_stopped = true; } else if (susp->susp.log_stop_cnt == susp->susp.current) { susp->logically_stopped = true; }} /* yin_fetch */ void yin_mark(yin_susp_type susp){ sound_xlmark(susp->s);}void yin_free(yin_susp_type susp){ int j; boolean active = false;/* stdputstr("yin_free: "); */ for (j = 0; j < 2; j++) { if (susp->chan[j]) { if (susp->chan[j]->refcnt) active = true; else { susp->chan[j] = NULL; /* nyquist_printf("deactivating channel %d\n", j); */ } } } if (!active) {/* stdputstr("all channels freed, freeing susp now\n"); */ ffree_generic(susp, sizeof(yin_susp_node), "yin_free"); sound_unref(susp->s); free(susp->block); free(susp->temp); }}void yin_print_tree(yin_susp_type susp, int n){ indent(n); stdputstr("s:"); sound_print_tree_1(susp->s, n);}LVAL snd_make_yin(sound_type s, double low_step, double high_step, long stepsize){ LVAL result; int j; register yin_susp_type susp; rate_type sr = s->sr; time_type t0 = s->t0; falloc_generic(susp, yin_susp_node, "snd_make_yin"); susp->susp.fetch = yin_fetch; susp->terminate_cnt = UNKNOWN; /* initialize susp state */ susp->susp.free = yin_free; susp->susp.sr = sr / stepsize; susp->susp.t0 = t0; susp->susp.mark = yin_mark; susp->susp.print_tree = yin_print_tree; susp->susp.name = "yin"; susp->logically_stopped = false; susp->susp.log_stop_cnt = logical_stop_cnt_cvt(s); susp->susp.current = 0; susp->s = s; susp->s_cnt = 0; susp->m = (long) (sr / step_to_hz(high_step)); if (susp->m < 2) susp->m = 2; /* add 1 to make sure we round up */ susp->middle = (long) (sr / step_to_hz(low_step)) + 1; susp->blocksize = susp->middle * 2; susp->stepsize = stepsize; /* blocksize must be at least step size to implement stepping */ if (susp->stepsize > susp->blocksize) susp->blocksize = susp->stepsize; susp->block = (sample_type *) malloc(susp->blocksize * sizeof(sample_type)); susp->temp = (float *) malloc((susp->middle - susp->m + 1) * sizeof(float)); susp->fillptr = susp->block; susp->endptr = susp->block + susp->blocksize; xlsave1(result); result = newvector(2); /* create array for F0 and harmonicity */ /* create sounds to return */ for (j = 0; j < 2; j++) { sound_type snd = sound_create((snd_susp_type)susp, susp->susp.t0, susp->susp.sr, 1.0); LVAL snd_lval = cvsound(snd);/* nyquist_printf("yin_create: sound %d is %x, LVAL %x\n", j, snd, snd_lval); */ setelement(result, j, snd_lval); susp->chan[j] = snd->list; } xlpop(); return result;}LVAL snd_yin(sound_type s, double low_step, double high_step, long stepsize){ sound_type s_copy = sound_copy(s); return snd_make_yin(s_copy, low_step, high_step, stepsize);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -