Skip to main content

Composable digital signal processing in NumPy.

npDSP is a lightweight Python library for building digital signal processing systems from composable processing blocks.

The core idea is simple: build DSP as a pipeline of blocks and connect them with Python’s >> operator.

import numpy as np
import npdsp

pipeline = npdsp.Add(1) >> npdsp.Multiply(2)

x = np.array([1, 2, 3])
y = pipeline(x)

print(y)
# [4 6 8]

npDSP provides mathematical blocks, FIR and IIR filters, and stateful blocks that can be used naturally in streaming applications.

Features

  • Composable DSP blocks — build processing chains from small, reusable components.

  • ``>>`` pipeline composition — express a DSP chain directly in Python.

  • NumPy-based — process NumPy arrays without introducing a separate signal representation.

  • FIR filters — finite impulse response filtering.

  • IIR filters — infinite impulse response filtering with persistent state.

  • Streaming processing — process successive chunks of samples while stateful blocks retain their state.

  • Mathematical blocks — use mathematical operations as composable DSP blocks.

  • Stateful blocks — blocks can maintain state between calls.

  • Named blocks — name and access blocks within a pipeline.

  • Profiling — inspect processing performance.

Installation

Install from PyPI:

pip install npDSP

Or with uv:

uv add npDSP

Pipelines

The fundamental building block in npDSP is the processing block.

Blocks can be composed with >>:

pipeline = npdsp.Add(1) >> npdsp.Multiply(2) >> some_filter

The resulting pipeline is callable:

output = pipeline(input)

This keeps a DSP system readable: the pipeline definition describes the order in which the signal is processed.

FIR and IIR filters

npDSP includes both FIR and IIR filtering.

Because filters are ordinary npDSP blocks, they can be combined directly with mathematical operations and other processing blocks.

For example:

pipeline = preprocessing >> fir_filter >> iir_filter >> postprocessing

The FIR/IIR case is particularly useful for streaming because the filter’s internal state can persist between successive calls.

Streaming

npDSP is designed to work naturally with streaming data.

Suppose a device continuously provides chunks of samples. You can put an npDSP pipeline directly between the device and whatever consumes the processed signal:

while True:
    samples = streaming_device.get_samples()

    output = pipeline(samples)

    do_something_with(output)

The pipeline does not need to know where the samples came from. Each call processes the next chunk.

For stateful blocks, such as IIR filters, the state is retained between calls:

Streaming device
      │
      │  get_samples()
      ▼
┌─────────────┐
│   samples   │
└──────┬──────┘
       │
       ▼
┌─────────────────────────────┐
│        npDSP pipeline       │
│                             │
│  block → FIR → IIR → block  │
│             │               │
│             └── state ──────┤
└─────────────┬───────────────┘
              │
              ▼
           output
              │
              ▼
       your application
              │
              │
              └─────── repeat

So a stream can be processed incrementally:

while True:
    samples = streaming_device.get_samples()
    output = pipeline(samples)

    # Write to an output device, analyse it,
    # visualise it, encode it, etc.
    consume(output)

The important part is that the pipeline persists across iterations. A stateful block sees the chunks as consecutive parts of the same signal rather than independent signals.

This makes the same DSP components useful for applications such as:

  • real-time audio processing

  • data acquisition

  • sensor processing

  • streaming analysis

  • hardware I/O

  • other applications where samples arrive continuously

Batch processing

The same pipeline can also be used on a complete NumPy array:

output = pipeline(samples)

There is no separate streaming API that you need to learn. Streaming simply means calling the same pipeline repeatedly as new chunks arrive.

Mathematical blocks

Mathematical operations are also available as blocks.

For example:

pipeline = npdsp.Add(1) >> npdsp.Multiply(2)

This allows simple mathematical transformations to be combined with filters and other DSP operations without leaving the pipeline abstraction.

Stateful processing

Some DSP operations need to remember previous samples or previous processing state.

npDSP blocks can be stateful, allowing them to maintain this information between calls.

For example, an IIR filter can be called repeatedly:

while True:
    samples = streaming_device.get_samples()
    output = iir_filter(samples)

    consume(output)

The next call continues from the state established by the previous call.

This is especially important when a signal is split into chunks. Processing each chunk independently would introduce discontinuities at the chunk boundaries; a stateful block can instead carry the required state from one chunk to the next.

Named blocks

Blocks can be given names:

pipeline = npdsp.Add(1, name="offset") >> npdsp.Multiply(2, name="gain")

Named blocks can then be accessed from the pipeline:

gain = pipeline["gain"]

This can be useful when inspecting or working with larger processing chains.

Example

A complete streaming DSP application can be as simple as:

pipeline = preprocessing >> fir_filter >> iir_filter >> postprocessing

while True:
    samples = streaming_device.get_samples()
    output = pipeline(samples)

    output_device.write(output)

The application controls the stream. npDSP handles the processing.

Documentation

Documentation is available at:

https://npdsp.readthedocs.io/

It includes the API reference, concepts, examples, and block documentation.

Development

Clone the repository:

git clone https://github.com/mrhiemstra/npDSP.git
cd npDSP

Install the development environment:

uv sync

Run the tests:

uv run pytest

Build the documentation:

uv run sphinx-build -b html docs/source docs/build/html

Build the package:

uv build

Requirements

See pyproject.toml for the complete dependency specification.

Project status

npDSP is currently in Alpha. The API may change between releases.

License

npDSP is released under the MIT License.

Release files for npdsp 0.0.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for npdsp 0.0.6
File Size Uploaded
npdsp-0.0.6.tar.gz 22.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for npdsp 0.0.6
File Interpreter ABI Platform
npdsp-0.0.6-py3-none-any.whl Python 3 none any Details

Total release size: 55.2 kB

Release files / npdsp-0.0.6.tar.gz

Download URL npdsp-0.0.6.tar.gz
Size 22.9 kB
Tags Source
SHA-256 checksum
How to use checksums
493d39aa3f7bb2c7b0b22421bfa89e8eb9993a6a9ec47a4a7f7d689779000b43
BLAKE2b-256 checksum
How to use checksums
e8f7fa15ed87a9737599e9d79fe5c23c63bb8511642d3cac83963af8822fac51
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 16, 2026.

Transparency log

Release files / npdsp-0.0.6-py3-none-any.whl

Download URL npdsp-0.0.6-py3-none-any.whl
Size 32.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f0763efb3ab8c3ad1ba843bba832446ae2d56be528c49efb54600e7842c59568
BLAKE2b-256 checksum
How to use checksums
dd6237d31867fa30983ffeb12f9b3fa4e4fe194537f90fba9e2ae55c255e1b6b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 16, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.0.6 This release

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page