Jack Gassett

SID Filters

Recommended Posts

Ok, try this updated bit file, it sounds much, much better to me.

 

Alvie took a look at the noise generator and saw that we have it tied to bit 22 of the accumulator but the sidplay implementation uses bit 19 of the accumulator. He made a quick change to the VHDL code and the result sounds much better I think.

 

Any other differences that anyone can pick out?

 

Jack.

Papilio-pro-ZPUino-SID-filters_noisefix.zip

Share this post


Link to post
Share on other sites

Just been giving the new bit file a run through - I think we're pretty much there, I've listened to a few tunes and I can't spot any obvious issues! Well done guys, mightily impressed with the coding and turnaround time on these issues!

 

I've noticed also since the direct register writing fix, the timing seems to be better. I think previously all the unnecessary writing to ram and then copying to registers was slowing down the ZPUino player too much, seems to sound a lot tighter now.

 

Just as an aside, although my primary interest is for a standalone SID / POKEY / YM MIDI synth module (a hardware version of Plogue chipsounds is basically what I'm after!), I'm wondering from the papilio arcade side of the house, is there a desire to produce a full C64 as an output - a full SID with filters is obviously a big (and most exciting!) part, the PLA/CIAs are dead easy though the VIC-II would take some work (although obviously there's other HDL out there already for that)?

 

Well done guys

  • Like 1

Share this post


Link to post
Share on other sites
Just been giving the new bit file a run through - I think we're pretty much there, I've listened to a few tunes and I can't spot any obvious issues! Well done guys, mightily impressed with the coding and turnaround time on these issues!

 

I've noticed also since the direct register writing fix, the timing seems to be better. I think previously all the unnecessary writing to ram and then copying to registers was slowing down the ZPUino player too much, seems to sound a lot tighter now.

 

Just as an aside, although my primary interest is for a standalone SID / POKEY / YM MIDI synth module (a hardware version of Plogue chipsounds is basically what I'm after!), I'm wondering from the papilio arcade side of the house, is there a desire to produce a full C64 as an output - a full SID with filters is obviously a big (and most exciting!) part, the PLA/CIAs are dead easy though the VIC-II would take some work (although obviously there's other HDL out there already for that)?

There is this implementation of the Commodore 64, but the license is not Open Source. I don't know if the author would be willing to let us implement this for Papilio users... We could ask, he seems open to granting licenses, or maybe he would be ok with it. Maybe if I just wrote a tutorial about how to get it working on the Papilio.

 

Well done guys

Share this post


Link to post
Share on other sites
If you stay with the 500K you will be able to get the majority of the synthesis features. But you will miss out on the SID analog filters, even if we save space and do not include the tinySID library the 2 BRAMs needed by the SID analog filters rules out implementation on the 500K.

 

Jack.

 

 

How about an actual analog filter audio wing? Looks like a simple circuit, quad op-amp, a couple of digital pots and a handful of resistors. Might be a viable option for those wishing to use the simpler FPGA boards and the real deal would be a big more authentic than recreating the analog portion digitally.

Share this post


Link to post
Share on other sites
There is this implementation of the Commodore 64, but the license is not Open Source. I don't know if the author would be willing to let us implement this for Papilio users... We could ask, he seems open to granting licenses, or maybe he would be ok with it. Maybe if I just wrote a tutorial about how to get it working on the Papilio.

 

It looks like the older versions include the source, unless I'm missing something? I believe only the one that includes code from the Chameleon project are closed source. I haven't actually looked at the source or the hardware requirements but it looks like someone could attempt a port to the Papilio board if they wanted to.

Share this post


Link to post
Share on other sites
How about an actual analog filter audio wing? Looks like a simple circuit, quad op-amp, a couple of digital pots and a handful of resistors. Might be a viable option for those wishing to use the simpler FPGA boards and the real deal would be a big more authentic than recreating the analog portion digitally.

 

Problem is the 11-bit dual VCR (Voltage Controlled Resistor). Note that the filter settings are set by the music, and can change during play.

 

Regarding the authenticity of sound.... note that in real SID there were no OP amps, they were implemented with NMOS transistors and were not ideal.

 

I see two or three options here for P1 500:

a) Remove the big serial fifo (uses one BRAM)

B) Cut the filter accuracy to 1024 entries instead of 2048 (only one BRAM needed then)

c) Find some other way to compute the non-linear filter response.

 

Alvie

Share this post


Link to post
Share on other sites
Problem is the 11-bit dual VCR (Voltage Controlled Resistor). Note that the filter settings are set by the music, and can change during play.

 

Regarding the authenticity of sound.... note that in real SID there were no OP amps, they were implemented with NMOS transistors and were not ideal.

 

I see two or three options here for P1 500:

a) Remove the big serial fifo (uses one BRAM)

B) Cut the filter accuracy to 1024 entries instead of 2048 (only one BRAM needed then)

c) Find some other way to compute the non-linear filter response.

 

