dfpwm
no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
| — | dfpwm [2015/06/25 15:36] (current) โ created - external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | DFPWM (Dynamic Filter Pulse Width Modulation) is an audio codec created by Ben " | ||
| + | |||
| + | DFPWM is recognisable, | ||
| + | |||
| + | It depends on the implementation as to what all the parameters are. Testing has shown that 8 bits per sample works better than 16 bits. The codec is not frequency-dependent, | ||
| + | |||
| + | If necessary, you can get away with converting your streams to raw 1-bit, or you could possibly assume a static-strength low-pass filter. | ||
| + | |||
| + | The implementation in Computronics handles streams using Ri=7, Rd=20, 8 bits per sample, and LSB stored first. | ||
| + | |||
| + | ==== Specification ==== | ||
| + | |||
| + | DFPWM, at its simplest, works like this: | ||
| + | Decoding: | ||
| + | smp(t) <- Predictor(bit(t)) | ||
| + | Encoding: | ||
| + | if smp(t) > LastPredictor OR (smp(t) = LastPredictor = 127): | ||
| + | bit(t) <- Predictor(1) | ||
| + | else: | ||
| + | bit(t) <- Predictor(0) | ||
| + | |||
| + | where bit is either LOW or HIGH, and smp โ [LOW, HIGH]. (Apologies for using the โ, it's just that if I try to do "less than or equal", | ||
| + | |||
| + | === State === | ||
| + | |||
| + | Firstly we need to give some types: | ||
| + | * Let q,s be signed integers. | ||
| + | * Let b' be a single bit, either 0 or 1. | ||
| + | * Let Ri,Rd be chosen constant signed integers. ((7,20) is reasonable for 8 bits per sample.) | ||
| + | |||
| + | Then we need to assign meanings: | ||
| + | * Let q be the " | ||
| + | * Let s be the " | ||
| + | * Let Ri be the strength increase. | ||
| + | * Let Rd be the strength decrease. | ||
| + | |||
| + | Ri and Rd are constant (and, until someone discovers a better set of values, will always be 7 and 20 respectively). q and s vary. | ||
| + | |||
| + | From here we can define the predictor. | ||
| + | |||
| + | === Predictor === | ||
| + | |||
| + | To simplify this, we will define this in terms of signed 8-bit samples. | ||
| + | |||
| + | == Input comprehension == | ||
| + | Let b' be the previous instance of b, initialised to 0 to simplify implementation. | ||
| + | |||
| + | Let t be the " | ||
| + | |||
| + | == Charge adjustment == | ||
| + | Let q' be an integer such that | ||
| + | > q' <- q + (s*(t - q) + 128)/256 | ||
| + | |||
| + | If q == q', and q != t, then: | ||
| + | > If t < q: q' <- q' - 1 | ||
| + | > If t > q: q' <- q' + 1 | ||
| + | |||
| + | This is done to ensure that the " | ||
| + | |||
| + | Then set q <- q'. | ||
| + | |||
| + | == Strength adjustment == | ||
| + | Let r,z be integers such that: | ||
| + | > If b == b', then r = Ri, z = 255 | ||
| + | > If b != b', then r = Rd, z = 0 | ||
| + | |||
| + | Let s' be an integer such that | ||
| + | > s' <- s + (r*(z - s) + 128)/256 | ||
| + | |||
| + | If s == s', and s != z, then: | ||
| + | > If z < s: s' <- s' - 1 | ||
| + | > If z > s: s' <- s' + 1 | ||
| + | |||
| + | Then set s <- s'. | ||
| + | |||
| + | === Filtering === | ||
| + | |||
| + | You can do anything here, within reason. These methods are by no means the best way to deal with the noise you get. | ||
| + | |||
| + | These notes are based on the C implementation. | ||
| + | |||
| + | == Antijerk == | ||
| + | |||
| + | If the current target and the previous target are different, output the average of the current and previous results from the predictor; otherwise, output the value directly. | ||
| + | |||
| + | == Low-pass filter == | ||
| + | |||
| + | outQ <- outQ + (expectedOutput - outQ) * 100/256, essentially. | ||
dfpwm.txt ยท Last modified: 2015/06/25 15:36 by 127.0.0.1