From 7c24e9a9b02b04dcaf9507acb94091ea70a2c02d Mon Sep 17 00:00:00 2001 From: Xavi Del Campo Date: Fri, 31 Jan 2020 10:32:23 +0100 Subject: Imported pristine psxsdk-20190410 from official repo --- libmodplay/modplay.c | 290 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 290 insertions(+) create mode 100644 libmodplay/modplay.c (limited to 'libmodplay/modplay.c') diff --git a/libmodplay/modplay.c b/libmodplay/modplay.c new file mode 100644 index 0000000..9f5f33d --- /dev/null +++ b/libmodplay/modplay.c @@ -0,0 +1,290 @@ +// MODplay for the PS1 +// Music Module Player +// Supports ProTracker (.mod) module format + +// Requires libADPCM! + +// If NO_PSX_LIB is defined, no parts using PSXSDK functions are compiled +// This is useful if you want to use the library to handle module files in tools + +#ifndef NO_PSX_LIB +#include +#endif + +#include +#include +#include +#include + +#ifndef NO_PSX_LIB +#include +#endif + +#include "modplay.h" +#include "modplay_int.h" + +// Configuration defines + +// Size of ADPCM buffer used by MODUploadSamples when +// converting 8-bit unsigned PCM samples to PS1 ADPCM format +// By default it is set to 0x4000, 16 kilobytes + +#define ADPCM_BUFFER_SIZE 0x4000 + + + +int modplay_base_voice = 0; +int modplay_max_vol = 0x3fff; +int modplay_chan_vols[8]; +int modplay_int_cnt = 0; +int modplay_samples_off[32]; +int modplay_chan_mask = 0; +int modplay_is_mono = 0; +unsigned char modplay_adpcm_buffer[ADPCM_BUFFER_SIZE]; + +unsigned int modload_flags = 0; + +ModMusic *MODLoad(void *d) +{ + return MODLoadEx(d, 0); +} + +ModMusic *MODLoadEx(void *d, unsigned int flags) +{ + modload_flags = flags; + + // If the module file was in no other format, assume the module file is + // in ProTracker format. There's no real way to detect a ProTracker module + // file 100% correctly so this will do. + + return MODLoad_MOD(d); +} + +void MODUnload(ModMusic *m) +{ + int x; + + MODStop(m); + + switch(m->fmt) + { + case MOD_FMT_MOD: + free(m->pattern_data); + + for(x = 0; x < m->sample_num; x++) + { + if(m->sample[x].data != NULL) + free(m->sample[x].data); + } + + free(m->sample); + + free(m); + break; + } + +} + +#ifdef NO_PSX_LIB +void MODPlay_func(ModMusic *m, int c, int s, int p, int vl, int vr) +{ + // Just a stub +} +#else +void MODPlay_func(ModMusic *m, int c, int s, int p, int vl, int vr) +{ + int v = c + modplay_base_voice; +// static int mask = 0; + +// if(s != -1) +// { + // SsKeyOff(v); + if(p != -1) + SsVoicePitch(v, p); +// } + + if(modplay_max_vol != 0x3fff) + { + vl = (modplay_max_vol * vl) / 0x4000; + vr = (modplay_max_vol * vr) / 0x4000; + vl&=0x3fff; + vr&=0x3fff; + } + + if(modplay_is_mono) + { + if(vl>vr) + vr=vl; + else + vl=vr; + } + + SsVoiceVol(v, vl, vr); + + if(s != -1) + { + if(modplay_samples_off[s] != -1) + { + SsVoiceStartAddr(v, modplay_samples_off[s]); + modplay_chan_mask|=(1<fmt) + { + case MOD_FMT_MOD: + MODPlay_MOD(m, t); + break; + } + + //printf("modplay_chan_mask = %d\n", modplay_chan_mask); +#ifndef NO_PSX_LIB + SsKeyOnMask(modplay_chan_mask); +#endif +} + +void MODStop(ModMusic *m) +{ +#ifndef NO_PSX_LIB + int mask = 0; + int x; + + for(x = 0; xchannel_num; x++) + mask|=1<<(modplay_base_voice+x); + + SsKeyOffMask(mask); +#endif +} + +#ifndef NO_PSX_LIB +int MODUploadSamples(ModMusic *m, int base_addr) +{ + int x, b; + + if(base_addr == -1) + base_addr = SPU_DATA_BASE_ADDR; + + modplay_samples_off[0] = base_addr; + + for(x = 0; x < m->sample_num; x++) + { + b = SsAdpcmPack(m->sample[x].data, modplay_adpcm_buffer, + m->sample[x].length, FMT_U8, sizeof(modplay_adpcm_buffer), 0); + SsUpload(modplay_adpcm_buffer, b, modplay_samples_off[x]); + + if(x!=30) + modplay_samples_off[x+1] = modplay_samples_off[x]+b; + } + + return modplay_samples_off[x]; +} + +int MOD4PSX_Upload(void *d, int base_addr) +{ + unsigned char *c = d; + int x; + int o; + int sz; + int n; + int smpOff; + +// Check magic string + + if(strncmp((char*)c, "_mod4psx", 8) != 0) + return -1; + + o = 12; + n = *((int*)(c+8)); + + if(base_addr == -1) + smpOff = SPU_DATA_BASE_ADDR; + else + smpOff = base_addr; + + //smpOff = modplay_samples_off[0]; + + printf("Number of samples: %d\n", n); + + for(x = 0; x < n; x++) + { +// Get size + sz = *((int*)(c+o)); + printf("Size: %d\n", sz); +// Ignore eight reserved bytes (for future expension) + o+=12; + + if(sz > 0) + { + modplay_samples_off[x] = smpOff; + + SsUpload(c+o, sz, modplay_samples_off[x]); + + smpOff+=sz; + } + else + modplay_samples_off[x] = -1; + + o += sz; + } + + return modplay_samples_off[x]; +} + +#endif + +void MODSetBaseVoice(int base_voice) +{ + modplay_base_voice = base_voice; +} + +void MODSetMaxVolume(unsigned short max_volume) +{ + // Default is 0x3fff. + // Valid values 0 (MUTE) - 0x3FFF (MAX) + + modplay_max_vol = max_volume & 0x3fff; +} + +void MODRewind(ModMusic *m) +{ + MODStop(m); + m->song_pos = 0; + m->pat_pos = 0; + + if(m->fmt == MOD_FMT_MOD) + { + m->divisions_sec = 7; + m->beats_minute = 125; + m->ticks_division = 6; + } +} + +void MODSetTranspose(ModMusic *m, short transpose) +{ + m->transpose = transpose; +} + +void MODSetMono(int value) +{ + /* Sets mono audio mode + left volume = right volume */ + + modplay_is_mono = value; +} + +#ifdef NO_PSX_LIB + +// Some code might use this, so use a stub. + +unsigned short SsFreqToPitch(int hz) +{ + return 0; +} + +#endif -- cgit v1.2.3