Exemplo n.º 1
0
LVAL xlc_snd_copy(void)
{
    sound_type arg1 = getsound(xlgasound());
    sound_type result;

    xllastarg();
    result = sound_copy(arg1);
    return cvsound(result);
}
Exemplo n.º 2
0
void audio_callback(s16 *stream, int length)
{
  u32 sample_length = length / 2;
  u32 _length;
  s16 *stream_base = (s16 *)stream;
  s32 *source;
  s32 current_sample;

  u32 i;

  if(audio_paused)
    return;

  if(config.enable_sound)
  {
    if((audio.buffer_base + sample_length) >= AUDIO_BUFFER_SIZE)
    {
      u32 partial_length = (AUDIO_BUFFER_SIZE - audio.buffer_base) * 2;
      sound_copy(audio.buffer_base, partial_length, normal);
      sound_copy(0, length - partial_length, normal);
      audio.buffer_base = (length - partial_length) / 2;
    }
    else
    {
      sound_copy(audio.buffer_base, length, normal);
      audio.buffer_base += sample_length;
    }
  }
  else
  {
    if((audio.buffer_base + sample_length) >= AUDIO_BUFFER_SIZE)
    {
      u32 partial_length = (AUDIO_BUFFER_SIZE - audio.buffer_base) * 2;
      audio.buffer_base = (length - partial_length) / 2;
    }
    else
    {
      audio.buffer_base += sample_length;
    }
    memset(stream, 0, length);
  }
}
Exemplo n.º 3
0
sound_type snd_make_pvshell(char *name, rate_type sr, time_type t0,
                            h_fn_type h, pvs_free_fn_type free_fn,
                            sound_type f, sound_type g,
                            void *state, long n)
{
    register pvshell_susp_type susp;

    falloc_generic(susp, pvshell_susp_node, "snd_make_pvshell");
    susp->susp.fetch = pvshell_fetch;

    /* initialize susp state */
    susp->susp.free = pvshell_free;
    susp->susp.sr = sr;
    susp->susp.t0 = t0;
    susp->susp.mark = pvshell_mark;
    susp->susp.print_tree = pvshell_print_tree;
    susp->susp.name = name;
    susp->logically_stopped = false;
    susp->susp.log_stop_cnt = UNKNOWN;
    susp->susp.current = 0;

    /* copy the sound so that we have a private "reader" object */
    susp->pvshell.f = (f ? sound_copy(f) : f);
    susp->pvshell.f_cnt = 0;

    susp->pvshell.g = (g ? sound_copy(g) : g);
    susp->pvshell.g_cnt = 0;

    susp->pvshell.h = h;
    susp->pvshell.free_fn = free_fn;
    susp->pvshell.flags = 0; /* terminated and logically stopped flags -- these
                                are for the client of pvshell to use */

    assert(n <= PVSHELL_STATE_MAX);
    memcpy(susp->pvshell.state, state, n);

    susp->started = false;
    return sound_create((snd_susp_type)susp, t0, sr, 1.0);
}
Exemplo n.º 4
0
double sound_max(LVAL snd_expr, long n)
{
    LVAL s_as_lval;
    sound_type s = NULL;
    long blocklen;
    sample_block_values_type sbufp;
    register double maximum = 0;

    s_as_lval = xleval(snd_expr);
    /* BE CAREFUL - DO NOT ALLOW GC TO RUN WHILE LVAL IS UNPROTECTED */
    if (exttypep(s_as_lval, a_sound)) {
        /* if snd_expr was simply a symbol, then s now points to
        a shared sound_node.  If we read samples from it, then
        the sound bound to the symbol will be destroyed, so
        copy it first.  If snd_expr was a real expression that
        computed a new value, then the next garbage collection
        will reclaim the sound_node.  We need to make the new
        sound reachable by the garbage collector to that any
        lisp data reachable from the sound do not get collected.
        To make the sound reachable, we need to allocate a node,
        and the GC might run, so we need to protect the OLD s
        but then make it unreachable.
        We will let the GC collect the sound in the end.
        */
        xlprot1(s_as_lval);
        s = sound_copy(getsound(s_as_lval));
        s_as_lval = cvsound(s);	/* destroys only ref. to original */
        /* printf("sound_max: copy is %x, lval %x\n", s, s_as_lval); */
        while (n > 0) {
            long togo, j;
            sample_block_type sampblock = 
              sound_get_next(s, &blocklen);
            if (sampblock == zero_block || blocklen == 0) {
                break;
            }
            togo = MIN(blocklen, n);
            sbufp = sampblock->samples;
            for (j = 0; j < togo; j++) {
                register double samp = *sbufp++;
                if (samp > maximum) maximum = samp;
                else if (-samp > maximum) maximum = -samp;
            }
            n -= togo;
        }
        xlpop();
    } else {
        xlerror("sound_max: expression did not return a sound",
                 s_as_lval);
    }
    return maximum * s->scale;
}
Exemplo n.º 5
0
sound_type snd_sax_all(double freq, sound_type breath_env, sound_type freq_env, double vibrato_freq, double vibrato_gain, sound_type reed_stiffness, sound_type noise_env, sound_type blow_pos, sound_type reed_table_offset, rate_type sr)
{
    sound_type breath_env_copy = sound_copy(breath_env);
    sound_type freq_env_copy = sound_copy(freq_env);
    sound_type reed_stiffness_copy = sound_copy(reed_stiffness);
    sound_type noise_env_copy = sound_copy(noise_env);
    sound_type blow_pos_copy = sound_copy(blow_pos);
    sound_type reed_table_offset_copy = sound_copy(reed_table_offset);
    return snd_make_sax_all(freq, breath_env_copy, freq_env_copy, vibrato_freq, vibrato_gain, reed_stiffness_copy, noise_env_copy, blow_pos_copy, reed_table_offset_copy, sr);
}
Exemplo n.º 6
0
void n_samples_from_sound(sound_type s, long n, float *table)
{
    long blocklen;
    sample_type scale_factor = s->scale;
    s = sound_copy(s);
    while (n > 0) {
        sample_block_type sampblock = sound_get_next(s, &blocklen);
        long togo = min(blocklen, n);
        long i;
        sample_block_values_type sbufp = sampblock->samples;
        for (i = 0; i < togo; i++) {
            *table++ = (float) (*sbufp++ * scale_factor);
        }
        n -= togo;
    }
    sound_unref(s);
}
Exemplo n.º 7
0
sound_type snd_convolve(sound_type x_snd, sound_type h_snd)
{
    sound_type x_snd_copy = sound_copy(x_snd);
    return snd_make_convolve(x_snd_copy, h_snd);
}
Exemplo n.º 8
0
sound_type snd_alpassvc(sound_type input, sound_type delaysnd, double feedback, double maxdelay)
{
    sound_type input_copy = sound_copy(input);
    sound_type delaysnd_copy = sound_copy(delaysnd);
    return snd_make_alpassvc(input_copy, delaysnd_copy, feedback, maxdelay);
}
Exemplo n.º 9
0
void trigger_fetch(trigger_susp_type susp, snd_list_type snd_list)
{
    int cnt = 0; /* how many samples computed */
    int togo;
    int n;
    sample_block_type out;
    register sample_block_values_type out_ptr;
    register sample_block_values_type out_ptr_reg;
    register sample_block_values_type input_ptr_reg;
    falloc_sample_block(out, "trigger_fetch");
    out_ptr = out->samples;
    snd_list->block = out;

    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;

        /* don't run past the input sample block: */
        susp_check_term_samples(s1, s1_ptr, s1_cnt);
        togo = min(togo, susp->s1_cnt);

        /* don't run past terminate time */
        if (susp->terminate_cnt != UNKNOWN &&
            susp->terminate_cnt <= susp->susp.current + cnt + togo) {
            togo = susp->terminate_cnt - (susp->susp.current + cnt);
            if (togo == 0) break;
        }

        n = togo;
        input_ptr_reg = susp->s1_ptr;
        out_ptr_reg = out_ptr;
        if (n) do { /* the inner sample computation loop */
            sample_type s = *input_ptr_reg++;
            if (susp->previous <= 0 && s > 0) {
                trigger_susp_type new_trigger;
                sound_type new_trigger_snd;
                LVAL result;
                long delay; /* sample delay to s2 */
                time_type now;

                susp->previous = s; /* don't retrigger */

                /**** close off block ****/
                togo = togo - n;
                susp->s1_ptr += togo;
                susp_took(s1_cnt, togo);
                cnt += togo;
                snd_list->block_len = cnt;
                susp->susp.current += cnt;
                now = susp->susp.t0 + susp->susp.current / susp->susp.sr;

                /**** eval closure and add result ****/
D               nyquist_printf("trigger_fetch: about to eval closure at %g, "
                               "susp->susp.t0 %g, susp.current %d:\n",
                               now, susp->susp.t0, (int)susp->susp.current);
                xlsave1(result);
                result = xleval(cons(susp->closure, consa(cvflonum(now))));
                if (exttypep(result, a_sound)) {
                    susp->s2 = sound_copy(getsound(result));
D                   nyquist_printf("trigger: copied result from closure is %p\n",
                                   susp->s2);
                } else xlerror("closure did not return a (monophonic) sound", 
                               result);
D               nyquist_printf("in trigger: after evaluation; "
                               "%p returned from evform\n",
                               susp->s2);
                result = NIL;

                /**** cloan this trigger to become s1 ****/
                falloc_generic(new_trigger, trigger_susp_node, 
                               "new_trigger");
                memcpy(new_trigger, susp, sizeof(trigger_susp_node));
                /* don't copy s2 -- it should only be referenced by add */
                new_trigger->s2 = NULL;
                new_trigger_snd = sound_create((snd_susp_type) new_trigger,
                                               now, susp->susp.sr, 1.0F);
                susp->s1 = new_trigger_snd;
                /* add will have to ask new_trigger for samples, new_trigger
                 * will continue reading samples from s1 (the original input)
                 */
                susp->s1_cnt = 0;
                susp->s1_ptr = NULL;

                /**** convert to add ****/
                susp->susp.mark = add_mark;
                /* logical stop will be recomputed by add: */
                susp->susp.log_stop_cnt = UNKNOWN; 
                susp->susp.print_tree = add_print_tree;

                /* assume sample rates are the same */
                if (susp->s1->sr != susp->s2->sr) 
                    xlfail("in trigger: sample rates must match");

                /* take care of scale factor, if any */
                if (susp->s2->scale != 1.0) {
                    // stdputstr("normalizing next sound in a seq\n");
                    susp->s2 = snd_make_normalize(susp->s2);
                }

                /* figure out which add fetch routine to use */
                delay = ROUND((susp->s2->t0 - now) * susp->s1->sr);
                if (delay > 0) {    /* fill hole between s1 and s2 */
                    D stdputstr("using add_s1_nn_fetch\n");
                    susp->susp.fetch = add_s1_nn_fetch;
                    susp->susp.name = "trigger:add_s1_nn_fetch";
                } else {
                    susp->susp.fetch = add_s1_s2_nn_fetch;
                    susp->susp.name = "trigger:add_s1_s2_nn_fetch";
                }

D               stdputstr("in trigger: calling add's fetch\n");
                /* fetch will get called later ..
                   (*(susp->susp.fetch))(susp, snd_list); */
D               stdputstr("in trigger: returned from add's fetch\n");
                xlpop();

                susp->closure = NULL;   /* allow garbage collection now */
                /**** calculation tree modified, time to exit ****/
                /* but if cnt == 0, then we haven't computed any samples */
                /* call on new fetch routine to get some samples */
                if (cnt == 0) {
                    ffree_sample_block(out, "trigger-pre-adder"); // because adder will reallocate
                    (*susp->susp.fetch)(susp, snd_list);
                }
                return;
            } else {
                susp->previous = s;
                /* output zero until ready to add in closure */
                *out_ptr_reg++ = 0; 
            }
        } while (--n); /* inner loop */

        /* using input_ptr_reg is a bad idea on RS/6000: */
        susp->s1_ptr += togo;
        out_ptr += togo;
        susp_took(s1_cnt, togo);
        cnt += togo;
    } /* outer loop */

    if (togo == 0 && cnt == 0) {
        snd_list_terminate(snd_list);
    } else {
        snd_list->block_len = cnt;
        susp->susp.current += cnt;
    }
} /* trigger_fetch */
Exemplo n.º 10
0
sound_type snd_coterm(sound_type s1, sound_type s2)
{
    sound_type s1_copy = sound_copy(s1);
    sound_type s2_copy = sound_copy(s2);
    return snd_make_coterm(s1_copy, s2_copy);
}
Exemplo n.º 11
0
sound_type snd_flute_freq(double freq, sound_type breath_env, sound_type freq_env, rate_type sr)
{
    sound_type breath_env_copy = sound_copy(breath_env);
    sound_type freq_env_copy = sound_copy(freq_env);
    return snd_make_flute_freq(freq, breath_env_copy, freq_env_copy, sr);
}
Exemplo n.º 12
0
sound_type snd_offset(sound_type s1, double offset)
{
    sound_type s1_copy = sound_copy(s1);
    return snd_make_offset(s1_copy, offset);
}
Exemplo n.º 13
0
sound_type snd_abs(sound_type input)
{
    sound_type input_copy = sound_copy(input);
    return snd_make_abs(input_copy);
}
Exemplo n.º 14
0
sample_type sound_save_sound(LVAL s_as_lval, long n, snd_type snd,
                             char *buf, long *ntotal, snd_type player)
{
    long blocklen;
    long buflen;
    sound_type s;
    long debug_unit;    /* print messages at intervals of this many samples */
    long debug_count;   /* next point at which to print a message */
    sample_type max_sample = 0.0F;
    cvtfn_type cvtfn;
    *ntotal = 0;

    /* if snd_expr was simply a symbol, then s now points to
        a shared sound_node.  If we read samples from it, then
        the sound bound to the symbol will be destroyed, so
        copy it first.  If snd_expr was a real expression that
        computed a new value, then the next garbage collection
        will reclaim the sound_node.  We need to make the new
        sound reachable by the garbage collector to that any
        lisp data reachable from the sound do not get collected.
        To make the sound reachable, we need to allocate a node,
        and the GC might run, so we need to protect the OLD s
        but then make it unreachable.
        We will let the GC collect the sound in the end.
    */
    xlprot1(s_as_lval);
    s = sound_copy(getsound(s_as_lval));
    s_as_lval = cvsound(s);	/* destroys only ref. to original */

    /* for debugging */
/*    printing_this_sound = s;*/


    debug_unit = debug_count = (long) max(snd->format.srate, 10000.0);

    cvtfn = find_cvt_to_fn(snd, buf);

#ifdef MACINTOSH
    if (player) {
        gprintf(TRANS, "Playing audio: Click and hold mouse button to stop playback.\n");
    }
#endif

    while (n > 0) {
        long togo;
        float peak;
        sample_block_type sampblock = sound_get_next(s, &blocklen);
        oscheck();
#ifdef SNAPSHOTS
        stdputstr(".");
        if (sound_created_flag) {
            stdputstr("SNAPSHOT: ");
            sound_print_tree(printing_this_sound);
            sound_created_flag = false;
        }
        fflush(stdout);
#endif
        if (sampblock == zero_block || blocklen == 0) {
            break;
        }
        togo = min(blocklen, n);

        buflen = (*cvtfn)((void *) buf, (void *) sampblock->samples,
                          togo, s->scale, &peak);
        if (peak > max_sample) max_sample = peak;

#ifdef MACINTOSH
        if (Button()) {
            if (player) {
                snd_reset(player);
            }
            gprintf(TRANS, "\n\nStopping playback...\n\n\n");
            break;
        }
#endif

        if (snd->u.file.file != -1) snd_write(snd, (void *) buf, buflen);
        if (player) write_to_audio(player, (void *) buf, buflen);

        n -= togo;
        *ntotal += togo;
        if (*ntotal > debug_count) {
            gprintf(TRANS, " %d ", *ntotal);
            fflush(stdout);
            debug_count += debug_unit;
        }
    }
    gprintf(TRANS, "\ntotal samples: %d\n", *ntotal);
    xlpop();
    return max_sample;
}
Exemplo n.º 15
0
sound_type snd_follow(sound_type sndin, double floor, double risetime, double falltime, long lookahead)
{
    sound_type sndin_copy = sound_copy(sndin);
    return snd_make_follow(sndin_copy, floor, risetime, falltime, lookahead);
}
Exemplo n.º 16
0
sound_type snd_log(sound_type input)
{
    sound_type input_copy = sound_copy(input);
    return snd_make_log(input_copy);
}
Exemplo n.º 17
0
sound_type snd_reson(sound_type s, double hz, double bw, int normalization)
{
    sound_type s_copy = sound_copy(s);
    return snd_make_reson(s_copy, hz, bw, normalization);
}
Exemplo n.º 18
0
sound_type snd_slope(sound_type input)
{
    sound_type input_copy = sound_copy(input);
    return snd_make_slope(input_copy);
}
Exemplo n.º 19
0
sample_type sound_save_array(LVAL sa, long n, snd_type snd, 
                             char *buf, long *ntotal, snd_type player)
{
    long i, chans;
    long buflen;
    sound_state_type state;
    double start_time = HUGE_VAL;
    float *float_bufp;
    LVAL sa_copy;
    long debug_unit;    /* print messages at intervals of this many samples */
    long debug_count;   /* next point at which to print a message */
    sample_type max_sample = 0.0F;
    cvtfn_type cvtfn;

    *ntotal = 0;

    /* THE ALGORITHM: first merge floating point samples from N channels
     * into consecutive multi-channel frames in buf.  Then, treat buf
     * as just one channel and use one of the cvt_to_* functions to
     * convert the data IN PLACE in the buffer (this is ok because the
     * converted data will never take more space than the original 32-bit
     * floats, so the converted data will not overwrite any floats before
     * the floats are converted
     */

    /* if snd_expr was simply a symbol, then sa now points to
        a shared sound_node.  If we read samples from it, then
        the sounds bound to the symbol will be destroyed, so
        copy it first.  If snd_expr was a real expression that
        computed a new value, then the next garbage collection
        will reclaim the sound array.  See also sound_save_sound()
    */
    chans = getsize(sa);
    if (chans > MAX_SND_CHANNELS) {
        xlerror("sound_save: too many channels", sa);
        free(buf);
        snd_close(snd);
    }
    xlprot1(sa);
    sa_copy = newvector(chans);
    xlprot1(sa_copy);

    /* Why do we copy the array into an xlisp array instead of just
     * the state[i] array? Because some of these sounds may reference
     * the lisp heap. We must put the sounds in an xlisp array so that
     * the gc will find and mark them. xlprot1(sa_copy) makes the array
     * visible to gc.
     */
    for (i = 0; i < chans; i++) {
        sound_type s = getsound(getelement(sa, i));
        setelement(sa_copy, i, cvsound(sound_copy(s)));
    }
    sa = sa_copy;	/* destroy original reference to allow GC */

    state = (sound_state_type) malloc(sizeof(sound_state_node) * chans);
    for (i = 0; i < chans; i++) {
        state[i].sound = getsound(getelement(sa, i));
        state[i].scale = state[i].sound->scale;
D       nyquist_printf("save scale factor %d = %g\n", (int)i, state[i].scale);
        state[i].terminated = false;
        state[i].cnt = 0;   /* force a fetch */
        start_time = min(start_time, state[i].sound->t0);
    }

    for (i = 0; i < chans; i++) {
        if (state[i].sound->t0 > start_time)
            sound_prepend_zeros(state[i].sound, start_time);
    }

    /* for debugging */
/*    printing_this_sound = s;*/

    cvtfn = find_cvt_to_fn(snd, buf);

#ifdef MACINTOSH
    if (player) {
        gprintf(TRANS, "Playing audio: Click and hold mouse button to stop playback.\n");
    }
#endif

    debug_unit = debug_count = (long) max(snd->format.srate, 10000.0);

    while (n > 0) {
        /* keep the following information for each sound:
            has it terminated?
            pointer to samples
            number of samples remaining in block
           scan to find the minimum remaining samples and
           output that many in an inner loop.  Stop outer
           loop if all sounds have terminated
         */
        int terminated = true;
        int togo = n;
        int j;
        float peak;

        oscheck();

        for (i = 0; i < chans; i++) {
            if (state[i].cnt == 0) {
                if (sndwrite_trace) {
                    nyquist_printf("CALLING SOUND_GET_NEXT "
                                   "ON CHANNEL %d (%p)\n",
                                   (int)i, state[i].sound);
                    sound_print_tree(state[i].sound);
                }
                state[i].ptr = sound_get_next(state[i].sound,
                                   &(state[i].cnt))->samples;
                if (sndwrite_trace) {
                    nyquist_printf("RETURNED FROM CALL TO SOUND_GET_NEXT "
                                   "ON CHANNEL %d\n", (int)i);
                }
                if (state[i].ptr == zero_block->samples) {
                    state[i].terminated = true;
                }
            }
            if (!state[i].terminated) terminated = false;
            togo = min(togo, state[i].cnt);
        }

        if (terminated) break;

        float_bufp = (float *) buf;
        for (j = 0; j < togo; j++) {
            for (i = 0; i < chans; i++) {
                double s = *(state[i].ptr++) * state[i].scale; 
                *float_bufp++ = (float) s;
            }
        }
        // we're treating sound as mono for the conversion, so multiply
        // togo by chans to get proper number of samples, and divide by
        // chans to convert back to frame count required by snd_write
        buflen = (*cvtfn)((void *) buf, (void *) buf, togo * chans, 1.0F, 
                          &peak) / chans;
        if (peak > max_sample) max_sample = peak;
#ifdef MACINTOSH
        if (Button()) {
            if (player) {
                snd_reset(player);
            }
            gprintf(TRANS, "\n\nStopping playback...\n\n\n");
            break;
        }
#endif

        if (snd->u.file.file != -1) snd_write(snd, (void *) buf, buflen);
        if (player) write_to_audio(player, (void *) buf, buflen);

        n -= togo;
        for (i = 0; i < chans; i++) {
            state[i].cnt -= togo;
        }
        *ntotal += togo;
        if (*ntotal > debug_count) {
            gprintf(TRANS, " %d ", *ntotal);
            fflush(stdout);
            debug_count += debug_unit;
        }
    }
    gprintf(TRANS, "total samples: %d x %d channels\n",
           *ntotal, chans);

    /* references to sounds are shared by sa_copy and state[].
     * here, we dispose of state[], allowing GC to do the
     * sound_unref call that frees the sounds. (Freeing them now
     * would be a bug.)
     */
    free(state);
    xlpop();
    return max_sample;
}
Exemplo n.º 20
0
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);
}
Exemplo n.º 21
0
sound_type snd_normalize(sound_type s1)
{
    sound_type s1_copy = sound_copy(s1);
    return snd_make_normalize(s1_copy);
}
Exemplo n.º 22
0
sample_type sound_save_sound(LVAL s_as_lval, long n, SF_INFO *sf_info, 
        SNDFILE *sndfile, float *buf, long *ntotal, PaStream *audio_stream)
{
    long blocklen;
    sound_type s;
    int i;
    sample_type *samps;
    long debug_unit;    /* print messages at intervals of this many samples */
    long debug_count;   /* next point at which to print a message */
    sample_type max_sample = 0.0F;
    sample_type threshold = 0.0F;
    /* jlh    cvtfn_type cvtfn; */
    *ntotal = 0;
    /* if snd_expr was simply a symbol, then s now points to
        a shared sound_node.  If we read samples from it, then
        the sound bound to the symbol will be destroyed, so
        copy it first.  If snd_expr was a real expression that
        computed a new value, then the next garbage collection
        will reclaim the sound_node.  We need to make the new
        sound reachable by the garbage collector to that any
        lisp data reachable from the sound do not get collected.
        To make the sound reachable, we need to allocate a node,
        and the GC might run, so we need to protect the OLD s
        but then make it unreachable.
        We will let the GC collect the sound in the end.
    */
    xlprot1(s_as_lval);
    s = sound_copy(getsound(s_as_lval));
    s_as_lval = cvsound(s);	/* destroys only ref. to original */

    /* for debugging */
/*    printing_this_sound = s;*/


    debug_unit = debug_count = (long) max(sf_info->samplerate, 10000.0);

    sound_frames = 0;
    sound_srate = sf_info->samplerate;

    while (n > 0) {
        long togo;
        sample_block_type sampblock = sound_get_next(s, &blocklen);
        oscheck();
#ifdef SNAPSHOTS
        stdputstr(".");
        if (sound_created_flag) {
            stdputstr("SNAPSHOT: ");
            sound_print_tree(printing_this_sound);
            sound_created_flag = false;
        }
        fflush(stdout);
#endif
        if (sampblock == zero_block || blocklen == 0) {
            break;
        }
        togo = min(blocklen, n);
        if (s->scale != 1) { /* copy/scale samples into buf */
            for (i = 0; i < togo; i++) {
                buf[i] = s->scale * sampblock->samples[i];
            }
            samps = buf;
        } else {
            samps = sampblock->samples;
        }
        if (is_pcm(sf_info)) {
            for (i = 0; i < togo; i++) {
                sample_type s = samps[i];
                COMPUTE_MAXIMUM_AND_WRAP(samps[i]);
            }
        } else {
            for (i = 0; i < togo; i++) {
                sample_type s = samps[i];
                COMPUTE_MAXIMUM();
            }
        }
        if (sndfile) {
            sf_writef_float(sndfile, samps, togo);
        }
        if (audio_stream) {
            Pa_WriteStream(audio_stream, samps, togo);
            sound_frames += togo;
        }

        n -= togo;
        *ntotal += togo;
        if (*ntotal > debug_count) {
            gprintf(TRANS, " %ld ", *ntotal);
            fflush(stdout);
            debug_count += debug_unit;
        }
    }
    gprintf(TRANS, "\ntotal samples: %ld\n", *ntotal);
    xlpop();
    return max_sample;
}
Exemplo n.º 23
0
sound_type snd_tonev(sound_type s1, sound_type hz)
{
    sound_type s1_copy = sound_copy(s1);
    sound_type hz_copy = sound_copy(hz);
    return snd_make_tonev(s1_copy, hz_copy);
}
Exemplo n.º 24
0
sound_type snd_clip(sound_type s, double level)
{
    sound_type s_copy = sound_copy(s);
    return snd_make_clip(s_copy, level);
}
Exemplo n.º 25
0
sample_type sound_save_array(LVAL sa, long n, SF_INFO *sf_info, 
        SNDFILE *sndfile, float *buf, long *ntotal, PaStream *audio_stream)
{
    long i, chans;
    float *float_bufp;
    sound_state_type state;
    double start_time = HUGE_VAL;
    LVAL sa_copy;
    long debug_unit;    /* print messages at intervals of this many samples */
    long debug_count;   /* next point at which to print a message */
    sample_type max_sample = 0.0F;
    sample_type threshold = 0.0F;
    /*    cvtfn_type cvtfn; jlh */

    *ntotal = 0;

    /* THE ALGORITHM: first merge floating point samples from N channels
     * into consecutive multi-channel frames in buf.  Then, treat buf
     * as just one channel and use one of the cvt_to_* functions to
     * convert the data IN PLACE in the buffer (this is ok because the
     * converted data will never take more space than the original 32-bit
     * floats, so the converted data will not overwrite any floats before
     * the floats are converted
     */

    /* if snd_expr was simply a symbol, then sa now points to
        a shared sound_node.  If we read samples from it, then
        the sounds bound to the symbol will be destroyed, so
        copy it first.  If snd_expr was a real expression that
        computed a new value, then the next garbage collection
        will reclaim the sound array.  See also sound_save_sound()
    */

    chans = getsize(sa);
    if (chans > MAX_SND_CHANNELS) {
        xlerror("sound_save: too many channels", sa);
        free(buf);
        sf_close(sndfile);
    }
    xlprot1(sa);
    sa_copy = newvector(chans);
    xlprot1(sa_copy);

    /* Why do we copy the array into an xlisp array instead of just
     * the state[i] array? Because some of these sounds may reference
     * the lisp heap. We must put the sounds in an xlisp array so that
     * the gc will find and mark them. xlprot1(sa_copy) makes the array
     * visible to gc.
     */
    for (i = 0; i < chans; i++) {
        sound_type s = getsound(getelement(sa, i));
        setelement(sa_copy, i, cvsound(sound_copy(s)));
    }
    sa = sa_copy;	/* destroy original reference to allow GC */

    state = (sound_state_type) malloc(sizeof(sound_state_node) * chans);
    for (i = 0; i < chans; i++) {
        state[i].sound = getsound(getelement(sa, i));
        state[i].scale = state[i].sound->scale;
D       nyquist_printf("save scale factor %ld = %g\n", i, state[i].scale);
        state[i].terminated = false;
        state[i].cnt = 0;   /* force a fetch */
        start_time = min(start_time, state[i].sound->t0);
    }

    for (i = 0; i < chans; i++) {
        if (state[i].sound->t0 > start_time)
            sound_prepend_zeros(state[i].sound, start_time);
    }

    debug_unit = debug_count = (long) max(sf_info->samplerate, 10000.0);

    sound_frames = 0;
    sound_srate = sf_info->samplerate;
    while (n > 0) {
        /* keep the following information for each sound:
            has it terminated?
            pointer to samples
            number of samples remaining in block
           scan to find the minimum remaining samples and
           output that many in an inner loop.  Stop outer
           loop if all sounds have terminated
         */
        int terminated = true;
        int togo = n;
        int j;

        oscheck();

        for (i = 0; i < chans; i++) {
            if (state[i].cnt == 0) {
                if (sndwrite_trace) {
                    nyquist_printf("CALLING SOUND_GET_NEXT ON CHANNEL %ld (%lx)\n",
				   i, (unsigned long) state[i].sound); /* jlh 64 bit issue */
                    sound_print_tree(state[i].sound);
                }
                state[i].ptr = sound_get_next(state[i].sound,
                                   &(state[i].cnt))->samples;
                if (sndwrite_trace) {
                    nyquist_printf("RETURNED FROM CALL TO SOUND_GET_NEXT ON CHANNEL %ld\n", i);
                }
                if (state[i].ptr == zero_block->samples) {
                    state[i].terminated = true;
                }
            }
            if (!state[i].terminated) terminated = false;
            togo = min(togo, state[i].cnt);
        }

        if (terminated) break;

        float_bufp = (float *) buf;
        if (is_pcm(sf_info)) {
            for (j = 0; j < togo; j++) {
                for (i = 0; i < chans; i++) {
                    float s = (float) (*(state[i].ptr++) * (float) state[i].scale);
                    COMPUTE_MAXIMUM_AND_WRAP(s);
                    *float_bufp++ = s;
                }
            }
        } else {
            for (j = 0; j < togo; j++) {
                for (i = 0; i < chans; i++) {
                    float s = (float) (*(state[i].ptr++) * (float) state[i].scale);
                    COMPUTE_MAXIMUM();
                    *float_bufp++ = s;
                }
            }
        }
        /* Here we have interleaved floats. Before converting to the sound
           file format, call PortAudio to play them. */
        if (audio_stream) {
            PaError err = Pa_WriteStream(audio_stream, buf, togo);
            if (err) {
                printf("Pa_WriteStream error %d\n", err);
            }
            sound_frames += togo;
        }
        if (sndfile) sf_writef_float(sndfile, buf, togo);

        n -= togo;
        for (i = 0; i < chans; i++) {
            state[i].cnt -= togo;
        }
        *ntotal += togo;
        if (*ntotal > debug_count) {
            gprintf(TRANS, " %ld ", *ntotal);
            fflush(stdout);
            debug_count += debug_unit;
        }
    }
    gprintf(TRANS, "total samples: %ld x %ld channels\n",
           *ntotal, chans);

    /* references to sounds are shared by sa_copy and state[].
     * here, we dispose of state[], allowing GC to do the
     * sound_unref call that frees the sounds. (Freeing them now
     * would be a bug.)
     */
    free(state);
    xlpop();
    return max_sample;
}
Exemplo n.º 26
0
sound_type snd_stkchorus(sound_type s1, double baseDelay, double depth, double freq, double mix)
{
    sound_type s1_copy = sound_copy(s1);
    return snd_make_stkchorus(s1_copy, baseDelay, depth, freq, mix);
}
Exemplo n.º 27
0
sound_type snd_recip(sound_type s1)
{
    sound_type s1_copy = sound_copy(s1);
    return snd_make_recip(s1_copy);
}
Exemplo n.º 28
0
sound_type snd_quantize(sound_type s1, long steps)
{
    sound_type s1_copy = sound_copy(s1);
    return snd_make_quantize(s1_copy, steps);
}
Exemplo n.º 29
0
sound_type snd_clarinet(double freq, sound_type breath_env, rate_type sr)
{
    sound_type breath_env_copy = sound_copy(breath_env);
    return snd_make_clarinet(freq, breath_env_copy, sr);
}