1 /*
2 ** music_dumb.cpp
3 ** Alternative module player, using a modified DUMB for decoding.
4 ** Based on the Foobar2000 component foo_dumb, version 0.9.8.4.
5 **
6 **---------------------------------------------------------------------------
7 ** Copyright 2008 Randy Heit
8 ** All rights reserved.
9 **
10 ** Redistribution and use in source and binary forms, with or without
11 ** modification, are permitted provided that the following conditions
12 ** are met:
13 **
14 ** 1. Redistributions of source code must retain the above copyright
15 **    notice, this list of conditions and the following disclaimer.
16 ** 2. Redistributions in binary form must reproduce the above copyright
17 **    notice, this list of conditions and the following disclaimer in the
18 **    documentation and/or other materials provided with the distribution.
19 ** 3. The name of the author may not be used to endorse or promote products
20 **    derived from this software without specific prior written permission.
21 **
22 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 **---------------------------------------------------------------------------
33 **
34 */
35 
36 // HEADER FILES ------------------------------------------------------------
37 
38 #include <math.h>
39 #include <mutex>
40 #include <string>
41 #include <stdint.h>
42 #include "streamsource.h"
43 
44 
45 #undef CDECL	// w32api's windef.h defines this
46 #include "../dumb/include/dumb.h"
47 #include "../dumb/include/internal/it.h"
48 #include "zmusic/m_swap.h"
49 #include "zmusic/mididefs.h"
50 #include "zmusic/midiconfig.h"
51 #include "fileio.h"
52 
53 // MACROS ------------------------------------------------------------------
54 
55 // TYPES -------------------------------------------------------------------
56 
57 DumbConfig dumbConfig;
58 
59 class DumbSong : public StreamSource
60 {
61 public:
62 	DumbSong(DUH *myduh, int samplerate);
63 	~DumbSong();
64 	//bool SetPosition(int ms);
65 	bool SetSubsong(int subsong) override;
66 	bool Start() override;
67 	SoundStreamInfo GetFormat() override;
68 	void ChangeSettingNum(const char* setting, double val) override;
69 	std::string GetStats() override;
70 
71 	std::string Codec;
72 	std::string TrackerVersion;
73 	std::string FormatVersion;
74 	int NumChannels;
75 	int NumPatterns;
76 	int NumOrders;
77 	float MasterVolume;
78 
79 protected:
80 	int srate, interp, volramp;
81 	int start_order;
82 	double delta;
83 	double length;
84 	bool eof;
85 	bool started = false;
86 	size_t written;
87 	DUH *duh;
88 	DUH_SIGRENDERER *sr;
89 
90 	bool open2(long pos);
91 	long render(double volume, double delta, long samples, sample_t **buffer);
92 	int decode_run(void *buffer, unsigned int size);
93 	bool GetData(void *buffer, size_t len) override;
94 
95 };
96 
97 #pragma pack(1)
98 
99 #if defined(__GNUC__)
100 #define FORCE_PACKED __attribute__((__packed__))
101 #else
102 #define FORCE_PACKED
103 #endif
104 
105 typedef struct tagITFILEHEADER
106 {
107 	uint32_t id;			// 0x4D504D49
108 	char songname[26];
109 	uint16_t reserved1;		// 0x1004
110 	uint16_t ordnum;
111 	uint16_t insnum;
112 	uint16_t smpnum;
113 	uint16_t patnum;
114 	uint16_t cwtv;
115 	uint16_t cmwt;
116 	uint16_t flags;
117 	uint16_t special;
118 	uint8_t globalvol;
119 	uint8_t mv;
120 	uint8_t speed;
121 	uint8_t tempo;
122 	uint8_t sep;
123 	uint8_t zero;
124 	uint16_t msglength;
125 	uint32_t msgoffset;
126 	uint32_t reserved2;
127 	uint8_t chnpan[64];
128 	uint8_t chnvol[64];
129 } FORCE_PACKED ITFILEHEADER, *PITFILEHEADER;
130 
131 typedef struct MODMIDICFG
132 {
133 	char szMidiGlb[9*32];      // changed from CHAR
134 	char szMidiSFXExt[16*32];  // changed from CHAR
135 	char szMidiZXXExt[128*32]; // changed from CHAR
136 } FORCE_PACKED MODMIDICFG, *LPMODMIDICFG;
137 
138 #pragma pack()
139 
140 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
141 
142 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
143 
144 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
145 
146 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
147 
148 // PUBLIC DATA DEFINITIONS -------------------------------------------------
149 
150 // PRIVATE DATA DEFINITIONS ------------------------------------------------
151 
152 // CODE --------------------------------------------------------------------
153 
154 //==========================================================================
155 //
156 // ReadDUH
157 //
158 // Reads metadata from a generic module.
159 //
160 //==========================================================================
161 
ReadDUH(DUH * duh,DumbSong * info,bool meta,bool dos)162 static void ReadDUH(DUH * duh, DumbSong *info, bool meta, bool dos)
163 {
164 	if (!duh) return;
165 
166 	DUMB_IT_SIGDATA * itsd = duh_get_it_sigdata(duh);
167 
168 	if (!itsd) return;
169 
170 	info->NumChannels = itsd->n_pchannels;
171 	info->NumPatterns = itsd->n_patterns;
172 	info->NumOrders = itsd->n_orders;
173 
174 	if (meta)
175 	{
176 		if (itsd->name[0])
177 		{
178 			//if (dos) info.meta_add(field_title, string_utf8_from_oem((char*)&itsd->name, sizeof(itsd->name)));
179 			//else info.meta_add(field_title, pfc::stringcvt::string_utf8_from_ansi((char *)&itsd->name, sizeof(itsd->name)));
180 		}
181 		if (itsd->song_message && *itsd->song_message)
182 		{
183 			//if (dos) info.meta_add(field_comment, string_utf8_from_oem_multiline((char*)itsd->song_message));
184 			//else info.meta_add(field_comment, pfc::stringcvt::string_utf8_from_ansi((char *)itsd->song_message));
185 		}
186 	}
187 
188 	// std::string does not like nullptr assignments. Was this really necessary? :(
189 	auto a = duh_get_tag(duh, "FORMAT");
190 	if (a) info->Codec = a;
191 	a = duh_get_tag(duh, "TRACKERVERSION");
192 	if (a) info->TrackerVersion = a;
193 	a = duh_get_tag(duh, "FORMATVERSION");
194 	if (a) info->FormatVersion = a;
195 
196 
197 #if 0
198 	std::string name;
199 
200 	if (itsd->n_samples)
201 	{
202 		int i, n;
203 		//info.info_set_int(field_samples, itsd->n_samples);
204 
205 		if (meta && itsd->sample)
206 		{
207 			for (i = 0, n = itsd->n_samples; i < n; i++)
208 			{
209 				if (itsd->sample[i].name[0])
210 				{
211 					name = "smpl";
212 					if (i < 10) name += '0';
213 					name += '0' + i;
214 					//if (dos) info.meta_add(name, string_utf8_from_oem((char*)&itsd->sample[i].name, sizeof(itsd->sample[i].name)));
215 					//else info.meta_add(name, pfc::stringcvt::string_utf8_from_ansi((char *)&itsd->sample[i].name, sizeof(itsd->sample[i].name)));
216 				}
217 			}
218 		}
219 	}
220 
221 	if (itsd->n_instruments)
222 	{
223 		//info.info_set_int(field_instruments, itsd->n_instruments);
224 
225 		if (meta && itsd->instrument)
226 		{
227 			for (i = 0, n = itsd->n_instruments; i < n; i++)
228 			{
229 				if (itsd->instrument[i].name[0])
230 				{
231 					name = "inst";
232 					if (i < 10) name += '0';
233 					name += '0' + i;
234 					//if (dos) info.meta_add(name, string_utf8_from_oem((char*)&itsd->instrument[i].name, sizeof(itsd->instrument[i].name)));
235 					//else info.meta_add(name, pfc::stringcvt::string_utf8_from_ansi((char *)&itsd->instrument[i].name, sizeof(itsd->instrument[i].name)));
236 				}
237 			}
238 		}
239 	}
240 #endif
241 }
242 
243 //==========================================================================
244 //
245 // ReadIT
246 //
247 // Reads metadata from an IT file.
248 //
249 //==========================================================================
250 
ReadIT(const uint8_t * ptr,unsigned size,DumbSong * info,bool meta)251 static bool ReadIT(const uint8_t * ptr, unsigned size, DumbSong *info, bool meta)
252 {
253 	PITFILEHEADER pifh = (PITFILEHEADER) ptr;
254 	if ((!ptr) || (size < 0x100)) return false;
255 	if ((LittleLong(pifh->id) != 0x4D504D49) ||
256 		(LittleShort(pifh->insnum) >= 256) ||
257 		(!pifh->smpnum) || (LittleShort(pifh->smpnum) > 4000) || // XXX
258 		(!pifh->ordnum)) return false;
259 	if (sizeof(ITFILEHEADER) + LittleShort(pifh->ordnum) +
260 		LittleShort(pifh->insnum)*4 +
261 		LittleShort(pifh->smpnum)*4 +
262 		LittleShort(pifh->patnum)*4 > size) return false;
263 
264 	char ver[40];
265 
266 	snprintf(ver, 40, "IT v%u.%02x", LittleShort(pifh->cmwt) >> 8, LittleShort(pifh->cmwt) & 255);
267 	info->Codec = ver;
268 
269 	snprintf(ver, 40, "%u.%02x", LittleShort(pifh->cwtv) >> 8, LittleShort(pifh->cwtv) & 255);
270 	info->TrackerVersion = ver;
271 
272 	//if ( pifh->smpnum ) info.info_set_int( field_samples, LittleShort(pifh->smpnum) );
273 	//if ( pifh->insnum ) info.info_set_int( field_instruments, LittleShort(pifh->insnum) );
274 
275 	//if ( meta && pifh->songname[0] ) info.meta_add( field_title, string_utf8_from_it( (char*)&pifh->songname, 26 ) );
276 
277 	unsigned n, l, m_nChannels = 0;
278 
279 	// bah, some file (jm-romance.it) with message length rounded up to a multiple of 256 (384 instead of 300)
280 	unsigned msgoffset = LittleLong(pifh->msgoffset);
281 	unsigned msgend = msgoffset + LittleShort(pifh->msglength);
282 
283 	uint32_t * offset;
284 //	std::string name;
285 
286 	if (meta)
287 	{
288 		offset = (uint32_t *)(ptr + 0xC0 + LittleShort(pifh->ordnum) + LittleShort(pifh->insnum) * 4);
289 
290 		for (n = 0, l = LittleShort(pifh->smpnum); n < l; n++, offset++)
291 		{
292 			uint32_t offset_n = LittleLong( *offset );
293 			if ( offset_n >= msgoffset && offset_n < msgend ) msgend = offset_n;
294 			if ((!offset_n) || (offset_n + 0x14 + 26 + 2 >= size)) continue;
295 			// XXX
296 			if (ptr[offset_n] == 0 && ptr[offset_n + 1] == 0 &&
297 				ptr[offset_n + 2] == 'I' && ptr[offset_n + 3] == 'M' &&
298 				ptr[offset_n + 4] == 'P' && ptr[offset_n + 5] == 'S')
299 			{
300 				offset_n += 2;
301 			}
302 #if 0
303 			if (*(ptr + offset_n + 0x14))
304 			{
305 				name = "smpl";
306 				if (n < 10) name << '0';
307 				name << ('0' + n);
308 				//info.meta_add(name, string_utf8_from_it((const char *) ptr + offset_n + 0x14, 26));
309 			}
310 #endif
311 		}
312 
313 		offset = (uint32_t *)(ptr + 0xC0 + LittleShort(pifh->ordnum));
314 
315 		for (n = 0, l = LittleShort(pifh->insnum); n < l; n++, offset++)
316 		{
317 			uint32_t offset_n = LittleLong( *offset );
318 			if ( offset_n >= msgoffset && offset_n < msgend ) msgend = offset_n;
319 			if ((!offset_n) || (offset_n + 0x20 + 26 >= size)) continue;
320 #if 0
321 			if (*(ptr + offset_n + 0x20))
322 			{
323 				name = "inst";
324 				if (n < 10) name << '0';
325 				name << ('0' + n);
326 				//info.meta_add(name, string_utf8_from_it((const char *) ptr + offset_n + 0x20, 26));
327 			}
328 #endif
329 		}
330 	}
331 
332 	unsigned pos = 0xC0 + LittleShort(pifh->ordnum) + LittleShort(pifh->insnum) * 4 + LittleShort(pifh->smpnum) * 4 + LittleShort(pifh->patnum) * 4;
333 
334 	if (pos < size)
335 	{
336 		uint16_t val16 = LittleShort( *(uint16_t *)(ptr + pos) );
337 		pos += 2;
338 		if (pos + val16 * 8 < size) pos += val16 * 8;
339 	}
340 
341 	if (LittleShort(pifh->flags) & 0x80)
342 	{
343 		if (pos + sizeof(MODMIDICFG) < size)
344 		{
345 			pos += sizeof(MODMIDICFG);
346 		}
347 	}
348 
349 	if ((pos + 8 < size) && (*(uint32_t *)(ptr + pos) == MAKE_ID('P','N','A','M')))
350 	{
351 		unsigned len = LittleLong(*(uint32_t *)(ptr + pos + 4));
352 		pos += 8;
353 		if ((pos + len <= size) && (len <= 240 * 32) && (len >= 32))
354 		{
355 			if (meta)
356 			{
357 				l = len / 32;
358 				for (n = 0; n < l; n++)
359 				{
360 #if 0
361 					if (*(ptr + pos + n * 32))
362 					{
363 						name = "patt";
364 						if (n < 10) name << '0';
365 						name << ('0' + n);
366 						//info.meta_add(name, string_utf8_from_it((const char *) ptr + pos + n * 32, 32));
367 					}
368 #endif
369 				}
370 			}
371 			pos += len;
372 		}
373 	}
374 
375 	if ((pos + 8 < size) && (*(uint32_t *)(ptr + pos) == MAKE_ID('C','N','A','M')))
376 	{
377 		unsigned len = LittleLong(*(uint32_t *)(ptr + pos + 4));
378 		pos += 8;
379 		if ((pos + len <= size) && (len <= 64 * 20) && (len >= 20))
380 		{
381 			l = len / 20;
382 			m_nChannels = l;
383 			if (meta)
384 			{
385 				for (n = 0; n < l; n++)
386 				{
387 #if 0
388 					if (*(ptr + pos + n * 20))
389 					{
390 						name = "chan";
391 						if (n < 10) name << '0';
392 						name << ('0' + n);
393 						//info.meta_add(name, string_utf8_from_it((const char *) ptr + pos + n * 20, 20));
394 					}
395 #endif
396 				}
397 			}
398 			pos += len;
399 		}
400 	}
401 
402 	offset = (uint32_t *)(ptr + 0xC0 + LittleShort(pifh->ordnum) + LittleShort(pifh->insnum) * 4 + LittleShort(pifh->smpnum) * 4);
403 
404 	uint8_t chnmask[64];
405 
406 	for (n = 0, l = LittleShort(pifh->patnum); n < l; n++)
407 	{
408 		memset(chnmask, 0, sizeof(chnmask));
409 		uint32_t offset_n = LittleLong( offset[n] );
410 		if ((!offset_n) || (offset_n + 4 >= size)) continue;
411 		unsigned len = LittleShort(*(uint16_t *)(ptr + offset_n));
412 		unsigned rows = LittleShort(*(uint16_t *)(ptr + offset_n + 2));
413 		if ((rows < 4) || (rows > 256)) continue;
414 		if (offset_n + 8 + len > size) continue;
415 		unsigned i = 0;
416 		const uint8_t * p = ptr + offset_n + 8;
417 		unsigned nrow = 0;
418 		while (nrow < rows)
419 		{
420 			if (i >= len) break;
421 			uint8_t b = p[i++];
422 			if (!b)
423 			{
424 				nrow++;
425 				continue;
426 			}
427 			unsigned ch = b & 0x7F;
428 			if (ch) ch = (ch - 1) & 0x3F;
429 			if (b & 0x80)
430 			{
431 				if (i >= len) break;
432 				chnmask[ch] = p[i++];
433 			}
434 			// Channel used
435 			if (chnmask[ch] & 0x0F)
436 			{
437 				if ((ch >= m_nChannels) && (ch < 64)) m_nChannels = ch+1;
438 			}
439 			// Note
440 			if (chnmask[ch] & 1) i++;
441 			// Instrument
442 			if (chnmask[ch] & 2) i++;
443 			// Volume
444 			if (chnmask[ch] & 4) i++;
445 			// Effect
446 			if (chnmask[ch] & 8) i += 2;
447 			if (i >= len) break;
448 		}
449 	}
450 
451 	if ( meta && ( LittleShort(pifh->special) & 1 ) && ( msgend - msgoffset ) && ( msgend < size ) )
452 	{
453 		const char * str = (const char *) ptr + msgoffset;
454 		std::string msg(str);
455 		//info.meta_add( field_comment, string_utf8_from_it_multiline( msg ) );
456 	}
457 
458 	info->NumChannels = m_nChannels;
459 	info->NumPatterns = LittleShort(pifh->patnum);
460 	info->NumOrders = LittleShort(pifh->ordnum);
461 
462 	return true;
463 }
464 
465 //==========================================================================
466 //
467 // DUMB memory file system
468 //
469 //==========================================================================
470 
471 typedef struct tdumbfile_mem_status
472 {
473 	const uint8_t *ptr;
474 	unsigned int offset, size;
475 } dumbfile_mem_status;
476 
dumbfile_mem_skip(void * f,long n)477 static int DUMBCALLBACK dumbfile_mem_skip(void *f, long n)
478 {
479 	dumbfile_mem_status * s = (dumbfile_mem_status *) f;
480 	s->offset += n;
481 	if (s->offset > s->size)
482 	{
483 		s->offset = s->size;
484 		return 1;
485 	}
486 	return 0;
487 }
488 
dumbfile_mem_getc(void * f)489 static int DUMBCALLBACK dumbfile_mem_getc(void *f)
490 {
491 	dumbfile_mem_status * s = (dumbfile_mem_status *) f;
492 	if (s->offset < s->size)
493 	{
494 		return *(s->ptr + s->offset++);
495 	}
496 	return -1;
497 }
498 
dumbfile_mem_getnc(char * ptr,int32 n,void * f)499 static int32 DUMBCALLBACK dumbfile_mem_getnc(char *ptr, int32 n, void *f)
500 {
501 	dumbfile_mem_status * s = (dumbfile_mem_status *) f;
502 	long max = s->size - s->offset;
503 	if (max > n) max = n;
504 	if (max)
505 	{
506 		memcpy(ptr, s->ptr + s->offset, max);
507 		s->offset += max;
508 	}
509 	return max;
510 }
511 
dumbfile_mem_seek(void * f,long n)512 static int DUMBCALLBACK dumbfile_mem_seek(void *f, long n)
513 {
514 	dumbfile_mem_status * s = (dumbfile_mem_status *) f;
515 	s->offset = n;
516 	if (s->offset > s->size)
517 	{
518 		s->offset = s->size;
519 		return 1;
520 	}
521 	return 0;
522 }
523 
dumbfile_mem_get_size(void * f)524 static long DUMBCALLBACK dumbfile_mem_get_size(void *f)
525 {
526 	dumbfile_mem_status * s = (dumbfile_mem_status *) f;
527 	return s->size;
528 }
529 
530 static DUMBFILE_SYSTEM mem_dfs = {
531 	NULL, // open
532 	&dumbfile_mem_skip,
533 	&dumbfile_mem_getc,
534 	&dumbfile_mem_getnc,
535 	NULL, // close
536 	&dumbfile_mem_seek,
537 	&dumbfile_mem_get_size
538 };
539 
540 //==========================================================================
541 //
542 // dumb_read_allfile
543 //
544 //==========================================================================
545 
dumb_read_allfile(dumbfile_mem_status * filestate,uint8_t * start,MusicIO::FileInterface * reader,int lenhave,int lenfull)546 DUMBFILE *dumb_read_allfile(dumbfile_mem_status *filestate, uint8_t *start, MusicIO::FileInterface *reader, int lenhave, int lenfull)
547 {
548 	filestate->size = lenfull;
549 	filestate->offset = 0;
550 	if (lenhave >= lenfull)
551 		filestate->ptr = (uint8_t *)start;
552     else
553     {
554         uint8_t *mem = new uint8_t[lenfull];
555         memcpy(mem, start, lenhave);
556         if (reader->read(mem + lenhave, lenfull - lenhave) != (lenfull - lenhave))
557         {
558             delete[] mem;
559             return NULL;
560         }
561         filestate->ptr = mem;
562     }
563     return dumbfile_open_ex(filestate, &mem_dfs);
564 }
565 
566 //==========================================================================
567 //
568 // MOD_SetAutoChip
569 //
570 // Disables interpolation for short samples that meet criteria set by
571 // the cvars referenced at the top of this function.
572 //
573 //==========================================================================
574 
MOD_SetAutoChip(DUH * duh)575 static void MOD_SetAutoChip(DUH *duh)
576 {
577 	int size_force = dumbConfig.mod_autochip_size_force;
578 	int size_scan = dumbConfig.mod_autochip_size_scan;
579 	int scan_threshold_8 = ((dumbConfig.mod_autochip_scan_threshold * 0x100) + 50) / 100;
580 	int scan_threshold_16 = ((dumbConfig.mod_autochip_scan_threshold * 0x10000) + 50) / 100;
581 	DUMB_IT_SIGDATA * itsd = duh_get_it_sigdata(duh);
582 
583 	if (itsd)
584 	{
585 		for (int i = 0, j = itsd->n_samples; i < j; i++)
586 		{
587 			IT_SAMPLE * sample = &itsd->sample[i];
588 			if (sample->flags & IT_SAMPLE_EXISTS)
589 			{
590 				int channels = sample->flags & IT_SAMPLE_STEREO ? 2 : 1;
591 				if (sample->length < size_force) sample->max_resampling_quality = 0;
592 				else if (sample->length < size_scan)
593 				{
594 					if ((sample->flags & (IT_SAMPLE_LOOP|IT_SAMPLE_PINGPONG_LOOP)) == IT_SAMPLE_LOOP)
595 					{
596 						int loop_start = sample->loop_start * channels;
597 						int loop_end = sample->loop_end * channels;
598 						int s1, s2;
599 						if (sample->flags & IT_SAMPLE_16BIT)
600 						{
601 							s1 = ((signed short *)sample->data)[loop_start];
602 							s2 = ((signed short *)sample->data)[loop_end - channels];
603 							if (abs(s1 - s2) > scan_threshold_16)
604 							{
605 								sample->max_resampling_quality = 0;
606 								continue;
607 							}
608 							if (channels == 2)
609 							{
610 								s1 = ((signed short *)sample->data)[loop_start + 1];
611 								s2 = ((signed short *)sample->data)[loop_end - 1];
612 								if (abs(s1 - s2) > scan_threshold_16)
613 								{
614 									sample->max_resampling_quality = 0;
615 									continue;
616 								}
617 							}
618 						}
619 						else
620 						{
621 							s1 = ((signed char *)sample->data)[loop_start];
622 							s2 = ((signed char *)sample->data)[loop_end - channels];
623 							if (abs(s1 - s2) > scan_threshold_8)
624 							{
625 								sample->max_resampling_quality = 0;
626 								continue;
627 							}
628 							if (channels == 2)
629 							{
630 								s1 = ((signed char *)sample->data)[loop_start + 1];
631 								s2 = ((signed char *)sample->data)[loop_end - 1];
632 								if (abs(s1 - s2) > scan_threshold_8)
633 								{
634 									sample->max_resampling_quality = 0;
635 									continue;
636 								}
637 							}
638 						}
639 					}
640 					if ((sample->flags & (IT_SAMPLE_SUS_LOOP|IT_SAMPLE_PINGPONG_SUS_LOOP)) == IT_SAMPLE_SUS_LOOP)
641 					{
642 						int sus_loop_start = sample->sus_loop_start * channels;
643 						int sus_loop_end = sample->sus_loop_end * channels;
644 						int s1, s2;
645 						if (sample->flags & IT_SAMPLE_16BIT)
646 						{
647 							s1 = ((signed short *)sample->data)[sus_loop_start];
648 							s2 = ((signed short *)sample->data)[sus_loop_end - channels];
649 							if (abs(s1 - s2) > scan_threshold_16)
650 							{
651 								sample->max_resampling_quality = 0;
652 								continue;
653 							}
654 							if (channels == 2)
655 							{
656 								s1 = ((signed short *)sample->data)[sus_loop_start + 1];
657 								s2 = ((signed short *)sample->data)[sus_loop_end - 1];
658 								if (abs(s1 - s2) > scan_threshold_16)
659 								{
660 									sample->max_resampling_quality = 0;
661 									continue;
662 								}
663 							}
664 						}
665 						else
666 						{
667 							s1 = ((signed char *)sample->data)[sus_loop_start];
668 							s2 = ((signed char *)sample->data)[sus_loop_end - channels];
669 							if (abs(s1 - s2) > scan_threshold_8)
670 							{
671 								sample->max_resampling_quality = 0;
672 								continue;
673 							}
674 							if (channels == 2)
675 							{
676 								s1 = ((signed char *)sample->data)[sus_loop_start + 1];
677 								s2 = ((signed char *)sample->data)[sus_loop_end - 1];
678 								if (abs(s1 - s2) > scan_threshold_8)
679 								{
680 									sample->max_resampling_quality = 0;
681 									continue;
682 								}
683 							}
684 						}
685 					}
686 
687 					int k, l = sample->length * channels;
688 					if (sample->flags & IT_SAMPLE_LOOP) l = sample->loop_end * channels;
689 					if (sample->flags & IT_SAMPLE_16BIT)
690 					{
691 						for (k = channels; k < l; k += channels)
692 						{
693 							if (abs(((signed short *)sample->data)[k - channels] - ((signed short *)sample->data)[k]) > scan_threshold_16)
694 							{
695 								break;
696 							}
697 						}
698 						if (k < l)
699 						{
700 							sample->max_resampling_quality = 0;
701 							continue;
702 						}
703 						if (channels == 2)
704 						{
705 							for (k = 2 + 1; k < l; k += 2)
706 							{
707 								if (abs(((signed short *)sample->data)[k - 2] - ((signed short *)sample->data)[k]) > scan_threshold_16)
708 								{
709 									break;
710 								}
711 							}
712 						}
713 						if (k < l)
714 						{
715 							sample->max_resampling_quality = 0;
716 							continue;
717 						}
718 					}
719 					else
720 					{
721 						for (k = channels; k < l; k += channels)
722 						{
723 							if (abs(((signed char *)sample->data)[k - channels] - ((signed char *)sample->data)[k]) > scan_threshold_8)
724 							{
725 								break;
726 							}
727 						}
728 						if (k < l)
729 						{
730 							sample->max_resampling_quality = 0;
731 							continue;
732 						}
733 						if (channels == 2)
734 						{
735 							for (k = 2 + 1; k < l; k += 2)
736 							{
737 								if (abs(((signed char *)sample->data)[k - 2] - ((signed char *)sample->data)[k]) > scan_threshold_8)
738 								{
739 									break;
740 								}
741 							}
742 						}
743 						if (k < l)
744 						{
745 							sample->max_resampling_quality = 0;
746 							continue;
747 						}
748 					}
749 				}
750 			}
751 		}
752 	}
753 }
754 
755 //==========================================================================
756 //
757 // MOD_OpenSong
758 //
759 //==========================================================================
760 
MOD_OpenSong(MusicIO::FileInterface * reader,int samplerate)761 StreamSource* MOD_OpenSong(MusicIO::FileInterface *reader, int samplerate)
762 {
763 	DUH *duh = 0;
764 	int headsize;
765 	union
766 	{
767 		uint8_t start[64];
768 		uint32_t dstart[64/4];
769 	};
770 	dumbfile_mem_status filestate;
771 	DUMBFILE *f = NULL;
772 	DumbSong *state = NULL;
773 
774 	bool is_it = false;
775 	bool is_dos = true;
776 
777 	auto fpos = reader->tell();
778     int size = (int)reader->filelength();
779 
780 	filestate.ptr = start;
781 	filestate.offset = 0;
782 	headsize = MIN((int)sizeof(start), size);
783 
784     if (headsize != reader->read(start, headsize))
785     {
786         return NULL;
787     }
788 
789 	if (size >= 4 && dstart[0] == MAKE_ID('I','M','P','M'))
790 	{
791 		is_it = true;
792 		if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
793 		{
794 			duh = dumb_read_it_quick(f);
795 		}
796 	}
797 	else if (size >= 17 && !memcmp(start, "Extended Module: ", 17))
798 	{
799 		if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
800 		{
801 			duh = dumb_read_xm_quick(f);
802 		}
803 	}
804 	else if (size >= 0x30 && dstart[11] == MAKE_ID('S','C','R','M'))
805 	{
806 		if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
807 		{
808 			duh = dumb_read_s3m_quick(f);
809 		}
810 	}
811 	else if (size >= 1168 &&
812 		/*start[28] == 0x1A &&*/ start[29] == 2 &&
813 		( !memcmp( &start[20], "!Scream!", 8 ) ||
814 		  !memcmp( &start[20], "BMOD2STM", 8 ) ||
815 		  !memcmp( &start[20], "WUZAMOD!", 8 ) ) )
816 	{
817 		if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
818 		{
819 			duh = dumb_read_stm_quick(f);
820 		}
821 	}
822 	else if (size >= 2 &&
823 		((start[0] == 0x69 && start[1] == 0x66) ||
824 		 (start[0] == 0x4A && start[1] == 0x4E)))
825 	{
826 		if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
827 		{
828 			duh = dumb_read_669_quick(f);
829 		}
830 	}
831 	else if (size >= 0x30 && dstart[11] == MAKE_ID('P','T','M','F'))
832 	{
833 		if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
834 		{
835 			duh = dumb_read_ptm_quick(f);
836 		}
837 	}
838 	else if (size >= 4 && dstart[0] == MAKE_ID('P','S','M',' '))
839 	{
840 		if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
841 		{
842 			duh = dumb_read_psm_quick(f, 0/*start_order*/);
843 			/*start_order = 0;*/
844 		}
845 	}
846 	else if (size >= 4 && dstart[0] == (uint32_t)MAKE_ID('P','S','M',254))
847 	{
848 		if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
849 		{
850 			duh = dumb_read_old_psm_quick(f);
851 		}
852 	}
853 	else if (size >= 3 && start[0] == 'M' && start[1] == 'T' && start[2] == 'M')
854 	{
855 		if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
856 		{
857 			duh = dumb_read_mtm_quick(f);
858 		}
859 	}
860 	else if (size >= 12 && dstart[0] == MAKE_ID('R','I','F','F') &&
861 		(dstart[2] == MAKE_ID('D','S','M','F') ||
862 		 dstart[2] == MAKE_ID('A','M',' ',' ') ||
863 		 dstart[2] == MAKE_ID('A','M','F','F')))
864 	{
865 		if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
866 		{
867 			duh = dumb_read_riff_quick(f);
868 		}
869 	}
870 	else if (size >= 32 &&
871 		!memcmp( start, "ASYLUM Music Format", 19 ) &&
872 		!memcmp( start + 19, " V1.0", 5 ) )
873 	{
874 		if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
875 		{
876 			duh = dumb_read_asy_quick(f);
877 		}
878 	}
879 	else if (size >= 8 &&
880 		dstart[0] == MAKE_ID('O','K','T','A') &&
881 		dstart[1] == MAKE_ID('S','O','N','G'))
882 	{
883 		if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
884 		{
885 			duh = dumb_read_okt_quick(f);
886 		}
887 	}
888 
889 	if ( ! duh )
890 	{
891 		is_dos = false;
892 		if (filestate.ptr == (uint8_t *)start)
893 		{
894 			if (!(f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
895 			{
896                 reader->seek(fpos, SEEK_SET);
897 				return NULL;
898 			}
899 		}
900 		else
901 		{
902 			filestate.offset = 0;
903 		}
904 		// No way to get the filename, so we can't check for a .mod extension, and
905 		// therefore, trying to load an old 15-instrument SoundTracker module is not
906 		// safe. We'll restrict MOD loading to 31-instrument modules with known
907 		// signatures and let the sound system worry about 15-instrument ones.
908 		// (Assuming it even supports them)
909 		duh = dumb_read_mod_quick(f, true);
910 	}
911 
912 	if (f != NULL)
913 	{
914 		dumbfile_close(f);
915 	}
916 	if ( duh )
917 	{
918 		if (dumbConfig.mod_autochip)
919 		{
920 			MOD_SetAutoChip(duh);
921 		}
922 		state = new DumbSong(duh, samplerate);
923 
924 		if (is_it) ReadIT(filestate.ptr, size, state, false);
925 		else ReadDUH(duh, state, false, is_dos);
926 	}
927 	else
928 	{
929 		// Reposition file pointer for other codecs to do their checks.
930         reader->seek(fpos, SEEK_SET);
931 	}
932 	if (filestate.ptr != (uint8_t *)start)
933 	{
934 		delete[] const_cast<uint8_t *>(filestate.ptr);
935 	}
936 	return state;
937 }
938 
939 //==========================================================================
940 //
941 // DumbSong :: read												static
942 //
943 //==========================================================================
944 
GetData(void * buffer,size_t sizebytes)945 bool DumbSong::GetData(void *buffer, size_t sizebytes)
946 {
947 	if (eof)
948 	{
949 		memset(buffer, 0, sizebytes);
950 		return false;
951 	}
952 
953 	while (sizebytes > 0)
954 	{
955 		int written = decode_run(buffer, (unsigned)sizebytes / 8);
956 		if (written < 0)
957 		{
958 			return false;
959 		}
960 		if (written == 0)
961 		{
962 			memset(buffer, 0, sizebytes);
963 			return true;
964 		}
965 		else
966 		{
967 			// Convert to float
968 			for (int i = 0; i < written * 2; ++i)
969 			{
970 				((float *)buffer)[i] = (((int *)buffer)[i] / (float)(1 << 24)) * MasterVolume;
971 			}
972 		}
973 		buffer = (uint8_t *)buffer + written * 8;
974 		sizebytes -= written * 8;
975 	}
976 	return true;
977 }
978 
979 //==========================================================================
980 //
981 // ChangeSetting
982 //
983 //==========================================================================
984 
ChangeSettingNum(const char * setting,double val)985 void DumbSong::ChangeSettingNum(const char* setting, double val)
986 {
987 	if (!stricmp(setting, "dumb.mastervolume"))
988 		MasterVolume = (float)val;
989 }
990 
991 //==========================================================================
992 //
993 // DumbSong constructor
994 //
995 //==========================================================================
996 
DumbSong(DUH * myduh,int samplerate)997 DumbSong::DumbSong(DUH* myduh, int samplerate)
998 {
999 	duh = myduh;
1000 	sr = NULL;
1001 	eof = false;
1002 	interp = dumbConfig.mod_interp;
1003 	volramp = dumbConfig.mod_volramp;
1004 	written = 0;
1005 	length = 0;
1006 	start_order = 0;
1007 	MasterVolume = (float)dumbConfig.mod_dumb_mastervolume * 4;
1008 	if (dumbConfig.mod_samplerate != 0)
1009 	{
1010 		srate = dumbConfig.mod_samplerate;
1011 	}
1012 	else
1013 	{
1014 		srate = samplerate;
1015 	}
1016 	delta = 65536.0 / srate;
1017 }
1018 
1019 //==========================================================================
1020 //
1021 // DumbSong destructor
1022 //
1023 //==========================================================================
1024 
~DumbSong()1025 DumbSong::~DumbSong()
1026 {
1027 	if (sr) duh_end_sigrenderer(sr);
1028 	if (duh) unload_duh(duh);
1029 }
1030 
1031 //==========================================================================
1032 //
1033 // DumbSong GetFormat
1034 //
1035 //==========================================================================
1036 
GetFormat()1037 SoundStreamInfo DumbSong::GetFormat()
1038 {
1039 	return { 32*1024, srate, 2 };
1040 }
1041 
1042 //==========================================================================
1043 //
1044 // DumbSong :: Play
1045 //
1046 //==========================================================================
1047 
Start()1048 bool DumbSong::Start()
1049 {
1050 	started = open2(0);
1051 	return started;
1052 }
1053 
1054 //==========================================================================
1055 //
1056 // DumbSong :: SetSubsong
1057 //
1058 //==========================================================================
1059 
SetSubsong(int order)1060 bool DumbSong::SetSubsong(int order)
1061 {
1062 	if (order == start_order)
1063 	{
1064 		return true;
1065 	}
1066 	if (!started)
1067 	{
1068 		start_order = order;
1069 		return true;
1070 	}
1071 	DUH_SIGRENDERER *oldsr = sr;
1072 	sr = NULL;
1073 	start_order = order;
1074 	if (!open2(0))
1075 	{
1076 		sr = oldsr;
1077 		return false;
1078 	}
1079 	duh_end_sigrenderer(oldsr);
1080 	return true;
1081 }
1082 
1083 //==========================================================================
1084 //
1085 // DumbSong :: open2
1086 //
1087 //==========================================================================
1088 
open2(long pos)1089 bool DumbSong::open2(long pos)
1090 {
1091 	if (start_order != 0)
1092 	{
1093 		sr = dumb_it_start_at_order(duh, 2, start_order);
1094 		if (sr && pos) duh_sigrenderer_generate_samples(sr, 0, 1, pos, 0);
1095 	}
1096 	else
1097 	{
1098 		sr = duh_start_sigrenderer(duh, 0, 2, pos);
1099 	}
1100 	if (!sr)
1101 	{
1102 		return false;
1103 	}
1104 
1105 	DUMB_IT_SIGRENDERER *itsr = duh_get_it_sigrenderer(sr);
1106 	dumb_it_set_resampling_quality(itsr, interp);
1107 	dumb_it_set_ramp_style(itsr, volramp);
1108 	if (!m_Looping)
1109 	{
1110 		dumb_it_set_loop_callback(itsr, &dumb_it_callback_terminate, NULL);
1111 	}
1112 	dumb_it_set_xm_speed_zero_callback(itsr, &dumb_it_callback_terminate, NULL);
1113 	dumb_it_set_global_volume_zero_callback(itsr, &dumb_it_callback_terminate, NULL);
1114 	return true;
1115 }
1116 
1117 //==========================================================================
1118 //
1119 // DumbSong :: render
1120 //
1121 //==========================================================================
1122 
render(double volume,double delta,long samples,sample_t ** buffer)1123 long DumbSong::render(double volume, double delta, long samples, sample_t **buffer)
1124 {
1125 	long written = duh_sigrenderer_generate_samples(sr, volume, delta, samples, buffer);
1126 
1127 	if (written < samples)
1128 	{
1129 		if (!m_Looping)
1130 		{
1131 			eof = true;
1132 		}
1133 		else
1134 		{
1135 			duh_end_sigrenderer(sr);
1136 			sr = NULL;
1137 			if (!open2(0))
1138 			{
1139 				eof = true;
1140 			}
1141 		}
1142 	}
1143 	return written;
1144 }
1145 
1146 //==========================================================================
1147 //
1148 // DumbSong :: decode_run
1149 //
1150 // Given a buffer of 32-bit PCM stereo pairs and a size specified in
1151 // samples, returns the number of samples written to the buffer.
1152 //
1153 //==========================================================================
1154 
decode_run(void * buffer,unsigned int size)1155 int DumbSong::decode_run(void *buffer, unsigned int size)
1156 {
1157 	if (eof) return 0;
1158 
1159 	DUMB_IT_SIGRENDERER *itsr = duh_get_it_sigrenderer(sr);
1160 	if (itsr == nullptr) return 0;
1161 	int dt = int(delta * 65536.0 + 0.5);
1162 	long samples = long((((LONG_LONG)itsr->time_left << 16) | itsr->sub_time_left) / dt);
1163 	if (samples == 0 || samples > (long)size) samples = size;
1164 	sample_t **buf = (sample_t **)&buffer;
1165 	int written = 0;
1166 
1167 retry:
1168 	dumb_silence(buf[0], size * 2);
1169 	written = render(1, delta, samples, buf);
1170 
1171 	if (eof) return false;
1172 	else if (written == 0) goto retry;
1173 	else if (written == -1) return -1;
1174 
1175 	return written;
1176 }
1177 
1178 //==========================================================================
1179 //
1180 // DumbSong :: GetStats
1181 //
1182 //==========================================================================
1183 
GetStats()1184 std::string DumbSong::GetStats()
1185 {
1186 	//return StreamSong::GetStats();
1187 	DUMB_IT_SIGRENDERER *itsr = duh_get_it_sigrenderer(sr);
1188 	DUMB_IT_SIGDATA *itsd = duh_get_it_sigdata(duh);
1189 
1190 	int channels = 0;
1191 	for (int i = 0; i < DUMB_IT_N_CHANNELS; i++)
1192 	{
1193 		IT_PLAYING * playing = itsr->channel[i].playing;
1194 		if (playing && !(playing->flags & IT_PLAYING_DEAD)) channels++;
1195 	}
1196 	for (int i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++)
1197 	{
1198 		if (itsr->playing[i]) channels++;
1199 	}
1200 
1201 	if (itsr == NULL || itsd == NULL)
1202 	{
1203 		return "Problem getting stats";
1204 	}
1205 	else
1206 	{
1207 		char out[120];
1208 		snprintf(out, 120, "%s, Order:%3d/%d Patt:%2d/%d Row:%2d/%2d Chan:%2d/%2d Speed:%2d Tempo:%3d",
1209 			Codec.c_str(),
1210 			itsr->order, NumOrders,
1211 			(itsd->order && itsr->order < itsd->n_orders ? itsd->order[itsr->order] : 0), NumPatterns,
1212 			itsr->row, itsr->n_rows,
1213 			channels, NumChannels,
1214 			itsr->speed,
1215 			itsr->tempo
1216 			);
1217 		return out;
1218 	}
1219 }
1220 
1221