/* sndmax.c -- computes the maximum amplitude in a sound */ /* CHANGE LOG * -------------------------------------------------------------------- * 28Apr03 dm min->MIN; fix compiler warning * 31Jan07 rbd handle negative scale factors */ #ifdef UNIX #include "sys/types.h" #endif #include /* #include "snd.h" */ #include "xlisp.h" #include "sound.h" #include "falloc.h" #include "sndmax.h" #include "extern.h" 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 fabs(maximum * s->scale); }