Previous Thread
Next Thread
Print Thread
Page 4 of 55 1 2 3 4 5 6 54 55
Joined: Nov 2003
Posts: 459
K
Senior Member
Offline
Senior Member
K
Joined: Nov 2003
Posts: 459
No, no, kingshriek did a full rip later.
ftp://ftp.modland.com/pub/modules/Dreamcast%20Sound%20Format/-%20unknown/Skies%20Of%20Arcadia/

PS2 had a whole slew of 'budget' releases, all those Visual Novel ports and the general assorted Japanese crud. Dreamcast is mostly arcade games (Model 3 ports obviously). I think KID did port of of their Visual Novels to it though, that's one thing to look at. smile

Joined: Mar 2001
Posts: 17,215
Likes: 234
R
Very Senior Member
OP Offline
Very Senior Member
R
Joined: Mar 2001
Posts: 17,215
Likes: 234
Oh, nice! Hell, if there's a full rip of SOA I might do a DSF engine just for that reason :-)

Also, plenty of non-budget PS2 games used sequenced music, although it was much more popular with Japanese devs than US/European ones.

Joined: May 2002
Posts: 67
N
Member
Offline
Member
N
Joined: May 2002
Posts: 67
Would a DSF engine be extensible to NAOMI?

Seconding the desire for SoA/EA, the soundtrack CD was too few discs for too much music and suffered as a result frown


-nZero
Joined: Mar 2001
Posts: 17,215
Likes: 234
R
Very Senior Member
OP Offline
Very Senior Member
R
Joined: Mar 2001
Posts: 17,215
Likes: 234
Yes. I would assume that pre-GDROM Naomi games are probably a good hunting ground for sequenced music, as well.

