makepad_audio_widgets/
display_audio.rs1
2use {
3 crate::{
4 makepad_draw::*,
5 makepad_widgets::*,
6 }
7};
8
9live_design!{
10 use link::shaders::*;
11
12 DrawWave = {{DrawWave}} {
13 texture wave_texture: texture2d
14
15 fn vu_fill(self)->vec4{
16 return vec4(Pal::iq1((1.0-0.5*self.pos.y)),1.0)
17 }
18
19 fn pixel(self) -> vec4 {
20 let wave = sample2d(self.wave_texture, vec2(self.pos.x, 0.0));
21 let right = (wave.y + wave.z / 256.0 - 0.5) * 3.0;
22 let left = (wave.w + wave.x / 256.0 - 0.5) * 3.0;
23 let sdf = Sdf2d::viewport(self.pos * self.rect_size);
25 let step = 0.0;
26 let vu_ht = self.rect_size.y*(1.0-self.vu_left * self.gain);
28 sdf.rect(0.,vu_ht,self.rect_size.x, self.rect_size.y-vu_ht);
29 sdf.fill(self.vu_fill())
30 for i in 0..4 {
31 let wave = sample2d(self.wave_texture, vec2(self.pos.x, step));
32 let right = (wave.y + wave.z / 256.0 - 0.5) * 3.0;
33 let left = (wave.w + wave.x / 256.0 - 0.5) * 3.0;
34 let audio = (left + right) - 0.01;
35 let half = self.rect_size.y * 0.5;
36 let scale = half * 2.0;
37 sdf.hline(half + audio * scale, abs(audio) * scale);
38 let color = Pal::iq1(0.35 + 2.0 * step) * 0.8;
39 sdf.fill_premul(vec4(color, 0.0))
40 step += 1.0 / 16.0;
41 }
42 return sdf.result
43 }
44 }
45
46 pub DisplayAudio = {{DisplayAudio}} {
47 width: Fill,
48 height: Fill
49 }
50}
51
52#[derive(Live, LiveHook, LiveRegister)]#[repr(C)]
54struct DrawWave {
55 #[deref] draw_super: DrawQuad,
56 #[live] gain: f32,
57 #[live] vu_left: f32,
58 #[live] vu_right: f32
59}
60
61#[derive(Live, Widget)]
62pub struct DisplayAudio {
63 #[walk] walk: Walk,
64 #[redraw] #[live] draw_wave: DrawWave,
65 #[rust(Texture::new(cx))] wave_texture: Texture,
66 #[rust] data_offset: [usize; 32],
67 #[rust([0; 32])] active: [usize; 32],
68 #[rust([(0.0,0.0);32])] vu:[(f32,f32); 32],
69}
70
71
72impl Widget for DisplayAudio {
73 fn handle_event(&mut self, _cx: &mut Cx, _event: &Event, _scope: &mut Scope){
74 }
75
76 fn draw_walk(&mut self, cx: &mut Cx2d, _scope: &mut Scope, walk: Walk) -> DrawStep {
77 self.draw_wave.draw_vars.set_texture(0, &self.wave_texture);
78 self.draw_wave.vu_left = self.vu[0].0.powf(1.0/3.0)*1.2;
79 self.draw_wave.vu_right = self.vu[0].1.powf(1.0/3.0)*1.2;
80 self.vu[0].0 *= 0.95;
81 self.vu[0].1 *= 0.95;
82 self.draw_wave.draw_walk(cx, walk);
83 DrawStep::done()
84 }
85}
86
87#[derive(Clone, DefaultNone)]
88pub enum DisplayAudioAction {
89 None
90}
91const WAVE_SIZE_X: usize = 1024;
92const WAVE_SIZE_Y: usize = 16;
93
94impl LiveHook for DisplayAudio {
95
96 fn after_new_from_doc(&mut self, cx: &mut Cx) {
97 self.wave_texture = Texture::new_with_format(cx, TextureFormat::VecBGRAu8_32 {
98 data: {
99 let mut data = Vec::new();
100 data.resize(WAVE_SIZE_X * WAVE_SIZE_Y, 0);
101 for j in 0..WAVE_SIZE_Y {
102 for i in 0..WAVE_SIZE_X {
103 let left_u16 = 32767;
104 let right_u16 = 32767;
105 data[j * WAVE_SIZE_X + i] = left_u16 << 16 | right_u16;
106 }
107 }
108 Some(data)
109 },
110 width: WAVE_SIZE_X,
111 height: WAVE_SIZE_Y,
112 updated: TextureUpdated::Full,
113 });
114 }
115}
116
117impl DisplayAudio {
118 pub fn process_buffer(&mut self, cx: &mut Cx, chan: Option<usize>, voice: usize, audio: &AudioBuffer, gain:f32) {
119 let mut wave_buf = self.wave_texture.take_vec_u32(cx);
120 let frames = audio.frame_count();
121 let wave_off = self.data_offset[voice];
122 let voice_offset = voice * WAVE_SIZE_X;
123 let mut is_active = false;
124 for i in 0..frames {
125 let left = audio.channel(chan.unwrap_or(0))[i];
126 let right = audio.channel(chan.unwrap_or(audio.channel_count().min(1)))[i];
127 if left.abs() > self.vu[voice].0 {self.vu[voice].0 = left.abs()};
128 if right.abs() > self.vu[voice].1 {self.vu[voice].1 = right.abs()};
129 let left_u16 = ((left + 0.5) * 65536.0).max(0.0).min(65535.0) as u32;
130 let right_u16 = ((right + 0.5) * 65536.0).max(0.0).min(65535.0) as u32;
131 if left.abs()>0.0000000000001 || right.abs()>0.0000000000001 {
132 is_active = true;
133 }
134 let off = voice_offset + ((wave_off + i) % (WAVE_SIZE_X));
135 wave_buf[off] = left_u16 << 16 | right_u16;
136 }
137 self.draw_wave.gain = gain;
138 self.wave_texture.put_back_vec_u32(cx, wave_buf, None);
139 self.data_offset[voice] = (self.data_offset[voice] + frames) % (WAVE_SIZE_X);
140 if is_active {
141 self.active[voice] = 6
142 }
143 if self.active[voice]>0 {
144 self.draw_wave.redraw(cx);
145 self.active[voice] -= 1;
146 }
147 }
148}
149
150impl DisplayAudioRef {
151 pub fn process_buffer(&self, cx: &mut Cx, chan: Option<usize>, voice: usize, buffer: &AudioBuffer, gain:f32) {
152 if let Some(mut inner) = self.borrow_mut() {
153 inner.process_buffer(cx, chan, voice, buffer, gain);
154 }
155 }
156
157 pub fn voice_off(&self, _cx: &mut Cx, _voice: usize,) {
158 }
159}
160
161impl DisplayAudioSet {
162 pub fn process_buffer(&self, cx: &mut Cx, chan: Option<usize>, voice: usize, buffer: &AudioBuffer, gain:f32) {
163 for item in self.iter(){
164 item.process_buffer(cx, chan, voice, buffer, gain);
165 }
166 }
167
168 pub fn voice_off(&self, cx: &mut Cx, voice: usize,) {
169 for item in self.iter(){
170 item.voice_off(cx, voice);
171 }
172 }
173}