summaryrefslogtreecommitdiff
path: root/draw.fs
blob: 4f35d545a219d710fb5f6897395a07ad816bb19f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
\ -*- snd-forth -*-
\ draw.fs -- draw.scm -> draw.fs

\ Author: Michael Scholz <mi-scholz@users.sourceforge.net>
\ Created: Sun Dec 18 23:36:09 CET 2005
\ Changed: Sat Jul 25 17:37:39 CEST 2009

\ Commentary:

\ make-current-window-display  ( -- )
\ close-current-window-display ( -- )

\ Code:

require extensions

\ --- inset overall waveform; if click, move to that location ---

#f value current-window-display-is-running \ for prefs

hide
0.20 constant inset-width
0.25 constant inset-height

: update-current-window-location <{ snd -- #f }>
  current-window-display-is-running if
    snd channels 0 ?do
      'inset-envelope snd i channel-property { vals }
      \ set edit-position to impossible value
      vals array? if vals 'edit-position -2 array-assoc-set! to vals then
    loop
  then
  #f
;
: display-current-window-location <{ snd chn -- }>
  current-window-display-is-running
  snd chn time-graph? && if
    snd chn undef axis-info                 { axinf }
    axinf 12 array-ref                      { grf-width }
    inset-width grf-width f* fround->s      { width }
    grf-width width -                       { x-offset }
    axinf 11 array-ref axinf 13 array-ref - { grf-height }
    inset-height grf-height f* fround->s    { height }
    axinf 13 array-ref 10 -                 { chan-offset }
    chan-offset height 2/ +                 { y-offset }
    snd channel-style channels-separate = if chn else 0 then { grf-chn }
    axinf 19 array-ref                      { new-peaks }
    snd chn #f frames                       { frms }
    #f { data0 }
    #f { data1 }
    width  10 >
    height 10 > &&
    frms   0>   &&
    chn 0= snd channel-style channels-superimposed <> || && if
      x-offset chan-offset height + width 2      snd grf-chn undef #f fill-rectangle drop
      x-offset chan-offset          2     height snd grf-chn undef #f fill-rectangle drop
      snd chn right-sample frms f/ width f* fround->s { rx }
      snd chn left-sample  frms f/ width f* fround->s { lx }
      x-offset lx + chan-offset rx lx - 1 max height
      snd grf-chn selection-context #f fill-rectangle drop
      'inset-envelope snd chn channel-property { old-env }
      old-env array? if
	new-peaks not
	old-env 'width         array-assoc-ref width                 = &&
	old-env 'height        array-assoc-ref height                = &&
	old-env 'y-offset      array-assoc-ref y-offset              = &&
	old-env 'edit-position array-assoc-ref snd chn edit-position = && if
	  old-env 'data0 array-assoc-ref to data0
	  old-env 'data1 array-assoc-ref to data1
	  #t
	else
	  #f
	then
      else
	#f
      then unless			\ else (old-env == #f)
	snd chn current-edit-position 0 frms make-graph-data { data }
	\ data may be a vct or a list of two vcts
	data vct? if
	  data vct-peak
	else
	  data 0 array-ref vct-peak data 1 array-ref vct-peak fmax
	then { data-max }
	data-max f0> if height data-max f2* f/ else 0.0 then { data-scaler }
	width 2* { new-len }
	data vct? if data length else data 0 array-ref length then { data-len }
	data-len width f/ fround->s { step }
	data-len width > if
	  new-len make-array to data0
	  data array? if new-len make-array to data1 then
	  0 { idxi }
	  0 { idxj }
	  data-max fnegate { max-y }
	  data-max { min-y }
	  0 { stepper }
	  begin idxi data-len < idxj new-len < && while
	      data1 if
		max-y data 1 array-ref idxi vct-ref fmax to max-y
		min-y data 0 array-ref  idxi vct-ref fmin to min-y
	      else
		max-y data idxi vct-ref fmax to max-y
	      then
	      stepper 1+ to stepper
	      stepper step >= if
		data0 idxj    x-offset array-set!
		data0 idxj 1+ y-offset max-y data-scaler f* f- fround->s array-set!
		data-max fnegate to max-y
		data1 if
		  data1 idxj    x-offset array-set!
		  data1 idxj 1+ y-offset min-y data-scaler f* f- fround->s array-set!
		  data-max to min-y
		then
		x-offset 1+ to x-offset
		stepper step - to stepper
		idxj 2 + to idxj
	      then
	      idxi 1+ to idxi
	  repeat
	  begin idxj new-len < while
	      data0 idxj    data0 idxj 2 - array-ref array-set!
	      data0 idxj 1+ data0 idxj 1 - array-ref array-set!
	      data1 if
		data1 idxj    data1 idxj 2 - array-ref array-set!
		data1 idxj 1+ data1 idxj 1 - array-ref array-set!
	      then
	      idxj 2 + to idxj
	  repeat
	else
	  width data-len f/ fround->s { xstep }
	  data-len 2* make-array to data0
	  data array? if new-len 2* make-array to data1 then
	  0 { idxj }
	  x-offset { xj }
	  data-len 0 ?do
	    data0 idxj xj array-set!
	    data1 if
	      data0 idxj 1+ y-offset data 1 array-ref i vct-ref data-scaler f* f- fround->s
	      array-set!
	      data1 idxj    xj array-set!
	      data1 idxj 1+ y-offset data 0 array-ref i vct-ref data-scaler f* f- fround->s
	      array-set!
	    else
	      data0 idxj 1+ y-offset data i vct-ref data-scaler f* f- fround->s array-set!
	    then
	    idxj 2 + to idxj
	    xj xstep + to xj
	  loop
	then
	#()      'width         width                 array-assoc-set!
	( vals ) 'height        height                array-assoc-set!
	( vals ) 'edit-position snd chn edit-position array-assoc-set!
	( vals ) 'data0         data0                 array-assoc-set!
	( vals ) 'data1         data1                 array-assoc-set!
	( vals ) 'y-offset      y-offset              array-assoc-set! { vals }
	'inset-envelope vals snd chn set-channel-property drop
      then
      data1 length 2 mod if data1 array-pop drop then
      data0 snd grf-chn time-graph draw-lines drop
      data1 if data1 snd grf-chn time-graph draw-lines drop then
    then
  then
;
: click-current-window-location <{ snd chn button state x y axis -- f }>
  current-window-display-is-running
  axis time-graph = && if
    snd chn undef axis-info            { axinf }
    axinf 12 array-ref                 { grf-width }
    inset-width grf-width f* fround->s { width }
    grf-width width -                  { x-offset }
    axinf 11 array-ref axinf 13 array-ref - inset-height f* fround->s { height }
    axinf 13 array-ref 10 -            { chan-offset }
    width         0>
    x x-offset    >= &&
    x grf-width   <= &&
    y chan-offset >= &&
    y chan-offset height + <= && if
      snd chn #f frames x x-offset f- width f/ f* fround->s { samp }
      snd chn left-sample { ls }
      snd chn right-sample { rs }
      samp snd chn #f set-cursor drop
      samp ls < samp rs > || if
	samp ls rs - 2/ - 0 max snd chn #f frames 1- min snd chn set-right-sample drop
      then
      snd chn update-time-graph drop
      #t
    else
      #f
    then
  else
    #f
  then
;
: undo-cb { snd chn -- proc; self -- }
  0 proc-create snd , chn ,
 does> ( self -- )
  { self }
  'inset-envelope #f self @ ( snd ) self cell+ @ ( chn ) set-channel-property drop
;
: install-current-window-location <{ snd -- }>
  snd channels 0 ?do
    'inset-envelope snd i set-channel-property-save-state-ignore drop
    snd i undo-hook snd i undo-cb add-hook!
  loop
;
set-current

: make-current-window-display ( -- )
  doc" Displays in upper right corner the overall current sound \
and where the current window fits in it."
  current-window-display-is-running unless
    #t to current-window-display-is-running
    after-open-hook  <'> install-current-window-location add-hook!
    after-graph-hook <'> display-current-window-location add-hook!
    mouse-click-hook <'> click-current-window-location   add-hook!
    update-hook      <'> update-current-window-location  add-hook!
  then
;

: close-current-window-display ( -- )
  current-window-display-is-running if
    #f to current-window-display-is-running
    after-open-hook  <'> install-current-window-location remove-hook! drop
    after-graph-hook <'> display-current-window-location remove-hook! drop
    mouse-click-hook <'> click-current-window-location   remove-hook! drop
    update-hook      <'> update-current-window-location  remove-hook! drop
    sounds each { snd }
      snd channels 0 ?do snd i undo-hook <'> undo-cb remove-hook! drop loop
    end-each
  then
;

previous

\ draw.fs ends here