Files
2026-04-17 14:55:32 -04:00

181 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
source_files:
- Common/DTS.Common/Classes/DSP/ScalerAttribute.cs
- Common/DTS.Common/Classes/DSP/DASRestriction.cs
- Common/DTS.Common/Classes/DSP/DSPFilterRestriction.cs
- Common/DTS.Common/Classes/DSP/IStreamingFilterProfile.cs
- Common/DTS.Common/Classes/DSP/StreamingFilterConverter.cs
- Common/DTS.Common/Classes/DSP/DSPFilterConverter.cs
- Common/DTS.Common/Classes/DSP/StreamingFilterProfile.cs
- Common/DTS.Common/Classes/DSP/DSPFilterCollection.cs
- Common/DTS.Common/Classes/DSP/StreamingFilterProfileCollection.cs
- Common/DTS.Common/Classes/DSP/DSPFilterType.cs
generated_at: "2026-04-16T03:17:48.073484+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "5b580a9c32ce9826"
---
# DSP Module Documentation
## 1. Purpose
This module provides data structures and utilities for configuring and managing digital signal processing (DSP) filters in the DTS system. It defines filter profiles (`StreamingFilterProfile`, `DSPFilterType`), their restrictions based on hardware type and protocol version (`DASRestriction`, `DSPFilterRestriction`), and collections (`StreamingFilterProfileCollection`, `DSPFilterCollection`) that load filter configurations from XML files. It also includes type converters (`StreamingFilterConverter`, `DSPFilterConverter`) for UI integration (e.g., property grids) and supports both legacy and ratio-based filter rate calculations. The module centralizes DSP filter metadata and logic, enabling consistent filter selection and configuration across the application.
## 2. Public Interface
### Classes
- **`ScalerAttribute`**
```csharp
[AttributeUsage(AttributeTargets.Enum | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Field, AllowMultiple = false)]
public class ScalerAttribute : Attribute
```
- **`Scaler`** (`double`): Stores a scaling factor (e.g., for computing filter cutoff frequencies from sample rates).
- **Constructor `ScalerAttribute(double d)`**: Initializes the `Scaler` property with the provided value.
- **`DASRestriction`**
```csharp
public class DASRestriction
```
- **`DASType`** (`string`): Hardware type string (e.g., `"SLICE6_AIR"`). An empty string means *all* DAS types match.
- **`ProtocolVersion`** (`int`): Minimum required protocol version. Values ≤ 0 mean *all* protocol versions match.
- **Constructors**:
- `DASRestriction()`: Sets `DASType = ""`, `ProtocolVersion = -1`.
- `DASRestriction(string dasType, int protocolVersion)`: Initializes with specified values.
- **`DSPFilterRestriction`**
```csharp
public class DSPFilterRestriction
```
Identical structure and behavior to `DASRestriction` (same properties and constructors). *Note: No functional difference is evident in the source; likely a duplicate or legacy artifact.*
- **`StreamingFilterProfile`**
```csharp
public class StreamingFilterProfile : IStreamingFilterProfile
```
- **`Ratio`** (`double`): Scaling factor for computing filter cutoff frequency from sample rate (`fc = sps / Ratio`). `double.NaN` indicates no ratio-based calculation.
- **`DisplayString`** (`string`), **`DescriptionString`** (`string`), **`EnumValue`** (`int`): Metadata for UI and firmware communication.
- **`Restrictions`** (`DASRestriction[]`): Array of hardware/protocol restrictions.
- **Constructors**:
- `StreamingFilterProfile()`: Default.
- `StreamingFilterProfile(StreamingFilterProfileCollection.DefaultProfiles profile, DASRestriction[] restrictions)`: Initializes from a `DefaultProfiles` enum value and restrictions.
- `StreamingFilterProfile(string display, string description, int enumValue, double ratio, DASRestriction[] restrictions)`: Direct initialization.
- **`GetDSPFilterRate(double sps, string hwType)`** (`double`): Returns the filter cutoff frequency (fc) for given sample rate (`sps`) and hardware type (`hwType`). Returns `double.NaN` if filtering is unsupported or restrictions not met.
- For `SLICE6_AIR` with `sps ≥ 20480`, returns `double.NaN`.
- For other cases, uses `DSPFilterType.Get6PButterWorthLegacyTable()` and `Ratio` to compute `fc = sps / Ratio` if `Ratio` is valid.
- **`ToString()`**: Returns `DisplayString`.
- **`DSPFilterType`**
```csharp
public class DSPFilterType : IStreamingFilterProfile
```
- **`Ratio`**, **`EnumValue`**, **`DisplayString`**, **`DescriptionString`**, **`Restrictions`**: Same semantics as `StreamingFilterProfile`.
- **Constructors**:
- `DSPFilterType()`: Default.
- `DSPFilterType(DSPFilterCollection.DSPFilterDefaults filter, DASRestriction[] restrictions)`: Initializes from `DSPFilterDefaults` enum value.
- `DSPFilterType(int enumValue, string displayString, string descriptionString, double ratio, DASRestriction[] restrictions)`: Direct initialization.
- **`GetDSPFilterRate(double sps, string hwType)`** (`double`): Returns `fc` for the legacy 6-pole Butterworth filter (`EnumValue == 13`). Returns `double.NaN` if `EnumValue ≠ 13`, restrictions not met, or hardware unsupported.
- **Static Methods**:
- **`Get6PButterWorthLegacyTable()`** (`Tuple<int, int>[]`): Returns the breakpoint table: `[(8000,1280), (5000,610), (2000,366), (1000,120), (500,120), (200,50), (80,15)]`.
- **`GetLegacytDSPFilterRate(double sps, string hwType)`** (`double`): Returns `fc` for legacy Butterworth filter using the breakpoint table. Returns `double.NaN` for `SLICE6_AIR` with `sps ≥ 20480`.
- **Constants**:
- **`S6A_CAP`** (`int = 20480`): Sample rate threshold above which `SLICE6_AIR` falls back to analog filtering.
- **`StreamingFilterProfileCollection`**
```csharp
public class StreamingFilterProfileCollection : Collection<StreamingFilterProfile>
```
- **`GetCollection()`** (`static`): Singleton accessor. Loads from `"StreamingFilterProfiles.xml"` (creates default file if missing).
- **`GetStreamingFilterProfile(string s)`** (`StreamingFilterProfile`): Returns the profile with matching `DisplayString`, or the default (`EnumValue == 13`), or the first item.
- **`DefaultProfiles`** enum: Defines profiles with `ScalerAttribute` for `Ratio`:
- `Default` (`13`): `Ratio = NaN` (legacy).
- `Profile7` (`7`): `Ratio = 4`.
- `Profile8` (`8`): `Ratio = 6.4`.
- `Profile9` (`9`): `Ratio = 8`.
- `Profile10` (`10`): `Ratio = 10`.
- **`DEFAULT_VALUE`** (`int = 13`): Enum value for the default profile.
- **`DSPFilterCollection`**
```csharp
public class DSPFilterCollection : Collection<DSPFilterType>
```
- **`GetDSPFilterCollection()`** (`static`): Singleton accessor. Loads from `"DSPFilters.xml"` (creates default file if missing).
- **`GetFilter(string s)`** (`DSPFilterType`): Returns filter with matching `DisplayString`, or `EnumValue == 0` (None), or first item.
- **`DSPFilterDefaults`** enum: Defines filter types with `ScalerAttribute` (`Ratio = NaN` for all):
- `None` (`0`).
- `Butterworth` (`13`).
- `FIR` (`14`).
- **Constants**:
- **`BUTTERWORTH`** (`int = 13`), **`FIR45TAP`** (`int = 14`), **`NONE`** (`int = 0`).
### Converters
- **`StreamingFilterConverter`**
```csharp
public class StreamingFilterConverter : ArrayConverter
```
- **`Values`** (`StreamingFilterProfile[]`): Cached array of profiles from `StreamingFilterProfileCollection`.
- **`CanConvertFrom`**, **`ConvertFrom`**: Supports conversion from `string` (matches `DisplayString`).
- **`GetStandardValuesSupported`**, **`GetStandardValuesExclusive`**, **`GetStandardValues`**: Provides standard values (entire collection) for property grids.
- **`DSPFilterConverter`**
```csharp
public class DSPFilterConverter : ArrayConverter
```
- **`Values`** (`DSPFilterType[]`): Cached array of filters from `DSPFilterCollection`.
- **`CanConvertFrom`**, **`ConvertFrom`**: Supports conversion from `string` (matches `DisplayString`).
- **`GetStandardValuesSupported`**, **`GetStandardValuesExclusive`**, **`GetStandardValues`**: Provides standard values (entire collection) for property grids.
### Interfaces
- **`IStreamingFilterProfile`**
```csharp
public interface IStreamingFilterProfile
```
Defines contract for filter profiles:
- **`EnumValue`** (`int`), **`DisplayString`** (`string`), **`DescriptionString`** (`string`), **`Restrictions`** (`DASRestriction[]`), **`Ratio`** (`double`).
- **`GetDSPFilterRate(double sps, string hwType)`** (`double`): Compute filter cutoff frequency.
## 3. Invariants
- **Singleton Collections**: `StreamingFilterProfileCollection.GetCollection()` and `DSPFilterCollection.GetDSPFilterCollection()` are thread-safe singletons (using `lock` and lazy initialization). The XML files (`StreamingFilterProfiles.xml`, `DSPFilters.xml`) are created with defaults if missing.
- **Restriction Matching**: A restriction matches if `DASType` is empty (any hardware) or equals `hwType`, and `ProtocolVersion ≤ 0` (any version) or `ProtocolVersion` matches the DASs version (exact match implied, though version comparison logic is not in this module).
- **Filter Rate Calculation**:
- `StreamingFilterProfile.GetDSPFilterRate` uses `Ratio` for ratio-based filters (`Ratio > 0`) and falls back to legacy table lookup (`DSPFilterType.GetLegacytDSPFilterRate`) only if `EnumValue == DEFAULT_VALUE` (13) and `Ratio = NaN`.
- `DSPFilterType.GetDSPFilterRate` only supports the Butterworth filter (`EnumValue == 13`).
- `SLICE6_AIR` with `sps ≥ 20480` is unsupported for digital filtering (returns `double.NaN`).
- **Enum Values**: `DEFAULT_VALUE = 13` (for `StreamingFilterProfileCollection.DefaultProfiles.Default`) and `BUTTERWORTH = 13` (for `DSPFilterCollection.DSPFilterDefaults.Butterworth`) are hardcoded constants.
## 4. Dependencies
### Internal Dependencies
- **`DTS.Common.Enums.Hardware`**: Used for `HardwareTypes` (e.g., `SLICE6_AIR`, `SLICE6_AIR_BR`, `SLICE6_AIR_TC`).
- **`System.ComponentModel.DataAnnotations`**: Used for `DisplayAttribute` (to extract `Name`/`Description` from enum fields).
- **`System.Xml.Serialization`**: Used for XML serialization/deserialization of collections.
- **`System.Collections.ObjectModel`**: Base for `Collection<T>`.
### External Dependencies
- **XML Files**:
- `StreamingFilterProfiles.xml`: Default location for streaming filter profiles.
- `DSPFilters.xml`: Default location for DSP filter types.
*(Both are created on first access if missing.)*
- **UI Frameworks**: `StreamingFilterConverter` and `DSPFilterConverter` depend on `System.ComponentModel` (e.g., `ITypeDescriptorContext`, `StandardValuesCollection`) for property grid integration.
### Inferred Usage
- `StreamingFilterProfileCollection` and `DSPFilterCollection` are used by converters and likely by UI components (e.g., dropdowns for filter selection).
- `ScalerAttribute` is applied to enums in `StreamingFilterProfileCollection.DefaultProfiles` and `DSPFilterCollection.DSPFilterDefaults` to store scaling factors.
## 5. Gotchas
- **Duplicate Classes**: `DASRestriction` and `DSPFilterRestriction` are identical in structure and behavior. The codebase does not clarify if they serve distinct purposes or are redundant.
- **`Ratio = NaN` Semantics**: In `StreamingFilterProfile`, `Ratio = NaN` triggers legacy filter rate calculation (via `DSPFilterType.GetLegacytDSPFilterRate`), but only if `EnumValue == DEFAULT_VALUE` (13). This is not obvious from the method name or documentation.
- **`GetDSPFilterRate` Inconsistency**:
- `StreamingFilterProfile.GetDSPFilterRate` uses `Ratio` for ratio-based filters.
- `DSPFilterType.GetDSPFilterRate` *only* supports Butterworth (`EnumValue == 13`) and ignores `Ratio`.
This implies `StreamingFilterProfile` is for flexible profiles, while `DSPFilterType` is for legacy filter types.
- **Hardware-Specific Logic**: `SLICE6_AIR` has a special case (`sps ≥ 20480` → `double.NaN`) in both `StreamingFilterProfile` and `DSPFilterType`. This is hardcoded and not configurable via XML.
- **Protocol Version Matching**: `ProtocolVersion` is stored but never compared against a DASs actual version in the provided code. Matching logic is assumed but not implemented here.
- **Case Sensitivity**: `GetFilter`/`GetStreamingFilterProfile` use `DisplayString == s` (case-sensitive). UI components may need to handle case normalization.
- **Thread Safety**: Singletons use `lock` for initialization, but cached arrays (`Values` in converters) are not reloaded if XML files change at runtime.
- **Typo**: Method `GetLegacytDSPFilterRate` (missing 'h' in "Legacy") and `S6A_CAP` (capitalization inconsistency with `SLICE6_AIR` enum values).