{"id":25,"date":"2026-09-16T16:38:42","date_gmt":"2026-09-16T16:38:42","guid":{"rendered":"https:\/\/parkr.dev\/?p=25"},"modified":"2026-09-16T16:44:19","modified_gmt":"2026-09-16T16:44:19","slug":"why-kahustack-dsp-is-building-audio-analysis-primitives","status":"publish","type":"post","link":"https:\/\/parkr.dev\/?p=25","title":{"rendered":"Why KahuStack DSP Is Building Audio Analysis Primitives"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">A meter is usually treated as an application: feed it audio, draw some bars, and report a number.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For KahuStack DSP, we want to work one level deeper.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Our analysis of Airwindows Meter exposed an especially useful idea: interesting information about audio can be found not only in loudness or frequency balance, but in the&nbsp;<strong>pattern and distribution of waveform events over time<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Meter reaches that idea with a few surprisingly simple observations. It watches sample peaks, waveform slew, zero-crossing intervals, and sustained near-ceiling activity. It then tracks how those observations move through different ranges over time.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We do not want to clone that plugin. We want to extract the reusable ideas underneath it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That means creating a new family of Rust audio-analysis primitives.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Small measurements, reusable everywhere<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The first layer contains extremely small measurements:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Sample peak<\/strong>\u00a0\u2014 the largest absolute sample magnitude.<\/li>\n\n\n\n<li><strong>Sample delta<\/strong>\u00a0\u2014 how much one sample changes from the previous sample.<\/li>\n\n\n\n<li><strong>Slew rate<\/strong>\u00a0\u2014 sample-rate-normalized waveform slope.<\/li>\n\n\n\n<li><strong>Zero crossings<\/strong>\u00a0\u2014 where the waveform changes sign.<\/li>\n\n\n\n<li><strong>Crossing interval<\/strong>\u00a0\u2014 how much time passes between zero crossings.<\/li>\n\n\n\n<li><strong>Crossing rate<\/strong>\u00a0\u2014 how often crossings occur.<\/li>\n\n\n\n<li><strong>Clip runs<\/strong>\u00a0\u2014 how long a signal remains at or near a ceiling.<\/li>\n\n\n\n<li><strong>Running extrema<\/strong>\u00a0\u2014 reusable minimum and maximum accumulation.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">None of these primitives knows what a mix is supposed to sound like.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">They simply measure the signal.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That distinction matters because the same&nbsp;<code>SlewRate<\/code>&nbsp;primitive can help characterize a snare transient, detect a click, evaluate distortion, inspect an oscillator, analyze aliasing, or contribute to a future mastering meter.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Time is a separate concern<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Measurements become more useful when they are aggregated over meaningful time windows.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Instead of hard-coding a particular number of samples, KahuStack DSP will use time-based analysis windows that remain consistent at 44.1, 48, 96, or 192 kHz.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Those windows can produce reusable frames containing measurements such as:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>peak\nmaximum slew\nmaximum crossing interval\ncrossing rate\nclip statistics\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The audio engine produces the measurements. The user interface merely displays them.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That makes the system deterministic and keeps analysis independent from screen refresh rate.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Distribution matters as much as magnitude<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This is the part we find most interesting.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A track that reaches the same peak over and over is different from a track whose meaningful peaks occur across a wide range of intensities.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Two signals may have the same maximum slew but very different patterns of transient activity.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Two bass-heavy signals may have similar low-frequency energy while producing very different zero-crossing behavior.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So the second major part of the library will deal with&nbsp;<strong>distributions<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Our initial inventory includes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>fixed histograms<\/li>\n\n\n\n<li>decaying or &#8220;leaky&#8221; histograms<\/li>\n\n\n\n<li>distribution coverage<\/li>\n\n\n\n<li>distribution spread<\/li>\n\n\n\n<li>normalized entropy<\/li>\n\n\n\n<li>event density<\/li>\n\n\n\n<li>configurable bin weighting<\/li>\n\n\n\n<li>joint two-dimensional histograms<\/li>\n\n\n\n<li>feature-balance measurements<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">These primitives let us ask better questions.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Not just:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">How high did this value get?<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">but:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">How frequently did meaningful events happen?<\/p>\n<\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">How broadly were those events distributed?<\/p>\n<\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">How varied was the recent behavior?<\/p>\n<\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Which combinations of features occurred together?<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Entropy gives us a useful new measurement<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">One especially useful addition is distribution entropy.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If nearly every observed event falls into one narrow range, entropy is low.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If events are spread broadly across many meaningful ranges, entropy rises.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That gives us a mathematically understandable measurement for something audio engineers often hear but do not have a convenient meter for:&nbsp;<strong>event diversity<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example, a heavily limited signal may remain loud while losing variation in transient amplitude. A peak meter still reports a healthy-looking level. An event-distribution analyzer can show that the signal has become much more uniform.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That does not make one result automatically better than another, but it gives the engineer new information.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The primitive inventory<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The first KahuStack DSP analysis inventory is intentionally broad.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Measurement primitives<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>SampleDeltaTracker\nSamplePeak\nRunningMax\nRunningMin\nMinMax\nSlewRate\nZeroCrossingDetector\nCrossingIntervalTracker\nCrossingRate\nClipRunDetector\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Time and aggregation<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>WindowScheduler\nWindowAccumulator\nWindowedPeak\nWindowedMaxSlew\nWindowedCrossingRate\nWindowedMaxCrossingInterval\nWindowedClipStatistics\nSignalActivityFrame\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Distribution analysis<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>FixedHistogram\nLeakyHistogram\nHistogramDecay\nBinWeighting\nDistributionCoverage\nDistributionEntropy\nDistributionSpread\nJointHistogram\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Derived analysis<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>EventDensity\nFeatureBalance\nActivityDimension\nClipActivity\nActivityProfile\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Each piece is deliberately narrow.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The final tools become compositions of these pieces rather than giant special-purpose analyzers.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Why Rust is a good fit<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">These measurements are ideal Rust DSP components.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">They can use:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>fixed-size storage<\/li>\n\n\n\n<li>const generics<\/li>\n\n\n\n<li>strongly typed units<\/li>\n\n\n\n<li>explicit state<\/li>\n\n\n\n<li>deterministic processing<\/li>\n\n\n\n<li>allocation-free audio paths<\/li>\n\n\n\n<li>compile-time channel and histogram sizes where useful<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">A histogram can be:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>FixedHistogram::&lt;16&gt;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">and a two-dimensional feature map can be:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>JointHistogram::&lt;16, 16&gt;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">with bounded memory and no allocation in the audio thread.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The same implementation can serve native plugins, command-line analysis, KahuStack applications, and WebAssembly.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Why strongly typed units matter<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Audio analysis mixes many quantities that look like ordinary floating-point numbers but are not interchangeable.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A peak amplitude is not a duration.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A crossing interval is not a frequency.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A sample delta is not the same measurement as a sample-rate-normalized slew rate.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So the library will continue KahuStack DSP&#8217;s strongly typed approach with concepts such as:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>LinearAmplitude\nDbFs\nSampleRate\nSampleCount\nSeconds\nSampleDelta\nAmplitudePerSecond\nCrossingInterval\nCrossingRate\nClipDuration\nNormalized\nOccupancy\nAnalysisTimestamp\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The type system becomes part of the correctness model.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What this enables<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The immediate inspiration is metering, but the long-term value is much larger.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">These primitives can support:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>compressor development<\/li>\n\n\n\n<li>limiter testing<\/li>\n\n\n\n<li>clipper analysis<\/li>\n\n\n\n<li>transient processing<\/li>\n\n\n\n<li>saturation characterization<\/li>\n\n\n\n<li>oscillator QA<\/li>\n\n\n\n<li>anti-aliasing research<\/li>\n\n\n\n<li>click and discontinuity detection<\/li>\n\n\n\n<li>reference matching<\/li>\n\n\n\n<li>waveform rendering<\/li>\n\n\n\n<li>MANA synth telemetry<\/li>\n\n\n\n<li>Voxaliber analysis<\/li>\n\n\n\n<li>automated DSP tests<\/li>\n\n\n\n<li>WASM audio testbenches<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">That is why we are building the primitives first.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A future KahuStack activity meter may eventually combine amplitude activity, transient activity, low-frequency temporal activity, and clipping behavior into a single visual analysis tool.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">But that meter will be only one consumer of the library.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The real product is the analysis foundation underneath it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The larger goal<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">KahuStack DSP is increasingly becoming a library of reusable DSP ideas rather than a collection of isolated effects.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Audio analysis should follow the same principle.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Instead of embedding measurement logic inside one compressor, one synth, one waveform display, and one meter, we can establish common primitives with well-defined units, permanent tests, and predictable behavior.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Then new tools can be built by composition.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That gives us a cleaner codebase, better testability, more consistent measurements, easier WASM integration, and a much stronger foundation for future audio research.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The core idea is simple:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Measure the signal once, define the measurement clearly, and make it reusable everywhere.<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A meter is usually treated as an application: feed it audio, draw some bars, and report a number. For KahuStack DSP, we want to work one level deeper. Our analysis of Airwindows Meter exposed an especially useful idea: interesting information about audio can be found not only in loudness or frequency balance, but in the&nbsp;pattern [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-25","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/parkr.dev\/index.php?rest_route=\/wp\/v2\/posts\/25","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/parkr.dev\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/parkr.dev\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/parkr.dev\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/parkr.dev\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=25"}],"version-history":[{"count":3,"href":"https:\/\/parkr.dev\/index.php?rest_route=\/wp\/v2\/posts\/25\/revisions"}],"predecessor-version":[{"id":27,"href":"https:\/\/parkr.dev\/index.php?rest_route=\/wp\/v2\/posts\/25\/revisions\/27"}],"wp:attachment":[{"href":"https:\/\/parkr.dev\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=25"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/parkr.dev\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=25"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/parkr.dev\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=25"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}