/* Extended Module Player * Copyright (C) 1998-1999 Claudio Matsuoka and Hipolito Carraro Jr. * * This file is part of the Extended Module Player and is distributed * under the terms of the GNU General Public License. See docs/COPYING * for more information. */ /* Date: Fri, 25 Dec 1998 03:49:17 +0200 (EET) * From: janne * To: claudio@helllabs.org, hipolito@brhs.com.br * Subject: gusmax * * i got rh5.1 running on p90/48mb and my soundcard is gusmax which i use * with jaroslav's lowlevel gus drivers.. well there's a problem with xmp * when i try to load modules bigger than half megs (my gusmax has only 512k * memory), it hangs and goes in to 'uninoterruptible sleep' and cannot be * killed even with kill -9.. well anyway i thought it'd be nice to have * perhaps a cubicplayer style sample crunching if soundcard doesn't have * enough memory, or at least try and make it not hang if i try to load * modules that are too big.. :) */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "driver.h" #include "convert.h" #include "mixer.h" #define INTERPOLATE() \ if (itpt >> SMIX_SFT_FT) { \ cur_bk += itpt >> SMIX_SFT_FT; \ smp_x1 = in_bk[cur_bk]; \ smp_dt = in_bk[cur_bk + 1] - smp_x1; \ itpt &= SMIX_AND_FT; \ } #define CRUNCHER() \ cur_bk = -1; \ itpt = 0x10000; \ smp_x1 = smp_dt = 0; \ while (count--) { \ INTERPOLATE (); \ *(out_bk++) = smp_x1 + ((itpt * smp_dt) >> SMIX_SFT_FT); \ itpt += itpt_inc; \ } static void cruncher_8bit (int count, int itpt_inc, char *in_bk, char *out_bk) { int smp_x1, smp_dt, itpt, cur_bk; CRUNCHER (); } static void cruncher_16bit (int count, int itpt_inc, int16 *in_bk, int16 *out_bk) { int smp_x1, smp_dt, itpt, cur_bk; CRUNCHER (); } int xmp_cvt_crunch (struct patch_info **patch, unsigned int ratio) { struct patch_info *pi; int type, loop_end, loop_dt, smp_len; int itpt_inc, base_note; if (ratio == 0x10000) return ratio; if ((*patch)->len == XMP_PATCH_FM) return 0; type = 0; loop_end = (*patch)->loop_end; loop_dt = loop_end - (*patch)->loop_start; smp_len = (*patch)->len; if ((*patch)->mode & WAVE_16_BITS) { smp_len >>= 1; loop_dt >>= 1; loop_end >>= 1; ++type; } if (ratio < 0x10000 && smp_len < XMP_DEF_MINLEN) return 0x10000; base_note = ((long long) ((*patch)->base_note) << SMIX_SFT_FT) / ratio; itpt_inc = ((long long) base_note << SMIX_SFT_FT) / (*patch)->base_note; smp_len = ((long long) smp_len << SMIX_SFT_FT) / itpt_inc; loop_end = ((long long) loop_end << SMIX_SFT_FT) / itpt_inc; loop_dt = ((long long) loop_dt << SMIX_SFT_FT) / itpt_inc; pi = calloc (1, sizeof (struct patch_info) + (smp_len << type) + sizeof (int)); memcpy (pi, *patch, sizeof (struct patch_info)); pi->len = smp_len << type; pi->loop_end = loop_end << type; pi->loop_start = (loop_end - loop_dt) << type; pi->base_note = base_note; if (type) cruncher_16bit (smp_len, itpt_inc, (int16 *) &(*patch)->data, (int16 *) &pi->data); else cruncher_8bit (smp_len, itpt_inc, (char *) &(*patch)->data, (char *) &pi->data); free (*patch); *patch = pi; return ratio; }