1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-04-30 15:49:41 +02:00
Steve Daulton 333c0e3440 Fix for bug 1653 (Nyquist *Table* size limit)
as suggested by RBD in comment #1
2017-06-15 21:46:11 +01:00

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);