summaryrefslogtreecommitdiff
path: root/nyqsrc/pvshell.h
diff options
context:
space:
mode:
Diffstat (limited to 'nyqsrc/pvshell.h')
-rw-r--r--nyqsrc/pvshell.h90
1 files changed, 90 insertions, 0 deletions
diff --git a/nyqsrc/pvshell.h b/nyqsrc/pvshell.h
new file mode 100644
index 0000000..6e925fb
--- /dev/null
+++ b/nyqsrc/pvshell.h
@@ -0,0 +1,90 @@
+/* pvshell.h -- a generic Nyquist primitive, esp. for phase vocoder */
+
+/* how many doubles to provide for miscellaneous state info */
+#define PVSHELL_STATE_MAX 8
+
+/* define some bits to return conditions */
+#define PVSHELL_FLAG_TERMINATE 4
+#define PVSHELL_FLAG_LOGICAL_STOP 8
+
+/* this function is called to compute samples. It should compute n
+ * samples (floats == sample_type) and store them at out[i].
+ * You can return less than n samples by writing the actual number
+ * of samples computed into *n. Normally, you return zero.
+ * To indicate that the time of the FIRST sample is the logical stop
+ * time, return PVSHELL_FLAG_LOGICAL_STOP. (If the logical stop time
+ * is not at the first sample, but instead at sample j, then just
+ * return j samples (from 0 to j-1), save the rest of the samples,
+ * and the next time, the first sample will correspond to the logical
+ * stop time, so you can return PVSHELL_FLAG_LOGICAL_STOP.
+ * To indicate that the sound has terminated, return
+ * PVSHELL_FLAG_TERMINATE. This should be the only time you return
+ * zero samples. (As with logical stop time, if you have samples to
+ * return before termination, then do it, and return
+ * PVSHELL_FLAG_TERMINATE the next time you are called, at which
+ * point you've returned all the samples, so you can set *n = 0.
+ */
+struct pvshell_struct;
+
+typedef long (*h_fn_type)(struct pvshell_struct *susp,
+ sample_block_values_type out, long *n);
+
+typedef struct pvshell_struct {
+ sound_type f;
+ long f_cnt;
+ sample_block_values_type f_ptr;
+
+ sound_type g;
+ long g_cnt;
+ sample_block_values_type g_ptr;
+
+ long flags; /* for terminated and logically stopped flags */
+
+ // state is extra storage for whatever you like
+ double state[PVSHELL_STATE_MAX];
+
+ // h is a function that computes sound from f, g, x, y, state
+ h_fn_type h;
+} pvshell_node, *pvshell_type;
+
+
+/* to get samples from f or g, use these macros. For each sample, call
+ * PVSHELL_TEST_X to get logical stop and terminate flags (but do not
+ * fetch a sample). Then, if you want, call PVSHELL_FETCH_X to get the
+ * next sample. You can call PVSHELL_TEST_X multiple times before
+ * calling PVSHELL_FETCH_X, e.g. you can return exit a loop when you
+ * see a logical stop flag and later call PVSHELL_TEST_X again. You
+ * CANNOT call PVSHELL_FETCH_X multiples times without an intervening
+ * call to PVSHELL_TEST_X. Finally, the logical stop flag is only
+ * returned once. Normally you should write something like:
+ * new_flags = PVSHELL_TEST_F(susp);
+ * susp->flags | = new_flags; // remember flags
+ * if (new_flags) break;
+ * in the sample loop so that you will break when you see logical_stop.
+ * Outside the loop, you can return (*n ? 0 : susp->flags) which will
+ * return 0 if you computed samples before the logical stop was detected.
+ * Then the next time you are called, you will return the logical_stop
+ * flag because you saved it in susp->flags, and the flag applies to the
+ * *beginning* of the sample block. This code handles terminate too.
+ */
+#define PVSHELL_TEST_F(susp) ((susp)->f_cnt == 0 ? pvshell_test_f(susp) : 0)
+#define PVSHELL_FETCH_F(susp) ((susp)->f_cnt--, (*(susp)->f_ptr++))
+
+#define PVSHELL_TEST_G(susp) ((susp)->g_cnt == 0 ? pvshell_test_g(susp) : 0)
+#define PVSHELL_FETCH_G(susp) ((susp)->g_cnt--, (*(susp)->g_ptr++))
+
+/* snd_make_pvshell -- create an instance of pvshell.
+ name -- string name of the operation, for debugging & printing
+ (name is not copied. It must be a permanent, immutable string.)
+ sr -- sample rate of output sound
+ t0 -- start time of output sound
+ h -- function that computes samples of output
+ f -- first input sound, e.g. sound to be time-stretched
+ g -- second input sound, e.g. sound to control varying stretch factor
+ state -- initial state information needed by h
+ n -- number of doubles in state (< PVSHELL_STATE_MAX)
+*/
+sound_type snd_make_pvshell(char *name, rate_type sr, time_type t0,
+ h_fn_type h, sound_type f, sound_type g,
+ double *state, long n);
+