Sound driver fun

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Sound driver fun
by on (#151992)
What's new:
Added driver "Celes" which has a version of psychopathicteen's fm code, whichever old version was posted here. This song (mp3|spc) uses an earlier version of the driver.

Celes repurposes IT commands for other features. I really should get around to adding SPC playback into schismtracker.
Current smconv :: all source with Celes, Pitchmod, SNESMod, and Super SNESMod NoFX drivers. (updated December 2017:: no Windows binary yet.)

11 songs
Re: Sound driver fun
by on (#152023)
Filesize-wise, I kept everything below 5632 bytes. Anything bigger, and you're forced to modify the SNESMod compiler application and the source code to deal with the change (I stopped just 10 bytes short of having to do this)... and for me, I wanted to just simply implant the code using a hex editor.

The glitch that I mentioned deals with noise generation and SFX (pitch modulation might technically count, too).

I really don't like the idea of overwriting existing IT tracker effects (that makes things worse for me to test when composing in Schism Tracker, as I have no way to disable those effects, which means my pre-conversion testing can seriously get hampered). I prefer either unused effects in Impulse Tracker (either that, or I prefer implementing the original effects)... I did S0x-S3x for that reason, and I did S9x, too.

I actually had the following ideas for extra features (from 2013, actually), but I stopped short because I would have to modify the compiler source code to reallocate the module files due to memory consumption (and some of these are brand new, literally conjured up right on cue):

S94 ~ Turn on phase inversion for one channel (Volume = Volume - 1 EOR FF)
S95 ~ Turn off phase inversion for one channel
S96 ~ Turn on phase inversion for all channels
S97 ~ Turn off phase inversion for all channels
S98 ~ Set Zxx Mode to Direct Gain
S99 ~ Set Zxx Mode to FIR Filter Coefficients
S9A ~ Set Zxx Mode to Master Volume
S9B ~ Set Zxx Mode to Echo Volume (this one's new... and it's supposed to be a substitute for overwriting an Impulse Tracker effect)
S9C ~ Set Zxx Mode to Echo Feedback (this one's new... and it's supposed to be a substitute for overwriting an Impulse Tracker effect)
S9D ~ Set Zxx Mode to Echo Delay/Special (this one's new... and it's supposed to be a substitute for overwriting an Impulse Tracker effect)
S9E~ Set pitch modulation control to Modify Direct Gain (Direct Gain = Originally Intended Volume, and Volume = 7Fh)
S9F~ Set pitch modulation control to Do Not Modify Direct Gain (Direct Gain = 7Fh)

Zxx ~ Set Parameter
If Zxx Mode is set to Direct Gain, then the corresponding channel's direct gain will be modified as such. This can become a Custom Gain if the value is above 7F. Unfortunately gain is not tempo-sensitive... and it doesn't care about volume.
If Zxx Mode is FIR Filter Coefficients than the corresponding channel will modify the corresponding coefficient (either that, or an alternative implementation is that you could link to an array that contains a list of FIR coefficent parameters, provided by the song message... but please don't go out of bounds if this implementation is selected).
If Zxx Mode is Echo Volume, then odd channels modify left echo volume, and even channels modify right echo volume.
If Zxx Mode is Echo Delay/Special, then...
- 00h restores all parameters to original settings
- 01h-0Fh sets the delay (but only up to the original value specified in the module... if you want to go further, then set your default rate higher.)
- 10h resets the FIR coefficients to the module's default settings
- 11h resets the echo volume to the module's default settings
- 12h resets the echo feedback to the module's default settings
- 13h disables echo writes. This essentially means your echo buffer plays nothing but looped audio.
- 14h re-enables echo writes.
- I haven't decided on 15-FF yet.

Warning: You must set the Zxx mode first, or else you'll get an undefined effect.
Warning 2: Echo delay has a semi-delayed effect on the song due to the way the hardware processes the echo.
Re: Sound driver fun
by on (#152033)
That's a great point about IT tracker effects, I never had to think about that before because I use an XM tracker. That should definately be changed.
Re: Sound driver fun
by on (#152089)
I've got the sample directory starting at 0100h and the program at 0300h for the extended pitchmod spc program. I've changed it2spc.cpp and include/snesmod.asm to reflect this change*. Everything works fine in ROM and as an SPC file. Is there any reason why 0100h-01ffh shouldn't be used?

One of the things that I've never gotten around to, but have been meaning to work on, is adding a command line option to SMCONV to select between the various spc programs. So, that's something I'll add soon.

*The original SNESMOD and Pitchmod spc programs are still using the orginal addresses.
Re: Sound driver fun
by on (#152098)
Augustus Blackheart wrote:
I've got the sample directory starting at 0100h [...] Is there any reason why 0100h-01ffh shouldn't be used?

Stack pointer starts at $01EF and grows down. Too many nested subroutine calls will blow up your sample directory.
Re: Sound driver fun
by on (#152173)
tepples wrote:
Stack pointer starts at $01EF and grows down. Too many nested subroutine calls will blow up your sample directory.


D'oh! I probably should have read a doument on the SPC or something. I figured that it was programmed that way for a reason. Everything has been put back in it's proper place.

KungFuFurby, what about using S0D, S0E, S0F to reset delay, echo and feedback to the default settings. S00 could possibly reset delay, echo and feedback, or reset the FIR coefficients.

It's up to 5679 bytes right now but I haven't implemented the following yet: phase inversion, direct gain Zxx mode, FIR coefficients Zxx mode, pitch modulation control to modify/not modify direct gain, disable echo writes, and enable echo writes. Zxx mode echo volume sets the actual echo level right now and doesn't have odd channels modify left echo volume, and even channels modify right echo volume.
Re: Sound driver fun
by on (#152799)
Quote:
S0D ~ reset echo delay (alternately, this could be disable echo writes)
S0E ~ reset echo volume (alternately, this could be enable echo writes)
S0F ~ reset echo feedback


I'll accept these changes and move Z13-Z14 to Z11-Z12 since now there's nothing there.

May as well call this big featureset "Super SNESMod" for what it's doing right now.

As of your current version (0.4)...

- Master volume can go past 7Fh... but they'll all be negative values. You can omit the check to save some bytes... just make sure to indicate that you'll get negative volume values if you go past that value.

- I actually wanted to have echo volume be applied without scaling via the master volume (Zxx can help with that by enabling and disabling the scaling). I have a special effect that I could use that involves fooling around with FIR coefficients, setting the EDL as low as possible for smooth transitions, zeroing out the feedback and master volume (without zeroing out the echo volume)... and you'll get filtering on the entire sound output.

- MODULE can be a dynamically changing variable that can also be not divisible by $100. Simply pre-compile the SPC700 source code (with MODULE being essentially a pointer to the end of the current source code... I think that converts OK for TASM), and have SMCONV make its pointers based off of which version you choose.

The following are bugs/concerns from the original SNESMod:

- Fast linear increase is never executed due to multiplication limitations. Volume only ever gets to 7E rather than 7F. This is because of a series of three multiplication operations, none of them skipped, that turns FF into FD, which in turn results in the rather unusual maximum.

- Envelope processing is improperly handled with note delays: they are not delayed with the note, and the previous envelope appears to get frozen in their tracks.

- Envelopes are reset with note slides regardless of whether they finished or not. That's not natural tracker behavior if I remember correctly... I did take advantage of this bug once, though, but I prefer mine not reset.

- The tempo change command can accidentally cause the first tick to come around much later than expected. Most commonly, this is because it's not in the first channel, at least when I noticed it.

- Why is tempo limited to 200? I understand why a lower limit of 80 is mandatory, but tempo can go all the way up to 255, and the timer is able to go that fast.

- Tempo ticks need to be recalibrated. SNESMod's timing, compared to Schism Tracker, is off by (current tempo - 3). This is best indicated when using samples that are timing sensitive to go smoothly, drumbeat samples in particular.

- Ultra low pitches produce glitched values instead of actual low value. Yes, I was crazy enough to go that low with the pitch.

The following are bugs of my original modifications:

- Noise and pitch modulation are not safe with SFX. Echo is in the same boat, but it is not as serious.

Your current version concerns me in the following fashion:

- The way your Zxx code is executed looks quite fatal to SNESMod's standard. That's because the X register is reserved for the channel ID. I would recommend saving the accumulator in m0 (which is fully open in this case), get the parameter mode, then

Also, where did your smconv and snesmod_dev.asm files go? They were here previously...
Re: Sound driver fun
by on (#153198)
KungFuFurby wrote:
As of your current version (0.4)...

- Master volume can go past 7Fh... but they'll all be negative values. You can omit the check to save some bytes... just make sure to indicate that you'll get negative volume values if you go past that value.

...

Your current version concerns me in the following fashion:

- The way your Zxx code is executed looks quite fatal to SNESMod's standard. That's because the X register is reserved for the channel ID. I would recommend saving the accumulator in m0 (which is fully open in this case), get the parameter mode, then


Thanks, I didn't get all the changes from my other version into this one. I've updated it now.

Quote:
Also, where did your smconv and snesmod_dev.asm files go? They were here previously...


I'll add new versions to the first post as soon as I test the latest code. I've only tested the version which uses unimplemented impulse tracker commands for setting all of these features.
Re: Sound driver fun
by on (#155119)
I've added a version with all sfx streaming code removed.

Also, what would be a good option for commands to handle filter sweeps?

I could use z01-05 (which would require an additional S9x command to enable this mode) for different types of filter sweeps and values higher than that could set the delay between each change. I would also need a way to avoid overflows. I've done this so far by hardcoding the values and adding addtional delays for some of the coefficients.

I'm starting to run out of commands to use. What about repurposing the Tremor command. Does anybody actually use that?

Anyway, for anybody who is interested I made my tracker have an SNESMOD option so if I'm tracking for the SNES it shows me what the commands do and when enabled the tracker ignores SNESMOD specific commands on playback. This lets me use way more commands (at the expense of compatibility should I want to use the mod for some other purpose; then again there are already issues when pitch modultion is used).

I suppose at this point I should add spc700 emulation to the tracker.
Re: Sound driver fun
by on (#155122)
I think I've used the tremor command once or twice years ago, but I forget in which song. Or maybe it was retrigger.
Re: Sound driver fun
by on (#155153)
Looked at the asm file and I can't read it because there's no spaces. Everything is on big wall of text.
Re: Sound driver fun
by on (#155156)
psycopathicteen wrote:
Looked at the asm file and I can't read it because there's no spaces. Everything is on big wall of text.

LF newlines. Don't open it in notepad, it won't work, it will only interpret CR-LF as a new line.
Re: Sound driver fun
by on (#155159)
DoNotWant wrote:
psycopathicteen wrote:
Looked at the asm file and I can't read it because there's no spaces. Everything is on big wall of text.

LF newlines. Don't open it in notepad, it won't work, it will only interpret CR-LF as a new line.



It is ridiculous that it is 2015 and notepad still doesn't know what to do with LF newlines, something so completely trivial to implement. I suppose Microsoft is too busy removing or hiding features people have used for years or forcing them to download adware begging them to update to Windows 10 and/or forcing them to download Windows 10 rather than doing anything useful or worthwhile.

I think many people replace notepad with notepad++, notepad2, or textpad.
Re: Sound driver fun
by on (#155163)
Some of my older psuedo-SNES songs actually use Ixy (normally I improvise with volume envelopes, but it would be neat to see that actually get implemented).
Re: Sound driver fun
by on (#155164)
For use as a programmers' text editor, Microsoft did update Notepad. It's called Visual Studio Code.

I'd like to see a tutorial on how to best set up Notepad++ or your other favorite Windows text editor.
Re: Sound driver fun
by on (#155165)
Wordpad.exe can handle both types of newlines.
Re: Sound driver fun
by on (#155168)
tepples wrote:
For use as a programmers' text editor, Microsoft did update Notepad. It's called Visual Studio Code.

I'd like to see a tutorial on how to best set up Notepad++ or your other favorite Windows text editor.


I still think since Notepad is the default text editor that it should know what to do with LF.

Thankfully, I haven't had to use Windows in awhile, but I will be forced to in a couple of months. I already know I'll be annoyed by how changing the colors used for the GUI doesn't fully apply to each and every application.

I'll let you know what I end up using for text editing.

KungFuFurby wrote:
Some of my older psuedo-SNES songs actually use Ixy (normally I improvise with volume envelopes, but it would be neat to see that actually get implemented).


I'd be interested in hearing any songs which use this command.
Re: Sound driver fun
by on (#155325)
How do you get an .spc file to actually play in a game?
Re: Sound driver fun
by on (#156099)
psycopathicteen wrote:
How do you get an .spc file to actually play in a game?


The necessary files are in smconv which is linked to in the first post.
Re: Sound driver fun
by on (#156101)
Is anyone interested in having the following added to SNESMod?
Code:
S9? ~ zmode filter sweep evol/delay
      > default EVOL < 80h: set evol_max [default 40h]
      80h: Turn off EVOL sweep
      81h-0ffh: Set delay between filter changes (-80h)
S9? ~ zmode noise freq/min filter sweep evol
      00-1eh: Set minimum noise freq during noise freq sweep
      1f: set Noise freq sweep mode to single decrease [default]
      20: set Noise freq sweep mode to ping pong
      21h-7ch: Set minimum band pass DSP_C0 [default 34h]
      80h-ffh: Set minimum echo volume for filter sweeps (-80h) [default 20h]
S9? ~ zmode filter sweep
      00: Disable filter sweep
      01: Sweep to bandpass filter one shot
      02: Sweep to bandpass filter ping pong
      03: Sweep to lowpass filter one shot
      04: Sweep from bandpass filter one shot
      05: Sweep from bandpass filter ping pong
      06-ffh: Delay before changing filter coefficients [default 80h]

* no noise freq sweep increase (yet)
* noise freq sweep values currently use S5x command
* need to find other ways set these values that don't conflict with exisiting .it commands (maybe something like S4[3-f] also sets parameters)
* negative values for filter sweep echo volume not supported.
* I didn't spend anytime thinking about how to set this up, I just did the first thing I thought of, so maybe there's a better way to handle the coefficent changes that would allow for more options while still avoiding overflows.

I also have a command (currently sacrificing the ability to set the master volume with negative values) which decreases the master volume while increasing the echo volume (old mvol value becomes vol value and minimum mvol value can be 0-7eh)

Bug wise the tempo and envelope processing for note delays are fixed.

Anyway, mostly wanted to see if adding any of this would be useful for anybody before moving on to smconv and adding in any other features.
Re: Sound driver fun
by on (#159068)
I updated the first post with a link to the latest smconv, drivers and examples.
Re: Sound driver fun
by on (#159715)
Whoops, SPC creation is broken for SuperSNESMod under some circumstances (I haven't done enough testing yet to determine why it's happening). With a couple of songs I've managed to crash SPCTool2 and OpenSPCLite. AudioOverload doesn't crash but bad things happen soundwise. Other songs work fine so I'm assuming it's some specific command that's causing issues. Soundbanks work fine.
Re: Sound driver fun
by on (#159750)
How are you doing filter sweeps?
Re: Sound driver fun
by on (#159753)
Actually, it appears the SPC file itself is fine as putting it into a ROM causes no issues. It has always worked on real hardware and every emulator I've tried.

The current code slowly increases or decreases several echo filter coeffcients based on a short user specifed delay until it reaches specific hard coded values. It also, optionally, increases or decreases the echo volume as it does so. Before I start working to isolate the issue I'm going to try some other players. What are people using to play SPCs?
Re: Sound driver fun
by on (#159771)
Augustus Blackheart wrote:
The current code slowly increases or decreases several echo filter coeffcients based on a short user specifed delay until it reaches specific hard coded values.

That sounds almost exactly like something I was going to try so as to get a phaser effect (far down the road, of course; I've done essentially no SPC700 programming as yet)...

I really need to read through the source code at some point and see how Super SNESMod does what it does.

Quote:
What are people using to play SPCs?

Winamp, using this: http://alpha-ii.com/Download/Main.html#SNESamp
Also this (standalone Windows): http://dgrfactory.jp/spcplay/index.html

EDIT: Avast is blocking the downloads on that Japanese site (the second link). I'd assume it's a false positive, but I can't be certain. Way old version (with English translation) here: http://www.smwcentral.net/?p=section&a=details&id=4616
Re: Sound driver fun
by on (#159777)
93143 wrote:
Augustus Blackheart wrote:
The current code slowly increases or decreases several echo filter coeffcients based on a short user specifed delay until it reaches specific hard coded values.

That sounds almost exactly like something I was going to try so as to get a phaser effect (far down the road, of course; I've done essentially no SPC700 programming as yet)...

I really need to read through the source code at some point and see how Super SNESMod does what it does.


Yeah, it's not the best code at the moment but it works. I have some ideas to improve it. The main concern is ensuring avoiding overflows with the coefficents.

93143 wrote:


All the SPC files that crashed the other players play perfectly in SPCPlay. I've emailed the author of AudioOverload to let him know about the issues with his player. It looks like OpenSPC Lite has been abandoned(?), since there's source available perhaps I'll add it to my list of projects (it doesn't support pitch modulation... what?).

In case anybody is interested in testing this issue with other SPC players, the file pause.spc is one of the files that crashes SPCTool2, OpenSPC Lite and causes mayhem--and sometimes crashes--AudioOverload. The file is in the example directory of the smconv link in the first post.
Re: Sound driver fun
by on (#159797)
This reminds me of Shin Togenkyo, which did the same thing.

Here are my results...

Game Music Box ~ Fails after a few seconds (just like Shin Togenkyo)
Audio Overload 1.5 ~ Sticks on the first note (Shin Togenkyo worked)
Audio Overload 2.0 ~ Fails just like Shin Togenkyo (causes glitched audio)
vspcplay (I manually compiled a version originally ported/fixed up by bazz... the pre-compiled version gave me an Illegal Instruction error) ~ Doesn't even play (the PC constantly reads $FFCF... huh) (Shin Togenkyo worked, but accidentally missed the first note)
PSF/SPCPlay (command line application for Mac OS X) ~ Works perfectly (uses libopenspc++ if you're curious)

I do know of a few things that may have caused these SPC players a headache...
- Shin Togenkyo may have accidentally used memory wraparound for its stack.
- Memory wraparound was also not handled when it came to addressing if I remember correctly. In SNESMod's case, that was great for me, because I could catch myself if I failed to initialize the instruments in a .it file. In other player's cases (including the real deal), you'd get everything playing the wrong instrument.
- Are register wraparounds also implemented? Hmm... this one I didn't test.
Re: Sound driver fun
by on (#159809)
KungFuFurby wrote:
This reminds me of Shin Togenkyo, which did the same thing.

Here are my results...

Game Music Box ~ Fails after a few seconds (just like Shin Togenkyo)
Audio Overload 1.5 ~ Sticks on the first note (Shin Togenkyo worked)
Audio Overload 2.0 ~ Fails just like Shin Togenkyo (causes glitched audio)
vspcplay (I manually compiled a version originally ported/fixed up by bazz... the pre-compiled version gave me an Illegal Instruction error) ~ Doesn't even play (the PC constantly reads $FFCF... huh) (Shin Togenkyo worked, but accidentally missed the first note)
PSF/SPCPlay (command line application for Mac OS X) ~ Works perfectly (uses libopenspc++ if you're curious)


Thanks for checking. Here's what I did to fix it:

The first four lines of FilterSweep are as follows:

Code:
   inc   current_filter_time
   cmp   filter_time, current_filter_time
   bne   skip_filter_sweep
   mov   current_filter_time, #0

Here's the relevent part of main_loop before:
Code:
   cmp   filter_sweep, #0
   beq   main_loop
   SPROC
   call   FilterSweep
skip_filter_sweep:

...and after:
Code:
   cmp   filter_sweep, #0
   beq   main_loop

   inc   current_filter_time
   cmp   filter_time, current_filter_time
   bne   skip_filter_sweep
   mov   current_filter_time, #0

   SPROC
   call   FilterSweep
skip_filter_sweep:


Moving those first four lines in FilterSweep to main_loop was all it took to fix the issue.
Re: Sound driver fun
by on (#160333)
Anybody had the idea of implementing flanging? I think it could be done by manually shifting the echo memory by variable amounts. I'll test it out with Bad Apple.
Re: Sound driver fun
by on (#160787)
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. Here's what I speak of...

Code:
;********************************************************
CMD_LOADE:
;********************************************************
   mov   a, xfer_address
   mov   y, next_sample
   mov   !EffectDirectory+y, a
   clrc
   adc   a, SPC_PORT2
   mov   !EffectDirectory+2+y, a
   
   mov   a, xfer_address+1
   mov   !EffectDirectory+1+y, a
   
   adc   a, SPC_PORT3
   mov   !EffectDirectory+3+y, a
   
   clrc            ; safety clear for invalid loop points (thanks KungFuFurby)
   adc   next_sample, #4
   call   StartTransfer
   
   jmp   CommandRet


A clrc is added there because I discovered the bug during the development of MazezaM Challenge in 2012 (one of the songs I made managed to accidentally break the SFX under one condition), and adding the clrc opcode fixed the bug. This was actually the very first successful modification I made to SNESMod, and it was for bugfixing purposes. I actually sent the revision I made to the original developer, given the sound driver's original purpose was to play music and sound effects.
Re: Sound driver fun
by on (#161104)
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!
Re: Sound driver fun
by on (#161562)
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.
Re: Sound driver fun
by on (#161566)
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.
Re: Sound driver fun
by on (#161574)
Yeah, I was a bit sloppy there... the full fix was only in one of the drivers. They're all updated now.
Re: Sound driver fun
by on (#161586)
Well, have a 404 not found when I try to download your updated version Augustus Blackheart... :(
Re: Sound driver fun
by on (#161597)
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.
Re: Sound driver fun
by on (#161627)
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.
Re: Sound driver fun
by on (#161880)
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            ;
Re: Sound driver fun
by on (#162107)
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.
Re: Sound driver fun
by on (#162138)
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).
Re: Sound driver fun
by on (#168460)
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.
Re: Sound driver fun
by on (#186574)
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
Re: Sound driver fun
by on (#186580)
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.
Re: Sound driver fun
by on (#210193)
I fixed some of the clicking in SNESMod by using some code from XM2SNES. The issue I was having was with a bass sample and it would play fine unless 8th or 16th notes were used. This has been fixed!

SNESMod is a little less clicky than it was, but still more clicky than XM2SNES. This is still something I hope to fix, I don't have a lot of patience for this sort of thing, I'm always more interested in adding shiny new things than fixing broken things.