It is currently Sun Apr 30, 2017 11:18 pm

All times are UTC - 7 hours



Forum rules


Related:



Post new topic Reply to topic  [ 43 posts ]  Go to page Previous  1, 2, 3
Author Message
 Post subject: Re: Sound driver fun
PostPosted: Tue Dec 22, 2015 2:26 pm 
Offline

Joined: Sat Jul 26, 2014 9:50 am
Posts: 48
KungFuFurby wrote:
Your SNESMod has a bug that I had fixed (and got incorporated into an actual updated version of SNESMod)...

The bug that occurs has to do with loading sound effects. It happens when loop points go bad and cause the carry flag to accidentally get set, resulting in the sample pointers to be out of alignment by one byte.


I've added this fix. I haven't updated the windows binary yet and I was hoping to get the increase in patterns, instruments and samples working in this latest update. Maybe next time. I did add your bugfix for ultra low pitch. Thanks for that!


Top
 Profile  
 
 Post subject: Re: Sound driver fun
PostPosted: Wed Dec 30, 2015 3:10 pm 
Offline

Joined: Sat Jul 26, 2014 9:50 am
Posts: 48
To save space I think I'll have the vibrato waveform set the tremolo and panbrello waveform as well. I've attached a short tremolo demo to the first post.


Top
 Profile  
 
 Post subject: Re: Sound driver fun
PostPosted: Wed Dec 30, 2015 4:17 pm 
Offline

Joined: Wed Jul 09, 2008 8:46 pm
Posts: 232
The negative octave handling code is not present in snesmod-1.2.asm. In addition, I added a clrc opcode just past asl a in oct_cont so that negative octaves don't mess anything else up.


Top
 Profile  
 
 Post subject: Re: Sound driver fun
PostPosted: Wed Dec 30, 2015 5:38 pm 
Offline

Joined: Sat Jul 26, 2014 9:50 am
Posts: 48
Yeah, I was a bit sloppy there... the full fix was only in one of the drivers. They're all updated now.


Top
 Profile  
 
 Post subject: Re: Sound driver fun
PostPosted: Wed Dec 30, 2015 10:10 pm 
Offline

