Implemented more stringent loop checking in ft2play
parent
a7671023c4
commit
cb1a699647
Frameworks/modplay
modplay.xcodeproj
|
@ -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 = "<group>"; };
|
||||
83EAF76618E8F70400C896A6 /* dbopl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dbopl.c; sourceTree = "<group>"; };
|
||||
83EAF76718E8F70400C896A6 /* dbopl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dbopl.h; sourceTree = "<group>"; };
|
||||
83F1529219C667000000856F /* barray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = barray.h; sourceTree = "<group>"; };
|
||||
83F1529319C667000000856F /* barray.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = barray.c; sourceTree = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
83F4D54718D82105009B2DE6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
|
@ -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 */,
|
||||
|
|
|
@ -0,0 +1,189 @@
|
|||
#include "barray.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef _B_ARRAY_H_
|
||||
#define _B_ARRAY_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
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
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue