Dual PCM

Discussion in 'Utilities' started by MarkeyJester, Nov 27, 2016.

  1. Natsumi

    Natsumi Markey's Member

    Joined:
    Oct 7, 2011
    Messages:
    648
    Location:
    Otter's lap
    All of the SFX is delayed by very noticeable degree. I hit a ring, and only after few frames (say, 5-8), the ring sfx starts playing. I tested using Regen
     
  2. MarkeyJester

    MarkeyJester !%#@ Member

    Joined:
    Jun 27, 2009
    Messages:
    2,660
    Yeah, that's pretty much what the problem is.

    The YM2612 address/data is now cued in a list in Z80 RAM to shortern the distance between stopping and starting the Z80. Unfortunately, the Z80 just isn't fast enough to handle all of the requests from SMPS, and thus, the list needs to be rather large, hence, a delay.
     
  3. MarkeyJester

    MarkeyJester !%#@ Member

    Joined:
    Jun 27, 2009
    Messages:
    2,660
    Try this.

    I was suspecting the Z80 was too slow. Turns out, it wasn't the Z80 that was slow, it was the 68k, or more specifically, interrupts on 68k side causing de-synchronisation .
     
  4. Natsumi

    Natsumi Markey's Member

    Joined:
    Oct 7, 2011
    Messages:
    648
    Location:
    Otter's lap
    It's much better, but there is still a little delay that is offputting
     
  5. MarkeyJester

    MarkeyJester !%#@ Member

    Joined:
    Jun 27, 2009
    Messages:
    2,660
    There is a slight delay between the PSG and the FM/DAC, that might be what's sounding off, I have JUST fixed that right now this second. If that's not it, then you must have brilliant ears, because the overall delay is a single frame =$

    Also, I am a little embarrassed to report that...

    ...well, I've made a fatal error that caused the sound driver to sound aweful on hardware. I STRONGLY suggest fixing it by opening up "Macro.asm", and in "Z80DMA_ON", changing this:

    Code:
    		move.w	#$0000,d7
    To this:

    Code:
    		move.w	#$0180,d7
    This didn't allow the Z80 enough time, and well, the results were horrible, this will fix the quality greatly... You won't notice this quality on emulation, but you will definately on hardware!

    I will have an update coming later on tonight which will ensure the highest quality possible for 20,500Hz Dual samples, it's gonna be AMAZING guys, because you'll be able to hear the difference on emulation as well as hardware~

    Edit; here's a recording of it so far from hardware:

    Model 1 Recording
    Nomad Recording

    I couldn't get a Model 2 recording because it lacks a headphone jack, but it sounds pretty damn fine on there (in fact, Model 2's filter seems to do the samples some extra justice).
     
    Last edited: Dec 13, 2016
  6. MarkeyJester

    MarkeyJester !%#@ Member

    Joined:
    Jun 27, 2009
    Messages:
    2,660
    UPDATE!!

    We now have an update, this driver now avoids Z80 stops caused by FM operator data being written, I shall update the first post with the most recent version, but here is a list of steps you those that already have the driver installed and in use.

    >> 1. Download this new "Z80.asm" source, and replace the old one in the "Dual PCM" folder.

    >> 2. Download this new "Macros.asm" source, and replace the old one.

    >> 3. Open up "sonic1.asm" and find "sub_71B4C:":

    Code:
    sub_71B4C:				; XREF: loc_B10; PalToCRAM
    		lea	($FFF000).l,a6
    Replace this, with:

    Code:
    YM_Access_WaitRead:
    		StartZ80					; EXT: request Z80 stop off (allow it to continue)
    		rept	$10					; EXT: delay for a long enough time to allow the...
    		nop						; EXT: '' ...68k pointer to be saved correctly.
    		endr						; EXT: ''
    
    sub_71B4C:   
    		lea	($FFF000).l,a6
    
    		lea	($A00000+YM_Access).l,a0		; EXT: load access address in Z80
    		move.l	#$A00000,d0				; EXT: prepare Z80 RAM address in d0 (i.e. start of Cue list address)
    		StopZ80						; EXT: request Z80 stop on
    		tst.b	(a0)+					; EXT: is the Z80 accessing the 68k pointer?
    		bne.s	YM_Access_WaitRead			; EXT: if so, branch and wait for it to finish...
    		move.b	(a0)+,d1				; EXT: load lower byte of pointer
    		move.b	(a0)+,d0				; EXT: load upper byte of pointer
    		StartZ80					; EXT: request Z80 stop off
    		lsl.w	#$08,d0					; EXT: shift upper byte up
    		move.b	d1,d0					; EXT: put lower byte with it
    		move.l	d0,$10(a6)				; EXT: store the cue address
    >> 4. Find "loc_71C44:":

    Code:
    loc_71C44:
    		rts	
    Replace it with this:

    Code:
    loc_71C44:
    		bra.s	YM_Access_TestWrite			; EXT: jump into the access loop
    
    YM_Access_WaitWrite:
    		StartZ80					; EXT: request Z80 stop off (allow it to continue)
    		rept	$10					; EXT: delay for a long enough time to let the Z80...
    		nop						; EXT: '' ...finish writing the 68k pointer, so it doesn't...
    		endr						; EXT: '' ...clash with 68k's pointer writing.
    
    YM_Access_TestWrite:
    		lea	($A00000+YM_Access).l,a0		; EXT: load access address in Z80
    		lea	$13(a6),a1				; EXT: load the 68k's pointer finish location
    		StopZ80						; EXT: request Z80 stop on
    		tst.b	(a0)+					; EXT: is the Z80 accessing the 68k pointer?
    		bne.s	YM_Access_WaitWrite			; EXT: if so, branch and wait for it to finish...
    		move.b	(a1),(a0)+				; EXT: save lower byte of pointer
    		move.b	-(a1),(a0)				; EXT: save upper byte of pointer
    		StartZ80					; EXT: request Z80 stop off
    
    		rts	
    >> 5. Find routine "loc_72068:", and delete these:

    Code:
    		moveq	#$FFFFFFFF,d2				; MJ: clear PCM finish flag
    Code:
    		addq.b	#$01,d2					; MJ: set PCM finish flag
    		beq.s	SD_NoFM					; MJ: if it hasn't finished yet (not for two turns), branch
    		moveq	#$02,d5					; MJ: set longer delay for FM/PSG channels (DAC has delay now...)
    
    SD_NoFM:
    >> 6. Find routine "loc_72114:", and insert this instruction directly after the label:

    Code:
    		moveq	#$02,d5					; EXT: set PSG to delay for 1 extra frame (This is to match the PSG with the FM/DAC which is delayed a frame by the Z80)
    
    >> 7. Find routine "loc_72228:":

    Code:
    loc_72228:
    		moveq	#0,d3
    		move.b	1(a1),d3
    		move.b	d3,d4
    		bmi.s	loc_72244
    		subq.w	#2,d3
    		lsl.w	#2,d3
    And replace it with:

    Code:
    loc_72228:
    		moveq	#0,d3
    		move.b	1(a1),d3
    		moveq	#$02,d2					; EXT: set PSG to delay for 1 extra frame (This is to match the PSG with the FM/DAC which is delayed a frame by the Z80)
    		move.b	d3,d4
    		bmi.s	loc_72244
    		move.b	#$01,d2					; EXT: set DAC/FM to delay for 0 frames like normal (these have an auto delay of 1 frame in the Z80)
    		subq.w	#2,d3
    		lsl.w	#2,d3
    >> 8. Find "loc_72276:", further down you will find this:

    Code:
    		move.b	#1,$E(a5)
    Replace it with this:

    Code:
    		move.b	d2,$E(a5)				; EXT: moving d2 contents (1 for FM/4 for PSG)
    >> 9. Find "Sound_E4:":

    Code:
    Sound_E4:				; XREF: Sound_ChkValue; Sound_ExIndex; sub_72504
    		moveq	#$2B,d0
    		move.b	#$80,d1
    		jsr	sub_7272E(pc)
    		moveq	#$27,d0
    		moveq	#0,d1
    		jsr	sub_7272E(pc)
    		movea.l	a6,a0
    		move.w	#$EF,d0				; MJ: new size of data to clear
    
    loc_725B6:
    		clr.l	(a0)+
    		dbf	d0,loc_725B6
    
    		move.b	#$80,9(a6)	; set music to $80 (silence)
    		jsr	sub_7256A(pc)
    		bra.w	sub_729B6
    
    ; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||
    
    
    sub_725CA:				; XREF: Sound_ChkValue
    		movea.l	a6,a0
    		move.b	0(a6),d1
    		move.b	$27(a6),d2
    		move.b	$2A(a6),d3
    		move.b	$26(a6),d4
    		move.w	$A(a6),d5
    		move.w	#$93,d0				; MJ: new size
    
    loc_725E4:
    		clr.l	(a0)+
    		dbf	d0,loc_725E4
    
    		move.b	d1,0(a6)
    		move.b	d2,$27(a6)
    		move.b	d3,$2A(a6)
    		move.b	d4,$26(a6)
    		move.w	d5,$A(a6)
    		move.b	#$80,9(a6)
    		jsr	sub_7256A(pc)
    		bra.w	sub_729B6
    ; End of function sub_725CA
    Replace it with this:

    Code:
    Sound_E4:
    		StopZ80
    		lea	(StopSample).l,a0				; EXT: load stop sample address
    		lea	($A00000+PCM1_Sample).l,a1			; EXT: load PCM 1 slot address
    		move.b	(a0)+,(a1)+					; EXT: set address of sample
    		move.b	(a0)+,(a1)+					; EXT: ''
    		move.b	(a0)+,(a1)+					; EXT: ''
    		move.b	#(CUPCM1_NewSample&$FF),($A00000+CU_Stack).l	; EXT: set routine to run
    		move.b	#(CUPCM1_NewSample>>$08),($A00000+CU_Stack+1).l	; EXT: ''
    		move.b	#%11001001,($A00000+CUPCM1_RET).l		; EXT: change "NOP" to "RET"
    		lea	(StopSample).l,a0				; EXT: load stop sample address
    		lea	($A00000+PCM2_Sample).l,a1			; EXT: load PCM 2 slot address
    		move.b	(a0)+,(a1)+					; EXT: ''
    		move.b	(a0)+,(a1)+					; EXT: ''
    		move.b	(a0)+,(a1)+					; EXT: ''
    		move.b	#%00101000,($A00000+CUPCM2_RET).l		; EXT: change "JR NZ" to "JR Z"
    		StartZ80
    
    		moveq	#$2B,d0
    		move.b	#$80,d1
    		jsr	sub_7272E(pc)
    		moveq	#$27,d0
    		moveq	#0,d1
    		jsr	sub_7272E(pc)
    		movea.l	a6,a0
    		move.l	$10(a6),d6					; EXT: store YM Cue list pointer
    		move.w	#$EF,d0						; MJ: new size of data to clear
    
    loc_725B6:
    		clr.l	(a0)+
    		dbf	d0,loc_725B6
    
    		move.l	d6,$10(a6)					; EXT: restore YM Cue list pointer
    		move.b	#$80,9(a6)	; set music to $80 (silence)
    		jsr	sub_7256A(pc)
    		bra.w	sub_729B6
    
    ; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||
    
    
    sub_725CA:				; XREF: Sound_ChkValue
    		movea.l	a6,a0
    		move.b	0(a6),d1
    		move.b	$27(a6),d2
    		move.b	$2A(a6),d3
    		move.b	$26(a6),d4
    		move.w	$A(a6),d5
    		move.l	$10(a6),d6					; EXT: store YM Cue list pointer
    		move.w	#$93,d0						; MJ: new size
    
    loc_725E4:
    		clr.l	(a0)+
    		dbf	d0,loc_725E4
    
    		move.b	d1,0(a6)
    		move.b	d2,$27(a6)
    		move.b	d3,$2A(a6)
    		move.b	d4,$26(a6)
    		move.w	d5,$A(a6)
    		move.l	d6,$10(a6)					; EXT: restore YM Cue list pointer
    		move.b	#$80,9(a6)
    		jsr	sub_7256A(pc)
    		bra.w	sub_729B6
    ; End of function sub_725CA
    >> 10. Find this:

    Code:
    sub_7272E:
    		pea	(a0)					; MJ: store register
    		lea	($A04000).l,a0				; MJ: load YM2612 address port
    		StopZ80						; MJ: request Z80 stop "ON"
    		move.b	d0,(a0)					; MJ: write address
    	rept	$0F
    		nop						; MJ: delay (Tested on MD1 and 2. F nops are required)
    	endr
    		move.b	d1,$01(a0)				; MJ: write data
    	rept	$0F
    		nop						; MJ: delay (Tested on MD1 and 2. F nops are required)
    	endr
    		move.b	#$2A,(a0)				; MJ: write address (set it back to DAC port for the Z80)
    		StartZ80					; MJ: request Z80 stop "OFF"
    		move.l	(sp)+,a0				; MJ: restore register
    		rts						; MJ: return
    
    ; End of function sub_7272E
    
    ; ===========================================================================
    
    loc_7275A:				; XREF: sub_72722
    		move.b	1(a5),d2
    		bclr	#2,d2
    		add.b	d2,d0
    
    ; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||
    
    
    sub_72764:
    		pea	(a0)					; MJ: store register
    		lea	($A04000).l,a0				; MJ: load YM2612 address port
    		StopZ80						; MJ: request Z80 stop "ON"
    		move.b	d0,$02(a0)				; MJ: write address
    	rept	$0F
    		nop						; MJ: delay (Tested on MD1 and 2. F nops are required)
    	endr
    		move.b	d1,$03(a0)				; MJ: write data
    	rept	$0F
    		nop						; MJ: delay (Tested on MD1 and 2. F nops are required)
    	endr
    		move.b	#$2A,(a0)				; MJ: write address (set it back to DAC port for the Z80)
    		StartZ80					; MJ: request Z80 stop "OFF"
    		move.l	(sp)+,a0				; MJ: restore register
    		rts						; MJ: return
    Replace it with:

    Code:
    sub_7272E:
    		movem.l	d2/a0,-(sp)				; EXT: store register data
    		movea.l	$10(a6),a0				; EXT: load Cue pointer
    		addq.w	#$01,a0					; EXT: skip $40
    		move.b	#$00,d2					; EXT: prepare d2 for YM2612 port address ($4000 - $4001)
    		StopZ80						; EXT: request Z80 stop "ON"
    		move.b	d2,(a0)+				; EXT: write YM2612 port address
    		move.b	d1,(a0)+				; EXT: write YM2612 data
    		move.b	d0,(a0)+				; EXT: write YM2612 address
    		StartZ80					; EXT: request Z80 stop "OFF"
    		move.w	a0,d2					; EXT: load Cue pointer
    		andi.w	#$0FFF,d2				; EXT: wrap it
    		ori.w	#$1000,d2				; EXT: ''
    		move.w	d2,$12(a6)				; EXT: update it
    		movem.l	(sp)+,d2/a0				; EXT: restore register data
    		rts						; EXT: return
    
    ; ===========================================================================
    
    loc_7275A:				; XREF: sub_72722
    		move.b	1(a5),d2
    		bclr	#2,d2
    		add.b	d2,d0
    
    ; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||
    
    
    sub_72764:
    		movem.l	d2/a0,-(sp)				; EXT: store register data
    		movea.l	$10(a6),a0				; EXT: load Cue pointer
    		addq.w	#$01,a0					; EXT: skip $40
    		move.b	#$02,d2					; EXT: prepare d2 for YM2612 port address ($4002 - $4003)
    		StopZ80						; EXT: request Z80 stop "ON"
    		move.b	d2,(a0)+				; EXT: write YM2612 port address
    		move.b	d1,(a0)+				; EXT: write YM2612 data
    		move.b	d0,(a0)+				; EXT: write YM2612 address
    		StartZ80					; EXT: request Z80 stop "OFF"
    		move.w	a0,d2					; EXT: load Cue pointer
    		andi.w	#$0FFF,d2				; EXT: wrap it
    		ori.w	#$1000,d2				; EXT: ''
    		move.w	d2,$12(a6)				; EXT: update it
    		movem.l	(sp)+,d2/a0				; EXT: restore register data
    		rts						; EXT: return
    >> 11. Find this:

    Code:
    SoundDriverLoad:
    		lea	(Z80ROM).l,a0				; load Z80 ROM data
    		lea	($A00000).l,a1				; load Z80 RAM space address
    		move.w	#(Z80ROM_End-Z80ROM)-$01,d1		; set repeat times
    		move.w	#$2000,d2				; prepare total Z80 size
    		sub.w	d1,d2					; subtract repeat times from total size
    		subq.w	#$02,d2					; decrease by 2 (for dbf)
    		move.w	#$0100,($A11100).l			; request Z80 stop (ON)
    		move.w	#$0100,($A11200).l			; request Z80 reset (OFF)
    		btst.b	#$00,($A11100).l			; has the Z80 stopped yet?
    		bne.s	*-$08					; if not, branch
    
    SM_LoadZ80:
    		move.b	(a0)+,(a1)+				; dump Z80 data to Z80 space
    		dbf	d1,SM_LoadZ80				; repeat til done
    
    SM_ClearZ80:
    		move.b	d0,(a1)+				; clear remaining Z80 space
    		dbf	d2,SM_ClearZ80				; repeat til done
    		move.w	#$0000,($A11200).l			; request Z80 reset (ON)
    		moveq	#$7F,d1					; set repeat times
    		dbf	d1,*					; there's no way of checking for reset, so a manual delay is necessary
    		move.w	#$0000,($A11100).l			; request Z80 stop (OFF)
    		move.w	#$0100,($A11200).l			; request Z80 reset (OFF)
    		rts						; return
    Replace it with:

    Code:
    SoundDriverLoad:
    		lea	(Z80ROM).l,a0				; load Z80 ROM data
    		lea	($A00000).l,a1				; load Z80 RAM space address
    		move.w	#(Z80ROM_End-Z80ROM)-$01,d1		; set repeat times
    		move.w	#$0100,($A11100).l			; request Z80 stop (ON)
    		move.w	#$0100,($A11200).l			; request Z80 reset (OFF)
    		btst.b	#$00,($A11100).l			; has the Z80 stopped yet?
    		bne.s	*-$08					; if not, branch
    
    SM_LoadZ80:
    		move.b	(a0)+,(a1)+				; dump Z80 data to Z80 space
    		dbf	d1,SM_LoadZ80				; repeat til done
    		lea	(StopSample).l,a0			; load stop/mute sample address
    		lea	($A00000+MuteSample).l,a1		; load Z80 RAM space where the pointer is to be stored
    		move.b	(a0)+,(a1)+				; copy pointer over into Z80
    		move.b	(a0)+,(a1)+				; ''
    		move.b	(a0)+,(a1)+				; ''
    		move.w	#$0000,($A11200).l			; request Z80 reset (ON)
    		moveq	#$7F,d1					; set repeat times
    		dbf	d1,*					; there's no way of checking for reset, so a manual delay is necessary
    		move.w	#$0000,($A11100).l			; request Z80 stop (OFF)
    		move.w	#$0100,($A11200).l			; request Z80 reset (OFF)
    		rts						; return
    >> 12. Find this:

    Code:
    Z80ROM:		incbin	"Dual PCM\Z80.bin"
    		dcz80	SWF_StopSample
    Z80ROM_End:	even
    Replace it with this:

    Code:
    Z80ROM:		incbin	"Dual PCM\Z80.bin"
    Z80ROM_End:	even
    Finished... I'll be updating the first post now.
     
    Last edited: Dec 13, 2016
  7. Novedicus

    Novedicus Well-Known Member Member

    Joined:
    Aug 26, 2013
    Messages:
    857
    "The requested URL /10_DualPCM/Macro.asm was not found on this server."
     
  8. MarkeyJester

    MarkeyJester !%#@ Member

    Joined:
    Jun 27, 2009
    Messages:
    2,660
    Whoops, it was "Macros.asm" not, "Macro.asm". Fixed...
     
    LuigiXHero likes this.
  9. MarkeyJester

    MarkeyJester !%#@ Member

    Joined:
    Jun 27, 2009
    Messages:
    2,660
    Alright ladies and gentlemen, I have some good news for you all!

    I rewrote the Z80 side of Dual PCM in order to support pitch control, this form of pitch control isn't done by delay however since a delay would cause both samples to pitch at the same time. Instead I'm using a mathematical fixed point 16 bit quotient 8 bit dividend to control the pitch of each PCM channel individually, this also means that a specific pitch can be played, any specific pitch that PCM playback can muster. This brought the sample playback down to about 13.000Hz unfortunately...

    However, after rearranging the time in which the samples are fused (doing on playback rather than collection), I was able to increase that sample rate to 14.400Hz. And with suggestions, support and encouragement from Natsumi, as well as a lot of shared ideas, we've managed to get a stable enough build to play back any two samples, any size, at any pitch, including looping sample support, as well as reversal playback. All at a sample rate of 14.400Hz, but with little to no chopping on hardware for that clean and crisp quality.

    http://mrjester.hapisan.com/01_Public/DualPCMPitchTest.mp3

    (I posted this in the music thread.)

    However, I went a step further and wondered how well it'd perform by changing the number of bytes loaded into the buffer vs playback. Dual PCM has always been; "Load 20, Play 10". So after ripping the driver apart, and applying some careful buffer wrapping methods for non-POT (not power of two) sizes, I tried with; "Load 18, Play 10", and this raised the sample rate to 16.500Hz. I then went a step further and tried "Load 14, Play 10", and the sample rate is a nice healthy 18.000Hz playback!

    I've muted FM and PSG playback so you can hear just Dual PCM running (FM and PSG are still running in the background, they in quite mode):

    http://mrjester.hapisan.com/01_Public/DualPCMPitchTest2.mp3

    I haven't tested this on hardware yet, and I suspect there may be a considerable delay, there's also a lot of testing and some clean-up to do, so stay tuned~

    This is so exciting! =D
     
  10. EMK-20218

    EMK-20218 They call me as 'Eduardo Knuckles' Member

    Joined:
    Aug 8, 2008
    Messages:
    953
    Location:
    SEGA Land
    Talking about how the things are being exciting, I'm very excited with the possibility of this new feature. I'm giving usage to this new DAC driver to a hack I'm working on, especially because the feature of having a dual playback of the DAC is one of the things I was most wanting since I started working with SMPS music years ago, and it's now available. I'm really positively stunned with how the features are growing in this new sound engine. I'm really curious to see how will be this DAC feature in practice so that I'll be able to use it.

    SUGGESTION:
    I'm not sure if it'll be good, but I think it would be interesting if there's two tools. One for extract the DAC sequence from any SMPS of Sonic 1 default format. This tool would check where the DAC sequence starts in the source SMPS, so it would check the second PCM channel pointer in the SMPS we want to insert the sequence, so the tool could insert the sequence at the end of the Dual PCM SMPS file. So, the tool adjusts the DAC2 pointer automatically to the sequence inserted. This would ease the work of the insertion of the second DAC sequence in a song for the people who don't want or who don't have patience or knowledge to do it in pure binary.

    The other tool would be a kind of a mod of the MID2SMPS Midi Driver or any kind of similar tool which would reproduce more than one DAC in once in a MIDI as the MIDI driver does, easing the creation of DAC sequences using both of the DAC channels.
     
    MarkeyJester likes this.
  11. MarkeyJester

    MarkeyJester !%#@ Member

    Joined:
    Jun 27, 2009
    Messages:
    2,660
    I wasn't going to deal with external tools for using this driver, I was actually hoping someone else might, but it looks like those people don't care for it right now, which is fair enough.

    I can't do much since I've never used these tools, I've always used a hex editor. But what I can do, is make a tool that'll take the DAC channel out of one music track, and put it into another music track as PCM 2, but that's the best I can do for you. Maybe one day I'll work up the time to make an exclusive music editing tool (I've been wishing for one myself for many years, an SMPS editor of some sort), but my knowledge of operating systems and libraries to use are extremely limited, and every instances I attempt, leads the program to lag, due to a lack of information on the internet as to "properly why".
     
    HackGame likes this.
  12. Crash

    Crash Well-Known Member Member

    Joined:
    Jul 15, 2010
    Messages:
    299
    Location:
    Australia
    mid2smps is open source, but I'm not sure if the midi driver that goes along with it is. I've considered learning how to use Visual Basic 6 in the past so I can make some edits to it for my own purposes, but I never got around to it, and I dunno how well it works with modern Windows versions.
     
  13. MarkeyJester

    MarkeyJester !%#@ Member

    Joined:
    Jun 27, 2009
    Messages:
    2,660
    A small bump (nothing major yet).

    After some heavy drumbling, a lot of nudging and fudging, and some very precise instruction usage, and abusing undocumented quirks, I have managed to do the following so far:
    1. The sample rate playback is currently 20,500Hz and counting (might get it a little higher if you're lucky).
    2. The samples are now stored on the ROM in their native unsigned 8-bit format. The output is still the same, as in, you'll still have a 7-bit sample being played, but 8-bit unsigned is stored on the ROM. So you could in reality just include an unsigned 8-bit sample, without the use of the tool I've written. You just have to make sure that the byte "00" isn't used anywhere in the sample (I'm keeping the tool in of course, just for ease of use for noobs, but still...)
    3. I "might" include some volume control at the expense of some of that sample rate (let me know your opinion on that).
    4. The SMPS structure to DAC channels has changed significantly. Now you select a sample using the F5 flag (F5 XX, where XX is the instrument/sample ID), and you play the note you want from 81 to DF (for pitch/notes).
    5. The FA flag will turn on/off the "reverse playback" mode, use once to turn on, use again to turn off.
    6. The FB flag will turn on/off the "looping" mode, when the sample reaches the end it'll loop back and play again (will be useful for instruments/sounds that play a sound/note forever with no decay).
    7. The E1 and F0 (detune and modulation) flags affect the frequency/pitch of the samples, so you can make it vibrato, or bend or whatever... as well as the E9 flag for pitch changing.
    8. Reduced the wait time on the 68k side by a MASSIVE amount of time.
    All of the above is working with the (still) ability to play any sample, anywhere, any size, anytime, and at near perfect quality on hardware (due to Jester Stream Technology, and the YMCUE Listing System).

    I have a lot of clean up to do, but so long as you're all patient the coming weeks, you'll be thankful of the features and control available to you on release~ Also, I'm open to feature ideas related to the driver itself, if I can support those ideas, I will. But you have to speak up...
     
    Dandaman955, Pacca, ProjectFM and 5 others like this.
  14. nineko

    nineko I am the Holy Cat Member

    Joined:
    Mar 24, 2008
    Messages:
    1,749
    Location:
    italy
    You know, the FA and FB flags are almost enough to cover all the sample looping modes supported in XM files. That said, I wonder if all these new features should warrant a new, improved version of xm3smps, which could still convert a certain number of melodic channels in the traditional way, but could also convert two XM channels to your dual PCM channels (while also exporting the used samples, if needed). If anything, I'm not sure if that's something I want to do in the days of mid2smps, though. I feel less and less people are working with XM files these days, even though what you're doing with your driver, ironically, is really akin to what modules do...

    Also yeah, awesome work, et al.
     
    EMK-20218, Natsumi, jubbalub and 2 others like this.
  15. ProjectFM

    ProjectFM Optimistic and self-dependent Member

    Joined:
    Oct 4, 2014
    Messages:
    733
    Location:
    Portland, Maine
    I actually only switched to mid2smps from xm3smps because it was the more popular option and I believe it can support more coordination flags such as pitch slides. I'd be completely on board with an updated version of xm3smps, hopefully one with some of the additional features of oerg's version. People used to working with midi only have the additional steps of converting the file to XM (loading it in ModPlugTracker and saving it) and setting the loop point (which is a pain in the butt using midi so this would save time).

    I don't know if this is in the original version, but oerg's version crashes sometimes. One example I remember is when loading a save state. I haven't used xm3smps so I don't remember the exact details. I know this is off topic, but if you do update xm3smps, you should try fixing this.
     
  16. Cinossu

    Cinossu A blend of secret herbs and spices Member

    Joined:
    Aug 14, 2007
    Messages:
    274
    Location:
    London, UK
    Some optional volume control at the expense of sound rate would be a good possibility to have; I know it's always been something I've wanted for the DAC channel. So that gets my vote!

    You've done absolute amazing work with this so far. Very much looking forward to these latest changes.
     
    Natsumi and MarkeyJester like this.
  17. MarkeyJester

    MarkeyJester !%#@ Member

    Joined:
    Jun 27, 2009
    Messages:
    2,660
    Speaking of volume control, I've been looking into it, and I may be able to give you all $80 grades of volume control. Not only that, the method I'm testing and investing in, might also allow for some filtering effects of some kind, but we'll see~

    I'll quote you all with a sample rate once I've found the most optimal way I can, looks like it might be quite expensive, I blame the lack of available registers myself d=

    EDIT: Just tested, looks like you'll get 17,000Hz, I'll try to push for 18,000Hz if I can though...
     
    Last edited: Mar 31, 2017
    Natsumi, FохConED and ProjectFM like this.
  18. Cinossu

    Cinossu A blend of secret herbs and spices Member

    Joined:
    Aug 14, 2007
    Messages:
    274
    Location:
    London, UK
    Out of curiosity, how expensive would it be to be able to switch off something like that by a flag of some sort? So you could have some times with better sample rate but at the sacrifice of no volume control at the time, but at the times you do want it you have to deal with the lower sample rate instead.
     
  19. EMK-20218

    EMK-20218 They call me as 'Eduardo Knuckles' Member

    Joined:
    Aug 8, 2008
    Messages:
    953
    Location:
    SEGA Land
    Supposing this new version coming true, would be there any possibility of keeping the same "/oerg" additions along with proper 32X support and valleybell's SMPS playback and/or tempo calculator?
     
  20. nineko

    nineko I am the Holy Cat Member

    Joined:
    Mar 24, 2008
    Messages:
    1,749
    Location:
    italy
    1. no
    2. there is a private fork of xm3smps which can target the 32X
    3. no
    4. this could have been a yes, but no

    5. all of this is off topic, please no more posts about xm3smps, I apologise to Markey Otterboi for this derail