~ubuntu-branches/debian/squeeze/stella/squeeze

« back to all changes in this revision

Viewing changes to src/emucore/rsynth/holmes.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephen Kitt
  • Date: 2010-07-12 23:49:36 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20100712234936-juawrr3etzhr2qpv
Tags: 3.1.2-1
* New maintainer (closes: #532039).
* New upstream version (closes: #461121):
  - includes launcher (closes: #396058).
* Fix the reference to the X Window System in the description (closes:
  #411815).
* Move to main, DFSG-free ROMs are available (see README.Debian).
* Enhance the package description.
* Drop the libslang2-dev dependency (closes: #560274).
* Remove the Encoding entry from stella.desktop.
* Avoid ignoring errors when cleaning.
* Add ${misc:Depends} to the package dependencies.
* Provide a doc-base file to install the documentation using doc-base.
* Switch to debhelper 7 with a simplified rules file.
* Use autotools-dev to provide updated configuration files.
* Update to Standards-Version 3.9.0:
  - Move to menu section Applications/Emulators.
  - Move the homepage declaration.
* Re-write the manpage.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
    Copyright (c) 1994,2001-2003 Nick Ing-Simmons. All rights reserved.
3
 
 
4
 
    This library is free software; you can redistribute it and/or
5
 
    modify it under the terms of the GNU Library General Public
6
 
    License as published by the Free Software Foundation; either
7
 
    version 2 of the License, or (at your option) any later version.
8
 
 
9
 
    This library is distributed in the hope that it will be useful,
10
 
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 
    Library General Public License for more details.
13
 
 
14
 
    You should have received a copy of the GNU Library General Public
15
 
    License along with this library; if not, write to the Free
16
 
    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
17
 
    MA 02111-1307, USA
18
 
 
19
 
*/
20
 
#include "config.h"
21
 
/* $Id: holmes.c,v 1.2 2006/06/12 14:12:52 stephena Exp $
22
 
 */
23
 
char *holmes_id = "$Id: holmes.c,v 1.2 2006/06/12 14:12:52 stephena Exp $";
24
 
#include <stdio.h>
25
 
#include <ctype.h>
26
 
#include <assert.h>
27
 
#include "useconfig.h"
28
 
#include <math.h>
29
 
#include "rsynth.h"
30
 
#include "darray.h"
31
 
 
32
 
typedef struct {
33
 
    float v;                    /* boundary value */
34
 
    long t;                     /* transition time */
35
 
} slope_t;
36
 
 
37
 
 
38
 
 
39
 
typedef struct {
40
 
    float a;
41
 
    float b;
42
 
    float v;
43
 
} filter_t, *filter_ptr;
44
 
 
45
 
static float
46
 
filter(filter_ptr p, float v)
47
 
{
48
 
    return p->v = (p->a * v + p->b * p->v);
49
 
}
50
 
 
51
 
/* 'a' is dominant element, 'b' is dominated
52
 
   ext is flag to say to use external times from 'a' rather
53
 
   than internal i.e. ext != 0 if 'a' is NOT current element.
54
 
 
55
 
 */
56
 
 
57
 
static void
58
 
set_trans(slope_t * t, int i, Elm_ptr a, Elm_ptr b, int ext, int e,
59
 
          float speed)
60
 
{
61
 
    t[i].t = (long) (((ext) ? a->p[i].ed : a->p[i].id) * speed);
62
 
    if (t[i].t) {
63
 
        float afrac = a->p[i].prop * 0.01F;
64
 
        t[i].v = a->p[i].stdy * (1.0F - afrac) + (afrac * b->p[i].stdy);
65
 
    }
66
 
    else
67
 
        t[i].v = b->p[i].stdy;
68
 
}
69
 
 
70
 
 
71
 
/*
72
 
   ______________ b
73
 
   /
74
 
   /
75
 
   /
76
 
   a____________/
77
 
   0   d
78
 
   ---------------t---------------
79
 
 */
80
 
 
81
 
float
82
 
linear(float a, float b, long t, long d)
83
 
{
84
 
    if (t <= 0)
85
 
        return a;
86
 
    else if (t >= d)
87
 
        return b;
88
 
    else {
89
 
        float f = (float) t / (float) d;
90
 
        return a + (b - a) * f;
91
 
    }
92
 
}
93
 
 
94
 
float
95
 
interpolate(char *w, char *p, slope_t * s, slope_t * e, float mid, long t,
96
 
            long d)
97
 
{
98
 
    float steady = d - (s->t + e->t);
99
 
#ifdef DEBUG
100
 
    fprintf(stdout, "%4s %s s=%g,%d e=%g,%d m=%g,%g\n",
101
 
            w, p, s->v, s->t, e->v, e->t, mid, steady);
102
 
#endif
103
 
    if (steady >= 0) {
104
 
        /* Value reaches stready state somewhere ... */
105
 
        if (t < s->t)
106
 
            return linear(s->v, mid, t, s->t);  /* initial transition */
107
 
        else {
108
 
            t -= s->t;
109
 
            if (t <= steady)
110
 
                return mid;     /* steady state */
111
 
            else
112
 
                return linear(mid, e->v, (int) (t - steady), e->t);
113
 
            /* final transition */
114
 
        }
115
 
    }
116
 
    else {
117
 
        float f = (float) 1.0 - ((float) t / (float) d);
118
 
        float sp = linear(s->v, mid, t, s->t);
119
 
        float ep = linear(e->v, mid, d - t, e->t);
120
 
        return f * sp + ((float) 1.0 - f) * ep;
121
 
    }
122
 
}
123
 
 
124
 
#define CHECK_SPACING(a,b)                                \
125
 
  do {                                                    \
126
 
      if (a < b + 200)                                    \
127
 
       fprintf(stdout,"%s=%g < %s=%g+200\n",#a,a,#b,b); \
128
 
     } while (0)
129
 
 
130
 
 
131
 
unsigned
132
 
rsynth_interpolate(rsynth_t * rsynth, 
133
 
                   unsigned char *elm, unsigned nelm, 
134
 
                   float *f0, unsigned nf0)
135
 
{
136
 
    filter_t flt[nEparm];
137
 
    float ep[nEparm];
138
 
    Elm_ptr le = &Elements[0];
139
 
    unsigned i = 0;
140
 
    unsigned tf0 = 0;
141
 
    unsigned ntf0 = 0;
142
 
    unsigned samp = 0;
143
 
    float contour[3];
144
 
    float f0s = rsynth->speaker->F0Hz;
145
 
    float f0e = f0s;
146
 
    int j;
147
 
    float speed = rsynth->speed;
148
 
    float F0Hz;
149
 
 
150
 
    if (nf0 < 3 || !f0 || (rsynth->flags & RSYNTH_MONOTONE)) {
151
 
        unsigned i;
152
 
        f0 = contour;
153
 
        nf0 = 3;
154
 
        for (i = 0; i < nelm; i += 2) {
155
 
            f0[1] += elm[i + 1];
156
 
        }
157
 
        if ((rsynth->flags & RSYNTH_MONOTONE)) {
158
 
            f0[0] = rsynth->speaker->F0Hz;      /* top */
159
 
            f0[2] = f0[0];      /* bottom */
160
 
        }
161
 
        else {
162
 
            f0[0] = 1.1 * rsynth->speaker->F0Hz;        /* top */
163
 
            f0[2] = 0.6 * f0[0];        /* bottom */
164
 
        }
165
 
    }
166
 
 
167
 
#if 0
168
 
    fprintf(stderr, "f0 (%g) %5.1f %gs %5.1f\n", rsynth->F0hz,
169
 
            f0[0], 1.0 * f0[1] * rsynth->samples_frame / rsynth->samp_rate,
170
 
            f0[2]);
171
 
#endif
172
 
    f0e = f0s = *f0++;
173
 
 
174
 
 
175
 
    /* flag new utterance */
176
 
 
177
 
 
178
 
    /* Experimental feature:
179
 
       frac is the proporion of the new value that is fed into lowpass 
180
 
       filter. This is added to (1-frac) of old value.
181
 
       So a value of 1.0 means no smoothing. A value of 0.5 seems ok
182
 
       and tracks look smoother. Smoothing is insurance against 
183
 
       interpollation bugs and mis-features changing parameters too fast.
184
 
 
185
 
       Revisit this with some theory...
186
 
     */
187
 
    for (j = 0; j < nEparm; j++) {
188
 
        flt[j].v = le->p[j].stdy;
189
 
        flt[j].a = rsynth->smooth;
190
 
        flt[j].b = 1.0F - rsynth->smooth;
191
 
    }
192
 
    while (i < nelm) {
193
 
        Elm_ptr ce = &Elements[elm[i++]];
194
 
        unsigned dur = elm[i++];
195
 
        if (rsynth->flags & RSYNTH_ETRACE) {
196
 
            printf("%s.%ld ", ce->name,
197
 
                   1000 * dur * rsynth->samples_frame / rsynth->sr);
198
 
        }
199
 
        /* Skip zero length elements which are only there to affect
200
 
           boundary values of adjacent elements.
201
 
           Note this mainly refers to "QQ" element in fricatives
202
 
           as stops have a non-zero length central element.
203
 
         */
204
 
        if (dur > 0) {
205
 
            Elm_ptr ne = (i < nelm) ? &Elements[elm[i]] : &Elements[0];
206
 
            slope_t start[nEparm];
207
 
            slope_t end[nEparm];
208
 
            unsigned t;
209
 
 
210
 
            int i;
211
 
            for (i = 0; i < nEparm; i++) {
212
 
 
213
 
 
214
 
                if (ce->p[i].rk > le->p[i].rk) {
215
 
                    if (rsynth->parm_file)
216
 
                        fprintf(rsynth->parm_file,
217
 
                                "# %3s %2s(%2d) <  %2s(%2d)\n", Ep_name[i],
218
 
                                le->name, le->p[i].rk, ce->name,
219
 
                                ce->p[i].rk);
220
 
                    set_trans(start, i, ce, le, 0, 's', speed);
221
 
                    /* we dominate last */
222
 
                }
223
 
                else {
224
 
                    if (rsynth->parm_file)
225
 
                        fprintf(rsynth->parm_file,
226
 
                                "# %3s %2s(%2d) >= %2s(%2d)\n", Ep_name[i],
227
 
                                le->name, le->p[i].rk, ce->name,
228
 
                                ce->p[i].rk);
229
 
                    set_trans(start, i, le, ce, 1, 's', speed);
230
 
                    /* last dominates us */
231
 
                }
232
 
 
233
 
                if (ne->p[i].rk > ce->p[i].rk) {
234
 
                    if (rsynth->parm_file)
235
 
                        fprintf(rsynth->parm_file,
236
 
                                "# %3s %2s(%2d) <  %2s(%2d)\n", Ep_name[i],
237
 
                                ce->name, ce->p[i].rk, ne->name,
238
 
                                ne->p[i].rk);
239
 
                    set_trans(end, i, ne, ce, 1, 'e', speed);
240
 
                    /* next dominates us */
241
 
                }
242
 
                else {
243
 
                    if (rsynth->parm_file)
244
 
                        fprintf(rsynth->parm_file,
245
 
                                "# %3s %2s(%2d) >= %2s(%2d)\n", Ep_name[i],
246
 
                                ce->name, ce->p[i].rk, ne->name,
247
 
                                ne->p[i].rk);
248
 
                    set_trans(end, i, ce, ne, 0, 'e', speed);
249
 
                    /* we dominate next */
250
 
                }
251
 
 
252
 
            }
253
 
 
254
 
            if (rsynth->parm_file) {
255
 
                int j;
256
 
                fprintf(rsynth->parm_file, "# %s\n", ce->name);
257
 
                fprintf(rsynth->parm_file, "%c%6s %6s", '#', "f0", "ao");
258
 
                for (j = 0; j < nEparm; j++)
259
 
                    fprintf(rsynth->parm_file, "%c%6s", ' ', Ep_name[j]);
260
 
                fprintf(rsynth->parm_file, "\n#%6s %6s", "", "");
261
 
                for (j = 0; j < nEparm; j++)
262
 
                    fprintf(rsynth->parm_file, "%c%6.4g", ' ', start[j].v);
263
 
                fprintf(rsynth->parm_file, "\n#%6s %6s", "", "");
264
 
                for (j = 0; j < nEparm; j++)
265
 
                    fprintf(rsynth->parm_file, "%c%6ld", ' ', start[j].t);
266
 
                fprintf(rsynth->parm_file, "\n");
267
 
            }
268
 
 
269
 
            for (t = 0; t < dur; t++, tf0++) {
270
 
                int j;
271
 
                float peak = 0.25;
272
 
 
273
 
                for (j = 0; j < nEparm; j++) {
274
 
                    ep[j] =
275
 
                        filter(flt + j,
276
 
                               interpolate(ce->name, Ep_name[j], &start[j],
277
 
                                           &end[j], (float) ce->p[j].stdy,
278
 
                                           t, dur));
279
 
                }
280
 
 
281
 
                while (tf0 == ntf0) {
282
 
                    tf0 = 0;
283
 
                    f0s = f0e;
284
 
                    ntf0 = (unsigned) *f0++;
285
 
                    f0e = *f0++;
286
 
#if 0
287
 
                    fprintf(stderr, "f0 %5.1f %gs %5.1f\n", f0s,
288
 
                            1.0 * ntf0 * samples_frame / samp_rate, f0e);
289
 
#endif
290
 
                }
291
 
 
292
 
                /* interpolate the f0 value */
293
 
                F0Hz = linear(f0s, f0e, tf0, ntf0);
294
 
 
295
 
                if (rsynth->flags & RSYNTH_F0TRACE) {
296
 
                    printf(" %5.1fHz", F0Hz);
297
 
                }
298
 
 
299
 
                /* Now call the synth for each frame */
300
 
                CHECK_SPACING(ep[f2], ep[f1]);
301
 
                CHECK_SPACING(ep[f3], ep[f2]);
302
 
                CHECK_SPACING(rsynth->speaker->F4hz, ep[f3]);
303
 
 
304
 
                samp += rsynth_frame(rsynth, F0Hz, ep, ce->name);
305
 
 
306
 
                if (rsynth->parm_file) {
307
 
                    fprintf(rsynth->parm_file, " %6.4g %6.4g",
308
 
                            F0Hz, 10 * log10(peak));
309
 
                    for (j = 0; j < nEparm; j++)
310
 
                        fprintf(rsynth->parm_file, " %6.4g", ep[j]);
311
 
                    fprintf(rsynth->parm_file, "\n");
312
 
                }
313
 
            }
314
 
            if (rsynth->parm_file) {
315
 
                int j;
316
 
                fprintf(rsynth->parm_file, "#%6s %6s", "", "");
317
 
                for (j = 0; j < nEparm; j++)
318
 
                    fprintf(rsynth->parm_file, " %6.4g", end[j].v);
319
 
                fprintf(rsynth->parm_file, "\n");
320
 
                fprintf(rsynth->parm_file, "#%6s %6s", "", "");
321
 
                for (j = 0; j < nEparm; j++)
322
 
                    fprintf(rsynth->parm_file, " %6ld", end[j].t);
323
 
                fprintf(rsynth->parm_file, "\n");
324
 
            }
325
 
        }
326
 
        le = ce;
327
 
    }
328
 
    if (rsynth->flags & (RSYNTH_ETRACE | RSYNTH_F0TRACE)) {
329
 
        printf("\n");
330
 
    }
331
 
    return samp;
332
 
}