diff --git a/Cog.xcodeproj/project.pbxproj b/Cog.xcodeproj/project.pbxproj index a437a417b..74da734c2 100644 --- a/Cog.xcodeproj/project.pbxproj +++ b/Cog.xcodeproj/project.pbxproj @@ -191,6 +191,7 @@ 83E5E54D18087CA5001F3284 /* miniModeOnTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 83E5E54B18087CA5001F3284 /* miniModeOnTemplate.pdf */; }; 83E6B7621816136F00D4576D /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83E6B759181612FD00D4576D /* Sparkle.framework */; }; 83E6B7651816178200D4576D /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83E6B759181612FD00D4576D /* Sparkle.framework */; }; + 83EEAB241C965C56002761C5 /* Syntrax.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83EEAAFA1C9651D8002761C5 /* Syntrax.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 83F9D8071A884C54007ABEC2 /* SilenceDecoder.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83F9D7F61A884B46007ABEC2 /* SilenceDecoder.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; @@ -614,6 +615,20 @@ remoteGlobalIDString = 8DC2EF4F0486A6940098B216; remoteInfo = Sparkle; }; + 83EEAAF91C9651D8002761C5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 83EEAAF51C9651D8002761C5 /* Syntrax.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 832FF2F81C96508E0076D662; + remoteInfo = Syntrax; + }; + 83EEAB251C965C61002761C5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 83EEAAF51C9651D8002761C5 /* Syntrax.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 832FF2F71C96508E0076D662; + remoteInfo = Syntrax; + }; 83F9D7F51A884B46007ABEC2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 83F9D7F11A884B44007ABEC2 /* SilenceDecoder.xcodeproj */; @@ -681,6 +696,7 @@ dstPath = ""; dstSubfolderSpec = 13; files = ( + 83EEAB241C965C56002761C5 /* Syntrax.bundle in CopyFiles */, 83F9D8071A884C54007ABEC2 /* SilenceDecoder.bundle in CopyFiles */, 836F5BF91A357A01002730CC /* sidplay.bundle in CopyFiles */, 839BD010196521E600947767 /* BASSMODS.bundle in CopyFiles */, @@ -985,6 +1001,7 @@ 83E5E54A18087CA5001F3284 /* miniModeOffTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = miniModeOffTemplate.pdf; path = Images/miniModeOffTemplate.pdf; sourceTree = ""; }; 83E5E54B18087CA5001F3284 /* miniModeOnTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = miniModeOnTemplate.pdf; path = Images/miniModeOnTemplate.pdf; sourceTree = ""; }; 83E6B750181612FD00D4576D /* Sparkle.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Sparkle.xcodeproj; path = Frameworks/Sparkle/Sparkle.xcodeproj; sourceTree = ""; }; + 83EEAAF51C9651D8002761C5 /* Syntrax.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Syntrax.xcodeproj; path = Plugins/Syntrax/Syntrax.xcodeproj; sourceTree = ""; }; 83F9D7F11A884B44007ABEC2 /* SilenceDecoder.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SilenceDecoder.xcodeproj; path = Plugins/SilenceDecoder/SilenceDecoder.xcodeproj; sourceTree = ""; }; 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 8E07AB760AAC930B00A4B32F /* PreferencesController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = PreferencesController.h; path = Preferences/PreferencesController.h; sourceTree = ""; }; @@ -1270,6 +1287,7 @@ 17B619FF0B909ED400BC003F /* PlugIns */ = { isa = PBXGroup; children = ( + 83EEAAF51C9651D8002761C5 /* Syntrax.xcodeproj */, 835CBC7118DA79F80087A03E /* modplay.xcodeproj */, 8360EF0017F92B23005208A4 /* HighlyComplete.xcodeproj */, B09E94300D747F7B0064F138 /* FFMPEG.xcodeproj */, @@ -1730,6 +1748,14 @@ name = Products; sourceTree = ""; }; + 83EEAAF61C9651D8002761C5 /* Products */ = { + isa = PBXGroup; + children = ( + 83EEAAFA1C9651D8002761C5 /* Syntrax.bundle */, + ); + name = Products; + sourceTree = ""; + }; 83F9D7F21A884B44007ABEC2 /* Products */ = { isa = PBXGroup; children = ( @@ -1870,6 +1896,7 @@ buildRules = ( ); dependencies = ( + 83EEAB261C965C61002761C5 /* PBXTargetDependency */, 83F9D8061A884C33007ABEC2 /* PBXTargetDependency */, 836F5BEE1A3579F5002730CC /* PBXTargetDependency */, 839BD012196521FD00947767 /* PBXTargetDependency */, @@ -2039,6 +2066,10 @@ ProductGroup = 83E6B751181612FD00D4576D /* Products */; ProjectRef = 83E6B750181612FD00D4576D /* Sparkle.xcodeproj */; }, + { + ProductGroup = 83EEAAF61C9651D8002761C5 /* Products */; + ProjectRef = 83EEAAF51C9651D8002761C5 /* Syntrax.xcodeproj */; + }, { ProductGroup = 17C808B10C3BD1C5005707C4 /* Products */; ProjectRef = 17C808B00C3BD1C5005707C4 /* TagLib.xcodeproj */; @@ -2281,6 +2312,13 @@ remoteRef = 83E6B760181612FD00D4576D /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 83EEAAFA1C9651D8002761C5 /* Syntrax.bundle */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = Syntrax.bundle; + remoteRef = 83EEAAF91C9651D8002761C5 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 83F9D7F61A884B46007ABEC2 /* SilenceDecoder.bundle */ = { isa = PBXReferenceProxy; fileType = wrapper.cfbundle; @@ -2641,6 +2679,11 @@ name = Sparkle; targetProxy = 83E6B7631816138800D4576D /* PBXContainerItemProxy */; }; + 83EEAB261C965C61002761C5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Syntrax; + targetProxy = 83EEAB251C965C61002761C5 /* PBXContainerItemProxy */; + }; 83F9D8061A884C33007ABEC2 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = SilenceDecoder; diff --git a/Frameworks/Syntrax-c/Syntrax-c/Info.plist b/Frameworks/Syntrax-c/Syntrax-c/Info.plist new file mode 100644 index 000000000..40c88298d --- /dev/null +++ b/Frameworks/Syntrax-c/Syntrax-c/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2016 Christopher Snowhill. All rights reserved. + NSPrincipalClass + + + diff --git a/Frameworks/Syntrax-c/Syntrax-c/file.c b/Frameworks/Syntrax-c/Syntrax-c/file.c new file mode 100644 index 000000000..016e8404b --- /dev/null +++ b/Frameworks/Syntrax-c/Syntrax-c/file.c @@ -0,0 +1,400 @@ +#include +#include +#include +#include + +#include "file.h" + +size_t filesize; + +Song* File_loadSong(const char *path) +{ + Song *synSong; + FILE *f; + uint8_t *buffer; + size_t size; + + if (!(f = fopen(path, "rb"))) return NULL; + + fseek(f, 0, SEEK_END); + size = ftell(f); + fseek(f, 0, SEEK_SET); + + if (!(buffer = (uint8_t *) malloc(size))) { + fclose(f); + return NULL; + } + + if (fread(buffer, 1, size, f) != size) { + free(buffer); + fclose(f); + return NULL; + } + + fclose(f); + + synSong = File_loadSongMem(buffer, size); + + free(buffer); + + return synSong; +} + +uint16_t get_le16(const void *p) +{ + return (((const uint8_t*)p)[0]) + + (((const uint8_t*)p)[1]) * 0x100; +} + +uint32_t get_le32(const void *p) +{ + return (((const uint8_t*)p)[0]) + + (((const uint8_t*)p)[1]) * 0x100 + + (((const uint8_t*)p)[2]) * 0x10000 + + (((const uint8_t*)p)[3]) * 0x1000000; +} + +static long File_readHeader(SongHeader *h, const uint8_t *buffer, size_t size) +{ + if (size < 52) return -1; + + h->version = get_le16(buffer); + h->UNK00 = get_le16(buffer + 2); + h->patNum = get_le32(buffer + 4); + h->subsongNum = get_le32(buffer + 8); + h->instrNum = get_le32(buffer + 12); + h->UNK01 = get_le32(buffer + 16); + h->UNK02 = get_le16(buffer + 20); + h->UNK03 = get_le16(buffer + 22); + h->UNK04 = get_le16(buffer + 24); + h->UNK05 = get_le16(buffer + 26); + h->UNK06 = get_le16(buffer + 28); + h->UNK07 = get_le16(buffer + 30); + h->UNK08 = get_le16(buffer + 32); + h->UNK09 = get_le16(buffer + 34); + h->UNK0A = get_le16(buffer + 36); + h->UNK0B = get_le16(buffer + 38); + h->UNK0C = get_le16(buffer + 40); + h->UNK0D = get_le16(buffer + 42); + h->UNK0E = get_le16(buffer + 44); + h->UNK0F = get_le16(buffer + 46); + h->UNK10 = get_le16(buffer + 48); + h->UNK11 = get_le16(buffer + 50); + + return 52; +} + +static long File_readSubSong(Subsong *subSong, const uint8_t *buffer, size_t size) +{ + int i, j; + + if (size < 16564) return -1; + + for (i = 0; i < 16; i++) + subSong->UNK00[i] = get_le32(buffer + i * 4); + + for (i = 0; i < SE_MAXCHANS; i++) + subSong->mutedChans[i] = buffer[64 + i]; + + subSong->tempo = get_le32(buffer + 80); + subSong->groove = get_le32(buffer + 84); + subSong->startPosCoarse = get_le32(buffer + 88); + subSong->startPosFine = get_le32(buffer + 92); + subSong->endPosCoarse = get_le32(buffer + 96); + subSong->endPosFine = get_le32(buffer + 100); + subSong->loopPosCoarse = get_le32(buffer + 104); + subSong->loopPosFine = get_le32(buffer + 108); + subSong->isLooping = get_le16(buffer + 112); + + memcpy(subSong->m_Name, buffer + 114, 32); + subSong->m_Name[32] = '\0'; + + subSong->channelNumber = get_le16(buffer + 146); + subSong->delayTime = get_le16(buffer + 148); + + for (i = 0; i < SE_MAXCHANS; i++) + subSong->chanDelayAmt[i] = buffer[150 + i]; + + subSong->amplification = get_le16(buffer + 166); + + subSong->UNK01 = get_le16(buffer + 168); + subSong->UNK02 = get_le16(buffer + 170); + subSong->UNK03 = get_le16(buffer + 172); + subSong->UNK04 = get_le16(buffer + 174); + subSong->UNK05 = get_le16(buffer + 176); + subSong->UNK06 = get_le16(buffer + 178); + + for (i = 0; i < SE_MAXCHANS; i++) { + for (j = 0; j < 0x100; j++) { + subSong->orders[i][j].patIndex = get_le16(buffer + 180 + i * 1024 + j * 4); + subSong->orders[i][j].patLen = get_le16(buffer + 180 + i * 1024 + j * 4 + 2); + } + } + + return 16564; +} + +long File_readRow(Row *r, const uint8_t *buffer, size_t size) +{ + if (size < 5) return -1; + + r->note = buffer[0]; + r->dest = buffer[1]; + r->instr = buffer[2]; + r->spd = buffer[3]; + r->command = buffer[4]; + + return 5; +} + +static long File_readInstrumentEffect(InstrumentEffect *effect, const uint8_t *buffer, size_t size) +{ + if (size < 40) return -1; + + effect->destWave = get_le32(buffer); + effect->srcWave1 = get_le32(buffer + 4); + effect->srcWave2 = get_le32(buffer + 8); + effect->oscWave = get_le32(buffer + 12); + effect->variable1 = get_le32(buffer + 16); + effect->variable2 = get_le32(buffer + 20); + effect->fxSpeed = get_le32(buffer + 24); + effect->oscSpeed = get_le32(buffer + 28); + effect->effectType = get_le32(buffer + 32); + effect->oscSelect = buffer[36]; + effect->resetEffect = buffer[37]; + effect->UNK00 = get_le16(buffer + 38); + + return 40; +} + +static long File_readInstrument(Instrument *instr, const uint8_t *buffer, size_t size) +{ + int i, j; + long sizeRead; + + if (size < 8712) return -1; + + instr->version = get_le16(buffer); + + memcpy(instr->name, buffer + 2, 32); + instr->name[32] = '\0'; + + instr->waveform = get_le16(buffer + 34); + instr->wavelength = get_le16(buffer + 36); + instr->masterVolume = get_le16(buffer + 38); + instr->amWave = get_le16(buffer + 40); + instr->amSpeed = get_le16(buffer + 42); + instr->amLoopPoint = get_le16(buffer + 44); + instr->finetune = get_le16(buffer + 46); + instr->fmWave = get_le16(buffer + 48); + instr->fmSpeed = get_le16(buffer + 50); + instr->fmLoopPoint = get_le16(buffer + 52); + instr->fmDelay = get_le16(buffer + 54); + instr->arpIndex = get_le16(buffer + 56); + + for (i = 0; i < SE_MAXCHANS; i++) + instr->m_ResetWave[i] = buffer[58 + i]; + + instr->panWave = get_le16(buffer + 74); + instr->panSpeed = get_le16(buffer + 76); + instr->panLoopPoint = get_le16(buffer + 78); + instr->UNK00 = get_le16(buffer + 80); + instr->UNK01 = get_le16(buffer + 82); + instr->UNK02 = get_le16(buffer + 84); + instr->UNK03 = get_le16(buffer + 86); + instr->UNK04 = get_le16(buffer + 88); + instr->UNK05 = get_le16(buffer + 90); + + buffer += 92; size -= 92; + + for (i = 0; i < 4; i++) { + sizeRead = File_readInstrumentEffect(&instr->effects[i], buffer, size); + if (sizeRead < 0) return -1; + buffer += sizeRead; size -= sizeRead; + } + + memcpy(instr->smpFullImportPath, buffer, 192); + instr->smpFullImportPath[192] = '\0'; + + buffer += 192; size -= 192; + + instr->UNK06 = get_le32(buffer); + instr->UNK07 = get_le32(buffer + 4); + instr->UNK08 = get_le32(buffer + 8); + instr->UNK09 = get_le32(buffer + 12); + instr->UNK0A = get_le32(buffer + 16); + instr->UNK0B = get_le32(buffer + 20); + instr->UNK0C = get_le32(buffer + 24); + instr->UNK0D = get_le32(buffer + 28); + instr->UNK0E = get_le32(buffer + 32); + instr->UNK0F = get_le32(buffer + 36); + instr->UNK10 = get_le32(buffer + 40); + instr->UNK11 = get_le32(buffer + 44); + instr->UNK12 = get_le16(buffer + 48); + + buffer += 50; size -= 50; + + instr->shareSmpDataFromInstr = get_le16(buffer); + instr->hasLoop = get_le16(buffer + 2); + instr->hasBidiLoop = get_le16(buffer + 4); + + buffer += 6; size -= 6; + + instr->smpStartPoint = get_le32(buffer); + instr->smpLoopPoint = get_le32(buffer + 4); + instr->smpEndPoint = get_le32(buffer + 8); + instr->hasSample = get_le32(buffer + 12); + instr->smpLength = get_le32(buffer + 16); + + buffer += 20; size -= 20; + + for (i = 0; i < SE_MAXCHANS; i++) { + for (j = 0; j < 0x100; j++) { + instr->synthBuffers[i][j] = get_le16(buffer + i * 512 + j * 2); + } + } + + return 8712; +} + +Song* File_loadSongMem(const uint8_t *buffer, size_t size) +{ + int i, j, k; + int songVer; + Subsong *subs; + Order *orderCol; + Order *order; + Row *row; + Instrument *instr; + Song *synSong; + long sizeRead; + + synSong = (Song *) calloc(1, sizeof(Song)); + if (!synSong) return NULL; + + /* + //unused vars + int8_t _local5[] = [0, 0, 0, 0, 0, 0]; + bool _local2 = false; + int _local7 = 0; + bool _local8 = true; + */ + + sizeRead = File_readHeader(&synSong->h, buffer, size); + if (sizeRead < 0) goto FAIL; + buffer += sizeRead; size -= sizeRead; + + songVer = synSong->h.version; + if ((songVer >= 3456) && (songVer <= 3457)){ + if (synSong->h.subsongNum > 0){ + synSong->subsongs = (Subsong *) malloc(synSong->h.subsongNum *sizeof(Subsong)); + if (!synSong->subsongs) goto FAIL; + + for (i = 0; i < synSong->h.subsongNum; i++) { + sizeRead = File_readSubSong(synSong->subsongs + i, buffer, size); + if (sizeRead < 0) goto FAIL; + buffer += sizeRead; size -= sizeRead; + } + + synSong->rows = (Row *) malloc(synSong->h.patNum * 64 *sizeof(Row)); + if (!synSong->rows) goto FAIL; + + for (i = 0, j = synSong->h.patNum * 64; i < j; i++) { + sizeRead = File_readRow(synSong->rows + i, buffer, size); + if (sizeRead < 0) goto FAIL; + buffer += sizeRead; size -= sizeRead; + } + + synSong->patNameSizes = (uint32_t *) malloc(synSong->h.patNum * sizeof(uint32_t)); + if (!synSong->patNameSizes) goto FAIL; + synSong->patternNames = calloc(sizeof(char *), synSong->h.patNum); + if (!synSong->patternNames) goto FAIL; + + for (i = 0; i < synSong->h.patNum; i++) { + if (size < 4) goto FAIL; + j = synSong->patNameSizes[i] = get_le32(buffer); + buffer += 4; size -= 4; + + if (size < j) goto FAIL; + + synSong->patternNames[i] = malloc(j + sizeof(char)); + if (!synSong->patternNames[i]) goto FAIL; + + memcpy(synSong->patternNames[i], buffer, j); + synSong->patternNames[i][j] = '\0'; + + buffer += j; size -= j; + } + + synSong->instruments = malloc(synSong->h.instrNum * sizeof(Instrument)); + if (!synSong->instruments) goto FAIL; + synSong->samples = calloc(sizeof(int16_t *), synSong->h.instrNum); + if (!synSong->samples) goto FAIL; + + for (i = 0; i < synSong->h.instrNum; i++) { + instr = &synSong->instruments[i]; + sizeRead = File_readInstrument(instr, buffer, size); + if (sizeRead < 0) goto FAIL; + buffer += sizeRead; size -= sizeRead; + + if (songVer == 3456){ + instr->shareSmpDataFromInstr = 0; + instr->hasLoop = 0; + instr->hasBidiLoop = 0; + instr->smpStartPoint = 0; + instr->smpLoopPoint = 0; + instr->smpEndPoint = 0; + if (instr->hasSample){ + instr->smpStartPoint = 0; + instr->smpEndPoint = (instr->smpLength / 2); + instr->smpLoopPoint = 0; + } + } + if (instr->hasSample){ + //instr->smpLength is in bytes, I think + if (size < instr->smpLength) goto FAIL; + synSong->samples[i] = malloc(instr->smpLength); + if (!synSong->samples[i]) goto FAIL; + memcpy(synSong->samples[i], buffer, instr->smpLength); + buffer += instr->smpLength; size -= instr->smpLength; + } else { + synSong->samples[i] = NULL; + } + + } + memcpy(synSong->arpTable, buffer, 0x100); + buffer += 0x100; size -= 0x100; + } else goto FAIL; + } else goto FAIL; + + return synSong; + +FAIL: + File_freeSong(synSong); + return NULL; +} + +void File_freeSong(Song *synSong) +{ + int i; + + if (synSong) { + if (synSong->subsongs) free(synSong->subsongs); + if (synSong->rows) free(synSong->rows); + if (synSong->patNameSizes) free(synSong->patNameSizes); + if (synSong->patternNames) { + for (i = 0; i < synSong->h.patNum; i++) { + if (synSong->patternNames[i]) free(synSong->patternNames[i]); + } + free(synSong->patternNames); + } + if (synSong->instruments) free(synSong->instruments); + if (synSong->samples) { + for (i = 0; i < synSong->h.instrNum; i++) { + if (synSong->samples[i]) free(synSong->samples[i]); + } + free(synSong->samples); + } + free(synSong); + } +} diff --git a/Frameworks/Syntrax-c/Syntrax-c/file.h b/Frameworks/Syntrax-c/Syntrax-c/file.h new file mode 100644 index 000000000..94d27fa92 --- /dev/null +++ b/Frameworks/Syntrax-c/Syntrax-c/file.h @@ -0,0 +1,19 @@ +#ifndef FILE_H +#define FILE_H + +#include "syntrax.h" + +#ifdef __cplusplus +extern "C" { +#endif + +Song* File_loadSong(const char *path); +Song* File_loadSongMem(const uint8_t *buffer, size_t size); + +void File_freeSong(Song *synSong); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Frameworks/Syntrax-c/Syntrax-c/resampler.c b/Frameworks/Syntrax-c/Syntrax-c/resampler.c new file mode 100644 index 000000000..d14995229 --- /dev/null +++ b/Frameworks/Syntrax-c/Syntrax-c/resampler.c @@ -0,0 +1,379 @@ +#include "resampler.h" + +#include +#include +#include + +/* Copyright (C) 2004-2008 Shay Green. + Copyright (C) 2015 Christopher Snowhill. This module is free software; you +can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#undef PI +#define PI 3.1415926535897932384626433832795029 + +enum { imp_scale = 0x7FFF }; +typedef int16_t imp_t; +typedef int32_t imp_off_t; /* for max_res of 512 and impulse width of 32, end offsets must be 32 bits */ + +#if RESAMPLER_BITS == 16 +typedef int32_t intermediate_t; +#elif RESAMPLER_BITS == 32 +typedef int64_t intermediate_t; +#endif + +static void gen_sinc( double rolloff, int width, double offset, double spacing, double scale, + int count, imp_t* out ) +{ + double angle; + + double const maxh = 256; + double const step = PI / maxh * spacing; + double const to_w = maxh * 2 / width; + double const pow_a_n = pow( rolloff, maxh ); + scale /= maxh * 2; + angle = (count / 2 - 1 + offset) * -step; + + while ( count-- ) + { + double w; + *out++ = 0; + w = angle * to_w; + if ( fabs( w ) < PI ) + { + double rolloff_cos_a = rolloff * cos( angle ); + double num = 1 - rolloff_cos_a - + pow_a_n * cos( maxh * angle ) + + pow_a_n * rolloff * cos( (maxh - 1) * angle ); + double den = 1 - rolloff_cos_a - rolloff_cos_a + rolloff * rolloff; + double sinc = scale * num / den - scale; + + out [-1] = (imp_t) (cos( w ) * sinc + sinc); + } + angle += step; + } +} + +enum { width = 32 }; +enum { stereo = 2 }; +enum { max_res = 512 }; +enum { min_width = (width < 4 ? 4 : width) }; +enum { adj_width = min_width / 4 * 4 + 2 }; +enum { write_offset = adj_width * stereo }; + +enum { buffer_size = 128 }; + +typedef struct _resampler +{ + int width_; + int rate_; + int inptr; + int infilled; + int outptr; + int outfilled; + + int latency; + + imp_t const* imp; + imp_t impulses [max_res * (adj_width + 2 * (sizeof(imp_off_t) / sizeof(imp_t)))]; + sample_t buffer_in[buffer_size * stereo * 2]; + sample_t buffer_out[buffer_size * stereo]; +} resampler; + +void * resampler_create() +{ + resampler *r = (resampler *) malloc(sizeof(resampler)); + if (r) resampler_clear(r); + return r; +} + +void * resampler_dup(const void *_r) +{ + void *_t = (resampler *) malloc(sizeof(resampler)); + if (_t) resampler_dup_inplace(_t, _r); + return _t; +} + +void resampler_dup_inplace(void *_t, const void *_r) +{ + const resampler *r = (const resampler *)_r; + resampler *t = (resampler *)_t; + if (r && t) + { + memcpy(t, r, sizeof(resampler)); + t->imp = t->impulses + (r->imp - r->impulses); + } + else if (t) + { + resampler_clear(t); + } +} + +void resampler_destroy(void *r) +{ + free(r); +} + +void resampler_clear(void *_r) +{ + resampler * r = (resampler *)_r; + r->width_ = adj_width; + r->inptr = 0; + r->infilled = 0; + r->outptr = 0; + r->outfilled = 0; + r->latency = 0; + r->imp = r->impulses; + + resampler_set_rate(r, 1.0); +} + +void resampler_set_rate( void *_r, double new_factor ) +{ + int step; //const + double filter; //const + double fraction, pos; + int n; + + resampler *rs = (resampler *)_r; + imp_t* out; + + double const rolloff = 0.999; + double const gain = 1.0; + + /* determine number of sub-phases that yield lowest error */ + double ratio_ = 0.0; + int res = -1; + { + double least_error = 2; + double pos = 0; + int r; + for ( r = 1; r <= max_res; r++ ) + { + double nearest, error; + pos += new_factor; + nearest = floor( pos + 0.5 ); + error = fabs( pos - nearest ); + if ( error < least_error ) + { + res = r; + ratio_ = nearest / res; + least_error = error; + } + } + } + rs->rate_ = ratio_; + + /* how much of input is used for each output sample */ + step = stereo * (int) floor( ratio_ ); + fraction = fmod( ratio_, 1.0 ); + + filter = (ratio_ < 1.0) ? 1.0 : 1.0 / ratio_; + pos = 0.0; + /*int input_per_cycle = 0;*/ + out = rs->impulses; + + for ( n = res; --n >= 0; ) + { + int cur_step; + + gen_sinc( rolloff, (int) (rs->width_ * filter + 1) & ~1, pos, filter, + (double)(imp_scale * gain * filter), (int) rs->width_, out ); + out += rs->width_; + + cur_step = step; + pos += fraction; + if ( pos >= 0.9999999 ) + { + pos -= 1.0; + cur_step += stereo; + } + + ((imp_off_t*)out)[0] = (cur_step - rs->width_ * 2 + 4) * sizeof (sample_t); + ((imp_off_t*)out)[1] = 2 * sizeof (imp_t) + 2 * sizeof (imp_off_t); + out += 2 * (sizeof(imp_off_t) / sizeof(imp_t)); + /*input_per_cycle += cur_step;*/ + } + /* last offset moves back to beginning of impulses*/ + ((imp_off_t*)out) [-1] -= (char*) out - (char*) rs->impulses; + + rs->imp = rs->impulses; +} + +int resampler_get_free(void *_r) +{ + resampler *r = (resampler *)_r; + return buffer_size * stereo - r->infilled; +} + +int resampler_get_min_fill(void *_r) +{ + resampler *r = (resampler *)_r; + const int min_needed = write_offset + stereo; + const int latency = r->latency ? 0 : adj_width; + int min_free = min_needed - r->infilled - latency; + return min_free < 0 ? 0 : min_free; +} + +void resampler_write_pair(void *_r, sample_t ls, sample_t rs) +{ + resampler *r = (resampler *)_r; + + if (!r->latency) + { + int i; + for ( i = 0; i < adj_width / 2; ++i) + { + r->buffer_in[r->inptr + 0] = 0; + r->buffer_in[r->inptr + 1] = 0; + r->buffer_in[buffer_size * stereo + r->inptr + 0] = 0; + r->buffer_in[buffer_size * stereo + r->inptr + 1] = 0; + r->inptr = (r->inptr + stereo) % (buffer_size * stereo); + r->infilled += stereo; + } + r->latency = 1; + } + + if (r->infilled < buffer_size * stereo) + { + r->buffer_in[r->inptr + 0] = ls; + r->buffer_in[r->inptr + 1] = rs; + r->buffer_in[buffer_size * stereo + r->inptr + 0] = ls; + r->buffer_in[buffer_size * stereo + r->inptr + 1] = rs; + r->inptr = (r->inptr + stereo) % (buffer_size * stereo); + r->infilled += stereo; + } +} + +#if defined(_MSC_VER) || defined(__GNUC__) +#define restrict __restrict +#endif + +static const sample_t * resampler_inner_loop( resampler *r, sample_t** out_, + sample_t const* out_end, sample_t const in [], int in_size ) +{ + in_size -= write_offset; + if ( in_size > 0 ) + { + sample_t* restrict out = *out_; + sample_t const* const in_end = in + in_size; + imp_t const* imp = r->imp; + + do + { + int n; + /* accumulate in extended precision*/ + int pt = imp [0]; + intermediate_t l = (intermediate_t)pt * (intermediate_t)(in [0]); + intermediate_t r = (intermediate_t)pt * (intermediate_t)(in [1]); + if ( out >= out_end ) + break; + for ( n = (adj_width - 2) / 2; n; --n ) + { + pt = imp [1]; + l += (intermediate_t)pt * (intermediate_t)(in [2]); + r += (intermediate_t)pt * (intermediate_t)(in [3]); + + /* pre-increment more efficient on some RISC processors*/ + imp += 2; + pt = imp [0]; + r += (intermediate_t)pt * (intermediate_t)(in [5]); + in += 4; + l += (intermediate_t)pt * (intermediate_t)(in [0]); + } + pt = imp [1]; + l += (intermediate_t)pt * (intermediate_t)(in [2]); + r += (intermediate_t)pt * (intermediate_t)(in [3]); + + /* these two "samples" after the end of the impulse give the + * proper offsets to the next input sample and next impulse */ + in = (sample_t const*) ((char const*) in + ((imp_off_t*)(&imp [2]))[0]); /* some negative value */ + imp = (imp_t const*) ((char const*) imp + ((imp_off_t*)(&imp [2]))[1]); /* small positive or large negative */ + + out [0] = (sample_t) (l >> 15); + out [1] = (sample_t) (r >> 15); + out += 2; + } + while ( in < in_end ); + + r->imp = imp; + *out_ = out; + } + return in; +} + +#undef restrict + +static int resampler_wrapper( resampler *r, sample_t out [], int* out_size, + sample_t const in [], int in_size ) +{ + sample_t* out_ = out; + int result = resampler_inner_loop( r, &out_, out + *out_size, in, in_size ) - in; + + *out_size = out_ - out; + return result; +} + +static void resampler_fill( resampler *r ) +{ + while (!r->outfilled && r->infilled) + { + int inread; + + int writepos = ( r->outptr + r->outfilled ) % (buffer_size * stereo); + int writesize = (buffer_size * stereo) - writepos; + if ( writesize > ( buffer_size * stereo - r->outfilled ) ) + writesize = buffer_size * stereo - r->outfilled; + inread = resampler_wrapper(r, &r->buffer_out[writepos], &writesize, &r->buffer_in[buffer_size * stereo + r->inptr - r->infilled], r->infilled); + r->infilled -= inread; + r->outfilled += writesize; + if (!inread) + break; + } +} + +int resampler_get_avail(void *_r) +{ + resampler *r = (resampler *)_r; + if (r->outfilled < stereo && r->infilled >= r->width_) + resampler_fill( r ); + return r->outfilled; +} + +static void resampler_read_pair_internal( resampler *r, sample_t *ls, sample_t *rs, int advance ) +{ + if (r->outfilled < stereo) + resampler_fill( r ); + if (r->outfilled < stereo) + { + *ls = 0; + *rs = 0; + return; + } + *ls = r->buffer_out[r->outptr + 0]; + *rs = r->buffer_out[r->outptr + 1]; + if (advance) + { + r->outptr = (r->outptr + 2) % (buffer_size * stereo); + r->outfilled -= stereo; + } +} + +void resampler_read_pair( void *_r, sample_t *ls, sample_t *rs ) +{ + resampler *r = (resampler *)_r; + resampler_read_pair_internal(r, ls, rs, 1); +} + +void resampler_peek_pair( void *_r, sample_t *ls, sample_t *rs ) +{ + resampler *r = (resampler *)_r; + resampler_read_pair_internal(r, ls, rs, 0); +} diff --git a/Frameworks/Syntrax-c/Syntrax-c/resampler.h b/Frameworks/Syntrax-c/Syntrax-c/resampler.h new file mode 100644 index 000000000..356ba9c4a --- /dev/null +++ b/Frameworks/Syntrax-c/Syntrax-c/resampler.h @@ -0,0 +1,75 @@ +#ifndef _RESAMPLER_H_ +#define _RESAMPLER_H_ + +/* Copyright (C) 2004-2008 Shay Green. + Copyright (C) 2015 Christopher Snowhill. This module is free software; you +can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#define RESAMPLER_BITS 32 +#define RESAMPLER_DECORATE syntrax + +#ifdef RESAMPLER_DECORATE +#undef PASTE +#undef EVALUATE +#define PASTE(a,b) a ## b +#define EVALUATE(a,b) PASTE(a,b) +#define resampler_create EVALUATE(RESAMPLER_DECORATE,_resampler_create) +#define resampler_dup EVALUATE(RESAMPLER_DECORATE,_resampler_dup) +#define resampler_dup_inplace EVALUATE(RESAMPLER_DECORATE,_resampler_dup_inplace) +#define resampler_destroy EVALUATE(RESAMPLER_DECORATE,_resampler_destroy) +#define resampler_clear EVALUATE(RESAMPLER_DECORATE,_resampler_clear) +#define resampler_set_rate EVALUATE(RESAMPLER_DECORATE,_resampler_set_rate) +#define resampler_get_free EVALUATE(RESAMPLER_DECORATE,_resampler_get_free) +#define resampler_get_min_fill EVALUATE(RESAMPLER_DECORATE,_resampler_get_min_fill) +#define resampler_write_pair EVALUATE(RESAMPLER_DECORATE,_resampler_write_pair) +#define resampler_get_avail EVALUATE(RESAMPLER_DECORATE,_resampler_get_avail) +#define resampler_read_pair EVALUATE(RESAMPLER_DECORATE,_resampler_read_pair) +#define resampler_peek_pair EVALUATE(RESAMPLER_DECORATE,_resampler_peek_pair) +#endif + +#include + +#if RESAMPLER_BITS == 16 +typedef int16_t sample_t; +#elif RESAMPLER_BITS == 32 +typedef int32_t sample_t; +#else +#error Choose a bit depth! +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +void * resampler_create(); +void * resampler_dup(const void *); +void resampler_dup_inplace(void *, const void *); +void resampler_destroy(void *); + +void resampler_clear(void *); + +void resampler_set_rate( void *, double new_factor ); + +int resampler_get_free(void *); +int resampler_get_min_fill(void *); + +void resampler_write_pair(void *, sample_t ls, sample_t rs); + +int resampler_get_avail(void *); + +void resampler_read_pair( void *, sample_t *ls, sample_t *rs ); +void resampler_peek_pair( void *, sample_t *ls, sample_t *rs ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Frameworks/Syntrax-c/Syntrax-c/syntrax.c b/Frameworks/Syntrax-c/Syntrax-c/syntrax.c new file mode 100644 index 000000000..5ca0e6322 --- /dev/null +++ b/Frameworks/Syntrax-c/Syntrax-c/syntrax.c @@ -0,0 +1,2354 @@ +#include +#include +#include +#define _USE_MATH_DEFINES +#include +#include + +#include "syntrax.h" +#include "file.h" +#include "resampler.h" + +static void reset(Player *p) +{ + int i, j; + + if (p->overlapBuff){ + memset(p->overlapBuff, 0, SE_OVERLAP * 2 *2 + 2); + } + + if (p->delayBufferL && p->delayBufferR){ + memset(p->delayBufferL, 0, 65536 *2); + memset(p->delayBufferR, 0, 65536 *2); + } + if (p->tuneChannels){ + for (i = 0; i < SE_MAXCHANS; i++) { + TuneChannel *tc = &p->tuneChannels[i]; + Voice *v = &p->voices[i]; + + tc->EQMIWERPIF = 0; + tc->LJHG = 0; + tc->insNum = -1; + tc->HFRLJCG = 0; + tc->ACKCWV = 0; + tc->ELPHLDR = 0; + tc->TVORFCC = 0; + tc->freq = 0; + tc->BNWIGU = 0; + tc->UHYDBDDI = 0; + tc->XESAWSO = 0; + tc->JOEEPJCI = 0; + tc->fmDelay = 0; + tc->sampleBuffer = NULL; + tc->smpLoopEnd = 0; + //tc->smpLength = 0; + tc->sampPos = 0; + tc->EYRXAB = 0; + tc->volume = 0; + tc->panning = 0; + tc->VNVJPDIWAJQ = 0; + tc->smpLoopStart = 0; + tc->hasLoop = 0; + tc->hasBidiLoop = 0; + tc->isPlayingBackward = 0; + tc->hasLooped = 0; + + v->waveBuff = p->silentBuffer; + for (j = 0; j < 4; j++) { + VoiceEffect *ve = &tc->effects[j]; + + ve->QOMCBTRPXF = 0; + ve->TIPUANVVR = 0; + ve->MFATTMREMVP = 0; + ve->MDTMBBIQHRQ = 0; + ve->RKF = 0; + ve->DQVLFV = 0; + ve->ILHG = 0; + ve->YLKJB = 0; + ve->VMBNMTNBQU = 0; + ve->ABJGHAUY = 0; + ve->SPYK = 0; + + } + memset(&tc->synthBuffers, 0, 0x100 * SE_MAXCHANS *2 + 2); + } + } +} + +static int generateTables(Player *p) +{ + int i, j; + + p->dynamorphTable = (int16_t *) malloc(0x100 *2); + if (!p->dynamorphTable) return -1; + + for (i = 0; i < 0x0100; i++ ) { + p->dynamorphTable[i] = (sin(((M_PI * i) / 128)) * 32760); + } + + //debug Asscilloscope says 0xF8 to 0x61FFB + //we probably don't have uint24_t at our disposal + //uint32_t it is, then + p->freqTable = (uint32_t *) malloc(SE_NROFFINETUNESTEPS * 128 *4); + if (!p->freqTable) return -1; + for (i = 0; i < SE_NROFFINETUNESTEPS; i++) { + double x; + for (j = 0; j < 128; j++) { + x = (((j + 3) * 16) - i); + x = (x / 192); + x = pow(2, x); + x = (x * 220) + 0.5; + p->freqTable[i* 128 + j] = (int)(x); + } + } + + return 0; +} + +void playerDestroy(Player *p) +{ + int i; + + if (p) { + if (p->dynamorphTable) free(p->dynamorphTable); + if (p->freqTable) free(p->freqTable); + if (p->silentBuffer) free(p->silentBuffer); + if (p->overlapBuff) free(p->overlapBuff); + if (p->delayBufferL) free(p->delayBufferL); + if (p->delayBufferR) free(p->delayBufferR); + if (p->tuneChannels) free(p->tuneChannels); + if (p->voices) { + for (i = 0; i < SE_MAXCHANS; i++) + { + resampler_destroy(p->voices[i].resampler[0]); + resampler_destroy(p->voices[i].resampler[1]); + } + free(p->voices); + } + + if (p->instruments) free(p->instruments); + + free(p); + } +} + +Player * playerCreate(int SAMPLEFREQUENCY) +{ + int i, j; + + Player* p; + + srand(time(NULL)); + + p = (Player *) calloc(1, sizeof(Player)); + if (!p) return NULL; + + p->bufflen = BUFFERLENGTH; + if (generateTables(p) < 0) goto FAIL; + + p->SAMPLEFREQUENCY = SAMPLEFREQUENCY; + + p->overlapPos = 0; + + p->silentBuffer = malloc(0x0100 *2); + if (!p->silentBuffer) goto FAIL; + memset(p->silentBuffer, 0, 0x0100 *2); + + p->ISWLKT = 0; + p->posCoarse = 0; + p->posFine = 0; + p->bkpDelayPos = 0; + p->DONGS = 0; + p->AMYGPFQCHSW = 0; + p->selectedSubsong = 0; + p->PQV = 0; + p->someCounter = 0; + p->WDTECTE = 0; + p->sePmSong = SE_PM_SONG; + p->AMVM = 0x0100; + p->channelNumber = 0; + p->delayPos = 0; + + p->otherSamplesPerBeat = 2200; + p->samplesPerBeat = 2200; + + p->overlapBuff = malloc(SE_OVERLAP * 2 *2 + 2); + if (!p->overlapBuff) goto FAIL; + p->delayBufferL = malloc(65536 *2); + if (!p->delayBufferL) goto FAIL; + p->delayBufferR = malloc(65536 *2); + if (!p->delayBufferR) goto FAIL; + + p->tuneChannels = malloc(SE_MAXCHANS *sizeof(TuneChannel)); + if (!p->tuneChannels) goto FAIL; + p->voices = malloc(SE_MAXCHANS *sizeof(Voice)); + if (!p->voices) goto FAIL; + + for (i = 0; i < SE_MAXCHANS; i++) + { + Voice *v = &p->voices[i]; + memset(v, 0, sizeof(Voice)); + + v->resampler[0] = resampler_create(); + v->resampler[1] = resampler_create(); + if (!v->resampler[0] || !v->resampler[1]) goto FAIL; + } + + reset(p); + + return p; + +FAIL: + playerDestroy(p); + return NULL; +} + +static void instrEffect(Player *p, int chanNum) +{ + //TODO: minimize all the vars + //too many of them + int i, j; + int _local3; + int destWave; + int16_t *destBuff; + int pos; + int srcWave1; + int _local10; + int srcWave2; + int16_t *srcBuff1; + int16_t *srcBuff2; + double _local16; + double _local17; + double _local18; + int oscWave; + int16_t *oscBuff; + int _local21; + int _local22; + int _local23; + int _local25; + int _local26; + int _local27; + int var1; + int var2; + double _local30; + double _local31; + int _local32; + int _local33; + int _local34; + int _local35; + int _local36; + int _local37; + int _local38; + int _local39; + int _local40; + int _local43; + int butt, ron, pat, buf2, buf1; + + TuneChannel *tc = &p->tuneChannels[chanNum]; + const Instrument *ins = &p->instruments[tc->insNum]; + + for (i = 0; i < 4; i++ ) { + const InstrumentEffect *ie = &ins->effects[i]; + VoiceEffect *ve = &tc->effects[i]; + + ve->MFATTMREMVP = (ve->MFATTMREMVP + ie->oscSpeed); + ve->MFATTMREMVP = (ve->MFATTMREMVP & 0xFF); + switch (ie->effectType) { + + //NONE + case 0: + break; + + //NEGATE + case 1: + destWave = ie->destWave; + _local3 = ie->fxSpeed; + pos = ve->QOMCBTRPXF; + destBuff = tc->synthBuffers[destWave]; + + for (j = 0; j < _local3; j++ ) { + pos++; + pos = (pos & 0xFF); + destBuff[pos] = (0 - destBuff[pos]); + + } + ve->QOMCBTRPXF = pos; + break; + + //SWEEP + case 2: + destWave = ie->destWave; + _local3 = ie->fxSpeed; + destBuff = tc->synthBuffers[destWave]; + + + for (pos = 0, j = 0; j < 0x0100; j++ ) { + destBuff[j] = (destBuff[j] + pos); + destBuff[j] = (destBuff[j] + 0x8000); + destBuff[j] = (destBuff[j] & 0xFFFF); + destBuff[j] = (destBuff[j] - 0x8000); + pos = (pos + _local3); + + } + break; + + //AVERAGER + case 3: + destWave = ie->destWave; + srcWave1 = ie->srcWave1; + destBuff = tc->synthBuffers[destWave]; + srcBuff1 = tc->synthBuffers[srcWave1]; + _local3 = ie->fxSpeed; + pos = 0; + if (_local3 > 12){ + _local3 = 12; + } + + for (_local10 = 0; _local10 < _local3; _local10++ ) { + destBuff[0] = ((srcBuff1[0xFF] + srcBuff1[1]) >> 1); + + for (j = 1; j < 0xFF; j++ ) { + destBuff[j] = ((srcBuff1[j - 1] + srcBuff1[j + 1]) >> 1); + + } + destBuff[0xFF] = ((srcBuff1[254] + srcBuff1[0]) >> 1); + + } + break; + + //WAVEMIX + case 4: + destWave = ie->destWave; + srcWave1 = ie->srcWave1; + srcWave2 = ie->srcWave2; + destBuff = tc->synthBuffers[destWave]; + srcBuff1 = tc->synthBuffers[srcWave1]; + srcBuff2 = tc->synthBuffers[srcWave2]; + _local3 = ie->fxSpeed; + ve->QOMCBTRPXF = (ve->QOMCBTRPXF + _local3); + ve->QOMCBTRPXF = (ve->QOMCBTRPXF & 0xFF); + pos = ve->QOMCBTRPXF; + + for (j = 0; j < 0x0100; j++ ) { + destBuff[j] = ((srcBuff1[j] + srcBuff2[pos]) >> 1); + pos++; + pos = (pos & 0xFF); + + } + break; + + //FILTER + case 5: + destWave = ie->destWave; + srcWave1 = ie->srcWave1; + srcWave2 = ie->oscWave - 1; + destBuff = tc->synthBuffers[destWave]; + + srcBuff1 = tc->synthBuffers[srcWave1]; + srcBuff2 = srcWave2 >= 0 ? tc->synthBuffers[srcWave2] : NULL; + pos = ve->MFATTMREMVP; + + if (ie->oscWave == 0){ + _local16 = (double)((ie->variable1 * 20)); + _local17 = (double)((ie->variable2 * 16)); + } else { + if (ie->oscSelect){ + _local16 = (double)((ie->variable1 * 20)); + _local17 = ((double)((srcBuff2[pos] + 0x8000)) / 16); + } else { + _local16 = ((double)((srcBuff2[pos] + 0x8000)) / 13); + _local17 = (double)((ie->variable2 * 16)); + } + } + ve->DQVLFV = exp((-((2 * M_PI)) * (_local17 / 22000))); + ve->RKF = (((-4 * ve->DQVLFV) / (1 + ve->DQVLFV)) * cos(((2 * M_PI) * (_local16 / 22000)))); + ve->MDTMBBIQHRQ = ((1 - ve->DQVLFV) * sqrt((1 - ((ve->RKF * ve->RKF) / (4 * ve->DQVLFV))))); + + for (j = 0; j < 0x0100; j++) { + _local18 = (((ve->MDTMBBIQHRQ * ((double)(srcBuff1[j]) / 0x8000)) - (ve->RKF * ve->ILHG)) - (ve->DQVLFV * ve->YLKJB)); + ve->YLKJB = ve->ILHG; + ve->ILHG = _local18; + if (_local18 > 0.9999){ + _local18 = 0.9999; + } + if (_local18 < -0.9999){ + _local18 = -0.9999; + } + destBuff[j] = (_local18 * 0x8000); + + } + break; + + //FILTWHISTLE + case 6: + destWave = ie->destWave; + srcWave1 = ie->srcWave1; + srcWave2 = ie->oscWave - 1; + destBuff = tc->synthBuffers[destWave]; + + srcBuff1 = tc->synthBuffers[srcWave1]; + srcBuff2 = srcWave2 >= 0 ? tc->synthBuffers[srcWave2] : NULL; + pos = ve->MFATTMREMVP; + + if (ie->oscWave == 0){ + _local16 = (double)((ie->variable1 * 20)); + _local17 = (double)((ie->variable2 * 16)); + } else { + if (ie->oscSelect){ + _local16 = (double)((ie->variable1 * 20)); + _local17 = ((double)((srcBuff2[pos] + 0x8000)) / 16); + } else { + _local16 = ((double)((srcBuff2[pos] + 0x8000)) / 13); + _local17 = (double)((ie->variable2 * 16)); + } + } + ve->DQVLFV = exp((-((2 * M_PI)) * (_local17 / 22000))); + ve->RKF = (((-4 * ve->DQVLFV) / (1 + ve->DQVLFV)) * cos(((2 * M_PI) * (_local16 / 22000)))); + ve->MDTMBBIQHRQ = ((1 - ve->DQVLFV) * sqrt((1 - ((ve->RKF * ve->RKF) / (4 * ve->DQVLFV))))); + ve->DQVLFV = (ve->DQVLFV * 1.2); + + for (j = 0; j < 0x0100; j++ ) { + _local18 = (((ve->MDTMBBIQHRQ * ((double)(srcBuff1[j]) / 0x8000)) - (ve->RKF * ve->ILHG)) - (ve->DQVLFV * ve->YLKJB)); + ve->YLKJB = ve->ILHG; + ve->ILHG = _local18; + if (_local18 > 0.9999){ + _local18 = 0.9999; + } + if (_local18 < -0.9999){ + _local18 = -0.9999; + } + destBuff[j] = (_local18 * 0x8000); + + } + break; + + //MORPH + case 7: + destWave = ie->destWave; + srcWave1 = ie->srcWave1; + srcWave2 = ie->srcWave2; + oscWave = ie->oscWave - 1; + destBuff = tc->synthBuffers[destWave]; + + srcBuff1 = tc->synthBuffers[srcWave1]; + srcBuff2 = tc->synthBuffers[srcWave2]; + oscBuff = oscWave >= 0 ? tc->synthBuffers[oscWave] : NULL; + pos = ve->MFATTMREMVP; + + if (ie->oscWave == 0){ + _local21 = ie->variable1; + } else { + if (ie->oscSelect){ + _local21 = ie->variable1; + } else { + _local21 = ((oscBuff[pos] + 0x8000) / 0x0100); + } + } + _local22 = (0xFF - _local21); + + for (j = 0; j < 0x0100; j++) { + _local23 = (((srcBuff1[j] * _local21) / 0x0100) + ((srcBuff2[j] * _local22) / 0x0100)); + destBuff[j] = _local23; + + } + break; + + //DYNAMORPH + case 8: + destWave = ie->destWave; + srcWave1 = ie->srcWave1; + srcWave2 = ie->srcWave2; + oscWave = ie->oscWave - 1; + destBuff = tc->synthBuffers[destWave]; + + srcBuff1 = tc->synthBuffers[srcWave1]; + srcBuff2 = tc->synthBuffers[srcWave2]; + oscBuff = oscWave >= 0 ? tc->synthBuffers[oscWave] : NULL; + pos = ve->MFATTMREMVP; + + if (ie->oscWave == 0){ + _local25 = ie->variable1; + } else { + if (ie->oscSelect){ + _local25 = ie->variable1; + } else { + _local25 = ((oscBuff[pos] + 0x8000) / 0x0100); + } + } + + for (j = 0; j < 0x0100; j++) { + _local21 = ((p->dynamorphTable[_local25] >> 8) + 128); + _local22 = (0xFF - _local21); + _local23 = (((srcBuff1[j] * _local21) / 0x0100) + ((srcBuff2[j] * _local22) / 0x0100)); + destBuff[j] = _local23; + _local25++; + _local25 = (_local25 & 0xFF); + + } + break; + + //DISTORTION + case 9: + destWave = ie->destWave; + srcWave1 = ie->srcWave1; + oscWave = ie->oscWave - 1; + destBuff = tc->synthBuffers[destWave]; + + srcBuff1 = tc->synthBuffers[srcWave1]; + oscBuff = oscWave >= 0 ? tc->synthBuffers[oscWave] : NULL; + pos = ve->MFATTMREMVP; + + if (ie->oscWave == 0){ + _local21 = ie->variable1; + } else { + if (ie->oscSelect){ + _local21 = ie->variable1; + } else { + _local21 = ((oscBuff[pos] + 0x8000) / 0x0100); + } + } + + for (j = 0; j < 0x0100; j++) { + _local23 = ((srcBuff1[j] * _local21) / 16); + _local23 = (_local23 + 0x8000); + if (_local23 < 0){ + _local23 = -(_local23); + } + _local23 = (_local23 % 131072); + if (_local23 > 0xFFFF){ + _local23 = (131071 - _local23); + } + _local23 = (_local23 & 0xFFFF); + _local23 = (_local23 - 0x8000); + destBuff[j] = _local23; + + } + break; + + //SCROLL LEFT + case 10: + destWave = ie->destWave; + destBuff = tc->synthBuffers[destWave]; + _local10 = destBuff[0]; + + for (j = 0; j < 0xFF; j++) { + destBuff[j] = destBuff[j + 1]; + + } + destBuff[0xFF] = _local10; + break; + + //UPSAMPLE + case 11: + pos = ve->QOMCBTRPXF; + if (pos != 0){ + ve->QOMCBTRPXF--; + break; + } + ve->QOMCBTRPXF = ie->variable1; + destWave = ie->destWave; + destBuff = tc->synthBuffers[destWave]; + + for (j = 0; j < 128; j++) { + destBuff[j] = destBuff[j * 2]; + + } + + for (j = 0; j < 128; j++) { + destBuff[j + 128] = destBuff[j]; + + } + break; + + //CLIPPER + case 12: + destWave = ie->destWave; + srcWave1 = ie->srcWave1; + oscWave = ie->oscWave - 1; + destBuff = tc->synthBuffers[destWave]; + + srcBuff1 = tc->synthBuffers[srcWave1]; + oscBuff = oscWave >= 0 ? tc->synthBuffers[oscWave] : NULL; + pos = ve->MFATTMREMVP; + + if (ie->oscWave == 0){ + _local21 = ie->variable1; + } else { + if (ie->oscSelect){ + _local21 = ie->variable1; + } else { + _local21 = ((oscBuff[pos] + 0x8000) / 0x0100); + } + } + + for (j = 0; j < 0x0100; j++) { + _local23 = ((srcBuff1[j] * _local21) / 16); + if (_local23 < -32767){ + _local23 = -32767; + } + if (_local23 > 32767){ + _local23 = 32767; + } + destBuff[j] = _local23; + + } + break; + + //LOWPASS + case 13: + destWave = ie->destWave; + srcWave1 = ie->srcWave1; + srcWave2 = ie->oscWave - 1; + destBuff = tc->synthBuffers[destWave]; + + srcBuff1 = tc->synthBuffers[srcWave1]; + srcBuff2 = srcWave2 >= 0 ? tc->synthBuffers[srcWave2] : NULL; + pos = ve->MFATTMREMVP; + + if (ie->oscWave == 0){ + var1 = ie->variable1; + var2 = ie->variable2; + var1 = var1 * 16; + } else { + if (ie->oscSelect){ + var1 = ie->variable1; + var2 = ((srcBuff2[pos] + 0x8000) >> 8); + var1 = (var1 * 16); + } else { + //_local28 = ((_local14->data[_local7] + 0x8000) / 16); + var1 = ((srcBuff2[pos] + 0x8000) >> 4); + var2 = ie->variable2; + } + } + _local30 = (var1 - 920); + _local31 = (228 + var1); + _local26 = (int)(((2 * M_PI) * _local31)); + _local27 = (707 + ((1000 * var2) / 128)); + _local36 = ve->ABJGHAUY; + _local37 = ve->SPYK; + _local38 = ve->VMBNMTNBQU; + _local40 = 8; + + for (j = 0; j < 0x0100; j++) { + _local32 = ((_local26 * _local40) / 100); + _local39 = srcBuff1[j]; + _local33 = ((((_local36 * 1000) / _local27) - _local37) + _local39); + _local34 = (_local36 - ((_local32 * (_local38 / 100)) / 100)); + _local35 = (_local37 - ((_local32 * (_local36 / 100)) / 100)); + _local38 = _local33; + _local36 = _local34; + _local37 = _local35; + _local3 = _local37; + if (_local3 > 32767){ + _local3 = 32767; + } + if (_local3 < -32767){ + _local3 = -32767; + } + destBuff[j] = _local3; + + } + ve->ABJGHAUY = _local36; + ve->SPYK = _local37; + ve->VMBNMTNBQU = _local38; + break; + + //HIGHPASS + case 14: + destWave = ie->destWave; + srcWave1 = ie->srcWave1; + srcWave2 = ie->oscWave - 1; + destBuff = tc->synthBuffers[destWave]; + + srcBuff1 = tc->synthBuffers[srcWave1]; + srcBuff2 = srcWave2 >= 0 ? tc->synthBuffers[srcWave2] : NULL; + pos = ve->MFATTMREMVP; + + if (ie->oscWave == 0){ + var1 = ie->variable1; + var2 = ie->variable2; + var1 = (var1 * 32); + } else { + if (ie->oscSelect) { + var1 = ie->variable1; + var2 = ((srcBuff2[pos] + 0x8000) >> 8); + var1 = (var1 * 32); + } else { + //checked with IDA against windows ver. of Syntrax(v1.03) + //It's possible that the effect has changed along the way(v2.xx) + //same for lowpass + //_local28 = ((_local14->data[_local7] + 0x8000) / 16); + var1 = ((srcBuff2[pos] + 0x8000) >> 3); + var2 = ie->variable2; + } + } + _local30 = (var1 - 920); + _local31 = (228 + var1); + _local26 = (int)(((2 * M_PI) * _local31)); + _local27 = (707 + ((1000 * var2) / 128)); + _local36 = ve->ABJGHAUY; + _local37 = ve->SPYK; + _local38 = ve->VMBNMTNBQU; + _local40 = 8; + + for (j = 0; j < 0x0100; j++) { + _local32 = ((_local26 * _local40) / 100); + _local39 = srcBuff1[j]; + _local33 = ((((_local36 * 1000) / _local27) - _local37) + _local39); + _local34 = (_local36 - ((_local32 * (_local38 / 100)) / 100)); + _local35 = (_local37 - ((_local32 * (_local36 / 100)) / 100)); + _local38 = _local33; + _local36 = _local34; + _local37 = _local35; + _local3 = _local38; + if (_local3 > 32767){ + _local3 = 32767; + } + if (_local3 < -32767){ + _local3 = -32767; + } + destBuff[j] = _local3; + + } + ve->ABJGHAUY = _local36; + ve->SPYK = _local37; + ve->VMBNMTNBQU = _local38; + break; + + //BANDPASS + case 15: + destWave = ie->destWave; + srcWave1 = ie->srcWave1; + srcWave2 = ie->oscWave - 1; + destBuff = tc->synthBuffers[destWave]; + + srcBuff1 = tc->synthBuffers[srcWave1]; + srcBuff2 = srcWave2 >= 0 ? tc->synthBuffers[srcWave2] : NULL; + pos = ve->MFATTMREMVP; + + if (ie->oscWave == 0){ + var1 = ie->variable1; + var2 = ie->variable2; + var1 = var1 * 16; + } else { + if (ie->oscSelect){ + var1 = ie->variable1; + var2 = ((srcBuff2[pos] + 0x8000) >> 8); + var1 = var1 * 16; + } else { + var1 = ((srcBuff2[pos] + 0x8000) / 16); + var2 = ie->variable2; + } + } + _local30 = (var1 - 920); + _local31 = (228 + var1); + _local26 = (int)(((2 * M_PI) * _local31)); + _local27 = (707 + ((1000 * var2) / 128)); + _local36 = ve->ABJGHAUY; + _local37 = ve->SPYK; + _local38 = ve->VMBNMTNBQU; + _local40 = 8; + + for (j = 0; j < 0x0100; j++) { + _local32 = ((_local26 * _local40) / 100); + _local39 = srcBuff1[j]; + _local33 = ((((_local36 * 1000) / _local27) - _local37) + _local39); + _local34 = (_local36 - ((_local32 * (_local38 / 100)) / 100)); + _local35 = (_local37 - ((_local32 * (_local36 / 100)) / 100)); + _local38 = _local33; + _local36 = _local34; + _local37 = _local35; + _local3 = _local36; + if (_local3 > 32767){ + _local3 = 32767; + } + if (_local3 < -32767){ + _local3 = -32767; + } + destBuff[j] = _local3; + + } + ve->ABJGHAUY = _local36; + ve->SPYK = _local37; + ve->VMBNMTNBQU = _local38; + break; + + //METALNOISE + case 16: + destWave = ie->destWave; + destBuff = tc->synthBuffers[destWave]; + for (j = 0; j < 0x0100; j++ ) { + //Something very bad happens here + //I think it's fixed now. + destBuff[j] = (int)(((double)(rand()) / (double)(RAND_MAX)) * 65530 - 0x8000); + } + break; + + //SQUASH + case 17: + destWave = ie->destWave; + srcWave1 = ie->srcWave1; + oscWave = ie->oscWave - 1; + destBuff = tc->synthBuffers[destWave]; + + srcBuff1 = tc->synthBuffers[srcWave1]; + + oscBuff = oscWave >= 0 ? tc->synthBuffers[oscWave] : NULL; + pos = ve->MFATTMREMVP; + + if (ie->oscWave == 0){ + var1 = ie->variable1; + var2 = ie->variable2; + } else { + if (ie->oscSelect){ + var1 = ie->variable1; + var2 = ((oscBuff[pos] + 0x8000) >> 8); + } else { + var1 = ((oscBuff[pos] + 0x8000) >> 8); + var2 = ie->variable2; + } + } + + var2 = (var2 << 8); + var1 = (var1 + var2); + _local22 = 0; + + for (j = 0; j < 0x0100; j++ ) { + //Hex Rays decompiler is lovely tool. + //butt = (butt & 0xFFFF0000) | (_local22 & 0x0000FFFF); + butt = _local22 & 0xFFFF; + _local22 += var1; + //ron = (ron & 0xFFFFFF00) | ( butt & 0x000000FF); + ron = butt & 0xFF; + butt >>= 8; + buf1 = srcBuff1[butt]; + //overflow warning + buf2 = srcBuff1[butt + 1]; + pat = (255 - ron) * buf1; + destBuff[j] = (ron * buf2 >> 8) + (pat >> 8); + } + break; + } + } +} + +static void channelSomethingElse(Player *p, int chanNum) +{ + int _local3; + int _local4; + int _local5; + int _local6; + + TuneChannel *tc = &p->tuneChannels[chanNum]; + const Instrument *ins = &p->instruments[tc->insNum]; + + if (ins->amWave == 0){ + _local3 = 0; + } else { + tc->HFRLJCG = (tc->HFRLJCG + ins->amSpeed); + if (tc->HFRLJCG >= 0x0100){ + tc->HFRLJCG = (tc->HFRLJCG - 0x0100); + tc->HFRLJCG = (tc->HFRLJCG + ins->amLoopPoint); + if (tc->HFRLJCG >= 0x0100){ + tc->HFRLJCG = ins->amLoopPoint; + } + } + _local3 = tc->synthBuffers[ins->amWave - 1][tc->HFRLJCG]; + _local3 = (_local3 + 0x8000); + _local3 = (_local3 / 6); + _local3 = -(_local3); + if (_local3 < -10000){ + _local3 = -10000; + } + } + _local3 = (_local3 + 10000); + _local3 = (_local3 * ins->masterVolume); + _local3 = (_local3 >> 8); + _local3 = (_local3 * p->AMVM); + _local3 = (_local3 >> 8); + _local3 = (_local3 - 10000); + tc->volume = _local3; + if (ins->panWave == 0){ + _local5 = 0; + } else { + tc->ELPHLDR = (tc->ELPHLDR + ins->panSpeed); + if (tc->ELPHLDR >= 0x0100){ + tc->ELPHLDR = (tc->ELPHLDR - 0x0100); + tc->ELPHLDR = (tc->ELPHLDR + ins->panLoopPoint); + if (tc->ELPHLDR >= 0x0100){ + tc->ELPHLDR = ins->panLoopPoint; + } + } + _local5 = tc->synthBuffers[ins->panWave - 1][tc->ELPHLDR]; + _local5 = (_local5 >> 7); + } + tc->panning = _local5; + _local6 = 0; + _local6 = p->arpTable[(ins->arpIndex * 16) + tc->ACKCWV]; + tc->ACKCWV++; + tc->ACKCWV = (tc->ACKCWV & 15); + _local4 = p->freqTable[ins->finetune*128 + (_local6 + tc->TVORFCC)]; + if (tc->fmDelay){ + tc->fmDelay--; + } else { + if (ins->fmWave != 0){ + tc->JOEEPJCI = (tc->JOEEPJCI + ins->fmSpeed); + if (tc->JOEEPJCI >= 0x0100){ + tc->JOEEPJCI = (tc->JOEEPJCI - 0x0100); + tc->JOEEPJCI = (tc->JOEEPJCI + ins->fmLoopPoint); + if (tc->JOEEPJCI >= 0x0100){ + tc->JOEEPJCI = ins->fmLoopPoint; + } + } + _local4 = _local4 - tc->synthBuffers[ins->fmWave - 1][tc->JOEEPJCI]; + } + } + _local4 = (_local4 + tc->BNWIGU); + tc->freq = _local4; + if (tc->XESAWSO != 0){ + if (tc->XESAWSO > 0){ + if (tc->BNWIGU < tc->UHYDBDDI){ + tc->BNWIGU = (tc->BNWIGU + tc->XESAWSO); + if (tc->BNWIGU > tc->UHYDBDDI){ + tc->BNWIGU = tc->UHYDBDDI; + } + } + } else { + if (tc->BNWIGU > tc->UHYDBDDI){ + tc->BNWIGU = (tc->BNWIGU + tc->XESAWSO); + if (tc->BNWIGU < tc->UHYDBDDI){ + tc->BNWIGU = tc->UHYDBDDI; + } + } + } + } +} + +void playInstrument(Player *p, int chanNum, int instrNum, int note) //note: 1-112 +{ + int j; + int i; + TuneChannel *tc; + Voice *v; + const Instrument *ins; + + if (instrNum > p->synSong->h.instrNum){ + return; + } + if ((((p->tuneChannels[chanNum].insNum == -1)) && ((instrNum == 0)))){ + return; + } + + tc = &p->tuneChannels[chanNum]; + v = &p->voices[chanNum]; + + tc->ACKCWV = 0; + tc->HFRLJCG = 0; + tc->ELPHLDR = 0; + tc->JOEEPJCI = 0; + tc->TVORFCC = note; + tc->freq = 0; + tc->VNVJPDIWAJQ = note; + tc->BNWIGU = 0; + tc->UHYDBDDI = 0; + tc->XESAWSO = 0; + p->m_LastNotes[chanNum] = note; + + if (instrNum != 0) { + ins = &p->instruments[instrNum - 1]; + + if (ins->shareSmpDataFromInstr == 0){ + tc->sampleBuffer = p->samples[instrNum - 1]; + } else { + tc->sampleBuffer = p->samples[ins->shareSmpDataFromInstr - 1]; + } + tc->sampPos = ins->smpStartPoint; + tc->smpLoopStart = ins->smpLoopPoint; + tc->smpLoopEnd = ins->smpEndPoint; + tc->hasLoop = ins->hasLoop; + tc->hasBidiLoop = ins->hasBidiLoop; + tc->hasLooped = 0; + tc->isPlayingBackward = 0; + tc->EYRXAB = -1; + tc->fmDelay = ins->fmDelay; + + for (i = 0; i < 16; i++) { + if (ins->m_ResetWave[i]){ + //ins->synthBuffers[i].copyTo(tc.synthBuffers[i]); + memcpy(&tc->synthBuffers[i], &ins->synthBuffers[i], 0x100 *2); + } + } + tc->insNum = instrNum - 1; + + resampler_clear(v->resampler[0]); + v->last_delta = 0; + } + ins = &p->instruments[tc->insNum]; + + for (j = 0; j < 4; j++) { + if (ins->effects[j].effectType != 0){ + if (ins->effects[j].resetEffect) { + VoiceEffect *ve = &tc->effects[j]; + + ve->MFATTMREMVP = 0; + ve->QOMCBTRPXF = 0; + ve->TIPUANVVR = 0; + ve->YLKJB = 0; + ve->ILHG = 0; + ve->VMBNMTNBQU = 0; + ve->ABJGHAUY = 0; + ve->SPYK = 0; + } + } + } +} + +static void patEffect(Player *p, int note, int command, int dest, int spd, int chanNum) +{ + TuneChannel *tc = &p->tuneChannels[chanNum]; + Instrument *ins = &p->instruments[tc->insNum]; + int off; + double tempo; + + if (tc->insNum == -1) return; + switch (command) { + + //NONE + case 0: + default: + return; + + //PITCHBEND + case 1: + if (tc->VNVJPDIWAJQ){ + off = p->freqTable[ins->finetune*128 + tc->VNVJPDIWAJQ]; + tc->TVORFCC = tc->VNVJPDIWAJQ; + } else { + off = p->freqTable[ins->finetune*128 + note]; + } + tc->BNWIGU = 0; + tc->UHYDBDDI = (p->freqTable[ins->finetune*128 + dest] - off); + tc->XESAWSO = (spd * 20); + tc->VNVJPDIWAJQ = dest; + break; + + //CHNG WAVEFORM + case 2: + if (dest > 15){ + dest = 15; + } + ins->waveform = dest; + break; + + //CHNG WAVELENGTH + case 3: + if (dest > 192){ + dest = 0x0100; + } else { + if (dest > 96){ + dest = 128; + } else { + if (dest > 48){ + dest = 64; + } else { + dest = 32; + } + } + } + ins->wavelength = dest; + break; + + //CHNG MASTER VOL + case 4: + ins->masterVolume = dest; + break; + + //CHNG AMWAVE + case 5: + if (dest > 15){ + dest = 15; + } + ins->amWave = dest; + break; + + //CHNG AMSPD + case 6: + ins->amSpeed = dest; + break; + + //CHNG AMLPPOINT + case 7: + ins->amLoopPoint = dest; + break; + + //CHNG FINETUNE + case 8: + if (dest > 15){ + dest = 15; + } + ins->finetune = dest; + break; + + //CHNG FMWAVE + case 9: + if (dest > 15){ + dest = 15; + } + ins->fmWave = dest; + break; + + //CHNG FMSPD + case 10: + ins->fmSpeed = dest; + break; + + //CHNG FMLPPOINT + case 11: + ins->fmLoopPoint = dest; + break; + + //CHNG FMDELAY + case 12: + ins->fmDelay = dest; + break; + + //CHNG ARPEGGIO + case 13: + if (dest > 15){ + dest = 15; + } + ins->arpIndex = dest; + break; + + //CHNG EFF#1 DESTWAVE + case 14: + if (dest > 15){ + dest = 15; + } + ins->effects[0].destWave = dest; + break; + + //CHNG EFF#1 SRCWAVE1 + case 15: + if (dest > 15){ + dest = 15; + } + ins->effects[0].srcWave1 = dest; + break; + + //CHNG EFF#1 SRCWAVE2 + case 16: + if (dest > 15){ + dest = 15; + } + ins->effects[0].srcWave2 = dest; + break; + + //CHNG EFF#1 OSCWAVE + case 17: + if (dest > 15){ + dest = 15; + } + ins->effects[0].oscWave = dest; + break; + + //CHNG EFF#1 VARIABLE1 + case 18: + ins->effects[0].variable1 = dest; + break; + + //CHNG EFF#1 VARIABLE2 + case 19: + ins->effects[0].variable2 = dest; + break; + + //CHNG EFF#1 FXSPEED + case 20: + ins->effects[0].fxSpeed = dest; + break; + + //CHNG EFF#1 OSCSPEED + case 21: + ins->effects[0].oscSpeed = dest; + break; + + //CHNG EFF#1 OSCSELECT + case 22: + if (dest > 1){ + dest = 1; + } + ins->effects[0].oscSelect = dest; + break; + + //CHNG EFF#1 TYPE + case 23: + if (dest >= SE_NROFEFFECTS){ + dest = (SE_NROFEFFECTS - 1); + } + ins->effects[0].effectType = dest; + break; + + //CHNG EFF#1 RESETEFFECT + case 24: + if (dest > 1){ + dest = 1; + } + ins->effects[0].resetEffect = dest; + break; + + //CHNG EFF#2 DESTWAVE + case 25: + if (dest > 15){ + dest = 15; + } + ins->effects[1].destWave = dest; + break; + + //CHNG EFF#2 SRCWAVE1 + case 26: + if (dest > 15){ + dest = 15; + } + ins->effects[1].srcWave1 = dest; + break; + + //CHNG EFF#2 SRCWAVE2 + case 27: + if (dest > 15){ + dest = 15; + } + //Good god! SrcEffect2 is left unplugged. I could guess what it was. + //Luckly, I'm saved by one of the later effects. + ins->effects[1].srcWave2 = dest; + break; + + //CHNG EFF#2 OSCWAVE + case 28: + if (dest > 15){ + dest = 15; + } + ins->effects[1].oscWave = dest; + break; + + //CHNG EFF#2 VARIABLE1 + case 29: + ins->effects[1].variable1 = dest; + break; + + //CHNG EFF#2 VARIABLE2 + case 30: + ins->effects[1].variable2 = dest; + break; + + //CHNG EFF#2 FXSPEED + case 31: + ins->effects[1].fxSpeed = dest; + break; + + //CHNG EFF#2 OSCSPEED + case 32: + ins->effects[1].oscSpeed = dest; + break; + + //CHNG EFF#2 OSCSELECT + case 33: + if (dest > 1){ + dest = 1; + } + ins->effects[1].oscSelect = dest; + break; + + //CHNG EFF#2 TYPE + case 34: + if (dest >= SE_NROFEFFECTS){ + dest = (SE_NROFEFFECTS - 1); + } + ins->effects[1].effectType = dest; + break; + + //CHNG EFF#2 RESETEFFECT + case 35: + if (dest > 1){ + dest = 1; + } + ins->effects[1].resetEffect = dest; + break; + + //CHNG EFF#3 DESTWAVE + case 36: + if (dest > 15){ + dest = 15; + } + ins->effects[2].destWave = dest; + break; + + //CHNG EFF#3 SRCWAVE1 + case 37: + if (dest > 15){ + dest = 15; + } + ins->effects[2].srcWave1 = dest; + break; + + //CHNG EFF#3 SRCWAVE2 + case 38: + if (dest > 15){ + dest = 15; + } + ins->effects[2].srcWave2 = dest; + break; + + //CHNG EFF#3 OSCWAVE + case 39: + if (dest > 15){ + dest = 15; + } + ins->effects[2].oscWave = dest; + break; + + //CHNG EFF#3 VARIABLE1 + case 40: + ins->effects[2].variable1 = dest; + break; + + //CHNG EFF#3 VARIABLE2 + case 41: + ins->effects[2].variable2 = dest; + break; + + //CHNG EFF#3 FXSPEED + case 42: + ins->effects[2].fxSpeed = dest; + break; + + //CHNG EFF#3 OSCSPEED + case 43: + ins->effects[2].oscSpeed = dest; + break; + + //CHNG EFF#3 OSCSELECT + case 44: + if (dest > 1){ + dest = 1; + } + ins->effects[2].oscSelect = dest; + break; + + //CHNG EFF#3 TYPE + case 45: + if (dest >= SE_NROFEFFECTS){ + dest = (SE_NROFEFFECTS - 1); + } + ins->effects[2].effectType = dest; + break; + + //CHNG EFF#3 RESETEFFECT + case 46: + if (dest > 1){ + dest = 1; + } + ins->effects[2].resetEffect = dest; + break; + + //CHNG EFF#4 DESTWAVE + case 47: + if (dest > 15){ + dest = 15; + } + ins->effects[3].destWave = dest; + break; + + //CHNG EFF#4 SRCWAVE1 + case 48: + if (dest > 15){ + dest = 15; + } + ins->effects[3].srcWave1 = dest; + break; + + //CHNG EFF#4 SRCWAVE2 + case 49: + if (dest > 15){ + dest = 15; + } + ins->effects[3].srcWave2 = dest; + break; + + //CHNG EFF#4 OSCWAVE + case 50: + if (dest > 15){ + dest = 15; + } + ins->effects[3].oscWave = dest; + break; + + //CHNG EFF#4 VARIABLE1 + case 51: + ins->effects[3].variable1 = dest; + break; + + //CHNG EFF#4 VARIABLE2 + case 52: + ins->effects[3].variable2 = dest; + break; + + //CHNG EFF#4 FXSPEED + case 53: + ins->effects[3].fxSpeed = dest; + break; + + //CHNG EFF#4 OSCSPEED + case 54: + ins->effects[3].oscSpeed = dest; + break; + + //CHNG EFF#4 OSCSELECT + case 55: + if (dest > 1){ + dest = 1; + } + ins->effects[3].oscSelect = dest; + break; + + //CHNG EFF#4 TYPE + case 56: + if (dest >= SE_NROFEFFECTS){ + dest = (SE_NROFEFFECTS - 1); + } + ins->effects[3].effectType = dest; + break; + + //CHNG EFF#4 RESETEFFECT + case 57: + if (dest > 1){ + dest = 1; + } + ins->effects[3].resetEffect = dest; + break; + + //CHNG RESET WAVE #1 + case 58: + if (dest > 1){ + dest = 1; + } + ins->m_ResetWave[0] = dest; + break; + + //CHNG RESET WAVE #2 + case 59: + if (dest > 1){ + dest = 1; + } + ins->m_ResetWave[1] = dest; + break; + + //CHNG RESET WAVE #3 + case 60: + if (dest > 1){ + dest = 1; + } + ins->m_ResetWave[2] = dest; + break; + + //CHNG RESET WAVE #4 + case 61: + if (dest > 1){ + dest = 1; + } + ins->m_ResetWave[3] = dest; + break; + + //CHNG RESET WAVE #5 + case 62: + if (dest > 1){ + dest = 1; + } + ins->m_ResetWave[4] = dest; + break; + + //CHNG RESET WAVE #6 + case 63: + if (dest > 1){ + dest = 1; + } + ins->m_ResetWave[5] = dest; + break; + + //CHNG RESET WAVE #7 + case 64: + if (dest > 1){ + dest = 1; + } + ins->m_ResetWave[6] = dest; + break; + + //CHNG RESET WAVE #8 + case 65: + if (dest > 1){ + dest = 1; + } + ins->m_ResetWave[7] = dest; + break; + + //CHNG RESET WAVE #9 + case 66: + if (dest > 1){ + dest = 1; + } + ins->m_ResetWave[8] = dest; + break; + + //CHNG RESET WAVE #10 + case 67: + if (dest > 1){ + dest = 1; + } + ins->m_ResetWave[9] = dest; + break; + + //CHNG RESET WAVE #11 + case 68: + if (dest > 1){ + dest = 1; + } + ins->m_ResetWave[10] = dest; + break; + + //CHNG RESET WAVE #12 + case 69: + if (dest > 1){ + dest = 1; + } + ins->m_ResetWave[11] = dest; + break; + + //CHNG RESET WAVE #13 + case 70: + if (dest > 1){ + dest = 1; + } + ins->m_ResetWave[12] = dest; + break; + + //CHNG RESET WAVE #14 + case 71: + if (dest > 1){ + dest = 1; + } + ins->m_ResetWave[13] = dest; + break; + + //CHNG RESET WAVE #15 + case 72: + if (dest > 1){ + dest = 1; + } + ins->m_ResetWave[14] = dest; + break; + + //CHNG RESET WAVE #16 + case 73: + if (dest > 1){ + dest = 1; + } + ins->m_ResetWave[15] = dest; + break; + + //CHNG BPM + case 74: + if (dest <= 10){ + dest = 10; + } + if (dest > 220){ + dest = 220; + } + p->curSubsong.tempo = dest; + tempo = (double)(p->curSubsong.tempo); + tempo = (tempo / 60); + tempo = (tempo * 32); + p->samplesPerBeat = (int)(44100 / tempo); + break; + + //CHNG GROOVE + case 75: + if (dest > 3){ + dest = 3; + } + p->curSubsong.groove = dest; + break; + + //FIRE EXTERNAL EVENT + case 76: + //this effect is for controlling external code + //like animation and whatnot + //similar to how 8xx is used in Travolta's 'testlast' .mod + + //do take note of audio latency when dealing with this. + + //This is called UserEvent in ocx player doc, I think + break; + } +} + +static void channelSomething(Player *p, int chanNum) +{ + int _local2; + int _local3; + int note; + int dest; + int contrScript; + int spd; + + if (!p->PQV) return; + if (p->someCounter != p->WDTECTE) return; + + if (p->sePmSong == SE_PM_PATTERN){ + if (chanNum > 0) return; + _local2 = p->AMYGPFQCHSW; + _local3 = p->ISWLKT; + } else { + if (p->curSubsong.mutedChans[chanNum] == 1) return; + + _local3 = p->tuneChannels[chanNum].LJHG; + _local2 = p->curSubsong.orders[chanNum][p->tuneChannels[chanNum].EQMIWERPIF].patIndex; + } + note = p->rows[(_local2 * 64) + _local3].note; + if (note != 0) { + playInstrument(p, chanNum, p->rows[(_local2 * 64) + _local3].instr, note); + } + contrScript = p->rows[(_local2 * 64) + _local3].command; + dest = p->rows[(_local2 * 64) + _local3].dest; + spd = p->rows[(_local2 * 64) + _local3].spd; + patEffect(p, note, contrScript, dest, spd, chanNum); +} + +static void ABH(Player *p) +{ + int i, j0, j1; + int _local2; + Order *_local3; + int _local4; + bool _local5; + int _local6; + Order *_local9; + int _local10; + int _local11; + + if (!p->PQV) return; + + p->someCounter--; + if (p->someCounter == 0){ + if (p->sePmSong == SE_PM_PATTERN){ + if (!(p->ISWLKT & 1)){ + p->WDTECTE = (8 - p->curSubsong.groove); + } else { + p->WDTECTE = (8 + p->curSubsong.groove); + } + } else { + if (!(p->posFine & 1)){ + p->WDTECTE = (8 - p->curSubsong.groove); + } else { + p->WDTECTE = (8 + p->curSubsong.groove); + } + } + p->someCounter = p->WDTECTE; + if (p->sePmSong == SE_PM_PATTERN){ + p->ISWLKT++; + p->ISWLKT = (p->ISWLKT % p->DONGS); + } else { + for (i = 0; i < p->channelNumber; i++) { + TuneChannel *tc = &p->tuneChannels[i]; + + tc->LJHG++; + _local3 = p->curSubsong.orders[i]; + _local4 = tc->EQMIWERPIF; + if (_local4 == -1){ + _local4 = 0; + } + _local2 = _local3[_local4].patLen; + if ((((tc->LJHG == _local2)) || ((tc->EQMIWERPIF == -1)))){ + tc->LJHG = 0; + tc->EQMIWERPIF++; + p->curSubsong.mutedChans[i] = p->mutedChans[i]; + } + + } + p->posFine++; + if (p->posFine == 64){ + p->posFine = 0; + p->posCoarse++; + } + if ((((p->posCoarse == p->curSubsong.endPosCoarse)) && ((p->posFine == p->curSubsong.endPosFine)))){ + if (p->curSubsong.isLooping){ + _local5 = false; + + for (j0 = 0; j0 < SE_MAXCHANS; j0++) { + _local6 = 0; + + _local11 = 0; + _local9 = p->curSubsong.orders[j0]; + _local10 = ((p->curSubsong.loopPosCoarse * 64) + p->curSubsong.loopPosFine); + for (j1 = 0; j1 < 0x0100; j1++) { + if (_local6 > _local10){ + if (j1 != _local10){ + j1--; + } + break; + } + _local11 = _local6; + _local6 = (_local6 + _local9[j1].patLen); + + } + if (j1 == 0x0100){ + p->PQV = 0; + _local5 = true; + break; + } + _local10 = (_local10 - _local11); + _local10 = (_local10 & 63); + p->tuneChannels[j0].EQMIWERPIF = j1; + p->tuneChannels[j0].LJHG = _local10; + + } + if (_local5 == false){ + p->posCoarse = p->curSubsong.loopPosCoarse; + p->posFine = p->curSubsong.loopPosFine; + p->loopCount++; + } + } else { + p->PQV = 0; + p->sePmSong = SE_PM_SONG; + p->posCoarse = p->curSubsong.startPosCoarse; + p->posFine = p->curSubsong.startPosFine; + } + } + } + } +} + +void advanceTick(Player *p) +{ + int i; + ABH(p); + + for (i = 0; i < p->channelNumber; i++) { + channelSomething(p, i); + if (p->tuneChannels[i].insNum != -1) { + channelSomethingElse(p, i); + instrEffect(p, i); + } + } +} + +void mixChunk(Player *p, int16_t *outBuff, uint playbackBufferSize) +{ + int i, j; + uint sampleNum; + int amp, smp, pos; + int32_t audioMainR, audioMainL; + int32_t audioDelayR, audioDelayL; + uint otherDelayTime; + Voice *v; + TuneChannel *tc; + int insNum; + + //We just don't know! + uint dword_6632774C = 0; + + if ( p->channelNumber > 0 ) + { + while ( playbackBufferSize > 0 ) + { + if ( p->otherSamplesPerBeat >= playbackBufferSize ) + { + p->otherSamplesPerBeat = p->otherSamplesPerBeat - playbackBufferSize; + sampleNum = playbackBufferSize; + } + else + { + sampleNum = p->otherSamplesPerBeat; + p->otherSamplesPerBeat = p->samplesPerBeat * p->SAMPLEFREQUENCY / 44100; + } + playbackBufferSize -= sampleNum; + + for (i=0; i < p->channelNumber; ++i ) + { + v = &p->voices[i]; tc = &p->tuneChannels[i]; + + insNum = tc->insNum; + if ( insNum == -1 ) + { + v->waveBuff = p->silentBuffer; + v->isSample = 0; + } + else if ( !tc->sampleBuffer ) + { + int waveNum = p->instruments[insNum].waveform; + v->wavelength = (p->instruments[insNum].wavelength) - 1; + v->waveBuff = tc->synthBuffers[waveNum]; + v->isSample = 0; + } + else + { + v->waveBuff = tc->sampleBuffer; + v->sampPos = tc->sampPos; + v->smpLoopStart = tc->smpLoopStart; + v->smpLoopEnd = tc->smpLoopEnd; + v->hasLoop = tc->hasLoop; + v->hasBidiLoop = tc->hasBidiLoop; + v->isPlayingBackward = tc->isPlayingBackward; + v->hasLooped = tc->hasLooped; + v->isSample = 1; + } + + if ( tc->freq < 10 ) + tc->freq = 10; + + v->gain = (tc->volume + 10000) / 39; + v->delta = (tc->freq << 8) / p->SAMPLEFREQUENCY; + if (v->delta != v->last_delta && outBuff ) + { + double fdelta = (double)v->delta * (1.0 / (double)0x100); + v->last_delta = v->delta; + resampler_set_rate(v->resampler[0], fdelta); + } + + if ( v->gain > 0x100 ) + v->gain = 0x100; + if ( tc->panning ) + { + if ( tc->panning <= 0 ) + { + v->gainRight = 0x100; + v->gainLeft = 0x100 + tc->panning; + } + else + { + v->gainLeft = 0x100; + v->gainRight = 0x100 - tc->panning; + } + } + else + { + v->gainRight = 0x100; + v->gainLeft = 0x100; + } + if ( dword_6632774C ) + { + //v->gainDelay = word_6632B9F4[i]; + } + else + { + v->gainDelay = p->curSubsong.chanDelayAmt[i]; + } + v->gainRight = (v->gain * v->gainRight) >> 8; + v->gainLeft = (v->gain * v->gainLeft) >> 8; + v->gainDelayRight = (v->gainDelay * v->gainRight) >> 8; + v->gainDelayLeft = (v->gainDelay * v->gainLeft) >> 8; + } + if ( dword_6632774C ) + { + //amp = word_6632B964; + //otherDelayTime = word_6632BB24; + } + else + { + amp = p->curSubsong.amplification; + otherDelayTime = p->curSubsong.delayTime / (44100 / p->SAMPLEFREQUENCY); + } + if ( outBuff ) + { + if ( sampleNum > 0 ) + { + for(i = 0; i < sampleNum; i++) + { + audioMainR = 0; + audioMainL = 0; + audioDelayR = 0; + audioDelayL = 0; + if ( p->channelNumber > 0 ) + { + for (j = 0; j < p->channelNumber; ++j) + { + v = &p->voices[j]; + if ( v->isSample == 1 ) + { + if ( v->sampPos != -1 || resampler_get_avail(v->resampler[0]) ) + { + //interpolation + sample_t s; + while ( v->sampPos != -1 && resampler_get_min_fill(v->resampler[0]) ) + { + s = v->waveBuff[v->sampPos]; + resampler_write_pair(v->resampler[0], s, s); + if ( v->isPlayingBackward ) + { + v->sampPos--; + if ( v->sampPos <= v->smpLoopStart ) + { + v->isPlayingBackward = 0; + v->sampPos++; + } + } + else + { + v->sampPos++; + if ( v->sampPos >= v->smpLoopEnd ) + { + if ( v->hasLoop ) + { + v->hasLooped = 1; + if ( v->hasBidiLoop ) + { + v->isPlayingBackward = 1; + v->sampPos--; + } + else + { + v->sampPos += v->smpLoopStart - v->smpLoopEnd; + } + } + else + { + v->sampPos = -1; + } + } + } + } + + //smp = intp->interpSamp(v); + resampler_read_pair(v->resampler[0], &s, &s); + smp = s; + + audioMainR += (smp * v->gainRight) >> 8; + audioMainL += (smp * v->gainLeft) >> 8; + audioDelayR += (smp * v->gainDelayRight) >> 8; + audioDelayL += (smp * v->gainDelayLeft) >> 8; + } + } + else + { + //interpolation + //smp = intp->interpSynt(v); + sample_t s; + while ( resampler_get_min_fill(v->resampler[0]) ) + { + s = v->waveBuff[v->synthPos]; + resampler_write_pair(v->resampler[0], s, s); + v->synthPos++; + v->synthPos &= v->wavelength; + } + resampler_read_pair(v->resampler[0], &s, &s); + smp = s; + + audioMainR += (smp * v->gainRight) >> 8; + audioMainL += (smp * v->gainLeft) >> 8; + audioDelayR += (smp * v->gainDelayRight) >> 8; + audioDelayL += (smp * v->gainDelayLeft) >> 8; + } + } + } + + audioMainL = (p->delayBufferL[p->delayPos] + audioMainL / p->channelNumber) / 2; + audioMainR = (p->delayBufferR[p->delayPos] + audioMainR / p->channelNumber) / 2; + audioMainR = audioMainR * amp / 100; + audioMainL = audioMainL * amp / 100; + //clip audio + if ( audioMainR < -32760 ) audioMainR = -32760; + if ( audioMainR > 32760 ) audioMainR = 32760; + if ( audioMainL < -32760 ) audioMainL = -32760; + if ( audioMainL > 32760 ) audioMainL = 32760; + + //interleaved buffer + if ( p->overlapPos < SE_OVERLAP ) + { + audioMainR = p->overlapPos * audioMainR / 100; + audioMainR += (SE_OVERLAP - p->overlapPos) * p->overlapBuff[p->overlapPos*2] / 100; + audioMainL = p->overlapPos * audioMainL / 100; + audioMainL += (SE_OVERLAP - p->overlapPos) * p->overlapBuff[p->overlapPos*2+1] / 100; + ++p->overlapPos; + } + + //output + *outBuff++ = audioMainR; + *outBuff++ = audioMainL; + + p->delayBufferL[p->delayPos] = (((audioDelayL / p->channelNumber) + p->delayBufferL[p->delayPos]) / 2); + p->delayBufferR[p->delayPos] = (((audioDelayR / p->channelNumber) + p->delayBufferR[p->delayPos]) / 2); + p->delayPos = ++p->delayPos % otherDelayTime; + } + } + } + + if ( p->channelNumber > 0 ) + { + for (i = 0; i < p->channelNumber; ++i) + { + v = &p->voices[i]; tc = &p->tuneChannels[i]; + if ( v->isSample ) + { + tc->sampPos = v->sampPos; + tc->isPlayingBackward = v->isPlayingBackward; + tc->hasLooped = v->hasLooped; + } + } + } + if ( p->otherSamplesPerBeat == (p->samplesPerBeat * p->SAMPLEFREQUENCY) / 44100 ) + { + p->bkpDelayPos = p->delayPos; + for (i = 0; i < p->channelNumber; i++) + { + p->voices[i].bkpSynthPos = p->voices[i].synthPos; + resampler_dup_inplace(p->voices[i].resampler[1], p->voices[i].resampler[0]); + } + + p->overlapPos = 0; + if ( outBuff ) + { + for (i = 0; i < SE_OVERLAP; i++) + { + audioMainR = 0; + audioMainL = 0; + audioDelayR = 0; + audioDelayL = 0; + if ( p->channelNumber > 0 ) + { + for (j = 0; j < p->channelNumber; j++) + { + v = &p->voices[j]; + if ( v->isSample == 1 ) + { + if ( v->sampPos != -1 || resampler_get_avail(v->resampler[1]) ) + { + //interpolation + //smp = intp->interpSamp(v); + sample_t s; + while ( v->sampPos != -1 && resampler_get_min_fill(v->resampler[1]) ) + { + s = v->waveBuff[v->sampPos]; + resampler_write_pair(v->resampler[1], s, s); + if ( v->isPlayingBackward ) + { + v->sampPos--; + if ( v->sampPos <= v->smpLoopStart ) + { + v->isPlayingBackward = 0; + v->sampPos++; + } + } + else + { + v->sampPos++; + if ( v->sampPos >= v->smpLoopEnd ) + { + if ( v->hasLoop ) + { + v->hasLooped = 1; + if ( v->hasBidiLoop ) + { + v->isPlayingBackward = 1; + v->sampPos--; + } + else + { + v->sampPos += v->smpLoopStart - v->smpLoopEnd; + } + } + else + { + v->sampPos = -1; + } + } + } + } + resampler_read_pair(v->resampler[1], &s, &s); + smp = s; + + audioMainR += (smp * v->gainRight) >> 8; + audioMainL += (smp * v->gainLeft) >> 8; + audioDelayR += (smp * v->gainDelayRight) >> 8; + audioDelayL += (smp * v->gainDelayLeft) >> 8; + } + } + else + { + //interpolation + //smp = intp->interpSynt(v); + sample_t s; + while ( resampler_get_min_fill(v->resampler[1]) ) + { + s = v->waveBuff[v->synthPos]; + resampler_write_pair(v->resampler[1], s, s); + v->synthPos++; + v->synthPos &= v->wavelength; + } + resampler_read_pair(v->resampler[1], &s, &s); + smp = s; + + audioMainR += (smp * v->gainRight) >> 8; + audioMainL += (smp * v->gainLeft) >> 8; + audioDelayR += (smp * v->gainDelayRight) >> 8; + audioDelayL += (smp * v->gainDelayLeft) >> 8; + } + } + } + + audioMainL = (p->delayBufferL[p->delayPos] + audioMainL / p->channelNumber) / 2; + audioMainR = (p->delayBufferR[p->delayPos] + audioMainR / p->channelNumber) / 2; + audioMainR = audioMainR * amp / 100; + audioMainL = audioMainL * amp / 100; + //clip audio + if ( audioMainR < -32760 ) audioMainR = -32760; + if ( audioMainR > 32760 ) audioMainR = 32760; + if ( audioMainL < -32760 ) audioMainL = -32760; + if ( audioMainL > 32760 ) audioMainL = 32760; + + p->overlapBuff[i * 2] = audioMainR; + p->overlapBuff[i*2+1] = audioMainL; + + p->delayPos = ++p->delayPos % otherDelayTime; + } + } + p->delayPos = p->bkpDelayPos; + for (i = 0; i < p->channelNumber; i++) p->voices[i].synthPos = p->voices[i].bkpSynthPos; + + //dword_66327200 = 2 * sampleNum; + advanceTick(p); + } + } + return; + } + memset(outBuff, 0, playbackBufferSize * 2 *2); +} + + /*void newSong(void) + { + var _local1:int; + var i:int; + var j:int; + var _local4:Order; + var _local6:Vector.; + var _local7:Row; + + reset(); + AMYGPFQCHSW = 1; + selectedSubsong = 0; + WDTECTE = 8; + AMVM = 0x100; + synSong.h.subsongNum = 1; + synSong.h.version = 3457; + subsongs = new Vector.(); + subsongs.push(new Subsong()); + var subs0:Subsong = subsongs[0]; + curSubsong = subsongs[selectedSubsong]; + + subs0.tempo = 120; + subs0.groove = 0; + subs0.startPosCoarse = 0; + subs0.startPosFine = 0; + subs0.loopPosCoarse = 0; + subs0.loopPosFine = 0; + subs0.endPosCoarse = 1; + subs0.endPosFine = 0; + subs0.channelNumber = 4; + subs0.delayTime = 0x8000; + subs0.amplification = 400; + subs0.chanDelayAmt = new Vector.(SE_MAXCHANS, true); + + subs0.m_Name = "Empty"; + subs0.mutedChans = new Vector.(SE_MAXCHANS, true); + + + subs0.orders = Tools.malloc_2DVector(Order, SE_MAXCHANS, 0x0100, true, true); + for (i = 0; i < SE_MAXCHANS; i++) { + _local6 = subs0.orders[i]; + for (j = 0; j < 0x0100; j++) { + _local6[j].patIndex = 0; + _local6[j].patLen = 0; + } + } + + synSong.h.patNum = 2; + synSong.rows = Tools.malloc_1DVector(Row, 64 * synSong.h.patNum); + + for (i = 0; i < (64 * synSong.h.patNum); i++) { + rows[i].dest = 0; + rows[i].note = 0; + rows[i].instr = 0; + rows[i].command = 0; + rows[i].spd = 0; + + } + patternNames = new Vector.(); + patternNames.push("Empty"); + patternNames.push("Pat1"); + synSong.h.instrNum = 1; + synSong.instruments = new Vector.(); + synSong.instruments.push(new Instrument()); + + mutedChans = new Vector.(SE_MAXCHANS, true); + }*/ + +static void AAUCAPQW(Player *p) +{ + //What is this even for? + + p->PQV = 0; + p->sePmSong = SE_PM_SONG; + if (p->subsongs){ + p->posCoarse = p->curSubsong.startPosCoarse; + p->posFine = p->curSubsong.startPosFine; + } +} + +static void IMXFLSSMB(Player *p, int _arg1) +{ + p->PQV = 1; + p->AMYGPFQCHSW = _arg1; + p->ISWLKT = 63; + p->someCounter = 1; + p->sePmSong = SE_PM_PATTERN; + p->WDTECTE = p->subsongs[0].tempo - p->subsongs[0].groove; +} + +void initSubsong(Player *p, int num) +{ + int _local2; + int i, j; + Order *_local5; + bool _local6; + int _local7; + int _local8; + double tempo; + + //reset instruments + memcpy(p->instruments, p->synSong->instruments, p->synSong->h.instrNum * sizeof(Instrument)); + + p->loopCount = 0; + + if (num >= p->synSong->h.subsongNum) return; + + p->selectedSubsong = num; + p->curSubsong = p->subsongs[p->selectedSubsong]; + p->channelNumber = p->curSubsong.channelNumber; + reset(p); + _local6 = false; + + for (i = 0; i < SE_MAXCHANS; i++) { + p->m_LastNotes[i] = 0; + _local2 = 0; + + _local8 = 0; + _local5 = p->curSubsong.orders[i]; + _local7 = (((p->curSubsong.startPosCoarse * 64) + p->curSubsong.startPosFine) - 1); + for (j = 0; j < 0x0100; j++) { + if (_local2 >= _local7){ + if (j != _local7){ + j--; + } + break; + } + _local8 = _local2; + _local2 = (_local2 + _local5[j].patLen); + + } + if (j == 0x0100){ + _local6 = true; + break; + } + _local7 = (_local7 - _local8); + _local7 = (_local7 & 63); + p->tuneChannels[i].EQMIWERPIF = j; + p->tuneChannels[i].LJHG = _local7; + p->curSubsong.mutedChans[i] = p->mutedChans[i]; + + } + if (_local6 == false){ + p->someCounter = 1; + p->sePmSong = SE_PM_SONG; + p->PQV = 1; + p->WDTECTE = (8 + p->curSubsong.groove); + if (p->curSubsong.tempo){ + tempo = (double)(p->curSubsong.tempo); + tempo = (tempo / 60); + tempo = (tempo * 32); + p->samplesPerBeat = (int)((44100 / tempo)); + p->otherSamplesPerBeat = p->samplesPerBeat; + } + if (p->curSubsong.startPosFine == 0){ + p->posCoarse = p->curSubsong.startPosCoarse - 1; + } else { + p->posCoarse = p->curSubsong.startPosCoarse; + } + p->posFine = p->curSubsong.startPosFine - 1; + p->posFine = p->posFine & 63; + } +} + +int loadSong(Player *p, const Song *synSong) +{ + int i; + void *ptr; + + AAUCAPQW(p); + reset(p); + //clearSongData(); + p->synSong = synSong; + + //pass things locally + //not much purpouse here + //nor in AS3 + //why did I do it + p->rows = synSong->rows; + p->patternNames = (const char **) synSong->patternNames; + + ptr = realloc(p->instruments, synSong->h.instrNum * sizeof(Instrument)); + if (!ptr) return -1; + p->instruments = (Instrument *) ptr; + + p->subsongs = synSong->subsongs; + p->arpTable = synSong->arpTable; + p->samples = (const int16_t **) synSong->samples; + + //Do we really need to? + //What would Syntrax do? + for (i = 0; i < SE_MAXCHANS; i++) { + p->mutedChans[i] = synSong->subsongs[0].mutedChans[i]; + } + initSubsong(p, 0); + + return 0; +} + +bool playerGetSongEnded(Player *p) +{ + return p->PQV == 0; +} + +uint playerGetLoopCount(Player *p) +{ + return p->loopCount; +} + +void playerGetInfo(Player *p, syntrax_info *info) +{ + int i, j; + info->coarse = p->posCoarse; + info->fine = p->posFine; + info->subsongName = p->curSubsong.m_Name; + info->selectedSubs = p->selectedSubsong; + info->totalSubs = p->synSong->h.subsongNum; + for (i = 0, j = 0; i < p->channelNumber; i++) + { + Voice *v = &p->voices[i]; + if (v->waveBuff != p->silentBuffer) + { + if (v->isSample) + { + if (v->sampPos != -1) j++; + } + else j++; + } + } + info->channelsPlaying = j; +} diff --git a/Frameworks/Syntrax-c/Syntrax-c/syntrax.h b/Frameworks/Syntrax-c/Syntrax-c/syntrax.h new file mode 100644 index 000000000..ba18bce7a --- /dev/null +++ b/Frameworks/Syntrax-c/Syntrax-c/syntrax.h @@ -0,0 +1,365 @@ +#ifndef SYNTRAX_H +#define SYNTRAX_H + +#include + +//----------------------------typedefs------------------------- +#ifndef NULL +#define NULL 0 +#endif +typedef unsigned uint; +#ifndef __cplusplus +typedef enum { false, true } bool; +#endif + +//----------------------------defines-------------------------- +#define SE_NROFEFFECTS 18 +#define SE_MAXCHANS 16 +#define SE_NROFFINETUNESTEPS 16 + +#define SE_OVERLAP 100 + +#define BUFFERLENGTH 4096 +#define CHANNELS 2 +#define BITRATE 16 +#define RESAMPLE_POINTS 4 + +//some constants for controlling stuff +//I've no idea what the abreviations stand for +#define SE_PM_SONG 0 +#define SE_PM_PATTERN 1 + + +//---------------------------structures------------------------ +//player structs +//don't pack these +typedef struct +{ + int wavelength; + int gainDelay; + int delta; + int freq; + int isSample; + int isPlayingBackward; + int smpLoopEnd; + int PPMXBYLQ; //unused + int gain; + const int16_t *waveBuff; + int hasBidiLoop; + int synthPos; + int gainRight; + int smpLoopStart; + int bkpSynthPos; + int sampPos; + int gainLeft; + int hasLoop; + int smpLength; + int gainDelayRight; + int gainDelayLeft; + int hasLooped; + void * resampler[2]; + int last_delta; +} Voice; + +typedef struct +{ + int VMBNMTNBQU; + int TIPUANVVR; + double MDTMBBIQHRQ; + double YLKJB; + double DQVLFV; + int MFATTMREMVP; + double ILHG; + double RKF; + int SPYK; + int QOMCBTRPXF; + int ABJGHAUY; +} VoiceEffect; + +typedef struct +{ + int JOEEPJCI; + int BNWIGU; + int isPlayingBackward; + int ELPHLDR; + int panning; + int TVORFCC; + int EYRXAB; //rather unused + int UHYDBDDI; + int XESAWSO; + int hasBidiLoop; + int fmDelay; + int volume; + int ACKCWV; + int sampPos; + int insNum; + uint8_t EQMIWERPIF; + int freq; + int HFRLJCG; + int VNVJPDIWAJQ; + int hasLoop; + int LJHG; + const int16_t *sampleBuffer; + //SQUASH effect overflows into next buffer + //SE_MAXCHANS * 0x100 + 1 must be allocated + int16_t synthBuffers[SE_MAXCHANS][0x100]; + int16_t OVERFLOW_DUMMY; + int smpLoopStart; + int smpLoopEnd; + int hasLooped; + VoiceEffect effects[4]; +} TuneChannel; + + +//data structs + +typedef struct +{ + uint32_t destWave; + uint32_t srcWave1; + uint32_t srcWave2; + uint32_t oscWave; + uint32_t variable1; + uint32_t variable2; + uint32_t fxSpeed; + uint32_t oscSpeed; + uint32_t effectType; + int8_t oscSelect; + int8_t resetEffect; + int16_t UNK00; +} InstrumentEffect; + +typedef struct +{ + int16_t version; + char name[33]; + int16_t waveform; + int16_t wavelength; + int16_t masterVolume; + int16_t amWave; + int16_t amSpeed; + int16_t amLoopPoint; + int16_t finetune; + int16_t fmWave; + int16_t fmSpeed; + int16_t fmLoopPoint; + int16_t fmDelay; + int16_t arpIndex; + uint8_t m_ResetWave[SE_MAXCHANS]; + int16_t panWave; + int16_t panSpeed; + int16_t panLoopPoint; + int16_t UNK00; + int16_t UNK01; + int16_t UNK02; + int16_t UNK03; + int16_t UNK04; + int16_t UNK05; + InstrumentEffect effects[4]; + //why do we even need to store a full path? + //only filename appears to be used. + char smpFullImportPath[193]; + uint32_t UNK06; + uint32_t UNK07; + uint32_t UNK08; + uint32_t UNK09; + uint32_t UNK0A; + uint32_t UNK0B; + uint32_t UNK0C; + uint32_t UNK0D; + uint32_t UNK0E; + uint32_t UNK0F; + uint32_t UNK10; + uint32_t UNK11; + int16_t UNK12; + int16_t shareSmpDataFromInstr; //0 is off + int16_t hasLoop; + int16_t hasBidiLoop; + uint32_t smpStartPoint; + uint32_t smpLoopPoint; + uint32_t smpEndPoint; + uint32_t hasSample; + uint32_t smpLength; + int16_t synthBuffers[SE_MAXCHANS][0x100]; +} Instrument; + +typedef struct +{ + uint8_t note; + uint8_t dest; + uint8_t instr; + int8_t spd; + uint8_t command; +} Row; + +typedef struct +{ + uint16_t patIndex; //0 means empty + uint16_t patLen; +} Order; + +typedef struct +{ + uint32_t UNK00[16]; + //UNK00 is used for something. No idea what. + //There is a sequence to the data in it. + //zeroing it out with hex editor doesn't seem to break stuff with Jaytrax + //it could as well be uninitialized memory + uint8_t mutedChans[SE_MAXCHANS]; + uint32_t tempo; + uint32_t groove; + uint32_t startPosCoarse; + uint32_t startPosFine; + uint32_t endPosCoarse; + uint32_t endPosFine; + uint32_t loopPosCoarse; + uint32_t loopPosFine; + int16_t isLooping; + char m_Name[33]; + int16_t channelNumber; + uint16_t delayTime; + uint8_t chanDelayAmt[SE_MAXCHANS]; + int16_t amplification; + int16_t UNK01; + int16_t UNK02; + int16_t UNK03; + int16_t UNK04; + int16_t UNK05; + int16_t UNK06; + //if my eyes don't deceive me, this actually happens + //waste of space + Order orders[SE_MAXCHANS][0x100]; +} Subsong; + +typedef struct +{ + uint16_t version; + uint16_t UNK00; + uint32_t patNum; + uint32_t subsongNum; + uint32_t instrNum; + uint32_t UNK01; + int16_t UNK02; + int16_t UNK03; + int16_t UNK04; + int16_t UNK05; + int16_t UNK06; + int16_t UNK07; + int16_t UNK08; + int16_t UNK09; + int16_t UNK0A; + int16_t UNK0B; + int16_t UNK0C; + int16_t UNK0D; + int16_t UNK0E; + int16_t UNK0F; + int16_t UNK10; + int16_t UNK11; +} SongHeader; + + +typedef struct +{ + SongHeader h; + int8_t arpTable[0x100]; + + Row *rows; + //we don't know what maximum pat name length should be + //in fact this is probably a buffer overflow target in Syntrax(app crashed on too long name, from UI); + uint32_t *patNameSizes; + char **patternNames; + Instrument *instruments; + Subsong *subsongs; + int16_t **samples; +} Song; + + +typedef struct Player +{ + int16_t *silentBuffer; + uint8_t m_LastNotes[SE_MAXCHANS]; + + uint32_t *freqTable; + int16_t *dynamorphTable; + + const Song *synSong; + TuneChannel *tuneChannels; + Voice *voices; + + int SAMPLEFREQUENCY; + + int samplesPerBeat; + int otherSamplesPerBeat; + int someCounter; + int channelNumber; + int sePmSong; + int16_t *overlapBuff; + int16_t *delayBufferR; + int16_t *delayBufferL; + + int bkpDelayPos; + int delayPos; + int gainPos; + int overlapPos; + + int ISWLKT; + int WDTECTE; + int PQV; + int AMVM; + int DONGS; + uint8_t posCoarse; + int AMYGPFQCHSW; + int posFine; + int8_t mutedChans[SE_MAXCHANS]; + + int selectedSubsong; + Subsong curSubsong; + + //local pointers to song structures + const Row *rows; + const char ** patternNames; + Instrument *instruments; + const Subsong *subsongs; + const int8_t *arpTable; + const int16_t **samples; + + uint bufflen; + + uint loopCount; +} Player; + + +//---------------------------prototypes------------------------ +#ifdef __cplusplus +extern "C" { +#endif + +Player * playerCreate(int sampleFrequency); +void playerDestroy(Player *); + +int loadSong(Player *, const Song *); +void initSubsong(Player *, int num); + +void mixChunk(Player *, int16_t *outBuff, uint playbackBufferSize); + +void playInstrument(Player *, int chanNum, int instrNum, int note); //could be handy dandy + +bool playerGetSongEnded(Player *); +uint playerGetLoopCount(Player *); + +typedef struct _stmi +{ + unsigned char coarse; + unsigned char fine; + unsigned char channelsPlaying; + const char *subsongName; + int selectedSubs; + int totalSubs; +} syntrax_info; + +void playerGetInfo(Player *, syntrax_info *); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Frameworks/Syntrax-c/Syntrax_c.xcodeproj/project.pbxproj b/Frameworks/Syntrax-c/Syntrax_c.xcodeproj/project.pbxproj new file mode 100644 index 000000000..8e3c7ccd6 --- /dev/null +++ b/Frameworks/Syntrax-c/Syntrax_c.xcodeproj/project.pbxproj @@ -0,0 +1,304 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 83EEAB071C965247002761C5 /* file.c in Sources */ = {isa = PBXBuildFile; fileRef = 83EEAB011C965247002761C5 /* file.c */; }; + 83EEAB081C965247002761C5 /* file.h in Headers */ = {isa = PBXBuildFile; fileRef = 83EEAB021C965247002761C5 /* file.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 83EEAB091C965247002761C5 /* resampler.c in Sources */ = {isa = PBXBuildFile; fileRef = 83EEAB031C965247002761C5 /* resampler.c */; }; + 83EEAB0A1C965247002761C5 /* resampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 83EEAB041C965247002761C5 /* resampler.h */; }; + 83EEAB0B1C965247002761C5 /* syntrax.c in Sources */ = {isa = PBXBuildFile; fileRef = 83EEAB051C965247002761C5 /* syntrax.c */; }; + 83EEAB0C1C965247002761C5 /* syntrax.h in Headers */ = {isa = PBXBuildFile; fileRef = 83EEAB061C965247002761C5 /* syntrax.h */; settings = {ATTRIBUTES = (Public, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 832FF31B1C96511E0076D662 /* Syntrax_c.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Syntrax_c.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 832FF3201C96511E0076D662 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 83EEAB011C965247002761C5 /* file.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = file.c; sourceTree = ""; }; + 83EEAB021C965247002761C5 /* file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file.h; sourceTree = ""; }; + 83EEAB031C965247002761C5 /* resampler.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = resampler.c; sourceTree = ""; }; + 83EEAB041C965247002761C5 /* resampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resampler.h; sourceTree = ""; }; + 83EEAB051C965247002761C5 /* syntrax.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = syntrax.c; sourceTree = ""; }; + 83EEAB061C965247002761C5 /* syntrax.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = syntrax.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 832FF3171C96511E0076D662 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 832FF3111C96511E0076D662 = { + isa = PBXGroup; + children = ( + 832FF31D1C96511E0076D662 /* Syntrax-c */, + 832FF31C1C96511E0076D662 /* Products */, + ); + sourceTree = ""; + }; + 832FF31C1C96511E0076D662 /* Products */ = { + isa = PBXGroup; + children = ( + 832FF31B1C96511E0076D662 /* Syntrax_c.framework */, + ); + name = Products; + sourceTree = ""; + }; + 832FF31D1C96511E0076D662 /* Syntrax-c */ = { + isa = PBXGroup; + children = ( + 83EEAB011C965247002761C5 /* file.c */, + 83EEAB021C965247002761C5 /* file.h */, + 83EEAB031C965247002761C5 /* resampler.c */, + 83EEAB041C965247002761C5 /* resampler.h */, + 83EEAB051C965247002761C5 /* syntrax.c */, + 83EEAB061C965247002761C5 /* syntrax.h */, + 832FF3201C96511E0076D662 /* Info.plist */, + ); + path = "Syntrax-c"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 832FF3181C96511E0076D662 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 83EEAB0C1C965247002761C5 /* syntrax.h in Headers */, + 83EEAB081C965247002761C5 /* file.h in Headers */, + 83EEAB0A1C965247002761C5 /* resampler.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 832FF31A1C96511E0076D662 /* Syntrax_c */ = { + isa = PBXNativeTarget; + buildConfigurationList = 832FF3231C96511E0076D662 /* Build configuration list for PBXNativeTarget "Syntrax_c" */; + buildPhases = ( + 832FF3161C96511E0076D662 /* Sources */, + 832FF3171C96511E0076D662 /* Frameworks */, + 832FF3181C96511E0076D662 /* Headers */, + 832FF3191C96511E0076D662 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Syntrax_c; + productName = "Syntrax-c"; + productReference = 832FF31B1C96511E0076D662 /* Syntrax_c.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 832FF3121C96511E0076D662 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Christopher Snowhill"; + TargetAttributes = { + 832FF31A1C96511E0076D662 = { + CreatedOnToolsVersion = 7.2.1; + }; + }; + }; + buildConfigurationList = 832FF3151C96511E0076D662 /* Build configuration list for PBXProject "Syntrax_c" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 832FF3111C96511E0076D662; + productRefGroup = 832FF31C1C96511E0076D662 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 832FF31A1C96511E0076D662 /* Syntrax_c */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 832FF3191C96511E0076D662 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 832FF3161C96511E0076D662 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 83EEAB071C965247002761C5 /* file.c in Sources */, + 83EEAB0B1C965247002761C5 /* syntrax.c in Sources */, + 83EEAB091C965247002761C5 /* resampler.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 832FF3211C96511E0076D662 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 832FF3221C96511E0076D662 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 832FF3241C96511E0076D662 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = "Syntrax-c/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cogx.Syntrax-c"; + PRODUCT_NAME = Syntrax_c; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 832FF3251C96511E0076D662 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = "Syntrax-c/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cogx.Syntrax-c"; + PRODUCT_NAME = Syntrax_c; + SKIP_INSTALL = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 832FF3151C96511E0076D662 /* Build configuration list for PBXProject "Syntrax_c" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 832FF3211C96511E0076D662 /* Debug */, + 832FF3221C96511E0076D662 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 832FF3231C96511E0076D662 /* Build configuration list for PBXNativeTarget "Syntrax_c" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 832FF3241C96511E0076D662 /* Debug */, + 832FF3251C96511E0076D662 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 832FF3121C96511E0076D662 /* Project object */; +} diff --git a/Plugins/Syntrax/Syntrax.xcodeproj/project.pbxproj b/Plugins/Syntrax/Syntrax.xcodeproj/project.pbxproj new file mode 100644 index 000000000..1335ed6a9 --- /dev/null +++ b/Plugins/Syntrax/Syntrax.xcodeproj/project.pbxproj @@ -0,0 +1,356 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 83EEAB0F1C965324002761C5 /* jxsDecoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 83EEAB0E1C965324002761C5 /* jxsDecoder.m */; }; + 83EEAB111C965348002761C5 /* Syntrax_c.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83EEAB101C965348002761C5 /* Syntrax_c.framework */; }; + 83EEAB1E1C965835002761C5 /* jxsContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 83EEAB1D1C965835002761C5 /* jxsContainer.m */; }; + 83EEAB211C965A4F002761C5 /* jxsMetadataReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 83EEAB201C965A4F002761C5 /* jxsMetadataReader.m */; }; + 83EEAB231C965C32002761C5 /* Syntrax_c.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83EEAB171C96537A002761C5 /* Syntrax_c.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 83EEAB161C96537A002761C5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 83EEAB121C965379002761C5 /* Syntrax_c.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 832FF31B1C96511E0076D662; + remoteInfo = Syntrax_c; + }; + 83EEAB181C965384002761C5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 83EEAB121C965379002761C5 /* Syntrax_c.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 832FF31A1C96511E0076D662; + remoteInfo = Syntrax_c; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 83EEAB221C965C27002761C5 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 83EEAB231C965C32002761C5 /* Syntrax_c.framework in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 832FF2F81C96508E0076D662 /* Syntrax.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Syntrax.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; + 832FF2FB1C96508E0076D662 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 83EEAB0D1C965324002761C5 /* jxsDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jxsDecoder.h; sourceTree = ""; }; + 83EEAB0E1C965324002761C5 /* jxsDecoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = jxsDecoder.m; sourceTree = ""; }; + 83EEAB101C965348002761C5 /* Syntrax_c.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Syntrax_c.framework; path = "../../../../../Library/Developer/Xcode/DerivedData/Cog-gnnabzpuhvwhikcgqtwgtiebzjli/Build/Products/Debug/Syntrax_c.framework"; sourceTree = ""; }; + 83EEAB121C965379002761C5 /* Syntrax_c.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Syntrax_c.xcodeproj; path = "../../Frameworks/Syntrax-c/Syntrax_c.xcodeproj"; sourceTree = ""; }; + 83EEAB1A1C9653AA002761C5 /* Plugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Plugin.h; path = ../../../Audio/Plugin.h; sourceTree = ""; }; + 83EEAB1B1C9653C3002761C5 /* PlaylistController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlaylistController.h; path = ../../../Playlist/PlaylistController.h; sourceTree = ""; }; + 83EEAB1C1C965835002761C5 /* jxsContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jxsContainer.h; sourceTree = ""; }; + 83EEAB1D1C965835002761C5 /* jxsContainer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = jxsContainer.m; sourceTree = ""; }; + 83EEAB1F1C965A4F002761C5 /* jxsMetadataReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jxsMetadataReader.h; sourceTree = ""; }; + 83EEAB201C965A4F002761C5 /* jxsMetadataReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = jxsMetadataReader.m; sourceTree = ""; }; + 83EEAB271C965D2E002761C5 /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = ../../../Utils/Logging.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 832FF2F51C96508E0076D662 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 83EEAB111C965348002761C5 /* Syntrax_c.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 832FF2EF1C96508E0076D662 = { + isa = PBXGroup; + children = ( + 832FF2FA1C96508E0076D662 /* Syntrax */, + 832FF3101C9650E50076D662 /* Frameworks */, + 832FF2F91C96508E0076D662 /* Products */, + ); + sourceTree = ""; + }; + 832FF2F91C96508E0076D662 /* Products */ = { + isa = PBXGroup; + children = ( + 832FF2F81C96508E0076D662 /* Syntrax.bundle */, + ); + name = Products; + sourceTree = ""; + }; + 832FF2FA1C96508E0076D662 /* Syntrax */ = { + isa = PBXGroup; + children = ( + 83EEAB271C965D2E002761C5 /* Logging.h */, + 83EEAB1B1C9653C3002761C5 /* PlaylistController.h */, + 83EEAB1A1C9653AA002761C5 /* Plugin.h */, + 83EEAB1C1C965835002761C5 /* jxsContainer.h */, + 83EEAB1D1C965835002761C5 /* jxsContainer.m */, + 83EEAB0D1C965324002761C5 /* jxsDecoder.h */, + 83EEAB0E1C965324002761C5 /* jxsDecoder.m */, + 83EEAB1F1C965A4F002761C5 /* jxsMetadataReader.h */, + 83EEAB201C965A4F002761C5 /* jxsMetadataReader.m */, + 832FF2FB1C96508E0076D662 /* Info.plist */, + ); + path = Syntrax; + sourceTree = ""; + }; + 832FF3101C9650E50076D662 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 83EEAB121C965379002761C5 /* Syntrax_c.xcodeproj */, + 83EEAB101C965348002761C5 /* Syntrax_c.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 83EEAB131C965379002761C5 /* Products */ = { + isa = PBXGroup; + children = ( + 83EEAB171C96537A002761C5 /* Syntrax_c.framework */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 832FF2F71C96508E0076D662 /* Syntrax */ = { + isa = PBXNativeTarget; + buildConfigurationList = 832FF2FE1C96508E0076D662 /* Build configuration list for PBXNativeTarget "Syntrax" */; + buildPhases = ( + 832FF2F41C96508E0076D662 /* Sources */, + 832FF2F51C96508E0076D662 /* Frameworks */, + 832FF2F61C96508E0076D662 /* Resources */, + 83EEAB221C965C27002761C5 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + 83EEAB191C965384002761C5 /* PBXTargetDependency */, + ); + name = Syntrax; + productName = Syntrax; + productReference = 832FF2F81C96508E0076D662 /* Syntrax.bundle */; + productType = "com.apple.product-type.bundle"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 832FF2F01C96508E0076D662 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Christopher Snowhill"; + TargetAttributes = { + 832FF2F71C96508E0076D662 = { + CreatedOnToolsVersion = 7.2.1; + }; + }; + }; + buildConfigurationList = 832FF2F31C96508E0076D662 /* Build configuration list for PBXProject "Syntrax" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 832FF2EF1C96508E0076D662; + productRefGroup = 832FF2F91C96508E0076D662 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 83EEAB131C965379002761C5 /* Products */; + ProjectRef = 83EEAB121C965379002761C5 /* Syntrax_c.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 832FF2F71C96508E0076D662 /* Syntrax */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 83EEAB171C96537A002761C5 /* Syntrax_c.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = Syntrax_c.framework; + remoteRef = 83EEAB161C96537A002761C5 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + 832FF2F61C96508E0076D662 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 832FF2F41C96508E0076D662 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 83EEAB0F1C965324002761C5 /* jxsDecoder.m in Sources */, + 83EEAB211C965A4F002761C5 /* jxsMetadataReader.m in Sources */, + 83EEAB1E1C965835002761C5 /* jxsContainer.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 83EEAB191C965384002761C5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Syntrax_c; + targetProxy = 83EEAB181C965384002761C5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 832FF2FC1C96508E0076D662 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 832FF2FD1C96508E0076D662 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 832FF2FF1C96508E0076D662 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Syntrax/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; + PRODUCT_BUNDLE_IDENTIFIER = org.cogx.Syntrax; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + 832FF3001C96508E0076D662 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Syntrax/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; + PRODUCT_BUNDLE_IDENTIFIER = org.cogx.Syntrax; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 832FF2F31C96508E0076D662 /* Build configuration list for PBXProject "Syntrax" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 832FF2FC1C96508E0076D662 /* Debug */, + 832FF2FD1C96508E0076D662 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 832FF2FE1C96508E0076D662 /* Build configuration list for PBXNativeTarget "Syntrax" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 832FF2FF1C96508E0076D662 /* Debug */, + 832FF3001C96508E0076D662 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 832FF2F01C96508E0076D662 /* Project object */; +} diff --git a/Plugins/Syntrax/Syntrax/Info.plist b/Plugins/Syntrax/Syntrax/Info.plist new file mode 100644 index 000000000..7c0ba15dc --- /dev/null +++ b/Plugins/Syntrax/Syntrax/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSHumanReadableCopyright + Copyright © 2016 Christopher Snowhill. All rights reserved. + NSPrincipalClass + + + diff --git a/Plugins/Syntrax/Syntrax/jxsContainer.h b/Plugins/Syntrax/Syntrax/jxsContainer.h new file mode 100755 index 000000000..4f2984bdd --- /dev/null +++ b/Plugins/Syntrax/Syntrax/jxsContainer.h @@ -0,0 +1,17 @@ +// +// jxsContainer.h +// Syntrax-c +// +// Created by Christopher Snowhill on 03/14/16. +// Copyright 2016 __NoWork, Inc__. All rights reserved. +// + +#import + +#import "Plugin.h" + +@interface jxsContainer : NSObject { + +} + +@end diff --git a/Plugins/Syntrax/Syntrax/jxsContainer.m b/Plugins/Syntrax/Syntrax/jxsContainer.m new file mode 100755 index 000000000..c128cf474 --- /dev/null +++ b/Plugins/Syntrax/Syntrax/jxsContainer.m @@ -0,0 +1,105 @@ +// +// jxsContainer.m +// Syntrax-c +// +// Created by Christopher Snowhill on 03/14/16. +// Copyright 2016 __NoWork, Inc__. All rights reserved. +// + +#import +#import + +#import "jxsContainer.h" +#import "jxsDecoder.h" + +#import "Logging.h" + +@implementation jxsContainer + ++ (NSArray *)fileTypes +{ + return [jxsDecoder fileTypes]; +} + ++ (NSArray *)mimeTypes +{ + return nil; +} + ++ (float)priority +{ + return 1.0f; +} + ++ (NSArray *)urlsForContainerURL:(NSURL *)url +{ + if ([url fragment]) { + // input url already has fragment defined - no need to expand further + return [NSMutableArray arrayWithObject:url]; + } + + id audioSourceClass = NSClassFromString(@"AudioSource"); + id source = [audioSourceClass audioSourceForURL:url]; + + if (![source open:url]) + return 0; + + if (![source seekable]) + return 0; + + [source seek:0 whence:SEEK_END]; + long size = [source tell]; + [source seek:0 whence:SEEK_SET]; + + void * data = malloc(size); + [source read:data amount:size]; + + Song * synSong = File_loadSongMem(data, size); + if (!synSong) + { + ALog(@"Open failed for file: %@", [url absoluteString]); + free(data); + return NO; + } + + free(data); + + Player * synPlayer = playerCreate(44100); + if (!synPlayer) + { + ALog(@"Failed to create Syntrax-c player for file: %@", [url absoluteString]); + File_freeSong(synSong); + return NO; + } + + if (loadSong(synPlayer, synSong) < 0) + { + ALog(@"Load failed for file: %@", [url absoluteString]); + playerDestroy(synPlayer); + File_freeSong(synSong); + return NO; + } + + NSMutableArray *tracks = [NSMutableArray array]; + + syntrax_info info; + + playerGetInfo(synPlayer, &info); + + playerDestroy(synPlayer); + File_freeSong(synSong); + + int i; + int subsongs = info.totalSubs; + if ( subsongs ) { + for (i = 0; i < subsongs; i++) + { + [tracks addObject:[NSURL URLWithString:[[url absoluteString] stringByAppendingFormat:@"#%i", i]]]; + } + } + + return tracks; +} + + +@end diff --git a/Plugins/Syntrax/Syntrax/jxsDecoder.h b/Plugins/Syntrax/Syntrax/jxsDecoder.h new file mode 100755 index 000000000..de98db2be --- /dev/null +++ b/Plugins/Syntrax/Syntrax/jxsDecoder.h @@ -0,0 +1,25 @@ +// +// jxsDecoder.h +// Syntrax-c +// +// Created by Christopher Snowhill on 03/14/16. +// Copyright 2016 __NoWork, Inc__. All rights reserved. +// + +#import + +#import +#import + +#import "Plugin.h" + +@interface jxsDecoder : NSObject { + Song *synSong; + Player *synPlayer; + int track_num; + + long framesLength; + long totalFrames; + long framesRead; +} +@end diff --git a/Plugins/Syntrax/Syntrax/jxsDecoder.m b/Plugins/Syntrax/Syntrax/jxsDecoder.m new file mode 100755 index 000000000..253cfa81b --- /dev/null +++ b/Plugins/Syntrax/Syntrax/jxsDecoder.m @@ -0,0 +1,239 @@ +// +// jxsDecoder.m +// Syntrax-c +// +// Created by Christopher Snowhill on 03/14/16. +// Copyright 2016 __NoWork, Inc__. All rights reserved. +// + +#import "jxsDecoder.h" + +#import "Logging.h" + +#import "PlaylistController.h" + +@implementation jxsDecoder + +BOOL probe_length( Song * synSong, unsigned long * intro_length, unsigned long * loop_length, unsigned int subsong ) +{ + Player * synPlayer = playerCreate(44100); + + if (loadSong(synPlayer, synSong) < 0) + return NO; + + initSubsong(synPlayer, subsong); + + unsigned long length_total = 0; + unsigned long length_saved; + + const long length_safety = 44100 * 60 * 30; + + while ( !playerGetSongEnded(synPlayer) && playerGetLoopCount(synPlayer) < 1 && length_total < length_safety ) + { + mixChunk(synPlayer, NULL, 512); + length_total += 512; + } + + if ( !playerGetSongEnded(synPlayer) && playerGetLoopCount(synPlayer) < 1 ) + { + *loop_length = 0; + *intro_length = 44100 * 60 * 3; + playerDestroy(synPlayer); + return YES; + } + + length_saved = length_total; + + while ( !playerGetSongEnded(synPlayer) && playerGetLoopCount(synPlayer) < 2 ) + { + mixChunk(synPlayer, NULL, 512); + length_total += 512; + } + + playerDestroy(synPlayer); + + *loop_length = length_total - length_saved; + *intro_length = length_saved - *loop_length; + + return YES; +} + +- (BOOL)open:(id)s +{ + [s seek:0 whence:SEEK_END]; + size_t size = [s tell]; + [s seek:0 whence:SEEK_SET]; + + void * data = malloc(size); + [s read:data amount:size]; + + if ([[[s url] fragment] length] == 0) + track_num = 0; + else + track_num = [[[s url] fragment] intValue]; + + synSong = File_loadSongMem(data, size); + if (!synSong) + return NO; + + free(data); + + unsigned long intro_length, loop_length; + + if ( !probe_length(synSong, &intro_length, &loop_length, track_num) ) + return NO; + + framesLength = intro_length + loop_length * 2; + totalFrames = framesLength + 44100 * 8; + + [self willChangeValueForKey:@"properties"]; + [self didChangeValueForKey:@"properties"]; + + return YES; +} + +- (BOOL)decoderInitialize +{ + synPlayer = playerCreate(44100); + if (!synPlayer) + return NO; + + if (loadSong(synPlayer, synSong) < 0) + return NO; + + initSubsong(synPlayer, track_num); + + framesRead = 0; + + return YES; +} + +- (void)decoderShutdown +{ + if ( synPlayer ) + { + playerDestroy(synPlayer); + synPlayer = NULL; + } +} + +- (NSDictionary *)properties +{ + return [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInt:0], @"bitrate", + [NSNumber numberWithFloat:44100], @"sampleRate", + [NSNumber numberWithDouble:totalFrames], @"totalFrames", + [NSNumber numberWithInt:16], @"bitsPerSample", + [NSNumber numberWithBool:NO], @"floatingPoint", + [NSNumber numberWithInt:2], @"channels", + [NSNumber numberWithBool:YES], @"seekable", + @"host", @"endian", + nil]; +} + +- (int)readAudio:(void *)buf frames:(UInt32)frames +{ + BOOL repeat_one = IsRepeatOneSet(); + + if ( synPlayer && playerGetSongEnded(synPlayer) ) + return 0; + + if ( !repeat_one && framesRead >= totalFrames ) + return 0; + + if ( !synPlayer ) + { + if ( ![self decoderInitialize] ) + return 0; + } + + int total = 0; + while ( total < frames ) { + int framesToRender = 512; + if ( !repeat_one && framesToRender > totalFrames - framesRead ) + framesToRender = (int)(totalFrames - framesRead); + if ( framesToRender > frames - total ) + framesToRender = frames - total; + + int16_t * sampleBuf = ( int16_t * ) buf + total * 2; + + mixChunk(synPlayer, sampleBuf, framesToRender); + + if ( !repeat_one && framesRead + framesToRender > framesLength ) { + long fadeStart = ( framesLength > framesRead ) ? framesLength : framesRead; + long fadeEnd = ( framesRead + framesToRender < totalFrames ) ? framesRead + framesToRender : totalFrames; + const long fadeTotal = totalFrames - framesLength; + for ( long fadePos = fadeStart; fadePos < fadeEnd; ++fadePos ) { + const long scale = ( fadeTotal - ( fadePos - framesLength ) ); + const long offset = fadePos - framesRead; + int16_t * samples = sampleBuf + offset * 2; + samples[ 0 ] = (int16_t)(samples[ 0 ] * scale / fadeTotal); + samples[ 1 ] = (int16_t)(samples[ 1 ] * scale / fadeTotal); + } + + framesToRender = (int)(fadeEnd - framesRead); + } + + if ( !framesToRender ) + break; + + total += framesToRender; + framesRead += framesToRender; + + if ( playerGetSongEnded(synPlayer) ) + break; + } + + return total; +} + +- (long)seek:(long)frame +{ + if ( frame < framesRead || !synPlayer ) + { + [self decoderShutdown]; + if ( ![self decoderInitialize] ) + return 0; + } + + while ( framesRead < frame ) + { + int frames_todo = INT_MAX; + if ( frames_todo > frame - framesRead ) + frames_todo = (int)( frame - framesRead ); + mixChunk(synPlayer, NULL, frames_todo); + framesRead += frames_todo; + } + + framesRead = frame; + + return frame; +} + +- (void)close +{ + [self decoderShutdown]; + + if (synSong) + { + File_freeSong(synSong); + synSong = NULL; + } +} + ++ (NSArray *)fileTypes +{ + return [NSArray arrayWithObjects:@"jxs", nil]; +} + ++ (NSArray *)mimeTypes +{ + return [NSArray arrayWithObjects:@"audio/x-jxs", nil]; +} + ++ (float)priority +{ + return 1.0; +} + +@end diff --git a/Plugins/Syntrax/Syntrax/jxsMetadataReader.h b/Plugins/Syntrax/Syntrax/jxsMetadataReader.h new file mode 100644 index 000000000..5ec11f2c9 --- /dev/null +++ b/Plugins/Syntrax/Syntrax/jxsMetadataReader.h @@ -0,0 +1,17 @@ +// +// jxsMetadataReader.h +// Syntrax-c +// +// Created by Christopher Snowhill on 03/14/16. +// Copyright 2016 __NoWork, Inc__. All rights reserved. +// + +#import + +#import "Plugin.h" + +@interface jxsMetadataReader : NSObject { + +} + +@end diff --git a/Plugins/Syntrax/Syntrax/jxsMetadataReader.m b/Plugins/Syntrax/Syntrax/jxsMetadataReader.m new file mode 100644 index 000000000..838b615b9 --- /dev/null +++ b/Plugins/Syntrax/Syntrax/jxsMetadataReader.m @@ -0,0 +1,102 @@ +// +// jxsMetadataReader.m +// Syntrax-c +// +// Created by Christopher Snowhill on 03/14/16. +// Copyright 2016 __NoWork, Inc__. All rights reserved. +// + +#import "jxsMetadataReader.h" +#import "jxsDecoder.h" + +#import +#import + +#import "Logging.h" + +@implementation jxsMetadataReader + ++ (NSArray *)fileTypes +{ + return [jxsDecoder fileTypes]; +} + ++ (NSArray *)mimeTypes +{ + return [jxsDecoder mimeTypes]; +} + ++ (float)priority +{ + return 1.0f; +} + ++ (NSDictionary *)metadataForURL:(NSURL *)url +{ + id audioSourceClass = NSClassFromString(@"AudioSource"); + id source = [audioSourceClass audioSourceForURL:url]; + + if (![source open:url]) + return 0; + + if (![source seekable]) + return 0; + + [source seek:0 whence:SEEK_END]; + long size = [source tell]; + [source seek:0 whence:SEEK_SET]; + + void * data = malloc(size); + [source read:data amount:size]; + + Song * synSong = File_loadSongMem(data, size); + if (!synSong) + { + ALog(@"Open failed for file: %@", [url absoluteString]); + free(data); + return NO; + } + + free(data); + + Player * synPlayer = playerCreate(44100); + if (!synPlayer) + { + ALog(@"Failed to create player for file: %@", [url absoluteString]); + File_freeSong(synSong); + return NO; + } + + if (loadSong(synPlayer, synSong) < 0) + { + ALog(@"Load failed for file: %@", [url absoluteString]); + playerDestroy(synPlayer); + File_freeSong(synSong); + return NO; + } + + int track_num; + if ([[url fragment] length] == 0) + track_num = 0; + else + track_num = [[url fragment] intValue]; + + initSubsong(synPlayer, track_num); + + syntrax_info info; + playerGetInfo(synPlayer, &info); + + playerDestroy(synPlayer); + File_freeSong(synSong); + + //Some titles are all spaces?! + NSString *title = [[NSString stringWithUTF8String: info.subsongName] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + + if (title == nil) { + title = @""; + } + + return [NSDictionary dictionaryWithObject:title forKey:@"title"]; +} + +@end