-
Notifications
You must be signed in to change notification settings - Fork 89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ADPCM Loop Optimizations #105
ADPCM Loop Optimizations #105
Conversation
The extracted children can refer to their parent typed array views and buffer to keep from needing to make memory copies that take a lot of time to create and memory to use. As well some time can be saved by using the same Uint8Array for reading Uint8 values and strings.
The number of samples in the ADPCM can be known once the data chunk is extracted and the block size is known. From there the audio buffer can be created and its channel data passed to the decompress method. A lot of time is saved by writing to the channel data directly instead of writing to one array, copying that to another array, and then finally copying to the channel data. A surprising amount of time is saved by using one getChannelData call instead of calling to store each sample.
There are 1424 possible deltas given 89 steps and 16 codes. We can quickly compute those and reuse them to save time. Knowing the exact size of the waveform we can re-author the decompression loop to take advantage of that. We can place the block header decompression first in the outer while loop and then place an inner loop with the 2 samples per block decompression unwrapped. The first sample reads from the stream and the second uses the other 4 bits.
83b474c
to
80820c6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Just waitin' on Travis.
if (_deltaTable === null) { | ||
const NUM_STEPS = STEP_TABLE.length; | ||
const NUM_INDICES = INDEX_TABLE.length; | ||
_deltaTable = new Array(NUM_STEPS * NUM_INDICES).fill(0); |
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
constructor ( | ||
arrayBuffer, start = 0, end = arrayBuffer.byteLength, | ||
{ | ||
_uint8View = new Uint8Array(arrayBuffer) |
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
@ericrosenbaum, @mzgoddard, build is passing now. |
Depends on #104
Optimize ADPCMSoundDecoder to make the best use of the decompression loop knowing the full size of the waveform.
We can precompute and reuse the 1424 possible deltas given 89 steps and 16 codes. Using those can save a lot of time compared to the 10000s to millions of samples some files will have.
Knowing the full size of the waveform we can unwrap the current loop to specifically place the block header decompression and then loop over remaining block samples. Unwrapping the if/else block we can quick decode each byte into its two samples.
Performance
Memory
This doesn't really have an effect on memory.