SPC700 help

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
SPC700 help
by on (#92567)
I have been trying for at least 4-2 weeks to get this working, but I just can not seem to get sound to play. I understand about samples and the opcodes of the SPC700, and I am uploading my program correctly because it is being run, but I'm just not sure how to play notes or anything... I did try using someone elses spc700 code before and I did get sound but im not sure how to change the notes its playing or anything... Any help would be appreciated!

by on (#92569)
There's a fairly complete manual here

by on (#92574)
Great, finally a SPC doccumentation that isn't terribly old and outdated.

Yet, why are the BRR blocks displayed backwards ?
And some of the obscure opcodes are still unexplained.

Another thing that looks innacurate to me is how ADSR is explained. Decay rate (DR) is never a constant time as it depends on sustian level (SL). The lower the SL, the longer it takes to decay to this level.

The real (accurate) was to explain it is how the enveloppe variable (ENVX) is altered over time by multiplications by a constant (or additions, when it comes to attack phase).

by on (#92576)
I did try reading that, it help me just as much as the other ones read. I just done understand how this woks, im pretty sure songs arent just one long .brr file playing (or even most sound effects). I can get a .brr sample to play but im not sue how to change the note to make it play which is what i'm really stuck on right now as nothing I read has mentioned anything about it :/

by on (#92577)
To change the note, try writing a different pitch. To play a melody, write a pitch, write a different pitch a couple hundred milliseconds later, and repeat.

by on (#92578)
Bregalad wrote:
Great, finally a SPC doccumentation that isn't terribly old and outdated.

Really? I don't know much about the SNES, but comments like these are not very inspiring:

SPCTECH wrote:
I never used this flag either. I'm not really sure what it does.

Serious tech documents shouldn't be written in the first person. If there's something you don't know, just write "unknown". "I never used this" also doesn't mean much unless we know how much experience the writer had with the console.

by on (#92579)
So what you are saying is that you can program the SPC, but don't know how to make a fully functional sound engine ?

Well then you should fist think how your tracks are going to be stored.

Then you need to have a routine that is called regularly in time, using one of the SPC timers. How regularly is up to you, but a faster routine can be used for more precise effects, but you might not want to spend a lot of time optimizing your code for speed if it's the first time you write a sound engine so make it not too fast or it'll end up lagging anyways. (if the timer has already overflown when your routine returns to your idle loop, the routine will be called a second time etc... and the music will play gradually slower as the engine takes too much time to execute).

In your routine you'll need to do a loop for each track that decrease some kind of counters, and if they are down to zero, treat the next event in the track (be it a note, rest, or effect command, etc...)

You'll also need a pitch table. Since samples can be recorded at different pitches, it's more complex to do than, for exmaple, on the NES. There is several ways arround this, for exmaple have a generic pitch table of a lot of entires, and have a different offset for each sample. Also you only need a table for the highest octave (pitches 0x2000 to 0x3FFF) because lower octaves can be derived from it by shifting the value right.

You should probably first try to play simple melodies without effects, don't use echo or such effects on your first try. Also an ADSR enveloppe of 0xFF, 0xE0 will mean basically no envelope effect (full sustain forever) so you might want to keep that in mind for your first experiments, before implementing something more sophisticated.

One thing you should be very careful is to delay key-ons by a "frame". If you change a note from another and key off and on on the same frame, there will have a click sound, so you need to key off one frame, and key on the next frame.
This can be tricky to implement, but it's important to get it work right.

I have successfully written a sound engine for the SPC - and to get pretty complex effects working - and I'd gladly share the source if I didn't lost it ! I can share the compiled SPC but I'm afraid it wouldn't be of much use - not more than a compiled SPC from any existing game.

PS :
Quote:
Serious tech documents shouldn't be written in the first person. If there's something you don't know, just write "unknown". "I never used this" also doesn't mean much unless we know how much experience the writer had with the console.

This is right, however, there were other doccuments that claimed the SPC had 32k of memory, and I remember one where the author started by saying something like :
"I hate, hate the SPC so much, it's such a piece of crap !"
Then why are you writing a document about it ?

by on (#92583)
A little hint for you: for every 0001 (in hex) that you add to the pitch, I determined it increases the pitch by 3.90625 hz. :wink:

This might be as close as you can get to real technical documentation... it happens to cover the whole kit and kaboodle, including SNES sound.

by on (#92584)
Thanks for your help everybody I really appreciate it!

Now what I need help with is this code (yes I am aware its pretty messy but im just trying to get something that works right now). When ever I send something to $2140 nothing happens (no sounds plays), so I'm wondering what the problem is. And I checked if it was being uploaded and it is and it is running, my ROM is running fine and it's branching right (in the SPC700 code I mean) as far as I can tell but still nothing happens.

Thanks!

by on (#92589)
Code:
%wdsp(#!KOF, #$0F)

You're constantly keying off channels 0-3, so any sound that you ever start on those channels would be super, super short. Remove that line, and also add this among your DSP setup:
Code:
%wdsp(#!KOF, #$00)


Also, I see that you have echo enabled with the echo buffer address set to 0x100. This will cause problems if your code grows to cross into the echo buffer (and by problems I mean your code will probably crash).
Try changing this line
Code:
%wdsp(#!FLG, #$00)

To this
Code:
%wdsp(#!FLG, #$20)

by on (#92597)
Ok well I sorta of got it working. It works right in zsnes, and it kinda works in snes9x, but not in bsnes and im not sure why. Here is everything im using if it helps figure out the problem.

by on (#92599)
Word of advice: just ignore zsnes and snes9x altogether for development purposes. I've had stuff that sorta worked in them but failed on a real SNES (and in BSNES). It's better to use BSNES to debug code, as it's much more accurate.

by on (#92600)
Well I am aware of this, but like I said it is breaking in bsnes and I'm not sure why. Right now there is no sound in it.

by on (#92601)
BSNES has a debugger that lets you step the SPC (or S-SMP rather). I don't remember if it also has a DSP register viewer.

by on (#92602)
Ok well I checked if my code was running and it looks like it is everything is getting set properly and it is branching correctly but there is still no sound, so im not really sure what the problem is...

by on (#92603)
I'd suggest disabling echo, clearing the ADSR registers, setup the gain registers / master volume for a constant volume, setting up the sample source dir, the pitch register, clear KOF, set KON.

by on (#92605)
ok i think im getting closer the only problem i have now is that sound effects constantly play,is there some way to make them stop after a bit (I guess using a timer?).

by on (#92606)
Either use a timer to key the channel off, or mark the BRR sample as non-looped if it's a one-shot sound (e.g. an explotion/scream/etc).

by on (#92607)
Have you even read my long post ?
I explained how you need to have a routine that is called regularly, and one of the first things you should do is to deal with key on, key off and pitches.

by on (#92608)
Yes I read it now and it helped me very much, thank you.

Ok I got the sound effect to stop after a certain amount of frames and everything seems to work fine.... but now the sound effect plays too quietly and im not sure why. I have the master volume (left and right) set to #$7f and the volume for the voice at #$7f as well yet I can barely hear it. Here is my current code.

by on (#92609)
I think it's a problem with the enveloppe. It looks like you write 0, 0, 0 to enveloppe regs which should normally not work (in fact its weird if you hear sound with this settings, this should result in silence !)

You should write 0xFF to ADSR1 and 0xE0 to ADSR2 to have no enveloppe (sustain at max value forever). In this setting the value in GAIN have no effect.

Alternatifely you could write 0x00 to ADSR1, and 0x7F to GAIN, to directly force the enveloppe to 0x7F. Both should be completely equivalent.

by on (#92625)
Er.. sorry for all the questions... but now channel 3 seems to cut in and out when I activate it for some reason. None of the other channels seem to do this and I have all the channels set the same way. Here is my current code. Thanks!

by on (#92626)
I don't see anything in your SPC code that prevents processing the same command over and over. Does your code on the 65816 side write zero to the communication port a while after sending a "START CHANNEL X" command?

by on (#92631)
mic_ wrote:
I don't see anything in your SPC code that prevents processing the same command over and over. Does your code on the 65816 side write zero to the communication port a while after sending a "START CHANNEL X" command?


Yes, all im doing is making the channel stay active for as long as im holding a button, but for some reason when I hold up (which activates channel 3) it cuts in and out while the other ones don't.

by on (#92644)
Try using a different button to activate channel 3... sometimes it ends up being on the SNES end that causes a hiccup (or it could be your keyboard). Either that, or make sure your auto-fire is completely off (you may have accidentally activated it for the up key).

by on (#97312)
Um... sorry if this is considered a bad bump...

After taking a break from this for a while and working on some other things I decided to try to make a functional sound engine, I first wanted to start off with just playing sound effects so I wrote this:

http://www.pastebay.net/1069545

and when i try to play it in snes9x it makes some short sounds but never plays the whole things, and i get nothing in bsnes! Getting rid of the second:

Code:
mov $f2, #$4c   ;\
mov $f3, #$00   ; | Turn off all voices
mov $f2, #$5c   ; |
mov $f3, #$FF ;/


plays the whole thing but only once and still nothing in bsnes! So yeah any help would be great!

by on (#97316)
A channel that has KOFF=1 (and does not play any sound yet) is effectively muted and will be put into release state immediately after it has been turned on; try clearing the KOFF bit for channel 0 before toggling KON.
Furthermore, you don't need to write 1 to KOFF at all; writing $FF to KOFF once at startup puts all channels into release state.

by on (#97332)
Ok thanks, i think im getting closer now. The sounds play correctly in snes9x, but in bsnes I get this loud beeping sound and I don't know why. Here is the code im using:

http://www.pastebay.net/1069601
Re: SPC700 help
by on (#97520)
Does anyone have any ideas?...

If not, does anyone know of a working SPC engine I can study (Preferably one with comments :P)?
Re: SPC700 help
by on (#97522)
You can check out my engine from Christmas Craze sources (spc700.asm).
Re: SPC700 help
by on (#98082)
ARGHRGRHRG!! I can not figure this out... As far as I can tell, I don't seem to be doing anything too different from that one, but mine won't work on bsnes... *sigh* this is the only thing stopping me from making any more progress on my homebrew... I suppose i'll post my current code again, hopefully some can tell me what I am doing wrong:

http://www.pastebay.net/1070974
Re: SPC700 help
by on (#98097)
@Shiriu it's strange how your SPC code uses 6502-like syntax.

@wiiqwertyuiop : Maybe it would be better if you told us what goes wrong ?
Re: SPC700 help
by on (#98098)
It is optional in the Bass assembler, the best of currently available SPC700 assemblers. Actually, it is very convinient when you have previous knowledge of 6502 syntax, as the SPC700 is like a 6502 on steroids.
Re: SPC700 help
by on (#98113)
Code:
mov $f2, #$5c   ; \
mov $f3, #$ff ; |
mov $f2, #$4c   ; |
mov $f3, #$00 ; |
mov $f2, #$5c   ; |
mov $f3, #$00 ;/


You're introducing a race condition here. DSP register writes don't have an immediate effect, but are read at some specific time in a 64 cycle window.
The value of KOFF is read only ONCE during this 64 cycle window. If you do a loop like the following, there are 3 possible scenarios, depending on when the KOFF is processed by the DSP unit.

Code:
loop:
<------------------- Read KOFF=$00
mov $f2, #$5c   ; \
mov $f3, #$ff ; |
mov $f2, #$4c   ; |
mov $f3, #$00 ; |
mov $f2, #$5c   ; |
mov $f3, #$00 ;/
bra loop

This does not key off any channel.


Code:
loop:
mov $f2, #$5c
mov $f3, #$ff
<------------------- Read KOFF=$FF
mov $f2, #$4c
mov $f3, #$00
mov $f2, #$5c
mov $f3, #$00
bra loop

This does key off ALL channels.

Code:
loop:
mov $f2, #$5c
mov $f3, #$ff
mov $f2, #$4c
mov $f3, #$00
mov $f2, #$5c
mov $f3, #$00
<------------------- Read KOFF=$00
bra loop

This does not key off any channels.

One solution is to write KOFF and KON only once during each main loop iteration:

Code:
loop:
... (wait for next timer tick) ...

mov $f2, #$5c
mov $f3, koff_shadow
mov $f2, #$4c
mov $f3, kon_shadow

... (process channels, store key on/key off in shadow variable) ...
bra loop
Re: SPC700 help
by on (#98248)
Made some changes but still nothing in bsnes... :v

Here is my code:

http://www.pastebay.net/1071326
Re: SPC700 help
by on (#98382)
Ok, I finally, after working on it some more on my own, got it working perfectly! Thanks to those of you who helped for putting up with my stupid questions. :P