from __future__ import annotations

import mlx.core as mx


def asarray(x, dtype=mx.float32) -> mx.array:
    return mx.array(x, dtype=dtype)


def normalize_peak(x: mx.array, eps: float = 1e-8) -> mx.array:
    signal = x.astype(mx.float32)
    peak = mx.max(mx.abs(signal))
    return signal / mx.maximum(peak, mx.array(eps, dtype=mx.float32))


def frame(x: mx.array, frame_length: int, hop_length: int) -> mx.array:
    if frame_length <= 0:
        raise ValueError("frame_length must be positive")
    if hop_length <= 0:
        raise ValueError("hop_length must be positive")
    if x.ndim != 1:
        raise ValueError("x must be a 1D signal")
    if x.shape[0] < frame_length:
        raise ValueError("signal length must be at least frame_length")

    frames = []
    for start in range(0, x.shape[0] - frame_length + 1, hop_length):
        frames.append(x[start : start + frame_length])
    return mx.stack(frames, axis=0)
