summaryrefslogtreecommitdiff
path: root/nyqsrc/sndmax.c
diff options
context:
space:
mode:
Diffstat (limited to 'nyqsrc/sndmax.c')
-rw-r--r--nyqsrc/sndmax.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/nyqsrc/sndmax.c b/nyqsrc/sndmax.c
new file mode 100644
index 0000000..a91297b
--- /dev/null
+++ b/nyqsrc/sndmax.c
@@ -0,0 +1,73 @@
+/* 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 <stdio.h>
+/* #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);
+}
+
+