VGM export: Arcade sample looping

This commit is contained in:
tildearrow 2022-01-24 17:13:47 -05:00
parent d945e5299a
commit 9d2032d627
6 changed files with 50 additions and 20 deletions

View File

@ -4,8 +4,8 @@ project(furnace)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_PROJECT_VERSION_MAJOR 0)
set(CMAKE_PROJECT_VERSION_MINOR 4)
set(CMAKE_PROJECT_VERSION_PATCH 6)
set(CMAKE_PROJECT_VERSION_MINOR 5)
set(CMAKE_PROJECT_VERSION_PATCH 0)
if (ANDROID)
set(BUILD_GUI OFF)

View File

@ -15,17 +15,17 @@
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
<string>0.4.6</string>
<string>0.5</string>
<key>CFBundleName</key>
<string>Furnace</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.4.6</string>
<string>0.5</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>0.4.6</string>
<string>0.5</string>
<key>NSHumanReadableCopyright</key>
<string></string>
<key>NSHighResolutionCapable</key>

View File

@ -2287,25 +2287,40 @@ SafeWriter* DivEngine::saveVGM() {
if (memPos>=16777216) break;
sample->rendOffP=memPos;
unsigned int alignedSize=(sample->rendLength+0xff)&(~0xff);
unsigned int readPos=0;
if (alignedSize>65536) alignedSize=65536;
if (sample->depth==8) {
for (unsigned int j=0; j<alignedSize; j++) {
if (j>=sample->rendLength) {
pcmMem[memPos++]=0x80;
if (readPos>=sample->rendLength) {
if (sample->loopStart>=0 && sample->loopStart<(int)sample->rendLength) {
readPos=sample->loopStart;
pcmMem[memPos++]=((unsigned char)sample->rendData[readPos]+0x80);
} else {
pcmMem[memPos++]=0x80;
}
} else {
pcmMem[memPos++]=((unsigned char)sample->rendData[j]+0x80);
pcmMem[memPos++]=((unsigned char)sample->rendData[readPos]+0x80);
}
readPos++;
if (memPos>=16777216) break;
}
sample->loopOffP=readPos-sample->loopStart;
} else {
for (unsigned int j=0; j<alignedSize; j++) {
if (j>=sample->rendLength) {
pcmMem[memPos++]=0x80;
if (readPos>=sample->rendLength) {
if (sample->loopStart>=0 && sample->loopStart<(int)sample->rendLength) {
readPos=sample->loopStart;
pcmMem[memPos++]=(((unsigned short)sample->rendData[readPos]+0x8000)>>8);
} else {
pcmMem[memPos++]=0x80;
}
} else {
pcmMem[memPos++]=(((unsigned short)sample->rendData[j]+0x8000)>>8);
pcmMem[memPos++]=(((unsigned short)sample->rendData[readPos]+0x8000)>>8);
}
readPos++;
if (memPos>=16777216) break;
}
sample->loopOffP=readPos-sample->loopStart;
}
if (memPos>=16777216) break;
}
@ -3896,6 +3911,7 @@ bool DivEngine::moveSampleDown(int which) {
}
void DivEngine::noteOn(int chan, int ins, int note, int vol) {
if (chan<0 || chan>=chans) return;
isBusy.lock();
pendingNotes.push(DivNoteEvent(chan,ins,note,vol,true));
if (!playing) {
@ -3907,6 +3923,7 @@ void DivEngine::noteOn(int chan, int ins, int note, int vol) {
}
void DivEngine::noteOff(int chan) {
if (chan<0 || chan>=chans) return;
isBusy.lock();
pendingNotes.push(DivNoteEvent(chan,-1,-1,-1,false));
if (!playing) {

View File

@ -11,8 +11,8 @@
#include <map>
#include <queue>
#define DIV_VERSION "0.4.7pre1"
#define DIV_ENGINE_VERSION 29
#define DIV_VERSION "0.5pre1"
#define DIV_ENGINE_VERSION 30
enum DivStatusView {
DIV_STATUS_NOTHING=0,

View File

@ -77,8 +77,7 @@ void DivPlatformArcade::acquire_nuked(short* bufL, short* bufR, size_t start, si
chan[i].pcm.pos+=chan[i].pcm.freq;
if (chan[i].pcm.pos>=(s->rendLength<<8)) {
if (s->loopStart>=0 && s->loopStart<=(int)s->rendLength) {
// Sega PCM limitation
chan[i].pcm.pos=(s->loopStart&(~0xff))<<8;
chan[i].pcm.pos=s->loopStart<<8;
} else {
chan[i].pcm.sample=-1;
}
@ -143,8 +142,7 @@ void DivPlatformArcade::acquire_ymfm(short* bufL, short* bufR, size_t start, siz
chan[i].pcm.pos+=chan[i].pcm.freq;
if (chan[i].pcm.pos>=(s->rendLength<<8)) {
if (s->loopStart>=0 && s->loopStart<=(int)s->rendLength) {
// Sega PCM limitation
chan[i].pcm.pos=(s->loopStart&(~0xff))<<8;
chan[i].pcm.pos=s->loopStart<<8;
} else {
chan[i].pcm.sample=-1;
}
@ -262,7 +260,14 @@ int DivPlatformArcade::dispatch(DivCommand c) {
addWrite(0x10084+(pcmChan<<3),(s->rendOffP)&0xff);
addWrite(0x10085+(pcmChan<<3),(s->rendOffP>>8)&0xff);
addWrite(0x10006+(pcmChan<<3),MIN(255,((s->rendOffP&0xffff)+s->rendLength)>>8));
addWrite(0x10086+(pcmChan<<3),2+((s->rendOffP>>16)<<3));
if (s->loopStart<0 || s->loopStart>=(int)s->rendLength) {
addWrite(0x10086+(pcmChan<<3),2+((s->rendOffP>>16)<<3));
} else {
int loopPos=(s->rendOffP&0xffff)+s->loopStart+s->loopOffP;
addWrite(0x10004+(pcmChan<<3),loopPos&0xff);
addWrite(0x10005+(pcmChan<<3),(loopPos>>8)&0xff);
addWrite(0x10086+(pcmChan<<3),((s->rendOffP>>16)<<3));
}
}
} else {
chan[c.chan].pcm.sample=12*sampleBank+c.value%12;
@ -282,7 +287,14 @@ int DivPlatformArcade::dispatch(DivCommand c) {
addWrite(0x10084+(pcmChan<<3),(s->rendOffP)&0xff);
addWrite(0x10085+(pcmChan<<3),(s->rendOffP>>8)&0xff);
addWrite(0x10006+(pcmChan<<3),MIN(255,((s->rendOffP&0xffff)+s->rendLength)>>8));
addWrite(0x10086+(pcmChan<<3),2+((s->rendOffP>>16)<<3));
if (s->loopStart<0 || s->loopStart>=(int)s->rendLength) {
addWrite(0x10086+(pcmChan<<3),2+((s->rendOffP>>16)<<3));
} else {
int loopPos=(s->rendOffP&0xffff)+s->loopStart+s->loopOffP;
addWrite(0x10004+(pcmChan<<3),loopPos&0xff);
addWrite(0x10005+(pcmChan<<3),(loopPos>>8)&0xff);
addWrite(0x10086+(pcmChan<<3),((s->rendOffP>>16)<<3));
}
addWrite(0x10007+(pcmChan<<3),chan[c.chan].pcm.freq);
}
}

View File

@ -2,7 +2,7 @@
struct DivSample {
String name;
int length, rate, loopStart;
int length, rate, loopStart, loopOffP;
signed char vol, pitch;
unsigned char depth;
short* data;
@ -16,6 +16,7 @@ struct DivSample {
length(0),
rate(32000),
loopStart(-1),
loopOffP(0),
vol(0),
pitch(0),
depth(16),