Shop OBEX P1 Docs P2 Docs Learn Events
SPCcog - The sound of the Super Nintendo in a cog! — Parallax Forums

SPCcog - The sound of the Super Nintendo in a cog!

Wuerfel_21Wuerfel_21 Posts: 5,051
edited 2024-03-28 12:38 in Propeller 2

And once again I appropriate @Ahle2's brand...

This is an emulation of the Nintendo/Sony sound module used in the Super NES / Super Famicom (consisting of an SPC700 processor and a custom audio DSP) that runs in one P2 cog.

Features:

• 8 channels of BRR sample playback
• 32kHz sample rate, accurate to real S-DSP
• SPC700 CPU emulation with instruction timings
• SPC file metadata parsing library (SPCmeta.spin2)


No fancy videos or demos this time, just a simple SPC file player. That functionality is positively "idiot-proof", just load the file into memory and off you go. Doing anything more complex requires writing some SPC700-side code, so, uhh, have fun with that.

Temporary Notice: You can't actually build the example with DEBUG enabled under flexspin right now. >_< Will probably be fixed soon, stand by. Until then, no metadata for you. No longer applies, but I think there's a different bug now...


Update V1.1: Fixed BRR decode clamping and added another sample file.
Update V1.2: Fixed BRR decode even more and added even more sample files.
Update V1.2.1: Fixed some files not playing due to uncalled-for echo RAM clearing and added an affected example file.

