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

📄 sound.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
📖 第 1 页 / 共 4 页
字号:
void table_free(table_type table){    long len = (long) (table->length) + 1;    long bytes = table_size_in_bytes(len);    free(table);    table_memory -= bytes;}void table_unref(table_type table){    if (!table) return;    table->refcount--;    if (table->refcount <= 0) {        /* nyquist_printf("table refcount went to zero\n"); */        table_free(table);    }}void sound_unref(sound_type snd)/* note that sounds do not have ref counts, so sound_unref * always frees the sound object */{    if (!snd) return;    snd_list_unref(snd->list);    table_unref(snd->table);/*    nyquist_printf("\t\t\t\t\tfreeing sound@%p\n", snd);*/    if (snd->extra) free(snd->extra);    ffree_sound(snd, "sound_unref");}void snd_list_ref(snd_list_type list){    list->refcnt++;}void snd_list_terminate(snd_list)  snd_list_type snd_list;{    snd_susp_type susp = snd_list->u.next->u.susp;    long lsc = susp->log_stop_cnt;    long current = susp->current;    /* unreference the empty sample block that was allocated: */    sample_block_unref(snd_list->block);    /* use zero_block instead */    snd_list->block = zero_block;    /* either fetch more zeros or terminate now */    if (lsc != UNKNOWN && lsc > current) {        /* nyquist_printf("snd_list_terminate: lsc %d current %d\n",                 lsc, current); */        susp->fetch = fetch_zeros;        fetch_zeros(susp, snd_list);    } else {        snd_list->block_len = max_sample_block_len;        snd_list->logically_stopped = true;        snd_list_unref(snd_list->u.next);        snd_list->u.next = zero_snd_list;       /* be zero forever */    }}void snd_list_unref(snd_list_type list){    void (*freefunc)();    if (list == NULL || list == zero_snd_list) {        if (list == NULL)           nyquist_printf("why did snd_list_unref get %p?\n", list);        return;    }    list->refcnt--;/*    nyquist_printf("snd_list_unref "); print_snd_list_type(list); stdputstr("\n"); */    if (list->refcnt == 0) {        if (list->block && list->block != zero_block) {            /* there is a next snd_list *//*          stdputstr("["); */            sample_block_unref(list->block);/*          stdputstr("]"); */            snd_list_unref(list->u.next);        }        else if (list->block == NULL) { /* the next thing is the susp */            /* free suspension structure */            /* nyquist_printf("freeing susp@%p\n", list->u.susp); */            freefunc = list->u.susp->free;            (*freefunc)(list->u.susp);        }        /* nyquist_printf("freeing snd_list@%p\n", list); */        ffree_snd_list(list, "snd_list_unref");    }}void sample_block_ref(sample_block_type sam){    sam->refcnt++;}void sample_block_test(sample_block_type sam, char *s){    /* see if this block is being watched */    int i;    for (i = 0; i < blocks_to_watch_len; i++) {        if ((sam > (blocks_to_watch[i] - 1)) &&            (sam < (blocks_to_watch[i] + 1))) {            nyquist_printf(    "WOOPS! %s(0x%p) refers to a block 0x%p on the watch list!\n",                    s, sam, blocks_to_watch[i]);        }    }}void sample_block_unref(sample_block_type sam){    sam->refcnt--;    if (sam->refcnt == 0) {#ifndef GCBUG    sample_block_test(sam, "sample_block_unref");#endif        /*      nyquist_printf("freeing sample block %p\n", sam); */        ffree_sample_block(sam, "sample_block_unref");    }}/*****************************************************************************                                interp_style* Inputs:*       sound_type s: The sound we are using*       rate_type sr: The sampling rate* Result: int*       A small integer which is one of the symbolic values:*       The values are ordered, smallest to largest, as*               INTERP_n - none*               INTERP_s - scale*               INTERP_i - interpolated*               INTERP_r - ramp** Notes: *       The sampling rate s->sr and scale factor s->scale are compared*       with other values exactly (no fuzz).  ****************************************************************************/int interp_style(sound_type s, rate_type sr){    if (s->sr == sr)        { /* same sample rate */        return ((s->scale == 1.0) ? INTERP_n : INTERP_s);       } /* same sample rate */    else     if (s->sr * 10.0 > sr)        { /* 10x sample rate */        return INTERP_i;       } /* 10x sample rate */    else        return INTERP_r;}/*****************************************************************************                                 snd_sort_2* Inputs:*       sound_type * s1_ptr:*       sound_type * s2_ptr:*       rate_type sr:* Result: void*       * Effect: *       If the interp_style of s1 dominates the interp_style of s2,*       the sound_types input are interchanged.****************************************************************************//* snd_sort_2 -- sort 2 arguments by interpolation method */void snd_sort_2(sound_type *s1_ptr, sound_type *s2_ptr, rate_type sr){    if (interp_style(*s1_ptr, sr) > interp_style(*s2_ptr, sr)) {        sound_type s = *s1_ptr;        *s1_ptr = *s2_ptr;        *s2_ptr = s;    }}/* snd_sref -- access a sound at a given time point *//**/double snd_sref(sound_type s, time_type t){    double exact_cnt;      /* how many fractional samples to scan */    int cnt;               /* how many samples to flush */    sample_block_type sampblock = NULL;    long blocklen;    sample_type x1, x2;    /* interpolate between these samples */        /* changed true_t0 to just t0 based on comment that true_t0 is only         * for use by snd_prepend_zeros -RBD         */    exact_cnt = (t - s->t0) * s->sr;    if (exact_cnt < 0.0) return 0.0;    s = sound_copy(s);     /* don't modify s, create new reader */    cnt = (long) exact_cnt;       /* rounds down */    exact_cnt -= cnt;      /* remember fractional remainder */    /* now flush cnt samples */    while (cnt >= 0) {        sampblock = sound_get_next(s, &blocklen);        cnt -= blocklen;        if (sampblock == zero_block) {            sound_unref(s);            return 0.0;        }    }    /* -blocklen <= cnt <= -1 */    /* get next 2 samples and interpolate */    x1 = sampblock->samples[blocklen + cnt];    if (cnt == -1) {        sampblock = sound_get_next(s, &blocklen);        cnt -= blocklen;    }    x2 = sampblock->samples[blocklen + cnt + 1];    sound_unref(s);        /* free the reader */    return (x1 + exact_cnt * (x2 - x1)) * s->scale;}/* snd_sref_inverse -- find time point corresponding to some value *//**/double snd_sref_inverse(sound_type s, double val){    double exact_cnt;      /* how many fractional samples to scan */    int i;    sample_block_type sampblock;    long blocklen;    sample_type x1, x2;    /* interpolate between these samples */    if (val < 0) {        xlcerror("return 0", "negative value", cvflonum(val));        return 0.0;    }    s = sound_copy(s);     /* don't modify s, create new reader */    x1 = 0.0F;    /* now flush cnt samples */    while (true) {        sampblock = sound_get_next(s, &blocklen);        x2 = sampblock->samples[blocklen - 1];        if (x2 >= val) break;        x1 = x2;        if (sampblock == zero_block) {            xlcerror("return 0", "too large, no inverse", cvflonum(val));            sound_unref(s);            return 0.0;        }    }    /* x1 = last sample of previous block,       sampblock contains a value larger than val       blocklen is the length of sampblock */    /* search for first element exceeding val - could     * use binary search, but maximum block size places     * an upper bound on how bad this can get and we     * search for the right block linearly anyway.     */    for (i = 0; i < blocklen && sampblock->samples[i] <= val; i++) ;    /* now i is index of element exceeding val */    if (i > 1) x1 = sampblock->samples[i - 1];    x2 = sampblock->samples[i];    /* now interpolate to get fractional part */    if (x2 == x1) exact_cnt = 0;    else exact_cnt = (val - x1) / (x2 - x1);    /* and add the sample count of x1 */    exact_cnt += (s->current - blocklen) + (i - 1);    /* negative counts are possible because the first x1 is at     * sample -1, so force the location to be at least 0     */    if (exact_cnt < 0) exact_cnt = 0;    /* compute time = t0 + count / samplerate; */    exact_cnt = s->t0 + exact_cnt / s->sr;    sound_unref(s);        /* free the reader */    return exact_cnt;}time_type snd_stop_time(sound_type s){    if (s->stop == MAX_STOP) return MAX_STOP_TIME;    else return s->t0 + (s->stop + 0.5) / s->sr;}/* snd_xform -- return a sound with transformations applied *//* * The "logical" sound starts at snd->time and runs until some * as yet unknown termination time.  (There is also a possibly * as yet unknown logical stop time that is irrelevant here.) * The sound is clipped (zero) until snd->t0 and after snd->stop, * the latter being a sample count, not a time_type. * So, the "physical" sound starts at snd->t0 and runs for up to * snd->stop samples (or less if the sound terminates beforehand). * * The snd_xform procedure operates at the "logical" level, shifting * the sound from its snd->time to time.  The sound is stretched as * a result of setting the sample rate to sr.  It is then (further)  * clipped between start_time and stop_time.  If initial samples * are clipped, the sound is shifted again so that it still starts * at time.  The sound is then scaled by scale. * * To support clipping of initial samples, the "physical" start time * t0 is set to when the first unclipped sample will be returned, but * the number of samples to clip is saved as a negative count.  The * fetch routine SND_flush is installed to flush the clipped samples * at the time of the first fetch.  SND_get_first is then installed * for future fetches. * * An empty (zero) sound will be returned if all samples are clipped. * */sound_type snd_xform(sound_type snd,                      rate_type sr,                      time_type time,                      time_type start_time,                      time_type stop_time,                      promoted_sample_type scale){    long start_cnt, stop_cnt; /* clipping samples (sample 0 at new t0) */    /* start_cnt should reflect max of where the sound starts (t0)     * and the new start_time.     */    if (start_time == MIN_START_TIME) {        start_cnt = 0;    } else {        double new_start_cnt = ((start_time - time) * sr) + 0.5;        start_cnt = ((new_start_cnt > 0) ? (long) new_start_cnt : 0);    }    /* if (start_cnt < -(snd->current)) start_cnt = -(snd->current); */    /* stop_cnt should reflect min of the new stop_time and the previous     * snd->stop.     */    if (stop_time == MAX_STOP_TIME) {        stop_cnt = MAX_STOP;    } else {        double new_stop_cnt = ((stop_time - time) * sr) + 0.5;        if (new_stop_cnt < MAX_STOP) {            stop_cnt = (long) new_stop_cnt;        } else {            errputstr("Warning: stop count overflow in snd_xform\n");            stop_cnt = MAX_STOP;        }    }    if (stop_cnt > snd->stop) {        stop_cnt = snd->stop;    }    if (stop_cnt < 0 || start_cnt >= stop_cnt) {        snd = sound_create(NULL, time, sr, 1.0);        /* sound_create goes ahead and allocates a snd_list node, so         * we need to free it.           * Calling snd_list_unref here seems like the right thing, but          * it assumes too much structure is in place.  ffree_snd_list         * is simpler and more direct:         */        ffree_snd_list(snd->list, "snd_xform");        snd->list = zero_snd_list;        nyquist_printf("snd_xform: (stop_time < t0 or start >= stop) "                       "-> zero sound = %p\n", snd);            } else {        snd = sound_copy(snd);        snd->t0 = time;        if (start_cnt) {            snd->current -= start_cnt; /* indicate flush with negative num. */            /* the following code assumes that SND_get_first is the              routine to be called to get the first samples from this               sound.  We're going to replace it with SND_flush.  First,              make sure that the assumption is correct:            */            if ((snd->get_next != SND_get_first) &&                (snd->get_next != SND_flush)) {                errputstr("snd_xform: SND_get_first expected\n");                EXIT(1);            }            /* this will flush -current samples and revert to SND_get_first */            snd->get_next = SND_flush;            stop_cnt -= start_cnt;        }        snd->stop = stop_cnt;        snd->sr = sr;        snd->scale *= (float) scale;    }    return snd;}/* SND_flush -- the get_next function for flushing clipped samples *//* * this only gets called once: it flushes -current samples (a  * non-real-time operation) and installs SND_get_next to return

⌨️ 快捷键说明

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