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

📄 samples.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
字号:
/* samples.c -- various functions for the Nyquist sound data type *//* CHANGE LOG * -------------------------------------------------------------------- * 28Apr03  dm  min->MIN, max->MAX */#include <stdio.h>#ifndef mips#include "stdlib.h"#endif#include "xlisp.h"#include "sound.h"#include "falloc.h"#include "samples.h"LVAL s_next = NULL;LVAL s_send;void samples_symbols(){    s_next = xlenter(":NEXT");    s_send = xlenter("SEND");}/* snd_from_array -- convert lisp array to sound type *//**/sound_type snd_from_array(double t0, double sr, LVAL array){    sound_type result;    snd_list_type snd_list;    long total = 0;    if (!vectorp(array)) xlerror("array expected", array);    result = sound_create(NULL, t0, sr, 1.0);    snd_list = result->list;    while (total < getsize(array)) {        long togo = MIN(getsize(array) - total, max_sample_block_len);        sample_block_type block;        int i;        falloc_sample_block(block, "snd_from_array");        snd_list->block = block;        for (i = 0; i < togo; i++) {            LVAL elem = getelement(array, total + i);            sample_type *ptr = block->samples + i;            if (fixp(elem)) *ptr = (sample_type) getfixnum(elem);            else if (floatp(elem)) *ptr = (sample_type) getflonum(elem);            else xlerror("expecting array elem to be number", elem);        }        total += togo;        snd_list->block_len = (short) togo;        snd_list->u.next = snd_list_create(NULL);        snd_list = snd_list->u.next;    }    snd_list->block_len = max_sample_block_len;    snd_list->block = zero_block;    snd_list->logically_stopped = true;    snd_list->u.next = zero_snd_list;    return result;}/* snd_length -- count how many samples are in a sound *//**/long snd_length(sound_type s, long len){    long total = 0;    long blocklen;    s = sound_copy(s);    if (len > s->stop) len = s->stop;    while (total < len) {        sample_block_type sampblock = sound_get_next(s, &blocklen);        if (sampblock == zero_block) break;        total += blocklen;    }    if (total > len) total = len;    sound_unref(s);    return total;}/* snd_maxsamp -- compute the maximum value of samples in s *//**/double snd_maxsamp(sound_type s){    sample_type result = 0.0F;    long blocklen;    s = sound_copy(s);    while (true) {        sample_block_type sampblock = sound_get_next(s, &blocklen);        long i;        sample_block_values_type sbufp = sampblock->samples;        if (sampblock == zero_block || blocklen == 0) {            break;        }        for (i = 0; i < blocklen; i++) {            register sample_type samp = *sbufp++;            if (result < samp) result = samp;            else if (result < -samp) result = -samp;        }    }    return (double) (s->scale * result);}/* snd_samples -- convert sound (prefix) to lisp array *//**/LVAL snd_samples(sound_type s, long len){    LVAL v;    long vx = 0;    long blocklen;    register double scale_factor = s->scale;    len = snd_length(s, len);    s = sound_copy(s);    xlsave1(v);    v = newvector(len);    while (len > 0) {        sample_block_type sampblock = sound_get_next(s, &blocklen);        long togo = MIN(blocklen, len);        long i;        sample_block_values_type sbufp = sampblock->samples;        for (i = 0; i < togo; i++) {            setelement(v, vx++, cvflonum(*sbufp++ * scale_factor));        }        len -= togo;    }    sound_unref(s);    /* restore the stack */    xlpop();    return v;}/* NOTE: this code does not properly handle start times that do not * correspond to the time of the first actual sample *//* NOTE: we need some addtional state to keep track of where we are. *  We'll use the extra field of sound_type; first long is length, *  so second field will be the count of how many samples we've read. */#define CNT extra[1]#define INDEX extra[2]#define FIELDS 3#define SAMPLES list->block->samplesLVAL snd_fetch(sound_type s){    if (!s->extra) { /* this is the first call, so fix up s */        s->extra = (long *) malloc(sizeof(long) * FIELDS);        s->extra[0] = sizeof(long) * FIELDS;        s->CNT = s->INDEX = 0;    } else if (s->extra[0] != sizeof(long) * FIELDS) {        xlfail("sound in use by another iterator");    }    if (s->CNT == s->INDEX) {        sound_get_next(s, &(s->CNT));        s->INDEX = 0;    }    if (s->SAMPLES == zero_block->samples) {        return NULL;    }	    /* logical stop time is ignored by this code -- to fix this,     * you would need a way to return the logical stop time to      * the caller.     */    return cvflonum(s->SAMPLES[s->INDEX++] * s->scale);} /* snd_fetch *//* snd_fetch_array -- fetch a lisp array of samples *//* * storage layout: the extra field points to extra state that we'll use * extra[0] -> length of extra storage * extra[1] -> CNT (number of samples in current block) * extra[2] -> INDEX (current sample index in current block) * extra[3] -> FILLCNT (how many samples in buffer) * extra[4] -> TERMCNT (how many samples until termination) * extra[4 .. 4+len-1] -> samples (stored as floats) *  * Termination details: *   Return NIL when the sound terminates. *   Termination is defined as the point where all original * signal samples have been shifted out of the samples buffer * so that all that's left are zeros from beyond the termination * point. *   Implementation: when termination is discovered, set TERMCNT * to the number of samples to be shifted out. TERMCNT is initially * -1 as a flag that we haven't seen the termination yet.  * Each time samples are shifted, decrement TERMCNT by the shift amount. * When TERMCNT goes to zero, return NULL. *//* these macros define entries in extra, more macros are defined above */#define FILLCNT extra[3]#define TERMCNT extra[4]#define OFFSET 5LVAL snd_fetch_array(sound_type s, long len, long step){    long i, maxlen, skip, fillptr;    float *samples;    LVAL result;        if (len < 1) xlfail("len < 1");    if (!s->extra) { /* this is the first call, so fix up s */        s->extra = (long *) malloc(sizeof(long) * (len + OFFSET));        s->extra[0] = sizeof(long) * (len + OFFSET);        s->CNT = s->INDEX = s->FILLCNT = 0;        s->TERMCNT = -1;        maxlen = len;    } else {        maxlen = (s->extra[0] / sizeof(long)) - OFFSET;        if (maxlen < 1) xlfail("sound in use by another iterator");        if (maxlen < len) xlfail("len grew");    }    samples = (float *) &(s->extra[OFFSET]);        /* step 1: refill buffer with samples */    fillptr = s->FILLCNT;    while (fillptr < maxlen) {        if (s->INDEX == s->CNT) {            sound_get_next(s, &(s->CNT));            if (s->SAMPLES == zero_block->samples) {                if (s->TERMCNT < 0) s->TERMCNT = fillptr;            }	            s->INDEX = 0;        }        samples[fillptr++] = s->SAMPLES[s->INDEX++] * s->scale;    }    s->FILLCNT = fillptr;    /* it is important to test here AFTER filling the buffer, because     * if fillptr WAS 0 when we hit the zero_block, then filling the      * buffer will set TERMCNT to 0.     */    if (s->TERMCNT == 0) return NULL;        /* logical stop time is ignored by this code -- to fix this,     * you would need a way to return the logical stop time to      * the caller.     */    /* step 2: construct an array and return it */    xlsave1(result);    result = newvector(len);    for (i = 0; i < len; i++) {        setelement(result, i, cvflonum(samples[i]));    }    /* step 3: shift samples by step */    if (step < 0) xlfail("step < 0");    s->FILLCNT -= step;    if (s->FILLCNT < 0) s->FILLCNT = 0;    for (i = 0; i < s->FILLCNT; i++) {        samples[i] = samples[i + step];    }        if (s->TERMCNT >= 0) {        s->TERMCNT -= step;        if (s->TERMCNT < 0) s->TERMCNT = 0;    }    /* step 4: advance in sound to next sample we need     *   (only does work if step > size of buffer)     */    skip = step - maxlen;    while (skip > 0) {        long remaining = s->CNT - s->INDEX;        if (remaining >= skip) {            s->INDEX += skip;            skip = 0;        } else {            skip -= remaining;            sound_get_next(s, &(s->CNT));            s->INDEX = 0;        }    }        /* restore the stack */    xlpop();    return result;} /* snd_fetch_array */

⌨️ 快捷键说明

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