Comments

  • pik33pik33 Posts: 2,366

    Yet another sound chip emulator... Compiles and works but SPCCog.spin2 file opens in Flexprop with this famous "every second char is space" character coding bug.

  • Wuerfel_21Wuerfel_21 Posts: 5,051
    edited 2022-03-25 12:33

    @pik33 said:
    Yet another sound chip emulator... Compiles and works but SPCCog.spin2 file opens in Flexprop with this famous "every second char is space" character coding bug.

    Huh.... works for me. The wonders of UTF-16.

  • roglohrogloh Posts: 5,786
    edited 2022-03-25 12:36

    Probably because it is a unicode file. If you have VIM you can load it and convert it to regular 8 bit text with the :set fileencoding=utf-8 command then save it back with :wq.

  • pik33pik33 Posts: 2,366
    edited 2022-03-25 12:38

    For me it didn't - I recoded the file (and reduced its size x2) . This was Windows 11 - I will check this in Linux, maybe it is Windows only problem in Flexprop. The next thing to add this to the Propplay, which was not updated for a long time as I wanted to fully debug and add PSRAM support to the video driver first

  • pik33pik33 Posts: 2,366
    edited 2022-03-26 21:41

    (1) The file UTF16 coding error is WIndows only. Linux opens it properly. What caused the problem was probably ä in the comment.
    (2) I tried do do something with the SPCMeta in Basic to get the metadata printed, no success at all, and what was worse, there were very strange side effects.. I gave up and used retro old style programming mode :) to get the file info printed instead:

    const _CLKFREQ = 32*256*32_000
    const DEBUG_COGS = %01
    const leftpin = 8+6
    const rightpin = leftpin+1
    
    dim a1$ as string
    
    dim spc as class using "SPCcog"
    spc.start_spcfile(leftpin,rightpin,@spcfile)
    
    print("SPC metadata:")
    lpoke(addr(a1$),addr(spcfile)+$2e)
    print "Song title:",left$(a1$,32)
    lpoke(addr(a1$),addr(spcfile)+$4e)
    print "Game title:",left$(a1$,32)
    lpoke(addr(a1$),addr(spcfile)+$6e)
    print "Dumper name:",left$(a1$,16)
    lpoke(addr(a1$),addr(spcfile)+$7e)
    print "Comments:",left$(a1$,32)
    lpoke(addr(a1$),addr(spcfile)+$9e)
    print "Dumped at:",left$(a1$,11)
    lpoke(addr(a1$),addr(spcfile)+$a9)
    print "Play time:",left$(a1$,3);" s."
    lpoke(addr(a1$),addr(spcfile)+$ac)
    print "Fade time:",left$(a1$,5);" ms."
    lpoke(addr(a1$),addr(spcfile)+$b1)
    print "Artist:"," ",a1$;" ms."
    
    do:loop
    
    sub lpoke(addr as ulong,value as ulong)
    asm
    wrlong value, addr
    end asm
    end sub
    
    
    function addr(byref v as const any) as ulong
    return(cast(ulong,@v))
    end function
    
    shared asm 
    
    '' Note: copy the SPC files from the "tunes" directory
    ''       into the directory this file is in to make PropTool
    ''       find them. Or use that one command line option that
    ''       flexspin has. .... What, do I look like I remember how
    ''       that one goes? .... Ok, I have been informed I do
    ''       look like that. Well, I believe it'd be "-L ./tunes".
    ''       Yeah I think that'd do it.
    spcfile  'file "sd2-01.spc"
            'file  sd2-18.spc"
            'file "sd2-34.spc"
            'file "sd2-41.spc"
            'file "sd3-207.spc"
            'file "sd3-208.spc"
            file "sd3-301.spc"
            'file "sd3-312.spc"
            'file "mmx-04.spc"
            'file "mmx-16.spc"
            'file "scv4-06.spc"
            'file "scv4-28.spc"
            'file "iog-03.spc"
            'file "yi-07a.spc"
            'file "smr-128.spc"
            'file "sf-09.spc"
            'file "plok-01.spc"
            'file "plok-05.spc"
            'file "plok-12.spc"
            'file "plok-13.spc"
            'file "actr-04.spc"
            'file "Axel-F.spc"
            'file "sewer_surfin.spc"
            'file "fz-02.spc"
            'file "fz-07.spc"
            'file "fz-09.spc"
            'file "loz3-08.spc"
            'file "loz3-21.spc"
            'file "loz3-31.spc"
    end asm
    
  • Wuerfel_21Wuerfel_21 Posts: 5,051
    edited 2022-03-26 22:05

    @pik33 said:
    (1) The file UTF16 coding error is WIndows only. Linux opens it properly. What caused the problem was probably ä in the comment.

    That, and the box drawing characters. It works fine on Windows 7 for me with latest FlexProp. I blame Win11.

    (2) I tried do do something with the SPCMeta in Basic to get the metadata printed, no success at all, and what was worse, there were very strange side effects.. I gave up and used retro old style programming mode :) to get the file info printed instead:

    There is a reason that file is so complex - there's two different ways the basic metadata can be encoded (though "text" mode is the more common) and then there's xid6 extended metadata (only way to get Publisher and Year fields and also where you need to get the basic fields from when they exceed 32 characters).

    All the string functions in SPCmeta return ptr+length type strings and you have to check that length isn't zero.

  • pik33pik33 Posts: 2,366
    edited 2022-03-26 22:32

    The strange problem was:

    If I called

    a$,b=spcmeta.getSongTitle(@spcfile)
    print a$
    

    it printed the name, so OK, I added

    a$,b=spcmeta.getGameTitle(@spcfile)
    print a$
    

    Now, nothing was printed at all. Then I tried to print also the length returned by GetSongTitle - which was called first. It was 2, or 65, or 0, with the same file, it depended on how many of these functions I called after

    I think I did something wrong with pointers and addresses. Maybe tomorrow. I have a description of the file format including all these format variants.

  • @pik33 said:
    The strange problem was:

    If I called

    a$,b=spcmeta.getSongTitle(@spcfile)
    print a$
    

    it printed the name, so OK, I added

    a$,b=spcmeta.getGameTitle(@spcfile)
    print a$
    

    Now, nothing was printed at all. Then I tried to print also the length returned by GetSongTitle - which was called first. It was 2, or 65, or 0, with the same file, it depended on how many of these functions I called after

    I think I did something wrong with pointers and addresses. Maybe tomorrow. I have a description of the file format including all these format variants.

    No that just sounds like flexsploop. Have only tested the metadata reader on proptool because there's the aforementioned flexspin DEBUG bug wherein you can't actually pass multireturns into DEBUG (and I'm too dum dum to figure out how to fix it)

  • Just posted a V1.1 because I noticed a bug. Apparently decoded BRR samples need clamping. Makes the decode code a bit less nice / slower, but oh well. None of the gamerip files seem to rely on this behaviour, but one (1) drum sample in someone's Broken Moon chiptune cover SPC does (thanks youtube recommend algorithm lmao). Added that one to the examples to demonstrate. Sounds like this without fix:

    yea....

  • Should probably mention @pik33 because I know he actually uses SPCcog.

  • It turns out there is yet more nuance to BRR decoding... It seems like the particular precision of the decoder matters when going near the maximum values, as the clamping is weirdly buggy (clamp values are double of what they should be? At least that's what looking at the blargg SPC core used in many emulators would suggest). Previous versions of SPCcog had an additional bit of precision in the decoding stage, which was causing overflows when decoding some samples. The weird clamping is still needed though, see example above, so some extra instructions had to be inserted :(

    Uploaded V1.2 in first post.

  • MaciekMaciek Posts: 674
    edited 2023-03-28 16:15

    That functionality is positively "idiot-proof"...

    Finally, somebody has made something tailored specifically for me. If I can't break it, nobody can.

    But seriously, this is mighty impressive. Thanks for sharing.

  • Wuerfel_21Wuerfel_21 Posts: 5,051
    edited 2024-03-28 12:39

    Updated to V1.2.1 to fix a bug with initializing SPC file dumps. Some files have garbage in the echo RAM area that needs to be cleared out. This obviously shouldn't be happening if echo write is disabled through the FLG register and doing so anyways breaks some tunes.

    EDIT: oops, uploaded bad file, fixed now.

Sign In or Register to comment.