2018-07-13 13:57:00 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
2018-07-14 06:54:14 +00:00
|
|
|
import time
|
2018-07-24 11:28:53 +00:00
|
|
|
from typing import Optional, List
|
2018-07-12 22:27:26 +00:00
|
|
|
|
2018-07-24 11:28:53 +00:00
|
|
|
from ovgenpy import outputs
|
2018-07-28 11:06:27 +00:00
|
|
|
from ovgenpy.channel import Channel, ChannelConfig
|
2018-07-28 23:12:16 +00:00
|
|
|
from ovgenpy.config import register_config
|
2018-07-14 06:54:14 +00:00
|
|
|
from ovgenpy.renderer import MatplotlibRenderer, RendererConfig
|
2018-07-24 11:28:53 +00:00
|
|
|
from ovgenpy.triggers import ITriggerConfig, CorrelationTriggerConfig
|
2018-07-28 11:06:27 +00:00
|
|
|
from ovgenpy.utils import keyword_dataclasses as dc
|
2018-07-27 04:33:40 +00:00
|
|
|
from ovgenpy.utils.keyword_dataclasses import field
|
2018-07-28 11:06:27 +00:00
|
|
|
from ovgenpy.wave import Wave
|
2018-07-12 22:27:26 +00:00
|
|
|
|
2018-07-13 00:48:51 +00:00
|
|
|
|
2018-07-27 04:33:40 +00:00
|
|
|
# cgitb.enable(format='text')
|
|
|
|
|
2018-07-14 06:54:14 +00:00
|
|
|
RENDER_PROFILING = True
|
|
|
|
|
|
|
|
|
2018-07-28 11:06:27 +00:00
|
|
|
@register_config(always_dump='wave_prefix')
|
2018-07-24 11:28:53 +00:00
|
|
|
class Config:
|
2018-07-25 12:25:53 +00:00
|
|
|
master_audio: Optional[str]
|
2018-07-12 22:27:26 +00:00
|
|
|
fps: int
|
2018-07-24 03:38:15 +00:00
|
|
|
|
2018-07-28 11:06:27 +00:00
|
|
|
wav_prefix: str = '' # if wave/glob..., pwd. if folder, folder.
|
|
|
|
channels: List[ChannelConfig] = field(default_factory=list)
|
|
|
|
|
|
|
|
width_ms: int
|
|
|
|
subsampling: int
|
2018-07-24 11:28:53 +00:00
|
|
|
trigger: ITriggerConfig # Maybe overriden per Wave
|
2018-07-24 03:44:24 +00:00
|
|
|
|
|
|
|
amplification: float
|
2018-07-14 03:58:00 +00:00
|
|
|
render: RendererConfig
|
2018-07-24 03:44:24 +00:00
|
|
|
|
2018-07-24 11:28:53 +00:00
|
|
|
outputs: List[outputs.IOutputConfig]
|
2018-07-28 11:06:27 +00:00
|
|
|
create_window: bool = False
|
2018-07-13 02:29:05 +00:00
|
|
|
|
2018-07-17 01:23:31 +00:00
|
|
|
@property
|
2018-07-28 11:06:27 +00:00
|
|
|
def render_width_s(self) -> float:
|
|
|
|
return self.width_ms / 1000
|
2018-07-13 02:29:05 +00:00
|
|
|
|
2018-07-12 22:27:26 +00:00
|
|
|
|
2018-07-13 12:37:22 +00:00
|
|
|
_FPS = 60 # f_s
|
2018-07-12 22:27:26 +00:00
|
|
|
|
2018-07-28 11:06:27 +00:00
|
|
|
def default_config(**kwargs):
|
2018-07-12 22:27:26 +00:00
|
|
|
cfg = Config(
|
2018-07-28 11:06:27 +00:00
|
|
|
master_audio='',
|
|
|
|
fps=_FPS,
|
2018-07-27 04:33:40 +00:00
|
|
|
|
2018-07-28 11:06:27 +00:00
|
|
|
wav_prefix='',
|
|
|
|
channels=[],
|
2018-07-24 03:44:24 +00:00
|
|
|
|
2018-07-28 11:06:27 +00:00
|
|
|
width_ms=25,
|
|
|
|
subsampling=1,
|
2018-07-24 11:28:53 +00:00
|
|
|
trigger=CorrelationTriggerConfig(
|
2018-07-28 11:06:27 +00:00
|
|
|
trigger_strength=10,
|
|
|
|
use_edge_trigger=True,
|
2018-07-14 09:06:07 +00:00
|
|
|
|
2018-07-28 11:06:27 +00:00
|
|
|
responsiveness=0.1,
|
|
|
|
falloff_width=0.5,
|
2018-07-13 12:37:22 +00:00
|
|
|
),
|
2018-07-24 03:44:24 +00:00
|
|
|
|
2018-07-28 11:06:27 +00:00
|
|
|
amplification=1,
|
|
|
|
render=RendererConfig(
|
2018-07-13 11:05:31 +00:00
|
|
|
1280, 720,
|
2018-07-13 02:29:05 +00:00
|
|
|
ncols=1
|
2018-07-22 09:06:10 +00:00
|
|
|
),
|
2018-07-24 03:44:24 +00:00
|
|
|
|
2018-07-22 09:06:10 +00:00
|
|
|
outputs=[
|
2018-07-22 12:31:49 +00:00
|
|
|
# outputs.FFmpegOutputConfig(output),
|
|
|
|
outputs.FFplayOutputConfig(),
|
2018-07-28 11:06:27 +00:00
|
|
|
]
|
2018-07-12 22:27:26 +00:00
|
|
|
)
|
2018-07-28 11:06:27 +00:00
|
|
|
return dc.replace(cfg, **kwargs)
|
2018-07-12 22:27:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Ovgen:
|
|
|
|
def __init__(self, cfg: Config):
|
|
|
|
self.cfg = cfg
|
2018-07-28 11:06:27 +00:00
|
|
|
self._load_channels() # self.waves =
|
2018-07-22 09:06:10 +00:00
|
|
|
self._load_outputs() # self.outputs =
|
2018-07-20 21:19:43 +00:00
|
|
|
|
2018-07-28 11:06:27 +00:00
|
|
|
waves: List[Wave]
|
|
|
|
channels: List[Channel]
|
|
|
|
outputs: List[outputs.Output]
|
|
|
|
nchan: int
|
2018-07-12 22:27:26 +00:00
|
|
|
|
2018-07-28 11:06:27 +00:00
|
|
|
def _load_channels(self):
|
|
|
|
self.channels = [Channel(ccfg, self.cfg) for ccfg in self.cfg.channels]
|
|
|
|
self.waves = [channel.wave for channel in self.channels]
|
|
|
|
self.nchan = len(self.channels)
|
2018-07-16 05:07:26 +00:00
|
|
|
|
2018-07-22 09:06:10 +00:00
|
|
|
def _load_outputs(self):
|
2018-07-28 11:06:27 +00:00
|
|
|
self.outputs = [output_cfg(self.cfg) for output_cfg in self.cfg.outputs]
|
2018-07-22 09:06:10 +00:00
|
|
|
|
2018-07-28 11:06:27 +00:00
|
|
|
def play(self):
|
2018-07-12 22:27:26 +00:00
|
|
|
# Calculate number of frames (TODO master file?)
|
2018-07-28 11:06:27 +00:00
|
|
|
render_width_s = self.cfg.render_width_s
|
2018-07-12 22:27:26 +00:00
|
|
|
fps = self.cfg.fps
|
2018-07-22 09:06:10 +00:00
|
|
|
create_window = self.cfg.create_window
|
2018-07-16 05:07:26 +00:00
|
|
|
|
2018-07-12 22:27:26 +00:00
|
|
|
nframes = fps * self.waves[0].get_s()
|
|
|
|
nframes = int(nframes) + 1
|
|
|
|
|
2018-07-25 22:17:30 +00:00
|
|
|
renderer = MatplotlibRenderer(self.cfg.render, self.nchan, create_window)
|
2018-07-12 22:27:26 +00:00
|
|
|
|
2018-07-14 06:54:14 +00:00
|
|
|
if RENDER_PROFILING:
|
2018-07-13 11:05:31 +00:00
|
|
|
begin = time.perf_counter()
|
|
|
|
|
2018-07-12 22:27:26 +00:00
|
|
|
# For each frame, render each wave
|
2018-07-24 03:39:15 +00:00
|
|
|
prev = -1
|
2018-07-12 22:27:26 +00:00
|
|
|
for frame in range(nframes):
|
2018-07-13 00:48:51 +00:00
|
|
|
time_seconds = frame / fps
|
2018-07-12 22:27:26 +00:00
|
|
|
|
2018-07-24 03:39:15 +00:00
|
|
|
rounded = int(time_seconds)
|
|
|
|
if rounded != prev:
|
|
|
|
print(rounded)
|
|
|
|
prev = rounded
|
|
|
|
|
2018-07-16 05:07:26 +00:00
|
|
|
datas = []
|
|
|
|
# Get data from each wave
|
2018-07-20 21:19:43 +00:00
|
|
|
for wave, channel in zip(self.waves, self.channels):
|
2018-07-13 00:48:51 +00:00
|
|
|
sample = round(wave.smp_s * time_seconds)
|
2018-07-28 11:06:27 +00:00
|
|
|
region_len = round(wave.smp_s * render_width_s)
|
2018-07-16 05:07:26 +00:00
|
|
|
|
2018-07-20 21:19:43 +00:00
|
|
|
trigger_sample = channel.trigger.get_trigger(sample)
|
2018-07-16 05:07:26 +00:00
|
|
|
datas.append(wave.get_around(trigger_sample, region_len))
|
2018-07-28 11:06:27 +00:00
|
|
|
# FIXME channel.render_subsampling
|
2018-07-12 22:27:26 +00:00
|
|
|
|
2018-07-22 09:06:10 +00:00
|
|
|
# Render frame
|
2018-07-16 05:07:26 +00:00
|
|
|
renderer.render_frame(datas)
|
2018-07-12 22:27:26 +00:00
|
|
|
|
2018-07-22 09:06:10 +00:00
|
|
|
# Output frame
|
2018-07-22 12:11:34 +00:00
|
|
|
if self.outputs:
|
|
|
|
frame = renderer.get_frame()
|
2018-07-22 10:17:31 +00:00
|
|
|
for output in self.outputs:
|
|
|
|
output.write_frame(frame)
|
2018-07-22 09:06:10 +00:00
|
|
|
|
2018-07-14 06:54:14 +00:00
|
|
|
if RENDER_PROFILING:
|
2018-07-16 05:07:26 +00:00
|
|
|
# noinspection PyUnboundLocalVariable
|
2018-07-13 11:05:31 +00:00
|
|
|
dtime = time.perf_counter() - begin
|
|
|
|
render_fps = nframes / dtime
|
|
|
|
print(f'FPS = {render_fps}')
|