Also quite glad to see this! This has become one of my favorite threads of the forum. It covers a lot of ground, and it's great to see your hard work and perseverance payoff here. Cheers too you, nau!
@nau said:
The BJT gains are bound to my 'signal amplitude policy' : input file or audio source and output should never clip. These gains can be seen as follows : the first one (before the clipper) adjust 'how early' distortion occurs, and the second one gives the distorted signal a boost in order to give similar subjective level than dry signal.
The values were found empirically.
This might be where I have the biggest issue, though the article doesn't make it so clear, either. In the article, it shows the frequency response of the BJT stage as having about a 36 dB boost in the pass band. That amounts to multiplying the signal by about 63. And, if you want to get really technical, the waveshaper in the article clips at +/- .6, so you'd have to add about another 4.5 dB to make up for that. You're using much lower values. This is what I was talking about earlier when I said you should really crank the input to [tanh~] to get some serious distortion, and the DS-1 isn't a baby's distortion pedal.
Now, the article also says that the second BJT stage is really to boost the signal back up for the subsequent load. Since we're not sending this into other circuits here, I think the dB boost of the second BJT should be ignored. Also, you don't need to calculate the boost into the filter coefficients. That's only useful for plotting. You can just use [*~] before or after the filter do accomplish it.
So basically what I'm saying is, there should be a boost of about 40 dB ([*~ 100]) as part of the first BJT stage, and no boost for the last one. Then you can really break some teeth with this distortion.
- when switching between upsampled or not upsampled processing, the difference is barely noticeable (maybe the upsampled one has more highs, but that is the exact contrary of what I would expect). Does someone see what I am doing wrong, if this is the cause of this perceptual draw ?
As mod said, it's not so much more highs as less lows, and those lows are a result of aliasing. To my ears, the upsampled version sounds less muddy. (By the way, in your upsampled portion, you have a different argument for the second [DS1-bjt_stage~]. Making them equal makes the difference even less noticeable, and draws more attention to the mud than the highs.)
- the transfer curves can be seen in the patches, but are always slightly different than the one showed in the article. But I have been very careful when calculating coefficients and I don't really think they are wrong. Would there persist a difference between [filterplot.mmb] and traditional Matlab-like graphs ?
Yes, there is a difference, but it's not a Matlab thing. It's the choice of the logarithmic scaling in the x-axis. The article uses powers-of-ten as equal distances. Mine uses [mtof] for the scaling, so that a semitone, octave, or whatever musical interval is the same distance. Also, I made an adjustment so that everything between 0 and about 20 Hz (at 44.1k) gets squashed in the leftmost 10% of the graph. If I didn't to that, then about half the plot would be taken up with frequencies below the audible range.
- The DS1-tone_stage helpfile has been written by Maelstorm, and the response curve shows no gain value above 0db. Nevertheless the tone knob, when pushed, can lead to signal amplitude beyond [-1 1]... I can't figure out how a signal can have all its discretised frequencies pulled down and still exhibit peaking. Should I read more about the subject (is there a name for this symptom ?), or is there an error in my patch ?
This has nothing to do with your tone stage. It's because of the passband ripple in the Chebychev filters. The IEM Chebychev filters have a 1 dB ripple, though I don't actually know if that means +/- 1 dB or +/- .5 dB. Either way, it's creating a boost at some frequencies, and pushing the output down by 1 dB should keep it below [-1, 1]. This could also be contributing to the highs, as the ripple is typically more pronounced near the cutoff frequency.
- is my 'signal policy' perfectible ? I want the output signal never to clip, so I multiply the output by 0.4 in such a way that when Tone and Dist are full right but Level is medium the signal never clips.
The output from [tanh~] will never clip, so as long as you make up for the ripple and don't boost the second BJT stage, you should be fine.
Just one more thing to add for now, and that is you're doing too much in the upsampled portion. The only thing that needs to be in there is the non-linear function ([tanh~]) and the anti-aliasing filters. Everything else is linear and doesn't benefit from upsampling, so it's just creating more computational load. So it should look more like this:
[*~ 100]
|
[DS1-bjt_stage~ 1]
|
[DS1-opamp_gain~]
|
[*~ 8]
|
[pd upsample]
|
[DS1-tone_stage~]
|
[DS1-bjt_stage~ 1]
|
[*~ .891] <-- 1 dB cut
And [pd upsample] should look like this:
[inlet~]
|
[lp10_cheb~ 18000] [block~ 64 1 8]
|
[tanh~]
|
[lp10_cheb~ 18000]
|
[outlet~]
Okay, that turned out to be more words than I expected. But we're getting into DETAILS here! Again, nice work, nau.