annotate decoders/timidity/resample.c @ 474:c66080364dff

Most decoders now report total sample play time, now. Technically, this breaks binary compatibility with the 1.0 branch, since it extends the Sound_Sample struct, but most (all?) programs are just passing pointers allocated by SDL_sound around, and might be okay. Source-level compatibility is not broken...yet! :) --ryan. -------- Original Message -------- Subject: SDL_sound patch: Finding total length of time of sound file. Date: Sun, 26 Jan 2003 09:31:17 -0800 (PST) Hi Ryan, I am working with Eric Wing and helping him modify SDL_sound. AS part of our efforts in improving and enhancing SDL_sound, we like to submit this patch. We modified the codecs to find the total time of a sound file. Below is the explanation of the patch. The patch is appended as an attachment to this email. * MOTIVATION: We needed the ability to get the total play time of a sample (And we noticed that we're not the only ones). Since SDL_sound blocks direct access to the specific decoders, there is no way for a user to know this information short of decoding the whole thing. Because of this, we believe this will be a useful addition, even though the accuracy may not be perfect (subject to each decoder) or the information may not always be available. * CONTRIBUTORS: Wesley Leong (modified the majority of the codecs and verified the results) Eric Wing (showed everyone how to do modify codec, modified mikmod) Wang Lam (modified a handful of codecs, researched into specs and int overflow) Ahilan Anantha (modified a few codecs and helped with integer math) * GENERAL ISSUES: We chose the value to be milliseconds as an Sint32. Milliseconds because that's what Sound_Seek takes as a parameter and -1 to allow for instances/codecs where the value could not be determined. We are not sure if this is the final convention you want, so we are willing to work with you on this. We also expect the total_time field to be set on open and never again modified by SDL_sound. Users may access it directly much like the sample buffer and buffer_size. We thought about recomputing the time on DecodeAll, but since users may seek or decode small chunks first, not all the data may be there. So this is better done by the user. This may be good information to document. Currently, all the main codecs are implemented except for QuickTime.
author Ryan C. Gordon <icculus@icculus.org>
date Sat, 08 May 2004 08:19:50 +0000
parents a73c51c12452
children f33471c47efe
rev   line source
199
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
1 /*
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
2
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
3 TiMidity -- Experimental MIDI to WAVE converter
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
4 Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
5
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
6 This program is free software; you can redistribute it and/or modify
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
7 it under the terms of the GNU General Public License as published by
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
8 the Free Software Foundation; either version 2 of the License, or
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
9 (at your option) any later version.
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
10
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
11 This program is distributed in the hope that it will be useful,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
14 GNU General Public License for more details.
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
15
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
17 along with this program; if not, write to the Free Software
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
19
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
20 resample.c
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
21 */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
22
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
23 #if HAVE_CONFIG_H
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
24 # include <config.h>
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
25 #endif
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
26
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
27 #include <math.h>
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
28 #include <stdio.h>
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
29 #include <stdlib.h>
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
30
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
31 #include "SDL_sound.h"
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
32
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
33 #define __SDL_SOUND_INTERNAL__
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
34 #include "SDL_sound_internal.h"
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
35
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
36 #include "timidity.h"
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
37 #include "options.h"
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
38 #include "common.h"
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
39 #include "instrum.h"
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
40 #include "playmidi.h"
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
41 #include "tables.h"
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
42 #include "resample.h"
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
43
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
44 /*************** resampling with fixed increment *****************/
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
45
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
46 static sample_t *rs_plain(MidiSong *song, int v, Sint32 *countptr)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
47 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
48
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
49 /* Play sample until end, then free the voice. */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
50
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
51 sample_t v1, v2;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
52 Voice
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
53 *vp=&(song->voice[v]);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
54 sample_t
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
55 *dest=song->resample_buffer,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
56 *src=vp->sample->data;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
57 Sint32
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
58 ofs=vp->sample_offset,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
59 incr=vp->sample_increment,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
60 le=vp->sample->data_length,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
61 count=*countptr;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
62 Sint32 i;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
63
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
64 if (incr<0) incr = -incr; /* In case we're coming out of a bidir loop */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
65
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
66 /* Precalc how many times we should go through the loop.
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
67 NOTE: Assumes that incr > 0 and that ofs <= le */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
68 i = (le - ofs) / incr + 1;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
69
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
70 if (i > count)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
71 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
72 i = count;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
73 count = 0;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
74 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
75 else count -= i;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
76
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
77 while (i--)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
78 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
79 v1 = src[ofs >> FRACTION_BITS];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
80 v2 = src[(ofs >> FRACTION_BITS)+1];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
81 *dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
82 ofs += incr;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
83 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
84
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
85 if (ofs >= le)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
86 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
87 if (ofs == le)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
88 *dest++ = src[ofs >> FRACTION_BITS];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
89 vp->status=VOICE_FREE;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
90 *countptr-=count+1;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
91 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
92
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
93 vp->sample_offset=ofs; /* Update offset */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
94 return song->resample_buffer;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
95 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
96
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
97 static sample_t *rs_loop(MidiSong *song, Voice *vp, Sint32 count)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
98 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
99
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
100 /* Play sample until end-of-loop, skip back and continue. */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
101
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
102 sample_t v1, v2;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
103 Sint32
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
104 ofs=vp->sample_offset,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
105 incr=vp->sample_increment,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
106 le=vp->sample->loop_end,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
107 ll=le - vp->sample->loop_start;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
108 sample_t
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
109 *dest=song->resample_buffer,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
110 *src=vp->sample->data;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
111 Sint32 i;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
112
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
113 while (count)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
114 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
115 if (ofs >= le)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
116 /* NOTE: Assumes that ll > incr and that incr > 0. */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
117 ofs -= ll;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
118 /* Precalc how many times we should go through the loop */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
119 i = (le - ofs) / incr + 1;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
120 if (i > count)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
121 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
122 i = count;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
123 count = 0;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
124 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
125 else count -= i;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
126 while (i--)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
127 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
128 v1 = src[ofs >> FRACTION_BITS];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
129 v2 = src[(ofs >> FRACTION_BITS)+1];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
130 *dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
131 ofs += incr;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
132 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
133 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
134
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
135 vp->sample_offset=ofs; /* Update offset */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
136 return song->resample_buffer;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
137 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
138
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
139 static sample_t *rs_bidir(MidiSong *song, Voice *vp, Sint32 count)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
140 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
141 sample_t v1, v2;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
142 Sint32
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
143 ofs=vp->sample_offset,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
144 incr=vp->sample_increment,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
145 le=vp->sample->loop_end,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
146 ls=vp->sample->loop_start;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
147 sample_t
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
148 *dest=song->resample_buffer,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
149 *src=vp->sample->data;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
150 Sint32
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
151 le2 = le<<1,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
152 ls2 = ls<<1,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
153 i;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
154 /* Play normally until inside the loop region */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
155
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
156 if (ofs <= ls)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
157 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
158 /* NOTE: Assumes that incr > 0, which is NOT always the case
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
159 when doing bidirectional looping. I have yet to see a case
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
160 where both ofs <= ls AND incr < 0, however. */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
161 i = (ls - ofs) / incr + 1;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
162 if (i > count)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
163 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
164 i = count;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
165 count = 0;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
166 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
167 else count -= i;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
168 while (i--)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
169 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
170 v1 = src[ofs >> FRACTION_BITS];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
171 v2 = src[(ofs >> FRACTION_BITS)+1];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
172 *dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
173 ofs += incr;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
174 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
175 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
176
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
177 /* Then do the bidirectional looping */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
178
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
179 while(count)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
180 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
181 /* Precalc how many times we should go through the loop */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
182 i = ((incr > 0 ? le : ls) - ofs) / incr + 1;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
183 if (i > count)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
184 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
185 i = count;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
186 count = 0;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
187 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
188 else count -= i;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
189 while (i--)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
190 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
191 v1 = src[ofs >> FRACTION_BITS];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
192 v2 = src[(ofs >> FRACTION_BITS)+1];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
193 *dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
194 ofs += incr;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
195 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
196 if (ofs>=le)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
197 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
198 /* fold the overshoot back in */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
199 ofs = le2 - ofs;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
200 incr *= -1;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
201 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
202 else if (ofs <= ls)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
203 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
204 ofs = ls2 - ofs;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
205 incr *= -1;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
206 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
207 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
208
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
209 vp->sample_increment=incr;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
210 vp->sample_offset=ofs; /* Update offset */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
211 return song->resample_buffer;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
212 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
213
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
214 /*********************** vibrato versions ***************************/
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
215
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
216 /* We only need to compute one half of the vibrato sine cycle */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
217 static int vib_phase_to_inc_ptr(int phase)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
218 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
219 if (phase < VIBRATO_SAMPLE_INCREMENTS/2)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
220 return VIBRATO_SAMPLE_INCREMENTS/2-1-phase;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
221 else if (phase >= 3*VIBRATO_SAMPLE_INCREMENTS/2)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
222 return 5*VIBRATO_SAMPLE_INCREMENTS/2-1-phase;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
223 else
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
224 return phase-VIBRATO_SAMPLE_INCREMENTS/2;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
225 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
226
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
227 static Sint32 update_vibrato(MidiSong *song, Voice *vp, int sign)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
228 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
229 Sint32 depth;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
230 int phase, pb;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
231 double a;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
232
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
233 if (vp->vibrato_phase++ >= 2*VIBRATO_SAMPLE_INCREMENTS-1)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
234 vp->vibrato_phase=0;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
235 phase=vib_phase_to_inc_ptr(vp->vibrato_phase);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
236
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
237 if (vp->vibrato_sample_increment[phase])
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
238 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
239 if (sign)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
240 return -vp->vibrato_sample_increment[phase];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
241 else
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
242 return vp->vibrato_sample_increment[phase];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
243 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
244
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
245 /* Need to compute this sample increment. */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
246
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
247 depth=vp->sample->vibrato_depth<<7;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
248
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
249 if (vp->vibrato_sweep)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
250 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
251 /* Need to update sweep */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
252 vp->vibrato_sweep_position += vp->vibrato_sweep;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
253 if (vp->vibrato_sweep_position >= (1<<SWEEP_SHIFT))
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
254 vp->vibrato_sweep=0;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
255 else
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
256 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
257 /* Adjust depth */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
258 depth *= vp->vibrato_sweep_position;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
259 depth >>= SWEEP_SHIFT;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
260 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
261 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
262
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
263 a = FSCALE(((double)(vp->sample->sample_rate) *
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
264 (double)(vp->frequency)) /
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
265 ((double)(vp->sample->root_freq) *
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
266 (double)(song->rate)),
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
267 FRACTION_BITS);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
268
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
269 pb=(int)((sine(vp->vibrato_phase *
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
270 (SINE_CYCLE_LENGTH/(2*VIBRATO_SAMPLE_INCREMENTS)))
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
271 * (double)(depth) * VIBRATO_AMPLITUDE_TUNING));
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
272
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
273 if (pb<0)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
274 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
275 pb=-pb;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
276 a /= bend_fine[(pb>>5) & 0xFF] * bend_coarse[pb>>13];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
277 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
278 else
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
279 a *= bend_fine[(pb>>5) & 0xFF] * bend_coarse[pb>>13];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
280
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
281 /* If the sweep's over, we can store the newly computed sample_increment */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
282 if (!vp->vibrato_sweep)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
283 vp->vibrato_sample_increment[phase]=(Sint32) a;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
284
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
285 if (sign)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
286 a = -a; /* need to preserve the loop direction */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
287
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
288 return (Sint32) a;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
289 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
290
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
291 static sample_t *rs_vib_plain(MidiSong *song, int v, Sint32 *countptr)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
292 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
293
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
294 /* Play sample until end, then free the voice. */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
295
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
296 sample_t v1, v2;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
297 Voice *vp=&(song->voice[v]);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
298 sample_t
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
299 *dest=song->resample_buffer,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
300 *src=vp->sample->data;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
301 Sint32
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
302 le=vp->sample->data_length,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
303 ofs=vp->sample_offset,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
304 incr=vp->sample_increment,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
305 count=*countptr;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
306 int
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
307 cc=vp->vibrato_control_counter;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
308
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
309 /* This has never been tested */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
310
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
311 if (incr<0) incr = -incr; /* In case we're coming out of a bidir loop */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
312
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
313 while (count--)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
314 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
315 if (!cc--)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
316 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
317 cc=vp->vibrato_control_ratio;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
318 incr=update_vibrato(song, vp, 0);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
319 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
320 v1 = src[ofs >> FRACTION_BITS];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
321 v2 = src[(ofs >> FRACTION_BITS)+1];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
322 *dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
323 ofs += incr;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
324 if (ofs >= le)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
325 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
326 if (ofs == le)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
327 *dest++ = src[ofs >> FRACTION_BITS];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
328 vp->status=VOICE_FREE;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
329 *countptr-=count+1;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
330 break;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
331 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
332 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
333
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
334 vp->vibrato_control_counter=cc;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
335 vp->sample_increment=incr;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
336 vp->sample_offset=ofs; /* Update offset */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
337 return song->resample_buffer;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
338 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
339
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
340 static sample_t *rs_vib_loop(MidiSong *song, Voice *vp, Sint32 count)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
341 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
342
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
343 /* Play sample until end-of-loop, skip back and continue. */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
344
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
345 sample_t v1, v2;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
346 Sint32
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
347 ofs=vp->sample_offset,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
348 incr=vp->sample_increment,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
349 le=vp->sample->loop_end,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
350 ll=le - vp->sample->loop_start;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
351 sample_t
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
352 *dest=song->resample_buffer,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
353 *src=vp->sample->data;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
354 int
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
355 cc=vp->vibrato_control_counter;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
356 Sint32 i;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
357 int
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
358 vibflag=0;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
359
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
360 while (count)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
361 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
362 /* Hopefully the loop is longer than an increment */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
363 if(ofs >= le)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
364 ofs -= ll;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
365 /* Precalc how many times to go through the loop, taking
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
366 the vibrato control ratio into account this time. */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
367 i = (le - ofs) / incr + 1;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
368 if(i > count) i = count;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
369 if(i > cc)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
370 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
371 i = cc;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
372 vibflag = 1;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
373 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
374 else cc -= i;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
375 count -= i;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
376 while(i--)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
377 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
378 v1 = src[ofs >> FRACTION_BITS];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
379 v2 = src[(ofs >> FRACTION_BITS)+1];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
380 *dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
381 ofs += incr;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
382 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
383 if(vibflag)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
384 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
385 cc = vp->vibrato_control_ratio;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
386 incr = update_vibrato(song, vp, 0);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
387 vibflag = 0;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
388 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
389 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
390
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
391 vp->vibrato_control_counter=cc;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
392 vp->sample_increment=incr;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
393 vp->sample_offset=ofs; /* Update offset */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
394 return song->resample_buffer;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
395 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
396
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
397 static sample_t *rs_vib_bidir(MidiSong *song, Voice *vp, Sint32 count)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
398 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
399 sample_t v1, v2;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
400 Sint32
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
401 ofs=vp->sample_offset,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
402 incr=vp->sample_increment,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
403 le=vp->sample->loop_end,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
404 ls=vp->sample->loop_start;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
405 sample_t
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
406 *dest=song->resample_buffer,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
407 *src=vp->sample->data;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
408 int
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
409 cc=vp->vibrato_control_counter;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
410 Sint32
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
411 le2=le<<1,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
412 ls2=ls<<1,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
413 i;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
414 int
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
415 vibflag = 0;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
416
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
417 /* Play normally until inside the loop region */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
418 while (count && (ofs <= ls))
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
419 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
420 i = (ls - ofs) / incr + 1;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
421 if (i > count) i = count;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
422 if (i > cc)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
423 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
424 i = cc;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
425 vibflag = 1;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
426 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
427 else cc -= i;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
428 count -= i;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
429 while (i--)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
430 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
431 v1 = src[ofs >> FRACTION_BITS];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
432 v2 = src[(ofs >> FRACTION_BITS)+1];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
433 *dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
434 ofs += incr;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
435 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
436 if (vibflag)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
437 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
438 cc = vp->vibrato_control_ratio;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
439 incr = update_vibrato(song, vp, 0);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
440 vibflag = 0;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
441 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
442 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
443
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
444 /* Then do the bidirectional looping */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
445
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
446 while (count)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
447 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
448 /* Precalc how many times we should go through the loop */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
449 i = ((incr > 0 ? le : ls) - ofs) / incr + 1;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
450 if(i > count) i = count;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
451 if(i > cc)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
452 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
453 i = cc;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
454 vibflag = 1;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
455 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
456 else cc -= i;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
457 count -= i;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
458 while (i--)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
459 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
460 v1 = src[ofs >> FRACTION_BITS];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
461 v2 = src[(ofs >> FRACTION_BITS)+1];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
462 *dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
463 ofs += incr;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
464 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
465 if (vibflag)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
466 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
467 cc = vp->vibrato_control_ratio;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
468 incr = update_vibrato(song, vp, (incr < 0));
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
469 vibflag = 0;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
470 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
471 if (ofs >= le)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
472 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
473 /* fold the overshoot back in */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
474 ofs = le2 - ofs;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
475 incr *= -1;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
476 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
477 else if (ofs <= ls)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
478 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
479 ofs = ls2 - ofs;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
480 incr *= -1;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
481 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
482 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
483
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
484 vp->vibrato_control_counter=cc;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
485 vp->sample_increment=incr;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
486 vp->sample_offset=ofs; /* Update offset */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
487 return song->resample_buffer;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
488 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
489
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
490 sample_t *resample_voice(MidiSong *song, int v, Sint32 *countptr)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
491 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
492 Sint32 ofs;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
493 Uint8 modes;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
494 Voice *vp=&(song->voice[v]);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
495
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
496 if (!(vp->sample->sample_rate))
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
497 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
498 /* Pre-resampled data -- just update the offset and check if
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
499 we're out of data. */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
500 ofs=vp->sample_offset >> FRACTION_BITS; /* Kind of silly to use
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
501 FRACTION_BITS here... */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
502 if (*countptr >= (vp->sample->data_length>>FRACTION_BITS) - ofs)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
503 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
504 /* Note finished. Free the voice. */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
505 vp->status = VOICE_FREE;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
506
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
507 /* Let the caller know how much data we had left */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
508 *countptr = (vp->sample->data_length>>FRACTION_BITS) - ofs;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
509 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
510 else
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
511 vp->sample_offset += *countptr << FRACTION_BITS;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
512
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
513 return vp->sample->data+ofs;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
514 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
515
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
516 /* Need to resample. Use the proper function. */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
517 modes=vp->sample->modes;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
518
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
519 if (vp->vibrato_control_ratio)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
520 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
521 if ((modes & MODES_LOOPING) &&
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
522 ((modes & MODES_ENVELOPE) ||
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
523 (vp->status==VOICE_ON || vp->status==VOICE_SUSTAINED)))
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
524 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
525 if (modes & MODES_PINGPONG)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
526 return rs_vib_bidir(song, vp, *countptr);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
527 else
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
528 return rs_vib_loop(song, vp, *countptr);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
529 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
530 else
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
531 return rs_vib_plain(song, v, countptr);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
532 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
533 else
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
534 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
535 if ((modes & MODES_LOOPING) &&
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
536 ((modes & MODES_ENVELOPE) ||
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
537 (vp->status==VOICE_ON || vp->status==VOICE_SUSTAINED)))
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
538 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
539 if (modes & MODES_PINGPONG)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
540 return rs_bidir(song, vp, *countptr);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
541 else
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
542 return rs_loop(song, vp, *countptr);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
543 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
544 else
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
545 return rs_plain(song, v, countptr);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
546 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
547 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
548
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
549 void pre_resample(MidiSong *song, Sample *sp)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
550 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
551 double a, xdiff;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
552 Sint32 incr, ofs, newlen, count;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
553 Sint16 *newdata, *dest, *src = (Sint16 *) sp->data;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
554 Sint16 v1, v2, v3, v4, *vptr;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
555 #ifdef DEBUG_CHATTER
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
556 static const char note_name[12][3] =
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
557 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
558 "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
559 };
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
560 #endif
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
561
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
562 SNDDBG((" * pre-resampling for note %d (%s%d)\n",
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
563 sp->note_to_use,
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
564 note_name[sp->note_to_use % 12], (sp->note_to_use & 0x7F) / 12));
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
565
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
566 a = ((double) (sp->sample_rate) * freq_table[(int) (sp->note_to_use)]) /
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
567 ((double) (sp->root_freq) * song->rate);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
568 newlen = (Sint32)(sp->data_length / a);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
569 dest = newdata = safe_malloc(newlen >> (FRACTION_BITS - 1));
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
570
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
571 count = (newlen >> FRACTION_BITS) - 1;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
572 ofs = incr = (sp->data_length - (1 << FRACTION_BITS)) / count;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
573
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
574 if (--count)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
575 *dest++ = src[0];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
576
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
577 /* Since we're pre-processing and this doesn't have to be done in
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
578 real-time, we go ahead and do the full sliding cubic interpolation. */
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
579 while (--count)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
580 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
581 vptr = src + (ofs >> FRACTION_BITS);
254
a73c51c12452 Memory access fixes.
Ryan C. Gordon <icculus@icculus.org>
parents: 199
diff changeset
582 /*
a73c51c12452 Memory access fixes.
Ryan C. Gordon <icculus@icculus.org>
parents: 199
diff changeset
583 * Electric Fence to the rescue: Accessing *(vptr - 1) is not a
a73c51c12452 Memory access fixes.
Ryan C. Gordon <icculus@icculus.org>
parents: 199
diff changeset
584 * good thing to do when vptr <= src. (TiMidity++ has a similar
a73c51c12452 Memory access fixes.
Ryan C. Gordon <icculus@icculus.org>
parents: 199
diff changeset
585 * safe-guard here.)
a73c51c12452 Memory access fixes.
Ryan C. Gordon <icculus@icculus.org>
parents: 199
diff changeset
586 */
a73c51c12452 Memory access fixes.
Ryan C. Gordon <icculus@icculus.org>
parents: 199
diff changeset
587 v1 = (vptr > src) ? *(vptr - 1) : 0;
199
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
588 v2 = *vptr;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
589 v3 = *(vptr + 1);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
590 v4 = *(vptr + 2);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
591 xdiff = FSCALENEG(ofs & FRACTION_MASK, FRACTION_BITS);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
592 *dest++ = (Sint16)(v2 + (xdiff / 6.0) * (-2 * v1 - 3 * v2 + 6 * v3 - v4 +
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
593 xdiff * (3 * (v1 - 2 * v2 + v3) + xdiff * (-v1 + 3 * (v2 - v3) + v4))));
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
594 ofs += incr;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
595 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
596
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
597 if (ofs & FRACTION_MASK)
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
598 {
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
599 v1 = src[ofs >> FRACTION_BITS];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
600 v2 = src[(ofs >> FRACTION_BITS) + 1];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
601 *dest++ = v1 + (((v2 - v1) * (ofs & FRACTION_MASK)) >> FRACTION_BITS);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
602 }
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
603 else
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
604 *dest++ = src[ofs >> FRACTION_BITS];
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
605
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
606 sp->data_length = newlen;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
607 sp->loop_start = (Sint32)(sp->loop_start / a);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
608 sp->loop_end = (Sint32)(sp->loop_end / a);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
609 free(sp->data);
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
610 sp->data = (sample_t *) newdata;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
611 sp->sample_rate = 0;
2d887640d300 Initial add.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
612 }