Files
zyrarbot/zyrarbot/audio/effects/robot.py
T

47 lines
1.3 KiB
Python

from __future__ import annotations
import array
import math
from zyrarbot.audio.effects.base import AudioEffect
class RobotEffect(AudioEffect):
"""Efekt metalicznego, robotycznego głosu oparty na ring modulation (modulacja pierścieniowa ~65Hz)."""
id = "robot"
name = "Robot"
icon = "bot"
def __init__(self, freq_hz: float = 65.0, mix: float = 0.85) -> None:
self.freq_hz = freq_hz
self.mix = mix
self._phase = 0.0
self._phase_inc = 2.0 * math.pi * freq_hz / 48000.0
def process(self, pcm_data: bytes, sample_rate: int = 48000) -> bytes:
if not pcm_data:
return pcm_data
samples = array.array("h", pcm_data)
phase = self._phase
phase_inc = self._phase_inc
mix = self.mix
dry = 1.0 - mix
for i in range(0, len(samples), 2):
carrier = math.sin(phase)
phase += phase_inc
if phase >= 2.0 * math.pi:
phase -= 2.0 * math.pi
mod_factor = dry + mix * carrier
samples[i] = max(-32768, min(32767, int(samples[i] * mod_factor)))
samples[i + 1] = max(-32768, min(32767, int(samples[i + 1] * mod_factor)))
self._phase = phase
return samples.tobytes()
def reset(self) -> None:
self._phase = 0.0