package synthetic import ( "fmt" "github.com/uopi/uopi/internal/dsp" ) // floatParam extracts a float64 from params; returns 0 if missing or wrong type. func floatParam(params map[string]any, key string) float64 { if params == nil { return 0 } v, ok := params[key] if !ok { return 0 } f, ok := v.(float64) if !ok { return 0 } return f } // stringParam extracts a string from params; returns "" if missing or wrong type. func stringParam(params map[string]any, key string) string { if params == nil { return "" } v, ok := params[key] if !ok { return "" } s, ok := v.(string) if !ok { return "" } return s } // BuildPipeline converts a []NodeDef (from JSON) into a []dsp.Node ready for // execution. JSON numbers are float64, so all numeric params are handled as // float64 regardless of the final type needed. func BuildPipeline(defs []NodeDef) ([]dsp.Node, error) { nodes := make([]dsp.Node, 0, len(defs)) for i, d := range defs { n, err := buildNode(d) if err != nil { return nil, fmt.Errorf("pipeline node %d (%q): %w", i, d.Type, err) } nodes = append(nodes, n) } return nodes, nil } func buildNode(d NodeDef) (dsp.Node, error) { p := d.Params switch d.Type { case "gain": return &dsp.GainNode{Gain: floatParam(p, "gain")}, nil case "offset": return &dsp.OffsetNode{Offset: floatParam(p, "offset")}, nil case "add": return &dsp.AddNode{}, nil case "subtract": return &dsp.SubtractNode{}, nil case "multiply": return &dsp.MultiplyNode{}, nil case "divide": return &dsp.DivideNode{}, nil case "moving_average": return &dsp.MovingAverageNode{Window: max(1, int(floatParam(p, "window")))}, nil case "rms": return &dsp.RMSNode{Window: max(1, int(floatParam(p, "window")))}, nil case "derivative": return &dsp.DerivativeNode{}, nil case "clamp": return &dsp.ClampNode{ Min: floatParam(p, "min"), Max: floatParam(p, "max"), }, nil case "threshold": return &dsp.ThresholdNode{ Threshold: floatParam(p, "threshold"), High: floatParam(p, "high"), Low: floatParam(p, "low"), }, nil case "expr": return &dsp.ExprNode{Expr: stringParam(p, "expr")}, nil case "lua": return &dsp.LuaNode{Script: stringParam(p, "script")}, nil default: return nil, fmt.Errorf("unknown node type %q", d.Type) } }