Alvie

 

 

Would a digital pot not work in place of the VCR? Another option would be a JFET fed by a delta-sigma DAC, either one is simple enough to interface to the FPGA. Perhaps it's more trouble than it's worth though.

 

I suspect most would be hard pressed to hear the difference between 1024 and 2048 entries, but it would be interesting to hear the two side by side and compare.

Share this post


Link to post
Share on other sites

Hi, had a chance to check out the filters (nice job Alvie), but am I the only one hearing quite obvious distortion especially in low frequency filtered output. I'd suggest as a test to play "Hell Machine" as per my list I posted earlier in this thread, as the distortion there is quite obvious. It sounds to me like math overflow somewhere.

 

I took a quick look and I couldn't see anything obvious with the filter code but one level above the filter I saw:

  voice1_signed <= signed(voice_1 & "0") - 4096;  voice2_signed <= signed(voice_2 & "0") - 4096;  voice3_signed <= signed(voice_3 & "0") - 4096;

I don't understand why you're multiplying each voice by 2 (right shift) I suspect it's a logic problem :) The original signal is 12 bit unsigned (range 0 to 4095) which after the above conversion becomes signed (range 0*2-4096 to 4095*2 - 4094 or -4096 to 4094), note that the signal range has doubled from the original so, you 're passing to the filter larger amplitude signals than intended. I took a stab and replaced the above code with what I think was the intended conversion:

  voice1_signed <= signed("0" & voice_1) - 2048;  voice2_signed <= signed("0" & voice_2) - 2048;  voice3_signed <= signed("0" & voice_3) - 2048;

Which has eliminated the distortion, let me know what you think Alvie.

 

The only other question I have is the line at state 6 in the filter:

when 6 =>-- Adjust Vbp*Q, shift by 10w.Vhp := (mulr(35)&mulr(35)&mulr(25 downto 10)) - r.vlp;
If you intend to just shift by 10 then why are you blitzing bit 26 of the multiplier result? Should this not be a 16 bit result plus sign bit like so:
w.Vhp := (mulr(35)&mulr(26 downto 10)) - r.vlp;

Again, well done with the resid filter implementation, sounds real good.

Share this post


Link to post
Share on other sites

Hi, had a chance to check out the filters (nice job Alvie), but am I the only one hearing quite obvious distortion especially in low frequency filtered output. I'd suggest as a test to play "Hell Machine" as per my list I posted earlier in this thread, as the distortion there is quite obvious. It sounds to me like math overflow somewhere.

 

I took a quick look and I couldn't see anything obvious with the filter code but one level above the filter I saw:

 

  voice1_signed <= signed(voice_1 & "0") - 4096;  voice2_signed <= signed(voice_2 & "0") - 4096;  voice3_signed <= signed(voice_3 & "0") - 4096;
I don't understand why you're multiplying each voice by 2 (right shift) I suspect it's a logic problem :) The original signal is 12 bit unsigned (range 0 to 4095) which after the above conversion becomes signed (range 0*2-4096 to 4095*2 - 4094 or -4096 to 4094), note that the signal range has doubled from the original so, you 're passing to the filter larger amplitude signals than intended. I took a stab and replaced the above code with what I think was the intended conversion
 

Not really. The original reSID filters use 13-bit, not 12. so I extended them. So problem should be somewhere else.

 

  voice1_signed <= signed("0" & voice_1) - 2048;  voice2_signed <= signed("0" & voice_2) - 2048;  voice3_signed <= signed("0" & voice_3) - 2048;
Which has eliminated the distortion, let me know what you think Alvie.
 

Not quite right... you are inverting the samples here, cause you do not keep the sign. The upper "0" will cause them to read all as positive values, so a -2048 sample will become 2047...

 

The only other question I have is the line at state 6 in the filter:

when 6 =>-- Adjust Vbp*Q, shift by 10w.Vhp := (mulr(35)&mulr(35)&mulr(25 downto 10)) - r.vlp;
If you intend to just shift by 10 then why are you blitzing bit 26 of the multiplier result? Should this not be a 16 bit result plus sign bit like so:

w.Vhp := (mulr(35)&mulr(26 downto 10)) - r.vlp;
Again, well done with the resid filter implementation, sounds real good.

Ok, this might be the real issue. Not quite sure why I extended it using two bits. Care to try with only this change to see if distortion goes away ?

Alvie

Share this post


Link to post
Share on other sites

Actually I had already tried (mulr(35)&mulr(26 downto 10)) alone and it did not make any audible difference and the distortion was still there so I left it as per your original code before moving on to the filter input values.

 

I still don't understand the logic applied to the filer input, the main reason to subtract that type of constant from the voice values would be to turn an unsigned value into a signed value, but if the voices already represent signed values as you've stated before, then why subtract -4096?

 

With signed voices, the math there becomes voice range -2048 to 2047 is doubled to become -4096 to 4094 then after subtracting 4096 and accounting for 13 bit truncation it becomes a weird sign and range inverted signal, see this table with some example values covering the range:

