diff --git a/Frameworks/modplay/modplay.xcodeproj/project.pbxproj b/Frameworks/modplay/modplay.xcodeproj/project.pbxproj index dcc498bc6..de37782e3 100644 --- a/Frameworks/modplay/modplay.xcodeproj/project.pbxproj +++ b/Frameworks/modplay/modplay.xcodeproj/project.pbxproj @@ -13,6 +13,8 @@ 839CAC4018DA746000D67EA9 /* ft2play.c in Sources */ = {isa = PBXBuildFile; fileRef = 839CAC3F18DA746000D67EA9 /* ft2play.c */; }; 83EAF76818E8F70400C896A6 /* dbopl.c in Sources */ = {isa = PBXBuildFile; fileRef = 83EAF76618E8F70400C896A6 /* dbopl.c */; }; 83EAF76918E8F70400C896A6 /* dbopl.h in Headers */ = {isa = PBXBuildFile; fileRef = 83EAF76718E8F70400C896A6 /* dbopl.h */; }; + 83F1529419C667000000856F /* barray.h in Headers */ = {isa = PBXBuildFile; fileRef = 83F1529219C667000000856F /* barray.h */; }; + 83F1529519C667000000856F /* barray.c in Sources */ = {isa = PBXBuildFile; fileRef = 83F1529319C667000000856F /* barray.c */; }; 83F4D54818D82105009B2DE6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 83F4D54618D82105009B2DE6 /* InfoPlist.strings */; }; 83F4D57718D821D2009B2DE6 /* st3play.c in Sources */ = {isa = PBXBuildFile; fileRef = 83F4D57318D821D2009B2DE6 /* st3play.c */; }; 83F4D57818D821D2009B2DE6 /* st3play.h in Headers */ = {isa = PBXBuildFile; fileRef = 83F4D57418D821D2009B2DE6 /* st3play.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -25,6 +27,8 @@ 839CAC3F18DA746000D67EA9 /* ft2play.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ft2play.c; sourceTree = ""; }; 83EAF76618E8F70400C896A6 /* dbopl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dbopl.c; sourceTree = ""; }; 83EAF76718E8F70400C896A6 /* dbopl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dbopl.h; sourceTree = ""; }; + 83F1529219C667000000856F /* barray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = barray.h; sourceTree = ""; }; + 83F1529319C667000000856F /* barray.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = barray.c; sourceTree = ""; }; 83F4D53A18D82105009B2DE6 /* modplay.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = modplay.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 83F4D54518D82105009B2DE6 /* modplay-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "modplay-Info.plist"; sourceTree = ""; }; 83F4D54718D82105009B2DE6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -78,6 +82,8 @@ 83F4D54318D82105009B2DE6 /* modplay */ = { isa = PBXGroup; children = ( + 83F1529219C667000000856F /* barray.h */, + 83F1529319C667000000856F /* barray.c */, 83EAF76618E8F70400C896A6 /* dbopl.c */, 83EAF76718E8F70400C896A6 /* dbopl.h */, 838A72E418DEC9A1007C8A7D /* resampler.c */, @@ -107,6 +113,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 83F1529419C667000000856F /* barray.h in Headers */, 838A72E718DEC9A1007C8A7D /* resampler.h in Headers */, 835CBC8218DA95AC0087A03E /* ft2play.h in Headers */, 83EAF76918E8F70400C896A6 /* dbopl.h in Headers */, @@ -177,6 +184,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 83F1529519C667000000856F /* barray.c in Sources */, 838A72E618DEC9A1007C8A7D /* resampler.c in Sources */, 83EAF76818E8F70400C896A6 /* dbopl.c in Sources */, 83F4D57718D821D2009B2DE6 /* st3play.c in Sources */, diff --git a/Frameworks/modplay/modplay/barray.c b/Frameworks/modplay/modplay/barray.c new file mode 100644 index 000000000..b2aa082e3 --- /dev/null +++ b/Frameworks/modplay/modplay/barray.c @@ -0,0 +1,189 @@ +#include "barray.h" + +#include + + +void * bit_array_create(size_t size) +{ + size_t bsize = ((size + 7) >> 3) + sizeof(size_t); + void * ret = calloc(1, bsize); + if (ret) *(size_t *)ret = size; + return ret; +} + +void bit_array_destroy(void * array) +{ + if (array) free(array); +} + +void * bit_array_dup(void * array) +{ + if (array) + { + size_t * size = (size_t *) array; + size_t bsize = ((*size + 7) >> 3) + sizeof(*size); + void * ret = malloc(bsize); + if (ret) memcpy(ret, array, bsize); + return ret; + } + return NULL; +} + +void bit_array_reset(void * array) +{ + if (array) + { + size_t * size = (size_t *) array; + size_t bsize = (*size + 7) >> 3; + memset(size + 1, 0, bsize); + } +} + + +void bit_array_set(void * array, size_t bit) +{ + if (array) + { + size_t * size = (size_t *) array; + if (bit < *size) + { + unsigned char * ptr = (unsigned char *)(size + 1); + ptr[bit >> 3] |= (1U << (bit & 7)); + } + } +} + +void bit_array_set_range(void * array, size_t bit, size_t count) +{ + if (array && count) + { + size_t * size = (size_t *) array; + if (bit < *size) + { + unsigned char * ptr = (unsigned char *)(size + 1); + size_t i; + for (i = bit; i < *size && i < bit + count; ++i) + ptr[i >> 3] |= (1U << (i & 7)); + } + } +} + +int bit_array_test(void * array, size_t bit) +{ + if (array) + { + size_t * size = (size_t *) array; + if (bit < *size) + { + unsigned char * ptr = (unsigned char *)(size + 1); + if (ptr[bit >> 3] & (1U << (bit & 7))) + { + return 1; + } + } + } + return 0; +} + +int bit_array_test_range(void * array, size_t bit, size_t count) +{ + if (array) + { + size_t * size = (size_t *) array; + if (bit < *size) + { + unsigned char * ptr = (unsigned char *)(size + 1); + if ((bit & 7) && (count > 8)) + { + while ((bit < *size) && count && (bit & 7)) + { + if (ptr[bit >> 3] & (1U << (bit & 7))) return 1; + bit++; + count--; + } + } + if (!(bit & 7)) + { + while (((*size - bit) >= 8) && (count >= 8)) + { + if (ptr[bit >> 3]) return 1; + bit += 8; + count -= 8; + } + } + while ((bit < *size) && count) + { + if (ptr[bit >> 3] & (1U << (bit & 7))) return 1; + bit++; + count--; + } + } + } + return 0; +} + +void bit_array_clear(void * array, size_t bit) +{ + if (array) + { + size_t * size = (size_t *) array; + if (bit < *size) + { + unsigned char * ptr = (unsigned char *)(size + 1); + ptr[bit >> 3] &= ~(1U << (bit & 7)); + } + } +} + +void bit_array_clear_range(void * array, size_t bit, size_t count) +{ + if (array && count) + { + size_t * size = (size_t *) array; + if (bit < *size) + { + unsigned char * ptr = (unsigned char *)(size + 1); + size_t i; + for (i = bit; i < *size && i < bit + count; ++i) + ptr[i >> 3] &= ~(1U << (i & 7)); + } + } +} + +void bit_array_merge(void * dest, void * source, size_t offset) +{ + if (dest && source) + { + size_t * dsize = (size_t *) dest; + size_t * ssize = (size_t *) source; + size_t soffset = 0; + while (offset < *dsize && soffset < *ssize) + { + if (bit_array_test(source, soffset)) + { + bit_array_set(dest, offset); + } + soffset++; + offset++; + } + } +} + +void bit_array_mask(void * dest, void * source, size_t offset) +{ + if (dest && source) + { + size_t * dsize = (size_t *) dest; + size_t * ssize = (size_t *) source; + size_t soffset = 0; + while (offset < *dsize && soffset < *ssize) + { + if (bit_array_test(source, soffset)) + { + bit_array_clear(dest, offset); + } + soffset++; + offset++; + } + } +} diff --git a/Frameworks/modplay/modplay/barray.h b/Frameworks/modplay/modplay/barray.h new file mode 100644 index 000000000..fe8094cfc --- /dev/null +++ b/Frameworks/modplay/modplay/barray.h @@ -0,0 +1,24 @@ +#ifndef _B_ARRAY_H_ +#define _B_ARRAY_H_ + +#include + +void * bit_array_create(size_t size); +void bit_array_destroy(void * array); +void * bit_array_dup(void * array); + +void bit_array_reset(void * array); + +void bit_array_set(void * array, size_t bit); +void bit_array_set_range(void * array, size_t bit, size_t count); + +int bit_array_test(void * array, size_t bit); +int bit_array_test_range(void * array, size_t bit, size_t count); + +void bit_array_clear(void * array, size_t bit); +void bit_array_clear_range(void * array, size_t bit, size_t count); + +void bit_array_merge(void * array, void * source, size_t offset); +void bit_array_mask(void * array, void * source, size_t offset); + +#endif diff --git a/Frameworks/modplay/modplay/ft2play.c b/Frameworks/modplay/modplay/ft2play.c index 209945785..29e7f6332 100644 --- a/Frameworks/modplay/modplay/ft2play.c +++ b/Frameworks/modplay/modplay/ft2play.c @@ -42,6 +42,8 @@ #include "resampler.h" +#include "barray.h" + #include "ft2play.h" #if defined(_MSC_VER) && !defined(inline) @@ -425,7 +427,7 @@ typedef struct uint8_t muted[16]; uint32_t loopCount; - uint8_t playedOrder[8192]; + void * playedRows; } PLAYER; /* FUNCTION DECLARATIONS */ @@ -879,11 +881,9 @@ static void CheckEffects(PLAYER *p, StmTyp *ch) p->Song.PBreakFlag = 1; } } - if (p->Song.PBreakFlag == 1 && p->Song.PBreakPos == 0) + if (p->Song.PBreakFlag == 1) { - int32_t offset = p->Song.SongPos / 8; - int32_t bit = 1 << (p->Song.SongPos % 8); - p->playedOrder[offset] &= ~bit; + bit_array_clear_range(p->playedRows, p->Song.SongPos * 1024 + ch->PattPos, (p->Song.PattPos & 0x00FF) - ch->PattPos + 1); } } } @@ -2118,7 +2118,11 @@ static void MainPlayer(PLAYER *p) /* periodically called from mixer */ if (p->Song.PattDelTime2) { p->Song.PattDelTime2--; - if (p->Song.PattDelTime2) p->Song.PattPos--; + if (p->Song.PattDelTime2) + { + p->Song.PattPos--; + bit_array_clear(p->playedRows, p->Song.SongPos * 1024 + p->Song.PattPos); + } } if (p->Song.PBreakFlag) @@ -2140,17 +2144,12 @@ static void MainPlayer(PLAYER *p) /* periodically called from mixer */ p->Song.PattLen = p->PattLens[p->Song.PattNr]; } - if (p->Song.PattPos == 0) + if (bit_array_test(p->playedRows, p->Song.SongPos * 1024 + p->Song.PattPos)) { - int32_t offset = p->Song.SongPos / 8; - int32_t bit = 1 << (p->Song.SongPos % 8); - if (p->playedOrder[offset] & bit) - { - p->loopCount++; - memset(p->playedOrder, 0, sizeof(p->playedOrder)); - } - p->playedOrder[offset] |= bit; + p->loopCount++; + bit_array_reset(p->playedRows); } + bit_array_set(p->playedRows, p->Song.SongPos * 1024 + p->Song.PattPos); } } else @@ -3855,6 +3854,8 @@ void * ft2play_Alloc(uint32_t _samplingFrequency, int8_t interpolation, int8_t r /* generate FT2's pan table [round(65536*sqrt(n/256)) for n = 0...256] */ for (i = 0; i < 257; ++i) p->PanningTab[i] = sqrtf((float)(i) / 256.0f); + + p->playedRows = NULL; return p; @@ -3871,6 +3872,8 @@ void ft2play_Free(void *_p) if (p->Playing) { + if (p->playedRows) bit_array_destroy(p->playedRows); p->playedRows = NULL; + if (p->masterBufferL) free(p->masterBufferL); p->masterBufferL = NULL; if (p->masterBufferR) free(p->masterBufferR); p->masterBufferR = NULL; } @@ -3915,8 +3918,10 @@ void ft2play_PlaySong(void *_p, int32_t startOrder) p->Song.startOrder = (int16_t)startOrder; p->loopCount = 0; - memset(p->playedOrder, 0, sizeof(p->playedOrder)); - p->playedOrder[startOrder / 8] = 1 << (startOrder % 8); + + if (p->playedRows) bit_array_destroy(p->playedRows); + p->playedRows = bit_array_create(1024 * (p->Song.Len ?: 1)); + bit_array_set(p->playedRows, startOrder * 1024); } static int mopen_is_big_endian;