Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
"""
B-ASIC signal flow graph generators.
This module contains a number of functions generating SFGs for specific functions.
"""
from typing import Dict, Optional, Sequence, Union
import numpy as np
from b_asic.core_operations import Name, SymmetricTwoportAdaptor
from b_asic.port import InputPort, OutputPort
from b_asic.signal import Signal
from b_asic.signal_flow_graph import SFG
from b_asic.special_operations import Delay, Input, Output
def wdf_allpass(
coefficients: Sequence[float],
input_op: Optional[Union[Input, Signal, InputPort]] = None,
output: Optional[Union[Output, Signal, OutputPort]] = None,
name: Optional[str] = None,
latency: Optional[int] = None,
latency_offsets: Optional[Dict[str, int]] = None,
execution_time: Optional[int] = None,
) -> SFG:
"""
Generate a signal flow graph of a WDF allpass section based on symmetric two-port adaptors.
Parameters
----------
coefficients : 1D-array
Coefficients to use for the allpass section
input_op : Input, optional
The Input to connect the SFG to. If not provided, one will be generated.
output : Output, optional
The Output to connect the SFG to. If not provided, one will be generated.
name : Name, optional
The name of the SFG. If None, "WDF allpass section".
latency : int, optional
Latency of the symmetric two-port adaptors.
latency_offsets : optional
Latency offsets of the symmetric two-port adaptors.
execution_time : int, optional
Execution time of the symmetric two-port adaptors.
Returns
-------
Signal flow graph
"""
np.asarray(coefficients)
coefficients = np.squeeze(coefficients)
if coefficients.ndim != 1:
raise TypeError("coefficients must be a 1D-array")
if input_op is None:
input_op = Input()
if output is None:
output = Output()
if name is None:
name = "WDF allpass section"
order = len(coefficients)
odd_order = order % 2
if odd_order:
# First-order section
coeff = coefficients[0]
adaptor0 = SymmetricTwoportAdaptor(
coeff,
input_op,
latency=latency,
latency_offsets=latency_offsets,
execution_time=execution_time,
)
signal_out = Signal(adaptor0.output(0))
delay = Delay(adaptor0.output(1))
Signal(delay, adaptor0.input(1))
else:
signal_out = Signal(input_op)
# Second-order sections
sos_count = (order - 1) // 2 if odd_order else order // 2
offset1, offset2 = (1, 2) if odd_order else (0, 1)
for n in range(sos_count):
adaptor1 = SymmetricTwoportAdaptor(
coefficients[2 * n + offset1],
signal_out,
latency=latency,
latency_offsets=latency_offsets,
execution_time=execution_time,
)
# Signal(prev_adaptor., adaptor1.input(0), name="Previous-stage to next")
delay1 = Delay(adaptor1.output(1))
delay2 = Delay()
adaptor2 = SymmetricTwoportAdaptor(
coefficients[2 * n + offset2],
delay1,
delay2,
latency=latency,
latency_offsets=latency_offsets,
execution_time=execution_time,
)
Signal(adaptor2.output(1), adaptor1.input(1))
Signal(adaptor2.output(0), delay2)
signal_out = Signal(adaptor1.output(0))
output << signal_out
return SFG([input_op], [output], name=Name(name))