The Postfish awakens
Mar. 8th, 2004 03:59 amStill very incomplete, but the Postfish is slowly clawing its way out of the primordial ooze and showing glimmers of usefulness. One more feature (nonvolatile settings) and what's already there is ready to use for real work.

Yes, the above version has a few UI bugs that I've fixed and I don't care enough to take a new screenshot.
Slightly unexpectedly, the idea for a reverberation suppressor based on a floating expander actually works very well. This is unexpected only because suppression is a tool I've wanted for a long time and previous attempts to build a suppressor never panned out. This one resulted from a flash of insight and went from mental model to surprisingly effective code with no tweaking. It's nice when something that should work actually does.
Thus, Postfish now includes three novel signal processing techniques that don't seem particularly unobvious, but I've not found reference of anyone else applying them. Perhaps they're widely deployed in the commercial sector and I've not heard of them because the details are still considered trade secrets. On the other hand, these are CPU-intensive approaches, so it's possible the ideas are known but no one had applied them yet as general purpose consumer grade computing equipment is just recently powerful enough to perform the tasks.
Excerpts from the Postfish 'literature' (in progress):
1) The Postfish declipper is a 'build audio from scratch' reconstruction filter. Any section of audio exceeding a configured amplitude threshold is marked 'lost', and the filter builds new audio to fill the gap. In this way, it can be used to repair both digital clipping that occurred during sampling, as well as analog clipping that may have happened at an earlier stage.
The reconstruction filter uses conjugate gradients to solve A'W'WA(x)=A'W'b by minimizing A'b over the set of free x's where 'lost' samples are free x's, 'good' samples are equality-constrained x's, the matrix A implements a Fourier transform, the diagonal matrix W is a weighting function roughly equal to the inverse of the spectral envelope, and the vector b is -WA(x) with the free x's set to zero. The system is solved block-by-block at roughly O([blocksize]^2 log2 [blocksize]), then lapped using a 75% overlap window.
(Much thanks here to Camilla for setting direction to my mathematical thinking. Jack also suggested the A'Ax=A'b form.)
2) The companding code uses a two-stage assymmetric Bessel filter (attacks are handled by a fast filter, decays by a slow filter) to track desired gain changes. Unlike a soft knee, the followers will band-limit the noise from any gain change, not just triggering/release noise. The compander can use very fast attacks without the attack noise dominating the signal (the postfish compander can trigger and clamp full-range in under a millisecond).
Why Bessel filters specifically? Two reasons: They exhibit very little ringing in the time domain and about a half-order of magnitude less roundoff noise from gain compared to other IIR families.
(OK, number 2 isn't quite as impressive as the others, but I'm pleased to have implemented a multiband compander that gets all the details right. Did I mention that it has correct, reliable peak-lookahead behavior? :-)
3) Reverberation displays log amplitude decay with time (linear decay when plotted on a dB scale). In its simplest form, the suppressor follows actual {RMS|peak} amplitude attacks but chooses a slower-than-actual decay, then expands according to the dB distance between the slow and actual decay.
The 'depth' setting is used to limit the expanded distance between actual and slow decay; it's also used to drag the slow decay down with the actual decay once the expansion has hit the depth limit.
Thus, the suppressor can be used to 'dry out' a very 'wet' reverberative track.

Yes, the above version has a few UI bugs that I've fixed and I don't care enough to take a new screenshot.
Slightly unexpectedly, the idea for a reverberation suppressor based on a floating expander actually works very well. This is unexpected only because suppression is a tool I've wanted for a long time and previous attempts to build a suppressor never panned out. This one resulted from a flash of insight and went from mental model to surprisingly effective code with no tweaking. It's nice when something that should work actually does.
Thus, Postfish now includes three novel signal processing techniques that don't seem particularly unobvious, but I've not found reference of anyone else applying them. Perhaps they're widely deployed in the commercial sector and I've not heard of them because the details are still considered trade secrets. On the other hand, these are CPU-intensive approaches, so it's possible the ideas are known but no one had applied them yet as general purpose consumer grade computing equipment is just recently powerful enough to perform the tasks.
Excerpts from the Postfish 'literature' (in progress):
1) The Postfish declipper is a 'build audio from scratch' reconstruction filter. Any section of audio exceeding a configured amplitude threshold is marked 'lost', and the filter builds new audio to fill the gap. In this way, it can be used to repair both digital clipping that occurred during sampling, as well as analog clipping that may have happened at an earlier stage.
The reconstruction filter uses conjugate gradients to solve A'W'WA(x)=A'W'b by minimizing A'b over the set of free x's where 'lost' samples are free x's, 'good' samples are equality-constrained x's, the matrix A implements a Fourier transform, the diagonal matrix W is a weighting function roughly equal to the inverse of the spectral envelope, and the vector b is -WA(x) with the free x's set to zero. The system is solved block-by-block at roughly O([blocksize]^2 log2 [blocksize]), then lapped using a 75% overlap window.
(Much thanks here to Camilla for setting direction to my mathematical thinking. Jack also suggested the A'Ax=A'b form.)
2) The companding code uses a two-stage assymmetric Bessel filter (attacks are handled by a fast filter, decays by a slow filter) to track desired gain changes. Unlike a soft knee, the followers will band-limit the noise from any gain change, not just triggering/release noise. The compander can use very fast attacks without the attack noise dominating the signal (the postfish compander can trigger and clamp full-range in under a millisecond).
Why Bessel filters specifically? Two reasons: They exhibit very little ringing in the time domain and about a half-order of magnitude less roundoff noise from gain compared to other IIR families.
(OK, number 2 isn't quite as impressive as the others, but I'm pleased to have implemented a multiband compander that gets all the details right. Did I mention that it has correct, reliable peak-lookahead behavior? :-)
3) Reverberation displays log amplitude decay with time (linear decay when plotted on a dB scale). In its simplest form, the suppressor follows actual {RMS|peak} amplitude attacks but chooses a slower-than-actual decay, then expands according to the dB distance between the slow and actual decay.
The 'depth' setting is used to limit the expanded distance between actual and slow decay; it's also used to drag the slow decay down with the actual decay once the expansion has hit the depth limit.
Thus, the suppressor can be used to 'dry out' a very 'wet' reverberative track.