A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/* MikMod sound library
2 (c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS
3 for complete list.
4
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of
8 the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18 02111-1307, USA.
19*/
20
21/*==============================================================================
22
23 $Id$
24
25 Utility functions for the module loader
26
27==============================================================================*/
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#ifdef HAVE_MEMORY_H
34#include <memory.h>
35#endif
36#include <string.h>
37
38#include "mikmod_internals.h"
39
40#ifdef SUNOS
41extern int fprintf(FILE *, const char *, ...);
42#endif
43
44/*========== Shared tracker identifiers */
45
46const CHAR *STM_Signatures[STM_NTRACKERS] = {
47 "!Scream!",
48 "BMOD2STM",
49 "WUZAMOD!"
50};
51
52const CHAR *STM_Version[STM_NTRACKERS] = {
53 "Screamtracker 2",
54 "Converted by MOD2STM (STM format)",
55 "Wuzamod (STM format)"
56};
57
58/*========== Shared loader variables */
59
60SBYTE remap[UF_MAXCHAN]; /* for removing empty channels */
61UBYTE* poslookup=NULL; /* lookup table for pattern jumps after blank
62 pattern removal */
63UWORD poslookupcnt;
64UWORD* origpositions=NULL;
65
66int filters; /* resonant filters in use */
67UBYTE activemacro; /* active midi macro number for Sxx,xx<80h */
68UBYTE filtermacros[UF_MAXMACRO]; /* midi macro settings */
69FILTER filtersettings[UF_MAXFILTER]; /* computed filter settings */
70
71/*========== Linear periods stuff */
72
73int* noteindex=NULL; /* remap value for linear period modules */
74static unsigned noteindexcount=0;
75
76int *AllocLinear(void)
77{
78 if(of.numsmp>noteindexcount) {
79 noteindexcount=of.numsmp;
80 noteindex=(int*)MikMod_realloc(noteindex,noteindexcount*sizeof(int));
81 }
82 return noteindex;
83}
84
85void FreeLinear(void)
86{
87 MikMod_free(noteindex);
88 noteindex=NULL;
89 noteindexcount=0;
90}
91
92int speed_to_finetune(ULONG speed,int sample)
93{
94 ULONG ctmp=0,tmp,note=1,ft=0;
95
96 speed>>=1;
97 while((tmp=getfrequency(of.flags,getlinearperiod(note<<1,0)))<speed) {
98 ctmp=tmp;
99 note++;
100 }
101
102 if(tmp!=speed) {
103 if((tmp-speed)<(speed-ctmp))
104 while(tmp>speed)
105 tmp=getfrequency(of.flags,getlinearperiod(note<<1,--ft));
106 else {
107 note--;
108 while(ctmp<speed)
109 ctmp=getfrequency(of.flags,getlinearperiod(note<<1,++ft));
110 }
111 }
112
113 noteindex[sample]=note-4*OCTAVE;
114 return ft;
115}
116
117/*========== Order stuff */
118
119/* handles S3M and IT orders */
120void S3MIT_CreateOrders(int curious)
121{
122 int t;
123
124 of.numpos = 0;
125 memset(of.positions,0,poslookupcnt*sizeof(UWORD));
126 memset(poslookup,-1,256);
127 for(t=0;t<poslookupcnt;t++) {
128 int order=origpositions[t];
129 if(order==255) order=LAST_PATTERN;
130 of.positions[of.numpos]=order;
131 poslookup[t]=of.numpos; /* bug fix for freaky S3Ms / ITs */
132 if(origpositions[t]<254) of.numpos++;
133 else
134 /* end of song special order */
135 if((order==LAST_PATTERN)&&(!(curious--))) break;
136 }
137}
138
139/*========== Effect stuff */
140
141/* handles S3M and IT effects */
142void S3MIT_ProcessCmd(UBYTE cmd, UBYTE inf, unsigned int flags)
143{
144 UBYTE lo = inf&0xF;
145 /* process S3M / IT specific command structure */
146
147 if(cmd!=255) {
148 switch(cmd) {
149 case 1: /* Axx set speed to xx */
150 UniEffect(UNI_S3MEFFECTA,inf);
151 break;
152 case 2: /* Bxx position jump */
153 if (inf<poslookupcnt) {
154 /* switch to curious mode if necessary, for example
155 sympex.it, deep joy.it */
156 if(((SBYTE)poslookup[inf]<0)&&(origpositions[inf]!=255))
157 S3MIT_CreateOrders(1);
158
159 if(!((SBYTE)poslookup[inf]<0))
160 UniPTEffect(0xb,poslookup[inf]);
161 }
162 break;
163 case 3: /* Cxx patternbreak to row xx */
164 if ((flags & S3MIT_OLDSTYLE) && !(flags & S3MIT_IT))
165 UniPTEffect(0xd,(inf>>4)*10+(inf&0xf));
166 else
167 UniPTEffect(0xd,inf);
168 break;
169 case 4: /* Dxy volumeslide */
170 UniEffect(UNI_S3MEFFECTD,inf);
171 break;
172 case 5: /* Exy toneslide down */
173 UniEffect(UNI_S3MEFFECTE,inf);
174 break;
175 case 6: /* Fxy toneslide up */
176 UniEffect(UNI_S3MEFFECTF,inf);
177 break;
178 case 7: /* Gxx Tone portamento, speed xx */
179 if (flags & S3MIT_OLDSTYLE)
180 UniPTEffect(0x3,inf);
181 else
182 UniEffect(UNI_ITEFFECTG,inf);
183 break;
184 case 8: /* Hxy vibrato */
185 if (flags & S3MIT_OLDSTYLE) {
186 if (flags & S3MIT_IT)
187 UniEffect(UNI_ITEFFECTH_OLD,inf);
188 else
189 UniEffect(UNI_S3MEFFECTH,inf);
190 } else
191 UniEffect(UNI_ITEFFECTH,inf);
192 break;
193 case 9: /* Ixy tremor, ontime x, offtime y */
194 if (flags & S3MIT_OLDSTYLE)
195 UniEffect(UNI_S3MEFFECTI,inf);
196 else
197 UniEffect(UNI_ITEFFECTI,inf);
198 break;
199 case 0xa: /* Jxy arpeggio */
200 UniPTEffect(0x0,inf);
201 break;
202 case 0xb: /* Kxy Dual command H00 & Dxy */
203 if (flags & S3MIT_OLDSTYLE) {
204 if (flags & S3MIT_IT)
205 UniEffect(UNI_ITEFFECTH_OLD,0);
206 else
207 UniEffect(UNI_S3MEFFECTH,0);
208 } else
209 UniEffect(UNI_ITEFFECTH,0);
210 UniEffect(UNI_S3MEFFECTD,inf);
211 break;
212 case 0xc: /* Lxy Dual command G00 & Dxy */
213 if (flags & S3MIT_OLDSTYLE)
214 UniPTEffect(0x3,0);
215 else
216 UniEffect(UNI_ITEFFECTG,0);
217 UniEffect(UNI_S3MEFFECTD,inf);
218 break;
219 case 0xd: /* Mxx Set Channel Volume */
220 /* Ignore invalid values > 64. */
221 if (inf <= 0x40)
222 UniEffect(UNI_ITEFFECTM,inf);
223 break;
224 case 0xe: /* Nxy Slide Channel Volume */
225 UniEffect(UNI_ITEFFECTN,inf);
226 break;
227 case 0xf: /* Oxx set sampleoffset xx00h */
228 UniPTEffect(0x9,inf);
229 break;
230 case 0x10: /* Pxy Slide Panning Commands */
231 UniEffect(UNI_ITEFFECTP,inf);
232 break;
233 case 0x11: /* Qxy Retrig (+volumeslide) */
234 UniWriteByte(UNI_S3MEFFECTQ);
235 if(inf && !lo && !(flags & S3MIT_OLDSTYLE))
236 UniWriteByte(1);
237 else
238 UniWriteByte(inf);
239 break;
240 case 0x12: /* Rxy tremolo speed x, depth y */
241 UniEffect(UNI_S3MEFFECTR,inf);
242 break;
243 case 0x13: /* Sxx special commands */
244 if (inf>=0xf0) {
245 /* change resonant filter settings if necessary */
246 if((filters)&&((inf&0xf)!=activemacro)) {
247 activemacro=inf&0xf;
248 for(inf=0;inf<0x80;inf++)
249 filtersettings[inf].filter=filtermacros[activemacro];
250 }
251 } else {
252 /* Scream Tracker does not have samples larger than
253 64 Kb, thus doesn't need the SAx effect */
254 if ((flags & S3MIT_SCREAM) && ((inf & 0xf0) == 0xa0))
255 break;
256
257 UniEffect(UNI_ITEFFECTS0,inf);
258 }
259 break;
260 case 0x14: /* Txx tempo */
261 if(inf>=0x20)
262 UniEffect(UNI_S3MEFFECTT,inf);
263 else {
264 if(!(flags & S3MIT_OLDSTYLE))
265 /* IT Tempo slide */
266 UniEffect(UNI_ITEFFECTT,inf);
267 }
268 break;
269 case 0x15: /* Uxy Fine Vibrato speed x, depth y */
270 if(flags & S3MIT_OLDSTYLE) {
271 if (flags & S3MIT_IT)
272 UniEffect(UNI_ITEFFECTU_OLD,inf);
273 else
274 UniEffect(UNI_S3MEFFECTU,inf);
275 } else
276 UniEffect(UNI_ITEFFECTU,inf);
277 break;
278 case 0x16: /* Vxx Set Global Volume */
279 UniEffect(UNI_XMEFFECTG,inf);
280 break;
281 case 0x17: /* Wxy Global Volume Slide */
282 UniEffect(UNI_ITEFFECTW,inf);
283 break;
284 case 0x18: /* Xxx amiga command 8xx */
285 if(flags & S3MIT_OLDSTYLE) {
286 if(inf>128)
287 UniEffect(UNI_ITEFFECTS0,0x91); /* surround */
288 else
289 UniPTEffect(0x8,(inf==128)?255:(inf<<1));
290 } else
291 UniPTEffect(0x8,inf);
292 break;
293 case 0x19: /* Yxy Panbrello speed x, depth y */
294 UniEffect(UNI_ITEFFECTY,inf);
295 break;
296 case 0x1a: /* Zxx midi/resonant filters */
297 if(filtersettings[inf].filter) {
298 UniWriteByte(UNI_ITEFFECTZ);
299 UniWriteByte(filtersettings[inf].filter);
300 UniWriteByte(filtersettings[inf].inf);
301 }
302 break;
303 }
304 }
305}
306
307/*========== Unitrk stuff */
308
309/* Generic effect writing routine */
310void UniEffect(UWORD eff,UWORD dat)
311{
312 if((!eff)||(eff>=UNI_LAST)) return;
313
314 UniWriteByte(eff);
315 if(unioperands[eff]==2)
316 UniWriteWord(dat);
317 else
318 UniWriteByte(dat);
319}
320
321/* Appends UNI_PTEFFECTX opcode to the unitrk stream. */
322void UniPTEffect(UBYTE eff, UBYTE dat)
323{
324#ifdef MIKMOD_DEBUG
325 if (eff>=0x10)
326 fprintf(stderr,"UniPTEffect called with incorrect eff value %d\n",eff);
327 else
328#endif
329 if((eff)||(dat)||(of.flags&UF_ARPMEM)) UniEffect(UNI_PTEFFECT0+eff,dat);
330}
331
332/* Appends UNI_VOLEFFECT + effect/dat to unistream. */
333void UniVolEffect(UWORD eff,UBYTE dat)
334{
335 if((eff)||(dat)) { /* don't write empty effect */
336 UniWriteByte(UNI_VOLEFFECTS);
337 UniWriteByte(eff);UniWriteByte(dat);
338 }
339}
340
341/* ex:set ts=4: */