Joined: Tue Apr 24, 2012 12:22 pm
Posts: 53
Well, have a 404 not found when I try to download your updated version Augustus Blackheart... :(


Top
 Profile  
 
 Post subject: Re: Sound driver fun
PostPosted: Thu Dec 31, 2015 5:25 am 
Offline

Joined: Wed Jul 09, 2008 8:46 pm
Posts: 232
alekmaul wrote:
Well, have a 404 not found when I try to download your updated version Augustus Blackheart... :(


I cheated by replacing a 22 with a 30, realizing that the URL looked wrong since usually it indicated when the file was last updated.


Top
 Profile  
 
 Post subject: Re: Sound driver fun
PostPosted: Thu Dec 31, 2015 12:02 pm 
Offline

Joined: Sat Jul 26, 2014 9:50 am
Posts: 48
Today's update has reduced redundancy in the vibrato routine from the ABNOFX driver applied to all of the sound drivers. I'm rewriting how the special features use zeropage. After I make sure all those routine are working properly under the new system I'll be adding tremolo, panbrello, noise frequency sweeps, and possibly swing tempo if I have time. Then I'll rewrite the filter sweep routine. Next up should be... phase inversion and pitch modulation to modify direct gain.


Top
 Profile  
 
 Post subject: Re: Sound driver fun
PostPosted: Mon Jan 04, 2016 10:48 am 
Offline

Joined: Wed Jul 09, 2008 8:46 pm
Posts: 232
There are a couple of thoughts coming through my mind in regard to envelopes...

- There is a bug in regard to a note on with a delay freezing the previous instrument's envelope (this existed in the original version as well prior to your modifications).

- Perhaps there should be a "psuedo-gain" method of adjusting the gain on a per-step basis during SNESMod's idle loop (when the driver checks for commands and any ticks) for each of the channels rather than doing so instantly to reduce crackle. Obviously the rate won't be consistent this way, but one thing I do know is that direct gain has double precision of any attack-related gain/ADSR modes (except for bent gain, but only when loud enough). The psuedo-gain can also be applied to the panning, which has no such controls.

You don't need to implement this next part, but I have an extra piece of theory to apply to gain (especially if direct gain gives this a zero where in reality the value is less than a one, but not a zero):

- Exponential decrease can pull off volume levels that direct gain can't touch due to precision. The side effect of pulling this off is that it is prone to hiccups when the volume is increased since there is up to 15 sample's worth of delay in there after setup (especially if we're going all the way down to the lowest possible volume value gain can ever do, which is a sixteenth of what direct gain can pull off for an extreme low). This is because direct gain goes first and is set to 01.

I also have a bugfix in regards to surround failing to be disabled when the volume column uses a panning command:

Code:
;--------------------------------------------------------
; 128-192 set pan
;--------------------------------------------------------
vcmd_pan:
   cmp   mod_tick, #0      ; set panning
   bne   exit_vcmd      ;
   push   a         ;
   mov   a, y         ;
   sbc   a, #128         ;
   mov   ch_panning+x, a      ;
   mov   a, ch_flags+x      ; Bugfix by KungFuFurby 12/20/15
   and   a, #~CF_SURROUND   ; Surround should be disabled
   mov   ch_flags+x, a      ; when panning is set via volume
   pop   a         ; column.
   ret            ;


Top
 Profile  
 
 Post subject: Re: Sound driver fun
PostPosted: Thu Jan 07, 2016 6:27 pm 
Offline

Joined: Sat Jul 26, 2014 9:50 am
Posts: 48
KungFuFurby wrote:
- Perhaps there should be a "psuedo-gain" method of adjusting the gain on a per-step basis during SNESMod's idle loop (when the driver checks for commands and any ticks) for each of the channels rather than doing so instantly to reduce crackle. Obviously the rate won't be consistent this way, but one thing I do know is that direct gain has double precision of any attack-related gain/ADSR modes (except for bent gain, but only when loud enough). The psuedo-gain can also be applied to the panning, which has no such controls.

You don't need to implement this next part, but I have an extra piece of theory to apply to gain (especially if direct gain gives this a zero where in reality the value is less than a one, but not a zero):

- Exponential decrease can pull off volume levels that direct gain can't touch due to precision. The side effect of pulling this off is that it is prone to hiccups when the volume is increased since there is up to 15 sample's worth of delay in there after setup (especially if we're going all the way down to the lowest possible volume value gain can ever do, which is a sixteenth of what direct gain can pull off for an extreme low). This is because direct gain goes first and is set to 01.


Anything that reduces crackle is great. I'll have to try it out.

Quote:
I also have a bugfix in regards to surround failing to be disabled when the volume column uses a panning command:


Nice. I have it call the duplicate code from within Command_SetPanning which conviently ends with ret.

Awhile back I changed the default master volume to be much higher and as such, in my own version of the driver, I got rid of the Echo Volume scaled by Master Volume routine. Do you think it's worth keeping that as an option in Super SNESMod? It might be useful is someone is manually setting the master volume lower, however, it takes up a lot of space... although I don't know why people couldn't just use different echo values if it's a concern.


Top
 Profile  
 
 Post subject: Re: Sound driver fun
PostPosted: Fri Jan 08, 2016 9:36 am 
Offline

Joined: Wed Jul 09, 2008 8:46 pm
Posts: 232
Augustus Blackheart wrote:
Awhile back I changed the default master volume to be much higher and as such, in my own version of the driver, I got rid of the Echo Volume scaled by Master Volume routine. Do you think it's worth keeping that as an option in Super SNESMod? It might be useful is someone is manually setting the master volume lower, however, it takes up a lot of space... although I don't know why people couldn't just use different echo values if it's a concern.


I actually have something running through my head that might allow you to cut any effects that end up on the chopping block in the actual IT file (and also allows you to circumnavigate the assembler, not counting constant memory locations). Every single IT file must be scanned in the scenario of a soundbank though (or the user will have to manually define which ones to cut and/or keep... where all of them are on by default).

This is a lovely little file format that I have invented that allows you to pull off relocatable SPC700 code on the SNES (and in your C++ code if you want to make some adjustments) while minding constant memory locations (as defined by the assembler):

SPC700 Portable Code Format
Allows you to make relocatable modules of SPC700 code.
Works for blocks of code up to 32,767 bytes in length (unless you want to bend the rules and define where constant memory locations begin).

Most likely SNES implementation is to construct the code in WRAM, then send it to the SPC700. In theory it can also be done on the fly

It is highly recommended to have a master pointer array on hand for the SPC700, as this format works best with re-loadable "modules" (think of a collection of note effects, for example).

Header is the following:
(For standard variety, which has a 32,767 byte limit)
- 15-bit filesize (in SNES bytes, not SPC700 bytes) + 1 bit flag (flag indicates whether or not there are extra details within the code to either modify or handle in a non-standard method)
(For non-standard variety, which requires that you define a constant indicating where constant memory locations end... this is not put in the actual SPC700 file, and is instead usually hard-coded on the SNES's end)
- 2 byte filesize (in SNES bytes, not SPC700 bytes)
- 1 byte flag containing the following bits...
-- (Bit 7) Whether or not the counters are 16-bit.
-- (Bits 6-5 are not defined yet.)
-- (Bit 4) Whether or not there are non-constant values not auto-detected by the code as two-byte pointer offsets
-- (Bit 3) Whether or not there are non-constant values not auto-detected by the code as scattered bytes
-- (Bit 2) Whether or not there are SLEEP opcodes that should be sent to the SPC700
-- (Bit 1) Whether or not there are STOP opcodes that should be sent to the SPC700
-- (Bit 0) Whether or not there are a series of two-byte pointers

The one-byte flag is also there in the standard variety, but it is optional since the one-bit flag will indicate whether or not this flag exists.

The filesize can be omitted, but in substitution for there being no filesize, the file must be ended with a STOP SPC700 opcode. In these scenarios, the one-byte flag is required.

When flag bits are set to account for non-auto-detected opcodes, then extra collections of data will show up after the flag byte.

Each collection contains a counter for the number of pointers to deal with. Counters are 8-bit by default, but they can be set to 16 bits by setting the highest bit for the flag (highly doubtful unless you somehow use more than 256 pointers in one set).

These extra data shall show up when the corresponding bit is set...
- (Bit 4) Two-byte pointers to SPC700 RAM offsets
- (Bit 3) Four-byte pointers to SPC700 RAM offsets (two bytes per pointer to a byte in the order of low byte, followed by high byte)
- (Bit 2) Two-byte pointers to SLEEP opcodes that should not be skipped (this directly affects SPC700 RAM offsets)
- (Bit 1) Two-byte pointers to STOP opcodes that should not be skipped
- (Bit 0) Four-byte pointers to a collection of SPC700 RAM offsets (two bytes indicate the start point, and two bytes indicate the end point)

All opcodes with !a parameters (including indexed parameters) are defined as following...
- Positive values indicate a constant memory location
- Negative values (which in this case means the sign bit is set) indicate an offset from the starting memory location of the code (these values are EORed by $FFFF when sent to the SPC700... meaning $FFFF stands for a zero offset). These offsets are NOT relative to the start of the file on the SNES, as bytes can be skipped and modified.

A SLEEP opcode (which normally should not be executed on the SPC700) does not get sent to the SPC700, and instead marks the beginning of non-SPC700 code. Following the SLEEP opcode is a two-byte filesize indicating how many bytes are not SPC700 code.

A STOP opcode marks the end of the file, and also does not get sent to the SPC700.


This might work well for SNESMod in particular (and it also cuts down on the number of copies of code you have to maintain in the process).


Top
 Profile  
 
 Post subject: Re: Sound driver fun
PostPosted: Thu Apr 14, 2016 7:16 pm 
Offline

Joined: Sat Jul 26, 2014 9:50 am
Posts: 48
KungFuFurby wrote:
I actually have something running through my head that might allow you to cut any effects that end up on the chopping block in the actual IT file (and also allows you to circumnavigate the assembler, not counting constant memory locations). Every single IT file must be scanned in the scenario of a soundbank though (or the user will have to manually define which ones to cut and/or keep... where all of them are on by default).


That would be a much better way of doing things. Speaking of cutting down on multiple versions...

There are a lot of silly errors in that last version of SNESMod. Update coming soon.


Top
 Profile  
 
 Post subject: Re: Sound driver fun
PostPosted: Fri Jan 13, 2017 2:14 pm 
Offline

Joined: Sat Jul 26, 2014 9:50 am
Posts: 48
I have two different issues I can't seem to figure out:

Issue 1:

I have a version of SNESMod that never pushes anything to the stack (except calls of course but it's not like there are a ton of nested calls). In this driver I put 144 bytes of sample data starting at 0100h. This works fine for most of my songs but there are a couple where it is fine for half of the song and than at a certain point something occurs and the stack stops hovering around 235-237 and keeps dropping very rapidly wiping out the 144 bytes at 0100h, continuing to decrease and wraparound endlessly. Other than losing that sample data, the song continues to play fine.

Although I only know the value of the stack register with the SPC player, the samples at 0100h do get destroyed in every emulator I've tried and on real hardware. Other songs tested did not have this issue. Any thoughts on what would cause this to occur? Everything else about the song plays perfectly fine so if it's some sort of bug it is only specific to whatever is going on with the stack. (I've been looking over song data but there was nothing especially noteworthy about this song it uses all of the same commands as other songs I've tested use.)

Anyway, it's not the biggest deal, but it would be nice to save some bytes for module data. In the mean time I've gone back to storing that particular sample data outside of stack space. Maybe this is something that is not possible to do...

Issue 2:

I set up a system to swap out 144 bytes (8 32 sample BRR) in SNESMod. This is stored outside of stack space. It works. Kind of. Here is the test I ran:

1: load sample
2: play module
3: change sample data
4: jump to previous pattern
repeat 3-4

The first two transfers always work, the third is unsuccessful, the fourth transfer works, and after that only the 2nd and 4th transfers are successful. When a transfer is unsuccessful, the result is either a short burst of noise or what sounds like a low pitch sine-ish waveform.

Ideally, I would like to be able to change samples at any time that a song is playing. I'm not sure what the proper way to do this is. If anybody has suggestions for what I should (or shouldn't) be doing that would be helpful. I thought about modifying the SPC streaming code from SNESMod for this task if I can't get it to work using this code, but I'd like to understand why this method isn't working consistently.

code on the SNES side:
Code:
; increment memory pointer by 2
.macro incptr
.scope
   iny
   iny
   
   bne   _catch_overflow
   inc   spc_ptr+2

_catch_overflow:
.endscope
.endmacro

;----------------------------------------------------------------------
spcLoadSample:         ; y = sample address
;----------------------------------------------------------------------

   phx
   jsr   spcFlush   ; flush fifo!
   plx

   sty   z:spc_ptr
   lda   sample_bank
   sta   z:spc_ptr+2
   
   lda   z:spc_v      ; wait for spc
   pha
:   cmp   REG_APUIO1
   bne   :-
   lda   #CMD_SAMPLE   ; send SAMPLE message
   sta   REG_APUIO0
   pla
   eor   #80h
   ora   #01h
   sta   z:spc_v
   sta   REG_APUIO1
:   cmp   REG_APUIO1   ; wait for spc
   bne   :-

   ldx   #144/2   ; x = word length
   ldy   #0      ; y = index
   jsr   do_transfer
   rts
   
;--------------------------------------------------------------
; spc_ptr+y: source address
; x = length of transfer (WORDS)
;--------------------------------------------------------------
transfer_again:
   eor   #80h
   sta   REG_APUIO1
   sta   spc_v
   incptr
:   cmp   REG_APUIO1
   bne   :-
;--------------------------------------------------------------
do_transfer:
;--------------------------------------------------------------
   rep   #20h      ; transfer 1 word
   lda   [spc_ptr], y
   sta   REG_APUIO2
   sep   #20h
   lda   spc_v
   dex
   bne   transfer_again
   
   incptr

end_transfer:
   lda   #0   ; final word was transferred
   sta   REG_APUIO1   ; write p1=0 to terminate
   sta   spc_v
:   cmp   REG_APUIO1
   bne   :-
   sta   spc_pr+1
   rts

code on the SPC-700 side:
Code:
;-------------------------------------------------------------------
CopySample:
;-------------------------------------------------------------------
   mov   xfer_address, #Sample01&0ffh
   mov   xfer_address+1, #Sample01>>8
   call   StartTransfer
   mov   SPC_PORT1, comms_v
   ret
;-------------------------------------------------------------------
StartTransfer:
;-------------------------------------------------------------------
   mov   x, comms_v      ; start transfer
   mov   y, #0
   mov   SPC_PORT1, x
;-------------------------------------------------------------------
DoTransfer:
;-------------------------------------------------------------------
   cmp   x, SPC_PORT1      ; wait for data
   beq   DoTransfer
   mov   x, SPC_PORT1

   mov   a, SPC_PORT2      ; copy data
   mov   [xfer_address]+y, a
   mov   a, SPC_PORT3
   mov   SPC_PORT1, x      ;<- reply to snes
   inc   y
   mov   [xfer_address]+y, a
   inc   y
   beq   _inc_address      ; catch index overflow
_cont1:   cmp   x, #0         ; loop until x=0
   bne   DoTransfer

   mov   m0, y
   clrc
   adc   xfer_address, m0
   adc   xfer_address+1, #0
   mov   comms_v, x
   ret

_inc_address:
   inc   xfer_address+1
   bra   _cont1


Top
 Profile  
 
 Post subject: Re: Sound driver fun
PostPosted: Fri Jan 13, 2017 2:31 pm 
Offline

Joined: Sat Apr 25, 2015 1:47 pm
Posts: 262
Location: FL
I have something of a working SPC debugger/tracer, if you'd like me to figure out what's going on with the first issue.

I don't have any ideas right off the bat regarding the second one, but I can take a closer look at the code later and see if anything seems suspect.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 43 posts ]  Go to page Previous  1, 2, 3

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group