#include "fileio.h" #include "game.h" #include "resource.h" #include "sys.h" #include #define PAULA_FREQ 3546897 static const struct { uint16_t offset; // words uint16_t size; } _sounds_amiga[] = { { 0x0000, 0x0256 }, { 0x0000, 0x0256 }, { 0x0000, 0x0256 }, { 0x0000, 0x0256 }, { 0x012b, 0x051a }, { 0x03b8, 0x0532 }, { 0x0651, 0x03e8 }, { 0x0b51, 0x0c1c }, { 0x115f, 0x0e40 }, { 0x0000, 0x0256 }, { 0x0000, 0x0256 }, { 0x187f, 0x04c4 }, { 0x1ae1, 0x0c14 }, { 0x20eb, 0x1e1a }, { 0x2ff8, 0x0610 }, { 0x3300, 0x0420 }, { 0x3510, 0x032c }, { 0x36a6, 0x0574 } }; // Amiga, unexotica static const char *_modules[] = { "ALMOST", "mod.almost", "GUNN", "mod.bluesgunnbest", "EVERY", "mod.every", "SHOT", "mod.shot" }; struct mixerchannel_t { uint8_t *data; uint32_t pos; uint32_t step; uint32_t size; }; static int _rate = 22050; static struct mixerchannel_t _channel; static ModPlugFile *_mpf; static void mix(void *param, uint8_t *buf, int len) { memset(buf, 0, len); if (_mpf) { const int count = ModPlug_Read(_mpf, buf, len); if (count == 0) { ModPlug_SeekOrder(_mpf, 0); } } if (_channel.data) { for (int i = 0; i < len; i += sizeof(int16_t)) { const int pos = _channel.pos >> 16; if (pos >= _channel.size) { _channel.data = 0; break; } const int sample = *(int16_t *)(buf + i) + ((int8_t)_channel.data[pos]) * 256; *(int16_t *)(buf + i) = (sample < -32768 ? -32768 : (sample > 32767 ? 32767 : sample)); _channel.pos += _channel.step; } } } void sound_init(int rate) { _rate = rate; ModPlug_Settings mp_settings; memset(&mp_settings, 0, sizeof(mp_settings)); ModPlug_GetSettings(&mp_settings); mp_settings.mFlags = MODPLUG_ENABLE_OVERSAMPLING | MODPLUG_ENABLE_NOISE_REDUCTION; mp_settings.mChannels = 1; mp_settings.mBits = 16; mp_settings.mFrequency = rate; mp_settings.mResamplingMode = MODPLUG_RESAMPLE_FIR; mp_settings.mLoopCount = -1; ModPlug_SetSettings(&mp_settings); g_sys.start_audio(mix, 0); } void sound_fini() { g_sys.stop_audio(); } void play_sound(int num) { if (g_res.snd) { g_sys.lock_audio(); _channel.data = g_res.snd + _sounds_amiga[num].offset * 2; _channel.pos = 0; _channel.step = ((PAULA_FREQ / 0x358) << 16) / _rate; _channel.size = _sounds_amiga[num].size; g_sys.unlock_audio(); } } void play_music(int num) { g_sys.lock_audio(); if (_mpf) { ModPlug_Unload(_mpf); _mpf = 0; } const char *filename = _modules[num * 2 + 1]; if (fio_exists(filename)) { int slot = fio_open(filename, 1); int size = fio_size(slot); uint8_t *buf = (uint8_t *)malloc(size); if (buf) { fio_read(slot, buf, size); _mpf = ModPlug_Load(buf, size); free(buf); } fio_close(slot); } g_sys.unlock_audio(); }