Skip to content

Python Delay Line API

Dual-write circular delay line for complex128 samples, backed by dp_delay_cf64_t. Designed for polyphase FIR resamplers that need a contiguous window of history with no modulo arithmetic.

Source: src/doppler/delay/__init__.py


How it works

The buffer holds 2 × capacity samples, where capacity is the smallest power of two ≥ num_taps. Every push writes the new sample at buf[head] and buf[head + capacity]. ptr() always returns a contiguous num_taps-window — no wrap-around branch needed by the FIR kernel.

Newest sample is at index 0; oldest at index num_taps - 1.


Examples

Basic push and read-back

from doppler.delay import DelayCf64
import numpy as np

dl = DelayCf64(4)           # 4-tap window

dl.push(1+2j)
dl.push(3+4j)

window = dl.ptr()           # array([3+4j, 1+2j, 0+0j, 0+0j])
print(window[0])            # newest: 3+4j

Polyphase FIR inner loop

from doppler.delay import DelayCf64
import numpy as np

num_taps = 19
dl = DelayCf64(num_taps)

taps = np.ones(num_taps, dtype=np.float32) / num_taps   # example taps

for sample in iq_stream:
    dl.push(sample)
    window = dl.ptr()                       # contiguous num_taps window
    out = np.dot(window, taps.astype(np.complex128))

Push and read in one call

push_ptr pushes a sample and returns the updated window in one round-trip to C, saving one Python call per sample.

for sample in iq_stream:
    window = dl.push_ptr(sample)
    out = np.dot(window, taps)

Context manager

with DelayCf64(32) as dl:
    for s in stream:
        dl.push(s)
    # dl released on exit

DelayCf64

Dual-write circular delay line for complex128 samples.

Wraps dp_delay_cf64_t. Keeps the most-recent num_taps samples in a contiguous window so polyphase FIR kernels can MAC directly without modulo arithmetic.

Buffer size is 2 × capacity, where capacity is the smallest power of two ≥ num_taps. :meth:push writes to both halves; :meth:ptr always returns a contiguous window at the current head. Newest sample is at index 0, oldest at index num_taps - 1.

Parameters:

Name Type Description Default
num_taps int

Window length (number of samples to retain).

required

Examples:

>>> from doppler.delay import DelayCf64
>>> dl = DelayCf64(4)
>>> dl.push(1+2j)
>>> dl.push(3+4j)
>>> dl.ptr()
array([3.+4.j, 1.+2.j, 0.+0.j, 0.+0.j])

num_taps property

num_taps: int

Window length passed at construction.

capacity property

capacity: int

Actual allocated capacity (smallest power-of-two ≥ num_taps).

push

push(x: complex) -> None

Push one complex128 sample into the delay line.

push_ptr

push_ptr(x: complex) -> NDArray[np.complex128]

Push one sample and return the updated window in one call.

write

write(x: NDArray[complex128]) -> None

Push all samples from a complex128 array.

ptr

ptr() -> NDArray[np.complex128]

Return a copy of the current num_taps-sample window.

reset

reset() -> None

Zero all samples in the delay line.

destroy

destroy() -> None

Release C resources explicitly.