signed input   doubled   minus 4096       -2048     -4096            0       -1024     -2048         2048        -512     -1024         3072           0         0        -4096         512      1024        -3072        1024      2048        -2048        2048      4096            0

In any case, experimentally, reducing the amplitude of the input signals to the filter eliminates the distortion which shows there is some overflow occurring somewhere.

 

Share this post


Link to post
Share on other sites

No, the samples that come out from the sid_voice module are unsigned, not signed. In order to send them to the filters we need to convert them into signed values.

For a 12-bit value it will be within the range 0U and 4095U. By left shifting we get a value between 0U and 8190U. If we subtract the DC level (-4096S), we end up with a value in the range -4096 and +4094. So the level conversion seems correct.

What might be happening here is that due to the positive feedback from Q some overflow might be occurring, since we don't actually "clip" the signal in case it overflows or underflows.

To see where the distortion is coming from I need the registers at that time. You think you can get me that ?

Best,

Alvie

Share this post


Link to post
Share on other sites

But... in post #63 you said I'm inverting the samples from the sid_voice because I don't keep the sign bit and then just above you say the samples come out from the sid_voice unsigned. In any case, I don't see an easy way to get you the register values at the exact time the distortion occurs, perhaps you can run the song I suggested through your implementation and you can't miss hearing it. For now I'm sticking with not doubling the sample values as they enter the filter (eg voice1_signed <= signed("0" & voice_1) - 2048;) and that seems to work OK since voice_1/2/3 are unsigned, right? Don't change your mind again  :P

Share this post


Link to post
Share on other sites

Can you try this clipping code, to see if distortion goes away ?

--- a/zpu/hdl/zpuino/contrib/NetSID/src/sid_filters.vhd+++ b/zpu/hdl/zpuino/contrib/NetSID/src/sid_filters.vhd@@ -123,6 +123,9 @@ begin    process(clk, rst, r, input_valid, val, filt, voice1, voice2, voice3, voice3off, mulr, ext_in, hp_bp_lp, Mode_Vol)     variable w: regs_type;+    variable madj: signed(25 downto 0);+    constant smax: integer := (2**17)-1;+    constant smin: integer := -1*(2**17);   begin     w:=r;     mula <= (others => 'X');@@ -209,7 +212,15 @@ begin         w.state := 6;       when 6 =>         -- Adjust Vbp*Q, shift by 10-        w.Vhp := (mulr(35)&mulr(35)&mulr(25 downto 10)) - r.vlp;+        -- Perform clipping+        madj :=  mulr(35 downto 10);+        if (madj > smax) then+          madj := to_signed(smax,madj'LENGTH);+        elsif (madj < smin) then+          madj := to_signed(smin,madj'LENGTH);+        end if;++        w.Vhp := (madj(25)&madj(16 downto 0)) - r.vlp;         if hp_bp_lp(0)='1' then           w.Vf := r.Vf + r.Vlp;         end if;

Share this post


Link to post
Share on other sites

They just need to be cleaned up, packaged, and released. I'm going to set that as my goal for this week! It will be great to get this released out there, sorry it has taken so long.

 

Jack.

Share this post


Link to post
Share on other sites

Great to hear that! I am currently building my own hardware synthesizer system based on the RetroCade Synth and a Raspberry Pi as well as a simple MIDI controller, so I am slowly getting back into development of various components, from FPGA design on the chips to optimizing the Linux kernel for realtime-audio on the Pi to writing a MIDI sequencer in PureData. Can't wait to try out the new filters...

Share this post


Link to post
Share on other sites

Ok, I just took a look at the state of things in preparation for making a release. There is still a lot that needs to be done, the tinysid player needs to be turned into a library first. I'm going to start taking this a step at a time, but am not sure that it is doable in the next week. My initial goal is to just turn tinysid into a library with a stand alone player example. Once that is done then I will look at integrating into RetroCade with support for playing from SD card etc.

 

Jack.

Share this post


Link to post
Share on other sites

Great news, I had a late night hacking session last night and made way more progress then I expected. Tinysid is now a library that is wrapped by a SIDPlayer library, that is what I was expecting to be the hardest part and it is done!

 

I still need to add support for playing SID files from SD cards, then I will be able to add SID file support to the RetroCade sketch. After that its all about getting the VHDL code checked in, synthesize a new bit file for the release, and then packaging everything up. I will attempt to make a linux and Mac OSX release as well.

 

Jack.

Share this post


Link to post
Share on other sites

More good news, I have the sidplayer integrated into the RetroCade sketch and am now playing SID files using the LCD interface from both SmallFs and the SD card. The hardest part is now done and working!

 

Next up is to put together the VHDL code and start on a release. This is moving along faster then expected.

 

Are there any recommendations on what SID files to include in smallFS? I need the top ten favorite SID files out there.

 

Jack.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now