Incidentally, the Hikaru board has 2 AICAs and 2 blocks of RAM. (And since the AICA integrates an ARM7TDMI, it's got two of those too).

Joined: Mar 2001
Posts: 17,215
Likes: 234
R
Very Senior Member
OP Offline
Very Senior Member
R
Joined: Mar 2001
Posts: 17,215
Likes: 234
AOSDK's been updated with the latest.

Joined: Sep 2007
Posts: 56
K
Member
Offline
Member
K
Joined: Sep 2007
Posts: 56
I have some more SCSP fixes - these ones are AO specific.

The main AO fix relates to a problem I noticed in the 8-bit sampler in that it didn't account for sound memory being byte-swapped, making the 8-bit samples come out distorted. While I was at it, I also put in the interpolation code from MAME into the sampler.

Also I noticed that in the panning fix I put in awhile back, I screwed up the operator precedence, so I fixed that (someone else had already noticed this and fixed it for the MAME update).

Patch against AO SDK 1.1.4:

Code
diff -Nru aosdk_base/eng_ssf/scsp.c aosdk/eng_ssf/scsp.c
--- aosdk_base/eng_ssf/scsp.c	2007-12-11 08:52:18.000000000 -0800
+++ aosdk/eng_ssf/scsp.c	2007-12-12 04:00:20.000000000 -0800
@@ -512,7 +512,7 @@
 		if(iPAN&0x4) SegaDB-=12;
 		if(iPAN&0x8) SegaDB-=24;
 
-		if(iPAN&0xf==0xf) PAN=0.0;
+		if((iPAN&0xf)==0xf) PAN=0.0;
 		else PAN=pow(10.0,SegaDB/20.0);
 
 		if(iPAN<0x10)
@@ -1125,13 +1125,23 @@
 
 	if(PCM8B(slot))	//8 bit signed
 	{
-		INT8 *p=(signed char *) (slot->base+(addr));
-		sample=(p[0])<<8;
+		INT8 *p=(signed char *) (SCSP->SCSPRAM+((SA(slot)+addr)^1));
+		//sample=(p[0])<<8;
+		INT32 s;
+		INT32 fpart=slot->cur_addr&((1<<SHIFT)-1);
+		s=(int) (p[0]<<8)*((1<<SHIFT)-fpart)+(int) slot->Prev*fpart;
+		sample=(s>>SHIFT);
+		slot->Prev=p[0]<<8;
 	}
 	else	//16 bit signed (endianness?)
 	{
 		INT16 *p=(signed short *) (slot->base+addr);
-		sample=LE16(p[0]);
+		//sample=LE16(p[0]);
+		INT32 s;
+		INT32 fpart=slot->cur_addr&((1<<SHIFT)-1);
+		s=(int) LE16(p[0])*((1<<SHIFT)-fpart)+(int) slot->Prev*fpart;
+		sample=(s>>SHIFT);
+		slot->Prev=LE16(p[0]);
 	}
 
 	if(SBCTL(slot)&0x1)


Changes (AO-specific):
-Fixed 8-bit sampler to handle byte-swapped RAM
-Added in interpolation code from MAME
-Fixed an error in the panning calculation

Last edited by kingshriek; 12/12/07 12:16 PM.
Joined: Mar 2001
Posts: 17,215
Likes: 234
R
Very Senior Member
OP Offline
Very Senior Member
R
Joined: Mar 2001
Posts: 17,215
Likes: 234
Nice. That fixes the hard-panned cymbals in Black Matrix that shouldn't have been, and the interpolation does smooth out the sound a bit.

The AOSDK version's been bumped again to include this new stuff.

Joined: Sep 2007
Posts: 56
K
Member
Offline
Member
K
Joined: Sep 2007
Posts: 56
Well, I've been investigating sound quality issues some more and found that the interpolation wasn't really doing what was intended (an initial spectral analysis didn't show any significant rise in SNR). The sampler was interpolating over the previous and current sample but using a fractional address that corresponds to the current and next sample instead. After fixing the interpolation to use the current and next sample, I ended up with an SNR gain of 10 dB - much more along the lines of what I would have expected from it. This translates to a much improved playback quality.

Along the way, I fixed many issues. I tweaked the key-rate scaling calculation a bit to fix some problems in sakutai_07.ssf where some samples were getting cut off too early. Also, I noticed some non-looping samples actually had LEA (loop end address) set to 0, causing the samples not to be played at all (sakutai_02.ssf being an example). To handle this, I just check that the current address is greater than both LSA (loop start address) and LEA before stopping the slot. I also fixed the backwards loop mode so that it initially samples forwards before first hitting LSA (Soukyugurentai and Panzer Dragoon Saga use this loop mode).

Patch against AO SDK 1.1.5:
Code
diff -Nru aosdk_base/eng_ssf/scsp.c aosdk/eng_ssf/scsp.c
--- aosdk_base/eng_ssf/scsp.c	2007-12-12 09:36:00.000000000 -0800
+++ aosdk/eng_ssf/scsp.c	2007-12-14 04:28:31.000000000 -0800
@@ -134,6 +134,7 @@
 	UINT8 active;	//this slot is currently playing
 	UINT8 *base;		//samples base address
 	UINT32 cur_addr;	//current play address (24.8)
+	UINT32 nxt_addr;	//next play address
 	UINT32 step;		//pitch step (24.8)
 	UINT8 Backwards;	//the wave is playing backwards
 	struct _EG EG;			//Envelope
@@ -315,7 +316,7 @@
 	int rate;
 	if(octave&8) octave=octave-16;
 	if(KRS(slot)!=0xf)
-		rate=2*(octave+KRS(slot))+((FNS(slot)>>9)&1);
+		rate=octave+2*KRS(slot)+((FNS(slot)>>9)&1);
 	else
 		rate=0; //rate=((FNS(slot)>>9)&1);
 
@@ -383,7 +384,7 @@
 static UINT32 SCSP_Step(struct _SLOT *slot)
 {
 	int octave=OCT(slot);
-	int Fn;
+	UINT32 Fn;
 
 	Fn=(FNS_Table[FNS(slot)]);	//24.8
 	if(octave&8)
@@ -408,7 +409,7 @@
 	UINT32 start_offset;
 	slot->active=1;
 	slot->Backwards=0;
-	slot->cur_addr=0;
+	slot->cur_addr=0; slot->nxt_addr=1<<SHIFT;
 	start_offset = PCM8B(slot) ? SA(slot) : SA(slot) & 0x7FFFE;
 	slot->base=SCSP->SCSPRAM + start_offset;
 	slot->step=SCSP_Step(slot);
@@ -1089,7 +1090,9 @@
 {
 	INT32 sample;
 	int step=slot->step;
-	UINT32 addr;
+	UINT32 addr1,addr2,addr_select;                                   // current and next sample addresses
+	UINT32 *addr[2]      = {&addr1, &addr2};                          // used for linear interpolation
+	UINT32 *slot_addr[2] = {&(slot->cur_addr), &(slot->nxt_addr)};    //
 
 	if(SSCTL(slot)!=0)	//no FM or noise yet
 		return 0;
@@ -1101,23 +1104,33 @@
 	}
 
 	if(PCM8B(slot))
-		addr=slot->cur_addr>>SHIFT;
+	{
+		addr1=slot->cur_addr>>SHIFT;
+		addr2=slot->nxt_addr>>SHIFT;
+	}
 	else
-		addr=(slot->cur_addr>>(SHIFT-1))&0x7fffe;
+	{
+		addr1=(slot->cur_addr>>(SHIFT-1))&0x7fffe;
+		addr2=(slot->nxt_addr>>(SHIFT-1))&0x7fffe;
+	}
 
 	if(MDL(slot)!=0 || MDXSL(slot)!=0 || MDYSL(slot)!=0)
 	{
 		INT32 smp=(SCSP->RINGBUF[(SCSP->BUFPTR+MDXSL(slot))&63]+SCSP->RINGBUF[(SCSP->BUFPTR+MDYSL(slot))&63])/2;
 
 		smp>>=11;
-		addr+=smp;
+		addr1+=smp; addr2+=smp;
 		if(!PCM8B(slot))
-			addr&=0x7fffe;
+		{
+			addr1&=0x7fffe; addr2&=0x7fffe;
+		}
 		else
-			addr&=0x7ffff;
+		{
+			addr1&=0x7ffff; addr2&=0x7ffff;
+		}
 	}
 
-	if(addr==LSA(slot))
+	if(addr1==LSA(slot))
 	{
 		if(LPSLNK(slot) && slot->EG.state==ATTACK)
 			slot->EG.state = DECAY1;
@@ -1125,23 +1138,23 @@
 
 	if(PCM8B(slot))	//8 bit signed
 	{
-		INT8 *p=(signed char *) (SCSP->SCSPRAM+((SA(slot)+addr)^1));
+		INT8 *p1=(signed char *) (SCSP->SCSPRAM+((SA(slot)+addr1)^1));
+		INT8 *p2=(signed char *) (SCSP->SCSPRAM+((SA(slot)+addr2)^1));
 		//sample=(p[0])<<8;
 		INT32 s;
 		INT32 fpart=slot->cur_addr&((1<<SHIFT)-1);
-		s=(int) (p[0]<<8)*((1<<SHIFT)-fpart)+(int) slot->Prev*fpart;
+		s=(int) (p1[0]<<8)*((1<<SHIFT)-fpart)+(int) (p2[0]<<8)*fpart;
 		sample=(s>>SHIFT);
-		slot->Prev=p[0]<<8;
 	}
 	else	//16 bit signed (endianness?)
 	{
-		INT16 *p=(signed short *) (slot->base+addr);
+		INT16 *p1=(signed short *) (slot->base+addr1);
+		INT16 *p2=(signed short *) (slot->base+addr2);
 		//sample=LE16(p[0]);
 		INT32 s;
 		INT32 fpart=slot->cur_addr&((1<<SHIFT)-1);
-		s=(int) LE16(p[0])*((1<<SHIFT)-fpart)+(int) slot->Prev*fpart;
+		s=(int) LE16(p1[0])*((1<<SHIFT)-fpart)+(int) LE16(p2[0])*fpart;
 		sample=(s>>SHIFT);
-		slot->Prev=LE16(p[0]);
 	}
 
 	if(SBCTL(slot)&0x1)
@@ -1153,41 +1166,48 @@
 		slot->cur_addr-=step;
 	else
 		slot->cur_addr+=step;
-	addr=slot->cur_addr>>SHIFT;
-	switch(LPCTL(slot))
+	slot->nxt_addr=slot->cur_addr+(1<<SHIFT);
+	
+	addr1=slot->cur_addr>>SHIFT;
+	addr2=slot->nxt_addr>>SHIFT;
+	
+	for (addr_select=0;addr_select<2;addr_select++)
 	{
-	case 0:	//no loop
-		if(addr>=LEA(slot))
+		switch(LPCTL(slot))
 		{
+		case 0:	//no loop
+			if(*addr[addr_select]>=LSA(slot) && *addr[addr_select]>=LEA(slot))
+			{
 			//slot->active=0;
 			SCSP_StopSlot(slot,0);
+			}
+			break;
+		case 1: //normal loop
+			if(*addr[addr_select]>=LEA(slot))
+				*slot_addr[addr_select]=LSA(slot)<<SHIFT;
+			break;
+		case 2:	//reverse loop
+			if((*addr[addr_select]>=LSA(slot)) && !(slot->Backwards))
+			{
+				*slot_addr[addr_select]=LEA(slot)<<SHIFT;
+				slot->Backwards=1;
+			}
+			if((*addr[addr_select]<=LSA(slot) || (*slot_addr[addr_select]&0x80000000)) && slot->Backwards)
+				*slot_addr[addr_select]=LEA(slot)<<SHIFT;
+			break;
+		case 3: //ping-pong
+			if(*addr[addr_select]>=LEA(slot)) //reached end, reverse till start
+			{
+				*slot_addr[addr_select]=LEA(slot)<<SHIFT;
+				slot->Backwards=1;
+			}
+			if((*addr[addr_select]<=LSA(slot) || (*slot_addr[addr_select]&0x80000000)) && slot->Backwards)//reached start or negative
+			{
+				*slot_addr[addr_select]=LSA(slot)<<SHIFT;
+				slot->Backwards=0;
+			}
+			break;
 		}
-		break;
-	case 1: //normal loop
-		if(addr>=LEA(slot))
-			slot->cur_addr=LSA(slot)<<SHIFT;
-		break;
-	case 2:	//reverse loop
-		if(addr>=LEA(slot))
-		{
-			slot->cur_addr=LEA(slot)<<SHIFT;
-			slot->Backwards=1;
-		}
-		if(addr<LSA(slot) || (addr&0x80000000))
-			slot->cur_addr=LEA(slot)<<SHIFT;
-		break;
-	case 3: //ping-pong
-		if(addr>=LEA(slot)) //reached end, reverse till start
-		{
-			slot->cur_addr=LEA(slot)<<SHIFT;
-			slot->Backwards=1;
-		}
-		if((addr<LSA(slot) || (addr&0x80000000)) && slot->Backwards)//reached start or negative
-		{
-			slot->cur_addr=LSA(slot)<<SHIFT;
-			slot->Backwards=0;
-		}
-		break;
 	}
 
 	if(ALFOS(slot)!=0)


Changes:
-Rewrote much of the interpolation code
-Improved key-rate scaling calculation
-Fixed playback of non-looping samples with a zero loop-end address
-Fixed backwards looping mode so that it initially reads forward until encountering the loop-start address

Joined: Mar 2001
Posts: 17,215
Likes: 234
R
Very Senior Member
OP Offline
Very Senior Member
R
Joined: Mar 2001
Posts: 17,215
Likes: 234
Ok, that's a fantastic improvement in both the overall noise floor and the "smoothness" of some samples (e.g. the trumpet that comes in during sakutai_11 no longer sounds terribly rough).

Updated 1.1.6 SDK is posted.

Joined: Sep 2007
Posts: 56
K
Member
Offline
Member
K
Joined: Sep 2007
Posts: 56
While working with Assault Suit Leynos 2, I've discovered that it makes a very good test case for properly emulating the SCSP's FM synthesis capabilities. Quite a few tracks use it with clearly defined carrier and modulator layers.

Here's a patch against AO SDK 1.1.6 with my interpretation of the SCSP manual's overly confusing FM section:

Patch currently withdrawn, see EDIT
Code

The patch will definitely need testing against actual Saturn output (I myself haven't yet played enough of Leynos 2 to get to any stages that use FM-synth). Here's a test track from Leynos 2 that uses FM: http://h1.ripway.com/kingshriek/leynos2_modulation_test.zip. In the archive are two ssfs - one is the full track and the other is the FM voice only (a full modulation level of MDL=0xF is used).

Also in the patch is a small fix to the sampler step calculation. High OCT values (such as in pdz_11.ssf) were causing the calculation to roll over, so I changed UINT32 to UINT64.

Changes:
-Updated modulation code, taking into account MDL (needs testing against actual hardware output)
-Changed frequency-step calculation to use UINT64 to fix rollover problems caused by large OCT values

Last edited by kingshriek; 12/16/07 05:08 PM. Reason: Discovered that Shinobi X makes a lot more use of FM - going to do some more testing
Page 4 of 55 1 2 3 4 5 6 54 55

Moderated by  R. Belmont, Richard Bannister 

Link Copied to Clipboard
Who's Online Now
5 members (Dodg, yugffuts, judge, AJR, Vag), 289 guests, and 1 robot.
Key: Admin, Global Mod, Mod
ShoutChat
Comment Guidelines: Do post respectful and insightful comments. Don't flame, hate, spam.
Forum Statistics
Forums9
Topics9,320
Posts121,923
Members5,074
Most Online1,283
Dec 21st, 2022
Our Sponsor
These forums are sponsored by Superior Solitaire, an ad-free card game collection for macOS and iOS. Download it today!

Superior Solitaire
Forum hosted by www.retrogamesformac.com