feat: vẽ nhanh MIDI note
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import os
|
||||
import numpy as np
|
||||
import soundfile as sf
|
||||
import scipy.signal as signal
|
||||
from app.config import settings
|
||||
from app.core.vst_engine import (
|
||||
render_midi_events_to_audio,
|
||||
@@ -11,7 +12,7 @@ from app.core.vst_engine import (
|
||||
|
||||
if HAS_PEDALBOARD:
|
||||
try:
|
||||
from pedalboard import Pedalboard, Gain
|
||||
from pedalboard import Pedalboard, Gain, Chorus, Reverb
|
||||
except Exception:
|
||||
HAS_PEDALBOARD = False
|
||||
|
||||
@@ -222,6 +223,57 @@ class PythonRenderEngine:
|
||||
if mute:
|
||||
continue
|
||||
|
||||
# Apply Track FX (Chorus or Reverb)
|
||||
fx_type = track.get("fx_type")
|
||||
if fx_type == "chorus":
|
||||
if HAS_PEDALBOARD:
|
||||
try:
|
||||
board = Pedalboard([Chorus(rate_hz=1.5, depth=0.25)])
|
||||
track_buffer = board(track_buffer, sample_rate=self.sample_rate)
|
||||
except Exception as e:
|
||||
print(f"[RenderEngine] Pedalboard Chorus failed: {e}")
|
||||
else:
|
||||
# Fallback chorus using simple LFO delay modulation in scipy/numpy
|
||||
try:
|
||||
# 1.5 Hz sine LFO, modulating delay time between 15ms and 25ms (average 20ms)
|
||||
lfo = 0.020 + 0.005 * np.sin(2 * np.pi * 1.5 * np.arange(total_samples) / self.sample_rate)
|
||||
dry = track_buffer * 0.6
|
||||
wet = np.zeros_like(track_buffer)
|
||||
for ch in range(2):
|
||||
indices = np.arange(total_samples) - (lfo * self.sample_rate)
|
||||
indices = np.clip(indices, 0, total_samples - 1).astype(np.int32)
|
||||
wet[ch, :] = track_buffer[ch, indices]
|
||||
track_buffer = dry + wet * 0.5
|
||||
except Exception as e:
|
||||
print(f"[RenderEngine] Fallback Chorus failed: {e}")
|
||||
elif fx_type == "reverb":
|
||||
if HAS_PEDALBOARD:
|
||||
try:
|
||||
board = Pedalboard([Reverb(room_size=0.5, wet_level=0.4, dry_level=0.6)])
|
||||
track_buffer = board(track_buffer, sample_rate=self.sample_rate)
|
||||
except Exception as e:
|
||||
print(f"[RenderEngine] Pedalboard Reverb failed: {e}")
|
||||
else:
|
||||
# Fallback reverb using exponentially decaying noise room impulse response
|
||||
try:
|
||||
# Generate impulse response (decaying noise)
|
||||
len_ir = int(self.sample_rate * 2.0)
|
||||
t_ir = np.arange(len_ir) / self.sample_rate
|
||||
decay = np.exp(-t_ir / 0.5)
|
||||
ir_l = (np.random.rand(len_ir) * 2 - 1) * decay
|
||||
ir_r = (np.random.rand(len_ir) * 2 - 1) * decay
|
||||
|
||||
dry = track_buffer * 0.6
|
||||
wet = np.zeros_like(track_buffer)
|
||||
for ch in range(2):
|
||||
ir = ir_l if ch == 0 else ir_r
|
||||
# Convolve
|
||||
conv = signal.convolve(track_buffer[ch, :], ir, mode='full')[:total_samples]
|
||||
wet[ch, :] = conv
|
||||
track_buffer = dry + wet * 0.4
|
||||
except Exception as e:
|
||||
print(f"[RenderEngine] Fallback Reverb failed: {e}")
|
||||
|
||||
# Process track volume
|
||||
if HAS_PEDALBOARD:
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user