⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 multiseq.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
📖 第 1 页 / 共 2 页
字号:
    } else xlerror("closure did not return a sound", result);    /* now result holds a vector of nchans, insert them into add_susp's */    for (i = 0; i < ms->nchans; i++) {        snd_list_type snd_list = ms->chans[i];        add_susp_type susp = (add_susp_type) snd_list->u.susp;        long sother_start;        /* remove backpointer to ms */        susp->multiseq = NULL;        susp->susp.print_tree = add_print_tree;        susp->susp.free = add_free;        susp->susp.mark = add_mark;        susp->s2 = sound_copy(getsound(getelement(result, i)));        if (susp->s1->sr != susp->s2->sr)            xlfail("multiseq: sample rates must match");        if (susp->s2->scale != 1.0) {            susp->s2 = snd_make_normalize(susp->s2);        }        sother_start = ROUND((susp->s2->t0 - susp->susp.t0) * susp->s2->sr);D	    nyquist_printf("sother_start computed for %p: %d\n",                      susp, (int)sother_start);        if (sother_start > susp->susp.current) {D	    nyquist_printf("susp %p using add_s1_nn_fetch\n", susp);            susp->susp.fetch = add_s1_nn_fetch;            susp->susp.name = "multiseq:add_s1_nn_fetch";        } else if (susp->terminate_bits) { /* s1 is done, just get s2 now */            sound_unref(susp->s1);            susp->s1 = NULL;D	    nyquist_printf("susp %p using add_s2_nn_fetch\n", susp);            susp->susp.fetch = add_s2_nn_fetch;            susp->susp.name = "multiseq:add_s2_nn_fetch";        } else {D	    nyquist_printf("susp %p using add_s1_s2_nn_fetch\n", susp);            susp->susp.fetch = add_s1_s2_nn_fetch;            susp->susp.name = "multiseq:add_s1_s2_nn_fetch";        }        /* fix up logical stop info */        /* BUG: what if s2 is already stopped? */        susp->susp.log_stop_cnt = UNKNOWN;        susp->logically_stopped = false;        /* we need to compute at least 1 sample         * (at this point we don't really know if we've         * computed anything or not, so to be safe, do it.         */        snd_list->u.next = snd_list_create(&(susp->susp));        snd_list->block = internal_zero_block;        (*(susp->susp.fetch))(susp, snd_list);    }        /* now free the multiseq struct */    size = sizeof(snd_list_type) * ms->nchans;    ffree_generic(ms->chans, size, "multiseq_convert");    ffree_generic(ms, sizeof(multiseq_node), "multiseq_convert(2)");    ms->closure = NIL;	/* allow garbage collection now */    xlpop();}/* multiseq_fetch returns blocks of s1 until the logical stop time of s1's *//* * Fetch routines (in particular, the add_*_fetch routines that will * be installed on this susp at a later time) expect to be called with * a new snd_list installed and ready for a new block.  However, since * we are going to call multiseq_advance to pull blocks out of susps  * that will not be set up with a fresh snd_list in this way, it is  * simpler to dispose of the preallocated snd_list so that all susps * look alike to multiseq_advance.  Of course, multiseq_advance will * redo the work of allocating a snd_list. * * If a channel terminates early, we must be careful: continuing to * fetch will return pointers to the zero_block, but this will * indicate termination to whoever is fetching from multiseq. We * must check the pointers and substitute internal_zero_block to * avoid premature termination. */void multiseq_fetch(susp, snd_list)  register add_susp_type susp;  snd_list_type snd_list;{    time_type block_end_time;    /* undo the preallocation of a snd_list_node */    /* we can bypass the reference counting code because we     * know that this snd_list was just allocated and has no     * other references     */#ifdef MULTISEQ_GC_DEBUG    if (snd_list_to_watch == snd_list->u.next) {        nyquist_printf("multiseq_fetch: backing out snd_list_to_watch from %p\n",               snd_list_to_watch);        watch_snd_list(snd_list);    }#endif    ffree_snd_list(snd_list->u.next, "multiseq_fetch");    snd_list->u.susp = (snd_susp_type) susp;    snd_list->block = NULL;D    nyquist_printf("multiseq_fetch called: susp %p s1_cnt %d\n",                    susp, (int)susp->s1_cnt);    /* first compute how many samples we can generate from s1: */    if (susp->s1_cnt == 0) {        susp_get_block_samples(s1, s1_bptr, s1_ptr, s1_cnt);        if (susp->s1_ptr == zero_block->samples) {            susp->terminate_bits = 1;   /* mark s1 as terminated */            susp->s1_bptr = internal_zero_block;            susp->s1_ptr = internal_zero_block->samples;        }        /* see if we've reached a logical stop         * (I can't believe this code block is in 3 places -         *  there must be a better way... RBD)         */        if (!susp->logical_stop_bits) {            if (susp->s1->logical_stop_cnt != UNKNOWN) {                if (susp->susp.current + susp->s1_cnt >=                    susp->s1->logical_stop_cnt) {                    susp->logical_stop_bits = 1;                    susp->susp.log_stop_cnt =                       susp->s1->logical_stop_cnt;                    susp->multiseq->not_logically_stopped_cnt--;D		    nyquist_printf( "snd_make_multiseq: Logical stop reached, not_logically_stopped_cnt %d\n",                          susp->multiseq->not_logically_stopped_cnt);                }            }        }    }    /* s1_cnt has the number of samples we can return */    /* now compute time of the last sample */    block_end_time = susp_time(susp, susp->multiseq);D   nyquist_printf("block_end_time of %p: %g\n", susp, block_end_time);    multiseq_advance(susp->multiseq,  block_end_time);}/* multiseq_mark -- mark routine for multiseq susps *//**/void multiseq_mark(add_susp_type susp){    int i;    multiseq_type ms = susp->multiseq;D    nyquist_printf("multiseq_mark(%p)\n", susp);/*    nyquist_printf("marking s1@%p in add@%p\n", susp->s1, susp);*/    if (ms->closure) mark(ms->closure);    /* mark s1 of each susp in multiseq */    for (i = 0; i < ms->nchans; i++) {        snd_list_type snd_list = ms->chans[i];        if (snd_list) {            while (snd_list->block != NULL) {                if (snd_list == zero_snd_list) break;                snd_list = snd_list->u.next;            }            sound_xlmark(((add_susp_type) snd_list->u.susp)->s1);        }    }}/* snd_make_multiseq -- make a multiseq from an array and a closure *//* * NOTE: the resulting array of sounds will not use the normal * SND_get_first and SND_get_next routines to fetch new blocks * because these extend the snd_list of the sound immediately, * and this would confuse multiseq_advance() which has to extend * multiple snd_lists synchronously.  So, we use multiseq_get_next() * instead. */LVAL snd_make_multiseq(LVAL s1, LVAL closure){    multiseq_type ms;    int i;    LVAL result;    xlsave1(result);    /* allocate multiseq */    falloc_generic(ms, multiseq_node, "snd_make_multiseq");    /* install its array of snd_list_type */    if (!vectorp(s1) || getsize(s1) == 0) {        ffree_generic(ms, sizeof(multiseq_node), "snd_make_multiseq");        xlerror("bad argument type", s1);    }    ms->nchans = getsize(s1);    ms->closure = closure;    ms->not_logically_stopped_cnt = 0;    ms->low_water = 0.0;    ms->horizon = 0.0;    falloc_generic_n(ms->chans, snd_list_type, ms->nchans,                     "snd_make_multiseq");    /* allocate sounds to return */    result = newvector(ms->nchans);    /* ms->t0 will be the minimum of all t0's in array */    ms->t0 = (getsound(getelement(s1, 0)))->t0;    /* create sounds to return */    for (i = 0; i < ms->nchans; i++) {        add_susp_type susp;        sound_type snd;        falloc_generic(susp, add_susp_node, "snd_make_multiseq(add_susp)");        susp->s1 = sound_copy(getsound(getelement(s1, i)));        /* we used to only incr this if lsc was UNKNOWN, but           that's wrong. Should move this out of the loop now.         */        if (susp->s1->scale != 1.0) {            /* stdputstr("normalizing first sound in a seq\n"); */            susp->s1 = snd_make_normalize(susp->s1);        }        ms->not_logically_stopped_cnt++;D	nyquist_printf("snd_make_multiseq: not_logically_stopped_cnt %d\n",               ms->not_logically_stopped_cnt);        susp->s1_cnt = 0;        susp->s2 = NULL;        susp->s2_cnt = 0;        susp->susp.fetch = multiseq_fetch;        susp->susp.free = multiseq_free;        susp->susp.sr = susp->s1->sr;        susp->susp.mark = multiseq_mark;        susp->susp.print_tree = multiseq_print_tree;        susp->susp.name = "multiseq";        susp->susp.t0 = susp->s1->t0;        susp->terminate_bits = 0;   /* bits for s1 and s2 termination */        susp->terminate_cnt = UNKNOWN;        susp->logical_stop_bits = 0;    /* bits for s1 and s2 log. stop */        susp->susp.log_stop_cnt = UNKNOWN;        susp->logically_stopped = false;        susp->started = false;        susp->susp.current = 0;        susp->multiseq = ms;        snd = sound_create((snd_susp_type) susp, susp->s1->t0, susp->susp.sr,                           1.0);#ifdef GC_DEBUG        if (snd == sound_to_watch) {            nyquist_printf("watched sound is channel %d\n", i);        }#endif	        setelement(result, i, cvsound(snd));        if (snd->list->block || !snd->list->u.susp) {            stdputstr("data inconsistency in snd_make_seq\n");            EXIT(1);        }        ms->chans[i] = snd->list;D        nyquist_printf("ms->chans[%d] = %p, %p->u.susp = %p\n",                i, snd->list, snd->list, snd->list->u.susp);        ms->t0 = MIN(ms->t0, susp->s1->t0);        ms->sr = susp->s1->sr;	/* assume all samp rates are equal */D        nyquist_printf("Multiseq sound[%d]: \n", i);D        sound_print_tree(susp->s1);    }D    nyquist_printf("ms->t0 == %g\n", ms->t0);    xlpop();    return result;}/* note: snd_multiseq is a noop, just call snd_make_multiseq */void multiseq_free(add_susp_type susp){    int i;    multiseq_type ms = susp->multiseq;    boolean dead = true;    sound_unref(susp->s1);    sound_unref(susp->s2);  /* probably not necessary */    /* tricky part: remove pointer from ms->chans */    for (i = 0; i < ms->nchans; i++) {        if (ms->chans[i]) {            dead = false;            /*              * note that ms->chans is still a valid              * pointer (see snd_list_unref)             */            if (ms->chans[i]->u.susp == (snd_susp_type) susp) {                ms->chans[i] = NULL;D                nyquist_printf("susp %p freed, ms@%p->chans[%d] = NULL\n",                        susp, ms, i);            }        }    }    /* if last element is freed, free the multiseq struct too */    if (dead) {        i = sizeof(snd_list_type) * ms->nchans;        ffree_generic(ms->chans, i, "multiseq_free");        ffree_generic(ms, sizeof(multiseq_node), "multiseq_free(2)");    }    susp->multiseq = NULL;  /* just to be safe */    ffree_generic(susp, sizeof(add_susp_node), "multiseq_free(3)");}void multiseq_print_tree(add_susp_type susp, int n){    int i;    indent(n);    if (!susp->multiseq) {        xlfail("internal error: missing multiseq structure");    }    nyquist_printf("multiseq@%p = [ ", susp->multiseq);    for (i = 0; i < susp->multiseq->nchans; i++) {        if (susp->multiseq->chans[i]) {            nyquist_printf("%p", susp->multiseq->chans[i]->u.susp);        } else {            stdputstr("NULL");        }    }    indent(n);    stdputstr("s1:");    sound_print_tree_1(susp->s1, n);    indent(n);    stdputstr("closure:");    stdprint(susp->multiseq->closure);    indent(n);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -