mirror of
https://github.com/cookiengineer/audacity
synced 2025-04-30 15:49:41 +02:00
654 lines
22 KiB
C
654 lines
22 KiB
C
/* sound.h -- new nyquist sound data type */
|
|
|
|
/* CHANGE LOG
|
|
* --------------------------------------------------------------------
|
|
* 28Apr03 dm changes for portability: moved some defns out of here
|
|
*/
|
|
|
|
#include <math.h>
|
|
#include "stdefs.h"
|
|
|
|
/* used for *AUDIO-MARKERS* */
|
|
extern long sound_frames;
|
|
extern double sound_srate;
|
|
|
|
#if OSC
|
|
extern int nosc_enabled; /* enable polling for OSC messages */
|
|
#endif
|
|
|
|
#if USE_PRINTF
|
|
#define nyquist_printf printf
|
|
#endif
|
|
|
|
#define PERMS 0644 /* -rw-r--r-- */
|
|
|
|
/* default stop sample count (for clipping) */
|
|
#define MAX_STOP 0x7FFFFFFF
|
|
|
|
/* default stop time (for clipping) */
|
|
#define MAX_STOP_TIME 10E20
|
|
/* LISP-SRC: (SETF MAX-STOP-TIME 10E20) */
|
|
#define MIN_START_TIME -10E20
|
|
/* LISP-SRC: (SETF MIN-START-TIME -10E20) */
|
|
|
|
/* conversion from float to integer */
|
|
#define SCALE_FACTOR_TO_BYTE 127
|
|
#define SCALE_FACTOR_TO_SHORT 32767
|
|
#define SCALE_FACTOR_TO_24BIT 0x7FFFFF
|
|
#define SCALE_FACTOR_TO_LONG 2147483647
|
|
|
|
/* Note that the values assigned here are not arbitrary, but represent
|
|
a dominance relationship among the interpolation types.
|
|
*/
|
|
#define INTERP_n 0
|
|
#define INTERP_s 1
|
|
#define INTERP_i 2
|
|
#define INTERP_r 3
|
|
|
|
#define INTERP_nn 0
|
|
#define INTERP_ns 1
|
|
#define INTERP_ni 2
|
|
#define INTERP_nr 3
|
|
#define INTERP_sn 4
|
|
#define INTERP_ss 5
|
|
#define INTERP_si 6
|
|
#define INTERP_sr 7
|
|
#define INTERP_in 8
|
|
#define INTERP_is 9
|
|
#define INTERP_ii 10
|
|
#define INTERP_ir 11
|
|
#define INTERP_rn 12
|
|
#define INTERP_rs 13
|
|
#define INTERP_ri 14
|
|
#define INTERP_rr 15
|
|
|
|
#define INTERP_nnn 0
|
|
#define INTERP_nns 1
|
|
#define INTERP_nni 2
|
|
#define INTERP_nnr 3
|
|
#define INTERP_nsn 4
|
|
#define INTERP_nss 5
|
|
#define INTERP_nsi 6
|
|
#define INTERP_nsr 7
|
|
#define INTERP_nin 8
|
|
#define INTERP_nis 9
|
|
#define INTERP_nii 10
|
|
#define INTERP_nir 11
|
|
#define INTERP_nrn 12
|
|
#define INTERP_nrs 13
|
|
#define INTERP_nri 14
|
|
#define INTERP_nrr 15
|
|
#define INTERP_snn 16
|
|
#define INTERP_sns 17
|
|
#define INTERP_sni 18
|
|
#define INTERP_snr 19
|
|
#define INTERP_ssn 20
|
|
#define INTERP_sss 21
|
|
#define INTERP_ssi 22
|
|
#define INTERP_ssr 23
|
|
#define INTERP_sin 24
|
|
#define INTERP_sis 25
|
|
#define INTERP_sii 26
|
|
#define INTERP_sir 27
|
|
#define INTERP_srn 28
|
|
#define INTERP_srs 29
|
|
#define INTERP_sri 30
|
|
#define INTERP_srr 31
|
|
|
|
#define INTERP_inn 32
|
|
#define INTERP_ins 33
|
|
#define INTERP_ini 34
|
|
#define INTERP_inr 35
|
|
#define INTERP_isn 36
|
|
#define INTERP_iss 37
|
|
#define INTERP_isi 38
|
|
#define INTERP_isr 39
|
|
#define INTERP_iin 40
|
|
#define INTERP_iis 41
|
|
#define INTERP_iii 42
|
|
#define INTERP_iir 43
|
|
#define INTERP_irn 44
|
|
#define INTERP_irs 45
|
|
#define INTERP_iri 46
|
|
#define INTERP_irr 47
|
|
#define INTERP_rnn 48
|
|
#define INTERP_rns 49
|
|
#define INTERP_rni 50
|
|
#define INTERP_rnr 51
|
|
#define INTERP_rsn 52
|
|
#define INTERP_rss 53
|
|
#define INTERP_rsi 54
|
|
#define INTERP_rsr 55
|
|
#define INTERP_rin 56
|
|
#define INTERP_ris 57
|
|
#define INTERP_rii 58
|
|
#define INTERP_rir 59
|
|
#define INTERP_rrn 60
|
|
#define INTERP_rrs 61
|
|
#define INTERP_rri 62
|
|
#define INTERP_rrr 63
|
|
|
|
#define INTERP_nnnn 0
|
|
#define INTERP_nnns 1
|
|
#define INTERP_nnsn 4
|
|
#define INTERP_nnss 5
|
|
#define INTERP_nsnn 16
|
|
#define INTERP_nsns 17
|
|
#define INTERP_nssn 20
|
|
#define INTERP_nsss 21
|
|
#define INTERP_nrrr 63
|
|
#define INTERP_snnn 64
|
|
#define INTERP_snns 65
|
|
#define INTERP_snsn 68
|
|
#define INTERP_snss 69
|
|
#define INTERP_ssnn 80
|
|
#define INTERP_ssns 81
|
|
#define INTERP_sssn 84
|
|
#define INTERP_ssss 85
|
|
#define INTERP_niii 42
|
|
#define INTERP_siii 106
|
|
#define INTERP_srrr 127
|
|
#define INTERP_iiii 170
|
|
#define INTERP_rrrr 255
|
|
|
|
#define INTERP_nnnnnn 0
|
|
#define INTERP_nnnnns 1
|
|
#define INTERP_nnnnsn 4
|
|
#define INTERP_nnnnss 5
|
|
#define INTERP_nnnsnn 16
|
|
#define INTERP_nnnsns 17
|
|
#define INTERP_nnnssn 20
|
|
#define INTERP_nnnsss 21
|
|
#define INTERP_nnsnnn 64
|
|
#define INTERP_nnsnns 65
|
|
#define INTERP_nnsnsn 68
|
|
#define INTERP_nnsnss 69
|
|
#define INTERP_nnssnn 80
|
|
#define INTERP_nnssns 81
|
|
#define INTERP_nnsssn 84
|
|
#define INTERP_nnssss 85
|
|
#define INTERP_nsnnnn 256
|
|
#define INTERP_nsnnns 257
|
|
#define INTERP_nsnnsn 260
|
|
#define INTERP_nsnnss 261
|
|
#define INTERP_nsnsnn 272
|
|
#define INTERP_nsnsns 273
|
|
#define INTERP_nsnssn 276
|
|
#define INTERP_nsnsss 277
|
|
#define INTERP_nssnnn 320
|
|
#define INTERP_nssnns 321
|
|
#define INTERP_nssnsn 324
|
|
#define INTERP_nssnss 325
|
|
#define INTERP_nsssnn 336
|
|
#define INTERP_nsssns 337
|
|
#define INTERP_nssssn 340
|
|
#define INTERP_nsssss 341
|
|
#define INTERP_snnnnn 1024
|
|
#define INTERP_snnnns 1025
|
|
#define INTERP_snnnsn 1028
|
|
#define INTERP_snnnss 1029
|
|
#define INTERP_snnsnn 1040
|
|
#define INTERP_snnsns 1041
|
|
#define INTERP_snnssn 1044
|
|
#define INTERP_snnsss 1045
|
|
#define INTERP_snsnnn 1088
|
|
#define INTERP_snsnns 1089
|
|
#define INTERP_snsnsn 1092
|
|
#define INTERP_snsnss 1093
|
|
#define INTERP_snssnn 1104
|
|
#define INTERP_snssns 1105
|
|
#define INTERP_snsssn 1108
|
|
#define INTERP_snssss 1109
|
|
#define INTERP_ssnnnn 1280
|
|
#define INTERP_ssnnns 1281
|
|
#define INTERP_ssnnsn 1284
|
|
#define INTERP_ssnnss 1285
|
|
#define INTERP_ssnsnn 1296
|
|
#define INTERP_ssnsns 1297
|
|
#define INTERP_ssnssn 1300
|
|
#define INTERP_ssnsss 1301
|
|
#define INTERP_sssnnn 1344
|
|
#define INTERP_sssnns 1345
|
|
#define INTERP_sssnsn 1348
|
|
#define INTERP_sssnss 1349
|
|
#define INTERP_ssssnn 1360
|
|
#define INTERP_ssssns 1361
|
|
#define INTERP_sssssn 1364
|
|
#define INTERP_ssssss 1365
|
|
#define INTERP_iiiiii 2730
|
|
#define INTERP_rrrrrr 4095
|
|
|
|
#define INTERP_nnnnnnnn 0
|
|
#define INTERP_ssssssss 21845
|
|
|
|
|
|
#define INTERP_MASK 3
|
|
#define INTERP_SHIFT 2
|
|
|
|
LVAL snd_badsr(void);
|
|
long check_terminate_cnt(long tc);
|
|
|
|
typedef double time_type;
|
|
typedef double rate_type;
|
|
typedef float sample_type;
|
|
typedef double promoted_sample_type;
|
|
|
|
/* use radians or degrees for phase? */
|
|
#define ANGLEBASE 360.0
|
|
|
|
/* used by sndwrite.c for output buffers. This should be
|
|
* eliminated:
|
|
*/
|
|
#define MAX_SND_CHANNELS 24
|
|
|
|
#define max_table_len 1000001
|
|
/* Set to 4 for debugging block allocation stuff, 1012? for
|
|
production
|
|
*/
|
|
/* leave a few words short of 1024 in case we allocate powers of 2 */
|
|
#define max_sample_block_len 1020
|
|
/* #define max_sample_block_len 4 */
|
|
|
|
/* longest allowed sample is basically 2^31 but a bit lower to
|
|
allow for rounding */
|
|
#define MAX_SND_LEN (MAX_STOP - max_sample_block_len * 2)
|
|
|
|
|
|
/* Defines needed for xlisp */
|
|
#define getsound(x) ((sound_type) getinst(x))
|
|
#define xlgasound() (testarg(typearg(soundp)))
|
|
|
|
typedef short SFDataType, *SFDataPtr;
|
|
|
|
typedef sample_type sample_block_values[max_sample_block_len],
|
|
*sample_block_values_type;
|
|
|
|
typedef struct {
|
|
long refcnt; /* reference count */
|
|
sample_block_values samples;
|
|
} sample_block_node, *sample_block_type;
|
|
|
|
|
|
/* forward declaration for circular type dependencies */
|
|
typedef struct snd_list_struct *snd_list_type;
|
|
|
|
typedef struct snd_susp_struct {
|
|
void (*fetch)(struct snd_susp_struct *, snd_list_type snd_list);
|
|
void (*keep_fetch)(struct snd_susp_struct *, snd_list_type snd_list);
|
|
void (*free)(struct snd_susp_struct *);
|
|
void (*mark)(struct snd_susp_struct *); /* marks LVAL nodes for GC */
|
|
void (*print_tree)(struct snd_susp_struct *, int); /* debugging */
|
|
char *name; /* string name for debugging */
|
|
long toss_cnt; /* return this many zeros, then compute */
|
|
long current; /* current sample number */
|
|
double sr; /* sample rate */
|
|
time_type t0; /* starting time */
|
|
long log_stop_cnt; /* logical stop count */
|
|
/* other susp dependent stuff will be here... */
|
|
} snd_susp_node, *snd_susp_type;
|
|
|
|
|
|
typedef struct snd_list_struct {
|
|
sample_block_type block; /* pointer to block of samples */
|
|
union {
|
|
struct snd_list_struct *next;
|
|
snd_susp_type susp;
|
|
} u;
|
|
short refcnt;
|
|
short block_len;
|
|
boolean logically_stopped;
|
|
} snd_list_node; /* , *snd_list_type; -- defined above */
|
|
|
|
extern snd_list_type list_watch; //DBY
|
|
|
|
|
|
typedef struct table_struct {
|
|
long refcount; /* reference count */
|
|
double length; /* number of samples in table
|
|
(double allows fractional length)*/
|
|
sample_type samples[1]; /* arbitrary length array of sample */
|
|
} table_node, *table_type;
|
|
|
|
|
|
/* some counts are biased by -max_sample_block_len, so UNKNOWN can't be -1
|
|
* Any number less than -max_sample_block should do
|
|
*/
|
|
#define UNKNOWN (-10-max_sample_block_len)
|
|
|
|
typedef struct sound_struct {
|
|
sample_block_type (*get_next)(struct sound_struct *snd, long *cnt);
|
|
time_type time; /* logical starting time */
|
|
time_type t0; /* quantized time of first sample */
|
|
long stop; /* stop (clipping) sample no. */
|
|
time_type true_t0; /* exact time of first sample */
|
|
rate_type sr; /* sample rate */
|
|
long current; /* current sample number,
|
|
if negative, then the first
|
|
-current samples must be dropped
|
|
in order to find the first sample */
|
|
long logical_stop_cnt; /* log stop sample no, -1=unknwn */
|
|
snd_list_type list; /* sample block list, starting at curr. samp */
|
|
sample_type scale; /* scale factor for the result */
|
|
long prepend_cnt; /* how many zeros to prepend */
|
|
/* function to use as get_next after prepended zeros are generated: */
|
|
sample_block_type (*after_prepend)
|
|
(struct sound_struct * snd, long * cnt);
|
|
table_type table; /* pointer to table-ized version of this sound */
|
|
long *extra; /* used for extra state information, first word of extra
|
|
state should be the length of the extra state
|
|
(see sound_unref())
|
|
*/
|
|
} sound_node, *sound_type;
|
|
|
|
/* convert number of samples to memory size: */
|
|
#define table_size_in_bytes(n) \
|
|
(sizeof(table_node) + sizeof(sample_type) * ((n) - 1))
|
|
|
|
extern sample_block_type zero_block;
|
|
extern sample_block_type internal_zero_block;
|
|
|
|
extern snd_list_type zero_snd_list;
|
|
|
|
extern sound_type printing_this_sound; /* debugging global */
|
|
|
|
extern double sound_latency; /* controls output latency */
|
|
double snd_set_latency(double latency);
|
|
/* LISP: (SND-SET-LATENCY FLONUM) */
|
|
|
|
double compute_phase(double phase, double key, long n, double srate,
|
|
double new_srate, double freq, double *incr_ptr);
|
|
|
|
boolean soundp(LVAL);
|
|
/* LISP: (SOUNDP ANY) */
|
|
|
|
void snd_list_ref(snd_list_type list);
|
|
void sound_unref(sound_type snd);
|
|
void snd_list_unref(snd_list_type list);
|
|
|
|
LVAL cvsound(sound_type);
|
|
extern LVAL a_sound;
|
|
|
|
sample_block_type SND_get_next(sound_type snd, long * cnt);
|
|
sample_block_type SND_get_first(sound_type snd, long * cnt);
|
|
sample_block_type SND_get_zeros(sound_type snd, long * cnt);
|
|
sample_block_type SND_flush(sound_type snd, long * cnt);
|
|
|
|
double hz_to_step(double); /* LISP: (HZ-TO-STEP ANYNUM) */
|
|
int interp_style(sound_type s, rate_type sr);
|
|
void set_logical_stop_time(sound_type sound, time_type when); /* LISP: (SND-SET-LOGICAL-STOP SOUND ANYNUM) */
|
|
|
|
#define xlog(x) log(x)
|
|
/* LISP: double (LOG FLONUM) */
|
|
snd_list_type snd_list_create(snd_susp_type susp);
|
|
void snd_list_terminate(snd_list_type snd_list);
|
|
void snd_sort_2(sound_type * s1_ptr, sound_type * s2_ptr, rate_type sr);
|
|
|
|
double snd_sref(sound_type s, time_type t);
|
|
/* LISP: (SND-SREF SOUND ANYNUM) */
|
|
|
|
double snd_sref_inverse(sound_type s, double val);
|
|
/* LISP: (SREF-INVERSE SOUND ANYNUM) */
|
|
|
|
double snd_stop_time(sound_type s); /* LISP: (SND-STOP-TIME SOUND) */
|
|
#define snd_time(s) (s)->time
|
|
/* LISP: double (SND-TIME SOUND) */
|
|
|
|
#define snd_srate(s) (s)->sr
|
|
/* LISP: double (SND-SRATE SOUND) */
|
|
#define snd_t0(s) (s)->t0
|
|
/* LISP: double (SND-T0 SOUND) */
|
|
|
|
sound_type snd_xform(sound_type snd, rate_type sr, time_type time,
|
|
time_type start_time, time_type stop_time, promoted_sample_type scale);
|
|
/* LISP: (SND-XFORM SOUND ANYNUM ANYNUM ANYNUM ANYNUM ANYNUM) */
|
|
sound_type sound_create(snd_susp_type susp, time_type t0, rate_type sr,
|
|
promoted_sample_type scale);
|
|
|
|
void min_cnt(long *cnt_ptr, sound_type sound, snd_susp_type susp, long cnt);
|
|
void indent(int n);
|
|
void sound_prepend_zeros(sound_type snd, time_type t0);
|
|
|
|
|
|
|
|
#ifndef GCBUG
|
|
#define blocks_to_watch_max 50
|
|
extern long blocks_to_watch_len;
|
|
extern sample_block_type blocks_to_watch[blocks_to_watch_max];
|
|
|
|
void block_watch(long sample_block);
|
|
/* LISP: (BLOCK-WATCH FIXNUM) */
|
|
long sound_nth_block(sound_type snd, long n);
|
|
/* LISP: (SOUND-NTH-BLOCK SOUND FIXNUM) */
|
|
#endif
|
|
|
|
sound_type sound_copy(sound_type snd);
|
|
/* LISP: (SND-COPY SOUND) */
|
|
void sound_xlmark(void *a_sound);
|
|
void sound_print(LVAL snd_expr, long n);
|
|
/* LISP: (SND-PRINT ANY FIXNUM) */
|
|
void sound_play(LVAL snd_expr);
|
|
/* LISP: (SND-PLAY ANY) */
|
|
void stats(void);
|
|
/* LISP: (STATS) */
|
|
void sound_print_tree(sound_type snd);
|
|
/* LISP: (SND-PRINT-TREE SOUND) */
|
|
|
|
void mark_audio_time(void);
|
|
|
|
void sound_print_tree_1(sound_type snd, int n);
|
|
|
|
sound_type sound_scale(double factor, sound_type snd);
|
|
/* LISP: (SND-SCALE ANYNUM SOUND) */
|
|
void sound_init(void);
|
|
|
|
void sound_symbols(void);
|
|
|
|
table_type sound_to_table(sound_type s);
|
|
|
|
void table_unref(table_type table);
|
|
|
|
sound_type sound_zero(time_type t0, rate_type sr);
|
|
/* LISP: (SND-ZERO ANYNUM ANYNUM) */
|
|
|
|
#define sound_get_next(s, n) ((*(s->get_next))(s, n))
|
|
|
|
#define susp_print_tree(s, n) (*((s)->print_tree))(s, n)
|
|
|
|
double step_to_hz(double);
|
|
/* LISP: (STEP-TO-HZ ANYNUM) */
|
|
|
|
#ifdef WIN32
|
|
double log2(double x);
|
|
#endif /* WIN32 */
|
|
|
|
/* macros for access to samples within a suspension */
|
|
/* NOTE: assume suspension structure is named "susp" */
|
|
|
|
/* susp_check_samples points sample_ptr to a new sample block if necessary */
|
|
#define susp_check_samples(sound, sample_ptr, sample_cnt) \
|
|
if (susp->sample_cnt == 0) \
|
|
susp_get_samples(sound, sample_ptr, sample_cnt)
|
|
|
|
/* susp_check_samples_break is similar to susp_check_samples - "_break"
|
|
* normally means that this code will break out of the inner loop, but in
|
|
* this case, there is no reason (neither log nor term) to break.
|
|
* x2_sample is taken from sound
|
|
*/
|
|
#define susp_check_samples_break(sound, sample_ptr, sample_cnt, x2_sample) \
|
|
if (susp->sample_cnt == 0) { \
|
|
susp_get_samples(sound, sample_ptr, sample_cnt); \
|
|
x2_sample = susp_current_sample(sound, sample_ptr); }
|
|
|
|
|
|
/* susp_get_samples always gets next block (useful only in initialization code) */
|
|
#define susp_get_samples(sound, sample_ptr, sample_cnt) \
|
|
susp->sample_ptr = sound_get_next(susp->sound, &(susp->sample_cnt))->samples
|
|
|
|
/* susp_get_block_samples always gets next block (useful only in initialization code) */
|
|
#define susp_get_block_samples(sound, sample_block_ptr, sample_ptr, sample_cnt) \
|
|
susp->sample_block_ptr = sound_get_next(susp->sound, &susp->sample_cnt); \
|
|
susp->sample_ptr = susp->sample_block_ptr->samples
|
|
|
|
/* susp_took is called after you've taken n samples */
|
|
#define susp_took(sample_cnt, n) susp->sample_cnt -= n
|
|
|
|
/* susp_fetch_sample is used to grab just one sample, doesn't check for samples!,
|
|
* but applies scale factor: */
|
|
#define susp_fetch_sample(sound, sample_ptr, sample_cnt) \
|
|
(susp->sound->scale * (susp->sample_cnt--, *(susp->sample_ptr++)))
|
|
|
|
/* susp_current_sample grabs sample without advancing to next, applies scale
|
|
* factor: */
|
|
#define susp_current_sample(sound, sample_ptr) \
|
|
(susp->sound->scale * (*(susp->sample_ptr)))
|
|
|
|
/* susp_check_term_samples checks for samples; if new ones are fetched, then
|
|
* run termination test on signal and record result.
|
|
*/
|
|
#define susp_check_term_samples(sound, sample_ptr, sample_cnt) \
|
|
if (susp->sample_cnt == 0) { \
|
|
susp_get_samples(sound, sample_ptr, sample_cnt); \
|
|
terminate_test(sample_ptr, sound, susp->sample_cnt); }
|
|
|
|
/* susp_check_term_log_samples checks for samples
|
|
* if new ones are fetched, then run termination test and logical stop
|
|
* test on signal and record results.
|
|
*/
|
|
#define susp_check_term_log_samples(sound, sample_ptr, sample_cnt) \
|
|
if (susp->sample_cnt == 0) { \
|
|
susp_get_samples(sound, sample_ptr, sample_cnt); \
|
|
logical_stop_test(sound, susp->sample_cnt); \
|
|
terminate_test(sample_ptr, sound, susp->sample_cnt); }
|
|
|
|
/* susp_check_term_log_block_samples checks for samples
|
|
* if new ones are fetched, then run termination test and logical stop
|
|
* test on signal and record results. In this case, termination and logical
|
|
* stop happen at the MAXIMUM of termination and logical stop times, resp.
|
|
*
|
|
* Originally, this code assumed that logical stops occurred on block boundaries,
|
|
* but because of the SET-LOGICAL-STOP function, which just writes a stop time
|
|
* into the sound_struct, the logical stop can be anywhere. As soon as the
|
|
* logical stop is known, we want to propagate the value from the sound being
|
|
* read into the sound being computed. The propagation should set the logical
|
|
* stop of the computed sound to the MAX of any current value and the new
|
|
* value. When the bit fields indicate that all logical stop times have been
|
|
* encountered, then the sound being computed will make the logical stop happen
|
|
* on a block boundary and set the flag on the block of samples where the stop
|
|
* occurs.
|
|
*/
|
|
#define susp_check_term_log_block_samples(sound, sample_block_ptr, sample_ptr, sample_cnt, bit, all) \
|
|
if (susp->sample_cnt == 0) { \
|
|
susp_get_block_samples(sound, sample_block_ptr, sample_ptr, sample_cnt); \
|
|
/*OLD if (susp->sound->logical_stop_cnt == \
|
|
susp->sound->current - susp->sample_cnt) { \
|
|
*/ \
|
|
if (susp->sound->logical_stop_cnt != UNKNOWN && \
|
|
!(susp->logical_stop_bits & bit)) { \
|
|
susp->logical_stop_bits |= bit; \
|
|
/*OLD \
|
|
if (susp->logical_stop_bits == all) { \
|
|
susp->susp.log_stop_cnt = (long) \
|
|
((((susp->sound->current - susp->sample_cnt) / \
|
|
susp->sound->sr + susp->sound->t0) - \
|
|
susp->susp.t0) * susp->susp.sr + 0.5); \
|
|
assert(susp->susp.log_stop_cnt >= 0); } } \
|
|
*/ \
|
|
susp->susp.log_stop_cnt = max(susp->susp.log_stop_cnt, \
|
|
(((susp->sound->logical_stop_cnt / \
|
|
susp->sound->sr + susp->sound->t0) - \
|
|
susp->susp.t0) * susp->susp.sr + 0.5)); } \
|
|
if (susp->sample_ptr == zero_block->samples) { \
|
|
susp->terminate_bits |= bit; \
|
|
if (susp->terminate_bits == all) { \
|
|
susp->terminate_cnt = (long) \
|
|
((((susp->sound->current - susp->sample_cnt) / \
|
|
susp->sound->sr + susp->sound->t0) - \
|
|
susp->susp.t0) * susp->susp.sr + 0.5); \
|
|
} } }
|
|
|
|
|
|
/* logical_stop_cnt_cvt is used to convert from the logical stop count
|
|
* at one sample rate to that of another sample rate -- this macro is
|
|
* used by the snd_make_<op> routine in every <op>.c file, and assumes
|
|
* the target sample rate is susp->susp.sr.
|
|
*
|
|
* NOTE: this macro does not take into account the possibility of different
|
|
* start times - maybe it should.
|
|
*/
|
|
#define logical_stop_cnt_cvt(sound) \
|
|
(sound->logical_stop_cnt == UNKNOWN ? UNKNOWN : \
|
|
ROUND((sound->logical_stop_cnt / sound->sr) * susp->susp.sr))
|
|
|
|
|
|
/* logical_stop_test tests to see if sound has logically stopped; if so,
|
|
* sets susp->susp.log_stop_cnt. The resulting logical_stop_cnt will reflect
|
|
* the minimum logical_stop time of all sounds to which this test is applied.
|
|
*/
|
|
#define logical_stop_test(sound, cnt) \
|
|
if (susp->sound->logical_stop_cnt == susp->sound->current - (cnt)) {\
|
|
min_cnt(&susp->susp.log_stop_cnt, susp->sound, (snd_susp_type) susp, cnt); }
|
|
|
|
/* terminate_test checks to see if sound has terminated; if so,
|
|
* sets susp->terminate_cnt. The resulting terminate_cnt will reflect
|
|
* the minimum termination time of all sounds to which this test is applied.
|
|
*/
|
|
#define terminate_test(sample_ptr, sound, cnt) \
|
|
if (susp->sample_ptr == zero_block->samples) { \
|
|
min_cnt(&susp->terminate_cnt, susp->sound, (snd_susp_type) susp, cnt); }
|
|
|
|
|
|
/* susp_check_log_samples checks for new samples then checks for
|
|
* termination and logical stop conditions
|
|
*/
|
|
#define susp_check_log_samples(sound, sample_ptr, sample_cnt) \
|
|
if (susp->sample_cnt == 0) { \
|
|
susp_get_samples(sound, sample_ptr, sample_cnt); \
|
|
logical_stop_test(sound, susp->sample_cnt); }
|
|
|
|
/* susp_check_term_samples_break checks for new samples then checks for
|
|
* termination condition; breaks from inner loop
|
|
*/
|
|
#define susp_check_term_samples_break( \
|
|
sound, sample_ptr, sample_cnt, x2_sample) \
|
|
if (susp->sample_cnt == 0) { \
|
|
susp_get_samples(sound, sample_ptr, sample_cnt); \
|
|
x2_sample = susp_current_sample(sound, sample_ptr); \
|
|
terminate_test(sample_ptr, sound, susp->sample_cnt); \
|
|
if (susp->terminate_cnt < susp->susp.current + cnt + togo) { \
|
|
break; }} \
|
|
else x2_sample = susp_current_sample(sound, sample_ptr);
|
|
|
|
/* susp_check_log_samples_break checks for new samples then checks for
|
|
* logical stop conditions; breaks from inner loop
|
|
*/
|
|
#define susp_check_log_samples_break( \
|
|
sound, sample_ptr, sample_cnt, x2_sample) \
|
|
if (susp->sample_cnt == 0) { \
|
|
susp_get_samples(sound, sample_ptr, sample_cnt); \
|
|
x2_sample = susp_current_sample(sound, sample_ptr); \
|
|
logical_stop_test(sound, susp->sample_cnt); \
|
|
if (!susp->logically_stopped && susp->susp.log_stop_cnt != UNKNOWN && \
|
|
(susp->susp.log_stop_cnt < susp->susp.current + cnt + togo)) { \
|
|
break; }} \
|
|
else x2_sample = susp_current_sample(sound, sample_ptr);
|
|
|
|
|
|
/* susp_check_term_log_samples_break checks for new samples then checks for
|
|
* termination and logical stop conditions; breaks from inner loop
|
|
*/
|
|
#define susp_check_term_log_samples_break( \
|
|
sound, sample_ptr, sample_cnt, x2_sample) \
|
|
if (susp->sample_cnt == 0) { \
|
|
susp_get_samples(sound, sample_ptr, sample_cnt); \
|
|
x2_sample = susp_current_sample(sound, sample_ptr); \
|
|
terminate_test(sample_ptr, sound, susp->sample_cnt); \
|
|
logical_stop_test(sound, susp->sample_cnt); \
|
|
if ((susp->terminate_cnt != UNKNOWN && \
|
|
susp->terminate_cnt < susp->susp.current + cnt + togo) || \
|
|
(!susp->logically_stopped && susp->susp.log_stop_cnt != UNKNOWN && \
|
|
susp->susp.log_stop_cnt < susp->susp.current + cnt + togo)) { \
|
|
break; }} \
|
|
else x2_sample = susp_current_sample(sound, sample_ptr);
|
|
|
|
|