This is holmes.c in view mode; [Download] [Up]
#include <config.h> /* $Id: holmes.c,v 1.13 1994/11/08 13:30:50 a904209 Exp a904209 $ */ char *holmes_id = "$Id: holmes.c,v 1.13 1994/11/08 13:30:50 a904209 Exp a904209 $"; #include <stdio.h> #include <ctype.h> #include <useconfig.h> #include <math.h> #include "proto.h" #include "nsynth.h" #include "elements.h" #include "darray.h" #include "holmes.h" #include "phfeat.h" #include "getargs.h" #if 1 #define AMP_ADJ 14 #else #define AMP_ADJ 0 #endif FILE *par_file; FILE *jsru_file; int speed = 1; double frac = 1.0; typedef struct { float v; /* boundary value */ int t; /* transition time */ } slope_t; typedef struct { slope_t p[nEparm]; } trans_t; typedef struct { float a; float b; float v; } filter_t, *filter_ptr; static float filter PROTO((filter_ptr p, Float v)); static void jsru_save PROTO((double f0, float *tp)); static float filter(p, v) filter_ptr p; Float v; { return p->v = (p->a * v + p->b * p->v); } /* 'a' is dominant element, 'b' is dominated ext is flag to say to use external times from 'a' rather than internal i.e. ext != 0 if 'a' is NOT current element. */ static void set_trans PROTO((slope_t * t, Elm_ptr a, Elm_ptr b, int ext, int e)); static void set_trans(t, a, b, ext, e) slope_t *t; Elm_ptr a; Elm_ptr b; int ext; int e; { int i; for (i = 0; i < nEparm; i++) { t[i].t = ((ext) ? a->p[i].ed : a->p[i].id) * speed; if (t[i].t) t[i].v = a->p[i].fixd + (a->p[i].prop * b->p[i].stdy) * (float) 0.01; else t[i].v = b->p[i].stdy; } } static float linear PROTO((Float a, Float b, int t, int d)); /* ______________ b / / / a____________/ 0 d ---------------t--------------- */ static float linear(a, b, t, d) Float a; Float b; int t; int d; { if (t <= 0) return a; else if (t >= d) return b; else { float f = (float) t / (float) d; return a + (b - a) * f; } } static float interpolate PROTO((char *w, char *p, slope_t * s, slope_t * e, Float mid, int t, int d)); static float interpolate(w, p, s, e, mid, t, d) char *w; char *p; slope_t *s; slope_t *e; Float mid; int t; int d; { float steady = d - (s->t + e->t); #ifdef DEBUG fprintf(stdout, "%4s %s s=%g,%d e=%g,%d m=%g,%g\n", w, p, s->v, s->t, e->v, e->t, mid, steady); #endif if (steady >= 0) { /* Value reaches stready state somewhere ... */ if (t < s->t) return linear(s->v, mid, t, s->t); /* initial transition */ else { t -= s->t; if (t <= steady) return mid; /* steady state */ else return linear(mid, e->v, (int) (t - steady), e->t); /* final transition */ } } else { float f = (float) 1.0 - ((float) t / (float) d); float sp = linear(s->v, mid, t, s->t); float ep = linear(e->v, mid, d - t, e->t); return f * sp + ((float) 1.0 - f) * ep; } } unsigned holmes(nelm, elm, nsamp, samp_base) unsigned nelm; unsigned char *elm; unsigned nsamp; short *samp_base; { filter_t flt[nEparm]; klatt_frame_t pars; short *samp = samp_base; Elm_ptr le = &Elements[0]; unsigned i = 0; unsigned tstress = 0; unsigned ntstress = 0; slope_t stress_s; slope_t stress_e; float top = 1.1 * def_pars.F0hz10; int j; pars = def_pars; pars.FNPhz = le->p[fn].stdy; pars.B1phz = pars.B1hz = 60; pars.B2phz = pars.B2hz = 90; pars.B3phz = pars.B3hz = 150; #if 0 pars.F4hz = 3500; #endif pars.B4phz = def_pars.B4phz; /* flag new utterance */ parwave_init(&klatt_global); /* Set stress attack/decay slope */ stress_s.t = 40; stress_e.t = 40; stress_e.v = 0.0; for (j = 0; j < nEparm; j++) { flt[j].v = le->p[j].stdy; flt[j].a = frac; flt[j].b = (float) 1.0 - (float) frac; } while (i < nelm) { Elm_ptr ce = &Elements[elm[i++]]; unsigned dur = elm[i++]; i++; /* skip stress */ /* Skip zero length elements which are only there to affect boundary values of adjacent elements */ if (dur > 0) { Elm_ptr ne = (i < nelm) ? &Elements[elm[i]] : &Elements[0]; slope_t start[nEparm]; slope_t end[nEparm]; unsigned t; if (ce->rk > le->rk) { if (par_file) fprintf(par_file, "# %s < %s\n", le->name, ce->name); set_trans(start, ce, le, 0, 's'); /* we dominate last */ } else { if (par_file) fprintf(par_file, "# %s >= %s\n", le->name, ce->name); set_trans(start, le, ce, 1, 's'); /* last dominates us */ } if (ne->rk > ce->rk) { if (par_file) fprintf(par_file, "# %s < %s\n", ce->name, ne->name); set_trans(end, ne, ce, 1, 'e'); /* next dominates us */ } else { if (par_file) fprintf(par_file, "# %s >= %s\n", ce->name, ne->name); set_trans(end, ce, ne, 0, 'e'); /* we dominate next */ } if (par_file) { int j; fprintf(par_file, "# %s\n", ce->name); for (j = 0; j < nEparm; j++) fprintf(par_file, "%c%6s", (j) ? ' ' : '#', Ep_name[j]); fprintf(par_file, "\n"); for (j = 0; j < nEparm; j++) fprintf(par_file, "%c%6.4g", (j) ? ' ' : '#', start[j].v); fprintf(par_file, "\n"); for (j = 0; j < nEparm; j++) fprintf(par_file, "%c%6d", (j) ? ' ' : '#', start[j].t); fprintf(par_file, "\n"); } for (t = 0; t < dur; t++, tstress++) { float base = top * 0.8 /* 3 * top / 5 */; float tp[nEparm]; int j; if (tstress == ntstress) { unsigned j = i; stress_s = stress_e; tstress = 0; ntstress = dur; #ifdef DEBUG_STRESS printf("Stress %g -> ", stress_s.v); #endif while (j <= nelm) { Elm_ptr e = (j < nelm) ? &Elements[elm[j++]] : &Elements[0]; unsigned du = (j < nelm) ? elm[j++] : 0; unsigned s = (j < nelm) ? elm[j++] : 3; if (s || e->feat & vwl) { unsigned d = 0; if (s) stress_e.v = (float) s / 3; else stress_e.v = (float) 0.1; do { d += du; #ifdef DEBUG_STRESS printf("%s", (e && e->dict) ? e->dict : ""); #endif e = (j < nelm) ? &Elements[elm[j++]] : &Elements[0]; du = elm[j++]; } while ((e->feat & vwl) && elm[j++] == s); ntstress += d / 2; break; } ntstress += du; } #ifdef DEBUG_STRESS printf(" %g @ %d\n", stress_e.v, ntstress); #endif } for (j = 0; j < nEparm; j++) tp[j] = filter(flt + j, interpolate(ce->name, Ep_name[j], &start[j], &end[j], (float) ce->p[j].stdy, t, dur)); /* Now call the synth for each frame */ pars.F0hz10 = base + (top - base) * interpolate("", "f0", &stress_s, &stress_e, (float) 0, tstress, ntstress); pars.AVdb = pars.AVpdb = tp[av]; pars.AF = tp[af]; pars.FNZhz = tp[fn]; pars.ASP = tp[asp]; pars.Aturb = tp[avc]; pars.B1phz = pars.B1hz = tp[b1]; pars.B2phz = pars.B2hz = tp[b2]; pars.B3phz = pars.B3hz = tp[b3]; pars.F1hz = tp[f1]; pars.F2hz = tp[f2]; pars.F3hz = tp[f3]; /* AMP_ADJ + is a bodge to get amplitudes up to klatt-compatible levels Needs to be fixed properly in tables */ /* pars.ANP = AMP_ADJ + tp[an]; */ pars.AB = AMP_ADJ + tp[ab]; pars.A5 = AMP_ADJ + tp[a5]; pars.A6 = AMP_ADJ + tp[a6]; pars.A1 = AMP_ADJ + tp[a1]; pars.A2 = AMP_ADJ + tp[a2]; pars.A3 = AMP_ADJ + tp[a3]; pars.A4 = AMP_ADJ + tp[a4]; parwave(&klatt_global, &pars, samp); samp += klatt_global.nspfr; if (par_file) { for (j = 0; j < nEparm; j++) fprintf(par_file, " %6.4g", tp[j]); fprintf(par_file, "\n"); } if (jsru_file) jsru_save(pars.F0hz10 * 0.1, tp); /* Declination of f0 envelope 0.25Hz / cS */ top -= 0.5; } if (par_file) { int j; for (j = 0; j < nEparm; j++) fprintf(par_file, "%c%6.4g", (j) ? ' ' : '#', end[j].v); fprintf(par_file, "\n"); for (j = 0; j < nEparm; j++) fprintf(par_file, "%c%6d", (j) ? ' ' : '#', end[j].t); fprintf(par_file, "\n"); } } le = ce; } return (samp - samp_base); } int init_holmes(argc, argv) int argc; char *argv[]; { char *par_name = NULL; char *jsru_name = NULL; argc = getargs("Holmes",argc, argv, "p", "", &par_name, "Parameter file for plot", "j", "", &jsru_name, "Data for alternate synth (JSRU)", "S", "%d", &speed, "Speed (1.0 is 'normal')", "K", "%lg", &frac, "Parameter filter 'fraction'", NULL); if (help_only) return argc; if (par_name) { par_file = fopen(par_name, "w"); if (!par_file) perror(par_name); } if (jsru_name) { jsru_file = fopen(jsru_name, "w"); if (!jsru_file) perror(jsru_name); } return argc; } void term_holmes() { if (par_file) fclose(par_file); if (jsru_file) fclose(jsru_file); } static int jsru_freq PROTO((Float f, Float base, Float inc)); static int jsru_freq(f, base, inc) Float f; Float base; Float inc; { int i; f = (f - base) / inc; i = (int) f; if (i >= 64) i = 63; return i; } static int jsru_amp PROTO((Float a)); static int jsru_amp(a) Float a; { int i = a; if (i <= 0) i = 1; if (i >= 64) i = 63; return i; } /* 0 1 2 3 4 5 F1 F2 F3 FN flflim 125.0 550.0 1350.0 3500.0 3500.0 95.0 fincrm 25.0 50.0 50.0 0.0 0.0 5.0 */ static void jsru_save(f0, tp) double f0; float *tp; { f0 = 16 * (log(f0 / 25.0) / log(2.0)) - 1; /* fn, alf, f1, a1, f2, a2, f3, a3, ahf, v, f0, m */ fputc(jsru_freq(tp[fn], 95.0, 5.0), jsru_file); fputc(jsru_amp(tp[an]), jsru_file); fputc(jsru_freq(tp[f1], 125.0, 25.0), jsru_file); fputc(jsru_amp(tp[a1]), jsru_file); fputc(jsru_freq(tp[f2], 550.0, 50.0), jsru_file); fputc(jsru_amp(tp[a2]), jsru_file); fputc(jsru_freq(tp[f3], 1350.0, 50.0), jsru_file); fputc(jsru_amp(tp[a3]), jsru_file); fputc(jsru_amp(tp[a4]), jsru_file); fputc(jsru_amp(tp[av]), jsru_file); fputc((int) f0, jsru_file); fputc((int) 32, jsru_file); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.