1# snd-test.rb -- Snd Ruby code and tests
2
3# Translator/Author: Michael Scholz <mi-scholz@users.sourceforge.net>
4# Created: 2005/02/18 10:18:34
5# Changed: 2020/11/02 16:02:30
6
7# Tags: FIXME - something is wrong
8#       XXX   - info marker
9#
10# Tested with:
11#   Snd 20.x
12#   Ruby 3.x
13#
14# Reads init file ./.sndtest.rb or ~/.sndtest.rb for global variables,
15# hooks, etc.
16#
17# Example:
18#
19=begin
20% cat ./.sndtest.rb
21# $VERBOSE = true
22# $DEBUG   = true
23
24$original_save_dir       = set_save_dir(ENV["TMPDIR"])
25$original_temp_dir       = set_temp_dir(save_dir)
26$info_array_print_length = 4
27
28$sf_dir                  = "/usr/opt/sound/sf1/"
29$bigger_snd              = "/usr/opt/sound/SFiles/bigger.snd"
30$with_big_file           = true
31# $all_args              = true
32# $bigtest_08            = true
33# $tests                 = 2
34
35alias bye exit
36=end
37
38#
39# Start tests:
40#
41# snd -noinit -load snd-test.rb         # all tests
42# snd -noinit -load snd-test.rb 3 7 20  # only tests 3, 7, 20
43# snd -noinit -load snd-test.rb -23     # all tests except 23
44#
45#  test 00: constants
46#  test 01: defaults
47#  test 02: headers
48#  test 03: variables
49#  test 04: sndlib
50#  test 05: simple overall checks
51#  test 06: vcts
52#  test 07: colors
53#  test 08: clm
54#  test 09: mix
55#  test 10: marks
56#  test 11: dialogs
57#  test 12: extensions
58#  test 13: menus, edit lists, hooks, etc
59#  test 14: all together now
60#  test 15: chan-local vars
61#  test 16: regularized funcs
62#  test 17: dialogs and graphics
63#  test 18: enved
64#  test 19: save and restore
65#  test 20: transforms
66#  test 21: new stuff
67#  test 23: with-sound
68#  test 28: errors
69#  test all done
70
71$VERBOSE = false
72$DEBUG   = false
73
74$my_snd_error_hook = false
75$my_mus_error_hook = false
76
77# run snd-test.rb $tests times
78$tests = 1
79
80$HOME                           = ENV["HOME"]
81$original_save_dir              = (save_dir or $HOME + "/zap/snd")
82$original_temp_dir              = (temp_dir or $HOME + "/zap/tmp")
83$original_sound_file_extensions = sound_file_extensions
84$original_prompt                = listener_prompt
85$default_file_buffer_size       = mus_file_buffer_size()
86$info_array_print_length        = 24
87
88$sf_dir         = "/home/bil/sf1/"
89$bigger_snd     = "/home/bil/zap/sounds/bigger.snd"
90$with_big_file  = false
91# $bigtest_08 not included in $all_args
92$all_args       = false
93$bigtest_08     = false
94
95# Global variables may be overridden in `pwd`/.sndtest.rb or ~/.sndtest.rb.
96lambda do |file|
97  if File.file?(file)
98    load(file)
99  elsif File.file?(f = $HOME + "/" + file)
100    load(f)
101  end
102end.call(".sndtest.rb")
103
104unless $my_snd_error_hook
105  $my_snd_error_hook = Proc.new do |msg| true end
106end
107
108require "clm"
109
110# default 1, can be reset in .sndtest.rb
111$tests = ((integer?($tests) and $tests > 0) ? $tests : 1)
112$clmtest = 0
113
114$with_test_nogui  = provided?("snd-nogui")
115$with_test_gui    = (not $with_test_nogui)
116$with_test_motif  = provided?("snd-motif")
117$with_test_ladspa = provided?("snd-ladspa")
118$with_test_gl     = provided?("gl")
119$with_test_gl2ps  = provided?("gl2ps")
120$with_test_gsl    = provided?("gsl")
121$with_test_alsa   = provided?("alsa")
122
123if $with_test_nogui
124  def noop(*args, &body)
125    false
126  end
127
128  undef x_bounds
129  undef set_x_bounds
130  undef y_bounds
131  undef set_y_bounds
132  undef enved_filter
133  undef graph_cursor
134  undef set_graph_cursor
135  undef enved_envelope
136  undef set_enved_envelope
137  undef colormap
138  undef set_colormap
139
140  # XXX: snd-nogui.c defines "in"
141  alias call_in in
142
143  alias integer2colormap noop
144  alias colormap2integer noop
145  alias axis_color noop
146  alias highlight_color noop
147
148  x_bounds_value = [0.0, 0.1]
149  make_proc_with_setter(:x_bounds,
150    Proc.new do |*args| x_bounds_value end,
151    Proc.new do |bounds, *args| x_bounds_value = bounds end)
152
153  y_bounds_value = [-1.0, 1.0]
154  make_proc_with_setter(:y_bounds,
155    Proc.new do |*args| y_bounds_value end,
156    Proc.new do |bounds, *args| y_bounds_value = bounds end)
157
158  # XXX: For ruby18 it's important to define Procs with arity 0 in this way:
159  #
160  #     Proc.new do | | enved_filter_value end
161  # or  Proc.new do enved_filter_value end
162  # or  lambda do enved_filter_value end
163  #
164  # but not
165  #
166  #     lambda do | | enved_filter_value end
167  #
168  # Otherwise we can't correctly determine the arity in test 28.
169  enved_filter_value = true
170  make_proc_with_setter(:enved_filter,
171    Proc.new do | | enved_filter_value end,
172    Proc.new do |val| enved_filter_value = val end)
173
174  graph_cursor_value = 34
175  make_proc_with_setter(:graph_cursor,
176    Proc.new do | | graph_cursor_value end,
177    Proc.new do |val| graph_cursor_value = val end)
178
179  enved_envelope_value = nil
180  make_proc_with_setter(:enved_envelope,
181    Proc.new do | | enved_envelope_value end,
182    Proc.new do |val| enved_envelope_value = val end)
183
184  colormap_value = $hot_colormap
185  make_proc_with_setter(:colormap,
186    Proc.new do | | colormap_value end,
187    Proc.new do |val|
188      if val.kind_of?(Numeric) and val.between?(0, 20)
189        colormap_value = val
190      end
191    end)
192
193  $mouse_enter_graph_hook    = Hook.new("$mouse_enter_graph_hook", 2)
194  $mouse_enter_label_hook    = Hook.new("$mouse_enter_label_hook", 3)
195  $mouse_enter_listener_hook = Hook.new("$mouse_enter_listener_hook", 1)
196  $mouse_enter_text_hook     = Hook.new("$mouse_enter_text_hook", 1)
197  $mouse_leave_graph_hook    = Hook.new("$mouse_leave_graph_hook", 2)
198  $mouse_leave_label_hook    = Hook.new("$mouse_leave_label_hook", 3)
199  $mouse_leave_listener_hook = Hook.new("$mouse_leave_listener_hook", 1)
200  $mouse_leave_text_hook     = Hook.new("$mouse_leave_text_hook", 1)
201end
202
203require "examp"
204require "ws"
205require "hooks"
206require "mix"
207require "marks"
208require "pvoc"
209require "bird"
210require "v"
211require "poly"
212require "dsp"
213require "analog-filter"
214require "rgb"
215require "effects"
216require "draw"
217require "musglyphs"
218
219if $with_test_motif
220  RXSetErrorHandler(lambda do |dpy, e|
221      val, err = RXGetErrorText(dpy, Rerror_code(e), nil, 1024)
222      $stderr.printf("Xlib error_code[%s]: %s\n", val, err)
223      val, err = RXGetErrorText(dpy, Rrequest_code(e), nil, 1024)
224      $stderr.printf("Xlib request_code[%s]: %s\n", val, err)
225      val, err = RXGetErrorText(dpy, Rminor_code(e), nil, 1024)
226      $stderr.printf("Xlib minor_code[%s]: %s\n", val, err)
227      $stderr.printf("Ruby $!: %s\n", $!.inspect)
228      $stderr.printf("Ruby $@: %s\n", $@.inspect)
229    end)
230  RXSetIOErrorHandler(lambda do |dpy|
231      $stderr.printf("Xlib IO Error dpy: %s", dpy.inspect)
232      $stderr.printf("Ruby $!: %s\n", $!.inspect)
233      $stderr.printf("Ruby $@: %s\n", $@.inspect)
234    end)
235end
236
237# Returns Ascii value of KEY as a Fixnum.
238#
239# Since Ruby 1.9.0 (July/August 2006) ?x returns string "x" instead of
240# fixnum 120, so we need a new function.
241#
242# key_to_int(?x) => 120
243if ?x.kind_of?(String)
244  def key_to_int(key)
245    key.sum
246  end
247else
248  def key_to_int(key)
249    key
250  end
251end
252
253if $with_test_nogui
254  set_with_mix_tags(true)
255end
256
257unbind_key(key_to_int(?c), 4, true) # C-c for interrupt key
258trap("SIGINT") do |sig|
259  puts
260  snd_info("Interrupt received.  Finish snd-test.rb.")
261  snd_info("")
262  $timings.last.last.stop
263  finish_snd_test
264  clear_test_files
265  exit(2)
266end
267
268# let procs $snd|mus_error_hook("sndtestrc") untouched
269def reset_almost_all_hooks
270  reset_all_hooks
271  if proc?($my_snd_error_hook)
272    $snd_error_hook.add_hook!("sndtest", &$my_snd_error_hook)
273  end
274  if proc?($my_mus_error_hook)
275    $mus_error_hook.add_hook!("sndtest", &$my_mus_error_hook)
276  end
277end
278
279reset_almost_all_hooks
280
281$test_functions = Array.new
282
283def main_test
284  start_snd_test()
285  if false
286    # XXX: Instead of rand() one can use different command lines:
287    # snd -noinit snd-test.rb 3 2 1
288    # snd -noinit snd-test.rb 1 3 2
289    # etc.
290    $test_functions.rand!
291  end
292  $test_functions.each do |func|
293    before_test(func)
294    snd_func(func)
295    after_test(func)
296  end
297  finish_snd_test()
298  clear_test_files
299  exit(0)
300end
301
302if $with_test_nogui
303  def snd_info(fmt, *args)
304    clm_print("# %s\n", format(fmt, *args))
305    nil
306  end
307else
308  def snd_info(fmt, *args)
309    str = format(fmt, *args)
310    clm_print("\n# %s", str)
311    $stderr.printf("# %s\n", str)
312    nil
313  end
314end
315
316if RUBY_VERSION >= "1.9"
317  def snd_display_prev_caller(fmt, *args)
318    if line = caller(2)[0].scan(/:(.*):in /).first
319      snd_info("[%s] %s", line.first, format(fmt, *args))
320    else
321      snd_info(fmt, *args)
322    end
323  end
324else
325  def snd_display_prev_caller(fmt, *args)
326    # Because ruby < 1.9 has a line number bug we use function name.
327    if line = caller(2)[0].scan(/^.*:in `(.*)'/).first
328      snd_info("[%s] %s", line.first, format(fmt, *args))
329    else
330      snd_info(fmt, *args)
331    end
332  end
333end
334
335def snd_display(*args)
336  if args.empty?
337    snd_display_prev_caller("")
338  else
339    fmt = args.shift
340    snd_display_prev_caller(fmt, *args)
341  end
342end
343
344def snd_debug(*args)
345  if args.empty?
346    snd_display_prev_caller("#<SND-DEBUG>")
347  else
348    fmt = args.shift
349    snd_display_prev_caller("#<SND-DEBUG: %s>", format(fmt, *args))
350  end
351end
352
353def snd_test_format(sndfmt, res, req, fmt = "", *args)
354  str = format(sndfmt, res, req)
355  unless fmt.empty?
356    str = format(fmt, *args) + ": " + str
357  end
358  str
359end
360
361def snd_format(res, req, op = "!=", fmt = "", *args)
362  case req
363  when Float
364    snd_test_format("res %1.4f #{op} req %1.4f?", res, req, fmt, *args)
365  when Vct, Array, Vec, Poly
366    old_alen = mus_array_print_length()
367    old_vlen = print_length()
368    set_mus_array_print_length($info_array_print_length)
369    set_print_length($info_array_print_length)
370    if res.nil?
371      res = "nil"
372    end
373    str = snd_test_format("res #{op} req?\n# => res %s\n# => req %s",
374      res, req, fmt, *args)
375    set_mus_array_print_length(old_alen)
376    set_print_length(old_vlen)
377    str
378  else
379    snd_test_format("res %s #{op} req %s?",
380      res.inspect, req.inspect, fmt, *args)
381  end
382end
383
384def snd_format_neq(res, req, fmt = "", *args)
385  snd_format(res, req, "!=", fmt, *args)
386end
387
388def snd_format_eq(res, req, fmt = "", *args)
389  snd_format(res, req, "==", fmt, *args)
390end
391
392def snd_test_equal?(res, req)
393  case req
394  when Float
395    res.kind_of?(Numeric) and fequal?(res, req)
396  when Vct, Vec, Poly
397    vequal?(res, req)
398  else
399    res == req
400  end
401end
402
403def snd_test_neq(res, req, fmt = "", *args)
404  if snd_test_equal?(res, req)
405    false
406  else
407    snd_display_prev_caller(snd_format(res, req, "!=", fmt, *args))
408    true
409  end
410end
411
412def snd_test_eq(res, req, fmt = "", *args)
413  if snd_test_equal?(res, req)
414    snd_display_prev_caller(snd_format(res, req, "==", fmt, *args))
415    true
416  else
417    false
418  end
419end
420
421# snd_test_any_neq(res, req, :ffequal?, "more info")
422def snd_test_any_neq(res, req, func, fmt = "", *args)
423  if method(func).call(res, req)
424    false
425  else
426    snd_display_prev_caller(snd_format(res, req, "!=", fmt, *args))
427    true
428  end
429end
430
431# snd_test_any_eq(res, req, :ffequal?, "more info")
432def snd_test_any_eq(res, req, func, fmt = "", *args)
433  if method(func).call(res, req)
434    snd_display_prev_caller(snd_format(res, req, "==", fmt, *args))
435    true
436  else
437    false
438  end
439end
440
441def snd_test_lt(res, req, fmt = "", *args)
442  if res < req
443    snd_display_prev_caller(snd_format(res, req, "<", fmt, *args))
444    true
445  else
446    false
447  end
448end
449
450def snd_test_gt(res, req, fmt = "", *args)
451  if res > req
452    snd_display_prev_caller(snd_format(res, req, ">", fmt, *args))
453    true
454  else
455    false
456  end
457end
458
459# command line args: last arg(s) may be zero or many test numbers
460# snd -noinit -load snd-test.rb 3 7 20  # only tests 3, 7, 20
461# snd -noinit -load snd-test.rb -23     # all tests except 23
462
463lambda do
464  # non existent tests, non wanted tests (negative arguments like -23)
465  # added here
466  nargs = [22, 24, 25, 26, 27, 29]
467  targs = []
468  if script_arg.positive?
469    script_args[script_arg..-1].each do |arg|
470      n = Snd.catch(:all, nil) do Integer(arg) end.first
471      if integer?(n)
472        if n < 0
473          nargs << n.abs
474        elsif n <= 30             # test_30 for short tests
475          targs << n
476        end
477      end
478    end
479  end
480  if targs.empty?
481    29.times do |n| targs << n end
482  end
483  (targs - nargs).each do |n|
484    $test_functions << format("test_%02d", n).intern
485  end
486end.call
487
488def fneq_err(f1, f2, err = 0.001)
489  (f1 - f2).abs > err
490end
491
492def fneq(a, b)
493  fneq_err(a, b, 0.001)
494end
495
496def ffneq(a, b)
497  fneq_err(a, b, 0.01)
498end
499
500def fffneq(a, b)
501  fneq_err(a, b, 0.1)
502end
503
504def fequal_err(f1, f2, err = 0.001)
505  (f1 - f2).abs <= err
506end
507
508def fequal?(a, b)
509  fequal_err(a, b, 0.001)
510end
511
512def ffequal?(a, b)
513  fequal_err(a, b, 0.01)
514end
515
516def fffequal?(a, b)
517  fequal_err(a, b, 0.1)
518end
519
520# returns a vct or false
521# obj: Vct, Array, Vec, Poly
522def any2vct(obj)
523  obj.respond_to?(:to_vct) and obj.to_vct
524end
525
526# compares Arrays and Vcts
527def vequal_err(val0, val1, err = 0.001)
528  (v0 = any2vct(val0)) and
529  (v1 = any2vct(val1)) and
530  (v0.subtract(v1).peak <= err)
531end
532
533def vequal?(v0, v1)
534  vequal_err(v0, v1, 0.001)
535end
536
537def vvequal?(v0, v1)
538  vequal_err(v0, v1, 0.00002)
539end
540
541def vfequal?(v0, v1)
542  vequal_err(v0, v1, 0.01)
543end
544
545def vffequal?(v0, v1)
546  vequal_err(v0, v1, 0.1)
547end
548
549def vfffequal?(v0, v1)
550  vequal_err(v0, v1, 0.5)
551end
552
553alias vequal    vequal?
554alias vvequal   vvequal?
555alias vfequal   vfequal?
556alias vffequal  vffequal?
557alias vfffequal vfffequal?
558
559def cneq(a, b)
560  if number?(a) and number?(b)
561    fneq(a.real, b.real) or fneq(a.imag, b.imag)
562  else
563    true
564  end
565end
566
567def vcneql(a, b)
568  if a.length != b.length
569    true
570  else
571    a.each_with_index do |x, i|
572      if cneq(x, b[i])
573        return true
574      end
575    end
576    false
577  end
578end
579
580def cequal?(a, b)
581  if number?(a) and number?(b)
582    fequal?(a.real, b.real) and fequal?(a.imag, b.imag)
583  else
584    false
585  end
586end
587
588def vcequal?(a, b)
589  if a.length != b.length
590    false
591  else
592    a.each_with_index do |x, i|
593      if cneq(x, b[i])
594        return false
595      end
596    end
597    true
598  end
599end
600
601alias cequal  cequal?
602alias vcequal vcequal?
603
604def vmaxdiff(v0, v1)
605  v0.dup.subtract(v1).peak
606end
607
608def list_p(obj)
609  array?(obj) and (not obj.empty?)
610end
611
612def any_arity(obj)
613  case obj
614  when Proc, Method
615    obj.arity
616  when String, Symbol
617    method(obj).arity
618  else
619    0
620  end
621end
622
623def arity_ok(func, args)
624  rargs = Snd.catch do any_arity(func) end.first
625  if integer?(rargs)
626    if rargs >= 0
627      args == rargs
628    else
629      args >= (rargs.abs - 1)   # We have no idea how much optional args.
630    end
631  else
632    false
633  end
634end
635
636def set_arity_ok(func, args)
637  arity_ok("set_#{func}", args)
638end
639
640if $with_test_nogui
641  def dismiss_all_dialogs
642  end
643else
644  def dismiss_all_dialogs
645    dialog_widgets.each do |dialog|
646      if array?(dialog)
647        if symbol?(dialog.car)
648          if is_managed?(dialog)
649            hide_widget(dialog)
650          end
651        else
652          dialog.each do |d|
653            if symbol?(d.car)
654              if is_managed?(dialog)
655                hide_widget(dialog)
656              end
657            end
658          end
659        end
660      end
661    end
662  end
663end
664
665def safe_display_edits(snd = false, chn = false, edpos = false, with_src = true)
666  Snd.catch(:all, lambda do |*args|
667    snd_display_prev_caller("display_edits: %s", args)
668  end) do
669    display_edits(snd, chn, edpos, with_src)
670  end.first
671end
672
673def safe_divide(a, b)
674  b.zero? ? a : (a / b)
675end
676
677set_with_background_processes(false)
678
679def make_color_with_catch(c1, c2, c3)
680  make_color(c1, c2, c3)
681rescue
682  make_color(1, 0, 0)
683end
684
685def file_copy(f1, f2)
686  if File.exist?(f1)
687    fin = File.open(f1, "r")
688    fout = File.open(f2, "w")
689    fout.write(fin.read) until fin.eof?
690    fin.close
691    fout.close
692  end
693end
694
695def delete_file(file)
696  File.owned?(file) and File.unlink(file)
697end
698
699def delete_files(*files)
700  files.each do |f| delete_file(f) end
701end
702
703def with_file(file, verbose = $DEBUG, &body)
704  if File.exist?(full_name = $sf_dir + file)
705    body.call(full_name)
706  else
707    if verbose
708      snd_display_prev_caller("%s missing?", full_name)
709    end
710  end
711end
712
713def with_gc_disabled
714  GC.disable
715  ret = yield
716  GC.enable
717  GC.start
718  ret
719end
720
721Snd_error_tags.each do |tag|
722  res = Snd.catch(tag) do Snd.throw(tag, "snd-test") end
723  if res.first != tag
724    snd_display("Snd.catch (throwing 1): %s -> %s", tag.inspect, res.inspect)
725  end
726  res = Snd.catch(:all) do Snd.raise(tag, "snd-test") end
727  if res.first != tag
728    snd_display("Snd.catch (raising 1): %s -> %s", tag.inspect, res.inspect)
729  end
730  res = Snd.catch(tag, :okay) do Snd.throw(tag, "snd-test") end
731  if res.first != :okay
732    snd_display("Snd.catch (throwing 2): %s -> %s", tag.inspect, res.inspect)
733  end
734  res = Snd.catch(:all, :okay) do Snd.raise(tag, "snd-test") end
735  if res.first != :okay
736    snd_display("Snd.catch (raising 2): %s -> %s", tag.inspect, res.inspect)
737  end
738end
739
740def cwd
741  Dir.pwd + "/"
742end
743
744class Snd_test_time
745  def initialize
746    @real_time     = Time.now
747    @process_time  = process_times
748    @real = @utime = @stime = 0.0
749  end
750  attr_reader :real, :utime, :stime
751
752  def inspect
753    format("#<Snd_test_time: %s>", self.to_s)
754  end
755
756  def to_s
757    format("real: %1.3f, user: %1.3f, system: %1.3f", @real, @utime, @stime)
758  end
759
760  def start
761    @real_time    = Time.now
762    @process_time = process_times
763  end
764
765  def stop
766    @real = Time.now - @real_time
767    cur_time = process_times
768    @utime = cur_time.utime - @process_time.utime
769    @stime = cur_time.stime - @process_time.stime
770  end
771end
772
773def with_time(msg = nil, &body)
774  stt = Snd_test_time.new
775  stt.start
776  body.call
777  stt.stop
778  if msg and $VERBOSE
779    snd_info("%s (%s)", stt.to_s, msg)
780  end
781  [stt.real, stt.utime, stt.stime]
782end
783
784def start_snd_test()
785  # map_chan* procedure
786  $init_channel  = lambda do |y| 1.0 end
787  $default_srate = 22050.0
788  $timings       = Array.new(0)
789  set_show_listener(true)
790  set_window_x(600)
791  set_window_y(10)
792  kind = if $with_test_motif
793           "motif"
794         elsif $with_test_nogui
795           "nogui"
796         else
797           "unknown"
798         end
799  snd_info("===  Snd version: %s (snd_%s)", snd_version, kind)
800  snd_info("=== Ruby version: %s (%s) [%s]",
801    RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_PLATFORM)
802  snd_info("")
803  snd_info("%s", Time.now.localtime.strftime("%a %d-%b-%Y %I:%M %p"))
804  snd_info("")
805  $overall_start_time = Snd_test_time.new
806end
807
808def finish_snd_test()
809  $overall_start_time.stop
810  Snd.regions.apply(:forget_region)
811  stop_playing
812  reset_almost_all_hooks
813  set_ask_about_unsaved_edits(false)
814  set_remember_sound_state(false)
815  snd_info("all done!")
816  snd_info("")
817  unless $timings.empty?
818    $timings.each do |tst|
819      snd_info("%s %p", tst.first, tst.last)
820    end
821  end
822  snd_info("total   %p\n", $overall_start_time)
823  set_show_listener(true)
824  save_listener("test-ruby.output")
825  clear_listener
826  set_show_listener(true)
827  set_listener_prompt($original_prompt)
828end
829
830def clear_test_files
831  fs = 0
832  [$original_save_dir, $original_temp_dir, "/tmp"].each do |path|
833    if File.exist?(path)
834      d = Dir[path + "/snd_*"]
835      fs += d.length
836      d.each do |f| delete_file(f) end
837    end
838  end
839  snd_info("%s temporary file%s deleted",
840    fs.zero? ? "no" : fs, fs.between?(0, 1) ? "" : "s")
841  mus_sound_prune
842  $snd_opened_sound = false
843  ["1",
844   "aaa.eps",
845   "accelmap",
846   "envs.save",
847   "fmv.snd",
848   "fmv.wav",
849   "fmv0.snd",
850   "fmv1.snd",
851   "fmv2.snd",
852   "fmv3.snd",
853   "fmv4.reverb",
854   "fmv4.snd",
855   "hiho.marks",
856   "hiho.rb",
857   "hiho.snd",
858   "hiho.snd",
859   "hiho.tmp",
860   "hiho.wave",
861   "ho",
862   "new.snd",
863   "oboe.marks",
864   "obtest.snd.stereo",
865   "remembered-oboe.snd.rb",
866   "saved-snd.rb",
867   "snd.eps",
868   "test-1.snd",
869   "test-2.snd",
870   "test-macros.scm",
871   "test.aifc",
872   "test.aiff",
873   "test.data",
874   "test.rev",
875   "test.reverb",
876   "test.rf64",
877   "test.snd",
878   "test.snd.snd",
879   "test.wav",
880   "test.wave",
881   "test.xpm",
882   "test1.snd",
883   "test1.reverb",
884   "test2.snd",
885   "test3.snd",
886   "tmp.snd",
887   "with-mix.rbm",
888   "with-mix.snd"].each do |file| delete_file(file) end
889  ["bad_sample_type.snd.snd",
890   "ce-c3.w02.snd",
891   "hcom-16.snd.snd",
892   "ieee-text-16.snd.snd",
893   "mus10.snd.snd",
894   "nasahal.avi.snd",
895   "nist-shortpack.wav.snd",
896   "o2_dvi.wave.snd",
897   "oki.wav.snd",
898   "trumps22.adp.snd",
899   "wood.sds.snd"].each do |file|
900    with_file(file, false) do delete_file(file) end
901  end
902end
903
904def before_test(func)
905  set_sync_style(Sync_none)
906  set_mus_srate($clm_srate = $default_srate.to_i)
907  set_clipping(false)
908  set_mus_clipping(false)
909  $timings.push([func, Snd_test_time.new])
910  snd_info("%s", func)
911end
912
913def after_test(func)
914  $timings.last.last.stop
915  if sounds
916    snd_info("%s: open sounds: %s", func, short_file_name(true))
917    Snd.sounds.apply(:close_sound)
918  end
919  Snd.regions.apply(:forget_region)
920  set_ask_about_unsaved_edits(false)
921  set_remember_sound_state(false)
922  dismiss_all_dialogs
923  if $VERBOSE
924    snd_info("%s done (%s)\n#", func, $timings.last.last)
925  else
926    snd_info("%s done\n#", func)
927  end
928end
929
930# returns body's return value or error symbol (eg. :no_such_sound)
931def without_errors(&body)
932  Snd.catch(:all) do
933    body.call
934  end.first
935end
936
937if $with_test_motif
938  module Test_event
939    # see event.scm
940    def key_event(widget, key, state)
941      e = RXEvent(RKeyPress)
942      dpy = RXtDisplay(widget)
943      window = RXtWindow(widget)
944      Rset_type(e, RKeyPress)
945      Rset_window(e, window)
946      Rset_display(e, dpy)
947      Rset_root(e, RRootWindow(dpy, RDefaultScreen(dpy)))
948      Rset_x(e, 0)
949      Rset_y(e, 0)
950      Rset_x_root(e, 0)
951      Rset_y_root(e, 0)
952      Rset_keycode(e, RXKeysymToKeycode(dpy, [:KeySym, key_to_int(key)]))
953      Rset_state(e, state)
954      Rset_time(e, [:Time, RCurrentTime])
955      Rset_same_screen(e, true)
956      Rset_subwindow(e, [:Window, RNone])
957      err = RXSendEvent(dpy, window, false, RKeyPressMask, e)
958      if err.nonzero?
959        Rset_type(e, RKeyRelease)
960        Rset_time(e, [:Time, RCurrentTime])
961        err = RXSendEvent(dpy, window, false, RKeyReleaseMask, e)
962      end
963      if err.zero?
964        snd_display("[key-event error] ", err)
965      end
966      err
967    end
968
969    def key_event_with_mouse(widget, key, state, x, y)
970      e = RXEvent(RKeyPress)
971      dpy = RXtDisplay(widget)
972      window = RXtWindow(widget)
973      Rset_type(e, RKeyPress)
974      Rset_window(e, window)
975      Rset_display(e, dpy)
976      Rset_root(e, RRootWindow(dpy, RDefaultScreen(dpy)))
977      Rset_x(e, x)
978      Rset_y(e, y)
979      Rset_x_root(e, x)
980      Rset_y_root(e, y)
981      Rset_keycode(e, RXKeysymToKeycode(dpy, [:KeySym, key_to_int(key)]))
982      Rset_state(e, state)
983      Rset_time(e, [:Time, RCurrentTime])
984      Rset_same_screen(e, true)
985      Rset_subwindow(e, [:Window, RNone])
986      err = RXSendEvent(dpy, window, false, RKeyPressMask, e)
987      if err.nonzero?
988        Rset_type(e, RKeyRelease)
989        Rset_time(e, [:Time, RCurrentTime])
990        err = RXSendEvent(dpy, window, false, RKeyReleaseMask, e)
991      end
992      if err.zero?
993        snd_display("[key-event error] ", err)
994      end
995      err
996    end
997
998    def resize_event(widget, width, height)
999      e = RXEvent(RResizeRequest)
1000      dpy = RXtDisplay(widget)
1001      window = RXtWindow(widget)
1002      Rset_window(e, window)
1003      Rset_display(e, dpy)
1004      Rset_width(e, width)
1005      Rset_height(e, height)
1006      RXSendEvent(dpy, window, false, RResizeRedirectMask, e)
1007    end
1008
1009    def enter_event(widget)
1010      e = RXEvent(REnterNotify)
1011      dpy = RXtDisplay(widget)
1012      window = RXtWindow(widget)
1013      Rset_window(e, window)
1014      Rset_display(e, dpy)
1015      RXSendEvent(dpy, window, false, REnterWindowMask, e)
1016    end
1017
1018    def leave_event(widget)
1019      e = RXEvent(RLeaveNotify)
1020      dpy = RXtDisplay(widget)
1021      window = RXtWindow(widget)
1022      Rset_window(e, window)
1023      Rset_display(e, dpy)
1024      RXSendEvent(dpy, window, false, RLeaveWindowMask, e)
1025    end
1026
1027    def expose_event(widget, x, y, width, height)
1028      e = RXEvent(RExpose)
1029      dpy = RXtDisplay(widget)
1030      window = RXtWindow(widget)
1031      Rset_window(e, window)
1032      Rset_display(e, dpy)
1033      Rset_x(e, x)
1034      Rset_y(e, y)
1035      Rset_width(e, width)
1036      Rset_height(e, height)
1037      Rset_count(e, 0)
1038      RXSendEvent(dpy, window, false, RExposureMask, e)
1039    end
1040
1041    def click_event(widget, button, state, x, y)
1042      e = RXEvent(RButtonPress)
1043      dpy = RXtDisplay(widget)
1044      window = RXtWindow(widget)
1045      Rset_type(e, RButtonPress)
1046      Rset_window(e, window)
1047      Rset_display(e, dpy)
1048      Rset_root(e, RRootWindow(dpy, RDefaultScreen(dpy)))
1049      Rset_x(e, x)
1050      Rset_y(e, y)
1051      Rset_x_root(e, 0)
1052      Rset_y_root(e, 0)
1053      Rset_state(e, state)
1054      Rset_button(e, button)
1055      Rset_time(e, [:Time, RCurrentTime])
1056      Rset_same_screen(e, true)
1057      Rset_subwindow(e, [:Window, RNone])
1058      err = RXSendEvent(dpy, window, false, RButtonPressMask, e)
1059      if err.nonzero?
1060        Rset_type(e, RButtonRelease)
1061        Rset_time(e, [:Time, RCurrentTime])
1062        err = RXSendEvent(dpy, window, false, RButtonReleaseMask, e)
1063      end
1064      if err.zero?
1065        snd_display("[click-event error] ", err)
1066      end
1067      err
1068    end
1069
1070    def drag_event(widget, button, state, x0, y0, x1, y1)
1071      e = RXEvent(RButtonPress)
1072      e1 = RXEvent(RMotionNotify)
1073      dpy = RXtDisplay(widget)
1074      window = RXtWindow(widget)
1075      Rset_type(e, RButtonPress)
1076      Rset_window(e, window)
1077      Rset_display(e, dpy)
1078      Rset_root(e, RRootWindow(dpy, RDefaultScreen(dpy)))
1079      Rset_x(e, x0)
1080      Rset_y(e, y0)
1081      Rset_x_root(e, 0)
1082      Rset_y_root(e, 0)
1083      Rset_state(e, state)
1084      Rset_button(e, button)
1085      Rset_time(e, [:Time, RCurrentTime])
1086      Rset_same_screen(e, true)
1087      Rset_subwindow(e, [:Window, RNone])
1088      err = RXSendEvent(dpy, window, false, RButtonPressMask, e)
1089      if err.nonzero?
1090        Rset_window(e1, window)
1091        Rset_display(e1, dpy)
1092        Rset_root(e1, RRootWindow(dpy, RDefaultScreen(dpy)))
1093        # Rset_x(e1, x1)
1094        # Rset_y(e1, y1)
1095        Rset_x_root(e1, x0)
1096        Rset_y_root(e1, y0)
1097        Rset_state(e1, state)
1098        Rset_time(e1, [:Time, RCurrentTime + 300])
1099        Rset_same_screen(e1, true)
1100        Rset_subwindow(e1, [:Window, RNone])
1101        Rset_is_hint(e1, RNotifyNormal)
1102        den = if (x1 - x0).abs > 10 or (y1 - y0).abs > 10
1103                10
1104              else
1105                2
1106              end
1107        xdiff = ((x1 - x0) / den.to_f).floor
1108        ydiff = ((y1 - y0) / den.to_f).floor
1109        xn = x0 + xdiff
1110        yn = y0 + ydiff
1111        den.times do
1112          Rset_x(e1, xn)
1113          Rset_y(e1, yn)
1114          RXSendEvent(dpy, window, false, RButtonMotionMask, e1)
1115          xn += xdiff
1116          yn += ydiff
1117        end
1118        Rset_type(e, RButtonRelease)
1119        Rset_time(e, [:Time, RCurrentTime + 500])
1120        Rset_x(e, x1)
1121        Rset_y(e, y1)
1122        RXSendEvent(dpy, window, false, RButtonReleaseMask, e)
1123      end
1124    end
1125
1126    def select_item(wid, pos)
1127      if RXmIsList(wid)
1128        RXmListSelectPos(wid, pos + 1, true)
1129      else
1130        snd_display("is not a list!", RXtName(wid))
1131      end
1132    end
1133
1134    def click_button(button, value = false, bits = false)
1135      if RWidget?(button)
1136        if RXtIsSensitive(button)
1137          if RXmIsPushButton(button) or RXmIsPushButtonGadget(button)
1138            if RXtHasCallbacks(button,
1139                 RXmNactivateCallback) == RXtCallbackHasSome
1140              but = RXmPushButtonCallbackStruct()
1141              Rset_click_count(but, 0)
1142              e = RXEvent(RButtonPress)
1143              Rset_state(e, (bits or 0))
1144              Rset_event(but, e)
1145              RXtCallCallbacks(button, RXmNactivateCallback, but)
1146            else
1147              snd_display("pushbutton %s has no active callbacks",
1148                RXtName(button))
1149            end
1150          else
1151            if RXmIsToggleButton(button) or RXmIsToggleButtonGadget(button)
1152              if RXtHasCallbacks(button,
1153                   RXmNvalueChangedCallback) == RXtCallbackHasSome
1154                tgl = RXmToggleButtonCallbackStruct()
1155                Rset_set(tgl, value)
1156                e = RXEvent(RButtonPress)
1157                Rset_state(e, (bits or 0))
1158                Rset_event(tgl, e)
1159                RXtCallCallbacks(button, RXmNvalueChangedCallback, tgl)
1160              else
1161                snd_display("togglebutton %s has no valueChanged callbacks",
1162                  RXtName(button))
1163              end
1164            else
1165              if RXmIsArrowButton(button)
1166                if RXtHasCallbacks(button,
1167                     RXmNactivateCallback) == RXtCallbackHasSome
1168                  arr = RXmArrowButtonCallbackStruct()
1169                  Rset_click_count(arr, 0)
1170                  e = RXEvent(RButtonPress)
1171                  Rset_state(e, (bits or 0))
1172                  Rset_event(arr, e)
1173                  RXtCallCallbacks(button, RXmNactivateCallback, arr)
1174                else
1175                  snd_display("arrowbutton %s has no active callbacks",
1176                    RXtName(button))
1177                end
1178              else
1179                snd_display("%s (%s) is not a push or toggle button",
1180                            RXtName(button),
1181                            RXtName(RXtParent(button)))
1182              end
1183            end
1184          end
1185        else
1186          snd_display("%s is not sensitive", RXtName(button))
1187        end
1188      else
1189        snd_display("%s is not a widget", button)
1190      end
1191    end
1192
1193    def resize_pane(wid, height)
1194      RXtUnmanageChild(wid)
1195      RXtVaSetValues(wid,
1196                     [RXmNpaneMinimum, (height > 5 ? (height - 5) : 0),
1197                      RXmNpaneMaximum, height + 5])
1198      RXtManageChild(wid)
1199      RXtVaSetValues(wid, [RXmNpaneMinimum, 5, RXmNpaneMaximum, 1000])
1200    end
1201
1202    def force_event
1203      app = main_widgets.car
1204      msk = RXtIMXEvent | RXtIMAlternateInput
1205      until (RXtAppPending(app) & msk).zero?
1206        RXtDispatchEvent(RXtAppNextEvent(app))
1207      end
1208    end
1209
1210    def take_keyboard_focus(wid)
1211      if RXmIsTraversable(wid) and
1212           (RXmGetVisibility(wid) != RXmVISIBILITY_FULLY_OBSCURED)
1213        RXmProcessTraversal(wid, RXmTRAVERSE_CURRENT)
1214      end
1215    end
1216
1217    def move_scale(scl, val)
1218      RXmScaleSetValue(scl, val)
1219      cb = RXmScaleCallbackStruct()
1220      Rset_value(cb, val)
1221      Rset_event(cb, RXEvent())
1222      RXtCallCallbacks(scl, RXmNvalueChangedCallback, cb)
1223    end
1224
1225    def change_prop(winat, name, command)
1226      find_window = lambda do |dpy, top, natom|
1227        res = RXGetWindowProperty(dpy, top, natom, 0, 1024, false, RXA_STRING)
1228        if res[0] == RSuccess and res[1] != [:Atom, RNone]
1229          top
1230        else
1231          vals = RXQueryTree(dpy, top)
1232          if vals[0].zero?
1233            false
1234          else
1235            vals[3].each do |win|
1236              if RWindow?(val = find_window.call(dpy, win, natom))
1237                return val
1238              end
1239            end
1240            false
1241          end
1242        end
1243      end
1244      dpy = RXtDisplay(main_widgets[1])
1245      natom = RXInternAtom(dpy, winat, false)
1246      window = find_window.call(dpy, RDefaultRootWindow(dpy), natom)
1247      if RWindow?(window)
1248        RXChangeProperty(dpy, window,
1249          RXInternAtom(dpy, name, false),
1250          RXA_STRING, 8, RPropModeReplace, command)
1251        RXFlush(dpy)
1252        command
1253      else
1254        false
1255      end
1256    end
1257
1258    make_proc_with_setter(:beep_state,
1259      # return amp pitch duration
1260      lambda do
1261        vals = RXGetKeyboardControl(RXtDisplay(main_widgets.cadr))[1, 3]
1262      end,
1263      # amp pitch dur
1264      # set_beep_state([100, 200, 100])
1265      lambda do |lst|
1266        RXChangeKeyboardControl(RXtDisplay(main_widgets.cadr),
1267        RKBBellPercent |
1268        RKBBellPitch |
1269        RKBBellDuration,
1270        [0] + lst)
1271      end)
1272
1273    def beep
1274      RXBell(RXtDisplay(main_widgets.cadr), 100)
1275    end
1276  end
1277  include Test_event
1278end
1279
1280# snd-test.scm translations
1281# ---------------- test 00: constants ----------------
1282
1283Tiny_font_string = $with_test_motif ? "6x12" : "9x15"
1284Tiny_font_set_string = $with_test_motif ? "9x15" : "6x12"
1285
1286# XXX: temp_dir save_dir ladspa_dir peak_env_dir
1287#
1288# These variables default to NULL (snd.c/snd-0.h).
1289# snd-test.scm checks for #f
1290# snd-test.rb  checks for ""
1291
1292def test_00
1293  if sounds or mixes or marks or regions
1294    snd_display("start up sounds: %s, mixes: %s, marks: %s, regions: %s",
1295                sounds.inspect,
1296                mixes.inspect,
1297                marks.inspect,
1298                regions.inspect)
1299  end
1300  [[:Enved_amplitude, 0],
1301   [:Bartlett_window, 4],
1302   [:Bartlett_hann_window, 21],
1303   [:Blackman2_window, 6],
1304   [:Blackman3_window, 7],
1305   [:Blackman4_window, 8],
1306   [:Blackman5_window, 24],
1307   [:Blackman6_window, 25],
1308   [:Blackman7_window, 26],
1309   [:Blackman8_window, 27],
1310   [:Blackman9_window, 28],
1311   [:Blackman10_window, 29],
1312   [:Bohman_window, 22],
1313   [:Cauchy_window, 12],
1314   [:Mlt_sine_window, 33],
1315   [:Papoulis_window, 34],
1316   [:Dpss_window, 35],
1317   [:Sinc_window, 36],
1318   [:Channels_combined, 1],
1319   [:Channels_separate, 0],
1320   [:Channels_superimposed, 2],
1321   [:Connes_window, 18],
1322   [:Cursor_in_middle, 3],
1323   [:Cursor_in_view, 0],
1324   [:Cursor_on_left, 1],
1325   [:Cursor_on_right, 2],
1326   [:Exponential_window, 9],
1327   [:Flat_top_window, 23],
1328   [:Sync_none, 0],
1329   [:Sync_all, 1],
1330   [:Sync_by_sound, 2],
1331   [:Zoom_focus_active, 2],
1332   [:Zoom_focus_left, 0],
1333   [:Zoom_focus_middle, 3],
1334   [:Zoom_focus_right, 1],
1335   [:Gaussian_window, 14],
1336   [:Graph_dots, 1],
1337   [:Graph_dots_and_lines, 3],
1338   [:Graph_filled, 2],
1339   [:Graph_lines, 0],
1340   [:Graph_lollipops, 4],
1341   [:Hamming_window, 5],
1342   [:Hann_window, 1],
1343   [:Hann_poisson_window, 17],
1344   [:Kaiser_window, 11],
1345   [:Keyboard_no_action, 4],
1346   [:Parzen_window, 3],
1347   [:Poisson_window, 13],
1348   [:Rectangular_window, 0],
1349   [:Riemann_window, 10],
1350   [:Rv2_window, 30],
1351   [:Rv3_window, 31],
1352   [:Rv4_window, 32],
1353   [:Graph_as_sonogram, 1],
1354   [:Graph_as_spectrogram, 2],
1355   [:Graph_once, 0],
1356   [:Graph_as_wavogram, 3],
1357   [:Enved_spectrum, 1],
1358   [:Speed_control_as_float, 0],
1359   [:Speed_control_as_ratio, 1],
1360   [:Speed_control_as_semitone, 2],
1361   [:Enved_srate, 2],
1362   [:Tukey_window, 15],
1363   [:Welch_window, 2],
1364   [:Cursor_cross, 0],
1365   [:Cursor_line, 1],
1366   [:Dont_normalize, 0],
1367   [:Envelope_linear, 0],
1368   [:Envelope_exponential, 1],
1369   [:Normalize_by_channel, 1],
1370   [:Normalize_by_sound, 2],
1371   [:Normalize_globally, 3],
1372   [:X_axis_in_samples, 1],
1373   [:X_axis_in_beats, 3],
1374   [:X_axis_in_measures, 4],
1375   [:X_axis_in_seconds, 0],
1376   [:X_axis_as_clock, 5],
1377   [:X_axis_as_percentage, 2],
1378   [:Enved_add_point, 0],
1379   [:Enved_delete_point, 1],
1380   [:Enved_move_point, 2],
1381   [:Time_graph, 0],
1382   [:Transform_graph, 1],
1383   [:Lisp_graph, 2],
1384   [:Copy_context, 0],
1385   [:Cursor_context, 3],
1386   [:Selection_context, 2],
1387   [:Mark_context, 4],
1388   [:Show_no_axes, 0],
1389   [:Show_all_axes, 1],
1390   [:Show_x_axis, 2],
1391   [:Show_all_axes_unlabelled, 3],
1392   [:Show_x_axis_unlabelled, 4],
1393   [:Show_bare_x_axis, 5],
1394   # sndlib constants
1395   [:Mus_unknown_header, 0],
1396   [:Mus_next, 1],
1397   [:Mus_aifc, 2],
1398   [:Mus_riff, 3],
1399   [:Mus_nist, 6],
1400   [:Mus_raw, 12],
1401   [:Mus_ircam, 15],
1402   [:Mus_aiff, 49],
1403   [:Mus_bicsf, 5],
1404   [:Mus_voc, 10],
1405   [:Mus_svx, 9],
1406   [:Mus_soundfont, 26],
1407   [:Mus_rf64, 4],
1408   [:Mus_caff, 60],
1409   #
1410   [:Mus_interp_none, 0],
1411   [:Mus_interp_linear, 1],
1412   [:Mus_interp_sinusoidal, 2],
1413   [:Mus_interp_all_pass, 3],
1414   [:Mus_interp_lagrange, 4],
1415   [:Mus_interp_bezier, 5],
1416   [:Mus_interp_hermite, 6],
1417   #
1418   [:Mus_chebyshev_first_kind, 1],
1419   [:Mus_chebyshev_second_kind, 2],
1420   #
1421   [:Mus_unknown_sample, 0],
1422   [:Mus_bshort, 1],
1423   [:Mus_lshort, 10],
1424   [:Mus_mulaw, 2],
1425   [:Mus_alaw, 6],
1426   [:Mus_byte, 3],
1427   [:Mus_ubyte, 7],
1428   [:Mus_bfloat, 4],
1429   [:Mus_lfloat, 12],
1430   [:Mus_bint, 5],
1431   [:Mus_lint, 11],
1432   [:Mus_bintn, 17],
1433   [:Mus_lintn, 18],
1434   [:Mus_b24int, 8],
1435   [:Mus_l24int, 16],
1436   [:Mus_bdouble, 9],
1437   [:Mus_ldouble, 13],
1438   [:Mus_ubshort, 14],
1439   [:Mus_ulshort, 15],
1440   [:Mus_bfloat_unscaled, 19],
1441   [:Mus_lfloat_unscaled, 20],
1442   [:Mus_bdouble_unscaled, 21],
1443   [:Mus_ldouble_unscaled, 22]].each do |sym, req|
1444    snd_test_neq(Module.const_get(sym), req, "%s", sym)
1445  end
1446  if $with_test_gsl
1447    [[:Dolph_chebyshev_window, 16],
1448     [:Samaraki_window, 19],
1449     [:Ultraspherical_window, 20]].each do |sym, req|
1450      snd_test_neq(Module.const_get(sym), req, "%s", sym)
1451    end
1452  end
1453  #
1454  old_dir = temp_dir
1455  set_temp_dir(false)
1456  [[:region_graph_style, Graph_lines],
1457   [:ask_about_unsaved_edits, false],
1458   [:show_full_duration, false],
1459   [:show_full_range, false],
1460   [:initial_beg, 0.0],
1461   [:initial_dur, 0.1],
1462   [:ask_before_overwrite, false],
1463   [:auto_resize, true],
1464   [:auto_update, false],
1465   [:channel_style, 1],
1466   [:color_cutoff, 0.003],
1467   [:color_inverted, true],
1468   [:color_scale, 1.0],
1469   [:auto_update_interval, 60.0],
1470   [:cursor_update_interval, 0.05],
1471   [:cursor_location_offset, 0],
1472   [:dac_combines_channels, true],
1473   [:dac_size, 256],
1474   [:clipping, false],
1475   [:default_output_chans, 1],
1476   [:default_output_sample_type, Mus_lfloat],
1477   [:default_output_srate, 44100],
1478   [:default_output_header_type, Mus_next],
1479   [:dot_size, 1],
1480   [:cursor_size, 15],
1481   [:cursor_style, Cursor_cross],
1482   [:tracking_cursor_style, Cursor_line],
1483   [:enved_base, 1.0],
1484   [:enved_clip?, true],
1485   [:enved_filter, true],
1486   [:enved_filter_order, 40],
1487   [:enved_in_dB, false],
1488   [:enved_style, Envelope_linear],
1489   [:enved_power, 3.0],
1490   [:enved_target, 0],
1491   [:enved_wave?, false],
1492   [:enved_envelope, nil],
1493   [:eps_file, "snd.eps"],
1494   [:eps_bottom_margin, 0.0],
1495   [:eps_left_margin, 0.0],
1496   [:eps_size, 1.0],
1497   [:fft_window_alpha, 0.0],
1498   [:fft_window_beta, 0.0],
1499   [:fft_log_frequency, false],
1500   [:fft_log_magnitude, false],
1501   [:fft_with_phases, false],
1502   [:transform_size, 512],
1503   [:transform_graph_type, Graph_once],
1504   [:fft_window, 6],
1505   [:graph_cursor, 34],
1506   [:graph_style, Graph_lines],
1507   [:graphs_horizontal, true],
1508   [:html_dir, "."],
1509   [:html_program, "firefox"],
1510   [:just_sounds, true],
1511   [:listener_prompt, ">"],
1512   [:max_transform_peaks, 100],
1513   [:max_regions, 16],
1514   [:min_dB, -60.0],
1515   [:log_freq_start, 32.0],
1516   [:selection_creates_region, true],
1517   [:transform_normalization, Normalize_by_channel],
1518   [:print_length, 12],
1519   [:play_arrow_size, 10],
1520   [:save_state_file, "saved-snd.rb"],
1521   [:show_axes, 1],
1522   [:show_transform_peaks, false],
1523   [:show_indices, false],
1524   [:show_marks, true],
1525   [:show_mix_waveforms, true],
1526   [:show_selection_transform, false],
1527   [:show_y_zero, false],
1528   [:show_grid, false],
1529   [:grid_density, 1.0],
1530   [:show_sonogram_cursor, false],
1531   [:sinc_width, 10],
1532   [:spectrum_end, 1.0],
1533   [:spectro_hop, 4],
1534   [:spectrum_start, 0.0],
1535   [:spectro_x_angle, ($with_test_gl ? 300.0 : 90.0)],
1536   [:spectro_x_scale, ($with_test_gl ? 1.5 : 1.0)],
1537   [:spectro_y_angle, ($with_test_gl ? 320.0 : 0.0)],
1538   [:spectro_y_scale, 1.0],
1539   [:spectro_z_angle, ($with_test_gl ? 0.0 : 358.0)],
1540   [:spectro_z_scale, ($with_test_gl ? 1.0 : 0.1)],
1541   [:temp_dir, ""],
1542   [:ladspa_dir, ""],
1543   [:peak_env_dir, ""],
1544   [:tiny_font, Tiny_font_string],
1545   [:transform_type, $fourier_transform],
1546   [:with_file_monitor, true],
1547   [:clm_table_size, 512],
1548   [:with_verbose_cursor, false],
1549   [:with_inset_graph, false],
1550   [:with_interrupts, true],
1551   [:remember_sound_state, false],
1552   [:with_smpte_label, false],
1553   [:with_toolbar, false],
1554   [:with_tooltips, true],
1555   [:with_menu_icons, false],
1556   [:save_as_dialog_src, false],
1557   [:save_as_dialog_auto_comment, false],
1558   [:with_pointer_focus, false],
1559   [:wavelet_type, 0],
1560   [:time_graph_type, Graph_once],
1561   [:wavo_hop, 3],
1562   [:wavo_trace, 64],
1563   [:x_axis_style, 0],
1564   [:beats_per_minute, 60.0],
1565   [:beats_per_measure, 4],
1566   [:zero_pad, 0],
1567   [:zoom_focus_style, 2],
1568   [:sync_style, Sync_by_sound],
1569   [:mix_waveform_height, 20],
1570   [:mix_tag_width, 6],
1571   [:mix_tag_height, 14],
1572   [:mark_tag_width, 10],
1573   [:mark_tag_height, 4]].each do |sym, req|
1574    snd_test_neq(set_snd_func(sym, snd_func(sym)), req, "set_%s", sym)
1575  end
1576  set_temp_dir(old_dir)
1577  #
1578  set_max_transform_peaks(-123)
1579  set_zero_pad(-123)
1580  [[:max_transform_peaks, 100],
1581   [:zero_pad, 0]].each do |sym, req|
1582    snd_test_neq(set_snd_func(sym, snd_func(sym)), req, "set_%s", sym)
1583  end
1584  snd_test_neq(zero_pad(true, true), nil, "zero_pad(true, true)")
1585  if $with_test_motif
1586    [:axis_label_font,
1587     :axis_numbers_font,
1588     :tiny_font,
1589     :peaks_font,
1590     :bold_peaks_font].each do |sym|
1591      req = snd_func(sym)
1592      snd_test_neq(set_snd_func(sym, "8x123"), req,
1593        "set_%s to bogus value", sym)
1594    end
1595  end
1596  set_ask_about_unsaved_edits(false)
1597  set_remember_sound_state(false)
1598end
1599
1600# ---------------- test 01: defaults ----------------
1601
1602$good_colormap   = $hot_colormap
1603$better_colormap = $black_and_white_colormap
1604
1605def test_01
1606  if $with_test_gui
1607    unless colormap?($good_colormap)
1608      $good_colormap = false
1609      (1..20).each do |i|
1610        col = integer2colormap(i)
1611        if colormap?(col)
1612          $good_colormap = col
1613          break
1614        end
1615      end
1616    end
1617    unless colormap?($better_colormap)
1618      $better_colormap = false
1619      (colormap2integer($good_colormap)..20).each do |i|
1620        col = integer2colormap(i)
1621        if colormap?(col)
1622          $better_colormap = col
1623          break
1624        end
1625      end
1626    end
1627  end
1628  #
1629  old_dir = temp_dir
1630  set_temp_dir(false)
1631  [["amp_control", without_errors do amp_control() end, :no_such_sound],
1632   ["amp_control_bounds", amp_control_bounds()[1], 8.0],
1633   ["ask_about_unsaved_edits", ask_about_unsaved_edits(), false],
1634   ["ask_before_overwrite", ask_before_overwrite(), false],
1635   ["auto_resize", auto_resize(), true],
1636   ["auto_update", auto_update(), false],
1637   ["auto_update_interval", auto_update_interval(), 60.0],
1638   ["beats_per_measure", beats_per_measure(), 4],
1639   ["beats_per_minute", beats_per_minute(), 60.0],
1640   ["channel_style", channel_style(), 1],
1641   ["clipping", clipping(), false],
1642   ["clm_table_size", clm_table_size(), 512],
1643   ["color_cutoff", color_cutoff(), 0.003],
1644   ["color_inverted", color_inverted(), true],
1645   ["color_scale", color_scale(), 1.0],
1646   ["colormap", colormap(), $good_colormap],
1647   ["contrast_control", without_errors do
1648       contrast_control()
1649     end, :no_such_sound],
1650   ["contrast_control_amp", contrast_control_amp(), 1.0],
1651   ["contrast_control_bounds", contrast_control_bounds()[1], 10.0],
1652   ["contrast_control?", without_errors do
1653       contrast_control?()
1654     end, :no_such_sound],
1655   ["with_tracking_cursor", with_tracking_cursor(), false],
1656   ["cursor_location_offset", cursor_location_offset(), 0],
1657   ["cursor_size", cursor_size(), 15],
1658   ["cursor_style", cursor_style(), Cursor_cross],
1659   ["cursor_update_interval", cursor_update_interval(), 0.05],
1660   ["dac_combines_channels", dac_combines_channels(), true],
1661   ["dac_size", dac_size(), 256],
1662   ["default_output_chans", default_output_chans(), 1],
1663   ["default_output_sample_type", default_output_sample_type(), Mus_lfloat],
1664   ["default_output_header_type", default_output_header_type(), Mus_next],
1665   ["default_output_srate", default_output_srate(), 44100],
1666   ["dot_size", dot_size(), 1],
1667   ["enved_base", enved_base(), 1.0],
1668   ["enved_clip?", enved_clip?(), true],
1669   ["enved_envelope", enved_envelope(), nil],
1670   ["enved_filter", enved_filter(), true],
1671   ["enved_filter_order", enved_filter_order(), 40],
1672   ["enved_in_dB", enved_in_dB(), false],
1673   ["enved_power", enved_power(), 3.0],
1674   ["enved_style", enved_style(), Envelope_linear],
1675   ["enved_target", enved_target(), 0],
1676   ["enved_wave?", enved_wave?(), false],
1677   ["eps_bottom_margin", eps_bottom_margin(), 0.0],
1678   ["eps_file", eps_file(), "snd.eps"],
1679   ["eps_left_margin", eps_left_margin(), 0.0],
1680   ["eps_size", eps_size(), 1.0],
1681   ["expand_control", without_errors do
1682       expand_control()
1683     end, :no_such_sound],
1684   ["expand_control_bounds", expand_control_bounds()[1], 20.0],
1685   ["expand_control_hop", expand_control_hop(), 0.05],
1686   ["expand_control_jitter", expand_control_jitter(), 0.1],
1687   ["expand_control_length", expand_control_length(), 0.15],
1688   ["expand_control_ramp", expand_control_ramp(), 0.4],
1689   ["expand_control?", without_errors do
1690       expand_control?()
1691     end, :no_such_sound],
1692   ["fft_log_frequency", fft_log_frequency(), false],
1693   ["fft_log_magnitude", fft_log_magnitude(), false],
1694   ["fft_with_phases", fft_with_phases(), false],
1695   ["fft_window", fft_window(), 6],
1696   ["fft_window_alpha", fft_window_alpha(), 0.0],
1697   ["fft_window_beta", fft_window_beta(), 0.0],
1698   ["filter_control_coeffs", without_errors do
1699       filter_control_coeffs()
1700     end, :no_such_sound],
1701   ["filter_control_envelope", without_errors do
1702       filter_control_envelope()
1703     end, :no_such_sound],
1704   ["filter_control_in_dB", filter_control_in_dB(), false],
1705   ["filter_control_in_hz", filter_control_in_hz(), false],
1706   ["filter_control_order", filter_control_order(), 20],
1707   ["filter_control?", without_errors do
1708       filter_control?()
1709     end, :no_such_sound],
1710   ["graph_cursor", graph_cursor(), 34],
1711   ["graph_style", graph_style(), Graph_lines],
1712   ["graphs_horizontal", graphs_horizontal(), true],
1713   ["grid_density", grid_density(), 1.0],
1714   ["html_dir", html_dir(), "."],
1715   ["html_program", html_program(), "firefox"],
1716   ["initial_beg", initial_beg(), 0.0],
1717   ["initial_dur", initial_dur(), 0.1],
1718   ["just_sounds", just_sounds(), true],
1719   ["ladspa_dir", ladspa_dir(), ""],
1720   ["peak_env_dir", peak_env_dir(), ""],
1721   ["lisp_graph?", without_errors do lisp_graph?() end, :no_such_sound],
1722   ["listener_prompt", listener_prompt(), ">"],
1723   ["log_freq_start", log_freq_start(), 32.0],
1724   ["mark_tag_height", mark_tag_height(), 4],
1725   ["mark_tag_width", mark_tag_width(), 10],
1726   ["max_regions", max_regions(), 16],
1727   ["max_transform_peaks", max_transform_peaks(), 100],
1728   ["min_dB", min_dB(), -60.0],
1729   ["mix_tag_height", mix_tag_height(), 14],
1730   ["mix_tag_width", mix_tag_width(), 6],
1731   ["mix_waveform_height", mix_waveform_height(), 20],
1732   ["mus_array_print_length", mus_array_print_length(), 8],
1733   ["mus_clipping", mus_clipping(), false],
1734   ["mus_float_equal_fudge_factor", mus_float_equal_fudge_factor(), 0.0000001],
1735   ["play_arrow_size", play_arrow_size(), 10],
1736   ["print_length", print_length(), 12],
1737   ["read_only", without_errors do read_only() end, :no_such_sound],
1738   ["region_graph_style", region_graph_style(), Graph_lines],
1739   ["remember_sound_state", remember_sound_state(), false],
1740   ["reverb_control_feedback", reverb_control_feedback(), 1.09],
1741   ["reverb_control_length", without_errors do
1742       reverb_control_length()
1743     end, :no_such_sound],
1744   ["reverb_control_length_bounds", reverb_control_length_bounds()[1], 5.0],
1745   ["reverb_control_lowpass", reverb_control_lowpass(), 0.7],
1746   ["reverb_control_scale", without_errors do
1747       reverb_control_scale()
1748     end, :no_such_sound],
1749   ["reverb_control_scale_bounds", reverb_control_scale_bounds()[1], 4.0],
1750   ["reverb_control?", without_errors do
1751       reverb_control?()
1752     end, :no_such_sound],
1753   ["save_as_dialog_auto_comment", save_as_dialog_auto_comment, false],
1754   ["save_as_dialog_src", save_as_dialog_src, false],
1755   ["save_state_file", save_state_file(), "saved-snd.rb"],
1756   ["selection_creates_region", selection_creates_region(), true],
1757   ["show_axes", show_axes(), 1],
1758   ["show_controls", show_controls(), false],
1759   ["show_full_duration", show_full_duration(), false],
1760   ["show_full_range", show_full_range(), false],
1761   ["show_grid", show_grid(), false],
1762   ["show_indices", show_indices(), false],
1763   ["show_marks", show_marks(), true],
1764   ["show_mix_waveforms", show_mix_waveforms(), true],
1765   ["show_selection_transform", show_selection_transform(), false],
1766   ["show_sonogram_cursor", show_sonogram_cursor(), false],
1767   ["show_transform_peaks", show_transform_peaks(), false],
1768   ["show_y_zero", show_y_zero(), false],
1769   ["sinc_width", sinc_width(), 10],
1770   ["spectrum_end", spectrum_end(), 1.0],
1771   ["spectro_hop", spectro_hop(), 4],
1772   ["spectrum_start", spectrum_start(), 0.0],
1773   ["spectro_x_angle", spectro_x_angle(), ($with_test_gl ? 300.0 : 90.0)],
1774   ["spectro_x_scale", spectro_x_scale(), ($with_test_gl ? 1.5 : 1.0)],
1775   ["spectro_y_angle", spectro_y_angle(), ($with_test_gl ? 320.0 : 0.0)],
1776   ["spectro_y_scale", spectro_y_scale(), 1.0],
1777   ["spectro_z_angle", spectro_z_angle(), ($with_test_gl ? 0.0 : 358.0)],
1778   ["spectro_z_scale", spectro_z_scale(), ($with_test_gl ? 1.0 : 0.1)],
1779   ["speed_control", without_errors do speed_control() end, :no_such_sound],
1780   ["speed_control_bounds", speed_control_bounds()[1], 20.0],
1781   ["sync", without_errors do sync() end, :no_such_sound],
1782   ["sync_style", sync_style(), Sync_by_sound],
1783   ["temp_dir", temp_dir(), ""],
1784   ["time_graph_type", time_graph_type(), Graph_once],
1785   ["time_graph?", without_errors do time_graph?() end, :no_such_sound],
1786   ["tiny_font", tiny_font(), Tiny_font_string],
1787   ["tracking_cursor_style", tracking_cursor_style(), Cursor_line],
1788   ["transform_graph_type", transform_graph_type(), Graph_once],
1789   ["transform_graph?", without_errors do
1790       transform_graph?()
1791     end, :no_such_sound],
1792   ["transform_normalization", transform_normalization(), Normalize_by_channel],
1793   ["transform_size", transform_size(), 512],
1794   ["transform_type", transform_type(), $fourier_transform],
1795   ["wavelet_type", wavelet_type(), 0],
1796   ["wavo_hop", wavo_hop(), 3],
1797   ["wavo_trace", wavo_trace(), 64],
1798   ["with_mix_tags", with_mix_tags(), true],
1799   ["with_relative_panes", with_relative_panes(), true],
1800   ["with_tracking_cursor", with_tracking_cursor(), false],
1801   ["with_verbose_cursor", with_verbose_cursor(), false],
1802   ["with_inset_graph", with_inset_graph(), false],
1803   ["with_interrupts", with_interrupts(), true],
1804   ["with_smpte_label", with_smpte_label, false],
1805   ["with_toolbar", with_toolbar, false],
1806   ["with_tooltips", with_tooltips, true],
1807   ["with_menu_icons", with_menu_icons, false],
1808   ["with_pointer_focus", with_pointer_focus(), false],
1809   ["x_axis_style", x_axis_style(), 0],
1810   ["zero_pad", zero_pad(), 0],
1811   ["zoom_focus_style", zoom_focus_style(), 2]].each do |name, res, req|
1812    snd_test_neq(res, req, name)
1813  end
1814  set_temp_dir(old_dir)
1815  snd_test_neq($snd_opened_sound, false, "$snd_opened_sound")
1816  set_ask_about_unsaved_edits(false)
1817  set_remember_sound_state(false)
1818end
1819
1820# ---------------- test 02: headers ----------------
1821
1822def test_headers(name, chns, sr, dur, typ, frm,
1823                 loop_start = false, loop_end = false)
1824  if File.exist?(name)
1825    file = name
1826  else
1827    file = $sf_dir + name
1828  end
1829  if File.exist?(file)
1830    fchns = mus_sound_chans(file)
1831    fsr = mus_sound_srate(file)
1832    fdur = mus_sound_duration(file)
1833    if fchns != chns
1834      snd_display_prev_caller(snd_format_neq(fchns, chns, "%s chans", name))
1835    end
1836    if fsr != sr
1837      snd_display_prev_caller(snd_format_neq(fsr, sr, "%s srate", name))
1838    end
1839    if fneq(fdur, dur)
1840      snd_display_prev_caller(snd_format_neq(fdur, dur, "%s duration", name))
1841    end
1842    ffrm = mus_sound_sample_type(file)
1843    ftyp = mus_sound_header_type(file)
1844    req = mus_sound_length(file)
1845    res = mus_sound_datum_size(file) * fdur * fsr * fchns
1846    if (ffrm != Mus_unknown_sample) and
1847        (ftyp != 27) and
1848        (req + 1) < res
1849      snd_display_prev_caller(snd_format_neq(res, req, "%s length", name))
1850    end
1851    fframples = mus_sound_framples(file)
1852    res = fframples.to_f / fsr
1853    if fneq(res, fdur)
1854      snd_display_prev_caller(snd_format_neq(res, fdur, "%s framples", name))
1855    end
1856    fsamps = mus_sound_samples(file)
1857    res = fframples - fsamps / fchns
1858    if res.abs > 1
1859      snd_display_prev_caller(snd_format_neq(res, fsamps, "%s samples", name))
1860    end
1861    res = mus_header_type_name(ftyp)
1862    if res != typ
1863      snd_display_prev_caller(snd_format_neq(res, typ, "%s type", name))
1864    end
1865    res = mus_sample_type_name(ffrm)
1866    if res != frm
1867      snd_display_prev_caller(snd_format_neq(res, frm, "%s format", name))
1868    end
1869    lst = mus_sound_loop_info(file)
1870    if loop_start and loop_end
1871      if (not lst.nil?) and lst.length > 1
1872        if lst[0] != loop_start
1873          snd_display_prev_caller(snd_format_neq(lst[0],
1874            loop_start, "%s loop start", name))
1875        end
1876        if lst[1] != loop_end
1877          snd_display_prev_caller(snd_format_neq(lst[1],
1878            loop_end, "%s loop end", name))
1879        end
1880      else
1881        snd_display_prev_caller("%s loop info empty: %s?", name, lst.inspect)
1882      end
1883    else
1884      unless lst.nil?
1885        snd_display_prev_caller("%s thinks it has loop info: %s?", name, lst)
1886      end
1887    end
1888    mus_sound_forget(file)
1889  else
1890    if $DEBUG
1891      snd_display_prev_caller("%s missing?", file)
1892    end
1893  end
1894end
1895
1896def test_02
1897  test_headers("5_secs.aiff", 1, 44100, 5.303107, "AIFF", "big endian short (16 bits)")
1898  test_headers("8svx-8.snd", 1, 22050, 1.88766443729401, "SVX8", "signed byte (8 bits)")
1899  test_headers("Fnonull.aif", 1, 8000, 0.00112499995157123, "AIFC", "mulaw (8 bits)")
1900  test_headers("Pmiscck.aif", 1, 8000, 0.00112499995157123, "AIFC", "mulaw (8 bits)")
1901  test_headers("Pmiscck.wav", 1, 8000, 0.00112499995157123, "RIFF", "mulaw (8 bits)")
1902  test_headers("Poffset.aif", 1, 8000, 0.00112499995157123, "AIFC", "mulaw (8 bits)")
1903  test_headers("Porder.aif", 1, 8000, 0.00112499995157123, "AIFC", "mulaw (8 bits)")
1904  test_headers("Ptjunk.aif", 1, 8000, 0.00112499995157123, "AIFC", "mulaw (8 bits)")
1905  test_headers("Ptjunk.wav", 1, 8000, 0.00112499995157123, "RIFF", "mulaw (8 bits)")
1906  test_headers("SINE24-S.WAV", 2, 44100, 2.0, "RIFF", "little endian int (24 bits)")
1907  test_headers("a1.asf", 1, 16000, 3.736562, "asf", "unknown")
1908  test_headers("a2.asf", 1, 8000, 4.630625, "asf", "unknown")
1909  test_headers("addf8.afsp", 1, 8000, 2.9760000705719, "Sun/Next", "big endian short (16 bits)")
1910  test_headers("addf8.d", 1, 8000, 2.9760000705719, "SPPACK", "big endian short (16 bits)")
1911  test_headers("addf8.dwd", 1, 8000, 2.976000071, "DiamondWare", "little endian short (16 bits)")
1912  test_headers("addf8.nh", 2, 44100, 0.269931972, "raw (no header)", "big endian short (16 bits)")
1913  test_headers("addf8.sd", 1, 8000, 2.9760000705719, "ESPS", "big endian short (16 bits)")
1914  test_headers("addf8.sf_mipseb", 1, 8000, 2.9760000705719, "IRCAM", "big endian short (16 bits)")
1915  test_headers("addf8.sf_sun", 1, 8000, 2.9760000705719, "IRCAM", "big endian short (16 bits)")
1916  test_headers("addf8.sf_vax_b", 1, 8000, 2.9760000705719, "IRCAM", "big endian short (16 bits)")
1917  test_headers("addf8.wav", 1, 8000, 2.9760000705719, "RIFF", "little endian short (16 bits)")
1918  test_headers("aebass.krz", 1, 44100, 3.0, "Kurzweil 2000", "big endian short (16 bits)")
1919  test_headers("aiff-16.snd", 2, 44100, 0.746666669845581, "AIFF", "big endian short (16 bits)")
1920  test_headers("aiff-8.snd", 2, 44100, 0.746666669845581, "AIFF", "signed byte (8 bits)")
1921  test_headers("alaw.aifc", 1, 44100, 0.0367800444364548, "AIFC", "alaw (8 bits)")
1922  test_headers("alaw.wav", 1, 11025, 8.70666694641113, "RIFF", "alaw (8 bits)")
1923  test_headers("astor_basia.mp2", 2, 44100, 1.022,"raw (no header)", "big endian short (16 bits)")
1924  test_headers("c.asf", 1, 8000, 21.368126, "asf", "unknown")
1925  test_headers("ce-c3.w02", 1, 33000, 3.88848495483398, "TX-16W", "unknown")
1926  test_headers("ce-c4.w03", 1, 33000, 2.91618180274963, "TX-16W", "unknown")
1927  test_headers("ce-d2.w01", 1, 33000, 3.46439385414124, "TX-16W", "unknown")
1928  test_headers("clbonef.wav", 1, 22050, 2.57832193374634, "RIFF", "little endian float (32 bits)")
1929  test_headers("cranker.krz", 1, 44100, 3.48267579, "Kurzweil 2000", "big endian short (16 bits)")
1930  test_headers("d40130.aif", 1, 10000, 0.100000001490116, "AIFF", "big endian short (16 bits)")
1931  test_headers("d40130.au", 1, 10000, 0.100000001490116, "Sun/Next", "big endian short (16 bits)")
1932  test_headers("d40130.dsf", 1, 8000, 0.125, "Delusion", "little endian short (16 bits)")
1933  test_headers("d40130.fsm", 1, 8000, 0.12524999678, "Farandole", "little endian short (16 bits)")
1934  test_headers("d40130.iff", 1, 10000, 0.100000001490116, "SVX8", "signed byte (8 bits)")
1935  test_headers("d40130.pat", 1, 10000, 0.100000001490116, "Gravis Ultrasound patch", "little endian short (16 bits)")
1936  test_headers("d40130.sds", 1, 10000, 0.100000001490116, "MIDI sample dump", "unknown")
1937  test_headers("d40130.sdx", 1, 10000, 0.100000001490116, "Sample dump", "unsigned little endian short (16 bits)")
1938  test_headers("d40130.sf", 1, 10000, 0.100000001490116, "IRCAM", "little endian short (16 bits)")
1939  test_headers("d40130.smp", 1, 8000, 0.125, "SMP", "little endian short (16 bits)")
1940  test_headers("d40130.sou", 1, 8000, 0.125, "SBStudioII", "little endian short (16 bits)")
1941  test_headers("d40130.st3", 1, 8000, 0.125, "Digiplayer ST3", "unsigned little endian short (16 bits)")
1942  test_headers("d40130.uwf", 1, 8000, 0.1252499, "Ultratracker", "little endian short (16 bits)")
1943  test_headers("d40130.voc", 1, 10000, 0.100100003182888, "VOC", "unsigned byte (8 bits)")
1944  test_headers("d40130.w00", 1, 16000, 0.0625, "TX-16W", "unknown")
1945  test_headers("d40130.wav", 1, 10000, 0.100000001490116, "RIFF", "little endian short (16 bits)")
1946  test_headers("d43.wav", 1, 10000, 0.100000001490116, "RIFF", "little endian short (16 bits)")
1947  test_headers("digit0v0.aiff", 1, 8000, 0.560000002384186, "AIFC", "big endian short (16 bits)")
1948  test_headers("esps-16.snd", 1, 8000, 3.09737491607666, "ESPS", "big endian short (16 bits)")
1949  test_headers("forest.aiff", 2, 44100, 3.907143, "AIFF", "big endian short (16 bits)", 24981, 144332)
1950  test_headers("g721.au", 1, 11025, 4.35328817367554, "Sun/Next", "unknown")
1951  test_headers("g722.aifc", 1, 44100, 0.0184353739023209, "AIFC", "unknown")
1952  test_headers("gong.wve", 1, 8000, 3.96799993515015, "PSION", "alaw (8 bits)")
1953  test_headers("gsm610.wav", 1, 11025, 1.7687075138092, "RIFF", "unknown")
1954  test_headers("inrs-16.snd", 1, 8000, 2.46399998664856, "INRS", "little endian short (16 bits)")
1955  test_headers("kirk.wve", 1, 8000, 1.40799999237061, "PSION", "alaw (8 bits)")
1956  test_headers("loop.aiff", 1, 44100, 0.0367120169103146, "AIFC", "big endian short (16 bits)", 12, 23)
1957  test_headers("m.asf", 1, 8000, 64.964622, "asf", "unknown")
1958  test_headers("mary-sun4.sig", 1, 8000, 4.47612476348877, "Comdisco SPW signal", "big endian double (64 bits)")
1959  test_headers("mocksong.wav", 1, 11025, 7.869569301605, "RIFF", "little endian short (16 bits)")
1960  test_headers("mono24.wav", 1, 22050, 1.98997735977173, "RIFF", "little endian int (24 bits)")
1961  test_headers("msadpcm.wav", 1, 11025, 4.43501138687134, "RIFF", "unknown")
1962  test_headers("n8.snd", 1, 44100, 0.0367800444364548, "Sun/Next", "signed byte (8 bits)")
1963  test_headers("nasahal.aif", 1, 11025, 9.89841270446777, "AIFF", "signed byte (8 bits)")
1964  test_headers("nasahal.avi", 1, 11025, 10.432744, "AVI", "little endian short (16 bits)")
1965  test_headers("nasahal.dig", 1, 11025, 9.8984, "Sound Designer 1", "big endian short (16 bits)")
1966  test_headers("nasahal.ivc", 2, 44100, 0.449, "raw (no header)", "big endian short (16 bits)")
1967  test_headers("nasahal.pat", 1, 11025, 3.95410442352295, "Gravis Ultrasound patch", "unsigned byte (8 bits)")
1968  test_headers("nasahal.snd", 1, 11025, 9.89841270446777, "SNDT", "unsigned byte (8 bits)")
1969  test_headers("nasahal.svx", 1, 11025, 9.89841270446777, "SVX8", "signed byte (8 bits)")
1970  test_headers("nasahal.v8", 1, 8000, 13.6412496566772, "Covox V8", "unsigned byte (8 bits)")
1971  test_headers("nasahal.voc", 1, 11025, 9.89941024780273, "VOC", "unsigned byte (8 bits)")
1972  test_headers("nasahal.vox", 2, 44100, 0.22444, "raw (no header)", "big endian short (16 bits)")
1973  test_headers("nasahal8.wav", 1, 11025, 9.89841270446777, "RIFF", "unsigned byte (8 bits)")
1974  test_headers("nasahalad.smp", 1, 11025, 4.94920635223389, "Goldwave sample", "little endian short (16 bits)")
1975  test_headers("next-16.snd", 1, 22050, 1.00004529953003, "Sun/Next", "big endian short (16 bits)")
1976  test_headers("next-8.snd", 1, 22050, 0.226757362484932, "Sun/Next", "signed byte (8 bits)")
1977  test_headers("next-dbl.snd", 1, 22050, 0.226757362484932, "Sun/Next", "big endian double (64 bits)")
1978  test_headers("oboe.ldbl", 1, 22050, 2.30512475967407, "RIFF", "little endian double (64 bits)")
1979  test_headers("next-flt.snd", 1, 22050, 0.226757362484932, "Sun/Next", "big endian float (32 bits)")
1980  test_headers("aifc-float.snd", 1, 22050, 0.2267573624849, "AIFC", "big endian float (32 bits)")
1981  test_headers("next-mulaw.snd", 1, 8012, 2.03295063972473, "Sun/Next", "mulaw (8 bits)")
1982  test_headers("next24.snd", 1, 44100, 0.0367800444364548, "Sun/Next", "big endian int (24 bits)")
1983  test_headers("nist-01.wav", 1, 16000, 2.26912498474121, "NIST", "little endian short (16 bits)")
1984  test_headers("nist-10.wav", 1, 16000, 2.26912498474121, "NIST", "big endian short (16 bits)")
1985  test_headers("nist-16.snd", 1, 16000, 1.02400004863739, "NIST", "big endian short (16 bits)")
1986  test_headers("nist-shortpack.wav", 1, 16000, 4.53824996948242, "NIST", "unknown")
1987  test_headers("none.aifc", 1, 44100, 0.0367800444364548, "AIFC", "big endian short (16 bits)")
1988  test_headers("nylon2.wav", 2, 22050, 1.14376413822174, "RIFF", "unknown")
1989  test_headers("o2.adf", 1, 44100, 0.036780, "CSRE adf", "little endian short (16 bits)")
1990  test_headers("o2.avr", 1, 44100, 0.0183900222182274, "AVR", "big endian short (16 bits)")
1991  test_headers("o2.bicsf", 1, 44100, 0.0367800444364548, "IRCAM", "big endian short (16 bits)")
1992  test_headers("o2.mpeg1", 2, 44100, 0.0070975, "raw (no header)", "big endian short (16 bits)")
1993  test_headers("o2.sd2", 2, 44100, 0.0183900222, "raw (no header)", "big endian short (16 bits)")
1994  test_headers("o2.sf2", 1, 44100, 0.036780044436, "SoundFont", "little endian short (16 bits)")
1995  test_headers("o2.smp", 1, 8000, 0.202749997377396, "SMP", "little endian short (16 bits)")
1996  test_headers("o2.voc", 1, 44100, 0.0368934236466885, "VOC", "little endian short (16 bits)")
1997  test_headers("o2.wave", 1, 44100, 0.0367800444364548, "RIFF", "little endian short (16 bits)")
1998  test_headers("o2_12bit.aiff", 1, 44100, 0.036780044436, "AIFF", "big endian short (16 bits)")
1999  test_headers("o2_18bit.aiff", 1, 44100, 0.0367800444364548, "AIFF", "big endian int (24 bits)")
2000  test_headers("o2_711u.wave", 1, 44100, 0.0367800444364548, "RIFF", "mulaw (8 bits)")
2001  test_headers("o2_722.snd", 1, 44100, 0.0183900222182274, "Sun/Next", "unknown")
2002  test_headers("o2_726.aiff", 1, 8000, 0.0367499999701977, "AIFC", "unknown")
2003  test_headers("o2_726.snd", 1, 44100, 0.0230158735066652, "Sun/Next", "unknown")
2004  test_headers("o2_728.aiff", 1, 8000, 0.0367499999701977, "AIFC", "unknown")
2005  test_headers("o2_8.iff", 1, 44100, 0.0367800444364548, "SVX8", "signed byte (8 bits)")
2006  test_headers("o2_8.voc", 1, 44100, 0.0370294786989689, "VOC", "unsigned byte (8 bits)")
2007  test_headers("o2_dvi.wave", 1, 44100, 0.0232199542224407, "RIFF", "unknown")
2008  test_headers("o2_float.bicsf", 1, 44100, 0.0367800444, "IRCAM", "big endian float (32 bits)")
2009  test_headers("o2_gsm.aiff", 1, 8000, 0.0367499999701977, "AIFC", "unknown")
2010  test_headers("o2_u8.avr", 1, 44100, 0.0367800444364548, "AVR", "unsigned byte (8 bits)")
2011  test_headers("o2_u8.wave", 1, 44100, 0.0367800444364548, "RIFF", "unsigned byte (8 bits)")
2012  test_headers("o28.mpc", 1, 44100, 0.036780, "AKAI 4", "little endian short (16 bits)")
2013  test_headers("oboe.kts", 1, 22050, 2.305125, "Korg", "big endian short (16 bits)")
2014  test_headers("oboe.its", 1, 22050, 2.305125, "Impulse Tracker", "little endian short (16 bits)")
2015  test_headers("oboe.sf2", 1, 22050, 2.305124759674, "SoundFont", "little endian short (16 bits)")
2016  test_headers("oboe.paf", 1, 22050, 2.305125, "Ensoniq Paris", "big endian short (16 bits)")
2017  test_headers("oboe.pf1", 1, 22050, 2.305125, "Ensoniq Paris", "little endian short (16 bits)")
2018  test_headers("oboe.smp", 1, 22050, 2.305125, "snack SMP", "little endian short (16 bits)")
2019  test_headers("oboe.rf64", 1, 22050, 2.305125, "rf64", "little endian short (16 bits)")
2020  test_headers("oboe-be32.caf", 1, 22050, 2.305125, "caff", "normalized big endian int (32 bits)")
2021  test_headers("oboe-bf64.caf", 1, 22050, 2.305125, "caff", "big endian double (64 bits)")
2022  test_headers("oboe-lf32.caf", 1, 22050, 2.305125, "caff", "little endian float (32 bits)")
2023  test_headers("oboe-ulaw.caf", 1, 22050, 2.305125, "caff", "mulaw (8 bits)")
2024  test_headers("oboe.nsp", 1, 22050, 2.305125, "CSL", "little endian short (16 bits)")
2025  test_headers("oboe-ulaw.voc", 1, 22050, 2.305669, "VOC", "mulaw (8 bits)")
2026  test_headers("oboe-lf32.sf", 1, 22050, 2.305669, "IRCAM", "little endian float (32 bits)")
2027  test_headers("oboe.wfp", 1, 22050, 2.305125, "Turtle Beach", "little endian short (16 bits)")
2028  test_headers("oboe.sox", 1, 22050, 2.305125, "Sox", "normalized little endian int (32 bits)")
2029  test_headers("oki.snd", 2, 44100, 0.004195011, "raw (no header)", "big endian short (16 bits)")
2030  test_headers("oki.wav", 1, 44100, 0.016780, "RIFF", "unknown")
2031  test_headers("orv-dvi-adpcm.wav", 1, 44100, 1.92725622653961, "RIFF", "unknown")
2032  test_headers("riff-16.snd", 1, 22050, 1.88766443729401, "RIFF", "little endian short (16 bits)")
2033  test_headers("riff-8-u.snd", 1, 11025, 0.506848096847534, "RIFF", "unsigned byte (8 bits)")
2034  test_headers("rooster.wve", 1, 8000, 2.04800009727478, "PSION", "alaw (8 bits)")
2035  test_headers("sd1-16.snd", 1, 44100, 0.40054, "Sound Designer 1", "big endian short (16 bits)")
2036  test_headers("sf-16.snd", 1, 22050, 1.88766443729401, "IRCAM", "big endian short (16 bits)")
2037  test_headers("si654.adc", 1, 16000, 6.71362495422363, "ADC/OGI", "big endian short (16 bits)")
2038  test_headers("smp-16.snd", 1, 8000, 5.2028751373291, "SMP", "little endian short (16 bits)")
2039  test_headers("sound.pat", 1, 8000, 1.95050001144409, "Gravis Ultrasound patch", "unsigned little endian short (16 bits)")
2040  test_headers("sound.sap", 1, 8000, 1.95050001144409, "Goldwave sample", "little endian short (16 bits)")
2041  test_headers("sound.sds", 1, 8000, 1.95050001144409, "MIDI sample dump", "unknown")
2042  test_headers("sound.sfr", 1, 8000, 1.95050001144409, "SRFS", "little endian short (16 bits)")
2043  test_headers("sound.v8", 1, 8000, 1.95050001144409, "Covox V8", "unsigned byte (8 bits)")
2044  test_headers("sound.vox", 2, 44100, 0.0442177, "raw (no header)", "big endian short (16 bits)")
2045  test_headers("step.omf", 1, 11025, 8.70666694641113, "OMF", "signed byte (8 bits)")
2046  test_headers("step.qt", 1, 11025, 8.70630359649658, "Quicktime", "unsigned byte (8 bits)")
2047  test_headers("sun-16-afsp.snd", 1, 8000, 2.9760000705719, "Sun/Next", "big endian short (16 bits)")
2048  test_headers("sun-mulaw.snd", 1, 8000, 4.61950016021729, "Sun/Next", "mulaw (8 bits)")
2049  test_headers("sw1038t_short.wav", 2, 8000, 6.0, "NIST", "mulaw (8 bits)")
2050  test_headers("swirl.pat", 1, 22050, 1.0619500875473, "Gravis Ultrasound patch", "unsigned little endian short (16 bits)")
2051  test_headers("sy85.snd", 1, 8000, 5.05600023269653, "Sy-85", "big endian short (16 bits)")
2052  test_headers("sy99.snd", 1, 8000, 4.54400014877319, "Sy-99", "big endian short (16 bits)")
2053  test_headers("telephone.wav", 1, 16000, 2.2788124084, "NIST", "little endian short (16 bits)")
2054  test_headers("trumps22.adp", 1, 22050, 3.092880, "RIFF", "unknown")
2055  test_headers("truspech.wav", 1, 8000, 1.1599999666214, "RIFF", "unknown")
2056  test_headers("ulaw.aifc", 1, 44100, 0.0367800444364548, "AIFC", "mulaw (8 bits)")
2057  test_headers("voc-8-u.snd", 1, 8000, 1.49937498569489, "VOC", "unsigned byte (8 bits)")
2058  test_headers("o28.voc", 1, 44100, 0.036893, "VOC", "little endian short (16 bits)")
2059  test_headers("voxware.wav", 1, 8000, 0.324000000953674, "RIFF", "unknown")
2060  test_headers("wd.w00", 1, 8000, 0.202749997377396, "Sy-99", "big endian short (16 bits)")
2061  test_headers("wd1.smp", 1, 8000, 0.202749997377396, "SMP", "little endian short (16 bits)")
2062  test_headers("wd1.wav", 1, 44100, 0.0367800444364548, "RIFF", "little endian short (16 bits)")
2063  test_headers("wheel.mat", 2, 44100, 0.14564626, "raw (no header)", "big endian short (16 bits)")
2064  test_headers("b8.pvf", 1, 44100, 0.036803, "Portable Voice Format", "signed byte (8 bits)")
2065  test_headers("b16.pvf", 1, 44100, 0.0368, "Portable Voice Format", "big endian short (16 bits)")
2066  test_headers("b32.pvf", 1, 44100, 0.036803, "Portable Voice Format", "big endian int (32 bits)")
2067  test_headers("water.voc", 2, 32000, 42.3463897705078, "VOC", "little endian short (16 bits)")
2068  test_headers("wood.dsf", 1, 8000, 0.202749997377, "Delusion", "little endian short (16 bits)")
2069  test_headers("wood.dvi", 1, 22100, 0.0278733037412167, "RIFF", "unknown")
2070  test_headers("wood.dwd", 1, 22100, 0.0733936652541161, "DiamondWare", "signed byte (8 bits)")
2071  test_headers("wood.fsm", 1, 8000, 0.2029999942, "Farandole", "little endian short (16 bits)")
2072  test_headers("wood.mad", 1, 22100, 0.0372398197650909, "RIFF", "unknown")
2073  test_headers("wood.maud", 1, 44100, 0.0183900222182274, "MAUD", "big endian short (16 bits)")
2074  test_headers("wood.pat", 1, 22100, 0.0733936652541161, "Gravis Ultrasound patch", "little endian short (16 bits)")
2075  test_headers("wood.riff", 1, 44100, 0.0367800444364548, "RIFF", "little endian short (16 bits)")
2076  test_headers("wood.rifx", 1, 44100, 0.0367800444364548, "RIFF", "big endian short (16 bits)")
2077  test_headers("wood.sds", 1, 22100, 0.0733936652541161, "MIDI sample dump", "unknown")
2078  test_headers("wood.sdx", 1, 22100, 0.0733936652541161, "Sample dump", "unsigned little endian short (16 bits)")
2079  test_headers("wood.sf", 1, 44100, 0.0367800444364548, "IRCAM", "big endian short (16 bits)")
2080  test_headers("wood.sndr", 2, 44100, 0.009229, "raw (no header)", "big endian short (16 bits)")
2081  test_headers("wood.sndt", 1, 44100, 0.0367800444364548, "SNDT", "unsigned byte (8 bits)")
2082  test_headers("wood.st3", 1, 8000, 0.202749997377396, "Digiplayer ST3", "unsigned little endian short (16 bits)")
2083  test_headers("wood.uwf", 1, 8000, 0.202999994, "Ultratracker", "little endian short (16 bits)")
2084  test_headers("wood.w00", 1, 16000, 0.101374998688698, "TX-16W", "unknown")
2085  test_headers("wood12.aiff", 1, 44100, 0.0367800444364548, "AIFF", "big endian short (16 bits)")
2086  test_headers("wood16.dwd", 2, 44100, 0.03678004, "DiamondWare", "little endian short (16 bits)")
2087  test_headers("wood16.wav", 2, 44100, 0.03678004, "RIFF", "little endian short (16 bits)")
2088  test_headers("wood16.nsp", 2, 44100, 0.03678004, "CSL", "little endian short (16 bits)")
2089  test_headers("wood16.smp", 2, 44100, 0.03678004, "snack SMP", "little endian short (16 bits)")
2090  test_headers("wood24.aiff", 1, 44100, 0.0367800444364548, "AIFF", "big endian int (24 bits)")
2091  test_headers("woodblock.aiff", 1, 44100, 0.03678, "AIFF", "big endian short (16 bits)")
2092  test_headers("woodflt.snd", 1, 44100, 0.0367800444364548, "Sun/Next", "big endian float (32 bits)")
2093  test_headers("RealDrums.sf2", 1, 44100, 6.397256, "SoundFont", "little endian short (16 bits)")
2094  test_headers("32bit.sf", 1, 44100, 4.6, "IRCAM", "little endian float (32 bits, unscaled)")
2095  test_headers("PCM_48_8bit_m.w64", 1, 48000, 0.375, "SoundForge", "unsigned byte (8 bits)")
2096  test_headers("oboe.sf6", 1, 22050, 2.305125, "SoundForge", "little endian short (16 bits)")
2097  test_headers("addf8.24we", 1, 8000, 2.976000, "RIFF", "little endian int (24 bits)")
2098  test_headers("hybrid.snd", 1, 44100, 4.600000, "BICSF", "big endian float (32 bits)")
2099  test_headers("litmanna.sf", 1, 44100, 0.533, "IRCAM", "little endian short (16 bits)")
2100  test_headers("M1F1-float64C-AFsp.aif", 2, 8000, 2.9366, "AIFC", "big endian double (64 bits)")
2101  test_headers("MacBoing.wav", 1, 11127, 0.696, "RIFF", "unsigned byte (8 bits)")
2102  test_headers("t15.aiff", 2, 44100, 135.00, "AIFC", "little endian short (16 bits)")
2103  test_headers("tomf8.aud", 1, 8000, 2.016000, "INRS", "little endian short (16 bits)")
2104  test_headers("Xhs001x.nsp", 1, 10000, 6.017400, "CSL", "little endian short (16 bits)")
2105  test_headers("zulu_a4.w11", 1, 33000, 1.21987879276276, "TX-16W", "unknown", 23342, 40042)
2106  #
2107  name = "forest.aiff"
2108  with_file(name) do |file|
2109    snd_test_neq(mus_sound_mark_info(file),
2110                 [[4, 0], [3, 0], [2, 144332], [1, 24981]],
2111                 "mus_sound_mark_info %s", name)
2112  end
2113  name = "traffic.aiff"
2114  with_file(name) do |file|
2115    snd_test_neq(mus_sound_mark_info(file),
2116                 [[4, 1], [3, 0], [2, 171931], [1, 99461]],
2117                 "mus_sound_mark_info %s", name)
2118  end
2119end
2120
2121# ---------------- test 03: variables ----------------
2122
2123def test_03
2124  ind = open_sound("oboe.snd")
2125  test_dir = $HOME + "/test"
2126  if File.exist?(test_dir)
2127    old_val = temp_dir
2128    snd_test_neq(set_temp_dir(test_dir), test_dir, "set_temp_dir")
2129    set_temp_dir(old_val)
2130  end
2131  snd_test_neq(sample(1000), 0.0328, "sample 1000")
2132  #
2133  $snd_error_hook.reset_hook!
2134  $mus_error_hook.reset_hook!
2135  [$output_comment_hook,
2136   $help_hook,
2137   $mark_drag_hook,
2138   $mix_drag_hook,
2139   $mouse_drag_hook,
2140   $mouse_click_hook,
2141   $mouse_press_hook,
2142   $start_playing_hook,
2143   $start_playing_selection_hook,
2144   $stop_playing_hook,
2145   $key_press_hook,
2146   $snd_error_hook,
2147   $snd_warning_hook,
2148   $name_click_hook,
2149   $after_apply_controls_hook,
2150   $enved_hook,
2151   $mouse_enter_label_hook,
2152   $mouse_enter_graph_hook,
2153   $mouse_enter_listener_hook,
2154   $mouse_leave_label_hook,
2155   $mouse_leave_graph_hook,
2156   $mouse_leave_listener_hook,
2157   $initial_graph_hook,
2158   $after_graph_hook,
2159   $graph_hook].each_with_index do |h, i|
2160    if (not hook?(h)) or (not h.empty?)
2161      snd_display("hook[%d]: %p?", i, h)
2162    end
2163  end
2164  reset_almost_all_hooks
2165  #
2166  if $with_test_gui
2167    old_ctrl = show_controls
2168    set_show_controls(true)
2169    req = enved_dialog
2170    snd_test_neq(dialog_widgets[1], req, "enved_dialog")
2171    req = [0.0, 0.0, 1.0, 1.0, 2.0, 0.0]
2172    set_enved_envelope(req)
2173    snd_test_neq(enved_envelope, req, "set_enved_envelope")
2174    set_enved_envelope(enved_envelope())
2175    snd_test_neq(enved_envelope, req, "set_enved_envelope to self")
2176    set_show_controls(old_ctrl)
2177  end
2178  #
2179  gui_lst = [[:color_cutoff, 0.003, 0.01],
2180             [:color_inverted, true, false],
2181             [:color_scale, 1.0, 0.5],
2182             [:contrast_control?, false, true],
2183             [:enved_base, 1.0, 1.5],
2184             [:enved_in_dB, false, true],
2185             [:enved_target, 0, 1],
2186             [:enved_wave?, false, true],
2187             [:expand_control?, false, true],
2188             [:fft_log_frequency, false, true],
2189             [:fft_log_magnitude, false, true],
2190             [:fft_with_phases, false, true],
2191             [:enved_filter_order, 40, 20],
2192             [:filter_control?, false, true],
2193             [:transform_normalization, Normalize_by_channel, Dont_normalize],
2194             [:reverb_control?, false, true],
2195             [:show_transform_peaks, false, true],
2196             [:show_selection_transform, false, true],
2197             [:spectrum_end, 1.0, 0.7],
2198             [:spectro_hop, 4, 10],
2199             [:spectrum_start, 0.0, 0.1],
2200             [:spectro_x_angle, ($with_test_gl ? 300.0 : 90.0), 60.0],
2201             [:spectro_x_scale, ($with_test_gl ? 1.5 : 1.0), 2.0],
2202             [:spectro_y_angle, ($with_test_gl ? 320.0 : 0.0), 60.0],
2203             [:spectro_y_scale, 1.0, 2.0],
2204             [:spectro_z_angle, ($with_test_gl ? 0.0 : 358.0), 60.0],
2205             [:spectro_z_scale, ($with_test_gl ? 1.0 : 0.1), 0.2]]
2206  lst = [[:amp_control, 1.0, 0.5],
2207         [:amp_control_bounds, [0.0, 8.0], [1.0, 5.0]],
2208         [:ask_about_unsaved_edits, false, true],
2209         [:ask_before_overwrite, false, true],
2210         [:auto_resize, true, false],
2211         [:auto_update, false, true],
2212         [:channel_style, 0, 1],
2213         [:colormap, $good_colormap, $better_colormap],
2214         [:contrast_control, 0.0, 0.5],
2215         [:contrast_control_bounds, [0.0, 10.0], [1.0, 5.0]],
2216         [:contrast_control_amp, 1.0, 0.5],
2217         [:auto_update_interval, 60.0, 120.0],
2218         [:cursor_update_interval, 0.05, 0.1],
2219         [:cursor_location_offset, 0, 32768],
2220         [:with_tracking_cursor, false, true],
2221         [:cursor_size, 15, 30],
2222         [:cursor_style, Cursor_cross, Cursor_line],
2223         [:tracking_cursor_style, Cursor_line, Cursor_cross],
2224         [:dac_combines_channels, true, false],
2225         [:dac_size, 256, 512],
2226         [:clipping, false, true],
2227         [:default_output_chans, 1, 2],
2228         [:default_output_sample_type, Mus_lfloat, Mus_bshort],
2229         [:default_output_srate, 22050, 44100],
2230         [:default_output_header_type, Mus_next, Mus_aifc],
2231         [:dot_size, 1, 4],
2232         [:enved_clip?, false, true],
2233         [:enved_style, Envelope_linear, Envelope_exponential],
2234         [:enved_power, 3.0, 3.5],
2235         [:eps_file, "snd.eps", "snd-1.eps"],
2236         [:eps_left_margin, 0.0, 72.0],
2237         [:eps_size, 1.0, 2.0],
2238         [:eps_bottom_margin, 0.0, 36.0],
2239         [:expand_control, 1.0, 2.0],
2240         [:expand_control_bounds, [0.001, 20.0], [1.0, 2.0]],
2241         [:expand_control_hop, 0.05, 0.1],
2242         [:expand_control_jitter, 0.1, 0.2],
2243         [:expand_control_length, 0.15, 0.2],
2244         [:expand_control_ramp, 0.4, 0.2],
2245         [:fft_window_alpha, 0.0, 1.0],
2246         [:fft_window_beta, 0.0, 0.5],
2247         [:transform_size, 512, 1024],
2248         [:transform_graph_type, Graph_once, Graph_as_sonogram],
2249         [:fft_window, 6, 5],
2250         [:transform_graph?, false, true],
2251         [:filter_control_in_dB, false, true],
2252         [:filter_control_envelope, [0.0, 1.0, 1.0, 1.0], [0.0, 1.0, 1.0, 0.0]],
2253         [:enved_filter, true, false],
2254         [:filter_control_in_hz, false, true],
2255         [:filter_control_order, 20, 40],
2256         [:graph_cursor, 34, 32],
2257         [:graph_style, 0, 1],
2258         [:initial_beg, 0.0, 1.0],
2259         [:initial_dur, 0.1, 1.0],
2260         [:just_sounds, false, true],
2261         [:listener_prompt, ">", ":"],
2262         [:max_transform_peaks, 100, 10],
2263         [:max_regions, 16, 6],
2264         [:min_dB, -60.0, -90.0],
2265         [:log_freq_start, 32.0, 10.0],
2266         [:mix_waveform_height, 20, 40],
2267         [:mix_tag_height, 14, 20],
2268         [:mix_tag_width, 6, 20],
2269         [:mark_tag_height, 4, 20],
2270         [:mark_tag_width, 10, 20],
2271         [:mus_clipping, false, true],
2272         [:selection_creates_region, true, false],
2273         [:play_arrow_size, 10, 16],
2274         [:print_length, 12, 16],
2275         [:region_graph_style, Graph_lines, Graph_lollipops],
2276         [:reverb_control_decay, 1.0, 2.0],
2277         [:reverb_control_feedback, 1.09, 1.6],
2278         [:reverb_control_length, 1.0, 2.0],
2279         [:reverb_control_length_bounds, [0.0, 0.5], [1.0, 2.0]],
2280         [:reverb_control_lowpass, 0.7, 0.9],
2281         [:reverb_control_scale, 0.0, 0.2],
2282         [:reverb_control_scale_bounds, [0.0, 4.0], [0.0, 0.2]],
2283         [:show_axes, 1, 0],
2284         [:show_full_duration, false, true],
2285         [:show_full_range, false, true],
2286         [:show_indices, false, true],
2287         [:show_marks, true, false],
2288         [:show_mix_waveforms, true, false],
2289         [:show_y_zero, false, true],
2290         [:show_grid, false, true],
2291         [:grid_density, 1.0, 0.5],
2292         [:show_sonogram_cursor, false, true],
2293         [:sinc_width, 10, 40],
2294         [:speed_control, 1.0, 0.5],
2295         [:speed_control_bounds, [0.05, 20.0], [1.0, 5.0]],
2296         [:speed_control_style, 0, 1],
2297         [:speed_control_tones, 12, 18],
2298         [:sync, 0, 1],
2299         [:sync_style, Sync_by_sound, Sync_all],
2300         [:tiny_font, Tiny_font_string, Tiny_font_set_string],
2301         [:transform_type, $fourier_transform, $autocorrelation],
2302         [:with_verbose_cursor, false, true],
2303         [:wavelet_type, 0, 1],
2304         [:time_graph?, false, true],
2305         [:time_graph_type, Graph_once, Graph_as_wavogram],
2306         [:wavo_hop, 3, 6],
2307         [:wavo_trace, 64, 128],
2308         [:with_mix_tags, true, false],
2309         [:with_relative_panes, true, false],
2310         [:with_gl, $with_test_gl, false],
2311         [:x_axis_style, 0, 1],
2312         [:beats_per_minute, 30.0, 120.0],
2313         [:beats_per_measure, 1, 120],
2314         [:zero_pad, 0, 1],
2315         [:zoom_focus_style, 2, 1]]
2316  if $with_test_gui
2317    lst += gui_lst
2318  end
2319  lst.each do |sym, initval, newval|
2320    next unless symbol?(sym)
2321    2.times do |i|
2322      set_snd_func(sym, newval)
2323      snd_test_neq(snd_func(sym), newval, "set_%s[%d]", sym, i)
2324      set_snd_func(sym, initval)
2325    end
2326  end
2327  #
2328  [if $with_test_gui
2329     [:amp_control, 1.0, [-1.0, 123.123]]
2330   end,
2331   [:amp_control_bounds, [0.0, 8.0], [false, [0.0], [1.0, 0.0], 2.0]],
2332   [:channel_style, 0, [32, -1, 1.0]],
2333   [:colormap, $good_colormap, [321, -123]],
2334   [:color_cutoff, 0.003, [-1.0, 123.123]],
2335   [:color_scale, 1.0, [-32.0, 2000.0]],
2336   if $with_test_gui
2337     [:contrast_control, 0.0, [-123.123, 123.123]]
2338   end,
2339   [:contrast_control_bounds, [0.0, 10.0], [false, [0.0], [1.0, 0.0], 2.0]],
2340   [:cursor_size, 15, [1.123, -2.5]],
2341   [:dac_size, 256, [-1, 0, -123]],
2342   [:dot_size, 1, [0, -1, -123]],
2343   [:enved_target, 0, [123, -321]],
2344   [:expand_control, 1.0, [-1.0, 0.0]],
2345   [:expand_control_bounds, [0.001, 20.0], [false, [0.0], [1.0, 0.0], 2.0]],
2346   [:expand_control_hop, 0.05, [-1.0]],
2347   [:expand_control_length, 0.15, [-1.0, 0.0]],
2348   [:expand_control_ramp, 0.4, [-1.0, 1.0, 123.123]],
2349   [:fft_window_alpha, 0.0, [-1.0, 123.123]],
2350   [:fft_window_beta, 0.0, [-1.0, 123.123]],
2351   [:transform_size, 512, [-1, 0]],
2352   [:zero_pad, 0, [-1, -123]],
2353   [:cursor_style, Cursor_cross, [-1]],
2354   [:cursor_style, Cursor_line, [2, 123]],
2355   [:tracking_cursor_style, Cursor_line, [-1]],
2356   [:tracking_cursor_style, Cursor_line, [2, 123]],
2357   [:transform_graph_type, Graph_once, [-1, 123]],
2358   [:fft_window, 6, [-1, 123]],
2359   [:enved_filter_order, 40, [-1, 0]],
2360   [:filter_control_order, 20, [-10, -1, 0]],
2361   [:max_transform_peaks, 100, [-1]],
2362   [:max_regions, 16, [-1, -123]],
2363   [:reverb_control_length, 1.0, [-1.0]],
2364   [:show_axes, 1, [-1, 123]],
2365   [:sinc_width, 10, [-10]],
2366   [:spectrum_end, 1.0, [-1.0]],
2367   [:spectro_hop, 4, [-10, -1, 0]],
2368   [:spectrum_start, 0.0, [-1.0]],
2369   [:speed_control, 1.0, [0.0]],
2370   [:speed_control_bounds, [0.05, 20.0], [false, [0.0], [1.0, 0.0], 2.0]],
2371   [:speed_control_style, 0, [-1, 10]],
2372   [:sync_style, Sync_by_sound, [-1, 123]],
2373   [:transform_type, $fourier_transform,
2374     [integer2transform(-1), integer2transform(123)]],
2375   [:wavelet_type, 0, [-1, 123]],
2376   [:wavo_hop, 1, [0, -123]],
2377   [:wavo_trace, 1, [0, -123]],
2378   [:x_axis_style, 0, [-1, 123]],
2379   [:zoom_focus_style, 2, [-1, 123]]].each do |sym, initval, newvals|
2380    next unless symbol?(sym)
2381    newvals.each do |newval|
2382      Snd.catch do set_snd_func(sym, newval) end
2383      snd_test_eq(snd_func(sym), newval, "set_%s (bad set)", sym)
2384      set_snd_func(sym, initval)
2385    end
2386  end
2387  #
2388  if $with_test_gui
2389    set_sync_style(Sync_none)
2390    set_window_width(300)
2391    set_window_height(300)
2392    snd_test_neq(window_width, 300, "window width")
2393    snd_test_neq(window_height, 300, "window height")
2394    old_val = color_scale
2395    set_color_scale(100.0)
2396    snd_test_neq(color_scale, 100.0, "color_scale")
2397    set_color_scale(old_val)
2398  end
2399  #
2400  if proc?(search_procedure)
2401    snd_display("global search procedure: %s?", search_procedure.inspect)
2402  end
2403  set_search_procedure(lambda do |y| y > 0.1 end)
2404  unless proc?(search_procedure)
2405    snd_display("set global search procedure: %s?", search_procedure.inspect)
2406  end
2407  unless search_procedure.call(0.2)
2408    snd_display("search 0.1 > 0.2?")
2409  end
2410  if search_procedure.call(0.02)
2411    snd_display("search 0.1 > 0.02?")
2412  end
2413  set_search_procedure(lambda do |y| y < 0.0 end)
2414  if search_procedure.call(0.02)
2415    snd_display("search 0.0 < 0.02?")
2416  end
2417  set_search_procedure(false)
2418  if proc?(search_procedure)
2419    snd_display("global search procedure after reset: %s?",
2420      search_procedure.inspect)
2421  end
2422  set_search_procedure(lambda do |y| y > 0.1 end)
2423  unless proc?(search_procedure)
2424    snd_display("set global search procedure: %s?", search_procedure.inspect)
2425  end
2426  set_search_procedure(false)
2427  #
2428  if $with_test_gui
2429    old_val = enved_filter_order
2430    set_enved_filter_order(5)
2431    snd_test_neq(enved_filter_order, 6, "set_enved_filter_order 5")
2432    set_enved_filter_order(old_val)
2433    #
2434    zero_to_one = [0, 0.0, 50, 0.5, 100, 1.0]
2435    mod_down = [0, 1.0, 50, 0.5, 100, 0.0]
2436    set_enved_envelope(:zero_to_one)
2437    snd_test_neq(enved_envelope, zero_to_one, "set_enved_envelope (Symbol)")
2438    set_enved_envelope("mod_down")
2439    snd_test_neq(enved_envelope, mod_down, "set_enved_envelope (String)")
2440  end
2441  close_sound(ind)
2442  dismiss_all_dialogs
2443  undefined = []
2444  kernel_global_variables = Kernel.global_variables
2445  # XXX: from original snd-test.scm list removed or changed:
2446  #
2447  # :file2string   (Scheme specific in snd-utils.c)
2448  # :redo          (Ruby statement)
2449  #
2450  # :in replaced by :call_in
2451  [:snd_opened_sound, :abort, :add_colormap, :add_mark,
2452   :add_player, :add_sound_file_extension, :add_source_file_extension,
2453   :add_to_main_menu, :add_to_menu, :add_transform, :after_apply_controls_hook,
2454   :after_edit_hook, :after_graph_hook, :after_lisp_graph_hook,
2455   :after_open_hook, :after_save_as_hook, :after_save_state_hook,
2456   :after_transform_hook, :all_pass, :all_pass?, :amp_control,
2457   :amp_control_bounds, :amplitude_modulate, :analyse_ladspa, :apply_controls,
2458   :apply_ladspa, :array2file, :array_interp, :as_one_edit,
2459   :ask_about_unsaved_edits, :ask_before_overwrite, :asymmetric_fm,
2460   :asymmetric_fm?, :auto_resize, :auto_update, :auto_update_interval,
2461   :autocorrelate, :autocorrelation, :axis_color, :axis_info,
2462   :axis_label_font, :axis_numbers_font, :bad_header_hook, :bartlett_window,
2463   :bartlett_hann_window, :basic_color, :beats_per_measure, :beats_per_minute,
2464   :before_close_hook, :before_exit_hook, :before_save_as_hook,
2465   :before_save_state_hook, :before_transform_hook, :bind_key,
2466   :blackman2_window, :blackman3_window, :blackman4_window, :blackman5_window,
2467   :blackman6_window, :blackman7_window, :blackman8_window, :blackman9_window,
2468   :blackman10_window, :bohman_window, :bold_peaks_font, :call_in,
2469   :cauchy_window, :mlt_sine_window, :cepstrum, :change_samples_with_origin,
2470   :channel2vct, :channel_amp_envs, :channel_data, :channel_properties,
2471   :channel_property, :channel_style, :channel_widgets, :channels,
2472   :channels_combined, :channels_separate, :channels_superimposed,
2473   :chans, :clear_listener, :clip_hook,
2474   :clipping, :clm_channel, :clm_table_size, :close_hook, :close_sound,
2475   :color_cutoff, :color_orientation_dialog, :color_hook, :color_inverted,
2476   :color_scale, :color?, :colormap, :colormap_name, :colormap_ref,
2477   :colormap_size, :colormap?, :comb, :comb?, :combined_data_color,
2478   :comment, :connes_window, :continue_frample2file, :continue_sample2file,
2479   :contrast_control, :contrast_control_amp, :contrast_control_bounds,
2480   :contrast_control?, :contrast_enhancement, :controls2channel, :convolution,
2481   :convolve, :convolve_files, :convolve_selection_with, :convolve_with,
2482   :convolve?, :copy_context, :copy_sampler,
2483   :current_edit_position, :current_font, :cursor, :cursor_color,
2484   :cursor_context, :cursor_cross, :cursor_in_middle, :cursor_in_view,
2485   :cursor_line, :cursor_location_offset, :cursor_on_left, :cursor_on_right,
2486   :cursor_position, :cursor_size, :cursor_style, :cursor_update_interval,
2487   :dac_combines_channels, :dac_size, :data_color, :sample_type,
2488   :data_location, :data_size, :db2linear, :default_output_chans,
2489   :default_output_sample_type, :default_output_header_type,
2490   :default_output_srate, :define_envelope, :degrees2radians, :delay,
2491   :delay_tick, :delay?, :delete_colormap, :delete_mark, :delete_marks,
2492   :delete_sample, :delete_samples, :delete_samples_and_smooth,
2493   :delete_selection, :delete_selection_and_smooth, :delete_transform,
2494   :dialog_widgets, :disk_kspace, :display_edits, :dolph_chebyshev_window,
2495   :dont_normalize,
2496   :dot_product, :dot_size, :draw_axes, :draw_dot, :draw_dots, :draw_line,
2497   :draw_lines, :draw_mark_hook, :draw_mix_hook, :draw_string, :drop_hook,
2498   :during_open_hook, :edit_fragment, :edit_header_dialog, :edit_hook,
2499   :edit_list2function, :edit_position, :edit_tree, :edits, :edot_product,
2500   :env, :env_channel, :env_channel_with_base, :env_interp, :env_selection,
2501   :env_sound, :env?, :enved_add_point, :enved_amplitude, :enved_base,
2502   :enved_clip?, :enved_delete_point, :enved_dialog, :enved_envelope,
2503   :enved_filter, :enved_filter_order, :enved_hook, :enved_in_dB,
2504   :enved_move_point, :enved_power, :enved_spectrum, :enved_srate,
2505   :enved_style, :enved_target, :enved_wave?, :enved_waveform_color,
2506   :envelope_exponential, :envelope_linear, :eps_bottom_margin, :eps_file,
2507   :eps_left_margin, :eps_size, :exit, :exit_hook, :expand_control,
2508   :expand_control_bounds, :expand_control_hop, :expand_control_jitter,
2509   :expand_control_length, :expand_control_ramp, :expand_control?,
2510   :exponential_window, :fft, :fft_log_frequency, :fft_log_magnitude,
2511   :fft_window, :fft_window_alpha, :fft_window_beta, :fft_with_phases,
2512   :file2array, :file2frample, :file2frample?, :file2sample, :file2sample?,
2513   :file_name, :file_write_date, :fill_polygon, :fill_rectangle,
2514   :filter, :filtered_comb, :filtered_comb?, :filter_channel,
2515   :filter_control_coeffs, :filter_control_envelope, :filter_control_in_dB,
2516   :filter_control_in_hz, :filter_control_order,
2517   :filter_control_waveform_color, :filter_control?, :filter_selection,
2518   :filter_sound, :filter?, :find_dialog, :find_mark,
2519   :find_sound, :finish_progress_report, :fir_filter, :fir_filter?,
2520   :flat_top_window, :focus_widget, :foreground_color, :forget_region,
2521   :formant, :formant_bank, :formant_bank?, :formant?, :firmant, :firmant?,
2522   :comb_bank, :comb_bank?, :all_pass_bank, :all_pass_bank?,
2523   :filtered_comb_bank, :filtered_comb_bank?, :make_comb_bank,
2524   :make_all_pass_bank, :make_filtered_comb_bank,
2525   :fourier_transform, :frample2file, :frample2file?, :frample2frample,
2526   :framples, :free_player, :free_sampler,
2527   :gaussian_window, :gc_off, :gc_on, :gl_graph2ps, :glSpectrogram,
2528   :goto_listener_end, :granulate, :granulate?, :graph, :graph2ps,
2529   :graph_as_sonogram, :graph_as_spectrogram, :graph_as_wavogram,
2530   :graph_color, :graph_cursor, :graph_data, :graph_dots,
2531   :graph_dots_and_lines, :graph_filled, :graph_hook, :graph_lines,
2532   :graph_lollipops, :graph_once, :graph_style, :graphs_horizontal,
2533   :grid_density, :haar_transform, :hamming_window, :hann_poisson_window,
2534   :hann_window, :header_type, :help_dialog, :help_hook, :hide_widget,
2535   :highlight_color, :html_dir, :html_program, :hz2radians, :iir_filter,
2536   :iir_filter?, :in_any, :ina, :inb, :info_dialog,
2537   :init_ladspa, :initial_graph_hook, :insert_file_dialog, :insert_region,
2538   :insert_sample, :insert_samples, :insert_samples_with_origin,
2539   :insert_selection, :insert_silence, :insert_sound, :just_sounds,
2540   :kaiser_window, :key, :key_binding, :key_press_hook, :keyboard_no_action,
2541   :ladspa_activate, :ladspa_cleanup, :ladspa_connect_port,
2542   :ladspa_deactivate, :ladspa_descriptor, :ladspa_dir, :peak_env_dir,
2543   :ladspa_instantiate, :ladspa_run, :ladspa_run_adding,
2544   :ladspa_set_run_adding_gain, :left_sample, :linear2db, :lisp_graph,
2545   :lisp_graph_hook, :lisp_graph_style, :lisp_graph?, :list2vct,
2546   :list_ladspa, :listener_click_hook, :listener_color, :listener_font,
2547   :listener_prompt, :listener_selection, :listener_text_color,
2548   :little_endian?, :locsig, :locsig_ref, :locsig_reverb_ref,
2549   :locsig_reverb_set!, :locsig_set!, :locsig_type, :locsig?,
2550   :log_freq_start, :main_menu, :main_widgets, :make_all_pass,
2551   :make_asymmetric_fm, :make_moving_average, :make_moving_max,
2552   :make_bezier, :make_color, :make_comb, :make_filtered_comb, :make_convolve,
2553   :make_delay, :make_env, :make_fft_window, :make_file2frample,
2554   :make_file2sample, :make_filter, :make_fir_coeffs, :make_fir_filter,
2555   :make_formant, :make_firmant, :make_formant_bank,
2556   :make_frample2file, :make_granulate, :make_graph_data, :make_iir_filter,
2557   :make_locsig, :make_mix_sampler, :make_move_sound,
2558   :make_notch, :make_one_pole, :make_one_pole_all_pass, :make_one_zero,
2559   :make_oscil, :make_phase_vocoder, :make_player, :make_polyshape,
2560   :make_polywave, :make_pulse_train, :make_rand, :make_rand_interp,
2561   :make_readin, :make_region, :make_region_sampler, :make_sample2file,
2562   :make_sampler, :make_sawtooth_wave, :make_nrxysin,
2563   :make_nrxycos, "make_rxyk!cos".intern, "make_rxyk!sin".intern,
2564   :make_snd2sample, :make_square_wave,
2565   :make_src, :make_ssb_am, :make_ncos, :make_nsin, :make_table_lookup,
2566   :make_triangle_wave, :make_two_pole, :make_two_zero, :make_variable_graph,
2567   :make_vct, :make_wave_train, :map_chan, :map_channel, :mark_click_hook,
2568   :mark_color, :mark_context, :mark_drag_hook, :mark_home, :mark_hook,
2569   :mark_name, :mark_properties, :mark_property, :mark_sample, :mark_sync,
2570   :mark_sync_max, :mark_tag_height, :mark_tag_width, :mark?, :marks,
2571   :max_regions, :max_transform_peaks, :maxamp, :maxamp_position,
2572   :menu_widgets, :min_dB, :mix, :mix_amp, :mix_amp_env, :mix_click_hook,
2573   :mix_color, :mix_dialog_mix, :mix_drag_hook, :mix_file_dialog,
2574   :mix_length, :mix_home, :mix_name, :mix_position, :mix_properties,
2575   :mix_property, :mix_region, :mix_release_hook, :mix_sync, :mix_sync_max,
2576   :mix_sampler?, :mix_selection, :mix_speed, :mix_tag_height,
2577   :mix_tag_width, :mix_tag_y, :mix_vct, :mix_waveform_height, :mix?,
2578   :mixes, :mouse_click_hook, :mouse_drag_hook, :mouse_enter_graph_hook,
2579   :mouse_enter_label_hook, :mouse_enter_listener_hook,
2580   :mouse_enter_text_hook, :mouse_leave_graph_hook, :mouse_leave_label_hook,
2581   :mouse_leave_listener_hook, :mouse_leave_text_hook, :mouse_press_hook,
2582   :move_locsig, :move_sound, :move_sound?, :moving_average, :moving_average?,
2583   :moving_max, :moving_max?, :mus_aifc,
2584   :mus_aiff, :mus_alaw, :mus_alsa_buffer_size, :mus_alsa_buffers,
2585   :mus_alsa_capture_device, :mus_alsa_device, :mus_alsa_playback_device,
2586   :mus_alsa_squelch_warning, :mus_apply, :mus_array_print_length,
2587   :mus_float_equal_fudge_factor, :mus_b24int, :mus_bdouble,
2588   :mus_bdouble_unscaled, :mus_bfloat, :mus_bfloat_unscaled, :mus_bicsf,
2589   :mus_bint, :mus_bintn, :mus_bshort, :mus_byte, :mus_bytes_per_sample,
2590   :mus_caff, :mus_channel, :mus_channels, :mus_chebyshev_first_kind,
2591   :mus_chebyshev_second_kind,:mus_clipping, :mus_close, :mus_data,
2592   :mus_sample_type2string, :mus_sample_type_name, :mus_describe,
2593   :mus_error_hook, :mus_error_type2string, :mus_expand_filename,
2594   :mus_feedback, :mus_feedforward, :mus_fft, :mus_file_buffer_size,
2595   :mus_file_clipping, :mus_file_name, :mus_frequency,
2596   :mus_generator?, :mus_header_raw_defaults, :mus_header_type2string,
2597   :mus_header_type_name, :mus_hop, :mus_increment, :mus_input?,
2598   :mus_interp_all_pass, :mus_interp_bezier, :mus_interp_hermite,
2599   :mus_interp_lagrange, :mus_interp_linear, :mus_interp_none,
2600   :mus_interp_sinusoidal, :mus_interp_type, :mus_interpolate,
2601   :mus_ircam, :mus_l24int, :mus_ldouble, :mus_ldouble_unscaled,
2602   :mus_length, :mus_lfloat, :mus_lfloat_unscaled, :mus_lint,
2603   :mus_lintn, :mus_location, :mus_lshort, :mus_max_malloc,
2604   :mus_max_table_size, :mus_mulaw, :mus_name, :mus_next,
2605   :mus_nist, :mus_offset, :mus_order, :mus_oss_set_buffers,
2606   :mus_out_format, :mus_output?, :mus_phase, :mus_ramp,
2607   :mus_rand_seed, :mus_random, :mus_raw, :mus_reset, :mus_riff, :mus_run,
2608   :mus_scaler, :mus_set_formant_radius_and_frequency, :mus_sound_chans,
2609   :mus_sound_comment, :mus_sound_sample_type, :mus_sound_data_location,
2610   :mus_sound_datum_size, :mus_sound_duration, :mus_sound_forget,
2611   :mus_sound_framples, :mus_sound_header_type, :mus_sound_length,
2612   :mus_sound_loop_info, :mus_sound_mark_info, :mus_sound_maxamp,
2613   :mus_sound_maxamp_exists?, :mus_sound_prune, :mus_sound_report_cache,
2614   :mus_sound_samples, :mus_sound_srate, :mus_sound_type_specifier,
2615   :mus_sound_write_date, :mus_soundfont, :mus_srate, :mus_svx,
2616   :mus_ubshort, :mus_ubyte, :mus_ulshort, :mus_unknown_sample,
2617   :mus_unknown_header, :mus_voc, :mus_width, :mus_xcoeff,
2618   :mus_xcoeffs, :mus_ycoeff, :mus_ycoeffs, :name_click_hook,
2619   :new_sound, :new_sound_dialog, :new_sound_hook, :new_widget_hook,
2620   :next_sample, :normalize_by_channel, :normalize_by_sound,
2621   :normalize_channel, :normalize_globally, :notch, :notch?,
2622   :one_pole, :one_pole?, :one_pole_all_pass, :one_pole_all_pass?,
2623   :one_zero, :one_zero?,
2624   :open_file_dialog, :open_file_dialog_directory, :open_hook,
2625   :open_raw_sound, :open_raw_sound_hook, :open_sound, :orientation_hook,
2626   :oscil, :oscil?, :out_any, :outa, :outb, :outc, :outd,
2627   :output_comment_hook, :override_samples_with_origin,
2628   :pad_channel, :partials2polynomial, :partials2wave, :parzen_window,
2629   :pausing, :peaks, :peaks_font, :phase_partials2wave,
2630   :phase_vocoder, :phase_vocoder_amp_increments, :phase_vocoder_amps,
2631   :phase_vocoder_freqs, :phase_vocoder_phase_increments,
2632   :phase_vocoder_phases, :phase_vocoder?, :play, :play_arrow_size,
2633   :play_hook, :player_home, :player?, :players, :playing, :poisson_window,
2634   :polar2rectangular, :polynomial, :polyshape, :polywave, :polyshape?,
2635   :polywave?, :position2x, :position2y, :position_color, :preferences_dialog,
2636   :previous_sample, :print_dialog, :print_length, :progress_report,
2637   :pulse_train, :pulse_train?, :radians2degrees, :radians2hz, :ramp_channel,
2638   :rand, :rand_interp, :rand_interp?, :rand?, :read_mix_sample,
2639   :read_only, :read_region_sample, :read_sample, :readin, :readin?,
2640   :rectangular2magnitudes, :rectangular2polar, :rectangular_window,
2641   :redo_edit, :region2vct, :region_chans, :region_home, :region_framples,
2642   :region_graph_style, :region_maxamp, :region_maxamp_position,
2643   :region_position, :region_sample, :region_sampler?, :region_srate,
2644   :region?, :regions, :remember_sound_state, :remove_from_menu,
2645   :reset_controls, :reset_listener_cursor, :restore_controls,
2646   :restore_region, :reverb_control_decay, :reverb_control_feedback,
2647   :reverb_control_length, :reverb_control_length_bounds,
2648   :reverb_control_lowpass, :reverb_control_scale,
2649   :reverb_control_scale_bounds, :reverb_control?, :reverse_channel,
2650   :reverse_selection, :reverse_sound, :revert_sound, :riemann_window,
2651   :right_sample, :ring_modulate, :rv2_window, :rv3_window, :rv4_window,
2652   :samaraki_window, :sample, :sample2file, :sample2file?,
2653   :sampler_at_end?, :sampler_home, :sampler_position, :sampler?, :samples,
2654   :samples2seconds, :sash_color, :save_controls, :save_dir,
2655   :save_edit_history, :save_envelopes, :save_hook, :save_listener,
2656   :save_marks, :save_region, :save_region_dialog, :save_selection,
2657   :save_selection_dialog, :save_sound, :save_sound_as, :save_sound_dialog,
2658   :save_state, :save_state_file, :save_state_hook, :sawtooth_wave,
2659   :sawtooth_wave?, :scale_by, :scale_channel, :scale_selection_by,
2660   :scale_selection_to, :scale_to, :scan_channel, :script_arg,
2661   :script_args, :search_procedure, :seconds2samples, :select_all,
2662   :select_channel, :select_channel_hook, :select_sound, :select_sound_hook,
2663   :selected_channel, :selected_data_color, :selected_graph_color,
2664   :selected_sound, :selection_chans, :selection_color,
2665   :selection_context, :selection_creates_region, :selection_framples,
2666   :selection_maxamp, :selection_maxamp_position, :selection_member?,
2667   :selection_position, :selection_srate, :selection?, :short_file_name,
2668   :show_all_axes, :show_all_axes_unlabelled, :show_bare_x_axis,
2669   :show_axes, :show_controls, :show_grid, :show_indices,
2670   :show_full_duration, :show_full_range, :initial_beg, :initial_dur,
2671   :show_listener, :show_marks, :show_mix_waveforms, :show_no_axes,
2672   :show_selection, :show_selection_transform, :show_sonogram_cursor,
2673   :show_transform_peaks, :show_widget, :show_x_axis,
2674   :show_x_axis_unlabelled, :show_y_zero, :sinc_width, :nrxysin,
2675   :nrxysin?, :nrxycos, :nrxycos?, "rxyk!cos".intern, "rxyk!cos?".intern,
2676   "rxyk!sin".intern, "rxyk!sin?".intern, :smooth_channel, :smooth_selection,
2677   :smooth_sound, :snd2sample, :snd2sample?, :snd_error, :snd_error_hook,
2678   :snd_gcs, :snd_help, :snd_font, :snd_color, :snd_print, :snd_spectrum,
2679   :snd_tempnam, :snd_url, :snd_urls, :snd_version, :snd_warning,
2680   :snd_warning_hook, :sound_file_extensions, :sound_file?,
2681   :sound_files_in_directory, :sound_loop_info, :sound_properties,
2682   :sound_property, :sound_widgets, :sound?, :soundfont_info, :sounds,
2683   :spectrum_end, :spectro_hop, :spectrum_start, :spectro_x_angle,
2684   :spectro_x_scale, :spectro_y_angle, :spectro_y_scale, :spectro_z_angle,
2685   :spectro_z_scale, :spectrum, :speed_control, :speed_control_as_float,
2686   :speed_control_as_ratio, :speed_control_as_semitone,
2687   :speed_control_bounds, :speed_control_style, :speed_control_tones,
2688   :square_wave, :square_wave?, :squelch_update, :srate, :src,
2689   :src_channel, :src_selection, :src_sound, :src?, :ssb_am, :ssb_am?,
2690   :start_playing, :start_playing_hook,
2691   :start_playing_selection_hook, :start_progress_report,
2692   :status_report, :stop_player, :stop_playing,
2693   :stop_playing_hook, :stop_playing_selection_hook, :ncos, :ncos?,
2694   :nsin, :nsin?, :swap_channels, :sync, :sync_style, :sync_none,
2695   :sync_all, :sync_by_sound, :sync_max, :syncd_marks, :table_lookup,
2696   :table_lookup?, :tap, :tap?, :temp_dir, :text_focus_color, :time_graph,
2697   :time_graph_style, :time_graph_type, :time_graph?, :tiny_font,
2698   :tracking_cursor_style, :transform2vct, :transform_dialog,
2699   :transform_framples, :transform_graph, :transform_graph_style,
2700   :transform_graph_type, :transform_graph?, :transform_normalization,
2701   :transform_sample, :transform_size, :transform_type, :transform?,
2702   :triangle_wave, :triangle_wave?, :tukey_window,
2703   :two_pole, :two_pole?, :two_zero, :two_zero?, :ultraspherical_window,
2704   :unbind_key, :undo, :undo_edit, :undo_hook, :unselect_all,
2705   :update_hook, :update_lisp_graph, :update_sound, :update_time_graph,
2706   :update_transform_graph, :variable_graph?, :vct, :vct_multiply,
2707   :vct_add, :vct2channel, :vct2list, :vct2string,
2708   :vct2vector, :vct_add!, :vct_length,
2709   :vct_max, :vct_min, :vct_move!, :vct_multiply!, :vct_offset!,
2710   :vct_peak, :vct_ref, :vct_reverse!, :vct_scale!, :vct_set!, :vct_subseq,
2711   :vct_subtract!, :vct?, :vector2vct, :view_sound, :walsh_transform,
2712   :wave_train, :wave_train?, :wavelet_transform, :wavelet_type, :wavo_hop,
2713   :wavo_trace, :welch_window, :widget_position, :widget_size, :widget_text,
2714   :window_height, :window_width, :window_x, :window_y,
2715   :with_background_processes, :with_file_monitor, :with_gl,
2716   :with_mix_tags, :with_relative_panes, :with_tracking_cursor,
2717   :with_verbose_cursor, :with_inset_graph, :with_interrupts,
2718   :with_pointer_focus, :with_smpte_label, :with_toolbar, :with_tooltips,
2719   :with_menu_icons, :save_as_dialog_src, :save_as_dialog_auto_comment,
2720   :x2position, :x_axis_as_clock, :x_axis_as_percentage, :x_axis_in_beats,
2721   :x_axis_in_measures, :x_axis_in_samples, :x_axis_in_seconds,
2722   :x_axis_label, :x_axis_style, :x_bounds, :x_position_slider,
2723   :x_zoom_slider, :xramp_channel, :y2position, :y_axis_label,
2724   :y_bounds, :y_position_slider, :y_zoom_slider, :zero_pad,
2725   :zoom_color, :zoom_focus_active, :zoom_focus_left, :zoom_focus_middle,
2726   :zoom_focus_right, :zoom_focus_style].each do |n|
2727    next if Module.function?(n)
2728    str = n.to_s
2729    next if Object.const_defined?("#{str.capitalize}".intern)
2730    str = "$" + str
2731    # XXX: ruby18 likes a String
2732    next if kernel_global_variables.member?(str)
2733    # XXX: ruby19+ likes a Symbol
2734    next if kernel_global_variables.member?(str.intern)
2735    undefined << n
2736  end
2737  unless $with_test_ladspa
2738    undefined.delete_if do |s| s.to_s =~ /ladspa/ end
2739  end
2740  unless $with_test_gl
2741    undefined.delete_if do |s| s == :glSpectrogram end
2742  end
2743  unless $with_test_gl2ps
2744    undefined.delete_if do |s| s == :gl_graph2ps end
2745  end
2746  unless undefined.empty?
2747    snd_display("undefined[%d]: %s", undefined.length, undefined)
2748  end
2749end
2750
2751# ---------------- test 04: sndlib ----------------
2752
2753def frame2byte(file, frame)
2754  mus_sound_data_location(file) + mus_sound_chans(file) *
2755    mus_sound_datum_size(file) * frame
2756end
2757
2758def test_04_00
2759  oboe_snd = "oboe.snd"
2760  chns = mus_sound_chans(oboe_snd)
2761  dl = mus_sound_data_location(oboe_snd)
2762  fr = mus_sound_framples(oboe_snd)
2763  smps = mus_sound_samples(oboe_snd)
2764  len = mus_sound_length(oboe_snd)
2765  size = mus_sound_datum_size(oboe_snd)
2766  com = mus_sound_comment(oboe_snd)
2767  sr = mus_sound_srate(oboe_snd)
2768  m1 = mus_sound_maxamp_exists?(oboe_snd)
2769  mal = mus_sound_maxamp(oboe_snd)
2770  mz = mus_sound_maxamp "z.snd"
2771  bytes = mus_bytes_per_sample(mus_sound_sample_type(oboe_snd))
2772  snd_test_neq(mz[0], 0, "mus_sound_maxamp z.snd")
2773  snd_test_neq(mz[1], 0.0, "mus_sound_maxamp z.snd")
2774  [[Mus_bshort, 2],
2775   [Mus_lshort, 2],
2776   [Mus_mulaw, 1],
2777   [Mus_alaw, 1],
2778   [Mus_byte, 1],
2779   [Mus_ubyte, 1],
2780   [Mus_bfloat, 4],
2781   [Mus_lfloat, 4],
2782   [Mus_bint, 4],
2783   [Mus_lint, 4],
2784   [Mus_bintn, 4],
2785   [Mus_lintn, 4],
2786   [Mus_b24int, 3],
2787   [Mus_l24int, 3],
2788   [Mus_bdouble, 8],
2789   [Mus_ldouble, 8],
2790   [Mus_ubshort, 2],
2791   [Mus_ulshort, 2],
2792   [Mus_bdouble_unscaled, 8],
2793   [Mus_ldouble_unscaled, 8],
2794   [Mus_bfloat_unscaled, 4],
2795   [Mus_lfloat_unscaled, 4]].each do |frm, siz|
2796    snd_test_neq(mus_bytes_per_sample(frm), siz, "mus_bytes_per_sample")
2797  end
2798  snd_test_neq(mus_sample_type2string(Mus_bshort), "Mus_bshort",
2799    "mus_sample_type2string")
2800  snd_test_neq(mus_header_type2string(Mus_aifc), "Mus_aifc",
2801    "mus_header_type2string")
2802  hiho = "hiho.tmp"
2803  mus_sound_report_cache(hiho)
2804  fp = File.open(hiho)
2805  snd_test_neq(fp.readline.chomp, "sound table:", "print-cache 1")
2806  fp.close
2807  delete_file(hiho)
2808  req = 10
2809  snd_test_neq(chns, 1, "oboe: mus_sound_chans")
2810  snd_test_neq(dl, 28, "oboe: mus_sound_data_location")
2811  snd_test_neq(fr, 50828, "oboe: mus_sound_framples")
2812  snd_test_neq(smps, 50828, "oboe: mus_sound_samples")
2813  snd_test_neq(len, 50828 * 2 + 28, "oboe: mus_sound_length")
2814  snd_test_neq(size, 2, "oboe: mus_sound_datum_size")
2815  snd_test_neq(bytes, 2, "oboe: mus_sound_bytes")
2816  snd_test_neq(sr, 22050, "oboe: mus_sound_srate")
2817  if m1 and $clmtest.zero?
2818    snd_display("oboe: mus_sound_maxamp_exists? before maxamp: %s?", m1)
2819  end
2820  unless res = mus_sound_maxamp_exists?(oboe_snd)
2821    snd_display("oboe: mus_sound_maxamp_exists? after maxamp: %s?", res)
2822  end
2823  #
2824  if $clmtest.zero?
2825    res = mus_header_raw_defaults
2826    if (not array?(res)) or res.length != 3
2827      snd_display("mus_header_raw_defaults: %s?", res)
2828    end
2829    sr, chns, frm = res
2830    snd_test_neq(sr, 44100, "mus_header_raw_defaults srate")
2831    snd_test_neq(chns, 2, "mus_header_raw_defaults chns")
2832    snd_test_neq(frm, Mus_bshort, "mus_header_raw_defaults format")
2833  end
2834  old_val = mus_header_raw_defaults
2835  set_mus_header_raw_defaults([12345, 3, Mus_bdouble_unscaled])
2836  res = mus_header_raw_defaults
2837  if (not array?(res)) or res.length != 3
2838    snd_display("mus_header_raw_defaults: %s?", res)
2839  end
2840  sr, chns, frm = res
2841  snd_test_neq(sr, 12345, "mus_header_raw_defaults srate")
2842  snd_test_neq(chns, 3, "mus_header_raw_defaults chns")
2843  snd_test_neq(frm, Mus_bdouble_unscaled, "mus_header_raw_defaults format")
2844  set_mus_header_raw_defaults(old_val)
2845  #
2846  tm = mus_sound_write_date(oboe_snd)
2847  snd_test_neq(Time.at(tm).localtime.strftime("%d-%b %H:%M"), "15-Oct 04:34",
2848    "mus_sound_write_date oboe.snd")
2849  tm = mus_sound_write_date("pistol.snd")
2850  snd_test_neq(Time.at(tm).localtime.strftime("%d-%b %H:%M"), "01-Jul 22:06",
2851    "mus_sound_write_date pistol.snd")
2852  #
2853  ind = open_sound(oboe_snd)
2854  lfname = "test" + "-test" * 10 + ".snd"
2855  if variable_graph?(ind)
2856    snd_display("variable_graph thinks anything is a graph...")
2857  end
2858  if player?(ind)
2859    snd_display("player? thinks anything is a player...")
2860  end
2861  unless sound?(ind)
2862    snd_display("%s is not a sound?", ind)
2863  end
2864  if (sound?(false))
2865    snd_display("sound? false -> true?")
2866  end
2867  if (sound?(true))
2868    snd_display("sound? true -> true?")
2869  end
2870  save_sound_as(lfname, ind)
2871  close_sound(ind)
2872  #
2873  ind = open_sound(lfname)
2874  unless sound?(ind)
2875    snd_display("cannot find test...snd")
2876  end
2877  req = lfname.length
2878  snd_test_lt(file_name(ind).length, req, "file_name length")
2879  snd_test_neq(short_file_name(ind).length, req, "short_file_name length")
2880  close_sound(ind)
2881  mus_sound_forget(lfname)
2882  delete_file(lfname)
2883  #
2884  with_file("forest.aiff") do |fsnd|
2885    file_copy("fsnd", "fmv.snd")
2886    ind = open_sound("fmv.snd")
2887    snd_test_neq(sound_loop_info(ind), mus_sound_loop_info(fsnd), "loop_info")
2888    set_sound_loop_info(ind, [12000, 14000, 1, 2, 3, 4])
2889    snd_test_neq(sound_loop_info(ind),
2890      [12000, 14000, 1, 2, 3, 4, 1, 1], "set_loop_info")
2891    save_sound_as("fmv1.snd", ind, :header_type, Mus_aifc)
2892    close_sound(ind)
2893    snd_test_neq(mus_sound_loop_info("fmv1.snd"),
2894      [12000, 14000, 1, 2, 3, 4, 1, 1], "saved loop_info")
2895  end
2896  #
2897  ind = open_sound(oboe_snd)
2898  save_sound_as("fmv.snd", ind, :header_type, Mus_aifc)
2899  close_sound(ind)
2900  ind = open_sound("fmv.snd")
2901  snd_test_neq(sound_loop_info(ind), nil, "null loop_info")
2902  set_sound_loop_info(ind, [1200, 1400, 4, 3, 2, 1])
2903  snd_test_neq(sound_loop_info(ind),
2904    [1200, 1400, 4, 3, 2, 1, 1, 1], "set null loop_info")
2905  save_sound_as("fmv1.snd", :sound, ind, :header_type, Mus_aifc)
2906  close_sound(ind)
2907  snd_test_neq(mus_sound_loop_info("fmv1.snd"),
2908    [1200, 1400, 4, 3, 2, 1, 1, 1], "saved null loop_info")
2909  ind = open_sound("fmv.snd")
2910  set_sound_loop_info(ind, [1200, 1400, 4, 3, 2, 1, 1, 0])
2911  snd_test_neq(sound_loop_info(ind),
2912    [1200, 1400, 0, 0, 2, 1, 1, 0], "set null loop_info (no mode1)")
2913  save_sound_as("fmv1.snd", ind, :header_type, Mus_aifc)
2914  close_sound(ind)
2915  snd_test_neq(mus_sound_loop_info("fmv1.snd"),
2916    [1200, 1400, 0, 0, 2, 1, 1, 0], "saved null loop_info (no mode1)")
2917  #
2918  unless com.empty?
2919    snd_display("oboe: mus_sound_comment: %s", com.inspect)
2920  end
2921  [["nasahal8.wav",
2922    "ICRD: 1997-02-22\nIENG: Paul R. Roger\nISFT: Sound Forge 4.0\n"],
2923   ["8svx-8.snd",  "File created by Sound Exchange  "],
2924   ["sun-16-afsp.snd", "AFspdate:1981/02/11 23:03:34 UTC"],
2925   ["smp-16.snd", "Converted using Sox.                                        "],
2926   ["d40130.au", "1994 Jesus Villena"],
2927   ["wood.maud", "file written by SOX MAUD-export "],
2928   ["addf8.sf_mipseb",
2929    "date=\"Feb 11 18:03:34 1981\" info=\"Original recorded at 20 kHz, 15-bit D/A, digitally filtered and resampled\" speaker=\"AMK female\" text=\"Add the sum to the product of these three.\" "],
2930   ["mary-sun4.sig", "MARY HAD A LITTLE LAMB\n"],
2931   ["nasahal.pat", "This patch saved with Sound Forge 3.0."],
2932   ["next-16.snd",
2933    ";Written on Mon 1-Jul-91 at 12:10 PDT  at localhost (NeXT) using Allegro CL and clm of 25-June-91"],
2934   ["wood16.nsp", "Created by Snack   "],
2935   ["wood.sdx", "1994 Jesus Villena"],
2936   ["clmcom.aif", "this is a comment"],
2937   ["anno.aif", "1994 Jesus Villena\n"],
2938   ["telephone.wav",
2939    "sample_byte_format -s2 01\nchannel_count -i 1\nsample_count -i 36461\nsample_rate -i 16000\nsample_n_bytes -i 2\nsample_sig_bits -i 16\n"]
2940    ].each do |f, req|
2941    with_file(f) do |fsnd|
2942      snd_test_neq(mus_sound_comment(fsnd), req, "mus_sound_comment %s", fsnd)
2943    end
2944  end
2945  with_file("traffic.aiff") do |fsnd|
2946    res = mus_sound_comment(fsnd)
2947    unless string?(res)
2948      snd_display("mus_sound_comment traffic: %s", res.inspect)
2949    end
2950  end
2951  if $clmtest.zero?
2952    snd_test_neq(mal[1], 0.14724, "oboe: mus_sound_maxamp")
2953    snd_test_neq(mal[0], 24971, "oboe: mus_sound_maxamp at %d", mal[0])
2954  end
2955  res = mus_sound_type_specifier(oboe_snd)
2956  if res != 0x646e732e and # little endian reader
2957      res != 0x2e736e64    # big endian reader
2958    snd_display("oboe: mus_sound_type_specifier: 0x%x?", res)
2959  end
2960  #
2961  tm = file_write_date(oboe_snd)
2962  snd_test_neq(Time.at(tm).localtime.strftime("%d-%b-%Y %H:%M"),
2963    "15-Oct-2006 04:34", "file_write_date oboe.snd")
2964  #
2965  lasth = 1
2966  until mus_header_type_name(lasth) == "unknown"
2967    lasth += 1
2968  end
2969  if lasth < 50
2970    snd_display("header_type[%d] == %s?", lasth, mus_header_type_name(lasth))
2971  end
2972  lasth = 1
2973  until mus_sample_type_name(lasth) == "unknown"
2974    lasth += 1
2975  end
2976  if lasth < 10
2977    snd_display("sample_type[%d] == %s?", lasth, mus_sample_type_name(lasth))
2978  end
2979  [:Dont_normalize,
2980   :Normalize_globally,
2981   :Normalize_by_channel].each do |val_sym|
2982    req = Module.const_get(val_sym)
2983    set_transform_normalization(req)
2984    snd_test_neq(transform_normalization, req,
2985      "set_transform_normalization(%s)", val_sym)
2986  end
2987  #
2988  ind = new_sound("fmv.snd", 1, 22050, Mus_bshort, Mus_next,
2989                  "set_samples test", 100)
2990  set_samples(10, 3, Vct.new(3, 0.1))
2991  snd_test_neq(channel2vct(0, 20, ind, 0),
2992    vct(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.1, 0.1, 0.1, 0, 0, 0, 0, 0, 0, 0),
2993    "1 set samples 0 for 0.1")
2994  set_samples(20, 3, Vct.new(3, 0.1), ind, 0)
2995  snd_test_neq(channel2vct(10, 20, ind, 0),
2996    vct(0.1, 0.1, 0.1, 0, 0, 0, 0, 0, 0, 0, 0.1, 0.1, 0.1, 0, 0, 0, 0, 0, 0, 0),
2997    "2 set samples 10 for 0.1")
2998  set_samples(30, 3, Vct.new(3, 0.1), ind, 0, false, "a name")
2999  snd_test_neq(channel2vct(20, 20, ind, 0),
3000    vct(0.1, 0.1, 0.1, 0, 0, 0, 0, 0, 0, 0, 0.1, 0.1, 0.1, 0, 0, 0, 0, 0, 0, 0),
3001    "3 set samples 20 for 0.1")
3002  set_samples(0, 3, Vct.new(3, 0.2), ind, 0, false, "a name", 0, 1)
3003  snd_test_neq(channel2vct(0, 20, ind, 0),
3004    vct(0.2, 0.2, 0.2, 0, 0, 0, 0, 0, 0, 0, 0.1, 0.1, 0.1, 0, 0, 0, 0, 0, 0, 0),
3005    "4 set samples 0 at 1 for 0.1")
3006  snd_test_neq(channel2vct(20, 20, ind, 0),
3007    Vct.new(20, 0.0),
3008    "5 set samples 20 at 1 for 0.1")
3009  nd = new_sound("fmv1.snd", :channels, 2)
3010  vct2channel(Vct.new(10, 0.5), 0, 10, nd, 0)
3011  vct2channel(Vct.new(10, 0.3), 0, 10, nd, 1)
3012  save_sound_as("fmv1.snd", nd)
3013  close_sound(nd)
3014  unless File.exist?("fmv1.snd")
3015    snd_display("fmv1.snd not saved?")
3016  end
3017  set_samples(0, 10, "fmv1.snd", ind, 0, false, "another name", 1)
3018  snd_test_neq(channel2vct(0, 20, ind, 0),
3019    vct(0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3,
3020    0.1, 0.1, 0.1, 0, 0, 0, 0, 0, 0, 0),
3021               "6 set samples 0 at 1 for 0.1")
3022  set_samples(5, 6, "fmv1.snd", ind, 0, false, "another name 7", 0)
3023  snd_test_neq(channel2vct(0, 20, ind, 0),
3024    vct(0.3, 0.3, 0.3, 0.3, 0.3, 0.5, 0.5, 0.5, 0.5, 0.5,
3025        0.5, 0.1, 0.1, 0, 0, 0, 0, 0, 0, 0),
3026    "7 set samples 0 at 1 for 0.1")
3027  revert_sound(ind)
3028  set_samples(0, 10, "fmv1.snd", ind, 0, false, "another name 8", 1, 0, false)
3029  snd_test_neq(channel2vct(0, 20, ind, 0),
3030    vct(0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3,
3031        0.3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
3032    "8 set samples 0 at 1 for 0.1")
3033  set_samples(10, 10, "fmv1.snd", ind, 0, false, "another name 9", 0, 0)
3034  snd_test_neq(channel2vct(0, 20, ind, 0),
3035    vct(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0.5,
3036        0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5),
3037    "9 set samples 0 at 1 for 0.1")
3038  set_samples(20, 10, "fmv1.snd")
3039  snd_test_neq(channel2vct(10, 20, ind, 0),
3040    Vct.new(20, 0.5),
3041    "10 set samples 0 at 1 for 0.1")
3042  revert_sound(ind)
3043  set_samples(0, 10, "fmv1.snd", ind, 0, true, "another name", 1, 0, false)
3044  snd_test_neq(framples(ind, 0), 10, "11 set samples truncate")
3045  revert_sound(ind)
3046  delete_file("fmv1.snd")
3047  #
3048  res = Snd.catch do set_samples(0, 10, "fmv1.snd", ind, 0) end
3049  if res.first != :no_such_file
3050    snd_display("set samples, no such file: %s", res.inspect)
3051  end
3052  nd = new_sound("fmv1.snd", :channels, 1)
3053  vct2channel(Vct.new(10, 0.5), 0, 10, nd, 0)
3054  save_sound_as("fmv1.snd", nd)
3055  close_sound(nd)
3056  if (res = Snd.catch do
3057        set_samples(0, 10, "fmv1.snd", ind, 0, false, "another name", 1)
3058      end).first != :no_such_channel
3059    snd_display("set samples no such channel: %s", res.inspect)
3060  end
3061  if (res = Snd.catch do
3062        set_samples(0, 10, "fmv1.snd", ind, 0, false, "another name", -1)
3063      end).first != :no_such_channel
3064    snd_display("set samples no such channel (-1): %s", res.inspect)
3065  end
3066  res = Snd.catch do set_samples(0, -10, "fmv1.snd") end
3067  if res.first != :wrong_type_arg
3068    snd_display("set samples (-10): %s", res.inspect)
3069  end
3070  res = Snd.catch do set_samples(-10, 10, "fmv1.snd") end
3071  if res.first != :no_such_sample
3072    snd_display("set samples (beg -10): %s", res.inspect)
3073  end
3074  close_sound(ind)
3075  #
3076  len = 100
3077  [[Mus_bshort,  2 ** -15],
3078   [Mus_lshort,  2 ** -15],
3079   [Mus_mulaw,   0.02],
3080   [Mus_alaw,    0.02],
3081   [Mus_byte,    2 ** -7],
3082   [Mus_lfloat,  2 ** -23],
3083   [Mus_bint,    2 ** -23],
3084   [Mus_lint,    2 ** -23],
3085   [Mus_b24int,  2 ** -23],
3086   [Mus_l24int,  2 ** -23],
3087   [Mus_ubshort, 2 ** -15],
3088   [Mus_ulshort, 2 ** -15],
3089   [Mus_ubyte,   2 ** -7],
3090   [Mus_bfloat,  2 ** -23],
3091   [Mus_bdouble, 2 ** -23],
3092   [Mus_ldouble, 2 ** -23]].each do |type, allowed_diff|
3093    ind = new_sound("test.snd", 1, 22050, Mus_bfloat, Mus_next)
3094    v = make_vct(len)
3095    maxdiff = 0.0
3096    maxpos = false
3097    v[0] =  0.999
3098    v[1] = -1.000
3099    v[2] =  0.100
3100    v[3] = -0.100
3101    v[4] =  0.010
3102    v[5] = -0.010
3103    v[6] =  0.001
3104    v[7] = -0.001
3105    v[8] =  0.000
3106    9.upto(len - 1) do |i|
3107      val = random(1.9999)
3108      if val > 2.0 or val < 0.0
3109        snd_display("random 2.0: %1.4f?", val)
3110      end
3111      v[i] = 1.0 - val
3112    end
3113    vct2channel(v, 0, len, ind, 0)
3114    save_sound_as("test1.snd", ind, :header_type, Mus_next, :sample_type, type)
3115    close_sound(ind)
3116    ind = open_sound("test1.snd")
3117    v1 = channel2vct(0, len, ind, 0)
3118    len.times do |i|
3119      diff = (v[i] - v1[i]).abs
3120      if diff > maxdiff
3121        maxdiff = diff
3122        maxpos = i
3123      end
3124    end
3125    if maxdiff > allowed_diff
3126      snd_display(snd_format_neq(v1[maxpos], v[maxpos],
3127        "type %s: maxdiff %1.4f, maxpos %d",
3128        mus_sample_type_name(type),
3129        maxdiff,
3130        maxpos))
3131    end
3132    close_sound(ind)
3133  end
3134  #
3135  ob = view_sound(oboe_snd)
3136  samp = sample(1000, ob)
3137  old_comment = mus_sound_comment(oboe_snd)
3138  str = format("written %s",
3139    Time.now.localtime.strftime("%a %d-%b-%Y %H:%M"))
3140  set_comment(ob, str)
3141  #
3142  check_it = lambda do |snd, type, fmt|
3143    snd_test_neq(header_type(snd), type,
3144      "save_as %s", mus_header_type_name(type))
3145    ntyp = mus_sound_header_type("test.snd")
3146    snd_test_neq(ntyp,
3147                 type,
3148                 "saved_as %s -> %s",
3149                 mus_header_type_name(type),
3150                 mus_header_type_name(ntyp))
3151    snd_test_neq(sample_type(snd), fmt,
3152      "save_as %s", mus_sample_type_name(fmt))
3153    nfmt = mus_sound_sample_type("test.snd")
3154    snd_test_neq(nfmt,
3155                 fmt,
3156                 "saved_as %s -> %s",
3157                 mus_sample_type_name(fmt),
3158                 mus_sample_type_name(nfmt))
3159    snd_test_neq(sample(1000, snd), samp,
3160      "%s[1000]", mus_header_type_name(type))
3161  end
3162  #
3163  tag = Snd.catch do
3164    save_sound_as("test.snd", ob,
3165                  :header_type, Mus_aifc, :sample_type, Mus_bdouble)
3166  end
3167  if tag.first == :cannot_save
3168    snd_display("save_sound_as test.snd write trouble: %s", tag)
3169  end
3170  #
3171  set_filter_control_in_hz(true)
3172  ab = open_sound("test.snd")
3173  check_it.call(ab, Mus_aifc, Mus_bdouble)
3174  snd_test_neq(mus_sound_comment("test.snd"), str, "output_comment")
3175  snd_test_neq(comment(ab), str, "output_comment (comment)")
3176  close_sound(ab)
3177  snd_test_neq(mus_sound_comment(oboe_snd), old_comment,
3178    "set_comment overwrote current")
3179  set_filter_control_in_hz(false)
3180  #
3181  save_sound_as("test.snd", ob, :header_type, Mus_raw)
3182  ab = open_raw_sound("test.snd", 1, 22050, Mus_bshort)
3183  check_it.call(ab, Mus_raw, Mus_bshort)
3184  close_sound(ab)
3185  #
3186  save_sound_as("test.snd", ob, :header_type, Mus_nist, :sample_type, Mus_bint)
3187  ab = open_sound("test.snd")
3188  check_it.call(ab, Mus_nist, Mus_bint)
3189  close_sound(ab)
3190  #
3191  $output_comment_hook.reset_hook!
3192  $output_comment_hook.add_hook!("snd-test-4") do |string|
3193    string + " [written by me]"
3194  end
3195  save_sound_as(:file, "test.snd",
3196                :sound, ob,
3197                :header_type, Mus_riff,
3198                :sample_type, Mus_lfloat)
3199  $output_comment_hook.reset_hook!
3200  ab = open_sound("test.snd")
3201  check_it.call(ab, Mus_riff, Mus_lfloat)
3202  snd_test_neq(comment(ab), str + " [written by me]", "output_comment_hook")
3203  close_sound(ab)
3204  [[Mus_aiff,  Mus_b24int],
3205   [Mus_ircam, Mus_mulaw],
3206   [Mus_next,  Mus_alaw],
3207   [Mus_next,  Mus_ldouble]].each do |type, fmt|
3208    save_sound_as("test.snd", ob, :header_type, type, :sample_type, fmt)
3209    ab = open_sound("test.snd")
3210    check_it.call(ab, type, fmt)
3211    close_sound(ab)
3212  end
3213  save_sound_as("test.snd", ob,
3214                :header_type, Mus_next, :sample_type, Mus_bshort)
3215  ab = open_sound("test.snd")
3216  check_it.call(ab, Mus_next, Mus_bshort)
3217  $update_hook.reset_hook!
3218  set_y_bounds([-3.0, 3.0], ab, 0)
3219  set_sample_type(ab, Mus_lshort)
3220  # ; these set!'s can change the index via update-sound
3221  if find_sound("test.snd") != ab
3222    ab = find_sound("test.snd")
3223  end
3224  frm = sample_type(ab)
3225  snd_test_neq(frm, Mus_lshort, "set_sample_type %s", mus_sample_type_name(frm))
3226  snd_test_neq(y_bounds(ab, 0), [-3.0, 3.0], "set data format y_bounds")
3227  set_y_bounds([2.0], ab, 0)
3228  snd_test_neq(y_bounds(ab, 0), [-2.0, 2.0], "set data format y_bounds 1")
3229  set_y_bounds([-2.0], ab, 0)
3230  snd_test_neq(y_bounds(ab, 0), [-2.0, 2.0], "set data format y_bounds -2")
3231  set_header_type(ab, Mus_aifc)
3232  if find_sound("test.snd") != ab
3233    ab = find_sound("test.snd")
3234  end
3235  type = header_type(ab)
3236  snd_test_neq(type, Mus_aifc, "set_header_type %s", mus_header_type_name(type))
3237  set_channels(ab, 3)
3238  if find_sound("test.snd") != ab
3239    ab = find_sound("test.snd")
3240  end
3241  snd_test_neq(channels(ab), 3, "set_channels")
3242  set_data_location(ab, 1234)
3243  if find_sound("test.snd") != ab
3244    ab = find_sound("test.snd")
3245  end
3246  snd_test_neq(data_location(ab), 1234, "set_data_location")
3247  old_size = data_size(ab)
3248  set_data_size(ab, 1234)
3249  if find_sound("test.snd") != ab
3250    ab = find_sound("test.snd")
3251  end
3252  snd_test_neq(data_size(ab), 1234, "set_data_size")
3253  set_data_size(ab, old_size)
3254  set_srate(ab, 12345)
3255  if find_sound("test.snd") != ab
3256    ab = find_sound("test.snd")
3257  end
3258  snd_test_neq(srate(ab), 12345, "set_srate")
3259  close_sound(ab)
3260  #
3261  save_sound_as("test.snd", ob,
3262                :header_type, Mus_next, :sample_type, Mus_bfloat)
3263  ab = open_sound("test.snd")
3264  check_it.call(ab, Mus_next, Mus_bfloat)
3265  close_sound(ab)
3266  #
3267  save_sound_as("test.snd", ob,
3268                :header_type, Mus_next, :sample_type, Mus_bshort)
3269  close_sound(ob)
3270  ab = open_sound("test.snd")
3271  set_sample_type(Mus_lshort)
3272  if find_sound("test.snd") != ab
3273    ab = find_sound("test.snd")
3274  end
3275  frm = sample_type(ab)
3276  snd_test_neq(frm, Mus_lshort, "set_sample_type %s", mus_sample_type_name(frm))
3277  set_header_type(Mus_aifc)
3278  if find_sound("test.snd") != ab
3279    ab = find_sound("test.snd")
3280  end
3281  type = header_type(ab)
3282  snd_test_neq(type, Mus_aifc, "set_header_type %s", mus_header_type_name(type))
3283  set_channels(3)
3284  if find_sound("test.snd") != ab
3285    ab = find_sound("test.snd")
3286  end
3287  snd_test_neq(channels(), 3, "set_channels")
3288  set_data_location(1234)
3289  if find_sound("test.snd") != ab
3290    ab = find_sound("test.snd")
3291  end
3292  snd_test_neq(data_location(), 1234, "set_data_location")
3293  set_srate(12345)
3294  if find_sound("test.snd") != ab
3295    ab = find_sound("test.snd")
3296  end
3297  snd_test_neq(srate(), 12345, "set_srate")
3298  close_sound(ab)
3299  #
3300  ind = open_sound("2a.snd")
3301  [[lambda do
3302      save_sound_as("test.snd",
3303        :header_type, Mus_riff, :sample_type, Mus_l24int, :channel, 0)
3304    end,
3305    Mus_riff,
3306    Mus_l24int,
3307    srate(ind)],
3308   [lambda do
3309      save_sound_as("test.snd",
3310        :header_type, Mus_aifc, :sample_type, Mus_bfloat, :channel, 1,
3311        :srate, 12345)
3312    end,
3313    Mus_aifc,
3314    Mus_bfloat,
3315    12345],
3316   [lambda do
3317      save_sound_as("test.snd", :channel, 1, :comment, "this is a test")
3318    end,
3319    header_type(ind),
3320    sample_type(ind),
3321    srate(ind)]].each_with_index do |args, i|
3322    prc, type, fmt, sr = args
3323    prc.call
3324    snd = open_sound("test.snd")
3325    info = format("save_sound_as :channel %d", i)
3326    snd_test_neq(channels(snd), 1, "%s channels", info)
3327    snd_test_neq(header_type(snd), type, "%s header_type", info)
3328    snd_test_neq(sample_type(snd), fmt, "%s sample_type", info)
3329    snd_test_neq(srate(snd), sr, "%s srate", info)
3330    snd_test_neq(framples(snd), framples(ind, 0), "%s framples", info)
3331    snd_test_neq(maxamp(snd, 0), maxamp(ind, 0), "%s maxamp", info)
3332    close_sound(snd)
3333  end
3334  close_sound(ind)
3335  #
3336  [["t15.aiff", [[132300, 0.148], [132300, 0.126]]],
3337   ["M1F1-float64C-AFsp.aif",
3338    [[8000, -0.024], [8000, 0.021]]]].each do |f, vals|
3339    with_file(f) do |fsnd|
3340      ind = open_sound(fsnd)
3341      chn = -1
3342      if vals.detect do |val|
3343          chn += 1
3344          fneq(sample(val[0], ind, chn), val[1])
3345        end
3346        snd_display("%s trouble[%s]: %s", fsnd, chn,
3347          vals.map_with_index do |val, i| sample(val[0], ind, i) end)
3348      end
3349      close_sound(ind)
3350    end
3351  end
3352  #
3353  [["bad_chans.snd", [0, 22050, 0]],
3354   ["bad_srate.snd", [1, 0, 0]],
3355   ["bad_sample_type.snd", [1, 22050, 4411]],
3356   ["bad_chans.aifc", [0, 22050, 0]],
3357   ["bad_srate.aifc", [1, 0, 0]],
3358   ["bad_length.aifc", [1, 22050, -10]],
3359   ["bad_chans.riff", [0, 22050, 0]],
3360   ["bad_srate.riff", [1, 0, 0]],
3361   ["bad_chans.nist", [0, 22050, 0]],
3362   ["bad_srate.nist", [1, 0, 0]],
3363   ["bad_length.nist", [1, 22050, -10]]].each do |f, vals|
3364    with_file(f) do |fsnd|
3365      res = Snd.catch do
3366        [mus_sound_chans(fsnd),
3367         mus_sound_srate(fsnd),
3368         mus_sound_framples(fsnd)]
3369      end.first
3370      if res != vals and res != :mus_error
3371        snd_display(snd_format_neq(res, vals, fsnd))
3372      end
3373    end
3374  end
3375  #
3376  ind = open_sound("/usr/include/sys/" + Dir.pwd + "/oboe.snd")
3377  if (not sound?(ind)) or (short_file_name(ind) != "oboe.snd")
3378    snd_display("open_sound with slashes: %s", ind)
3379  end
3380  $bad_header_hook.reset_hook!
3381  $bad_header_hook.add_hook!("snd-test-4") do |n| true end
3382  ["bad_chans.snd",
3383   "bad_srate.snd",
3384   "bad_chans.aifc",
3385   "bad_srate.aifc",
3386   "bad_length.aifc",
3387   "bad_chans.riff",
3388   "bad_srate.riff",
3389   "bad_chans.nist",
3390   "bad_location.nist",
3391   "bad_field.nist",
3392   "bad_srate.nist",
3393   "bad_length.nist"].each do |f|
3394    with_file(f) do |fsnd|
3395      Snd.catch do insert_sound(fsnd) end
3396      Snd.catch do convolve_with(fsnd) end
3397      Snd.catch do mix(fsnd) end
3398      Snd.catch do
3399        snd = open_sound(fsnd)
3400        sound?(snd) and close_sound(snd)
3401      end
3402    end
3403  end
3404  close_sound(ind)
3405  Snd.sounds.apply(:close_sound)
3406  #
3407  if selected_sound
3408    snd_display("selected_sound %s %s?", selected_sound, sounds.inspect)
3409  end
3410  #
3411  with_file("a.sf2") do |fsnd|
3412    fil = open_sound(fsnd)
3413    loops = soundfont_info(fil)
3414    if loops.nil? or loops[0][2] != 65390 or loops[1][1] != 65490
3415      snd_display("soundfont_info: %s", loops.inspect)
3416    end
3417    close_sound(fil)
3418  end
3419end
3420
3421def test_04_01
3422  ["trunc.snd",
3423   "trunc.aiff",
3424   "trunc.wav",
3425   "trunc.sf",
3426   "trunc.voc",
3427   "trunc.nist",
3428   "bad.wav",
3429   "trunc1.aiff",
3430   "badform.aiff"].each do |file|
3431    with_file(file) do |fsnd|
3432      res = Snd.catch do open_sound(fsnd) end
3433      snd_test_neq(res.first, :mus_error, "open_sound %s", file)
3434    end
3435  end
3436  $open_raw_sound_hook.add_hook!("snd-test-044") do |file, choice|
3437    [1, 22050, Mus_bshort]
3438  end
3439  with_file("empty.snd") do |fsnd|
3440    ind = open_sound(fsnd)
3441    if sample_type(ind) != Mus_bshort or
3442        channels(ind) != 1 or
3443        srate(ind) != 22050 or
3444        data_location(ind) != 0 or
3445        framples(ind) != 0
3446      snd_display("open raw: %s %s %s %s %s?",
3447                  sample_type(ind),
3448                  channels(ind),
3449                  srate(ind),
3450                  data_location(ind),
3451                  framples(ind))
3452    end
3453    close_sound(ind)
3454  end
3455  $open_raw_sound_hook.reset_hook!
3456end
3457
3458def test_04_03
3459  #
3460  # check clipping choices
3461  #
3462  ind = view_sound("oboe.snd")
3463  set_clipping(false)
3464  scale_channel(10.0)
3465  save_sound_as("test.snd", ind,
3466                :header_type, Mus_next, :sample_type, Mus_bfloat)
3467  undo_edit(1, ind, 0)
3468  ind1 = open_sound("test.snd")
3469  snd_test_neq(maxamp(ind1, 0), 10.0 * maxamp(ind, 0), "clipping 0")
3470  close_sound(ind1)
3471  delete_file("test.snd")
3472  #
3473  set_clipping(true)
3474  map_channel(lambda do |y| y * 10.0 end, 0, framples(), ind, 0)
3475  save_sound_as("test.snd", ind,
3476                :header_type, Mus_next, :sample_type, Mus_bfloat)
3477  undo_edit(1, ind, 0)
3478  ind1 = open_sound("test.snd")
3479  snd_test_neq(maxamp(ind1, 0), 1.0, "clipping 1")
3480  close_sound(ind1)
3481  delete_file("test.snd")
3482  #
3483  set_clipping(false)
3484  mx = maxamp(ind)
3485  map_channel(lambda do |y| y + (1.001 - mx) end, 0, framples(), ind, 0)
3486  save_sound_as("test.snd", ind,
3487                :header_type, Mus_next, :sample_type, Mus_bfloat)
3488  ind1 = open_sound("test.snd")
3489  if res = scan_channel(lambda do |y| y < 0.0 end)
3490    snd_display("clipping 2: %s?", res)
3491  end
3492  close_sound(ind1)
3493  delete_file("test.snd")
3494  #
3495  set_clipping(true)
3496  save_sound_as("test.snd", ind,
3497                :header_type, Mus_next, :sample_type, Mus_bshort)
3498  ind1 = open_sound("test.snd")
3499  if res = scan_channel(lambda do |y| y < 0.0 end)
3500    snd_display("clipping 3: %s?", res)
3501  end
3502  close_sound(ind1)
3503  delete_file("test.snd")
3504  #
3505  set_clipping(false)
3506  close_sound(ind)
3507  #
3508  set_clipping(false)
3509  snd = new_sound("test.snd", :sample_type, Mus_lshort)
3510  pad_channel(0, 10)
3511  set_sample(1,  1.0)
3512  set_sample(2, -1.0)
3513  set_sample(3,  0.9999)
3514  set_sample(4,  2.0)
3515  set_sample(5, -2.0)
3516  set_sample(6,  1.3)
3517  set_sample(7, -1.3)
3518  set_sample(8,  1.8)
3519  set_sample(9, -1.8)
3520  save_sound(snd)
3521  close_sound(snd)
3522  snd = open_sound("test.snd")
3523  snd_test_neq(channel2vct(0, 10),
3524               vct(0.0, 1.0, -1.0, 1.0, 0.0, 0.0, -0.7, 0.7, -0.2, 0.2),
3525               "unclipped 1")
3526  close_sound(snd)
3527  mus_sound_forget("test.snd")
3528  #
3529  set_clipping(true)
3530  snd = new_sound("test.snd", :sample_type, Mus_lshort)
3531  pad_channel(0, 10)
3532  set_sample(1,  1.0)
3533  set_sample(2, -1.0)
3534  set_sample(3,  0.9999)
3535  set_sample(4,  2.0)
3536  set_sample(5, -2.0)
3537  set_sample(6,  1.3)
3538  set_sample(7, -1.3)
3539  set_sample(8,  1.8)
3540  set_sample(9, -1.8)
3541  save_sound(snd)
3542  close_sound(snd)
3543  snd = open_sound("test.snd")
3544  snd_test_neq(channel2vct(0, 10),
3545               vct(0.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0),
3546               "clipped")
3547  close_sound(snd)
3548  #
3549  with_file("32bit.sf") do |fsnd|
3550    ind = open_sound(fsnd)
3551    snd_test_neq(maxamp(ind, 0), 0.228, "32bit max")
3552    close_sound(ind)
3553  end
3554  [["next-dbl.snd", 10, 10,
3555    vct(0.475, 0.491, 0.499, 0.499, 0.492, 0.476, 0.453, 0.423, 0.387, 0.344)],
3556   ["oboe.ldbl", 1000, 10,
3557    vct(0.033, 0.035, 0.034, 0.031, 0.026, 0.020, 0.013, 0.009, 0.005, 0.004)],
3558   ["next-flt.snd", 10, 10,
3559    vct(0.475, 0.491, 0.499, 0.499, 0.492, 0.476, 0.453, 0.423, 0.387, 0.344)],
3560   ["clbonef.wav", 1000, 10,
3561    vct(0.111, 0.101, 0.070, 0.032, -0.014, -0.060, -0.085, -0.108, -0.129, -0.152)],
3562   ["next-8.snd", 10, 10,
3563    vct(0.898, 0.945, 0.977, 0.992, 0.992, 0.977, 0.945, 0.906, 0.844, 0.773)],
3564   ["o2_u8.wave", 1000, 10,
3565    vct(-0.164, -0.219, -0.258, -0.242, -0.180, -0.102, -0.047, 0.000, 0.039, 0.055)],
3566   ["next-16.snd", 1000, 10,
3567    vct(-0.026, -0.022, -0.024, -0.030, -0.041, -0.048, -0.050, -0.055, -0.048, -0.033)],
3568   ["o2.wave", 1000, 10,
3569    vct(-0.160, -0.216, -0.254, -0.239, -0.175, -0.102, -0.042, 0.005, 0.041, 0.059)],
3570   ["o2_18bit.aiff", 1000, 10,
3571    vct(-0.160, -0.216, -0.254, -0.239, -0.175, -0.102, -0.042, 0.005, 0.041, 0.059)],
3572   ["o2_12bit.aiff", 1000, 10,
3573    vct(-0.160, -0.216, -0.254, -0.239, -0.175, -0.102, -0.042, 0.005, 0.041, 0.059)],
3574   ["next24.snd", 1000, 10,
3575    vct(-0.160, -0.216, -0.254, -0.239, -0.175, -0.102, -0.042, 0.005, 0.041, 0.059)],
3576   ["mono24.wav", 1000, 10,
3577    vct(0.005, 0.010, 0.016, 0.008, -0.007, -0.018, -0.025, -0.021, -0.005, 0.001)],
3578   ["o2_711u.wave", 1000, 10,
3579    vct(-0.164, -0.219, -0.254, -0.242, -0.172, -0.103, -0.042, 0.005, 0.042, 0.060)],
3580   ["alaw.wav", 1000, 10,
3581    vct(-0.024, -0.048, -0.024, 0.000, 0.008, 0.008, 0.000, -0.040, -0.064, -0.024)],
3582   ["b32.pvf", 1000, 10,
3583    vct(-0.160, -0.216, -0.254, -0.239, -0.175, -0.102, -0.042, 0.005, 0.041, 0.059)],
3584   ["b32.wave", 1000, 10,
3585    vct(-0.160, -0.216, -0.254, -0.239, -0.175, -0.102, -0.042, 0.005, 0.041, 0.059)],
3586   ["b32.snd", 1000, 10,
3587    vct(-0.160, -0.216, -0.254, -0.239, -0.175, -0.102, -0.042, 0.005, 0.041, 0.059)],
3588   ["32bit.sf", 1000, 10,
3589    vct(0.016, 0.014, 0.013, 0.011, 0.010, 0.010, 0.010, 0.010, 0.012, 0.014)],
3590   ["nist-shortpack.wav", 10000, 10,
3591    vct(0.021, 0.018, 0.014, 0.009, 0.004, -0.001, -0.004, -0.006, -0.007, -0.008)],
3592   ["wood.sds", 1000, 10,
3593    vct(-0.160, -0.216, -0.254, -0.239, -0.175, -0.102, -0.042, 0.005, 0.041, 0.059)],
3594   ["mus10.snd", 10000, 10,
3595    vct(0.004, 0.001, 0.005, 0.009, 0.017, 0.015, 0.008, 0.011, 0.009, 0.012)],
3596   ["ieee-text-16.snd", 1000, 10,
3597    vct(-0.052, -0.056, -0.069, -0.077, -0.065, -0.049, -0.054, -0.062, -0.066, -0.074)],
3598   ["hcom-16.snd", 10000, 10,
3599    vct(0.000, 0.000, 0.000, 0.008, 0.000, -0.016, -0.016, -0.016, -0.008, 0.000)],
3600   ["ce-c3.w02", 1000, 10,
3601    vct(0.581, 0.598, 0.596, 0.577, 0.552, 0.530, 0.508, 0.479, 0.449, 0.425)],
3602   ["nasahal.avi", 20000, 10,
3603    vct(0.390, 0.120, -0.399, -0.131, 0.464, 0.189, -0.458, -0.150, 0.593, 0.439)],
3604   ["oki.wav", 100, 10,
3605    vct(0.396, 0.564, 0.677, 0.779, 0.761, 0.540, 0.209, -0.100, -0.301, -0.265)],
3606   ["trumps22.adp", 5000, 10,
3607    vct(0.267, 0.278, 0.309, 0.360, 0.383, 0.414, 0.464, 0.475, 0.486, 0.495)]
3608  ].each do |file, beg, dur, data|
3609    with_file(file) do |fsnd|
3610      Snd.catch do
3611        ind = open_sound(fsnd)
3612        snd_test_neq(channel2vct(beg, dur, ind, 0), data, "%s", file)
3613        close_sound(ind)
3614      end
3615    end
3616  end
3617end
3618
3619def test_04_04
3620  ["no error",
3621   "no frequency method",
3622   "no phase method",
3623   "null gen arg to method",
3624   "no length method",
3625   "no describe method",
3626   "no data method",
3627   "no scaler method",
3628   "memory allocation failed",
3629   "can't open file",
3630   "no sample input",
3631   "no sample output",
3632   "no such channel",
3633   "no file name provided",
3634   "no location method",
3635   "no channel method",
3636   "no such fft window",
3637   "unknown sample type",
3638   "header read failed",
3639   "unknown header type",
3640   "file descriptors not initialized",
3641   "not a sound file",
3642   "file closed",
3643   "write error",
3644   "header write failed",
3645   "can't open temp file",
3646   "interrupted",
3647   "bad envelope",
3648   "audio channels not available",
3649   "audio srate not available",
3650   "audio sample type not available",
3651   "no audio input available",
3652   "audio configuration not available",
3653   "audio write error",
3654   "audio size not available",
3655   "audio device not available",
3656   "can't close audio",
3657   "can't open audio",
3658   "audio read error",
3659   "can't write audio",
3660   "can't read audio",
3661   "no audio read permission",
3662   "can't close file",
3663   "arg out of range",
3664   "no channels method",
3665   "no hop method",
3666   "no width method",
3667   "no file-name method",
3668   "no ramp method",
3669   "no run method",
3670   "no increment method",
3671   "no offset method",
3672   "no xcoeff method",
3673   "no ycoeff method",
3674   "no xcoeffs method",
3675   "no ycoeffs method",
3676   "no reset",
3677   "bad size",
3678   "can't convert",
3679   "read error",
3680   "no feedforward method",
3681   "no feedback method",
3682   "no interp-type method",
3683   "no position method",
3684   "no order method",
3685   "no copy method",
3686   "can't translate"].each_with_index do |err, i|
3687    snd_test_neq(err, mus_error_type2string(i), "mus_error_type2string %d", i)
3688  end
3689  oboe_snd = "oboe.snd"
3690  cur_srate = mus_sound_srate(oboe_snd)
3691  cur_chans = mus_sound_chans(oboe_snd)
3692  cur_format = mus_sound_sample_type(oboe_snd)
3693  cur_type = mus_sound_header_type(oboe_snd)
3694  cur_loc = mus_sound_data_location(oboe_snd)
3695  cur_samps = mus_sound_samples(oboe_snd)
3696  set_mus_sound_srate(oboe_snd, cur_srate * 2)
3697  snd_test_neq(mus_sound_srate(oboe_snd), cur_srate * 2,
3698               "set_mus_sound_srate")
3699  set_mus_sound_samples(oboe_snd, cur_samps * 2)
3700  snd_test_neq(mus_sound_samples(oboe_snd), cur_samps * 2,
3701               "set_mus_sound_samples")
3702  set_mus_sound_chans(oboe_snd, cur_chans * 2)
3703  snd_test_neq(mus_sound_chans(oboe_snd), cur_chans * 2,
3704               "set_mus_sound_chans")
3705  set_mus_sound_data_location(oboe_snd, cur_loc * 2)
3706  snd_test_neq(mus_sound_data_location(oboe_snd), cur_loc * 2,
3707               "set_mus_sound_data_location")
3708  set_mus_sound_header_type(oboe_snd, Mus_nist)
3709  snd_test_neq(mus_sound_header_type(oboe_snd), Mus_nist,
3710               "set_mus_sound_header_type")
3711  set_mus_sound_sample_type(oboe_snd, Mus_lintn)
3712  snd_test_neq(mus_sound_sample_type(oboe_snd), Mus_lintn,
3713               "set_mus_sound_sample_type")
3714  set_mus_sound_srate(oboe_snd, cur_srate)
3715  set_mus_sound_samples(oboe_snd, cur_samps)
3716  set_mus_sound_chans(oboe_snd, cur_chans)
3717  set_mus_sound_data_location(oboe_snd, cur_loc)
3718  set_mus_sound_header_type(oboe_snd, cur_type)
3719  set_mus_sound_sample_type(oboe_snd, cur_format)
3720  #
3721  ind = open_sound("oboe.snd")
3722  save_sound_as("test.wave", ind, :header_type, Mus_riff)
3723  save_sound_as("test.rf64", ind, :header_type, Mus_rf64)
3724  save_sound_as("test.aifc", ind, :header_type, Mus_aifc)
3725  close_sound(ind)
3726  ["test.wave",
3727   "test.rf64",
3728   "test.aifc"].each do |file|
3729    cur_srate = mus_sound_srate(file)
3730    cur_chans = mus_sound_chans(file)
3731    cur_format = mus_sound_sample_type(file)
3732    cur_type = mus_sound_header_type(file)
3733    cur_loc = mus_sound_data_location(file)
3734    cur_samps = mus_sound_samples(file)
3735    set_mus_sound_srate(file, cur_srate * 2)
3736    snd_test_neq(mus_sound_srate(file), cur_srate * 2,
3737                 "%s set_mus_sound_srate", file)
3738    set_mus_sound_samples(file, cur_samps * 2)
3739    snd_test_neq(mus_sound_samples(file), cur_samps * 2,
3740                 "%s set_mus_sound_samples", file)
3741    set_mus_sound_chans(file, cur_chans * 2)
3742    snd_test_neq(mus_sound_chans(file), cur_chans * 2,
3743                 "%s set_mus_sound_chans", file)
3744    set_mus_sound_data_location(file, cur_loc * 2)
3745    snd_test_neq(mus_sound_data_location(file), cur_loc * 2,
3746                 "%s set_mus_sound_data_location", file)
3747    set_mus_sound_header_type(file, Mus_nist)
3748    snd_test_neq(mus_sound_header_type(file), Mus_nist,
3749                 "%s set_mus_sound_header_type", file)
3750    set_mus_sound_sample_type(file, Mus_lintn)
3751    snd_test_neq(mus_sound_sample_type(file), Mus_lintn,
3752                 "%s set_mus_sound_sample_type", file)
3753    set_mus_sound_srate(file, cur_srate)
3754    set_mus_sound_samples(file, cur_samps)
3755    set_mus_sound_chans(file, cur_chans)
3756    set_mus_sound_data_location(file, cur_loc)
3757    set_mus_sound_header_type(file, cur_type)
3758    set_mus_sound_sample_type(file, cur_format)
3759  end
3760  ["test.wave",
3761   "test.rf64",
3762   "test.aifc"].each do |file|
3763    ind = open_sound(file)
3764    cur_srate = srate(ind)
3765    cur_chans = chans(ind)
3766    cur_format = sample_type(ind)
3767    cur_type = header_type(ind)
3768    cur_loc = data_location(ind)
3769    cur_samps = framples(ind)
3770    set_srate(ind, cur_srate * 2)
3771    snd_test_neq(srate(ind), cur_srate * 2, "%s set_srate", file)
3772    set_framples(cur_samps * 2, ind)
3773    snd_test_neq(framples(ind), cur_samps * 2, "%s set_framples", file)
3774    set_chans(ind, cur_chans * 2) # this can change the index
3775    xind = find_sound(file)
3776    if ind != xind
3777      ind = xind
3778    end
3779    snd_test_neq(chans(ind), cur_chans * 2, "%s set_chans", file)
3780    set_data_location(ind, cur_loc * 2)
3781    snd_test_neq(data_location(ind), cur_loc * 2, "%s set_location", file)
3782    set_header_type(ind, Mus_nist)
3783    snd_test_neq(header_type(ind), Mus_nist, "%s set_header_type", file)
3784    set_sample_type(ind, Mus_lintn)
3785    snd_test_neq(sample_type(ind), Mus_lintn, "%s set_sample_type", file)
3786    set_srate(ind, cur_srate)
3787    set_framples(cur_samps, ind)
3788    set_channels(ind, cur_chans)
3789    set_data_location(ind, cur_loc)
3790    set_header_type(ind, cur_type)
3791    set_sample_type(ind, cur_format)
3792    close_sound(ind)
3793    delete_file(file)
3794  end unless $with_test_motif
3795end
3796
3797# XXX: with big file
3798#
3799# with_sound(:output, $bigger_snd, :srate, 44100, :play, false) do
3800#   72000.times do |i|
3801#     fm_violin_1(i, 0.1, 440, i / 72000.0 * 0.9 + 0.01)
3802#   end
3803# end
3804
3805$big_file_framples = 0
3806
3807def test_04_05
3808  if File.exist?($bigger_snd)
3809    # ; silence as last .9 secs, so it probably wasn't written
3810    probable_framples = (44100 * 71999.1).floor
3811    snd_test_neq(mus_sound_samples($bigger_snd), 3175160310, "bigger samples")
3812    snd_test_neq(mus_sound_framples($bigger_snd), 3175160310, "bigger framples")
3813    snd_test_neq(mus_sound_framples($bigger_snd), probable_framples,
3814                 "bigger framples (probable)")
3815    snd_test_neq(mus_sound_length($bigger_snd), 6350320648, "bigger length")
3816    snd_test_neq(mus_sound_duration($bigger_snd), 71999.1015, "bigger dur")
3817    ind = open_sound($bigger_snd)
3818    snd_test_neq(framples(ind), 3175160310, "bigger framples")
3819    $big_file_framples = framples(ind)
3820    snd_test_neq(framples(ind), probable_framples, "bigger framples (probable)")
3821    snd_test_neq(framples(ind, 0, 0), $big_file_framples, "bigger edpos-framples")
3822    m1 = add_mark(44100 * 50000, ind)
3823    snd_test_neq(mark_sample(m1), 44100 * 50000, "bigger mark at")
3824    set_mark_sample(m1, 44100 * 66000)
3825    snd_test_neq(mark_sample(m1), 44100 * 66000, "bigger mark to")
3826    if mix?(mx = mix_sound("oboe.snd", 44100 * 60000).car)
3827      snd_test_neq(mix_position(mx), 44100 * 60000, "bigger mix at")
3828      set_mix_position(mx, 44100 * 61000)
3829      snd_test_neq(mix_position(mx), 44100 * 61000, "bigger mix to")
3830      undo_edit(2)
3831    else
3832      snd_display("no mix tag from mix_sound: %s?", mx)
3833    end
3834    res = find_channel(lambda do |y| y != 0.0 end)
3835    if res.kind_of?(FalseClass) or res > 100
3836      snd_display("bigger find not 0.0: %s", res)
3837    end
3838    old_select = selection_creates_region
3839    set_selection_creates_region(false)
3840    select_all(ind)
3841    snd_test_neq(selection_framples(), framples(ind), "bigger select all")
3842    set_selection_position(44100 * 50000)
3843    snd_test_neq(selection_position(), 44100 * 50000, "bigger select pos")
3844    set_selection_position(0)
3845    set_selection_framples(44100 * 65000)
3846    snd_test_neq(selection_framples(), 44100 * 65000, "bigger select len")
3847    set_selection_creates_region(old_select)
3848    set_cursor(44100 * 50000, ind)
3849    snd_test_neq(cursor(ind), 44100 * 50000, "bigger cursor")
3850    m1 = add_mark(44123 * 51234, ind)
3851    snd_test_neq(mark_sample(m1), 44123 * 51234, "bigger mark at")
3852    mid = find_mark(44123 * 51234)
3853    snd_test_neq(mid, m1, "bigger find_mark")
3854    mx = mix_sound("oboe.snd", 44123 * 51234).car
3855    mxd = find_mix(44123 * 51234)
3856    snd_test_neq(mxd, mx, "bigger find_mix")
3857    set_cursor(44123 * 51234, ind)
3858    snd_test_neq(cursor(ind), 44123 * 51234, "bigger cursor 123")
3859    close_sound(ind)
3860  end
3861end
3862
3863def test_04_06
3864  ind = new_sound("tmp.snd", 1, 22050, Mus_l24int, Mus_riff, :size, 100000)
3865  old_selection_creates_region = selection_creates_region()
3866  set_selection_creates_region(true)
3867  x = -0.5
3868  incr = 1.0 / framples()
3869  map_channel(lambda do |n|
3870                val = x
3871                x += incr
3872                val
3873              end)
3874  save_sound(ind)
3875  close_sound(ind)
3876  ind = open_sound("tmp.snd")
3877  reg = select_all
3878  [[:Mus_next, :Mus_l24int],
3879   [:Mus_aifc, :Mus_l24int]].each do |ht, df|
3880    save_selection("tmp1.snd", 44100,
3881                   Module.const_get(df),
3882                   Module.const_get(ht))
3883    ind1 = open_sound("tmp1.snd")
3884    x = -0.5
3885    incr = 1.0 / framples()
3886    err = scan_channel(lambda do |n|
3887                         val = x
3888                         x += incr
3889                         fneq(val, n)
3890                       end, 0, 100000, ind1)
3891    if err
3892      snd_display("%s (%s) selection not saved correctly? %s", df, ht, err)
3893    end
3894    close_sound(ind1)
3895  end
3896  save_region(reg, "tmp1.snd", Mus_l24int, Mus_next)
3897  ind1 = open_sound("tmp1.snd")
3898  x = -0.5
3899  incr = 1.0 / framples()
3900  err = scan_channel(lambda do |n|
3901                       val = x
3902                       x += incr
3903                       fneq(val, n)
3904                     end, 0, 100000, ind1)
3905  if err
3906    snd_display("Mus_l24int (Mus_next) region not saved correctly? %s", err)
3907  end
3908  close_sound(ind1)
3909  delete_file("tmp1.snd")
3910  close_sound(ind)
3911  delete_file("tmp.snd")
3912  set_selection_creates_region(old_selection_creates_region)
3913  #
3914  ind = new_sound("tmp.snd", 1, 22050, Mus_bfloat, Mus_next,
3915                  :size, 10, :comment, false)
3916  map_channel($init_channel)
3917  env_channel([0.0, 0.0, 0.1, 0.1, 0.2, 0.2, 0.3, 0.3, 0.4, 0.4,
3918               0.5, 0.5, 0.6, 0.6, 0.7, 0.7, 0.8, 0.8, 0.9, 0.9])
3919  snd_test_neq(channel2vct(),
3920               vct(0.000, 0.100, 0.200, 0.300, 0.400,
3921                   0.500, 0.600, 0.700, 0.800, 0.900),
3922               "ramp env by 0.1")
3923  close_sound(ind)
3924end
3925
3926def test_04_07
3927  $open_raw_sound_hook.reset_hook!
3928  $open_raw_sound_hook.add_hook!(get_func_name) do |a, b| true end
3929  $bad_header_hook.reset_hook!
3930  $bad_header_hook.add_hook!(get_func_name) do |n| true end
3931  if $open_raw_sound_hook.empty?
3932    snd_display("$open_raw_sound_hook.add_hook! failed??")
3933  end
3934  if $bad_header_hook.empty?
3935    snd_display("$bad_header_hook.add_hook! failed??")
3936  end
3937  magic_words = [".snd", "FORM", "AIFF", "AIFC", "COMM", "COMT", "INFO", "INST", "inst", "MARK",
3938                 "SSND", "FVER", "NONE", "ULAW", "ulaw", "ima4", "raw ", "sowt", "in32", "in24",
3939                 "ni23", "fl32", "FL32", "fl64", "twos", "ALAW", "alaw", "APPL", "CLM ", "RIFF",
3940                 "RIFX", "WAVE", "fmt ", "data", "fact", "clm ", "NIST", "8SVX", "16SV", "Crea",
3941                 "tive", "SOUN", "D SA", "MPLE", "BODY", "VHDR", "CHAN", "ANNO", "NAME", "2BIT",
3942                 "HCOM", "FSSD", "%//\n", "%---", "ALaw", "Soun", "MAUD", "MHDR", "MDAT", "mdat",
3943                 "MThd", "sfbk", "sdta", "shdr", "pdta", "LIST", "GF1P", "ATCH", "$SIG", "NAL_",
3944                 "GOLD", " SAM", "SRFS", "Diam", "ondW", "CSRE", "SND ", "SNIN", "SNDT", "DDSF",
3945                 "FSMu", "UWFD", "LM89", "SY80", "SY85", "SCRS", "DSPL", "AVI ", "strf", "movi",
3946                 "PRAM", " paf", "fap ", "DS16", "HEDR", "HDR8", "SDA_", "SDAB", "SD_B", "NOTE",
3947                 "file", "=sam", "SU7M", "SU7R", "PVF1", "PVF2", "AUTH", "riff", "TWIN", "IMPS",
3948                 "SMP1", "Maui", "SDIF", "NVF "]
3949  len = magic_words.length
3950  magic_words.each_with_index do |magic, ctr|
3951    if $open_raw_sound_hook.empty?
3952      snd_display("$open_raw_sound_hook.add_hook! cleared??")
3953    end
3954    if $bad_header_hook.empty?
3955      snd_display("$bad_header_hook.add_hook! cleared??")
3956    end
3957    delete_file("test.snd")
3958    mus_sound_forget("test.snd")
3959    File.open("test.snd", "w") do |fp|
3960      fp.write(magic)
3961      128.times do
3962        fp.write(mus_random(1.0))
3963      end
3964    end
3965    res = Snd.catch do open_sound("test.snd") end.first
3966    if number?(res) and sound?(res)
3967      snd_display("open_sound garbage %s: %s?", magic, res)
3968      if sound?(res)
3969        close_sound(res)
3970      end
3971    end
3972    delete_file("test.snd")
3973    mus_sound_forget("test.snd")
3974    File.open("test.snd", "w") do |fp|
3975      fp.write(magic)
3976      128.times do
3977        fp.write(mus_random(128))
3978      end
3979    end
3980    res = Snd.catch do open_sound("test.snd") end.first
3981    if number?(res) and sound?(res)
3982      snd_display("open_sound plausible garbage %s: %s?", magic, res)
3983      if sound?(res)
3984        close_sound(res)
3985      end
3986    end
3987    delete_file("test.snd")
3988    mus_sound_forget("test.snd")
3989    File.open("test.snd", "w") do |fp|
3990      fp.write(magic)
3991      (1...12).each do |i|
3992        if (ctr + i) < len
3993          fp.write(magic_words[ctr + i])
3994        else
3995          fp.write(magic_words[i])
3996        end
3997      end
3998    end
3999    res = Snd.catch do open_sound("test.snd") end.first
4000    if number?(res) and sound?(res)
4001      snd_display("open_sound very plausible garbage %s: %s?", magic, res)
4002      if sound?(res)
4003        close_sound(res)
4004      end
4005    end
4006  end
4007  delete_file("test.snd")
4008  mus_sound_forget("test.snd")
4009end
4010
4011def make_aifc_file(framples, auth_lo, bits)
4012  File.open("test.aif", "w") do |fp|
4013    fp.write "FORM"
4014    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0146); # len
4015    fp.write "AIFCFVER"
4016    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0004); # version chunk size
4017    fp.putc(0242); fp.putc(0200); fp.putc(0121); fp.putc(0100); # version
4018    fp.write "COMM"
4019    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0046); # COMM chunk size
4020    fp.putc(0000); fp.putc(0001);                 # 1 chan
4021    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(framples); # framples
4022    fp.putc(0000); fp.putc(bits);                 # bits
4023    fp.putc(0100); fp.putc(0016); fp.putc(0254); fp.putc(0104); fp.putc(0000);
4024    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000);
4025    # srate as 80-bit float (sheesh)
4026    fp.write "NONE"                               # compression
4027    fp.putc(0016);                                # pascal string len
4028    fp.write "not compressed"
4029    fp.putc(0000);
4030    fp.write "AUTH"
4031    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(auth_lo); # AUTH chunk size
4032    fp.write "bil"
4033    fp.putc(0000);
4034    fp.write "SSND"
4035    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0014); # SSND chunk size
4036    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); # SSND data loc
4037    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); # block size?
4038    fp.putc(0000); fp.putc(0101); fp.putc(0000); fp.putc(0100); # two samples
4039  end
4040end
4041
4042undef read_ascii
4043def read_ascii(in_filename,
4044               out_filename = "test.snd",
4045               out_type = Mus_next,
4046               out_format = Mus_bshort,
4047               out_srate = 44100)
4048  in_buffer = IO.readlines(in_filename)         # array of strings
4049  out_snd = new_sound(out_filename, 1, out_srate, out_format, out_type,
4050                      format("created by %s: %s", get_func_name, in_filename))
4051  bufsize = 512
4052  data = make_vct(bufsize)
4053  loc = 0
4054  frame = 0
4055  short2float = 1.0 / 32768.0
4056  as_one_edit_rb do | |
4057    in_buffer.each do |line|
4058      line.split.each do |str_val|
4059        val = eval(str_val)
4060        data[loc] = val * short2float
4061        loc += 1
4062        if loc == bufsize
4063          vct2channel(data, frame, bufsize, out_snd, 0)
4064          frame += bufsize
4065          loc = 0
4066        end
4067      end
4068    end
4069    if loc > 0
4070      vct2channel(data, frame, loc, out_snd, 0)
4071    end
4072  end
4073  out_snd
4074end
4075
4076def test_04_08
4077  File.open("test.snd", "w") do |fp|
4078    fp.write ".snd"
4079    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0034); # location
4080    fp.putc(0000); fp.putc(0001); fp.putc(0215); fp.putc(0030); # nominal size
4081    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0022); # format
4082    fp.putc(0000); fp.putc(0000); fp.putc(0126); fp.putc(0042); # srate
4083    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0001); # chans
4084    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); # comment
4085    fp.putc(0000); fp.putc(0001); # samp 1
4086  end
4087  snd_test_neq(mus_sound_sample_type("test.snd"), Mus_bshort, "next 18")
4088  delete_file("test.snd")
4089  mus_sound_forget("test.snd")
4090  File.open("test.snd", "w") do |fp|
4091    fp.write ".snd"
4092    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0004); # location
4093    fp.putc(0000); fp.putc(0001); fp.putc(0215); fp.putc(0030); # nominal size
4094    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0022); # format
4095    fp.putc(0000); fp.putc(0000); fp.putc(0126); fp.putc(0042); # srate
4096    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0001); # chans
4097    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); # comment
4098    fp.putc(0000); fp.putc(0001); # samp 1
4099  end
4100  res = Snd.catch do open_sound("test.snd") end.first
4101  if number?(res) and sound?(res)
4102    snd_display("open_sound next bad location %s: %s?", data_location(res), res)
4103    close_sound(res)
4104  end
4105  delete_file("test.snd")
4106  mus_sound_forget("test.snd")
4107  File.open("test.snd", "w") do |fp|
4108    fp.write ".snd"
4109    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0034); # location
4110    fp.putc(0000); fp.putc(0001); fp.putc(0215); fp.putc(0030); # nominal size
4111    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0122); # format
4112    fp.putc(0000); fp.putc(0000); fp.putc(0126); fp.putc(0042); # srate
4113    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0001); # chans
4114    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); # comment
4115    fp.putc(0000); fp.putc(0001); # samp 1
4116  end
4117  res = Snd.catch do open_sound("test.snd") end.first
4118  if number?(res) and sound?(res)
4119    snd_display("open_sound next bad format %s: %s?", sample_type(res), res)
4120    close_sound(res)
4121  end
4122  delete_file("test.snd")
4123  mus_sound_forget("test.snd")
4124  delete_file("test.aif")
4125  mus_sound_forget("test.aif")
4126  #
4127  # ;;correct (make-aifc-file #o002 #o004 #o020)
4128  #
4129  make_aifc_file(0102, 004, 020)
4130  Snd.catch do
4131    ind = open_sound("test.aif")
4132    snd_test_neq(framples(ind), 2, "bad framples in header")
4133    close_sound(ind)
4134  end
4135  delete_file("test.aif")
4136  mus_sound_forget("test.aif")
4137  make_aifc_file(002, 150, 020)
4138  res = Snd.catch do open_sound("test.aif") end.first
4139  if number?(res) and sound?(res)
4140    snd_display("open_sound aifc no ssnd chunk %s: %s?",
4141                data_location(res), res)
4142    close_sound(res)
4143  end
4144  delete_file("test.aif")
4145  mus_sound_forget("test.aif")
4146  make_aifc_file(002, 000, 020)
4147  res = Snd.catch do open_sound("test.aif") end.first
4148  if number?(res) and sound?(res)
4149    snd_display("open_sound aifc 0-len auth chunk %s: %s?", data_location(res), res)
4150    close_sound(res)
4151  end
4152  delete_file("test.aif")
4153  mus_sound_forget("test.aif")
4154  make_aifc_file(002, 150, 120)
4155  res = Snd.catch do open_sound("test.aif") end.first
4156  if number?(res) and sound?(res)
4157    snd_display("open_sound aifc bits 80 %s: %s?", sample_type(res), res)
4158    close_sound(res)
4159  end
4160  delete_file("test.aif")
4161  mus_sound_forget("test.aif")
4162  File.open("test.aif", "w") do |fp|
4163    fp.write "FORM"
4164    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0176); # len
4165    fp.write "AIFCFVER"
4166    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0004); # version chunk size
4167    fp.putc(0242); fp.putc(0200); fp.putc(0121); fp.putc(0100); # version
4168    fp.write "COMM"
4169    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0046); # COMM chunk size
4170    fp.putc(0000); fp.putc(0001);                 # 1 chan
4171    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0002); # framples
4172    fp.putc(0000); fp.putc(0020);                 # bits
4173    fp.putc(0100); fp.putc(0016); fp.putc(0254); fp.putc(0104); fp.putc(0000);
4174    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000);
4175    # srate as 80-bit float (sheesh)
4176    fp.write "NONE"                               # compression
4177    fp.putc(0016);                                # pascal string len
4178    fp.write "not compressed"
4179    fp.putc(0000);
4180    fp.write "AUTH"
4181    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0004); # AUTH chunk size
4182    fp.write "bil"
4183    fp.putc(0000);
4184    fp.write "ANNO"
4185    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0004); # AUTH chunk size
4186    fp.write "cat"
4187    fp.putc(0000);
4188    fp.write "NAME"
4189    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0004); # AUTH chunk size
4190    fp.write "dog"
4191    fp.putc(0000);
4192    fp.write "SSND"
4193    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0004); # AUTH chunk size
4194
4195    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0014); # SSND chunk size
4196    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); # SSND data loc
4197    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); # block size?
4198    fp.putc(0000); fp.putc(0101); fp.putc(0000); fp.putc(0100); # two samples
4199  end
4200  Snd.catch do
4201    snd_test_neq(mus_sound_comment("test.aif").length, 15,
4202                 "aifc 3 aux comments")
4203  end
4204  delete_file("test.aif")
4205  mus_sound_forget("test.aif")
4206  File.open("test.aif", "w") do |fp|
4207    fp.write "FORM"
4208    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0142); # len
4209    fp.write "AIFC"
4210    fp.write "SSND"
4211    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0014); # SSND chunk size
4212    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); # SSND data location
4213    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); # block size?
4214    fp.putc(0000); fp.putc(0101); fp.putc(0000); fp.putc(0100); # two samples
4215    fp.write "COMM"
4216    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0046); # COMM chunk size
4217    fp.putc(0000); fp.putc(0001);                 # 1 chan
4218    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0002); # framples
4219    fp.putc(0000); fp.putc(0020);                 # bits
4220    fp.putc(0100); fp.putc(0016); fp.putc(0254); fp.putc(0104); fp.putc(0000);
4221    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000);
4222    # srate as 80-bit float (sheesh)
4223    fp.write "NONE"                               # compression
4224    fp.putc(0016);                                # pascal string len
4225    fp.write "not compressed"
4226    fp.putc(0000);
4227    fp.write "COMT"
4228    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0014);
4229    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000);
4230    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000);
4231    fp.write "bil"
4232    fp.putc(0000);
4233  end
4234  Snd.catch do
4235    snd_test_neq(mus_sound_comment("test.aif")[0..2], "bil",
4236                 "aifc trailing comt comments")
4237  end
4238  snd_test_neq(mus_sound_framples("test.aif"), 2, "aifc trailing comt framples")
4239  Snd.catch do
4240    ind = open_sound("test.aif")
4241    if fneq(sample(0), 0.00198) or
4242        fneq(sample(1), 0.00195) or
4243        fneq(sample(2), 0.0) or
4244        fneq(sample(3), 0.0)
4245      snd_display("aifc trailing comt samps: %s %s %s %s",
4246                  sample(0), sample(1), sample(2), sample(3))
4247    end
4248    close_sound(ind)
4249  end
4250  delete_file("test.aif")
4251  mus_sound_forget("test.aif")
4252  File.open("test.aif", "w") do |fp|
4253    fp.write "FORM"
4254    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0142); # len
4255    fp.write "AIFC"
4256    fp.write "SSND"
4257    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0014); # SSND chunk size
4258    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); # SSND data location
4259    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); # block size?
4260    fp.putc(0000); fp.putc(0101); fp.putc(0000); fp.putc(0100); # two samples
4261    fp.write "COMM"
4262    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0046); # COMM chunk size
4263    fp.putc(0000); fp.putc(0001);                 # 1 chan
4264    fp.putc(0000); fp.putc(0000); fp.putc(0100); fp.putc(0102); # framples
4265    fp.putc(0000); fp.putc(0020);                 # bits
4266    fp.putc(0100); fp.putc(0016); fp.putc(0254); fp.putc(0104); fp.putc(0000);
4267    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000);
4268    # srate as 80-bit float (sheesh)
4269    fp.write "NONE"                               # compression
4270    fp.putc(0016);                                # pascal string len
4271    fp.write "not compressed"
4272    fp.putc(0000);
4273    fp.write "COMT"
4274    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0014);
4275    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000);
4276    fp.putc(0000); fp.putc(0101); fp.putc(0000); fp.putc(0000);
4277    fp.write "bil"
4278    fp.putc(0000);
4279  end
4280  snd_test_neq(mus_sound_comment("test.aif")[0..2], "bil",
4281               "aifc trailing comt comment")
4282  snd_test_neq(mus_sound_framples("test.aif"), 2,
4283               "aifc trailing comt (bogus) framples")
4284  Snd.catch do
4285    ind = open_sound("test.aif")
4286    if fneq(sample(0), 0.00198) or
4287        fneq(sample(1), 0.00195) or
4288        fneq(sample(2), 0.0) or
4289        fneq(sample(3), 0.0)
4290      snd_display("aifc trailing comt samps (bogus frame setting): %s %s %s %s",
4291                  sample(0), sample(1), sample(2), sample(3))
4292    end
4293    close_sound(ind)
4294  end
4295  delete_file("test.aif")
4296  mus_sound_forget("test.aif")
4297  File.open("test.aif", "w") do |fp|
4298    fp.write "FORM"
4299    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0142); # len
4300    fp.write "AIFC"
4301    fp.write "SSND"
4302    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0014); # SSND chunk size
4303    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); # SSND data location
4304    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); # block size?
4305    fp.putc(0000); fp.putc(0101); fp.putc(0000); fp.putc(0100); # two samples
4306    fp.write "COMM"
4307    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0046); # COMM chunk size
4308    fp.putc(0000); fp.putc(0001);                 # 1 chan
4309    fp.putc(0000); fp.putc(0000); fp.putc(0100); fp.putc(0102); # framples
4310    fp.putc(0000); fp.putc(0020);                 # bits
4311    fp.putc(0100); fp.putc(0016); fp.putc(0254); fp.putc(0104); fp.putc(0000);
4312    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000);
4313    # srate as 80-bit float (sheesh)
4314    fp.write "NONE"                               # compression
4315    fp.putc(0016);                                # pascal string len
4316    fp.write "not compressed"
4317    fp.putc(0000);
4318    fp.write "SSND"
4319    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0014);
4320    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000);
4321    fp.putc(0000); fp.putc(0101); fp.putc(0000); fp.putc(0100);
4322  end
4323  res = Snd.catch do open_sound("test.aif") end.first
4324  if number?(res) and sound?(res)
4325    snd_display("open_sound aifc 2 ssnd chunks %s: %s?",
4326                data_location(res), res)
4327    close_sound(res)
4328  end
4329  delete_file("test.aif")
4330  mus_sound_forget("test.aif")
4331  File.open("test.aif", "w") do |fp|
4332    fp.write "FORM"
4333    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0040); # len
4334    fp.write "AIFC"
4335    fp.write "SSND"
4336    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0014); # SSND chunk size
4337    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); # SSND data location
4338    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); # block size?
4339    fp.putc(0000); fp.putc(0101); fp.putc(0000); fp.putc(0100); # two samples
4340  end
4341  res = Snd.catch do open_sound("test.aif") end.first
4342  if res != :mus_error
4343    snd_display("open_sound aifc no comm chunk: %s?", res)
4344    if number?(res) and sound?(res)
4345      close_sound(res)
4346    end
4347  end
4348  delete_file("test.aif")
4349  mus_sound_forget("test.aif")
4350  #
4351  File.open("test.aif", "w") do |fp|
4352    # write AIFC with trailing chunks to try to confuse file->sample
4353    fp.write "FORM"
4354    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0176); # len
4355    fp.write "AIFCFVER"
4356    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0004); # version chunk size
4357    fp.putc(0242); fp.putc(0200); fp.putc(0121); fp.putc(0100); # version
4358    fp.write "COMM"
4359    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0046); # COMM chunk size
4360    fp.putc(0000); fp.putc(0001);                 # 1 chan
4361    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0002); # framples
4362    fp.putc(0000); fp.putc(0020);                 # bits
4363    fp.putc(0100); fp.putc(0016); fp.putc(0254); fp.putc(0104); fp.putc(0000);
4364    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000);
4365    # srate as 80-bit float (sheesh)
4366    fp.write "NONE"                               # compression
4367    fp.putc(0016);                                # pascal string len
4368    fp.write "not compressed"
4369    fp.putc(0000);
4370    fp.write "SSND"
4371    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0014);
4372    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000);
4373    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000);
4374    fp.putc(0170); fp.putc(0101); fp.putc(0100); fp.putc(0100); # two samples
4375    fp.write "AUTH"
4376    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0004); # AUTH chunk size
4377    fp.write "bil"
4378    fp.putc(0000);
4379    fp.write "ANNO"
4380    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0004);
4381    fp.write "cat"
4382    fp.putc(0000);
4383    fp.write "NAME"
4384    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0004);
4385    fp.write "dog"
4386    fp.putc(0000);
4387  end
4388  Snd.catch do
4389    gen = make_file2sample("test.aif")
4390    snd_test_neq(gen.call(0), 0.93948, "file2sample chunked 0")
4391    snd_test_neq(gen.call(1), 0.50195, "file2sample chunked 1")
4392    snd_test_neq(gen.call(2), 0.00000, "file2sample chunked eof")
4393    snd_test_neq(gen.call(3), 0.00000, "file2sample chunked eof+1")
4394    res = open_sound("test.aif")
4395    snd_test_neq(framples(res), 2, "chunked framples")
4396    snd_test_neq(sample(0), 0.93948, "file chunked 0")
4397    snd_test_neq(sample(1), 0.50195, "file chunked 1")
4398    snd_test_neq(sample(2), 0.00000, "file chunked eof")
4399    snd_test_neq(sample(3), 0.00000, "file chunked eof+1")
4400    close_sound(res)
4401  end
4402  Snd.catch do
4403    snd_test_neq(mus_sound_framples("test.aif"), 2, "chunked mus_sound_framples")
4404  end
4405  delete_file("test.aif")
4406  mus_sound_forget("test.aif")
4407  #
4408  File.open("test.aif", "w") do |fp|
4409    # write AIFC with trailing chunks to try to confuse file->sample
4410    fp.write "FORM"
4411    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0176); # len
4412    fp.write "AIFCFVER"
4413    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0004); # version chunk size
4414    fp.putc(0242); fp.putc(0200); fp.putc(0121); fp.putc(0100); # version
4415    fp.write "SSND"
4416    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0014); # SSND chunk size
4417    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); # SSND data location
4418    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); # block size?
4419    fp.putc(0170); fp.putc(0101); fp.putc(0100); fp.putc(0100); # two samples
4420    fp.write "COMM"
4421    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0046); # COMM chunk size
4422    fp.putc(0000); fp.putc(0001);                 # 1 chan
4423    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0002); # framples
4424    fp.putc(0000); fp.putc(0020);                 # bits
4425    fp.putc(0100); fp.putc(0016); fp.putc(0254); fp.putc(0104); fp.putc(0000);
4426    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000);
4427    # srate as 80-bit float (sheesh)
4428    fp.write "NONE"                               # compression
4429    fp.putc(0016);                                # pascal string len
4430    fp.write "not compressed"
4431    fp.putc(0000);
4432    fp.write "APPL"
4433    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(key_to_int(?h));
4434    fp.write "CLM ;Written Mon 02-Nov-98 01:44 CST by root at ockeghem (Linux/X86) using Allegro CL, clm of 20-Oct-98"
4435    fp.putc(0000);
4436  end
4437  Snd.catch do
4438    gen = make_file2sample("test.aif")
4439    snd_test_neq(gen.call(0), 0.93948, "file2sample chunked 0")
4440    snd_test_neq(gen.call(1), 0.50195, "file2sample chunked 1")
4441    snd_test_neq(gen.call(2), 0.00000, "file2sample chunked eof")
4442    snd_test_neq(gen.call(3), 0.00000, "file2sample chunked eof+1")
4443    res = open_sound("test.aif")
4444    snd_test_neq(framples(res), 2, "chunked framples")
4445    snd_test_neq(sample(0), 0.93948, "file chunked 0")
4446    snd_test_neq(sample(1), 0.50195, "file chunked 1")
4447    snd_test_neq(sample(2), 0.00000, "file chunked eof")
4448    snd_test_neq(sample(3), 0.00000, "file chunked eof+1")
4449    snd_test_neq(comment(),
4450                 ";Written Mon 02-Nov-98 01:44 CST by root at ockeghem (Linux/X86) using Allegro CL, clm of 20-Oct-98",
4451                 "chunked appl comment")
4452    close_sound(res)
4453  end
4454  delete_file("test.aif")
4455  mus_sound_forget("test.aif")
4456  #
4457  File.open("test.aif", "w") do |fp|
4458    # write AIFC with trailing chunks to try to confuse file->sample
4459    fp.write "FORM"
4460    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0176); # len
4461    fp.write "AIFCFVER"
4462    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0004); # version chunk size
4463    fp.putc(0242); fp.putc(0200); fp.putc(0121); fp.putc(0100); # version
4464    fp.write "SSND"
4465    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0014); # SSND chunk size
4466    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); # SSND data location
4467    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); # block size?
4468    fp.putc(0170); fp.putc(0101); fp.putc(0100); fp.putc(0100); # two samples (onr frame)
4469    fp.write "COMM"
4470    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0046); # COMM chunk size
4471    fp.putc(0000); fp.putc(0002);                 # 2 chan
4472    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0001); # frame
4473    fp.putc(0000); fp.putc(0020);                 # bits
4474    fp.putc(0100); fp.putc(0016); fp.putc(0254); fp.putc(0104); fp.putc(0000);
4475    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(0000);
4476    # srate as 80-bit float (sheesh)
4477    fp.write "NONE"                               # compression
4478    fp.putc(0016);                                # pascal string len
4479    fp.write "not compressed"
4480    fp.putc(0000);
4481    fp.write "APPL"
4482    fp.putc(0000); fp.putc(0000); fp.putc(0000); fp.putc(key_to_int(?h));
4483    fp.write "CLM ;Written Mon 02-Nov-98 01:44 CST by root at ockeghem (Linux/X86) using Allegro CL, clm of 20-Oct-98"
4484    fp.putc(0000);
4485  end
4486  Snd.catch do
4487    gen = make_file2sample("test.aif")
4488    snd_test_neq(gen.call(0, 0), 0.93948, "file2sample chunked 0 0")
4489    snd_test_neq(gen.call(0, 1), 0.50195, "file2sample chunked 0 1")
4490    snd_test_neq(gen.call(1, 0), 0.00000, "file2sample chunked eof (stereo)")
4491    snd_test_neq(gen.call(1, 1), 0.00000, "file2sample chunked eof+1 (stereo)")
4492    res = open_sound("test.aif")
4493    snd_test_neq(framples(res), 1, "chunked framples (1)")
4494    snd_test_neq(sample(0, res, 0), 0.93948, "file chunked 0 0")
4495    snd_test_neq(sample(0, res, 1), 0.50195, "file chunked 0 1")
4496    snd_test_neq(sample(1, res, 0), 0.00000, "file chunked eof (stereo)")
4497    snd_test_neq(sample(1, res, 1), 0.00000, "file chunked eof+1 (stereo)")
4498    snd_test_neq(comment(),
4499                 ";Written Mon 02-Nov-98 01:44 CST by root at ockeghem (Linux/X86) using Allegro CL, clm of 20-Oct-98",
4500                 "chunked appl comment (stereo)")
4501    close_sound(res)
4502  end
4503  delete_file("test.aif")
4504  mus_sound_forget("test.aif")
4505  #
4506  files = sound_files_in_directory(Dir.pwd)
4507  if files.empty?
4508    snd_display("no sound files in %s?", Dir.pwd)
4509  end
4510  files1 = sound_files_in_directory()
4511  snd_test_neq(files1, files,
4512               "different sound files in %s and default?", Dir.pwd)
4513  files2 = sound_files_in_directory(".")
4514  if files1 != files2 or files != files2
4515    snd_display("sound_files_in_directory dot: %s but %s?:", files2, files)
4516  end
4517  $open_raw_sound_hook.reset_hook!
4518  $bad_header_hook.reset_hook!
4519  Snd.sounds.apply(:close_sound)
4520  #
4521  ind = new_sound(:size, 0)
4522  snd_test_neq(framples(ind), 0, "new_sound :size 0")
4523  snd_test_neq(sample(0), 0.0, "new_sound :size 0 sample 0")
4524  new_file_name = file_name(ind)
4525  close_sound(ind)
4526  delete_file(new_file_name)
4527  ind = new_sound(:size, 1)
4528  snd_test_neq(framples(ind), 1, "new_sound :size 1")
4529  snd_test_neq(sample(0), 0.0, "new_sound :size 1 sample 0")
4530  new_file_name = file_name(ind)
4531  close_sound(ind)
4532  delete_file(new_file_name)
4533  if (res = Snd.catch do new_sound(:size, -1) end).first != :out_of_range
4534    snd_display("new_sound :size -1: %s", res.inspect)
4535  end
4536  #
4537  with_file("caruso.asc") do |file|
4538    ind = read_ascii(file)
4539    unless sound?(ind)
4540      snd_display("read_ascii cannot find %s (%s)?", file, ind.inspect)
4541    end
4542    snd_test_neq(maxamp(ind, 0), 0.723, "read_ascii maxamp")
4543    snd_test_neq(framples(ind, 0), 50000, "read_ascii framples")
4544    snd_test_neq(srate(ind), 44100, "read_ascii srate")
4545    set_srate(ind, 8000)
4546    snd_test_neq(framples(ind, 0), 50000, "set srate clobbered new sound framples")
4547    snd_test_neq(maxamp(ind, 0), 0.723, "set srate clobbered new sound maxamp")
4548    close_sound(ind)
4549  end
4550  #
4551  ind = open_sound("oboe.snd")
4552  save_sound_as("test space.snd")
4553  close_sound(ind)
4554  ind = open_sound("test space.snd")
4555  snd_test_neq(short_file_name(ind), "test space.snd", "file name with space")
4556  snd_test_neq(mus_sound_framples("test space.snd"), framples(ind),
4557               "spaced filename framples")
4558  add_mark(1234, ind, 0)
4559  save_marks(ind)
4560  close_sound(ind)
4561  ind = open_sound("test space.snd")
4562  load("test space.marks")
4563  unless find_mark(1234, ind)
4564    snd_display("space file name save marks: %s", marks(ind).inspect)
4565  end
4566  rd = make_readin(:file, "test space.snd")
4567  snd_test_neq(mus_file_name(rd), "test space.snd",
4568               "file name with space readin")
4569  close_sound(ind)
4570  delete_files("test space.snd", "test space.marks")
4571end
4572
4573def test_04
4574  $tests.times do |i|
4575    $clmtest = i
4576    if $VERBOSE and $tests > 1
4577      snd_info("clmtest %d of %d", $clmtest + 1, $tests)
4578    end
4579    clear_listener()
4580    test_04_00
4581    test_04_01
4582    test_04_03
4583    test_04_04
4584    test_04_05 if $with_big_file
4585    test_04_06
4586  end
4587  test_04_07
4588  test_04_08
4589end
4590
4591# ---------------- test 05: simple overall checks ----------------
4592
4593def test_edpos(ind1, func_sym, func_body = nil, &change_thunk)
4594  unless func_body
4595    func_body = lambda do |snd, chn, val|
4596      snd_func(func_sym, snd, chn, val)
4597    end
4598  end
4599  fr1 = func_body.call(ind1, 0, false)
4600  fr2 = func_body.call(ind1, 0, 0)
4601  fr3 = func_body.call(ind1, 0, Current_edit_position)
4602  if fr1 != fr2 or fr1 != fr3
4603    snd_display_prev_caller("initial %s: %s %s %s?", func_sym, fr1, fr2, fr3)
4604  end
4605  change_thunk.call
4606  fr5 = func_body.call(ind1, 0, false)
4607  fr6 = func_body.call(ind1, 0, 1)
4608  fr7 = func_body.call(ind1, 0, Current_edit_position)
4609  if fr5 != fr6 or fr5 != fr7
4610    snd_display_prev_caller("%s (edpos 1): %s %s %s?", func_sym, fr5, fr6, fr7)
4611  end
4612  revert_sound(ind1)
4613end
4614
4615def test_edpos_1(func_sym, ind1, &body)
4616  v0 = channel2vct(12000, 10, ind1, 0)
4617  body.call(ind1, 0)
4618  v1 = channel2vct(12000, 10, ind1, 0)
4619  if vequal(v0, v1)
4620    s = snd_format(v1, v0, "==", "%s (0) no change!", func_sym)
4621    snd_display_prev_caller(s)
4622  end
4623  body.call(ind1, 0)
4624  v2 = channel2vct(12000, 10, ind1, 0)
4625  unless vequal(v1, v2)
4626    snd_display_prev_caller(snd_format(v2, v1, "!=", "%s (1)", func_sym))
4627  end
4628  revert_sound(ind1)
4629end
4630
4631def test_orig(func0, func1, name, ind1)
4632  v0 = channel2vct(12000, 10, ind1, 0)
4633  func0.call(ind1)
4634  v1 = channel2vct(12000, 10, ind1, 0)
4635  if vfequal(v0, v1)
4636    snd_display_prev_caller(snd_format(v1, v0, "==",
4637                                       "%s (orig 0) no change!", name))
4638  end
4639  func1.call(ind1)
4640  v2 = channel2vct(12000, 10, ind1, 0)
4641  unless vfequal(v0, v2)
4642    snd_display_prev_caller(snd_format(v2, v0, "!=", "%s (orig 1)", name))
4643  end
4644  revert_sound(ind1)
4645end
4646
4647def make_bandpass_2(flo1, fhi1, flo2, fhi2, len = 30)
4648  f1 = make_bandpass(flo1, fhi1, len)
4649  f2 = make_bandpass(flo2, fhi2, len)
4650  vct_add!(mus_xcoeffs(f1), mus_xcoeffs(f2))
4651  f1
4652end
4653
4654def bandpass_2(f, input)
4655  fir_filter(f, input)
4656end
4657
4658def check_maxamp(ind, val, name)
4659  if fneq(maxamp(ind, 0), val)
4660    snd_display_prev_caller("maxamp amp_env %s: %s should be %s",
4661                            name, maxamp(ind), val)
4662  end
4663  pos = find_channel(lambda do |y| y.abs >= (val - 0.0001) end)
4664  unless pos
4665    snd_display_prev_caller("actual maxamp %s vals not right", name)
4666  end
4667  maxpos = maxamp_position(ind, 0)
4668  if maxpos != pos
4669    snd_display_prev_caller("%s: \
4670find and maxamp_position disagree: %s (%s) %s (%s)?",
4671      name, pos, sample(pos, ind, 0), maxpos, sample(maxpos, ind, 0))
4672  end
4673  reader = make_sampler(0, ind, 0)
4674  data = Vct.new(framples(ind, 0)) do |i|
4675    next_sample(reader)
4676  end
4677  mx, mpos = vct_peak_and_location(data)
4678  if mpos != maxpos
4679    snd_display_prev_caller("%s: scan and maxamp_position disagree: %s %s?",
4680      name, mpos, maxpos)
4681  end
4682  if fneq(mx, val)
4683    snd_display_prev_caller("actual %s max: %s (correct: %s)", name, mx, val)
4684  end
4685end
4686
4687def check_env_vals(name, gen)
4688  reader = make_sampler()
4689  framples().times do |i|
4690    val = env(gen)
4691    y = next_sample(reader)
4692    if fneq(val, y)
4693      snd_display_prev_caller(snd_format_neq(val, y,
4694        "%s %s at %d", get_func_name, name, i))
4695      return
4696    end
4697  end
4698end
4699
4700def our_x2position(ind, x)
4701  ax = axis_info(ind, 0)
4702  [ax[10].to_f + ((x - ax[2]) * (ax[12].to_f - ax[10])) / (ax[4] - ax[2]),
4703    x2position(x, ind)]
4704end
4705
4706def region2vct_1(reg, chn, len)
4707  region2vct(reg, 0, len, chn)
4708end
4709
4710def region_to_vct(reg, chn, len)
4711  rs = make_region_sampler(reg, 0, chn)
4712  make_vct!(len) do next_sample(rs) end
4713end
4714
4715# basic edit tree cases
4716def test_05_00
4717  if playing
4718    snd_display("dac is running?")
4719  end
4720  ind = open_sound("oboe.snd")
4721  set_transform_graph?(true, ind, 0)
4722  set_transform_graph_type(Graph_as_sonogram, ind, 0)
4723  set_y_axis_label("hiho", ind, 0)
4724  set_fft_log_frequency(true, ind, 0)
4725  update_transform_graph(ind, 0)
4726  close_sound(ind)
4727  #
4728  ind = new_sound("test.snd")
4729  if redo_edit.nonzero?
4730    snd_display("redo_edit with no ops: %s?", redo_edit)
4731  end
4732  if undo_edit.nonzero?
4733    snd_display("undo_edit with no ops: %s?", undo_edit)
4734  end
4735  str = format("
4736EDITS: 0
4737
4738 (begin) [0:2]:
4739   (at 0, cp->sounds[0][0:0, 0.000]) [file: %s/test.snd[0]]
4740   (at 1, end_mark)
4741", Dir.pwd)
4742  if (res = safe_display_edits) != str
4743    snd_display("new 0: %s %s?", str, res)
4744  end
4745  insert_samples(10, 10, make_vct(10))
4746  str = format("
4747EDITS: 1
4748
4749 (begin) [0:2]:
4750   (at 0, cp->sounds[0][0:0, 0.000]) [file: %s/test.snd[0]]
4751   (at 1, end_mark)
4752
4753 (insert 1 20) ; insert_samples [1:4]:
4754   (at 0, cp->sounds[0][0:0, 0.000]) [file: %s/test.snd[0]]
4755   (at 1, cp->sounds[-1][0:8, 0.000])
4756   (at 10, cp->sounds[1][0:9, 1.000]) [buf: 10]
4757   (at 20, end_mark)
4758", Dir.pwd, Dir.pwd)
4759  if (res = safe_display_edits) != str
4760    snd_display("new 1: %s %s?", str, res)
4761  end
4762  undo_edit
4763  insert_samples(0, 10, make_vct(10))
4764  str = format("
4765EDITS: 1
4766
4767 (begin) [0:2]:
4768   (at 0, cp->sounds[0][0:0, 0.000]) [file: %s/test.snd[0]]
4769   (at 1, end_mark)
4770
4771 (insert 0 10) ; insert_samples [1:3]:
4772   (at 0, cp->sounds[1][0:9, 1.000]) [buf: 10]
4773   (at 10, cp->sounds[0][0:0, 0.000]) [file: %s/test.snd[0]]
4774   (at 11, end_mark)
4775", Dir.pwd, Dir.pwd)
4776  if (res = safe_display_edits) != str
4777    snd_display("new 2: %s %s?", str, res)
4778  end
4779  undo_edit(2)
4780  insert_samples(0, 10, make_vct(10))
4781  str = format("
4782EDITS: 1
4783
4784 (begin) [0:2]:
4785   (at 0, cp->sounds[0][0:0, 0.000]) [file: %s/test.snd[0]]
4786   (at 1, end_mark)
4787
4788 (insert 0 10) ; insert_samples [1:3]:
4789   (at 0, cp->sounds[1][0:9, 1.000]) [buf: 10]
4790   (at 10, cp->sounds[0][0:0, 0.000]) [file: %s/test.snd[0]]
4791   (at 11, end_mark)
4792", Dir.pwd, Dir.pwd)
4793  if (res = safe_display_edits) != str
4794    snd_display("new 3: %s %s?", str, res)
4795  end
4796  undo_edit
4797  set_sample(0, 0.5)
4798  str = format("
4799EDITS: 1
4800
4801 (begin) [0:2]:
4802   (at 0, cp->sounds[0][0:0, 0.000]) [file: %s/test.snd[0]]
4803   (at 1, end_mark)
4804
4805 (set 0 1) ; set_sample(0, 0.5000 [1:2]:
4806   (at 0, cp->sounds[1][0:0, 1.000]) [buf: 1]
4807   (at 1, end_mark)
4808", Dir.pwd)
4809  if (res = safe_display_edits) != str
4810    snd_display("new 4: %s %s?", str, res)
4811  end
4812  undo_edit
4813  set_samples(0, 10, make_vct(10))
4814  str = format("
4815EDITS: 1
4816
4817 (begin) [0:2]:
4818   (at 0, cp->sounds[0][0:0, 0.000]) [file: %s/test.snd[0]]
4819   (at 1, end_mark)
4820
4821 (set 0 10) ; set-samples [1:2]:
4822   (at 0, cp->sounds[1][0:9, 1.000]) [buf: 10]
4823   (at 10, end_mark)
4824", Dir.pwd)
4825  if (res = safe_display_edits) != str
4826    snd_display("new 5: %s %s?", str, res)
4827  end
4828  idx = 1
4829  test_idx = 5
4830  test_output = lambda do |str|
4831    idx += 1
4832    test_idx += 1
4833    if (res = safe_display_edits(ind, 0, idx)) != str
4834      snd_display("new %s: %s %s?", test_idx, str, res)
4835    end
4836  end
4837  delete_samples(3, 4)
4838  test_output.call("
4839 (delete 3 4) ; delete_samples(3, 4 [2:3]:
4840   (at 0, cp->sounds[1][0:2, 1.000]) [buf: 10]
4841   (at 3, cp->sounds[1][7:9, 1.000]) [buf: 10]
4842   (at 6, end_mark)
4843")
4844  set_samples(1, 4, make_vct(4))
4845  test_output.call("
4846 (set 1 4) ; set-samples [3:4]:
4847   (at 0, cp->sounds[1][0:0, 1.000]) [buf: 10]
4848   (at 1, cp->sounds[2][0:3, 1.000]) [buf: 4]
4849   (at 5, cp->sounds[1][9:9, 1.000]) [buf: 10]
4850   (at 6, end_mark)
4851")
4852  undo_edit(2)
4853  insert_samples(2, 3, make_vct(3))
4854  insert_samples(2, 1, make_vct(1))
4855  insert_samples(4, 1, make_vct(1))
4856  insert_samples(15, 1, make_vct(1))
4857  str = format("
4858EDITS: 5
4859
4860 (begin) [0:2]:
4861   (at 0, cp->sounds[0][0:0, 0.000]) [file: %s/test.snd[0]]
4862   (at 1, end_mark)
4863
4864 (set 0 10) ; set-samples [1:2]:
4865   (at 0, cp->sounds[1][0:9, 1.000]) [buf: 10]
4866   (at 10, end_mark)
4867
4868 (insert 2 3) ; insert_samples [2:4]:
4869   (at 0, cp->sounds[1][0:1, 1.000]) [buf: 10]
4870   (at 2, cp->sounds[2][0:2, 1.000]) [buf: 3]
4871   (at 5, cp->sounds[1][2:9, 1.000]) [buf: 10]
4872   (at 13, end_mark)
4873
4874 (insert 2 1) ; insert_samples [3:5]:
4875   (at 0, cp->sounds[1][0:1, 1.000]) [buf: 10]
4876   (at 2, cp->sounds[3][0:0, 1.000]) [buf: 1]
4877   (at 3, cp->sounds[2][0:2, 1.000]) [buf: 3]
4878   (at 6, cp->sounds[1][2:9, 1.000]) [buf: 10]
4879   (at 14, end_mark)
4880
4881 (insert 4 1) ; insert_samples [4:7]:
4882   (at 0, cp->sounds[1][0:1, 1.000]) [buf: 10]
4883   (at 2, cp->sounds[3][0:0, 1.000]) [buf: 1]
4884   (at 3, cp->sounds[2][0:0, 1.000]) [buf: 3]
4885   (at 4, cp->sounds[4][0:0, 1.000]) [buf: 1]
4886   (at 5, cp->sounds[2][1:2, 1.000]) [buf: 3]
4887   (at 7, cp->sounds[1][2:9, 1.000]) [buf: 10]
4888   (at 15, end_mark)
4889
4890 (insert 15 1) ; insert_samples [5:8]:
4891   (at 0, cp->sounds[1][0:1, 1.000]) [buf: 10]
4892   (at 2, cp->sounds[3][0:0, 1.000]) [buf: 1]
4893   (at 3, cp->sounds[2][0:0, 1.000]) [buf: 3]
4894   (at 4, cp->sounds[4][0:0, 1.000]) [buf: 1]
4895   (at 5, cp->sounds[2][1:2, 1.000]) [buf: 3]
4896   (at 7, cp->sounds[1][2:9, 1.000]) [buf: 10]
4897   (at 15, cp->sounds[5][0:0, 1.000]) [buf: 1]
4898   (at 16, end_mark)
4899", Dir.pwd)
4900  test_idx += 1
4901  idx += 2
4902  if (res = safe_display_edits) != str
4903    snd_display("new 8: %s?", res)
4904  end
4905  delete_samples(2, 1)
4906  test_output.call("
4907 (delete 2 1) ; delete_samples(2, 1 [6:7]:
4908   (at 0, cp->sounds[1][0:1, 1.000]) [buf: 10]
4909   (at 2, cp->sounds[2][0:0, 1.000]) [buf: 3]
4910   (at 3, cp->sounds[4][0:0, 1.000]) [buf: 1]
4911   (at 4, cp->sounds[2][1:2, 1.000]) [buf: 3]
4912   (at 6, cp->sounds[1][2:9, 1.000]) [buf: 10]
4913   (at 14, cp->sounds[5][0:0, 1.000]) [buf: 1]
4914   (at 15, end_mark)
4915")
4916  delete_samples(0, 5)
4917  test_output.call("
4918 (delete 0 5) ; delete_samples(0, 5 [7:4]:
4919   (at 0, cp->sounds[2][2:2, 1.000]) [buf: 3]
4920   (at 1, cp->sounds[1][2:9, 1.000]) [buf: 10]
4921   (at 9, cp->sounds[5][0:0, 1.000]) [buf: 1]
4922   (at 10, end_mark)
4923")
4924  delete_samples(6, 4)
4925  test_output.call("
4926 (delete 6 4) ; delete_samples(6, 4 [8:3]:
4927   (at 0, cp->sounds[2][2:2, 1.000]) [buf: 3]
4928   (at 1, cp->sounds[1][2:6, 1.000]) [buf: 10]
4929   (at 6, end_mark)
4930")
4931  delete_samples(0, 1)
4932  test_output.call("
4933 (delete 0 1) ; delete_samples(0, 1 [9:2]:
4934   (at 0, cp->sounds[1][2:6, 1.000]) [buf: 10]
4935   (at 5, end_mark)
4936")
4937  delete_samples(0, 5)
4938  test_output.call("
4939 (delete 0 5) ; delete_samples(0, 5 [10:1]:
4940   (at 0, end_mark)
4941")
4942  delete_samples(0, 10)
4943  unless edit_position == 10
4944    snd_display("no-op delete deleted something! %s", safe_display_edits)
4945  end
4946  insert_samples(0, 3, make_vct(3))
4947  test_output.call("
4948 (insert 0 3) ; insert_samples [11:2]:
4949   (at 0, cp->sounds[6][0:2, 1.000]) [buf: 3]
4950   (at 3, end_mark)
4951")
4952  delete_samples(2, 1)
4953  test_output.call("
4954 (delete 2 1) ; delete_samples(2, 1 [12:2]:
4955   (at 0, cp->sounds[6][0:1, 1.000]) [buf: 3]
4956   (at 2, end_mark)
4957")
4958  set_sample(0, 0.5)
4959  test_output.call("
4960 (set 0 1) ; set_sample(0, 0.5000 [13:3]:
4961   (at 0, cp->sounds[7][0:0, 1.000]) [buf: 1]
4962   (at 1, cp->sounds[6][1:1, 1.000]) [buf: 3]
4963   (at 2, end_mark)
4964")
4965  set_sample(1, 0.5)
4966  test_output.call("
4967 (set 1 1) ; set_sample(1, 0.5000 [14:3]:
4968   (at 0, cp->sounds[7][0:0, 1.000]) [buf: 1]
4969   (at 1, cp->sounds[8][0:0, 1.000]) [buf: 1]
4970   (at 2, end_mark)
4971")
4972  map_channel($init_channel, 0, 10)
4973  test_output.call("
4974 (set 0 10) ; map-channel [15:2]:
4975   (at 0, cp->sounds[9][0:9, 1.000]) [buf: 10]
4976   (at 10, end_mark)
4977")
4978  insert_samples(0, 10, make_vct(10))
4979  test_output.call("
4980 (insert 0 10) ; insert_samples [16:3]:
4981   (at 0, cp->sounds[10][0:9, 1.000]) [buf: 10]
4982   (at 10, cp->sounds[9][0:9, 1.000]) [buf: 10]
4983   (at 20, end_mark)
4984")
4985  set_samples(2, 3, make_vct(3))
4986  test_output.call("
4987 (set 2 3) ; set-samples [17:5]:
4988   (at 0, cp->sounds[10][0:1, 1.000]) [buf: 10]
4989   (at 2, cp->sounds[11][0:2, 1.000]) [buf: 3]
4990   (at 5, cp->sounds[10][5:9, 1.000]) [buf: 10]
4991   (at 10, cp->sounds[9][0:9, 1.000]) [buf: 10]
4992   (at 20, end_mark)
4993")
4994  set_samples(0, 12, make_vct(12))
4995  test_output.call("
4996 (set 0 12) ; set-samples [18:3]:
4997   (at 0, cp->sounds[12][0:11, 1.000]) [buf: 12]
4998   (at 12, cp->sounds[9][2:9, 1.000]) [buf: 10]
4999   (at 20, end_mark)
5000")
5001  set_samples(30, 10, make_vct(10))
5002  test_output.call("
5003 (set 20 21) ; set-samples [19:5]:
5004   (at 0, cp->sounds[12][0:11, 1.000]) [buf: 12]
5005   (at 12, cp->sounds[9][2:9, 1.000]) [buf: 10]
5006   (at 20, cp->sounds[-1][0:9, 0.000])
5007   (at 30, cp->sounds[13][0:9, 1.000]) [buf: 10]
5008   (at 40, end_mark)
5009")
5010  close_sound(ind)
5011end
5012
5013# scale/ramp
5014def test_05_01
5015  ind = new_sound("test.snd")
5016  idx = -1
5017  test_name = "scl"
5018  test_output = lambda do |ed, str|
5019    idx += 1
5020    if (res = safe_display_edits(ind, 0, ed)) != str
5021      snd_display("%s %s: %s %s?", test_name, idx, str, res)
5022    end
5023  end
5024  map_channel($init_channel, 0, 10)
5025  scale_channel(0.5)
5026  test_output.call(2, "
5027 (scale 0 10) ; scale_channel(0.500, 0, false [2:2]:
5028   (at 0, cp->sounds[1][0:9, 0.500]) [buf: 10]
5029   (at 10, end_mark)
5030")
5031  undo_edit
5032  scale_channel(0.5, 0, 3)
5033  test_output.call(2, "
5034 (scale 0 3) ; scale_channel(0.500, 0, 3 [2:3]:
5035   (at 0, cp->sounds[1][0:2, 0.500]) [buf: 10]
5036   (at 3, cp->sounds[1][3:9, 1.000]) [buf: 10]
5037   (at 10, end_mark)
5038")
5039  undo_edit
5040  scale_channel(0.5, 5, 5)
5041  test_output.call(2, "
5042 (scale 5 5) ; scale_channel(0.500, 5, 5 [2:3]:
5043   (at 0, cp->sounds[1][0:4, 1.000]) [buf: 10]
5044   (at 5, cp->sounds[1][5:9, 0.500]) [buf: 10]
5045   (at 10, end_mark)
5046")
5047  undo_edit
5048  scale_channel(0.5, 2, 4)
5049  test_output.call(2, "
5050 (scale 2 4) ; scale_channel(0.500, 2, 4 [2:4]:
5051   (at 0, cp->sounds[1][0:1, 1.000]) [buf: 10]
5052   (at 2, cp->sounds[1][2:5, 0.500]) [buf: 10]
5053   (at 6, cp->sounds[1][6:9, 1.000]) [buf: 10]
5054   (at 10, end_mark)
5055")
5056  undo_edit
5057  scale_channel(0.5, 10, 10)
5058  unless edit_position == 1
5059    snd_display("scale beyond end edited? %s", safe_display_edits)
5060  end
5061  scale_channel(0.5, 100, 10)
5062  unless edit_position == 1
5063    snd_display("scale way beyond end edited? %s", safe_display_edits)
5064  end
5065  scale_channel(0.5, 5, 10)
5066  test_output.call(2, "
5067 (scale 5 5) ; scale_channel(0.500, 5, 5 [2:3]:
5068   (at 0, cp->sounds[1][0:4, 1.000]) [buf: 10]
5069   (at 5, cp->sounds[1][5:9, 0.500]) [buf: 10]
5070   (at 10, end_mark)
5071")
5072  undo_edit
5073  set_sample(4, 0.5)
5074  test_output.call(2, "
5075 (set 4 1) ; set_sample(4, 0.5000 [2:4]:
5076   (at 0, cp->sounds[1][0:3, 1.000]) [buf: 10]
5077   (at 4, cp->sounds[2][0:0, 1.000]) [buf: 1]
5078   (at 5, cp->sounds[1][5:9, 1.000]) [buf: 10]
5079   (at 10, end_mark)
5080")
5081  scale_channel(0.5, 0, 4)
5082  test_output.call(3, "
5083 (scale 0 4) ; scale_channel(0.500, 0, 4 [3:4]:
5084   (at 0, cp->sounds[1][0:3, 0.500]) [buf: 10]
5085   (at 4, cp->sounds[2][0:0, 1.000]) [buf: 1]
5086   (at 5, cp->sounds[1][5:9, 1.000]) [buf: 10]
5087   (at 10, end_mark)
5088")
5089  scale_channel(0.5, 4, 1)
5090  test_output.call(4, "
5091 (scale 4 1) ; scale_channel(0.500, 4, 1 [4:4]:
5092   (at 0, cp->sounds[1][0:3, 0.500]) [buf: 10]
5093   (at 4, cp->sounds[2][0:0, 0.500]) [buf: 1]
5094   (at 5, cp->sounds[1][5:9, 1.000]) [buf: 10]
5095   (at 10, end_mark)
5096")
5097  scale_channel(0.5, 0, 7)
5098  test_output.call(5, "
5099 (scale 0 7) ; scale_channel(0.500, 0, 7 [5:5]:
5100   (at 0, cp->sounds[1][0:3, 0.250]) [buf: 10]
5101   (at 4, cp->sounds[2][0:0, 0.250]) [buf: 1]
5102   (at 5, cp->sounds[1][5:6, 0.500]) [buf: 10]
5103   (at 7, cp->sounds[1][7:9, 1.000]) [buf: 10]
5104   (at 10, end_mark)
5105")
5106  scale_channel(0.5, 1, 4)
5107  test_output.call(6, "
5108 (scale 1 4) ; scale_channel(0.500, 1, 4 [6:6]:
5109   (at 0, cp->sounds[1][0:0, 0.250]) [buf: 10]
5110   (at 1, cp->sounds[1][1:3, 0.125]) [buf: 10]
5111   (at 4, cp->sounds[2][0:0, 0.125]) [buf: 1]
5112   (at 5, cp->sounds[1][5:6, 0.500]) [buf: 10]
5113   (at 7, cp->sounds[1][7:9, 1.000]) [buf: 10]
5114   (at 10, end_mark)
5115")
5116  undo_edit(4)
5117  scale_channel(0.5, 1, 8)
5118  test_output.call(3, "
5119 (scale 1 8) ; scale_channel(0.500, 1, 8 [3:6]:
5120   (at 0, cp->sounds[1][0:0, 1.000]) [buf: 10]
5121   (at 1, cp->sounds[1][1:3, 0.500]) [buf: 10]
5122   (at 4, cp->sounds[2][0:0, 0.500]) [buf: 1]
5123   (at 5, cp->sounds[1][5:8, 0.500]) [buf: 10]
5124   (at 9, cp->sounds[1][9:9, 1.000]) [buf: 10]
5125   (at 10, end_mark)
5126")
5127  undo_edit(2)
5128  idx = -1
5129  test_name = "ramp"
5130  ramp_channel(0.0, 1.0)
5131  test_output.call(2, "
5132 (ramp 0 10) ; ramp_channel(0.000, 1.000, 0, false [2:2]:
5133   (at 0, cp->sounds[1][0:9, 1.000, [1]0.000 -> 1.000]) [buf: 10]
5134   (at 10, end_mark)
5135")
5136  scale_channel(0.5)
5137  test_output.call(3, "
5138 (scale 0 10) ; scale_channel(0.500, 0, false [3:2]:
5139   (at 0, cp->sounds[1][0:9, 0.500, [1]0.000 -> 1.000]) [buf: 10]
5140   (at 10, end_mark)
5141")
5142  undo_edit
5143  scale_channel(0.5, 0, 5)
5144  test_output.call(3, "
5145 (scale 0 5) ; scale_channel(0.500, 0, 5 [3:3]:
5146   (at 0, cp->sounds[1][0:4, 0.500, [1]0.000 -> 0.444]) [buf: 10]
5147   (at 5, cp->sounds[1][5:9, 1.000, [1]0.556 -> 1.000]) [buf: 10]
5148   (at 10, end_mark)
5149")
5150  undo_edit
5151  scale_channel(0.5, 2, 4)
5152  test_output.call(3, "
5153 (scale 2 4) ; scale_channel(0.500, 2, 4 [3:4]:
5154   (at 0, cp->sounds[1][0:1, 1.000, [1]0.000 -> 0.111]) [buf: 10]
5155   (at 2, cp->sounds[1][2:5, 0.500, [1]0.222 -> 0.556]) [buf: 10]
5156   (at 6, cp->sounds[1][6:9, 1.000, [1]0.667 -> 1.000]) [buf: 10]
5157   (at 10, end_mark)
5158")
5159  undo_edit
5160  scale_channel(0.5, 5, 5)
5161  test_output.call(3, "
5162 (scale 5 5) ; scale_channel(0.500, 5, 5 [3:3]:
5163   (at 0, cp->sounds[1][0:4, 1.000, [1]0.000 -> 0.444]) [buf: 10]
5164   (at 5, cp->sounds[1][5:9, 0.500, [1]0.556 -> 1.000]) [buf: 10]
5165   (at 10, end_mark)
5166")
5167  undo_edit(2)
5168  ramp_channel(0.2, 0.6, 2, 6)
5169  test_output.call(2, "
5170 (ramp 2 6) ; ramp_channel(0.200, 0.600, 2, 6 [2:4]:
5171   (at 0, cp->sounds[1][0:1, 1.000]) [buf: 10]
5172   (at 2, cp->sounds[1][2:7, 1.000, [1]0.200 -> 0.600]) [buf: 10]
5173   (at 8, cp->sounds[1][8:9, 1.000]) [buf: 10]
5174   (at 10, end_mark)
5175")
5176  scale_channel(0.5, 0, 5)
5177  test_output.call(3, "
5178 (scale 0 5) ; scale_channel(0.500, 0, 5 [3:5]:
5179   (at 0, cp->sounds[1][0:1, 0.500]) [buf: 10]
5180   (at 2, cp->sounds[1][2:4, 0.500, [1]0.200 -> 0.360]) [buf: 10]
5181   (at 5, cp->sounds[1][5:7, 1.000, [1]0.440 -> 0.600]) [buf: 10]
5182   (at 8, cp->sounds[1][8:9, 1.000]) [buf: 10]
5183   (at 10, end_mark)
5184")
5185  undo_edit
5186  scale_channel(0.5, 2, 6)
5187  test_output.call(3, "
5188 (scale 2 6) ; scale_channel(0.500, 2, 6 [3:4]:
5189   (at 0, cp->sounds[1][0:1, 1.000]) [buf: 10]
5190   (at 2, cp->sounds[1][2:7, 0.500, [1]0.200 -> 0.600]) [buf: 10]
5191   (at 8, cp->sounds[1][8:9, 1.000]) [buf: 10]
5192   (at 10, end_mark)
5193")
5194  undo_edit
5195  scale_channel(0.5, 5, 4)
5196  test_output.call(3, "
5197 (scale 5 4) ; scale_channel(0.500, 5, 4 [3:6]:
5198   (at 0, cp->sounds[1][0:1, 1.000]) [buf: 10]
5199   (at 2, cp->sounds[1][2:4, 1.000, [1]0.200 -> 0.360]) [buf: 10]
5200   (at 5, cp->sounds[1][5:7, 0.500, [1]0.440 -> 0.600]) [buf: 10]
5201   (at 8, cp->sounds[1][8:8, 0.500]) [buf: 10]
5202   (at 9, cp->sounds[1][9:9, 1.000]) [buf: 10]
5203   (at 10, end_mark)
5204")
5205  undo_edit
5206  set_sample(4, 0.5)
5207  test_output.call(3, "
5208 (set 4 1) ; set_sample(4, 0.5000 [3:6]:
5209   (at 0, cp->sounds[1][0:1, 1.000]) [buf: 10]
5210   (at 2, cp->sounds[1][2:3, 1.000, [1]0.200 -> 0.280]) [buf: 10]
5211   (at 4, cp->sounds[2][0:0, 1.000]) [buf: 1]
5212   (at 5, cp->sounds[1][5:7, 1.000, [1]0.440 -> 0.600]) [buf: 10]
5213   (at 8, cp->sounds[1][8:9, 1.000]) [buf: 10]
5214   (at 10, end_mark)
5215")
5216  undo_edit
5217  scale_channel(0.5, 4, 1)
5218  test_output.call(3, "
5219 (scale 4 1) ; scale_channel(0.500, 4, 1 [3:6]:
5220   (at 0, cp->sounds[1][0:1, 1.000]) [buf: 10]
5221   (at 2, cp->sounds[1][2:3, 1.000, [1]0.200 -> 0.280]) [buf: 10]
5222   (at 4, cp->sounds[1][4:4, 0.500, [1]0.360 -> 0.360]) [buf: 10]
5223   (at 5, cp->sounds[1][5:7, 1.000, [1]0.440 -> 0.600]) [buf: 10]
5224   (at 8, cp->sounds[1][8:9, 1.000]) [buf: 10]
5225   (at 10, end_mark)
5226")
5227  undo_edit
5228  delete_sample(4)
5229  test_output.call(3, "
5230 (delete 4 1) ; delete_samples(4, 1 [3:5]:
5231   (at 0, cp->sounds[1][0:1, 1.000]) [buf: 10]
5232   (at 2, cp->sounds[1][2:3, 1.000, [1]0.200 -> 0.280]) [buf: 10]
5233   (at 4, cp->sounds[1][5:7, 1.000, [1]0.440 -> 0.600]) [buf: 10]
5234   (at 7, cp->sounds[1][8:9, 1.000]) [buf: 10]
5235   (at 9, end_mark)
5236")
5237  undo_edit
5238  delete_samples(4, 2)
5239  test_output.call(3, "
5240 (delete 4 2) ; delete_samples(4, 2 [3:5]:
5241   (at 0, cp->sounds[1][0:1, 1.000]) [buf: 10]
5242   (at 2, cp->sounds[1][2:3, 1.000, [1]0.200 -> 0.280]) [buf: 10]
5243   (at 4, cp->sounds[1][6:7, 1.000, [1]0.520 -> 0.600]) [buf: 10]
5244   (at 6, cp->sounds[1][8:9, 1.000]) [buf: 10]
5245   (at 8, end_mark)
5246")
5247  undo_edit
5248  delete_samples(4, 3)
5249  test_output.call(3, "
5250 (delete 4 3) ; delete_samples(4, 3 [3:5]:
5251   (at 0, cp->sounds[1][0:1, 1.000]) [buf: 10]
5252   (at 2, cp->sounds[1][2:3, 1.000, [1]0.200 -> 0.280]) [buf: 10]
5253   (at 4, cp->sounds[1][7:7, 1.000, [1]0.600 -> 0.600]) [buf: 10]
5254   (at 5, cp->sounds[1][8:9, 1.000]) [buf: 10]
5255   (at 7, end_mark)
5256")
5257  undo_edit
5258  delete_samples(4, 4)
5259  test_output.call(3, "
5260 (delete 4 4) ; delete_samples(4, 4 [3:4]:
5261   (at 0, cp->sounds[1][0:1, 1.000]) [buf: 10]
5262   (at 2, cp->sounds[1][2:3, 1.000, [1]0.200 -> 0.280]) [buf: 10]
5263   (at 4, cp->sounds[1][8:9, 1.000]) [buf: 10]
5264   (at 6, end_mark)
5265")
5266  undo_edit
5267  delete_samples(4, 5)
5268  test_output.call(3, "
5269 (delete 4 5) ; delete_samples(4, 5 [3:4]:
5270   (at 0, cp->sounds[1][0:1, 1.000]) [buf: 10]
5271   (at 2, cp->sounds[1][2:3, 1.000, [1]0.200 -> 0.280]) [buf: 10]
5272   (at 4, cp->sounds[1][9:9, 1.000]) [buf: 10]
5273   (at 5, end_mark)
5274")
5275  undo_edit
5276  scale_channel(0.5, 4, 2)
5277  test_output.call(3, "
5278 (scale 4 2) ; scale_channel(0.500, 4, 2 [3:6]:
5279   (at 0, cp->sounds[1][0:1, 1.000]) [buf: 10]
5280   (at 2, cp->sounds[1][2:3, 1.000, [1]0.200 -> 0.280]) [buf: 10]
5281   (at 4, cp->sounds[1][4:5, 0.500, [1]0.360 -> 0.440]) [buf: 10]
5282   (at 6, cp->sounds[1][6:7, 1.000, [1]0.520 -> 0.600]) [buf: 10]
5283   (at 8, cp->sounds[1][8:9, 1.000]) [buf: 10]
5284   (at 10, end_mark)
5285")
5286  undo_edit
5287  pad_channel(4, 1)
5288  test_output.call(3, "
5289 (silence 4 1) ; pad-channel [3:6]:
5290   (at 0, cp->sounds[1][0:1, 1.000]) [buf: 10]
5291   (at 2, cp->sounds[1][2:3, 1.000, [1]0.200 -> 0.280]) [buf: 10]
5292   (at 4, cp->sounds[-1][0:0, 0.000])
5293   (at 5, cp->sounds[1][4:7, 1.000, [1]0.360 -> 0.600]) [buf: 10]
5294   (at 9, cp->sounds[1][8:9, 1.000]) [buf: 10]
5295   (at 11, end_mark)
5296")
5297  close_sound(ind)
5298end
5299
5300# xramp
5301def test_05_02
5302  ind = new_sound("test.snd")
5303  idx = -1
5304  test_name = "xramp"
5305  test_output = lambda do |ed, str|
5306    idx += 1
5307    if (res = safe_display_edits(ind, 0, ed)) != str
5308      snd_display("%s %s: %s %s?", test_name, idx, str, res)
5309    end
5310  end
5311  map_channel($init_channel, 0, 10)
5312  xramp_channel(0.0, 1.0, 32.0)
5313  test_output.call(2, "
5314 (ramp 0 10) ; xramp_channel(0.000, 1.000, 32.000, 0, false [2:2]:
5315   (at 0, cp->sounds[1][0:9, 1.000, [1]0.000 -> 1.000, off: -0.032, scl: 0.032]) [buf: 10]
5316   (at 10, end_mark)
5317")
5318  undo_edit
5319  xramp_channel(0.0, 1.0, 0.325)
5320  test_output.call(2, "
5321 (ramp 0 10) ; xramp_channel(0.000, 1.000, 0.325, 0, false [2:2]:
5322   (at 0, cp->sounds[1][0:9, 1.000, [1]0.000 -> 1.000, off: 1.481, scl: -1.481]) [buf: 10]
5323   (at 10, end_mark)
5324")
5325  undo_edit
5326  xramp_channel(0.0, 1.0, 0.0)
5327  test_output.call(2, format("
5328 (scale 0 10) ; scale_channel(0.000, 0, false [2:2]:
5329   (at 0, cp->sounds[0][0:9, 0.000]) [file: %s/test.snd[0]]
5330   (at 10, end_mark)
5331", Dir.pwd))
5332  undo_edit
5333  xramp_channel(0.0, 1.0, 1.0)
5334  test_output.call(2, "
5335 (ramp 0 10) ; ramp_channel(0.000, 1.000, 0, false [2:2]:
5336   (at 0, cp->sounds[1][0:9, 1.000, [1]0.000 -> 1.000]) [buf: 10]
5337   (at 10, end_mark)
5338")
5339  undo_edit
5340  xramp_channel(0.5, 1.5, 32.0)
5341  test_output.call(2, "
5342 (ramp 0 10) ; xramp_channel(0.500, 1.500, 32.000, 0, false [2:2]:
5343   (at 0, cp->sounds[1][0:9, 1.000, [1]0.500 -> 1.500, off: 0.468, scl: 0.032]) [buf: 10]
5344   (at 10, end_mark)
5345")
5346  if fneq(maxamp, 1.5) or fneq(sample(0), 0.5)
5347    snd_display("xramp 5 vals: %s %s", maxamp, sample(0))
5348  end
5349  undo_edit
5350  xramp_channel(-0.5, 1.5, 32.0)
5351  test_output.call(2, "
5352 (ramp 0 10) ; xramp_channel(-0.500, 1.500, 32.000, 0, false [2:2]:
5353   (at 0, cp->sounds[1][0:9, 1.000, [1]-0.500 -> 1.500, off: -0.565, scl: 0.065]) [buf: 10]
5354   (at 10, end_mark)
5355")
5356  if fneq(maxamp, 1.5) or fneq(sample(0), -0.5)
5357    snd_display("xramp 6 vals: %s %s", maxamp, sample(0))
5358  end
5359  undo_edit
5360  xramp_channel(0.0, 1.0, 32.0)
5361  vals = channel2vct
5362  scale_channel(0.5)
5363  test_output.call(3, "
5364 (scale 0 10) ; scale_channel(0.500, 0, false [3:2]:
5365   (at 0, cp->sounds[1][0:9, 0.500, [1]0.000 -> 1.000, off: -0.032, scl: 0.032]) [buf: 10]
5366   (at 10, end_mark)
5367")
5368  ctr = 0
5369  if res = scan_channel(lambda do |y|
5370                       if fneq(y, 0.5 * vals[ctr])
5371                         true
5372                       else
5373                         ctr += 1
5374                         false
5375                       end
5376               end)
5377    snd_display("trouble in xramp 7: %s", res)
5378  end
5379  undo_edit
5380  delete_sample(0)
5381  test_output.call(3, "
5382 (delete 0 1) ; delete_samples(0, 1 [3:2]:
5383   (at 0, cp->sounds[1][1:9, 1.000, [1]0.015 -> 1.000, off: -0.032, scl: 0.032]) [buf: 10]
5384   (at 9, end_mark)
5385")
5386  ctr = 1
5387  if res = scan_channel(lambda do |y|
5388                       if fneq(y, vals[ctr])
5389                         true
5390                       else
5391                         ctr += 1
5392                         false
5393                       end
5394               end)
5395    snd_display("trouble in xramp 8: %s", res)
5396  end
5397  undo_edit
5398  delete_samples(0, 2)
5399  test_output.call(3, "
5400 (delete 0 2) ; delete_samples(0, 2 [3:2]:
5401   (at 0, cp->sounds[1][2:9, 1.000, [1]0.037 -> 1.000, off: -0.032, scl: 0.032]) [buf: 10]
5402   (at 8, end_mark)
5403")
5404  ctr = 2
5405  if res = scan_channel(lambda do |y|
5406                       if fneq(y, vals[ctr])
5407                         true
5408                       else
5409                         ctr += 1
5410                         false
5411                       end
5412               end)
5413    snd_display("trouble in xramp 9: %s", res)
5414  end
5415  undo_edit
5416  delete_sample(0)
5417  delete_sample(0)
5418  test_output.call(4, "
5419 (delete 0 1) ; delete_samples(0, 1 [4:2]:
5420   (at 0, cp->sounds[1][2:9, 1.000, [1]0.037 -> 1.000, off: -0.032, scl: 0.032]) [buf: 10]
5421   (at 8, end_mark)
5422")
5423  undo_edit(2)
5424  delete_sample(4)
5425  test_output.call(3, "
5426 (delete 4 1) ; delete_samples(4, 1 [3:3]:
5427   (at 0, cp->sounds[1][0:3, 1.000, [1]0.000 -> 0.070, off: -0.032, scl: 0.032]) [buf: 10]
5428   (at 4, cp->sounds[1][5:9, 1.000, [1]0.189 -> 1.000, off: -0.032, scl: 0.032]) [buf: 10]
5429   (at 9, end_mark)
5430")
5431  undo_edit
5432  delete_samples(4, 2)
5433  test_output.call(3, "
5434 (delete 4 2) ; delete_samples(4, 2 [3:3]:
5435   (at 0, cp->sounds[1][0:3, 1.000, [1]0.000 -> 0.070, off: -0.032, scl: 0.032]) [buf: 10]
5436   (at 4, cp->sounds[1][6:9, 1.000, [1]0.293 -> 1.000, off: -0.032, scl: 0.032]) [buf: 10]
5437   (at 8, end_mark)
5438")
5439  undo_edit
5440  scale_channel(0.5, 4, 2)
5441  test_output.call(3, "
5442 (scale 4 2) ; scale_channel(0.500, 4, 2 [3:4]:
5443   (at 0, cp->sounds[1][0:3, 1.000, [1]0.000 -> 0.070, off: -0.032, scl: 0.032]) [buf: 10]
5444   (at 4, cp->sounds[1][4:5, 0.500, [1]0.118 -> 0.189, off: -0.032, scl: 0.032]) [buf: 10]
5445   (at 6, cp->sounds[1][6:9, 1.000, [1]0.293 -> 1.000, off: -0.032, scl: 0.032]) [buf: 10]
5446   (at 10, end_mark)
5447")
5448  ctr = 0
5449  if res = scan_channel(lambda do |y|
5450                       if (ctr > 5 and fneq(y, vals[ctr])) or
5451                           (ctr < 4 and fneq(y, vals[ctr])) or
5452                           ((ctr == 4 or ctr == 5) and fneq(y, 0.5 * vals[ctr]))
5453                         true
5454                       else
5455                         ctr += 1
5456                         false
5457                       end
5458               end)
5459    snd_display("trouble in xramp 13: %s", res)
5460  end
5461  undo_edit
5462  scale_channel(0.5, 0, 2)
5463  test_output.call(3, "
5464 (scale 0 2) ; scale_channel(0.500, 0, 2 [3:3]:
5465   (at 0, cp->sounds[1][0:1, 0.500, [1]0.000 -> 0.015, off: -0.032, scl: 0.032]) [buf: 10]
5466   (at 2, cp->sounds[1][2:9, 1.000, [1]0.037 -> 1.000, off: -0.032, scl: 0.032]) [buf: 10]
5467   (at 10, end_mark)
5468")
5469  undo_edit
5470  pad_channel(4, 2)
5471  test_output.call(3, "
5472 (silence 4 2) ; pad-channel [3:4]:
5473   (at 0, cp->sounds[1][0:3, 1.000, [1]0.000 -> 0.070, off: -0.032, scl: 0.032]) [buf: 10]
5474   (at 4, cp->sounds[-1][0:1, 0.000])
5475   (at 6, cp->sounds[1][4:9, 1.000, [1]0.118 -> 1.000, off: -0.032, scl: 0.032]) [buf: 10]
5476   (at 12, end_mark)
5477")
5478  undo_edit
5479  set_sample(4, 1.0)
5480  test_output.call(3, "
5481 (set 4 1) ; set_sample(4, 1.0000 [3:4]:
5482   (at 0, cp->sounds[1][0:3, 1.000, [1]0.000 -> 0.070, off: -0.032, scl: 0.032]) [buf: 10]
5483   (at 4, cp->sounds[2][0:0, 1.000]) [buf: 1]
5484   (at 5, cp->sounds[1][5:9, 1.000, [1]0.189 -> 1.000, off: -0.032, scl: 0.032]) [buf: 10]
5485   (at 10, end_mark)
5486")
5487  undo_edit
5488  set_samples(4, 2, make_vct(2))
5489  test_output.call(3, "
5490 (set 4 2) ; set-samples [3:4]:
5491   (at 0, cp->sounds[1][0:3, 1.000, [1]0.000 -> 0.070, off: -0.032, scl: 0.032]) [buf: 10]
5492   (at 4, cp->sounds[2][0:1, 1.000]) [buf: 2]
5493   (at 6, cp->sounds[1][6:9, 1.000, [1]0.293 -> 1.000, off: -0.032, scl: 0.032]) [buf: 10]
5494   (at 10, end_mark)
5495")
5496  undo_edit
5497  scale_channel(0.5)
5498  set_samples(4, 2, make_vct(2))
5499  test_output.call(4, "
5500 (set 4 2) ; set-samples [4:4]:
5501   (at 0, cp->sounds[1][0:3, 0.500, [1]0.000 -> 0.070, off: -0.032, scl: 0.032]) [buf: 10]
5502   (at 4, cp->sounds[2][0:1, 1.000]) [buf: 2]
5503   (at 6, cp->sounds[1][6:9, 0.500, [1]0.293 -> 1.000, off: -0.032, scl: 0.032]) [buf: 10]
5504   (at 10, end_mark)
5505")
5506  close_sound(ind)
5507  ind = new_sound("test.snd")
5508  test_name = "multi-ramp"
5509  idx = 0
5510  map_channel($init_channel, 0, 100)
5511  10.times do |i| scale_channel(0.5, i * 10, 10) end
5512  ramp_channel(0.0, 1.0)
5513  test_output.call(12, "
5514 (ramp 0 100) ; ramp_channel(0.000, 1.000, 0, false [12:11]:
5515   (at 0, cp->sounds[1][0:9, 0.500, [1]0.000 -> 0.091]) [buf: 100]
5516   (at 10, cp->sounds[1][10:19, 0.500, [1]0.101 -> 0.192]) [buf: 100]
5517   (at 20, cp->sounds[1][20:29, 0.500, [1]0.202 -> 0.293]) [buf: 100]
5518   (at 30, cp->sounds[1][30:39, 0.500, [1]0.303 -> 0.394]) [buf: 100]
5519   (at 40, cp->sounds[1][40:49, 0.500, [1]0.404 -> 0.495]) [buf: 100]
5520   (at 50, cp->sounds[1][50:59, 0.500, [1]0.505 -> 0.596]) [buf: 100]
5521   (at 60, cp->sounds[1][60:69, 0.500, [1]0.606 -> 0.697]) [buf: 100]
5522   (at 70, cp->sounds[1][70:79, 0.500, [1]0.707 -> 0.798]) [buf: 100]
5523   (at 80, cp->sounds[1][80:89, 0.500, [1]0.808 -> 0.899]) [buf: 100]
5524   (at 90, cp->sounds[1][90:99, 0.500, [1]0.909 -> 1.000]) [buf: 100]
5525   (at 100, end_mark)
5526")
5527  if fneq(maxamp, 0.5)
5528    snd_display("multi-ramp 1 maxamp: %s", maxamp)
5529  end
5530  undo_edit
5531  ramp_channel(0.1, 1.0, 10, 90)
5532  test_output.call(12, "
5533 (ramp 10 90) ; ramp_channel(0.100, 1.000, 10, 90 [12:11]:
5534   (at 0, cp->sounds[1][0:9, 0.500]) [buf: 100]
5535   (at 10, cp->sounds[1][10:19, 0.500, [1]0.100 -> 0.191]) [buf: 100]
5536   (at 20, cp->sounds[1][20:29, 0.500, [1]0.201 -> 0.292]) [buf: 100]
5537   (at 30, cp->sounds[1][30:39, 0.500, [1]0.302 -> 0.393]) [buf: 100]
5538   (at 40, cp->sounds[1][40:49, 0.500, [1]0.403 -> 0.494]) [buf: 100]
5539   (at 50, cp->sounds[1][50:59, 0.500, [1]0.504 -> 0.596]) [buf: 100]
5540   (at 60, cp->sounds[1][60:69, 0.500, [1]0.606 -> 0.697]) [buf: 100]
5541   (at 70, cp->sounds[1][70:79, 0.500, [1]0.707 -> 0.798]) [buf: 100]
5542   (at 80, cp->sounds[1][80:89, 0.500, [1]0.808 -> 0.899]) [buf: 100]
5543   (at 90, cp->sounds[1][90:99, 0.500, [1]0.909 -> 1.000]) [buf: 100]
5544   (at 100, end_mark)
5545")
5546  if fneq(maxamp, 0.5)
5547    snd_display("multi-ramp 2 maxamp: %s", maxamp)
5548  end
5549  undo_edit
5550  ramp_channel(0.0, 0.9, 0, 90)
5551  test_output.call(12, "
5552 (ramp 0 90) ; ramp_channel(0.000, 0.900, 0, 90 [12:11]:
5553   (at 0, cp->sounds[1][0:9, 0.500, [1]0.000 -> 0.091]) [buf: 100]
5554   (at 10, cp->sounds[1][10:19, 0.500, [1]0.101 -> 0.192]) [buf: 100]
5555   (at 20, cp->sounds[1][20:29, 0.500, [1]0.202 -> 0.293]) [buf: 100]
5556   (at 30, cp->sounds[1][30:39, 0.500, [1]0.303 -> 0.394]) [buf: 100]
5557   (at 40, cp->sounds[1][40:49, 0.500, [1]0.404 -> 0.496]) [buf: 100]
5558   (at 50, cp->sounds[1][50:59, 0.500, [1]0.506 -> 0.597]) [buf: 100]
5559   (at 60, cp->sounds[1][60:69, 0.500, [1]0.607 -> 0.698]) [buf: 100]
5560   (at 70, cp->sounds[1][70:79, 0.500, [1]0.708 -> 0.799]) [buf: 100]
5561   (at 80, cp->sounds[1][80:89, 0.500, [1]0.809 -> 0.900]) [buf: 100]
5562   (at 90, cp->sounds[1][90:99, 0.500]) [buf: 100]
5563   (at 100, end_mark)
5564")
5565  if fneq(maxamp, 0.5)
5566    snd_display("multi-ramp 3 maxamp: %s", maxamp)
5567  end
5568  if fneq(sample(89), 0.45)
5569    snd_display("multi-ramp 3 sample 89: %s", sample(89))
5570  end
5571  if fneq(sample(90), 0.5)
5572    snd_display("multi-ramp 3 sample 90: %s", sample(90))
5573  end
5574  undo_edit
5575  ramp_channel(0.1, 0.9, 10, 80)
5576  test_output.call(12, "
5577 (ramp 10 80) ; ramp_channel(0.100, 0.900, 10, 80 [12:11]:
5578   (at 0, cp->sounds[1][0:9, 0.500]) [buf: 100]
5579   (at 10, cp->sounds[1][10:19, 0.500, [1]0.100 -> 0.191]) [buf: 100]
5580   (at 20, cp->sounds[1][20:29, 0.500, [1]0.201 -> 0.292]) [buf: 100]
5581   (at 30, cp->sounds[1][30:39, 0.500, [1]0.303 -> 0.394]) [buf: 100]
5582   (at 40, cp->sounds[1][40:49, 0.500, [1]0.404 -> 0.495]) [buf: 100]
5583   (at 50, cp->sounds[1][50:59, 0.500, [1]0.505 -> 0.596]) [buf: 100]
5584   (at 60, cp->sounds[1][60:69, 0.500, [1]0.606 -> 0.697]) [buf: 100]
5585   (at 70, cp->sounds[1][70:79, 0.500, [1]0.708 -> 0.799]) [buf: 100]
5586   (at 80, cp->sounds[1][80:89, 0.500, [1]0.809 -> 0.900]) [buf: 100]
5587   (at 90, cp->sounds[1][90:99, 0.500]) [buf: 100]
5588   (at 100, end_mark)
5589")
5590  revert_sound
5591  map_channel($init_channel, 0, 100)
5592  ramp_channel(0.0, 1.0)
5593  10.times do |i| scale_channel(0.5, i * 10, 10) end
5594  test_output.call(12, "
5595 (scale 90 10) ; scale_channel(0.500, 90, 10 [12:11]:
5596   (at 0, cp->sounds[1][0:9, 0.500, [1]0.000 -> 0.091]) [buf: 100]
5597   (at 10, cp->sounds[1][10:19, 0.500, [1]0.101 -> 0.192]) [buf: 100]
5598   (at 20, cp->sounds[1][20:29, 0.500, [1]0.202 -> 0.293]) [buf: 100]
5599   (at 30, cp->sounds[1][30:39, 0.500, [1]0.303 -> 0.394]) [buf: 100]
5600   (at 40, cp->sounds[1][40:49, 0.500, [1]0.404 -> 0.495]) [buf: 100]
5601   (at 50, cp->sounds[1][50:59, 0.500, [1]0.505 -> 0.596]) [buf: 100]
5602   (at 60, cp->sounds[1][60:69, 0.500, [1]0.606 -> 0.697]) [buf: 100]
5603   (at 70, cp->sounds[1][70:79, 0.500, [1]0.707 -> 0.798]) [buf: 100]
5604   (at 80, cp->sounds[1][80:89, 0.500, [1]0.808 -> 0.899]) [buf: 100]
5605   (at 90, cp->sounds[1][90:99, 0.500, [1]0.909 -> 1.000]) [buf: 100]
5606   (at 100, end_mark)
5607")
5608  close_sound(ind)
5609end
5610
5611# ramp2
5612def test_05_03
5613  ind = new_sound("test.snd")
5614  idx = -1
5615  test_name = "ramp2"
5616  test_output = lambda do |ed, str|
5617    idx += 1
5618    if (res = safe_display_edits(ind, 0, ed)) != str
5619      snd_display("%s %s: %s %s?", test_name, idx, str, res)
5620    end
5621  end
5622  map_chan($init_channel, 0, 10)
5623  ramp_channel(0.0, 1.0)
5624  ramp_channel(0.0, 1.0)
5625  test_output.call(3, "
5626 (ramp 0 11) ; ramp_channel(0.000, 1.000, 0, false [3:2]:
5627   (at 0, cp->sounds[1][0:10, 1.000, [1]0.000 -> 1.000, [2]0.000 -> 1.000]) [buf: 11]
5628   (at 11, end_mark)
5629")
5630  unless vequal(res = channel2vct,
5631                vct(0.000, 0.010, 0.040, 0.090, 0.160, 0.250, 0.360, 0.490, 0.640, 0.810, 1.000))
5632    snd_display("ramp2 (0): %s", res)
5633  end
5634  scale_channel(0.5)
5635  test_output.call(4, "
5636 (scale 0 11) ; scale_channel(0.500, 0, false [4:2]:
5637   (at 0, cp->sounds[1][0:10, 0.500, [1]0.000 -> 1.000, [2]0.000 -> 1.000]) [buf: 11]
5638   (at 11, end_mark)
5639")
5640  undo_edit
5641  scale_channel(0.5, 0, 5)
5642  test_output.call(4, "
5643 (scale 0 5) ; scale_channel(0.500, 0, 5 [4:3]:
5644   (at 0, cp->sounds[1][0:4, 0.500, [1]0.000 -> 0.400, [2]0.000 -> 0.400]) [buf: 11]
5645   (at 5, cp->sounds[1][5:10, 1.000, [1]0.500 -> 1.000, [2]0.500 -> 1.000]) [buf: 11]
5646   (at 11, end_mark)
5647")
5648  unless vequal(res = channel2vct,
5649                vct(0.000, 0.005, 0.020, 0.045, 0.080, 0.250, 0.360, 0.490, 0.640, 0.810, 1.000))
5650    snd_display("ramp2 (2): %s", res)
5651  end
5652  undo_edit
5653  scale_channel(0.5, 2, 4)
5654  test_output.call(4, "
5655 (scale 2 4) ; scale_channel(0.500, 2, 4 [4:4]:
5656   (at 0, cp->sounds[1][0:1, 1.000, [1]0.000 -> 0.100, [2]0.000 -> 0.100]) [buf: 11]
5657   (at 2, cp->sounds[1][2:5, 0.500, [1]0.200 -> 0.500, [2]0.200 -> 0.500]) [buf: 11]
5658   (at 6, cp->sounds[1][6:10, 1.000, [1]0.600 -> 1.000, [2]0.600 -> 1.000]) [buf: 11]
5659   (at 11, end_mark)
5660")
5661  undo_edit(2)
5662  ramp_channel(0.75, 0.25)
5663  test_output.call(3, "
5664 (ramp 0 11) ; ramp_channel(0.750, 0.250, 0, false [3:2]:
5665   (at 0, cp->sounds[1][0:10, 1.000, [1]0.000 -> 1.000, [2]0.750 -> 0.250]) [buf: 11]
5666   (at 11, end_mark)
5667")
5668  undo_edit
5669  ramp_channel(0.2, 0.6, 2, 6)
5670  test_output.call(3, "
5671 (ramp 2 6) ; ramp_channel(0.200, 0.600, 2, 6 [3:4]:
5672   (at 0, cp->sounds[1][0:1, 1.000, [1]0.000 -> 0.100]) [buf: 11]
5673   (at 2, cp->sounds[1][2:7, 1.000, [1]0.200 -> 0.700, [2]0.200 -> 0.600]) [buf: 11]
5674   (at 8, cp->sounds[1][8:10, 1.000, [1]0.800 -> 1.000]) [buf: 11]
5675   (at 11, end_mark)
5676")
5677  scale_channel(0.5, 0, 5)
5678  test_output.call(4, "
5679 (scale 0 5) ; scale_channel(0.500, 0, 5 [4:5]:
5680   (at 0, cp->sounds[1][0:1, 0.500, [1]0.000 -> 0.100]) [buf: 11]
5681   (at 2, cp->sounds[1][2:4, 0.500, [1]0.200 -> 0.400, [2]0.200 -> 0.360]) [buf: 11]
5682   (at 5, cp->sounds[1][5:7, 1.000, [1]0.500 -> 0.700, [2]0.440 -> 0.600]) [buf: 11]
5683   (at 8, cp->sounds[1][8:10, 1.000, [1]0.800 -> 1.000]) [buf: 11]
5684   (at 11, end_mark)
5685")
5686  undo_edit
5687  set_sample(4, 0.5)
5688  test_output.call(4, "
5689 (set 4 1) ; set_sample(4, 0.5000 [4:6]:
5690   (at 0, cp->sounds[1][0:1, 1.000, [1]0.000 -> 0.100]) [buf: 11]
5691   (at 2, cp->sounds[1][2:3, 1.000, [1]0.200 -> 0.300, [2]0.200 -> 0.280]) [buf: 11]
5692   (at 4, cp->sounds[2][0:0, 1.000]) [buf: 1]
5693   (at 5, cp->sounds[1][5:7, 1.000, [1]0.500 -> 0.700, [2]0.440 -> 0.600]) [buf: 11]
5694   (at 8, cp->sounds[1][8:10, 1.000, [1]0.800 -> 1.000]) [buf: 11]
5695   (at 11, end_mark)
5696")
5697  undo_edit(3)
5698  close_sound(ind)
5699  ind = new_sound("test.snd")
5700  map_channel($init_channel, 0, 100)
5701  test_name = "multi-ramp2"
5702  10.times do |i| scale_channel(0.5, i * 10, 10) end
5703  ramp_channel(0.0, 1.0)
5704  ramp_channel(1.0, 0.0)
5705  test_output.call(13, "
5706 (ramp 0 100) ; ramp_channel(1.000, 0.000, 0, false [13:11]:
5707   (at 0, cp->sounds[1][0:9, 0.500, [1]0.000 -> 0.091, [2]1.000 -> 0.909]) [buf: 100]
5708   (at 10, cp->sounds[1][10:19, 0.500, [1]0.101 -> 0.192, [2]0.899 -> 0.808]) [buf: 100]
5709   (at 20, cp->sounds[1][20:29, 0.500, [1]0.202 -> 0.293, [2]0.798 -> 0.707]) [buf: 100]
5710   (at 30, cp->sounds[1][30:39, 0.500, [1]0.303 -> 0.394, [2]0.697 -> 0.606]) [buf: 100]
5711   (at 40, cp->sounds[1][40:49, 0.500, [1]0.404 -> 0.495, [2]0.596 -> 0.505]) [buf: 100]
5712   (at 50, cp->sounds[1][50:59, 0.500, [1]0.505 -> 0.596, [2]0.495 -> 0.404]) [buf: 100]
5713   (at 60, cp->sounds[1][60:69, 0.500, [1]0.606 -> 0.697, [2]0.394 -> 0.303]) [buf: 100]
5714   (at 70, cp->sounds[1][70:79, 0.500, [1]0.707 -> 0.798, [2]0.293 -> 0.202]) [buf: 100]
5715   (at 80, cp->sounds[1][80:89, 0.500, [1]0.808 -> 0.899, [2]0.192 -> 0.101]) [buf: 100]
5716   (at 90, cp->sounds[1][90:99, 0.500, [1]0.909 -> 1.000, [2]0.091 -> 0.000]) [buf: 100]
5717   (at 100, end_mark)
5718")
5719  undo_edit(12)
5720  ramp_channel(0.0, 1.0, 10, 20)
5721  ramp_channel(0.0, 1.0, 50, 10)
5722  ramp_channel(0.0, 1.0, 25, 10)
5723  test_output.call(4, "
5724 (ramp 25 10) ; ramp_channel(0.000, 1.000, 25, 10 [4:8]:
5725   (at 0, cp->sounds[1][0:9, 1.000]) [buf: 100]
5726   (at 10, cp->sounds[1][10:24, 1.000, [1]0.000 -> 0.737]) [buf: 100]
5727   (at 25, cp->sounds[1][25:29, 1.000, [1]0.789 -> 1.000, [2]0.000 -> 0.444]) [buf: 100]
5728   (at 30, cp->sounds[1][30:34, 1.000, [1]0.556 -> 1.000]) [buf: 100]
5729   (at 35, cp->sounds[1][35:49, 1.000]) [buf: 100]
5730   (at 50, cp->sounds[1][50:59, 1.000, [1]0.000 -> 1.000]) [buf: 100]
5731   (at 60, cp->sounds[1][60:99, 1.000]) [buf: 100]
5732   (at 100, end_mark)
5733")
5734  close_sound(ind)
5735end
5736
5737# ramp-xramp, xramp-ramp
5738def test_05_04
5739  ind = new_sound("test.snd")
5740  idx = -1
5741  test_name = "ramp-xramp"
5742  test_output = lambda do |ed, str|
5743    idx += 1
5744    if (res = safe_display_edits(ind, 0, ed)) != str
5745      snd_display("%s %s: %s %s?", test_name, idx, str, res)
5746    end
5747  end
5748  map_chan($init_channel, 0, 10)
5749  ramp_channel(0.0, 1.0)
5750  xramp_channel(0.0, 1.0, 32.0)
5751  test_output.call(3, "
5752 (ramp 0 11) ; xramp_channel(0.000, 1.000, 32.000, 0, false [3:2]:
5753   (at 0, cp->sounds[1][0:10, 1.000, [1]0.000 -> 1.000, [2]0.000 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
5754   (at 11, end_mark)
5755")
5756  unless vequal(case1 = channel2vct,
5757                vct(0.000, 0.001, 0.006, 0.018, 0.039, 0.075, 0.135, 0.233, 0.387, 0.628, 1.000))
5758    snd_display("ramp-xramp (1): %s", case1)
5759  end
5760  scale_channel(0.5)
5761  test_output.call(4, "
5762 (scale 0 11) ; scale_channel(0.500, 0, false [4:2]:
5763   (at 0, cp->sounds[1][0:10, 0.500, [1]0.000 -> 1.000, [2]0.000 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
5764   (at 11, end_mark)
5765")
5766  undo_edit
5767  scale_channel(0.5, 0, 5)
5768  test_output.call(4, "
5769 (scale 0 5) ; scale_channel(0.500, 0, 5 [4:3]:
5770   (at 0, cp->sounds[1][0:4, 0.500, [1]0.000 -> 0.400, [2]0.000 -> 0.097, off: -0.032, scl: 0.032]) [buf: 11]
5771   (at 5, cp->sounds[1][5:10, 1.000, [1]0.500 -> 1.000, [2]0.150 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
5772   (at 11, end_mark)
5773")
5774  unless vequal(case2 = channel2vct,
5775                vct(0.000, 0.001, 0.003, 0.009, 0.019, 0.075, 0.135, 0.233, 0.387, 0.628, 1.000))
5776    snd_display("ramp-xramp (2): %s", case2)
5777  end
5778  undo_edit
5779  scale_channel(0.5, 2, 4)
5780  test_output.call(4, "
5781 (scale 2 4) ; scale_channel(0.500, 2, 4 [4:4]:
5782   (at 0, cp->sounds[1][0:1, 1.000, [1]0.000 -> 0.100, [2]0.000 -> 0.013, off: -0.032, scl: 0.032]) [buf: 11]
5783   (at 2, cp->sounds[1][2:5, 0.500, [1]0.200 -> 0.500, [2]0.032 -> 0.150, off: -0.032, scl: 0.032]) [buf: 11]
5784   (at 6, cp->sounds[1][6:10, 1.000, [1]0.600 -> 1.000, [2]0.226 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
5785   (at 11, end_mark)
5786")
5787  undo_edit(2)
5788  xramp_channel(0.75, 0.25, 32.0)
5789  test_output.call(3, "
5790 (ramp 0 11) ; xramp_channel(0.750, 0.250, 32.000, 0, false [3:2]:
5791   (at 0, cp->sounds[1][0:10, 1.000, [1]0.000 -> 1.000, [2]0.750 -> 0.250, off: 0.234, scl: 0.016]) [buf: 11]
5792   (at 11, end_mark)
5793")
5794  undo_edit
5795  xramp_channel(0.2, 0.6, 3.0, 2, 6)
5796  test_output.call(3, "
5797 (ramp 2 6) ; xramp_channel(0.200, 0.600, 3.000, 2, 6 [3:4]:
5798   (at 0, cp->sounds[1][0:1, 1.000, [1]0.000 -> 0.100]) [buf: 11]
5799   (at 2, cp->sounds[1][2:7, 1.000, [1]0.200 -> 0.700, [2]0.200 -> 0.600, off: 0.000, scl: 0.200]) [buf: 11]
5800   (at 8, cp->sounds[1][8:10, 1.000, [1]0.800 -> 1.000]) [buf: 11]
5801   (at 11, end_mark)
5802")
5803  scale_channel(0.5, 0, 5)
5804  test_output.call(4, "
5805 (scale 0 5) ; scale_channel(0.500, 0, 5 [4:5]:
5806   (at 0, cp->sounds[1][0:1, 0.500, [1]0.000 -> 0.100]) [buf: 11]
5807   (at 2, cp->sounds[1][2:4, 0.500, [1]0.200 -> 0.400, [2]0.200 -> 0.310, off: 0.000, scl: 0.200]) [buf: 11]
5808   (at 5, cp->sounds[1][5:7, 1.000, [1]0.500 -> 0.700, [2]0.387 -> 0.600, off: 0.000, scl: 0.200]) [buf: 11]
5809   (at 8, cp->sounds[1][8:10, 1.000, [1]0.800 -> 1.000]) [buf: 11]
5810   (at 11, end_mark)
5811")
5812  undo_edit
5813  set_sample(4, 0.5)
5814  test_output.call(4, "
5815 (set 4 1) ; set_sample(4, 0.5000 [4:6]:
5816   (at 0, cp->sounds[1][0:1, 1.000, [1]0.000 -> 0.100]) [buf: 11]
5817   (at 2, cp->sounds[1][2:3, 1.000, [1]0.200 -> 0.300, [2]0.200 -> 0.249, off: 0.000, scl: 0.200]) [buf: 11]
5818   (at 4, cp->sounds[2][0:0, 1.000]) [buf: 1]
5819   (at 5, cp->sounds[1][5:7, 1.000, [1]0.500 -> 0.700, [2]0.387 -> 0.600, off: 0.000, scl: 0.200]) [buf: 11]
5820   (at 8, cp->sounds[1][8:10, 1.000, [1]0.800 -> 1.000]) [buf: 11]
5821   (at 11, end_mark)
5822")
5823  revert_sound
5824  test_name = "xramp-ramp"
5825  map_chan($init_channel, 0, 10)
5826  xramp_channel(0.0, 1.0, 32.0)
5827  ramp_channel(0.0, 1.0)
5828  test_output.call(3, "
5829 (ramp 0 11) ; ramp_channel(0.000, 1.000, 0, false [3:2]:
5830   (at 0, cp->sounds[1][0:10, 1.000, [1]0.000 -> 1.000, [2]0.000 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
5831   (at 11, end_mark)
5832")
5833  unless vequal(case1, (res = channel2vct))
5834    snd_display("xramp-ramp (1): %s", res)
5835  end
5836  scale_channel(0.5)
5837  test_output.call(4, "
5838 (scale 0 11) ; scale_channel(0.500, 0, false [4:2]:
5839   (at 0, cp->sounds[1][0:10, 0.500, [1]0.000 -> 1.000, [2]0.000 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
5840   (at 11, end_mark)
5841")
5842  undo_edit
5843  scale_channel(0.5, 0, 5)
5844  test_output.call(4, "
5845 (scale 0 5) ; scale_channel(0.500, 0, 5 [4:3]:
5846   (at 0, cp->sounds[1][0:4, 0.500, [1]0.000 -> 0.400, [2]0.000 -> 0.097, off: -0.032, scl: 0.032]) [buf: 11]
5847   (at 5, cp->sounds[1][5:10, 1.000, [1]0.500 -> 1.000, [2]0.150 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
5848   (at 11, end_mark)
5849")
5850  unless vequal(case2, (res = channel2vct))
5851    snd_display("xramp-ramp (2): %s", res)
5852  end
5853  undo_edit
5854  scale_channel(0.5, 2, 4)
5855  test_output.call(4, "
5856 (scale 2 4) ; scale_channel(0.500, 2, 4 [4:4]:
5857   (at 0, cp->sounds[1][0:1, 1.000, [1]0.000 -> 0.100, [2]0.000 -> 0.013, off: -0.032, scl: 0.032]) [buf: 11]
5858   (at 2, cp->sounds[1][2:5, 0.500, [1]0.200 -> 0.500, [2]0.032 -> 0.150, off: -0.032, scl: 0.032]) [buf: 11]
5859   (at 6, cp->sounds[1][6:10, 1.000, [1]0.600 -> 1.000, [2]0.226 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
5860   (at 11, end_mark)
5861")
5862  undo_edit(2)
5863  ramp_channel(0.75, 0.25)
5864  test_output.call(3, "
5865 (ramp 0 11) ; ramp_channel(0.750, 0.250, 0, false [3:2]:
5866   (at 0, cp->sounds[1][0:10, 1.000, [1]0.750 -> 0.250, [2]0.000 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
5867   (at 11, end_mark)
5868")
5869  undo_edit
5870  ramp_channel(0.2, 0.6, 2, 6)
5871  test_output.call(3, "
5872 (ramp 2 6) ; ramp_channel(0.200, 0.600, 2, 6 [3:4]:
5873   (at 0, cp->sounds[1][0:1, 1.000, [1]0.000 -> 0.013, off: -0.032, scl: 0.032]) [buf: 11]
5874   (at 2, cp->sounds[1][2:7, 1.000, [1]0.200 -> 0.600, [2]0.032 -> 0.333, off: -0.032, scl: 0.032]) [buf: 11]
5875   (at 8, cp->sounds[1][8:10, 1.000, [1]0.484 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
5876   (at 11, end_mark)
5877")
5878  scale_channel(0.5, 0, 5)
5879  test_output.call(4, "
5880 (scale 0 5) ; scale_channel(0.500, 0, 5 [4:5]:
5881   (at 0, cp->sounds[1][0:1, 0.500, [1]0.000 -> 0.013, off: -0.032, scl: 0.032]) [buf: 11]
5882   (at 2, cp->sounds[1][2:4, 0.500, [1]0.200 -> 0.360, [2]0.032 -> 0.097, off: -0.032, scl: 0.032]) [buf: 11]
5883   (at 5, cp->sounds[1][5:7, 1.000, [1]0.440 -> 0.600, [2]0.150 -> 0.333, off: -0.032, scl: 0.032]) [buf: 11]
5884   (at 8, cp->sounds[1][8:10, 1.000, [1]0.484 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
5885   (at 11, end_mark)
5886")
5887  undo_edit
5888  set_sample(4, 0.5)
5889  test_output.call(4, "
5890 (set 4 1) ; set_sample(4, 0.5000 [4:6]:
5891   (at 0, cp->sounds[1][0:1, 1.000, [1]0.000 -> 0.013, off: -0.032, scl: 0.032]) [buf: 11]
5892   (at 2, cp->sounds[1][2:3, 1.000, [1]0.200 -> 0.280, [2]0.032 -> 0.059, off: -0.032, scl: 0.032]) [buf: 11]
5893   (at 4, cp->sounds[2][0:0, 1.000]) [buf: 1]
5894   (at 5, cp->sounds[1][5:7, 1.000, [1]0.440 -> 0.600, [2]0.150 -> 0.333, off: -0.032, scl: 0.032]) [buf: 11]
5895   (at 8, cp->sounds[1][8:10, 1.000, [1]0.484 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
5896   (at 11, end_mark)
5897")
5898  close_sound(ind)
5899end
5900
5901# ramp2+xramp
5902def test_05_05
5903  ind = new_sound("test.snd")
5904  idx = -1
5905  test_name = "ramp2+xramp"
5906  test_output = lambda do |ed, str|
5907    idx += 1
5908    if (res = safe_display_edits(ind, 0, ed)) != str
5909      snd_display("%s %s: %s %s?", test_name, idx, str, res)
5910    end
5911  end
5912  map_chan($init_channel, 0, 10)
5913  xramp_channel(0.0, 1.0, 32.0)
5914  ramp_channel(0.0, 1.0)
5915  ramp_channel(0.0, 1.0)
5916  test_output.call(4, "
5917 (ramp 0 11) ; ramp_channel(0.000, 1.000, 0, false [4:2]:
5918   (at 0, cp->sounds[1][0:10, 1.000, [1]0.000 -> 1.000, [2]0.000 -> 1.000, [3]0.000 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
5919   (at 11, end_mark)
5920")
5921  unless vequal(case1 = channel2vct,
5922                vct(0.000, 0.000, 0.001, 0.005, 0.015, 0.038, 0.081, 0.163, 0.310, 0.565, 1.000))
5923    snd_display("ramp2+xramp (1): %s", case1)
5924  end
5925  scale_channel(0.5)
5926  test_output.call(5, "
5927 (scale 0 11) ; scale_channel(0.500, 0, false [5:2]:
5928   (at 0, cp->sounds[1][0:10, 0.500, [1]0.000 -> 1.000, [2]0.000 -> 1.000, [3]0.000 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
5929   (at 11, end_mark)
5930")
5931  undo_edit
5932  scale_channel(0.5, 0, 5)
5933  test_output.call(5, "
5934 (scale 0 5) ; scale_channel(0.500, 0, 5 [5:3]:
5935   (at 0, cp->sounds[1][0:4, 0.500, [1]0.000 -> 0.400, [2]0.000 -> 0.400, [3]0.000 -> 0.097, off: -0.032, scl: 0.032]) [buf: 11]
5936   (at 5, cp->sounds[1][5:10, 1.000, [1]0.500 -> 1.000, [2]0.500 -> 1.000, [3]0.150 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
5937   (at 11, end_mark)
5938")
5939  unless vequal(case2 = channel2vct,
5940                vct(0.000, 0.000, 0.001, 0.003, 0.008, 0.038, 0.081, 0.163, 0.310, 0.565, 1.000))
5941    snd_display("ramp2+xramp (2): %s", case2)
5942  end
5943  undo_edit
5944  scale_channel(0.5, 2, 4)
5945  test_output.call(5, "
5946 (scale 2 4) ; scale_channel(0.500, 2, 4 [5:4]:
5947   (at 0, cp->sounds[1][0:1, 1.000, [1]0.000 -> 0.100, [2]0.000 -> 0.100, [3]0.000 -> 0.013, off: -0.032, scl: 0.032]) [buf: 11]
5948   (at 2, cp->sounds[1][2:5, 0.500, [1]0.200 -> 0.500, [2]0.200 -> 0.500, [3]0.032 -> 0.150, off: -0.032, scl: 0.032]) [buf: 11]
5949   (at 6, cp->sounds[1][6:10, 1.000, [1]0.600 -> 1.000, [2]0.600 -> 1.000, [3]0.226 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
5950   (at 11, end_mark)
5951")
5952  undo_edit(2)
5953  ramp_channel(0.75, 0.25)
5954  test_output.call(4, "
5955 (ramp 0 11) ; ramp_channel(0.750, 0.250, 0, false [4:2]:
5956   (at 0, cp->sounds[1][0:10, 1.000, [1]0.000 -> 1.000, [2]0.750 -> 0.250, [3]0.000 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
5957   (at 11, end_mark)
5958")
5959  undo_edit
5960  ramp_channel(0.2, 0.6, 2, 6)
5961  test_output.call(4, "
5962 (ramp 2 6) ; ramp_channel(0.200, 0.600, 2, 6 [4:4]:
5963   (at 0, cp->sounds[1][0:1, 1.000, [1]0.000 -> 0.100, [2]0.000 -> 0.013, off: -0.032, scl: 0.032]) [buf: 11]
5964   (at 2, cp->sounds[1][2:7, 1.000, [1]0.200 -> 0.700, [2]0.200 -> 0.600, [3]0.032 -> 0.333, off: -0.032, scl: 0.032]) [buf: 11]
5965   (at 8, cp->sounds[1][8:10, 1.000, [1]0.800 -> 1.000, [2]0.484 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
5966   (at 11, end_mark)
5967")
5968  scale_channel(0.5, 0, 5)
5969  test_output.call(5, "
5970 (scale 0 5) ; scale_channel(0.500, 0, 5 [5:5]:
5971   (at 0, cp->sounds[1][0:1, 0.500, [1]0.000 -> 0.100, [2]0.000 -> 0.013, off: -0.032, scl: 0.032]) [buf: 11]
5972   (at 2, cp->sounds[1][2:4, 0.500, [1]0.200 -> 0.400, [2]0.200 -> 0.360, [3]0.032 -> 0.097, off: -0.032, scl: 0.032]) [buf: 11]
5973   (at 5, cp->sounds[1][5:7, 1.000, [1]0.500 -> 0.700, [2]0.440 -> 0.600, [3]0.150 -> 0.333, off: -0.032, scl: 0.032]) [buf: 11]
5974   (at 8, cp->sounds[1][8:10, 1.000, [1]0.800 -> 1.000, [2]0.484 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
5975   (at 11, end_mark)
5976")
5977  undo_edit
5978  set_sample(4, 0.5)
5979  test_output.call(5, "
5980 (set 4 1) ; set_sample(4, 0.5000 [5:6]:
5981   (at 0, cp->sounds[1][0:1, 1.000, [1]0.000 -> 0.100, [2]0.000 -> 0.013, off: -0.032, scl: 0.032]) [buf: 11]
5982   (at 2, cp->sounds[1][2:3, 1.000, [1]0.200 -> 0.300, [2]0.200 -> 0.280, [3]0.032 -> 0.059, off: -0.032, scl: 0.032]) [buf: 11]
5983   (at 4, cp->sounds[2][0:0, 1.000]) [buf: 1]
5984   (at 5, cp->sounds[1][5:7, 1.000, [1]0.500 -> 0.700, [2]0.440 -> 0.600, [3]0.150 -> 0.333, off: -0.032, scl: 0.032]) [buf: 11]
5985   (at 8, cp->sounds[1][8:10, 1.000, [1]0.800 -> 1.000, [2]0.484 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
5986   (at 11, end_mark)
5987")
5988  revert_sound
5989  idx = -1
5990  test_name = "xramp+ramp2"
5991  map_chan($init_channel, 0, 10)
5992  ramp_channel(0.0, 1.0)
5993  ramp_channel(0.0, 1.0)
5994  xramp_channel(0.0, 1.0, 32.0)
5995  test_output.call(4, "
5996 (ramp 0 11) ; xramp_channel(0.000, 1.000, 32.000, 0, false [4:2]:
5997   (at 0, cp->sounds[1][0:10, 1.000, [1]0.000 -> 1.000, [2]0.000 -> 1.000, [3]0.000 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
5998   (at 11, end_mark)
5999")
6000  unless vequal(case1, (res = channel2vct))
6001    snd_display("xramp+ramp2 (1): %s", res)
6002  end
6003  revert_sound(ind)
6004  close_sound(ind)
6005end
6006
6007# multi-ramp2+xramp
6008# multi-ramp-xramp
6009# xramp2
6010# multi-xramp2
6011def test_05_06
6012  ind = new_sound("test.snd")
6013  idx = -1
6014  test_name = "multi-ramp2+xramp"
6015  test_output = lambda do |ed, str|
6016    idx += 1
6017    if (res = safe_display_edits(ind, 0, ed)) != str
6018      snd_display("%s %s: %s %s?", test_name, idx, str, res)
6019    end
6020  end
6021  map_channel($init_channel, 0, 100)
6022  scale_channel(0.5)
6023  xramp_channel(1.0, 0.0, 32.0)
6024  ramp_channel(0.0, 1.0)
6025  ramp_channel(0.0, 1.0)
6026  case3 = channel2vct
6027  undo_edit(4)
6028  10.times do |i| scale_channel(0.5, i * 10, 10) end
6029  xramp_channel(1.0, 0.0, 32.0)
6030  ramp_channel(0.0, 1.0)
6031  ramp_channel(0.0, 1.0)
6032  test_output.call(14, "
6033 (ramp 0 100) ; ramp_channel(0.000, 1.000, 0, false [14:11]:
6034   (at 0, cp->sounds[1][0:9, 0.500, [1]0.000 -> 0.091, [2]0.000 -> 0.091, [3]1.000 -> 0.721, off: -0.032, scl: 0.032]) [buf: 100]
6035   (at 10, cp->sounds[1][10:19, 0.500, [1]0.101 -> 0.192, [2]0.101 -> 0.192, [3]0.695 -> 0.499, off: -0.032, scl: 0.032]) [buf: 100]
6036   (at 20, cp->sounds[1][20:29, 0.500, [1]0.202 -> 0.293, [2]0.202 -> 0.293, [3]0.480 -> 0.342, off: -0.032, scl: 0.032]) [buf: 100]
6037   (at 30, cp->sounds[1][30:39, 0.500, [1]0.303 -> 0.394, [2]0.303 -> 0.394, [3]0.329 -> 0.231, off: -0.032, scl: 0.032]) [buf: 100]
6038   (at 40, cp->sounds[1][40:49, 0.500, [1]0.404 -> 0.495, [2]0.404 -> 0.495, [3]0.222 -> 0.153, off: -0.032, scl: 0.032]) [buf: 100]
6039   (at 50, cp->sounds[1][50:59, 0.500, [1]0.505 -> 0.596, [2]0.505 -> 0.596, [3]0.147 -> 0.099, off: -0.032, scl: 0.032]) [buf: 100]
6040   (at 60, cp->sounds[1][60:69, 0.500, [1]0.606 -> 0.697, [2]0.606 -> 0.697, [3]0.094 -> 0.060, off: -0.032, scl: 0.032]) [buf: 100]
6041   (at 70, cp->sounds[1][70:79, 0.500, [1]0.707 -> 0.798, [2]0.707 -> 0.798, [3]0.057 -> 0.033, off: -0.032, scl: 0.032]) [buf: 100]
6042   (at 80, cp->sounds[1][80:89, 0.500, [1]0.808 -> 0.899, [2]0.808 -> 0.899, [3]0.030 -> 0.014, off: -0.032, scl: 0.032]) [buf: 100]
6043   (at 90, cp->sounds[1][90:99, 0.500, [1]0.909 -> 1.000, [2]0.909 -> 1.000, [3]0.012 -> -0.000, off: -0.032, scl: 0.032]) [buf: 100]
6044   (at 100, end_mark)
6045")
6046  unless vequal(case3, res = channel2vct)
6047    snd_display("multi-ramp2+xramp: %s", res)
6048  end
6049  revert_sound
6050  map_channel($init_channel, 0, 100)
6051  xramp_channel(1.0, 0.0, 32.0)
6052  ramp_channel(0.0, 1.0, 10, 20)
6053  ramp_channel(0.0, 1.0, 50, 10)
6054  ramp_channel(0.0, 1.0, 25, 10)
6055  test_output.call(5, "
6056 (ramp 25 10) ; ramp_channel(0.000, 1.000, 25, 10 [5:8]:
6057   (at 0, cp->sounds[1][0:9, 1.000, [1]1.000 -> 0.721, off: -0.032, scl: 0.032]) [buf: 100]
6058   (at 10, cp->sounds[1][10:24, 1.000, [1]0.000 -> 0.737, [2]0.695 -> 0.413, off: -0.032, scl: 0.032]) [buf: 100]
6059   (at 25, cp->sounds[1][25:29, 1.000, [1]0.789 -> 1.000, [2]0.000 -> 0.444, [3]0.398 -> 0.342, off: -0.032, scl: 0.032]) [buf: 100]
6060   (at 30, cp->sounds[1][30:34, 1.000, [1]0.556 -> 1.000, [2]0.329 -> 0.282, off: -0.032, scl: 0.032]) [buf: 100]
6061   (at 35, cp->sounds[1][35:49, 1.000, [1]0.271 -> 0.153, off: -0.032, scl: 0.032]) [buf: 100]
6062   (at 50, cp->sounds[1][50:59, 1.000, [1]0.000 -> 1.000, [2]0.147 -> 0.099, off: -0.032, scl: 0.032]) [buf: 100]
6063   (at 60, cp->sounds[1][60:99, 1.000, [1]0.094 -> -0.000, off: -0.032, scl: 0.032]) [buf: 100]
6064   (at 100, end_mark)
6065")
6066  close_sound(ind)
6067  ind = new_sound("test.snd")
6068  idx = -1
6069  test_name = "multi-ramp-xramp"
6070  map_channel($init_channel, 0, 100)
6071  scale_channel(0.5)
6072  ramp_channel(0.0, 1.0)
6073  xramp_channel(1.0, 0.0, 32.0)
6074  case3 = channel2vct
6075  undo_edit(3)
6076  10.times do |i| scale_channel(0.5, i * 10, 10) end
6077  ramp_channel(0.0, 1.0)
6078  xramp_channel(1.0, 0.0, 32.0)
6079  test_output.call(13, "
6080 (ramp 0 100) ; xramp_channel(1.000, 0.000, 32.000, 0, false [13:11]:
6081   (at 0, cp->sounds[1][0:9, 0.500, [1]0.000 -> 0.091, [2]1.000 -> 0.721, off: -0.032, scl: 0.032]) [buf: 100]
6082   (at 10, cp->sounds[1][10:19, 0.500, [1]0.101 -> 0.192, [2]0.695 -> 0.499, off: -0.032, scl: 0.032]) [buf: 100]
6083   (at 20, cp->sounds[1][20:29, 0.500, [1]0.202 -> 0.293, [2]0.480 -> 0.342, off: -0.032, scl: 0.032]) [buf: 100]
6084   (at 30, cp->sounds[1][30:39, 0.500, [1]0.303 -> 0.394, [2]0.329 -> 0.231, off: -0.032, scl: 0.032]) [buf: 100]
6085   (at 40, cp->sounds[1][40:49, 0.500, [1]0.404 -> 0.495, [2]0.222 -> 0.153, off: -0.032, scl: 0.032]) [buf: 100]
6086   (at 50, cp->sounds[1][50:59, 0.500, [1]0.505 -> 0.596, [2]0.147 -> 0.099, off: -0.032, scl: 0.032]) [buf: 100]
6087   (at 60, cp->sounds[1][60:69, 0.500, [1]0.606 -> 0.697, [2]0.094 -> 0.060, off: -0.032, scl: 0.032]) [buf: 100]
6088   (at 70, cp->sounds[1][70:79, 0.500, [1]0.707 -> 0.798, [2]0.057 -> 0.033, off: -0.032, scl: 0.032]) [buf: 100]
6089   (at 80, cp->sounds[1][80:89, 0.500, [1]0.808 -> 0.899, [2]0.030 -> 0.014, off: -0.032, scl: 0.032]) [buf: 100]
6090   (at 90, cp->sounds[1][90:99, 0.500, [1]0.909 -> 1.000, [2]0.012 -> -0.000, off: -0.032, scl: 0.032]) [buf: 100]
6091   (at 100, end_mark)
6092")
6093  unless vequal(case3, res = channel2vct)
6094    snd_display("multi-ramp-xramp: %s", res)
6095  end
6096  undo_edit(12)
6097  xramp_channel(0.0, 1.0, 3.0, 10, 20)
6098  xramp_channel(0.0, 1.0, 3.0, 50, 10)
6099  xramp_channel(0.0, 1.0, 3.0, 25, 10)
6100  test_output.call(4, "
6101 (ramp 25 10) ; xramp_channel(0.000, 1.000, 3.000, 25, 10 [4:8]:
6102   (at 0, cp->sounds[1][0:9, 1.000]) [buf: 100]
6103   (at 10, cp->sounds[1][10:24, 1.000, [1]0.000 -> 0.623, off: -0.500, scl: 0.500]) [buf: 100]
6104   (at 25, cp->sounds[1][25:29, 1.000, [1]0.690 -> 1.000, off: -0.500, scl: 0.500, [2]0.000 -> 0.315, off: -0.500, scl: 0.500]) [buf: 100]
6105   (at 30, cp->sounds[1][30:34, 1.000, [1]0.421 -> 1.000, off: -0.500, scl: 0.500]) [buf: 100]
6106   (at 35, cp->sounds[1][35:49, 1.000]) [buf: 100]
6107   (at 50, cp->sounds[1][50:59, 1.000, [1]0.000 -> 1.000, off: -0.500, scl: 0.500]) [buf: 100]
6108   (at 60, cp->sounds[1][60:99, 1.000]) [buf: 100]
6109   (at 100, end_mark)
6110")
6111  revert_sound
6112  test_name = "multi-xramp-ramp 3"
6113  map_channel($init_channel, 0, 100)
6114  10.times do |i| scale_channel(0.5, i * 10, 10) end
6115  xramp_channel(1.0, 0.0, 32.0)
6116  ramp_channel(0.0, 1.0)
6117  test_output.call(13, "
6118 (ramp 0 100) ; ramp_channel(0.000, 1.000, 0, false [13:11]:
6119   (at 0, cp->sounds[1][0:9, 0.500, [1]0.000 -> 0.091, [2]1.000 -> 0.721, off: -0.032, scl: 0.032]) [buf: 100]
6120   (at 10, cp->sounds[1][10:19, 0.500, [1]0.101 -> 0.192, [2]0.695 -> 0.499, off: -0.032, scl: 0.032]) [buf: 100]
6121   (at 20, cp->sounds[1][20:29, 0.500, [1]0.202 -> 0.293, [2]0.480 -> 0.342, off: -0.032, scl: 0.032]) [buf: 100]
6122   (at 30, cp->sounds[1][30:39, 0.500, [1]0.303 -> 0.394, [2]0.329 -> 0.231, off: -0.032, scl: 0.032]) [buf: 100]
6123   (at 40, cp->sounds[1][40:49, 0.500, [1]0.404 -> 0.495, [2]0.222 -> 0.153, off: -0.032, scl: 0.032]) [buf: 100]
6124   (at 50, cp->sounds[1][50:59, 0.500, [1]0.505 -> 0.596, [2]0.147 -> 0.099, off: -0.032, scl: 0.032]) [buf: 100]
6125   (at 60, cp->sounds[1][60:69, 0.500, [1]0.606 -> 0.697, [2]0.094 -> 0.060, off: -0.032, scl: 0.032]) [buf: 100]
6126   (at 70, cp->sounds[1][70:79, 0.500, [1]0.707 -> 0.798, [2]0.057 -> 0.033, off: -0.032, scl: 0.032]) [buf: 100]
6127   (at 80, cp->sounds[1][80:89, 0.500, [1]0.808 -> 0.899, [2]0.030 -> 0.014, off: -0.032, scl: 0.032]) [buf: 100]
6128   (at 90, cp->sounds[1][90:99, 0.500, [1]0.909 -> 1.000, [2]0.012 -> -0.000, off: -0.032, scl: 0.032]) [buf: 100]
6129   (at 100, end_mark)
6130")
6131  undo_edit(12)
6132  ramp_channel(0.0, 1.0, 10, 20)
6133  ramp_channel(0.0, 1.0, 50, 10)
6134  ramp_channel(0.0, 1.0, 25, 10)
6135  test_output.call(4, "
6136 (ramp 25 10) ; ramp_channel(0.000, 1.000, 25, 10 [4:8]:
6137   (at 0, cp->sounds[1][0:9, 1.000]) [buf: 100]
6138   (at 10, cp->sounds[1][10:24, 1.000, [1]0.000 -> 0.737]) [buf: 100]
6139   (at 25, cp->sounds[1][25:29, 1.000, [1]0.789 -> 1.000, [2]0.000 -> 0.444]) [buf: 100]
6140   (at 30, cp->sounds[1][30:34, 1.000, [1]0.556 -> 1.000]) [buf: 100]
6141   (at 35, cp->sounds[1][35:49, 1.000]) [buf: 100]
6142   (at 50, cp->sounds[1][50:59, 1.000, [1]0.000 -> 1.000]) [buf: 100]
6143   (at 60, cp->sounds[1][60:99, 1.000]) [buf: 100]
6144   (at 100, end_mark)
6145")
6146  close_sound(ind)
6147  ind = new_sound("test.snd")
6148  idx = -1
6149  test_name = "xramp2"
6150  map_chan($init_channel, 0, 10)
6151  xramp_channel(0.0, 1.0, 2.0)
6152  xramp_channel(0.0, 1.0, 2.0)
6153  test_output.call(3, "
6154 (ramp 0 11) ; xramp_channel(0.000, 1.000, 2.000, 0, false [3:2]:
6155   (at 0, cp->sounds[1][0:10, 1.000, [1]0.000 -> 1.000, off: -1.000, scl: 1.000, [2]0.000 -> 1.000, off: -1.000, scl: 1.000]) [buf: 11]
6156   (at 11, end_mark)
6157")
6158  unless vequal(res = channel2vct,
6159                vct(0.000, 0.005, 0.022, 0.053, 0.102, 0.172, 0.266, 0.390, 0.549, 0.750, 1.000))
6160    snd_display("xramp2 (1): %s", res)
6161  end
6162  scale_channel(0.5)
6163  test_output.call(4, "
6164 (scale 0 11) ; scale_channel(0.500, 0, false [4:2]:
6165   (at 0, cp->sounds[1][0:10, 0.500, [1]0.000 -> 1.000, off: -1.000, scl: 1.000, [2]0.000 -> 1.000, off: -1.000, scl: 1.000]) [buf: 11]
6166   (at 11, end_mark)
6167")
6168  undo_edit
6169  scale_channel(0.5, 0, 5)
6170  test_output.call(4, "
6171 (scale 0 5) ; scale_channel(0.500, 0, 5 [4:3]:
6172   (at 0, cp->sounds[1][0:4, 0.500, [1]0.000 -> 0.320, off: -1.000, scl: 1.000, [2]0.000 -> 0.320, off: -1.000, scl: 1.000]) [buf: 11]
6173   (at 5, cp->sounds[1][5:10, 1.000, [1]0.414 -> 1.000, off: -1.000, scl: 1.000, [2]0.414 -> 1.000, off: -1.000, scl: 1.000]) [buf: 11]
6174   (at 11, end_mark)
6175")
6176  unless vequal(res = channel2vct,
6177                vct(0.000, 0.003, 0.011, 0.027, 0.051, 0.172, 0.266, 0.390, 0.549, 0.750, 1.000))
6178    snd_display("xramp2 (2): %s", res)
6179  end
6180  undo_edit
6181  scale_channel(0.5, 2, 4)
6182  test_output.call(4, "
6183 (scale 2 4) ; scale_channel(0.500, 2, 4 [4:4]:
6184   (at 0, cp->sounds[1][0:1, 1.000, [1]0.000 -> 0.072, off: -1.000, scl: 1.000, [2]0.000 -> 0.072, off: -1.000, scl: 1.000]) [buf: 11]
6185   (at 2, cp->sounds[1][2:5, 0.500, [1]0.149 -> 0.414, off: -1.000, scl: 1.000, [2]0.149 -> 0.414, off: -1.000, scl: 1.000]) [buf: 11]
6186   (at 6, cp->sounds[1][6:10, 1.000, [1]0.516 -> 1.000, off: -1.000, scl: 1.000, [2]0.516 -> 1.000, off: -1.000, scl: 1.000]) [buf: 11]
6187   (at 11, end_mark)
6188")
6189  undo_edit(2)
6190  xramp_channel(0.75, 0.25, 0.3)
6191  test_output.call(3, "
6192 (ramp 0 11) ; xramp_channel(0.750, 0.250, 0.300, 0, false [3:2]:
6193   (at 0, cp->sounds[1][0:10, 1.000, [1]0.000 -> 1.000, off: -1.000, scl: 1.000, [2]0.750 -> 0.250, off: 0.964, scl: -0.714]) [buf: 11]
6194   (at 11, end_mark)
6195")
6196  undo_edit
6197  xramp_channel(0.2, 0.6, 32.0, 2, 6)
6198  test_output.call(3, "
6199 (ramp 2 6) ; xramp_channel(0.200, 0.600, 32.000, 2, 6 [3:4]:
6200   (at 0, cp->sounds[1][0:1, 1.000, [1]0.000 -> 0.072, off: -1.000, scl: 1.000]) [buf: 11]
6201   (at 2, cp->sounds[1][2:7, 1.000, [1]0.149 -> 0.625, off: -1.000, scl: 1.000, [2]0.200 -> 0.600, off: 0.187, scl: 0.013]) [buf: 11]
6202   (at 8, cp->sounds[1][8:10, 1.000, [1]0.741 -> 1.000, off: -1.000, scl: 1.000]) [buf: 11]
6203   (at 11, end_mark)
6204")
6205  scale_channel(0.5, 0, 5)
6206  test_output.call(4, "
6207 (scale 0 5) ; scale_channel(0.500, 0, 5 [4:5]:
6208   (at 0, cp->sounds[1][0:1, 0.500, [1]0.000 -> 0.072, off: -1.000, scl: 1.000]) [buf: 11]
6209   (at 2, cp->sounds[1][2:4, 0.500, [1]0.149 -> 0.320, off: -1.000, scl: 1.000, [2]0.200 -> 0.239, off: 0.187, scl: 0.013]) [buf: 11]
6210   (at 5, cp->sounds[1][5:7, 1.000, [1]0.414 -> 0.625, off: -1.000, scl: 1.000, [2]0.290 -> 0.600, off: 0.187, scl: 0.013]) [buf: 11]
6211   (at 8, cp->sounds[1][8:10, 1.000, [1]0.741 -> 1.000, off: -1.000, scl: 1.000]) [buf: 11]
6212   (at 11, end_mark)
6213")
6214  undo_edit
6215  set_sample(4, 0.5)
6216  test_output.call(4, "
6217 (set 4 1) ; set_sample(4, 0.5000 [4:6]:
6218   (at 0, cp->sounds[1][0:1, 1.000, [1]0.000 -> 0.072, off: -1.000, scl: 1.000]) [buf: 11]
6219   (at 2, cp->sounds[1][2:3, 1.000, [1]0.149 -> 0.231, off: -1.000, scl: 1.000, [2]0.200 -> 0.213, off: 0.187, scl: 0.013]) [buf: 11]
6220   (at 4, cp->sounds[2][0:0, 1.000]) [buf: 1]
6221   (at 5, cp->sounds[1][5:7, 1.000, [1]0.414 -> 0.625, off: -1.000, scl: 1.000, [2]0.290 -> 0.600, off: 0.187, scl: 0.013]) [buf: 11]
6222   (at 8, cp->sounds[1][8:10, 1.000, [1]0.741 -> 1.000, off: -1.000, scl: 1.000]) [buf: 11]
6223   (at 11, end_mark)
6224")
6225  undo_edit(3)
6226  close_sound(ind)
6227  ind = new_sound("test.snd")
6228  idx = -1
6229  test_name = "multi-xramp2"
6230  map_channel($init_channel, 0, 100)
6231  10.times do |i| scale_channel(0.5, i * 10, 10) end
6232  xramp_channel(0.0, 1.0, 3.0)
6233  xramp_channel(1.0, 0.0, 0.3)
6234  test_output.call(13, "
6235 (ramp 0 100) ; xramp_channel(1.000, 0.000, 0.300, 0, false [13:11]:
6236   (at 0, cp->sounds[1][0:9, 0.500, [1]0.000 -> 0.053, off: -0.500, scl: 0.500, [2]1.000 -> 0.950, off: 1.429, scl: -1.429]) [buf: 100]
6237   (at 10, cp->sounds[1][10:19, 0.500, [1]0.059 -> 0.117, off: -0.500, scl: 0.500, [2]0.945 -> 0.889, off: 1.429, scl: -1.429]) [buf: 100]
6238   (at 20, cp->sounds[1][20:29, 0.500, [1]0.124 -> 0.190, off: -0.500, scl: 0.500, [2]0.882 -> 0.819, off: 1.429, scl: -1.429]) [buf: 100]
6239   (at 30, cp->sounds[1][30:39, 0.500, [1]0.198 -> 0.271, off: -0.500, scl: 0.500, [2]0.811 -> 0.740, off: 1.429, scl: -1.429]) [buf: 100]
6240   (at 40, cp->sounds[1][40:49, 0.500, [1]0.279 -> 0.361, off: -0.500, scl: 0.500, [2]0.731 -> 0.651, off: 1.429, scl: -1.429]) [buf: 100]
6241   (at 50, cp->sounds[1][50:59, 0.500, [1]0.371 -> 0.462, off: -0.500, scl: 0.500, [2]0.641 -> 0.550, off: 1.429, scl: -1.429]) [buf: 100]
6242   (at 60, cp->sounds[1][60:69, 0.500, [1]0.473 -> 0.575, off: -0.500, scl: 0.500, [2]0.540 -> 0.437, off: 1.429, scl: -1.429]) [buf: 100]
6243   (at 70, cp->sounds[1][70:79, 0.500, [1]0.587 -> 0.701, off: -0.500, scl: 0.500, [2]0.425 -> 0.308, off: 1.429, scl: -1.429]) [buf: 100]
6244   (at 80, cp->sounds[1][80:89, 0.500, [1]0.715 -> 0.842, off: -0.500, scl: 0.500, [2]0.295 -> 0.164, off: 1.429, scl: -1.429]) [buf: 100]
6245   (at 90, cp->sounds[1][90:99, 0.500, [1]0.857 -> 1.000, off: -0.500, scl: 0.500, [2]0.148 -> 0.000, off: 1.429, scl: -1.429]) [buf: 100]
6246   (at 100, end_mark)
6247")
6248  close_sound(ind)
6249end
6250
6251# ramp3
6252# multi-ramp3
6253def test_05_07
6254  ind = new_sound("test.snd")
6255  idx = -1
6256  test_name = "ramp3"
6257  test_output = lambda do |ed, str|
6258    idx += 1
6259    if (res = safe_display_edits(ind, 0, ed)) != str
6260      snd_display("%s %s: %s %s?", test_name, idx, str, res)
6261    end
6262  end
6263  map_chan($init_channel, 0, 10)
6264  ramp_channel(0.0, 1.0)
6265  ramp_channel(0.0, 1.0)
6266  ramp_channel(0.0, 1.0)
6267  test_output.call(4, "
6268 (ramp 0 11) ; ramp_channel(0.000, 1.000, 0, false [4:2]:
6269   (at 0, cp->sounds[1][0:10, 1.000, [1]0.000 -> 1.000, [2]0.000 -> 1.000, [3]0.000 -> 1.000]) [buf: 11]
6270   (at 11, end_mark)
6271")
6272  unless vequal(res = channel2vct,
6273                vct(0.000, 0.001, 0.008, 0.027, 0.064, 0.125, 0.216, 0.343, 0.512, 0.729, 1.000))
6274    snd_display("ramp3 (1): %s", res)
6275  end
6276  scale_channel(0.5)
6277  test_output.call(5, "
6278 (scale 0 11) ; scale_channel(0.500, 0, false [5:2]:
6279   (at 0, cp->sounds[1][0:10, 0.500, [1]0.000 -> 1.000, [2]0.000 -> 1.000, [3]0.000 -> 1.000]) [buf: 11]
6280   (at 11, end_mark)
6281")
6282  undo_edit
6283  scale_channel(0.5, 0, 5)
6284  test_output.call(5, "
6285 (scale 0 5) ; scale_channel(0.500, 0, 5 [5:3]:
6286   (at 0, cp->sounds[1][0:4, 0.500, [1]0.000 -> 0.400, [2]0.000 -> 0.400, [3]0.000 -> 0.400]) [buf: 11]
6287   (at 5, cp->sounds[1][5:10, 1.000, [1]0.500 -> 1.000, [2]0.500 -> 1.000, [3]0.500 -> 1.000]) [buf: 11]
6288   (at 11, end_mark)
6289")
6290  undo_edit
6291  scale_channel(0.5, 2, 4)
6292  test_output.call(5, "
6293 (scale 2 4) ; scale_channel(0.500, 2, 4 [5:4]:
6294   (at 0, cp->sounds[1][0:1, 1.000, [1]0.000 -> 0.100, [2]0.000 -> 0.100, [3]0.000 -> 0.100]) [buf: 11]
6295   (at 2, cp->sounds[1][2:5, 0.500, [1]0.200 -> 0.500, [2]0.200 -> 0.500, [3]0.200 -> 0.500]) [buf: 11]
6296   (at 6, cp->sounds[1][6:10, 1.000, [1]0.600 -> 1.000, [2]0.600 -> 1.000, [3]0.600 -> 1.000]) [buf: 11]
6297   (at 11, end_mark)
6298")
6299  undo_edit(2)
6300  ramp_channel(0.75, 0.25)
6301  test_output.call(4, "
6302 (ramp 0 11) ; ramp_channel(0.750, 0.250, 0, false [4:2]:
6303   (at 0, cp->sounds[1][0:10, 1.000, [1]0.000 -> 1.000, [2]0.000 -> 1.000, [3]0.750 -> 0.250]) [buf: 11]
6304   (at 11, end_mark)
6305")
6306  undo_edit
6307  ramp_channel(0.2, 0.6, 2, 6)
6308  test_output.call(4, "
6309 (ramp 2 6) ; ramp_channel(0.200, 0.600, 2, 6 [4:4]:
6310   (at 0, cp->sounds[1][0:1, 1.000, [1]0.000 -> 0.100, [2]0.000 -> 0.100]) [buf: 11]
6311   (at 2, cp->sounds[1][2:7, 1.000, [1]0.200 -> 0.700, [2]0.200 -> 0.700, [3]0.200 -> 0.600]) [buf: 11]
6312   (at 8, cp->sounds[1][8:10, 1.000, [1]0.800 -> 1.000, [2]0.800 -> 1.000]) [buf: 11]
6313   (at 11, end_mark)
6314")
6315  scale_channel(0.5, 0, 5)
6316  test_output.call(5, "
6317 (scale 0 5) ; scale_channel(0.500, 0, 5 [5:5]:
6318   (at 0, cp->sounds[1][0:1, 0.500, [1]0.000 -> 0.100, [2]0.000 -> 0.100]) [buf: 11]
6319   (at 2, cp->sounds[1][2:4, 0.500, [1]0.200 -> 0.400, [2]0.200 -> 0.400, [3]0.200 -> 0.360]) [buf: 11]
6320   (at 5, cp->sounds[1][5:7, 1.000, [1]0.500 -> 0.700, [2]0.500 -> 0.700, [3]0.440 -> 0.600]) [buf: 11]
6321   (at 8, cp->sounds[1][8:10, 1.000, [1]0.800 -> 1.000, [2]0.800 -> 1.000]) [buf: 11]
6322   (at 11, end_mark)
6323")
6324  undo_edit
6325  set_sample(4, 0.5)
6326  test_output.call(5, "
6327 (set 4 1) ; set_sample(4, 0.5000 [5:6]:
6328   (at 0, cp->sounds[1][0:1, 1.000, [1]0.000 -> 0.100, [2]0.000 -> 0.100]) [buf: 11]
6329   (at 2, cp->sounds[1][2:3, 1.000, [1]0.200 -> 0.300, [2]0.200 -> 0.300, [3]0.200 -> 0.280]) [buf: 11]
6330   (at 4, cp->sounds[2][0:0, 1.000]) [buf: 1]
6331   (at 5, cp->sounds[1][5:7, 1.000, [1]0.500 -> 0.700, [2]0.500 -> 0.700, [3]0.440 -> 0.600]) [buf: 11]
6332   (at 8, cp->sounds[1][8:10, 1.000, [1]0.800 -> 1.000, [2]0.800 -> 1.000]) [buf: 11]
6333   (at 11, end_mark)
6334")
6335  undo_edit(3)
6336  close_sound(ind)
6337  ind = new_sound("test.snd")
6338  idx = -1
6339  test_name = "multi-ramp3"
6340  map_channel($init_channel, 0, 100)
6341  test_name = ""
6342  10.times do |i| scale_channel(0.5, i * 10, 10) end
6343  ramp_channel(0.0, 1.0)
6344  ramp_channel(1.0, -0.5)
6345  ramp_channel(-0.5, 1.5)
6346  test_output.call(14, "
6347 (ramp 0 100) ; ramp_channel(-0.500, 1.500, 0, false [14:11]:
6348   (at 0, cp->sounds[1][0:9, 0.500, [1]0.000 -> 0.091, [2]1.000 -> 0.864, [3]-0.500 -> -0.318]) [buf: 100]
6349   (at 10, cp->sounds[1][10:19, 0.500, [1]0.101 -> 0.192, [2]0.848 -> 0.712, [3]-0.298 -> -0.116]) [buf: 100]
6350   (at 20, cp->sounds[1][20:29, 0.500, [1]0.202 -> 0.293, [2]0.697 -> 0.561, [3]-0.096 -> 0.086]) [buf: 100]
6351   (at 30, cp->sounds[1][30:39, 0.500, [1]0.303 -> 0.394, [2]0.545 -> 0.409, [3]0.106 -> 0.288]) [buf: 100]
6352   (at 40, cp->sounds[1][40:49, 0.500, [1]0.404 -> 0.495, [2]0.394 -> 0.258, [3]0.308 -> 0.490]) [buf: 100]
6353   (at 50, cp->sounds[1][50:59, 0.500, [1]0.505 -> 0.596, [2]0.242 -> 0.106, [3]0.510 -> 0.692]) [buf: 100]
6354   (at 60, cp->sounds[1][60:69, 0.500, [1]0.606 -> 0.697, [2]0.091 -> -0.045, [3]0.712 -> 0.894]) [buf: 100]
6355   (at 70, cp->sounds[1][70:79, 0.500, [1]0.707 -> 0.798, [2]-0.061 -> -0.197, [3]0.914 -> 1.096]) [buf: 100]
6356   (at 80, cp->sounds[1][80:89, 0.500, [1]0.808 -> 0.899, [2]-0.212 -> -0.348, [3]1.116 -> 1.298]) [buf: 100]
6357   (at 90, cp->sounds[1][90:99, 0.500, [1]0.909 -> 1.000, [2]-0.364 -> -0.500, [3]1.318 -> 1.500]) [buf: 100]
6358   (at 100, end_mark)
6359")
6360  undo_edit(13)
6361  ramp_channel(0.0, 1.0, 10, 30)
6362  ramp_channel(0.0, 1.0, 50, 20)
6363  ramp_channel(0.0, 1.0, 20, 15)
6364  ramp_channel(0.0, 1.0, 30, 30)
6365  test_output.call(5, "
6366 (ramp 30 30) ; ramp_channel(0.000, 1.000, 30, 30 [5:10]:
6367   (at 0, cp->sounds[1][0:9, 1.000]) [buf: 100]
6368   (at 10, cp->sounds[1][10:19, 1.000, [1]0.000 -> 0.310]) [buf: 100]
6369   (at 20, cp->sounds[1][20:29, 1.000, [1]0.345 -> 0.655, [2]0.000 -> 0.643]) [buf: 100]
6370   (at 30, cp->sounds[1][30:34, 1.000, [1]0.690 -> 0.828, [2]0.714 -> 1.000, [3]0.000 -> 0.138]) [buf: 100]
6371   (at 35, cp->sounds[1][35:39, 1.000, [1]0.862 -> 1.000, [2]0.172 -> 0.310]) [buf: 100]
6372   (at 40, cp->sounds[1][40:49, 1.000, [1]0.345 -> 0.655]) [buf: 100]
6373   (at 50, cp->sounds[1][50:59, 1.000, [1]0.000 -> 0.474, [2]0.690 -> 1.000]) [buf: 100]
6374   (at 60, cp->sounds[1][60:69, 1.000, [1]0.526 -> 1.000]) [buf: 100]
6375   (at 70, cp->sounds[1][70:99, 1.000]) [buf: 100]
6376   (at 100, end_mark)
6377")
6378  close_sound(ind)
6379  ind = new_sound("test.snd")
6380  map_chan($init_channel, 0, 10)
6381  idx = -1
6382  test_name = "ramp+xramp"
6383  ramp_channel(0.0, 1.0)
6384  xramp_channel(0.0, 1.0, 32.0)
6385  test_output.call(3, "
6386 (ramp 0 11) ; xramp_channel(0.000, 1.000, 32.000, 0, false [3:2]:
6387   (at 0, cp->sounds[1][0:10, 1.000, [1]0.000 -> 1.000, [2]0.000 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
6388   (at 11, end_mark)
6389")
6390  idx = -1
6391  test_name = "xramp+xramp"
6392  undo_edit(2)
6393  xramp_channel(0.0, 1.0, 0.32)
6394  xramp_channel(0.0, 1.0, 32.0)
6395  test_output.call(3, "
6396 (ramp 0 11) ; xramp_channel(0.000, 1.000, 32.000, 0, false [3:2]:
6397   (at 0, cp->sounds[1][0:10, 1.000, [1]0.000 -> 1.000, off: 1.471, scl: -1.471, [2]0.000 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
6398   (at 11, end_mark)
6399")
6400  idx = -1
6401  test_name = "xramp+xramp+xramp"
6402  undo_edit(2)
6403  xramp_channel(0.0, 1.0, 0.32)
6404  xramp_channel(0.0, 1.0, 32.0)
6405  xramp_channel(0.0, 1.0, 32.0)
6406  test_output.call(4, "
6407 (ramp 0 11) ; xramp_channel(0.000, 1.000, 32.000, 0, false [4:2]:
6408   (at 0, cp->sounds[1][0:10, 1.000, [1]0.000 -> 1.000, off: 1.471, scl: -1.471, [2]0.000 -> 1.000, off: -0.032, scl: 0.032, [3]0.000 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
6409   (at 11, end_mark)
6410")
6411  idx = -1
6412  test_name = "xramp+xramp+ramp"
6413  undo_edit(3)
6414  xramp_channel(0.0, 1.0, 0.32)
6415  xramp_channel(0.0, 1.0, 32.0)
6416  ramp_channel(0.0, 1.0)
6417  test_output.call(4, "
6418 (ramp 0 11) ; ramp_channel(0.000, 1.000, 0, false [4:2]:
6419   (at 0, cp->sounds[1][0:10, 1.000, [1]0.000 -> 1.000, [2]0.000 -> 1.000, off: 1.471, scl: -1.471, [3]0.000 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
6420   (at 11, end_mark)
6421")
6422  idx = -1
6423  test_name = "xramp+ramp"
6424  undo_edit(3)
6425  xramp_channel(0.0, 1.0, 32.0)
6426  ramp_channel(0.0, 1.0)
6427  test_output.call(3, "
6428 (ramp 0 11) ; ramp_channel(0.000, 1.000, 0, false [3:2]:
6429   (at 0, cp->sounds[1][0:10, 1.000, [1]0.000 -> 1.000, [2]0.000 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
6430   (at 11, end_mark)
6431")
6432  idx = -1
6433  test_name = "ramp+ramp+xramp"
6434  undo_edit(2)
6435  ramp_channel(0.0, 1.0)
6436  ramp_channel(0.0, 1.0)
6437  xramp_channel(0.0, 1.0, 32.0)
6438  test_output.call(4, "
6439 (ramp 0 11) ; xramp_channel(0.000, 1.000, 32.000, 0, false [4:2]:
6440   (at 0, cp->sounds[1][0:10, 1.000, [1]0.000 -> 1.000, [2]0.000 -> 1.000, [3]0.000 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
6441   (at 11, end_mark)
6442")
6443  idx = -1
6444  test_name = "ramp+ramp+ramp+ramp"
6445  undo_edit(3)
6446  ramp_channel(0.0, 1.0)
6447  ramp_channel(0.0, 1.0)
6448  ramp_channel(0.0, 1.0)
6449  ramp_channel(0.0, 1.0)
6450  test_output.call(5, "
6451 (ramp 0 11) ; ramp_channel(0.000, 1.000, 0, false [5:2]:
6452   (at 0, cp->sounds[1][0:10, 1.000, [1]0.000 -> 1.000, [2]0.000 -> 1.000, [3]0.000 -> 1.000, [4]0.000 -> 1.000]) [buf: 11]
6453   (at 11, end_mark)
6454")
6455  idx = -1
6456  test_name = "ramp+ramp+ramp+xramp"
6457  undo_edit(4)
6458  ramp_channel(0.0, 1.0)
6459  ramp_channel(0.0, 1.0)
6460  ramp_channel(0.0, 1.0)
6461  xramp_channel(0.0, 1.0, 32.0)
6462  test_output.call(5, "
6463 (ramp 0 11) ; xramp_channel(0.000, 1.000, 32.000, 0, false [5:2]:
6464   (at 0, cp->sounds[1][0:10, 1.000, [1]0.000 -> 1.000, [2]0.000 -> 1.000, [3]0.000 -> 1.000, [4]0.000 -> 1.000, off: -0.032, scl: 0.032]) [buf: 11]
6465   (at 11, end_mark)
6466")
6467  close_sound(ind)
6468end
6469
6470def test_05_08
6471  data = make_vct(101, 1.0)
6472  rto1_data = make_vct(101)
6473  xto1_data = make_vct(101)
6474  cos_data = make_vct(101)
6475  xe = make_env(:envelope, [0, 0, 1, 1], :length, 101, :base, 32.0)
6476  incr = PI / 101.0
6477  ang = -0.5 * PI
6478  101.times do |i|
6479    rto1_data[i] = i * 0.01
6480    xto1_data[i] = env(xe)
6481    cos_data[i] = cos(ang)
6482    ang += incr
6483  end
6484  ind = new_sound("test.snd")
6485  set_to_1 = lambda do map_chan($init_channel, 0, 100) end
6486  cset_to_1 = lambda do |dat| 101.times do |i| dat[i] = 1.0 end end
6487  ramp_to_1 = lambda do ramp_channel(0.0, 1.0) end
6488  cramp_to_1 = lambda do |dat| vct_multiply!(dat, rto1_data) end
6489  scale_by_half = lambda do scale_channel(0.5) end
6490  cscale_by_half = lambda do |dat| vct_scale!(dat, 0.5) end
6491  scale_by_two = lambda do scale_channel(2.0, 30, 40) end
6492  cscale_by_two = lambda do |dat| (30...70).each do |i| dat[i] *= 2.0 end end
6493  xramp_to_1 = lambda do xramp_channel(0.0, 1.0, 32.0) end
6494  cxramp_to_1 = lambda do |dat| vct_multiply!(dat, xto1_data) end
6495  scale_mid = lambda do scale_channel(0.125, 30, 30) end
6496  cscale_mid = lambda do |dat| (30...60).each do |i| dat[i] *= 0.125 end end
6497  on_air = lambda do scale_channel(0.0, 10, 30) end
6498  con_air = lambda do |dat| (10...40).each do |i| dat[i] = 0.0 end end
6499  rev_channel2vct = lambda do
6500    len = data.length
6501    rd = make_sampler(len - 1, ind, 0, -1)
6502    dat = make_vct(len)
6503    (len - 1).downto(0) do |i| dat[i] = rd.call end
6504    free_sampler(rd)
6505    dat
6506  end
6507  if $with_test_motif
6508    edhist = channel_widgets(ind, 0)[7]
6509    edp = RXtParent(edhist)
6510    RXtUnmanageChild(edp)
6511    RXtVaSetValues(edp, [RXmNpaneMinimum, 100])
6512    RXtManageChild(edp)
6513  end
6514  set_squelch_update(true, ind)
6515  # 0 case
6516  set_to_1.call
6517  snd_test_neq(channel2vct, data, "0 case")
6518  snd_test_neq(rev_channel2vct.call, data, "0 rev case")
6519  # 1 case
6520  [[scale_by_two, cscale_by_two, :scale_by_two],
6521    [ramp_to_1, cramp_to_1, :ramp_to_1],
6522    [xramp_to_1, cxramp_to_1, :xramp_to_1],
6523    [scale_by_half, cscale_by_half, :scale_by_half],
6524    [scale_mid, cscale_mid, :scale_mid],
6525    [on_air, con_air, :on_air]].each do |func, check, name|
6526    revert_sound
6527    set_to_1.call
6528    cset_to_1.call(data)
6529    func.call
6530    check.call(data)
6531    snd_test_neq(channel2vct, data, "1 case %s", name)
6532    snd_test_neq(rev_channel2vct.call, data, "1 rev case %s", name)
6533  end
6534  # 2 case
6535  [[scale_by_two, cscale_by_two, :scale_by_two],
6536    [ramp_to_1, cramp_to_1, :ramp_to_1],
6537    [xramp_to_1, cxramp_to_1, :xramp_to_1],
6538    [scale_by_half, cscale_by_half, :scale_by_half],
6539    [scale_mid, cscale_mid, :scale_mid],
6540    [on_air, con_air, :on_air]].each do |func, check, name|
6541    [[scale_by_two, cscale_by_two, :scale_by_two],
6542      [ramp_to_1, cramp_to_1, :ramp_to_1],
6543      [xramp_to_1, cxramp_to_1, :xramp_to_1],
6544      [scale_by_half, cscale_by_half, :scale_by_half],
6545      [scale_mid, cscale_mid, :scale_mid],
6546      [on_air, con_air, :on_air]].each do |func1, check1, name1|
6547      revert_sound
6548      set_to_1.call
6549      cset_to_1.call(data)
6550      func.call
6551      check.call(data)
6552      func1.call
6553      check1.call(data)
6554      snd_test_neq(channel2vct, data, "2 case %s (%s)", name1, name)
6555      snd_test_neq(rev_channel2vct.call, data, "2 rev case %s (%s)", name1, name)
6556    end
6557  end
6558  # 3 case
6559  [[scale_by_two, cscale_by_two, :scale_by_two],
6560    [ramp_to_1, cramp_to_1, :ramp_to_1],
6561    [xramp_to_1, cxramp_to_1, :xramp_to_1],
6562    [scale_by_half, cscale_by_half, :scale_by_half],
6563    [scale_mid, cscale_mid, :scale_mid],
6564    [on_air, con_air, :on_air]].each do |func, check, name|
6565    [[scale_by_two, cscale_by_two, :scale_by_two],
6566      [ramp_to_1, cramp_to_1, :ramp_to_1],
6567      [xramp_to_1, cxramp_to_1, :xramp_to_1],
6568      [scale_by_half, cscale_by_half, :scale_by_half],
6569      [scale_mid, cscale_mid, :scale_mid],
6570      [on_air, con_air, :on_air]].each do |func1, check1, name1|
6571      [[scale_by_two, cscale_by_two, :scale_by_two],
6572        [ramp_to_1, cramp_to_1, :ramp_to_1],
6573        [xramp_to_1, cxramp_to_1, :xramp_to_1],
6574        [scale_by_half, cscale_by_half, :scale_by_half],
6575        [scale_mid, cscale_mid, :scale_mid],
6576        [on_air, con_air, :on_air]].each do |func2, check2, name2|
6577        revert_sound
6578        set_to_1.call
6579        cset_to_1.call(data)
6580        func.call
6581        check.call(data)
6582        func1.call
6583        check1.call(data)
6584        func2.call
6585        check2.call(data)
6586        snd_test_neq(channel2vct, data, "3 case %s (%s (%s))",
6587                     name2, name1, name)
6588        snd_test_neq(rev_channel2vct.call, data, "3 rev case %s (%s (%s))",
6589                     name2, name1, name)
6590      end
6591    end
6592  end
6593  if $all_args
6594    # 4 case
6595    [[scale_by_two, cscale_by_two, :scale_by_two],
6596     [ramp_to_1, cramp_to_1, :ramp_to_1],
6597     [xramp_to_1, cxramp_to_1, :xramp_to_1],
6598     [scale_by_half, cscale_by_half, :scale_by_half],
6599     [scale_mid, cscale_mid, :scale_mid],
6600     [on_air, con_air, :on_air]].each do |func, check, name|
6601      [[scale_by_two, cscale_by_two, :scale_by_two],
6602       [ramp_to_1, cramp_to_1, :ramp_to_1],
6603       [xramp_to_1, cxramp_to_1, :xramp_to_1],
6604       [scale_by_half, cscale_by_half, :scale_by_half],
6605       [scale_mid, cscale_mid, :scale_mid],
6606       [on_air, con_air, :on_air]].each do |func1, check1, name1|
6607        [[scale_by_two, cscale_by_two, :scale_by_two],
6608         [ramp_to_1, cramp_to_1, :ramp_to_1],
6609         [xramp_to_1, cxramp_to_1, :xramp_to_1],
6610         [scale_by_half, cscale_by_half, :scale_by_half],
6611         [scale_mid, cscale_mid, :scale_mid],
6612         [on_air, con_air, :on_air]].each do |func2, check2, name2|
6613          [[scale_by_two, cscale_by_two, :scale_by_two],
6614           [ramp_to_1, cramp_to_1, :ramp_to_1],
6615           [xramp_to_1, cxramp_to_1, :xramp_to_1],
6616           [scale_by_half, cscale_by_half, :scale_by_half],
6617           [scale_mid, cscale_mid, :scale_mid],
6618           [on_air, con_air, :on_air]].each do |func3, check3, name3|
6619            revert_sound
6620            set_to_1.call
6621            cset_to_1.call(data)
6622            func.call
6623            check.call(data)
6624            func1.call
6625            check1.call(data)
6626            func2.call
6627            check2.call(data)
6628            func3.call
6629            check3.call(data)
6630            snd_test_neq(channel2vct,
6631                         data,
6632                         "4 case %s (%s (%s (%s)))",
6633                         name3, name2, name1, name)
6634            snd_test_neq(rev_channel2vct.call,
6635                         data,
6636                         "4 rev case %s (%s (%s (%s)))",
6637                         name3, name2, name1, name)
6638          end
6639        end
6640      end
6641    end
6642    # 5 case
6643    [[scale_by_two, cscale_by_two, :scale_by_two],
6644     [ramp_to_1, cramp_to_1, :ramp_to_1],
6645     [xramp_to_1, cxramp_to_1, :xramp_to_1],
6646     [scale_by_half, cscale_by_half, :scale_by_half],
6647     [scale_mid, cscale_mid, :scale_mid],
6648     [on_air, con_air, :on_air]].each do |func, check, name|
6649      [[scale_by_two, cscale_by_two, :scale_by_two],
6650       [ramp_to_1, cramp_to_1, :ramp_to_1],
6651       [xramp_to_1, cxramp_to_1, :xramp_to_1],
6652       [scale_by_half, cscale_by_half, :scale_by_half],
6653       [scale_mid, cscale_mid, :scale_mid],
6654       [on_air, con_air, :on_air]].each do |func1, check1, name1|
6655        [[scale_by_two, cscale_by_two, :scale_by_two],
6656         [ramp_to_1, cramp_to_1, :ramp_to_1],
6657         [xramp_to_1, cxramp_to_1, :xramp_to_1],
6658         [scale_by_half, cscale_by_half, :scale_by_half],
6659         [scale_mid, cscale_mid, :scale_mid],
6660         [on_air, con_air, :on_air]].each do |func2, check2, name2|
6661          [[scale_by_two, cscale_by_two, :scale_by_two],
6662           [ramp_to_1, cramp_to_1, :ramp_to_1],
6663           [xramp_to_1, cxramp_to_1, :xramp_to_1],
6664           [scale_by_half, cscale_by_half, :scale_by_half],
6665           [scale_mid, cscale_mid, :scale_mid],
6666           [on_air, con_air, :on_air]].each do |func3, check3, name3|
6667            [[scale_by_two, cscale_by_two, :scale_by_two],
6668             [ramp_to_1, cramp_to_1, :ramp_to_1],
6669             [xramp_to_1, cxramp_to_1, :xramp_to_1],
6670             [scale_by_half, cscale_by_half, :scale_by_half],
6671             [scale_mid, cscale_mid, :scale_mid],
6672             [on_air, con_air, :on_air]].each do |func4, check4, name4|
6673              revert_sound
6674              set_to_1.call
6675              cset_to_1.call(data)
6676              func.call
6677              check.call(data)
6678              func1.call
6679              check1.call(data)
6680              func2.call
6681              check2.call(data)
6682              func3.call
6683              check3.call(data)
6684              func4.call
6685              check4.call(data)
6686              snd_test_neq(channel2vct,
6687                           data,
6688                           "5 case %s (%s (%s (%s (%s))))",
6689                           name4, name3, name2, name1, name)
6690              snd_test_neq(rev_channel2vct.call,
6691                           data,
6692                           "5 rev case %s (%s (%s (%s (%s))))",
6693                           name4, name3, name2, name1, name)
6694            end
6695          end
6696        end
6697      end
6698    end
6699    # 6 case
6700    [[scale_by_two, cscale_by_two, :scale_by_two],
6701     [ramp_to_1, cramp_to_1, :ramp_to_1],
6702     [xramp_to_1, cxramp_to_1, :xramp_to_1],
6703     [scale_by_half, cscale_by_half, :scale_by_half],
6704     [scale_mid, cscale_mid, :scale_mid],
6705     [on_air, con_air, :on_air]].each do |func, check, name|
6706      [[scale_by_two, cscale_by_two, :scale_by_two],
6707       [ramp_to_1, cramp_to_1, :ramp_to_1],
6708       [xramp_to_1, cxramp_to_1, :xramp_to_1],
6709       [scale_by_half, cscale_by_half, :scale_by_half],
6710       [scale_mid, cscale_mid, :scale_mid],
6711       [on_air, con_air, :on_air]].each do |func1, check1, name1|
6712        [[scale_by_two, cscale_by_two, :scale_by_two],
6713         [ramp_to_1, cramp_to_1, :ramp_to_1],
6714         [xramp_to_1, cxramp_to_1, :xramp_to_1],
6715         [scale_by_half, cscale_by_half, :scale_by_half],
6716         [scale_mid, cscale_mid, :scale_mid],
6717         [on_air, con_air, :on_air]].each do |func2, check2, name2|
6718          [[scale_by_two, cscale_by_two, :scale_by_two],
6719           [ramp_to_1, cramp_to_1, :ramp_to_1],
6720           [xramp_to_1, cxramp_to_1, :xramp_to_1],
6721           [scale_by_half, cscale_by_half, :scale_by_half],
6722           [scale_mid, cscale_mid, :scale_mid],
6723           [on_air, con_air, :on_air]].each do |func3, check3, name3|
6724            [[scale_by_two, cscale_by_two, :scale_by_two],
6725             [ramp_to_1, cramp_to_1, :ramp_to_1],
6726             [xramp_to_1, cxramp_to_1, :xramp_to_1],
6727             [scale_by_half, cscale_by_half, :scale_by_half],
6728             [scale_mid, cscale_mid, :scale_mid],
6729             [on_air, con_air, :on_air]].each do |func4, check4, name4|
6730              [[scale_by_two, cscale_by_two, :scale_by_two],
6731               [ramp_to_1, cramp_to_1, :ramp_to_1],
6732               [xramp_to_1, cxramp_to_1, :xramp_to_1],
6733               [scale_by_half, cscale_by_half, :scale_by_half],
6734               [scale_mid, cscale_mid, :scale_mid],
6735               [on_air, con_air, :on_air]].each do |func5, check5, name5|
6736                revert_sound
6737                set_to_1.call
6738                cset_to_1.call(data)
6739                func.call
6740                check.call(data)
6741                func1.call
6742                check1.call(data)
6743                func2.call
6744                check2.call(data)
6745                func3.call
6746                check3.call(data)
6747                func4.call
6748                check4.call(data)
6749                func5.call
6750                check5.call(data)
6751                snd_test_neq(channel2vct,
6752                             data,
6753                             "6 case %s (%s (%s (%s (%s (%s)))))",
6754                             name5, name4, name3, name2, name1, name)
6755                snd_test_neq(rev_channel2vct.call,
6756                             data,
6757                             "6 rev case %s (%s (%s (%s (%s (%s)))))",
6758                             name5, name4, name3, name2, name1, name)
6759              end
6760            end
6761          end
6762        end
6763      end
6764    end
6765  end
6766  close_sound(ind)
6767end
6768
6769def test_05_09
6770  ind = open_sound("oboe.snd")
6771  snd_test_neq(redo_edit(1, ind, 0), 0, "open redo_edit with no ops")
6772  snd_test_neq(undo_edit(1, ind, 0), 0, "open undo_edit with no ops")
6773  set_cursor(1000)
6774  delete_sample(321)
6775  snd_test_neq(cursor(), 999, "delete_sample before cursor")
6776  snd_test_neq(cursor(ind, 0, 0), 1000, "delete_sample before cursor (0)")
6777  undo_edit
6778  snd_test_neq(cursor(), 1000, "delete_sample after cursor undo")
6779  undo_edit(-1)
6780  snd_test_neq(cursor(), 999, "delete_sample before cursor redo")
6781  redo_edit(-1)
6782  delete_sample(1321)
6783  snd_test_neq(cursor(), 1000, "delete_sample after cursor")
6784  undo_edit
6785  delete_samples(0, 100)
6786  snd_test_neq(cursor(), 900, "delete_samples before cursor")
6787  undo_edit
6788  delete_samples(1100, 100)
6789  snd_test_neq(cursor(), 1000, "delete_samples after cursor")
6790  undo_edit
6791  insert_samples(100, 100, make_vct(100))
6792  snd_test_neq(cursor(), 1100, "insert_samples before cursor")
6793  undo_edit
6794  insert_samples(1100, 100, make_vct(100))
6795  snd_test_neq(cursor(), 1000, "insert_samples after cursor")
6796  undo_edit
6797  set_samples(0, 100, make_vct(100))
6798  snd_test_neq(cursor(), 1000, "set_samples cursor")
6799  set_show_axes(Show_x_axis_unlabelled, ind, 0)
6800  update_time_graph
6801  set_show_axes(Show_all_axes_unlabelled, ind, 0)
6802  update_time_graph
6803  close_sound(ind)
6804  #
6805  ind = new_sound("test.snd", :size, 100)
6806  vct2channel(Vct.new(3, 1.0), 10, 8)
6807  snd_test_neq(maxamp(ind, 0), 1.0, "vct2channel size mismatch maxamp")
6808  snd_test_neq(channel2vct(0, 20, ind, 0),
6809               vct(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
6810                   1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
6811               "vct2channel size mismatch")
6812  revert_sound(ind)
6813  set_samples(10, 5, Vct.new(3, 1.0))
6814  snd_test_neq(maxamp(ind, 0), 1.0, "set_samples size mismatch maxamp")
6815  snd_test_neq(channel2vct(0, 20, ind, 0),
6816               vct(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
6817                   1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
6818               "set_samples size mismatch")
6819  revert_sound(ind)
6820  insert_samples(10, 8, Vct.new(3, 1.0), ind, 0)
6821  snd_test_neq(maxamp(ind, 0), 1.0, "insert samples size mismatch maxamp")
6822  snd_test_neq(channel2vct(0, 20, ind, 0),
6823               vct(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
6824                   1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
6825               "insert samples size mismatch")
6826  close_sound(ind)
6827end
6828
6829def test_05_10
6830  ind = open_sound("oboe.snd")
6831  bnds = x_bounds(ind)
6832  xp = x_position_slider
6833  yp = y_position_slider
6834  xz = x_zoom_slider
6835  yz = y_zoom_slider
6836  snd_test_neq(snd_completion(" open-so"), " open-sound", "completion (1)")
6837  # XXX: Zoom_focus_right (constant) replaced with zoom_focus_style
6838  snd_test_neq(snd_completion(" zoom_focus_s"), " zoom_focus_style",
6839               "completion (2)")
6840  play("oboe.snd", :wait, true)
6841  play("oboe.snd", :start, 12000, :wait, true)
6842  play("oboe.snd", :start, 12000, :end, 15000, :wait, true)
6843  play(ind, :edit_position, edit_position - 1, :wait, true)
6844  old_speed = speed_control(ind)
6845  old_style = speed_control_style
6846  old_open = show_controls(ind)
6847  set_show_controls(true, ind)
6848  set_speed_control(-2.0, ind)
6849  play(ind, :start, 12345, :wait, true)
6850  set_speed_control_style(Speed_control_as_semitone)
6851  set_speed_control(0.5, ind)
6852  set_speed_control_style(Speed_control_as_ratio)
6853  set_speed_control(0.25, ind)
6854  set_speed_control(old_speed, ind)
6855  set_speed_control_style(old_style)
6856  set_show_controls(old_open, ind)
6857  k = disk_kspace("oboe.snd")
6858  if (not number?(k)) or k <= 0
6859    snd_display("disk_kspace = %s", k)
6860  end
6861  k = disk_kspace("/baddy/hiho")
6862  snd_test_neq(k, -1, "disk_kspace of bogus file")
6863  snd_test_neq(transform_framples, 0, "transform_framples")
6864  set_transform_size(512)
6865  set_transform_graph?(true)
6866  set_time_graph?(true)
6867  #
6868  Snd.catch(:all, lambda do |*args|
6869    snd_display("axis label error: %s", args)
6870  end) do
6871    snd_test_neq(x_axis_label(), "time", "def time x_axis_label")
6872    set_x_axis_label("no time", ind, 0, Time_graph)
6873    snd_test_neq(x_axis_label(), "no time", "set time x_axis_label")
6874    update_transform_graph
6875    snd_test_neq(x_axis_label(ind, 0, Transform_graph), "frequency",
6876                 "get fft x_axis_label")
6877    set_x_axis_label("hiho", ind, 0, Transform_graph)
6878    update_transform_graph
6879    snd_test_neq(x_axis_label(ind, 0, Transform_graph), "hiho",
6880                 "set fft x_axis_label")
6881    set_x_axis_label("frequency", ind, 0, Transform_graph) # for later test
6882    #
6883    graph([0, 0, 1, 1, 2, 0], "lisp")
6884    update_lisp_graph
6885    snd_test_neq(x_axis_label(ind, 0, Lisp_graph), "lisp",
6886                 "def lisp x_axis_label")
6887    set_x_axis_label("no lisp", ind, 0, Lisp_graph)
6888    snd_test_neq(x_axis_label(ind, 0, Lisp_graph), "no lisp",
6889                 "lisp x_axis_label")
6890    #
6891    set_y_axis_label("no amp", ind, 0, Time_graph)
6892    snd_test_neq(y_axis_label(), "no amp", "time y_axis_label")
6893    set_y_axis_label("no lamp", ind, 0, Lisp_graph)
6894    snd_test_neq(y_axis_label(ind, 0, Lisp_graph), "no lamp",
6895                 "lisp y_axis_label")
6896    set_y_axis_label(false)
6897    set_y_axis_label("no amp", ind, 0)
6898    snd_test_neq(y_axis_label(), "no amp", "time y_axis_label")
6899    set_y_axis_label(false, ind)
6900  end
6901  #
6902  cr = channel_widgets(ind, 0)[17]
6903  graph_data(make_vct(4), ind, 0, Copy_context, false, false, Graph_lines, cr)
6904  update_lisp_graph
6905  graph(vct(0, 0, 1, 1, 2, 0))
6906  32.times do
6907    graph(vct(0, 1, 2))
6908    graph([vct(0, 1, 2), vct(3, 2, 1), vct(1, 2, 3)])
6909    graph([vct(0, 1, 2), vct(3, 2, 1)])
6910  end
6911  set_x_bounds([0.0, 0.01])
6912  data = make_graph_data
6913  if vct?(data)
6914    snd_test_neq(right_sample - left_sample + 1,
6915                 data.length,
6916                 "make_graph_data bounds: %d %d",
6917                 left_sample,
6918                 right_sample)
6919    mid = (0.5 * data.length).round
6920    snd_test_neq(sample(left_sample + mid), data[mid],
6921                 "make_graph_data[%d]", mid)
6922  end
6923  data = make_graph_data(ind, 0, 0, 100, 199)
6924  if vct?(data)
6925    snd_test_neq(data.length, 100, "make_graph_data 100:199")
6926    snd_test_neq(sample(50), data[50], "make_graph_data 50")
6927  end
6928  set_x_bounds([0.0, 0.1])
6929  update_transform_graph
6930  Snd.catch(:no_such_axis, lambda do |*args|
6931    snd_display("transform axis not displayed?")
6932  end) do
6933    snd_test_neq(x_axis_label(ind, 0, Transform_graph), "frequency",
6934                 "def fft x_axis_label")
6935    set_x_axis_label("fourier", ind, 0, Transform_graph)
6936    snd_test_neq(x_axis_label(ind, 0, Transform_graph), "fourier",
6937                 "fft x_axis_label")
6938    set_x_axis_label("hiho")
6939    #
6940    set_y_axis_label("spectra", ind, 0, Transform_graph)
6941    snd_test_neq(y_axis_label(ind, 0, Transform_graph), "spectra",
6942                 "fft y_axis_label")
6943    set_y_axis_label("hiho")
6944  end
6945  #
6946  if number?(transform_framples) and transform_framples.zero?
6947    snd_display("transform_graph? transform-framples: %s?", trandform_framples)
6948  end
6949  update_transform_graph
6950  if (tag = Snd.catch do peaks("/baddy/hiho") end).first != :cant_open_file
6951    snd_display("peaks bad file: %s", tag.inspect)
6952  end
6953  peaks("tmp.peaks")
6954  pks_data = IO.readlines("tmp.peaks")
6955  if /Snd: fft peaks/ !~ pks_data[0]
6956    snd_display("peaks 1: %s", pks_data[0].inspect)
6957  end
6958  if /fft 512 points beginning at sample 0/ !~ pks_data[2]
6959    snd_display("peaks 2: %s", pks_data[2].inspect)
6960  end
6961  delete_file("tmp.peaks")
6962  peaks()
6963  if $with_test_motif
6964    if (not dialog_widgets[15]) or (not RXtIsManaged(dialog_widgets[15]))
6965      snd_display("peaks but no help?")
6966    end
6967  end
6968  dismiss_all_dialogs
6969  num_transforms = 6
6970  num_transform_graph_types = 3
6971  set_transform_graph?(true, ind, 0)
6972  set_transform_size(64, ind, 0)
6973  num_transforms.times do |i|
6974    set_transform_type(integer2transform(i))
6975    unless transform?(integer2transform(i))
6976      snd_display("transform? %d?", i)
6977    end
6978    num_transform_graph_types.times do |j|
6979      set_transform_graph_type(j, ind, 0)
6980      update_transform_graph(ind, 0)
6981    end
6982  end
6983  set_transform_type($fourier_transform)
6984  unless (res = transform?(transform_type))
6985    snd_display("transform? %s %s?", res, $fourier_transform)
6986  end
6987  unless transform?($autocorrelation)
6988    snd_display("transform? $autocorrelation")
6989  end
6990  if read_only(ind)
6991    snd_display("read_only open_sound: %s?", read_only(ind))
6992  end
6993  set_read_only(true, ind)
6994  unless read_only(ind)
6995    snd_display("set_read_only: %s?", read_only(ind))
6996  end
6997  a_ctr = 0
6998  bind_key(key_to_int(?a), 0, lambda do a_ctr = 3 end)
6999  key(key_to_int(?a), 0)
7000  snd_test_neq(a_ctr, 3, "bind_key")
7001  unbind_key(key_to_int(?a), 0)
7002  a_ctr = 0
7003  key(key_to_int(?a), 0)
7004  old_gstyle = graph_style
7005  5.times do |i|
7006    psf = eps_file
7007    if string?(psf)
7008      delete_file(psf)
7009      set_graph_style(i)
7010      graph2ps
7011      unless File.exist?(psf)
7012        snd_display("graph2ps: %s?", psf)
7013      end
7014      delete_file(psf)
7015    end
7016  end
7017  set_graph_style(old_gstyle)
7018  err = Snd.catch(:cannot_print, 12345) do graph2ps("/bad/bad.eps") end
7019  if err.first != 12345
7020    snd_display("graph2ps err: %s?", err.inspect)
7021  end
7022  n2 = open_sound("2.snd") or open_sound("4.aiff")
7023  set_transform_graph?(true, n2)
7024  [Channels_superimposed,
7025    Channels_combined,
7026    Channels_separate].each do |style|
7027    set_channel_style(style, n2)
7028    snd_test_neq(channel_style(n2), style, "channel_style")
7029    graph2ps("aaa.eps")
7030  end
7031  close_sound(n2)
7032  if channels(ind) == 1
7033    set_channel_style(Channels_superimposed, ind)
7034    snd_test_neq(channel_style(ind), Channels_separate, "channel_style[0]")
7035  end
7036  set_sync(32, ind)
7037  snd_test_neq(sync(ind), 32, "sunc->32")
7038  if (res = sync_max()) < 32
7039    snd_display("sync_max 32: %s?", res)
7040  end
7041  set_sync(0, ind)
7042  set_channel_sync(12, ind, 0)
7043  snd_test_neq(channel_sync(ind, 0), 12, "channel_sunc->12")
7044  set_channel_sync(0, ind, 0)
7045  snd_test_neq(a_ctr, 0, "unbind_key")
7046  snd_test_neq(xp, 0.0, "x_position_slider")
7047  snd_test_neq(yp, 0.0, "y_position_slider")
7048  if fneq(xz, 0.04338) and fneq(xz, 1.0)
7049    snd_display("x_zoom_slider: %s?", xz)
7050  end
7051  snd_test_neq(yz, 1.0, "y_zoom_slider")
7052  if (fneq(bnds[0], 0.0) or fneq(bnds[1], 0.1)) and
7053      (fneq(bnds[0], 0.0) or fneq(bnds[1], 2.305))
7054    snd_display("x_bounds: %s?", bnds)
7055  end
7056  snd_test_neq(find_sound("oboe.snd"), ind, "oboe: index")
7057  [[:sound?, true],
7058    [:chans, 1],
7059    [:channels, 1],
7060    [:framples, 50828],
7061    [:srate, 22050],
7062    [:data_location, 28],
7063    [:data_size, 50828 * 2],
7064    [:sample_type, Mus_bshort],
7065    [:maxamp, 0.14724],
7066    [:maxamp_position, 24971],
7067    [:comment, ""]].each do |func, val|
7068    snd_test_neq(snd_func(func, ind), val, "oboe")
7069  end
7070  snd_test_neq(short_file_name(ind), "oboe.snd", "oboe: short name")
7071  snd_test_neq(count_matches(lambda do |y| y > 0.125 end), 1314,
7072               "oboe: count_matches")
7073  snd_test_neq(count_matches(lambda do |y| y > 0.1 end), 2852,
7074               "oboe: unopt count_matches")
7075  spot = find_channel(lambda do |y| y > 0.13 end)
7076  if spot.kind_of?(FalseClass) or spot != 8862
7077    snd_display("find: %s?", spot)
7078  end
7079  set_right_sample(3000)
7080  if ((res = right_sample) - 3000).abs > 1
7081    snd_display("right_sample: %s?", res)
7082  end
7083  set_left_sample(1000)
7084  if ((res = left_sample) - 1000).abs > 1
7085    snd_display("left_sample: %s?", res)
7086  end
7087  eds = edits
7088  if eds[0].nonzero? or eds[1].nonzero?
7089    snd_display("edits: %s?", eds)
7090  end
7091  if edit_position != eds[0]
7092    snd_display("edit_position: %s %s?", edit_position, eds)
7093  end
7094  play(ind, :channel, 0, :wait, true)
7095  select_all(ind, 0)
7096  r0 = regions.first
7097  unless selection?
7098    snd_display("selection?")
7099  end
7100  unless region?(r0)
7101    snd_display("region?")
7102  end
7103  snd_test_neq(selection_chans, 1, "selection_chans (1)")
7104  snd_test_neq(selection_srate, srate(ind), "selection_srate")
7105  snd_test_neq(region_maxamp(r0), maxamp(ind), "region_maxamp (1)")
7106  snd_test_neq(region_maxamp_position(r0), maxamp_position(ind),
7107               "region_maxamp_position (1)")
7108  snd_test_neq(selection_maxamp(ind, 0), maxamp(ind), "selection_maxamp (1)")
7109  snd_test_neq(selection_maxamp_position(ind, 0), maxamp_position(ind),
7110               "selection_maxamp_position (1)")
7111  save_region(r0, "temp.dat")
7112  if File.exist?("temp.dat")
7113    File.unlink("temp.dat")
7114  else
7115    snd_display("save_region file disappeared?")
7116  end
7117  play(r0, :wait, true)   # needs to be true here or it never gets run
7118  if Snd.regions.length != 1
7119    snd_display("regions: %s", regions)
7120  end
7121  unless (res = selection_member?(ind))
7122    snd_display("selection_member?: %s?", res)
7123  end
7124  [[:region_srate, 22050],
7125   [:region_chans, 1],
7126   [:region_framples, 50828],
7127   [:region_home, ["oboe.snd", 0, 50827]]].each do |func, req|
7128    snd_test_neq(snd_func(func, r0), req, "%s", func)
7129  end
7130  snd_test_neq(selection_framples, 50828, "selection_framples")
7131  snd_test_neq(selection_position, 0, "selection_position")
7132  snd_test_neq(region_position(r0, 0), 0, "region_position")
7133  snd_test_neq(region_maxamp(r0), maxamp(ind), "region_maxamp (2)")
7134  snd_test_neq(selection_maxamp(ind, 0), maxamp(ind), "selection_maxamp (2)")
7135  [[:region_srate, 22050],
7136   [:region_chans, 1],
7137   [:region_framples, 50828],
7138   [:region_maxamp, maxamp(ind)]].each do |func, req|
7139    snd_test_neq(snd_func(func, r0), req, "%s", func)
7140  end
7141  samps1 = channel2vct(0, 50827, ind, 0)
7142  samps2 = region2vct(r0, 0, 50828, 0)
7143  rd = make_sampler(0, ind, 0, 1)
7144  unless sampler?(rd)
7145    snd_display("%s not sampler?", rd)
7146  end
7147  snd_test_neq(sampler_position(rd), 0, "initial sampler_position")
7148  snd_test_neq(sampler_home(rd), [ind, 0], "sampler_home")
7149  if sampler_at_end?(rd)
7150    snd_display("%s init at end?", rd)
7151  end
7152  if (res = Snd.catch do region2vct(r0, -1, 1233) end).first != :no_such_sample
7153    snd_display("region2vct -1: %s", res.inspect)
7154  end
7155  if res = Snd.catch do region2vct(r0, 12345678, 1) end.first
7156    snd_display("region2vct 12345678: %s", res.inspect)
7157  end
7158  snd_test_neq(rd.to_s,
7159               "#<sampler: oboe.snd[0: 0] from 0, at 0, forward>",
7160               "sampler actually got %s", rd.to_s)
7161  erd = rd
7162  snd_test_neq(erd, rd, "sampler equal?")
7163  50827.times do |i|
7164    val = (i % 2).nonzero? ? next_sample(rd) : read_sample(rd)
7165    if val != samps1[i] or val != samps2[i]
7166      snd_display("readers disagree at %s (%s %s %s)",
7167                  i, val, samps1[i], samps2[i])
7168      break
7169    end
7170  end
7171  free_sampler(rd)
7172  if (res = Snd.catch do make_sampler(0, ind, -1) end).first != :no_such_channel
7173    snd_display("make_sampler bad chan -1: %s?", res.inspect)
7174  end
7175  if (res = Snd.catch do make_sampler(0, ind, 1) end).first != :no_such_channel
7176    snd_display("make_sampler bad chan 1: %s?", res.inspect)
7177  end
7178  fd = make_sampler(0)
7179  if mix_sampler?(fd)
7180    snd_display("sampler: mix %s?", fd)
7181  end
7182  if region_sampler?(fd)
7183    snd_display("sampler: region %s?", fd)
7184  end
7185  unless sampler?(fd)
7186    snd_display("sampler: normal %s?", fd)
7187  end
7188  snd_test_neq(sampler_position(fd), 0, "sampler: position")
7189  free_sampler(fd)
7190  snd_test_neq(fd.to_s[-16, 16], "at eof or freed>", "freed sampler")
7191  reg = regions.first
7192  chns = region_chans(reg)
7193  if (res = Snd.catch do
7194        make_region_sampler(reg, 0, chans + 1)
7195      end).first != :no_such_channel
7196    snd_display("make_region_sampler bad chan (2): %s %s", res.inspect, regions)
7197  end
7198  if (res = Snd.catch do
7199        make_region_sampler(reg, 0, 0, -2)
7200      end).first != :no_such_direction
7201    snd_display("make_region_sampler bad dir (-2): %s", res.inspect)
7202  end
7203  revert_sound(ind)
7204  insert_sample(100, 0.5, ind)
7205  res = Snd.catch do insert_sound("oboe.snd", 0, 1) end
7206  if res.first != :no_such_channel
7207    snd_display("insert_sound bad chan (1): %s", res.inspect)
7208  end
7209  if (res = Snd.catch do insert_sample(-12, 1.0) end).first != :no_such_sample
7210    snd_display("insert_sample bad pos: %s", res.inspect)
7211  end
7212  set_show_axes(Show_no_axes, ind, 0)
7213  update_transform_graph(ind)
7214  update_time_graph(ind)
7215  snd_test_neq(sample(100), 0.5, "insert_sample (100)")
7216  snd_test_neq(framples(ind), 50829, "insert_sample (framples)")
7217  v0 = Array.new(3, 0.25)
7218  v1 = make_vct(3, 0.75)
7219  insert_samples(200, 3, v0, ind)
7220  insert_samples(300, 3, v1, ind)
7221  snd_test_neq(sample(201), 0.25, "insert_samples (201)")
7222  snd_test_neq(sample(301), 0.75, "insert_samples (301)")
7223  snd_test_neq(framples(ind), 50835, "insert_samples (framples)")
7224  save_sound_as("hiho.snd", ind, 22050, Mus_bshort, Mus_next)
7225  nind = view_sound("hiho.snd")
7226  snd_test_neq(sample(101, nind), sample(101, ind), "save_sound_as")
7227  unless read_only(nind)
7228    snd_display("read_only view_sound: %s?", read_only(nind))
7229  end
7230  set_speed_control_style(Speed_control_as_semitone, nind)
7231  snd_test_neq(speed_control_style(nind), Speed_control_as_semitone,
7232               "speed_control_style set semi")
7233  set_speed_control_tones(-8, nind)
7234  snd_test_neq(speed_control_tones(nind), 12, "speed_control_tones -8")
7235  set_speed_control_tones(18, nind)
7236  snd_test_neq(speed_control_tones(nind), 18, "speed_control_tones 18")
7237  graph2ps("aaa.eps")
7238  close_sound(nind)
7239  revert_sound(ind)
7240  #
7241  set_sample(50, 0.5, ind)
7242  snd_test_neq(sample(50), 0.5, "set_sample")
7243  set_samples(60, 3, Array.new(3, 0.25), ind)
7244  snd_test_neq(sample(60), 0.25, "set_samples (60)")
7245  snd_test_neq(sample(61), 0.25, "set_samples (61)")
7246  set_samples(10, 3, [0.1, 0.2, 0.3], ind)
7247  snd_test_neq(channel2vct(10, 3, ind), vct(0.1, 0.2, 0.3),
7248               "set_samples via list")
7249  revert_sound(ind)
7250  save_sound_as("temporary.snd", ind)
7251  set_samples(100000, 20000, "temporary.snd", ind)
7252  snd_test_neq(channel2vct(110000, 10), channel2vct(10000, 10),
7253               "set_samples to self")
7254  revert_sound(ind)
7255  delete_file("temporary.snd")
7256  delete_sample(100, ind)
7257  snd_test_neq(framples(ind), 50827, "delete_sample")
7258  delete_samples(0, 100, ind)
7259  snd_test_neq(framples(ind), 50727, "delete_samples")
7260  revert_sound(ind)
7261  maxa = maxamp(ind)
7262  scale_to(0.5, ind)
7263  newmaxa = maxamp(ind)
7264  snd_test_neq(newmaxa, 0.5, "scale_to")
7265  undo_edit(1, ind)
7266  scale_by(2.0, ind)
7267  newmaxa = maxamp(ind)
7268  snd_test_neq(newmaxa, 2.0 * maxa, "scale_by")
7269  revert_sound(ind)
7270  scale_by(-1, ind)
7271  mix("oboe.snd")
7272  snd_test_neq(maxamp(ind, 0), 0.0, "invert+mix")
7273  revert_sound(ind)
7274  select_all(ind)
7275  if regions.length != 2
7276    snd_display("regions (2): %s", regions)
7277  end
7278  scale_selection_to(0.5)
7279  newmaxa = maxamp(ind)
7280  snd_test_neq(newmaxa, 0.5, "scale_selection_to")
7281  revert_sound(ind)
7282  select_all(ind)
7283  scale_selection_by(2.0)
7284  newmaxa = maxamp(ind)
7285  snd_test_neq(newmaxa, 2.0 * maxa, "scale_selection_by")
7286  revert_sound(ind)
7287  select_all(ind)
7288  rread = make_region_sampler(regions.first, 0)
7289  sread = make_sampler(0, ind)
7290  rvect = region2vct(regions.first, 0, 100)
7291  svect = samples(0, 100, ind)
7292  snd_test_neq(region_sample(regions.first, 1), rvect[1], "region_sample")
7293  100.times do |i|
7294    rval = next_sample(rread)
7295    sval = next_sample(sread)
7296    snd_test_neq(rval, sval, "sample_read")
7297    snd_test_neq(rval, rvect[i], "region_samples")
7298    snd_test_neq(sval, svect[i], "samples")
7299  end
7300  free_sampler(rread)
7301  val0 = next_sample(sread)
7302  if sampler_at_end?(sread)
7303    snd_display("premature end?")
7304  end
7305  previous_sample(sread)
7306  val1 = previous_sample(sread)
7307  snd_test_neq(val0, val1, "previous_sample")
7308  free_sampler(rread)
7309  revert_sound(ind)
7310  s100 = sample(100)
7311  s40 = sample(40)
7312  len = framples
7313  addlen = mus_sound_framples("fyow.snd")
7314  old_csize = cursor_size
7315  old_cstyle = cursor_style
7316  set_cursor_style(Cursor_line)
7317  set_cursor_size(25)
7318  set_cursor(50, ind)
7319  snd_test_neq(cursor_style, Cursor_line, "cursor_style")
7320  snd_test_neq(cursor_size, 25, "cursor_size")
7321  set_cursor_style(Cursor_cross)
7322  set_cursor_size(15)
7323  set_cursor(30, ind, 0)
7324  set_cursor_style(Cursor_line)
7325  set_cursor_size(20)
7326  set_cursor(20, ind, 0)
7327  if $with_test_gui
7328    set_cursor_style(lambda do |snd, chn, ax|
7329      x, y = cursor_position
7330      size = (cursor_size / 2.0).round
7331      cr = channel_widgets(snd, chn)[17]
7332      draw_line(x - size, y - size, x + size, y + size,
7333                snd, chn, Cursor_context, cr)
7334      draw_line(x - size, y + size, x + size, y - size,
7335                snd, chn, Cursor_context, cr)
7336    end, ind, 0)
7337    unless proc?(res = cursor_style(ind, 0))
7338      snd_display("set_cursor_style to Proc: %s", res)
7339    end
7340  end
7341
7342  set_cursor_size(old_csize)
7343  set_cursor_style(old_cstyle)
7344  set_cursor(50, ind)
7345  insert_sound("fyow.snd", cursor, 0, ind, 0)
7346  ss100 = sample(100)
7347  snd_test_neq(sample(40), s40, "insert_sound s40")
7348  snd_test_eq(ss100, s100, "insert_sound s100")
7349  snd_test_neq(ss100, 0.001831, "insert_sound")
7350  snd_test_neq(framples, addlen + len, "insert_sound len")
7351  save_sound_as("not-temporary.snd")
7352  insert_samples(0, 100, "not-temporary.snd")
7353  set_cursor(framples(ind, 0, 0) - 2, ind, 0, 0)
7354  revert_sound
7355  snd_test_neq(cursor(ind, 0), framples(ind, 0, 0) - 2,
7356               "set edpos cursor %s", cursor)
7357  delete_file("not-temporary.snd")
7358  id = make_region(0, 99)
7359  insert_region(id, 60, ind)
7360  snd_test_neq(framples, len + 100, "insert_region len")
7361  snd_test_neq(sample(100), s40, "insert_region")
7362  if (res = Snd.catch do
7363        regmax = if regions
7364                   regions.map do |r| region2integer(r) end.max + 1000
7365                 else
7366                   1000
7367                 end
7368        insert_region(integer2region(regmax), 0)
7369      end).first != :no_such_region
7370    snd_display("insert_region bad id: %s", res.inspect)
7371  end
7372  save_region(id, "fmv.snd")
7373  region_srate(id)
7374  region_chans(id)
7375  region_framples(id)
7376  [[:mus_sound_header_type, Mus_next],
7377   [:mus_sound_sample_type, Mus_out_format],
7378   [:mus_sound_srate, region_srate(id)],
7379   [:mus_sound_chans, region_chans(id)],
7380   [:mus_sound_framples, region_framples(id)]].each do |func, req|
7381    snd_test_neq(snd_func(func, "fmv.snd"), req, "save_region (1) %s", func)
7382  end
7383  if region_position(id, 0).nonzero?
7384    snd_display("save_region position: %s", region_position(id, 0))
7385  end
7386  delete_file("fmv.snd")
7387  save_region(id, "fmv.snd", Mus_lshort, Mus_riff, "this is a comment")
7388  [[:mus_sound_header_type, Mus_riff],
7389   [:mus_sound_sample_type, Mus_lshort],
7390   [:mus_sound_comment, "this is a comment"],
7391   [:mus_sound_framples, region_framples(id)]].each do |func, req|
7392    snd_test_neq(snd_func(func, "fmv.snd"), req, "save_region (2) %s", func)
7393  end
7394  delete_file("fmv.snd")
7395  save_region(id,
7396              :file, "fmv.snd",
7397              :header_type, Mus_riff,
7398              :sample_type, Mus_lshort,
7399              :comment, "this is a comment")
7400  [[:mus_sound_header_type, Mus_riff],
7401   [:mus_sound_sample_type, Mus_lshort],
7402   [:mus_sound_comment, "this is a comment"],
7403   [:mus_sound_framples, region_framples(id)]].each do |func, req|
7404    snd_test_neq(snd_func(func, "fmv.snd"), req,
7405                 "save_region opt (3) %s", func)
7406  end
7407  delete_file("fmv.snd")
7408  save_region(id,
7409              :comment, "this is a comment",
7410              :file, "fmv.snd",
7411              :sample_type, Mus_lshort,
7412              :header_type, Mus_riff)
7413  [[:mus_sound_header_type, Mus_riff],
7414   [:mus_sound_sample_type, Mus_lshort],
7415   [:mus_sound_comment, "this is a comment"],
7416   [:mus_sound_framples, region_framples(id)]].each do |func, req|
7417    snd_test_neq(snd_func(func, "fmv.snd"), req,
7418                 "save_region opt1 (4) %s", func)
7419  end
7420  delete_file("fmv.snd")
7421  save_region(id, "fmv.snd", :sample_type, Mus_bshort)
7422  [[:mus_sound_header_type, Mus_next],
7423   [:mus_sound_sample_type, Mus_bshort],
7424   [:mus_sound_framples, region_framples(id)]].each do |func, req|
7425    snd_test_neq(snd_func(func, "fmv.snd"), req,
7426                 "save_region opt2 (5) %s", func)
7427  end
7428  delete_files("fmv.snd", "aaa.eps")
7429  close_sound(ind)
7430end
7431
7432def test_05_11
7433  res = Snd.catch do new_sound("hi.snd", :channels, 0) end
7434  if res.first != :out_of_range
7435    snd_display("new_sound bad chan: %s?", res)
7436  end
7437  #
7438  ind = new_sound("fmv.snd", 2, 22050, Mus_ldouble, Mus_next, "unequal lens")
7439  insert_silence(0, 1000, ind, 1)
7440  res1 = framples(ind, 0)
7441  res2 = framples(ind, 1)
7442  if res1 != 1 or res2 != 1001
7443    snd_test_neq(res1, 1, "silence 1")
7444    snd_test_neq(res2, 1001, "silence 1 (1001")
7445  end
7446  save_sound(ind)
7447  if (res1 = framples(ind, 0)) != 1001 or (res2 = framples(ind, 1)) != 1001
7448    snd_display("saved silence 1: %s %s?", res1, res2)
7449  end
7450  if (res = mus_sound_framples("fmv.snd")) != 1001
7451    snd_display("saved framples silence 1: %s?", res)
7452  end
7453  v0 = channel2vct(0, 1000, ind, 0)
7454  v1 = channel2vct(0, 1000, ind, 1)
7455  if fneq(vct_peak(v0), 0.0)
7456    snd_display("auto-pad 0: %s?", vct_peak(v0))
7457  end
7458  if fneq(vct_peak(v1), 0.0)
7459    snd_display("silence 0: %s?", vct_peak(v1))
7460  end
7461  close_sound(ind)
7462  delete_file("fmv.snd")
7463  #
7464  ind = new_sound("fmv.snd", 2, 22050, Mus_bshort, Mus_next, "unequal lens")
7465  pad_channel(0, 1000, ind, 1)
7466  if (res1 = framples(ind, 0)) != 1 or (res2 = framples(ind, 1)) != 1001
7467    snd_display("silence: %s %s?", res1, res2)
7468  end
7469  v0 = channel2vct(0, 1000, ind, 0)
7470  v1 = channel2vct(0, 1000, ind, 1)
7471  if fneq(vct_peak(v0), 0.0)
7472    snd_display("pad 0: %s?", vct_peak(v0))
7473  end
7474  if fneq(vct_peak(v1), 0.0)
7475    snd_display("pad 1: %s?", vct_peak(v1))
7476  end
7477  map_channel($init_channel, 0, 2, ind, 0)
7478  map_channel($init_channel, 0, 1002, ind, 1)
7479  pad_channel(0, 1000, ind, 0, 1)
7480  if (res = framples(ind, 1)) != 1002
7481    snd_display("pad_channel ed 1: %s?", res)
7482  end
7483  close_sound(ind)
7484  delete_file("fmv.snd")
7485  #
7486  ind = new_sound("fmv.snd", 1, 22050, Mus_bshort, Mus_ircam,
7487                  "this is a comment")
7488  v0 = make_vct(128)
7489  v0[64] = 0.5
7490  v0[127] = 0.5
7491  vct2samples(0, 128, v0, ind, 0)
7492  make_selection(0, 126)
7493  smooth_selection
7494  v0 = channel2vct(0, 128, ind, 0)
7495  if fneq(sample(127), 0.5) or fneq(sample(120), 0.4962) or
7496      fneq(sample(32), 0.07431) or fneq(sample(64), 0.25308)
7497    snd_display("smooth_selection: %s?", v0)
7498  end
7499  revert_sound(ind)
7500  vct_fill!(v0, 0.0)
7501  v0[10] = 0.5
7502  vct2channel(v0)
7503  select_all
7504  old_sw = sinc_width
7505  set_sinc_width(40)
7506  src_selection(0.5)
7507  v0 = channel2vct(0, 128, ind, 0)
7508  if fneq(sample(20), 0.5) or
7509    fneq(sample(30), 0.0) or
7510    fneq(sample(17), -0.1057)
7511    snd_display("src_selection: %s?", v0)
7512  end
7513  unselect_all
7514  if selection_member?
7515    snd_display("unselect_all but still a selection?")
7516  end
7517  unselect_all
7518  revert_sound(ind)
7519  set_sinc_width(old_sw)
7520  vct_fill!(v0, 0.0)
7521  v0[10] = 0.5
7522  vct2channel(v0, 0)
7523  select_all
7524  filter_selection([0, 0, 0.1, 1, 1, 0], 40)
7525  v0 = channel2vct(0, 128, ind, 0)
7526  if fneq(sample(29), 0.1945) or
7527    fneq(sample(39), -0.0137) or
7528    fneq(sample(24), -0.01986)
7529    snd_display("filter_selection: %s?", v0)
7530  end
7531  revert_sound(ind)
7532  vct_fill!(v0, 1.0)
7533  vct2channel(v0)
7534  select_all
7535  filter_selection(make_one_zero(:a0, 0.5, :a1, 0.0))
7536  v0 = channel2vct(0, 128, ind, 0)
7537  if fneq(sample(29), 0.5) or
7538    fneq(sample(39), 0.5) or
7539    fneq(sample(24), 0.5)
7540    snd_display("filter_selection one_zero: %s?", v0)
7541  end
7542  revert_sound(ind)
7543  vct_fill!(v0, 1.0)
7544  vct2channel(v0)
7545  delete_file("fmv5.snd")
7546  select_all
7547  env_selection([0, 0, 1, 1, 2, 0], 1.0)
7548  v0 = channel2vct(0, 128, ind, 0)
7549  if fneq(sample(64), 1.0) or
7550    fneq(sample(20), 0.3125) or
7551    fneq(sample(119), 0.127)
7552    snd_display("env_selection: %s?", v0)
7553  end
7554  save_selection("fmv5.snd", 22050, Mus_bint, Mus_next, "")
7555  revert_sound(ind)
7556  #
7557  res = Snd.catch do file2array("/baddy/hiho", 0, 0, 128, v0) end
7558  if res.first != :no_such_file
7559    snd_display("file2array w/o file: %s", res.inspect)
7560  end
7561  res = Snd.catch do file2array("fmv5.snd", 123, 0, 128, v0) end
7562  if res.first != :no_such_channel
7563    snd_display("file2array w/o channel: %s", res.inspect)
7564  end
7565  file2array("fmv5.snd", 0, 0, 128, v0)
7566  if fneq(v0[64], 1.0) or fneq(v0[20], 0.3125) or fneq(v0[119], 0.127)
7567    snd_display("save_selection: %s %s %s %s?", v0[64], v0[20], v0[119], v0)
7568  end
7569  if (res = mus_sound_sample_type("fmv5.snd")) != Mus_bint
7570    snd_display("save_selection type: %s?", mus_sample_type_name(res))
7571  end
7572  if (res = mus_sound_header_type("fmv5.snd")) != Mus_next
7573    snd_display("save_selection format: %s?", mus_header_type_name(res))
7574  end
7575  if (res = mus_sound_srate("fmv5.snd")) != 22050
7576    snd_display("save_selection srate: %s?", res)
7577  end
7578  vct_fill!(v0, 0.0)
7579  v0[100] = 0.5
7580  v0[2] = -0.5
7581  vct2channel(v0)
7582  select_all
7583  Snd.catch do reverse_selection end
7584  save_selection("fmv4.snd", 44100, Mus_lfloat, Mus_riff, "this is a comment")
7585  v0 = channel2vct(0, 128, ind, 0)
7586  if fneq(sample(27), 0.5) or fneq(sample(125), -0.5)
7587    snd_display("reverse_selection: %s?", v0)
7588  end
7589  file2array("fmv4.snd", 0, 0, 128, v0)
7590  if fneq(sample(27), 0.5) or fneq(sample(125), -0.5)
7591    snd_display("save reverse_selection: %s?", v0)
7592  end
7593  if (res = mus_sound_header_type("fmv4.snd")) != Mus_riff
7594    snd_display("save_selection type 1: %s", mus_header_type_name(res))
7595  end
7596  if (res = mus_sound_sample_type("fmv4.snd")) != Mus_lfloat
7597    snd_display("save_selection format 1: %s", mus_sample_type_name(res))
7598  end
7599  if (res = mus_sound_srate("fmv4.snd")) != 44100
7600    snd_display("save_selection srate 1: %s", res)
7601  end
7602  if (res = mus_sound_comment("fmv4.snd")) != "this is a comment"
7603    snd_display("save_selection comment: %s", res)
7604  end
7605  delete_file("fmv4.snd")
7606  #
7607  save_selection(:file, "fmv4.snd",
7608                 :header_type, Mus_riff,
7609                 :sample_type, Mus_lfloat,
7610                 :srate, 44100,
7611                 :comment, "this is a comment")
7612  if (res = mus_sound_header_type("fmv4.snd")) != Mus_riff
7613    snd_display("save_selection opt type 1: %s", mus_header_type_name(res))
7614  end
7615  if (res = mus_sound_sample_type("fmv4.snd")) != Mus_lfloat
7616    snd_display("save_selection opt format 1: %s", mus_sample_type_name(res))
7617  end
7618  if (res = mus_sound_srate("fmv4.snd")) != 44100
7619    snd_display("save_selection opt srate 1: %s", res)
7620  end
7621  if (res = mus_sound_comment("fmv4.snd")) != "this is a comment"
7622    snd_display("save_selection opt comment: %s", res)
7623  end
7624  delete_file("fmv4.snd")
7625  #
7626  save_selection(:file, "fmv4.snd", :sample_type, Mus_bfloat, :channel, 0)
7627  res = mus_sound_header_type("fmv4.snd")
7628  if res != Mus_next and res != Mus_ircam
7629    snd_display("save_selection opt1 type 1: %s", mus_header_type_name(res))
7630  end
7631  if (res = mus_sound_sample_type("fmv4.snd")) != Mus_bfloat
7632    snd_display("save_selection opt1 format 1: %s", mus_sample_type_name(res))
7633  end
7634  if (res = mus_sound_chans("fmv4.snd")) != 1
7635    snd_display("save_selection opt1 chans: %s", res)
7636  end
7637  delete_file("fmv4.snd")
7638  revert_sound(ind)
7639  vct_fill!(v0, 0.0)
7640  v0[2] = 1.0
7641  v1 = make_vct(256)
7642  128.times do |i| v1[i] = v0[i] end
7643  vct2channel(v1)
7644  select_all
7645  if mus_clipping
7646    set_mus_clipping(false)
7647  end
7648  if clipping
7649    set_clipping(false)
7650  end
7651  convolve_selection_with("fmv5.snd", 0.5)
7652  v0 = channel2vct(0, 128, ind, 0)
7653  if fneq(sample(66), -0.5)
7654    snd_display("convolve_selection_with: %s %s %s?", v0[66], sample(66), v0)
7655  end
7656  close_sound(ind)
7657  delete_file("fmv.snd")
7658end
7659
7660def test_05_12
7661  obind = open_sound("oboe.snd")
7662  vol = maxamp(obind)
7663  dur = framples
7664  set_amp_control(2.0, obind)
7665  snd_test_neq(amp_control(obind), 2.0, "set_amp_control")
7666  reset_controls(obind)
7667  snd_test_neq(amp_control(obind), 1.0, "set_amp_control")
7668  set_amp_control_bounds([0.0, 4.0], obind)
7669  snd_test_neq(amp_control_bounds(obind), [0.0, 4.0], "amp_control_bounds")
7670  set_amp_control(2.0, obind)
7671  if (res = Snd.catch do apply_controls(obind) end).first == :no_such_sound
7672    snd_display("apply_controls: cannot find oboe.snd? %s", res.inspect)
7673  end
7674  newamp = maxamp(obind)
7675  if fneq_err(2.0 * vol, newamp, 0.05)
7676    snd_display("apply amp: %s -> %s?", vol, newamp)
7677  end
7678  set_amp_control_bounds([0.0, 8.0], obind)
7679  set_speed_control_bounds([1.0, 5.0], obind)
7680  snd_test_neq(speed_control_bounds(obind), [1.0, 5.0], "speed_control_bounds")
7681  set_speed_control(0.5, obind)
7682  set_speed_control_bounds([0.05, 20.0], obind)
7683  add_mark(1234)
7684  apply_controls(obind)
7685  newdur = framples(obind)
7686  set_speed_control(1.0, obind)
7687  unless newdur - 2.0 * dur < 256
7688    snd_display("apply speed: %s -> %s?", dur, newdur)
7689  end
7690  set_contrast_control?(true, obind)
7691  set_contrast_control_bounds([0.5, 2.5], obind)
7692  snd_test_neq(contrast_control_bounds(obind), [0.5, 2.5],
7693               "contrast_control_bounds")
7694  set_contrast_control(1.0, obind)
7695  apply_controls(obind)
7696  set_contrast_control_bounds([0.0, 10.0], obind)
7697  snd_test_neq(contrast_control_bounds(obind), [0.0, 10.0],
7698               "contrast_control_bounds (2)")
7699  secamp = maxamp(obind)
7700  secdur = framples(obind)
7701  snd_test_neq(secamp, 0.989, "apply contrast")
7702  snd_test_neq(secdur, newdur, "apply contrast length")
7703  undo_edit(3, obind)
7704  set_reverb_control?(true, obind)
7705  set_reverb_control_scale_bounds([0.0, 1.0], obind)
7706  snd_test_neq(reverb_control_scale_bounds(obind), [0.0, 1.0],
7707               "reverb_control_scale_bounds")
7708  set_reverb_control_length_bounds([0.0, 2.0], obind)
7709  snd_test_neq(reverb_control_length_bounds(obind), [0.0, 2.0],
7710               "reverb_control_length_bounds")
7711  set_reverb_control_scale(0.2, obind)
7712  apply_controls(obind)
7713  revamp = maxamp(obind)
7714  revdur = framples(obind)
7715  snd_test_any_neq(revamp, 0.214, :ffequal?, "apply reverb scale")
7716  unless revdur - ((reverb_control_decay * 22050.0).round + 50828) < 256
7717    snd_display("apply reverb length: %s?", revdur)
7718  end
7719  undo_edit(1, obind)
7720  set_expand_control?(true, obind)
7721  set_expand_control_bounds([1.0, 3.0], obind)
7722  snd_test_neq(expand_control_bounds(obind), [1.0, 3.0],
7723               "expand_control_bounds")
7724  set_expand_control(1.5, obind)
7725  apply_controls(obind)
7726  expamp = maxamp(obind)
7727  expdur = framples(obind)
7728  if fneq_err(expamp, 0.152, 0.05)
7729    snd_display("apply expand_control scale: %s?", expamp)
7730  end
7731  if expdur <= 1.25 * 50828
7732    snd_display("apply expand_control length: %s?", expdur)
7733  end
7734  set_expand_control_bounds([0.001, 20.0], obind)
7735  undo_edit(1, obind)
7736  set_filter_control?(true, obind)
7737  set_filter_control_order(40, obind)
7738  set_filter_control_envelope([0.0, 0.0, 1.0, 0.5, 2.0, 0.0], obind)
7739  apply_controls(obind)
7740  fltamp = maxamp(obind)
7741  fltdur = framples(obind)
7742  snd_test_gt((fltamp - 0.02).abs, 0.005, "apply filter scale")
7743  snd_test_gt(fltdur - (40 + 50828), 256, "apply filter length")
7744  undo_edit(1, obind)
7745  #
7746  revert_sound(obind)
7747  make_selection(1000, 1000)
7748  scale_selection_to(0.1)
7749  scale_selection_by(2.0)
7750  make_selection(2000, 2001)
7751  scale_selection_by(2.0)
7752  scale_selection_to(0.5)
7753  make_selection(1000, 2001)
7754  scale_selection_to(0.5)
7755  scale_selection_by(0.5)
7756  make_selection(2000, 2000)
7757  scale_selection_by(2.0)
7758  scale_selection_to(0.5)
7759  make_selection(1000, 1001)
7760  scale_selection_to(0.1)
7761  scale_selection_by(2.0)
7762  make_selection(999, 2002)
7763  scale_selection_to(1.0)
7764  scale_selection_by(0.5)
7765  tree = edit_tree
7766  tr_tree = [[0, 0, 0, 998, 1.0, 0.0, 0.0, 0],
7767             [999, 0, 999, 999, 0.999969720840454, 0.0, 0.0, 0],
7768             [1000, 0, 1000, 1000, 6.09052181243896, 0.0, 0.0, 0],
7769             [1001, 0, 1001, 1001, 0.999969720840454, 0.0, 0.0, 0],
7770             [1002, 0, 1002, 1999, 0.499984979629517, 0.0, 0.0, 0],
7771             [2000, 0, 2000, 2000, 7.54652404785156, 0.0, 0.0, 0],
7772             [2001, 0, 2001, 2001, 3.7732629776001, 0.0, 0.0, 0],
7773             [2002, 0, 2002, 2002, 0.999969720840454, 0.0, 0.0, 0],
7774             [2003, 0, 2003, 50827, 1.0, 0.0, 0.0, 0],
7775             [50828, -2, 0, 0, 0.0, 0.0, 0.0, 0]]
7776  unless snd_test_neq(tree.length, tr_tree.length,
7777                      "edit trees are not same length")
7778    tree.each_with_index do |branch, i|
7779      tr_branch = tr_tree[i]
7780      5.times do |j|
7781        snd_test_neq(branch[j], tr_branch[j],
7782                     "edit trees disagree at [%d][%d]", i, j)
7783      end
7784    end
7785  end
7786  insert_silence(1001, 8)
7787  insert_silence(900, 50)
7788  insert_silence(2005, 1)
7789  insert_silence(999, 2)
7790  tree = edit_tree
7791  tr_tree = [[0, 0, 0, 899, 1.0, 0.0, 0.0, 0],
7792             [900, -1, 0, 49, 0.0, 0.0, 0.0, 0],
7793             [950, 0, 900, 948, 1.0, 0.0, 0.0, 0],
7794             [999, -1, 0, 1, 0.0, 0.0, 0.0, 0],
7795             [1001, 0, 949, 998, 1.0, 0.0, 0.0, 0],
7796             [1051, 0, 999, 999, 0.999969720840454, 0.0, 0.0, 0],
7797             [1052, 0, 1000, 1000, 6.09052181243896, 0.0, 0.0, 0],
7798             [1053, -1, 0, 7, 0.0, 0.0, 0.0, 0],
7799             [1061, 0, 1001, 1001, 0.999969720840454, 0.0, 0.0, 0],
7800             [1062, 0, 1002, 1946, 0.499984979629517, 0.0, 0.0, 0],
7801             [2007, -1, 0, 0, 0.0, 0.0, 0.0, 0],
7802             [2008, 0, 1947, 1999, 0.499984979629517, 0.0, 0.0, 0],
7803             [2061, 0, 2000, 2000, 7.54652404785156, 0.0, 0.0, 0],
7804             [2062, 0, 2001, 2001, 3.7732629776001, 0.0, 0.0, 0],
7805             [2063, 0, 2002, 2002, 0.999969720840454, 0.0, 0.0, 0],
7806             [2064, 0, 2003, 50827, 1.0, 0.0, 0.0, 0],
7807             [50889, -2, 0, 0, 0.0, 0.0, 0.0, 0]]
7808  unless snd_test_neq(tree.length, tr_tree.length,
7809                      "silenced edit trees are not same length")
7810    tree.each_with_index do |branch, i|
7811      tr_branch = tr_tree[i]
7812      5.times do |j|
7813        snd_test_neq(branch[j], tr_branch[j],
7814                     "silenced edit trees disagree at [%d][%d]", i, j)
7815      end
7816    end
7817  end
7818  snd_test_neq(vct(sample(998), sample(999), sample(1000), sample(1001)),
7819               vct(-0.03, 0.0, 0.0, -0.03),
7820               "insert_silence [999 for 2]")
7821  snd_test_neq(vct(sample(2006), sample(2007), sample(2008)),
7822               vct(-0.033, 0.0, -0.033),
7823               "insert_silence [2007 for 1]")
7824  revert_sound(obind)
7825  add_mark(1200, obind, 0)
7826  mark_num = marks(obind, 0).length
7827  scale_by(2.0, obind, 0)
7828  mark_now = marks(obind, 0).length
7829  snd_test_neq(mark_num, mark_now, "mark lost after scaling")
7830  set_selection_position(0)
7831  set_selection_framples(100)
7832  scale_selection_to(0.5)
7833  mark_now = marks(obind, 0).length
7834  snd_test_neq(mark_num, mark_now, "mark lost after scaling scaling")
7835  m1 = add_mark(1000)
7836  set_cursor(100, obind, 0)
7837  key(key_to_int(?u), 4, obind)
7838  key(key_to_int(?1), 0, obind)
7839  key(key_to_int(?0), 0, obind)
7840  key(key_to_int(?0), 0, obind)
7841  key(key_to_int(?o), 4, obind)
7842  snd_test_neq(mark_sample(m1), 1100, "mark after zeros")
7843  set_cursor(0, obind)
7844  key(key_to_int(?j), 4, obind)
7845  snd_test_neq(cursor(obind), 1100, "C-j")
7846  add_mark(100)
7847  set_cursor(0, obind)
7848  key(key_to_int(?u), 4, obind)
7849  key(key_to_int(?2), 0, obind)
7850  key(key_to_int(?j), 4, obind)
7851  snd_test_neq(cursor(obind), 1100, "C-u 2 C-j")
7852  key(key_to_int(?-), 4, obind)
7853  key(key_to_int(?j), 4, obind)
7854  snd_test_neq(cursor(obind), 100, "C-- C-j")
7855  revert_sound(obind)
7856  frs = framples(obind)
7857  make_region(0, 999, obind, 0)
7858  unless selection?
7859    snd_display("make_region but no selection? %s", selection?)
7860  end
7861  delete_selection
7862  snd_test_neq(framples(obind), frs - 1000, "delete_selection")
7863  val = sample(0, obind, 0)
7864  undo_edit
7865  snd_test_neq(sample(1000), val, "delete_selection val")
7866  insert_selection
7867  res = Snd.catch do insert_selection(0, obind, 123) end
7868  if res.first != :no_such_channel
7869    snd_display("insert_selection bad chan: %s?", res.inspect)
7870  end
7871  res = Snd.catch do mix_selection(0, obind, 123) end
7872  if res.first != :no_such_channel
7873    snd_display("mix_selection bad chan: %s?", res.inspect)
7874  end
7875  snd_test_neq(framples(obind), frs + 1000, "insert_selection")
7876  snd_test_neq(sample(2000), val, "insert_selection val")
7877  val = sample(900)
7878  mix_selection
7879  snd_test_neq(sample(900), val * 2.0, "mix_selection val")
7880  snd_test_neq(framples(obind), frs + 1000, "mix_selection len")
7881  close_sound(obind)
7882end
7883
7884Apply_to_sound, Apply_to_channel, Apply_to_selection = [0, 1, 2]
7885
7886def test_05_13
7887  ind = open_sound("2.snd")
7888  len = framples(ind)
7889  len2 = len * 2
7890  len4 = len * 4
7891  set_sync(1, ind)
7892  set_speed_control(0.5, ind)
7893  apply_controls(ind, Apply_to_sound)             # temp 1
7894  snd_test_gt((framples() - len2).abs, 256, "apply srate 0.5")
7895  make_selection(0, framples())
7896  set_speed_control(0.5, ind)
7897  apply_controls(ind, Apply_to_selection)         # temp 2
7898  snd_test_gt((framples() - len4).abs, 256, "apply srate 0.5 to selection")
7899  env_sound([0, 0, 1, 1], 0, framples(), 32.0)    # temp 3
7900  reg = select_all()                              # make multi_channel region
7901  insert_region(reg, 0)                           # temp 4
7902  insert_selection(0)                             # temp 5
7903  revert_sound(ind)
7904  #
7905  set_speed_control(0.5)
7906  set_sync(0, ind)
7907  set_selected_channel(ind, 1)
7908  apply_controls(ind, Apply_to_channel)
7909  snd_test_gt((framples(ind, 1) - len2).abs, 256, "apply srate 0.5 to chan 1")
7910  snd_test_neq(framples(ind, 0), len, "apply srate 0.5 but chan 0")
7911  set_speed_control(0.5, ind)
7912  apply_controls(ind, Apply_to_sound, 1000)
7913  make_selection(2000, 4000)
7914  set_speed_control(0.5, ind)
7915  apply_controls(ind, Apply_to_selection)
7916  set_selected_channel(ind, false)
7917  snd_test_neq(selected_channel(ind), false, "selected_channel false")
7918  close_sound(ind)
7919  #
7920  ind1 = open_sound("oboe.snd")
7921  mx1 = maxamp(ind1, 0)
7922  ind2 = open_sound("2.snd")
7923  mx20 = maxamp(ind2, 0)
7924  mx21 = maxamp(ind2, 1)
7925  select_sound(ind1)
7926  scale_sound_by(2.0)
7927  snd_test_neq(maxamp(ind1, 0), 2.0 * mx1, "scale_sound_by 2.0")
7928  res = edit_fragment(1, ind1, 0)
7929  req = ["scale_channel(2.000, 0, false", "scale", 0, 50828]
7930  snd_test_neq(res, req, "scale_sound_by")
7931  scale_sound_to(0.5)
7932  snd_test_neq(maxamp(ind1, 0), 0.5, "scale_sound_to 0.5")
7933  res = edit_fragment(2, ind1, 0)
7934  req = ["scale_channel(1.698, 0, false", "scale", 0, 50828]
7935  snd_test_neq(res, req, "scale_sound_to")
7936  scale_sound_by(0.0, 0, 1000, ind1, 0)
7937  snd_test_neq(maxamp(ind1, 0), 0.5, "scale_sound_by 0.0")
7938  res = edit_fragment(3, ind1, 0)
7939  req = ["scale_channel(0.000, 0, 1000", "scale", 0, 1000]
7940  snd_test_neq(res, req, "scale_sound_by 0.0")
7941  res = channel2vct(0, 1000, ind1, 0).peak
7942  snd_test_neq(res, 0.0, "0:0 scale_sound_by 0.0 [0:1000]")
7943  revert_sound(ind1)
7944  oldv = channel2vct(12000, 10, ind1, 0)
7945  scale_sound_by(2.0, 12000, 10, ind1, 0)
7946  newv = channel2vct(12000, 10, ind1, 0)
7947  10.times do |i|
7948    snd_test_neq(oldv[i] * 2.0, newv[i], "scale %d", i)
7949  end
7950  res = edit_fragment(1, ind1, 0)
7951  req = ["scale_channel(2.000, 12000, 10", "scale", 12000, 10]
7952  snd_test_neq(res, req, "scale_sound_by 2.0 [12000:10]")
7953  revert_sound(ind1)
7954  #
7955  select_sound(ind2)
7956  scale_sound_by(2.0)
7957  snd_test_neq(maxamp(ind2, 0), 2.0 * mx20, "2:0 scale_sound_by 2.0")
7958  snd_test_neq(maxamp(ind2, 1), 2.0 * mx21, "2:1 scale_sound_by 2.0")
7959  scale_sound_to(0.5)
7960  res = [maxamp(ind2, 0), maxamp(ind2, 1)].max
7961  snd_test_neq(res, 0.5, "2 scale_sound_to 0.5")
7962  scale_sound_by(0.0, 0, 1000, ind2, 1)
7963  res = edit_fragment(3, ind2, 1)
7964  req = ["scale_channel(0.000, 0, 1000", "scale", 0, 1000]
7965  snd_test_neq(res, req, "2:1 scale_sound_by 0.0")
7966  res = channel2vct(0, 1000, ind2, 1).peak
7967  snd_test_neq(res, 0.0, "2:1 scale_sound_by 0.0 [0:1000]")
7968  revert_sound(ind2)
7969  oldv = channel2vct(12000, 10, ind2, 0)
7970  scale_sound_by(2.0, 12000, 10, ind2, 0)
7971  newv = channel2vct(12000, 10, ind2, 0)
7972  10.times do |i|
7973    snd_test_neq(oldv[i] * 2.0, newv[i], "2 scale %d", i)
7974  end
7975  revert_sound(ind2)
7976  #
7977  set_sync(3, ind2)
7978  set_sync(3, ind1)
7979  scale_sound_by(2.0)
7980  snd_test_neq(maxamp(ind1, 0), mx1, "sync scale_sound_by 2.0")
7981  snd_test_neq(maxamp(ind2, 0), 2.0 * mx20, "2:0 sync scale_sound_by 2.0")
7982  snd_test_neq(maxamp(ind2, 1), 2.0 * mx21, "2:1 sync scale_sound_by 2.0")
7983  scale_sound_to(1.0, 20000, 40000, ind2, 1)
7984  snd_test_neq(maxamp(ind1, 0), mx1, "sync scale_sound_to 1.0")
7985  snd_test_neq(maxamp(ind2, 0), 2.0 * mx20, "2:0 sync scale_sound_to 1.0")
7986  snd_test_neq(maxamp(ind2, 1), 1.0, "2:1 sync scale_sound_to 1.0")
7987  close_sound(ind1)
7988  close_sound(ind2)
7989end
7990
7991def test_05_14
7992  ind = open_sound("now.snd")
7993  unless $snd_opened_sound.eql?(ind)
7994    snd_display("$snd_opened_sound: %s %s?", $snd_opened_sound, ind)
7995  end
7996  set_amp_control(0.5, ind)
7997  if fneq(res = amp_control(ind), 0.5)
7998    snd_display("amp_control (0.5): %s?", res)
7999  end
8000  set_amp_control(0.25, ind, 0)
8001  if fneq(res = amp_control(ind), 0.5)
8002    snd_display("amp_control after local set (0.5): %s?", res)
8003  end
8004  if fneq(res = amp_control(ind, 0), 0.25)
8005    snd_display("amp_control 0 (0.25): %s?", res)
8006  end
8007  set_amp_control(1.0, ind)
8008  if fneq(res = amp_control(ind), 1.0)
8009    snd_display("amp_control after local set (1.0): %s?", res)
8010  end
8011  if fneq(res = amp_control(ind, 0), 0.25)
8012    snd_display("amp_control 0 after set (0.25): %s?", res)
8013  end
8014  #
8015  set_transform_graph?(true, ind, 0)
8016  set_transform_graph_type(Graph_as_sonogram, ind, 0)
8017  update_transform_graph(ind, 0)
8018  res = transform_framples(ind, 0)
8019  if (not list?(res)) or
8020    fneq(res.car, 1.0) or
8021    res.caddr != 256
8022    snd_display("transform_framples: %s (%s)?",
8023                res.inspect, transform_size(ind, 0))
8024  end
8025  close_sound(ind)
8026  #
8027  ind = open_sound("4.aiff")
8028  if fneq(res = amp_control(ind), 1.0)
8029    snd_display("amp_control upon open (1.0): %s?", res)
8030  end
8031  if fneq(res = amp_control(ind, 2), 1.0)
8032    snd_display("amp_control 2 upon open (1.0): %s?", res)
8033  end
8034  set_amp_control(0.5, ind)
8035  if fneq(res = amp_control(ind, 2), 0.5)
8036    snd_display("amp_control 2 after global set (0.5): %s?", res)
8037  end
8038  set_amp_control(0.25, ind, 2)
8039  if fneq(res = amp_control(ind, 2), 0.25)
8040    snd_display("amp_control 2 (0.25): %s?", res)
8041  end
8042  after_ran = false
8043  $after_apply_controls_hook.reset_hook!
8044  $after_apply_controls_hook.add_hook!("snd-test") do |snd|
8045    after_ran = snd
8046  end
8047  apply_controls(ind)
8048  unless ind.eql?(after_ran)
8049    snd_display("$after_apply_controls_hook: %s?", after_ran)
8050  end
8051  $after_apply_controls_hook.reset_hook!
8052  revert_sound(ind)
8053  set_sync(1, ind)
8054  scale_to(vct(0.1, 0.2))
8055  mx = maxamp(ind, true)
8056  if fneq(mx[0], 0.1) or
8057    fneq(mx[1], 0.2) or
8058    fneq(mx[2], 0.2) or
8059    fneq(mx[3], 0.2)
8060    snd_display("scale_to with vector: %s?", mx)
8061  end
8062  set_filter_control_envelope([0, 0, 1, 1], ind)
8063  if [0.0, 0.0, 1.0, 1.0] != filter_control_envelope(ind)
8064    snd_display("set_filter_control_envelope: %s?",
8065                filter_control_envelope(ind))
8066  end
8067  set_filter_control_order(20, ind)
8068  unless vequal(res = filter_control_coeffs(ind),
8069                vct(-0.007, 0.010, -0.025, 0.029, -0.050, 0.055, -0.096,
8070                    0.109, -0.268, 0.241, 0.241, -0.268, 0.109, -0.096,
8071                    0.055, -0.050, 0.029, -0.025, 0.010, -0.007))
8072    snd_display("highpass coeffs: %s?", res)
8073  end
8074  set_filter_control_envelope(filter_control_envelope(ind), ind)
8075  if [0.0, 0.0, 1.0, 1.0] != filter_control_envelope(ind)
8076    snd_display("set_filter_control_envelope to self: %s?",
8077                filter_control_envelope(ind))
8078  end
8079  set_filter_control_envelope([0, 1, 1, 0], ind)
8080  unless vequal(res = filter_control_coeffs(ind),
8081                vct(0.003, 0.002, 0.004, 0.002, 0.007, 0.003, 0.014, 0.012,
8082                    0.059, 0.394, 0.394, 0.059, 0.012, 0.014, 0.003, 0.007,
8083                    0.002, 0.004, 0.002, 0.003))
8084    snd_display("lowpass coeffs: %s?", res)
8085  end
8086  close_sound(ind)
8087end
8088
8089def test_05_15
8090  obind = open_sound("4.aiff")
8091  amps = maxamp(obind, true)
8092  snd_test_neq(maxamp_position(obind, true), [810071, 810071, 810071, 810071],
8093               "4.aiff times")
8094  if window_width < 600
8095    set_window_width(600)
8096  end
8097  if window_height < 600
8098    set_window_height(600)
8099  end
8100  set_x_bounds([0.0, 0.1], obind, 0)
8101  set_show_axes(Show_x_axis, obind, 0)
8102  update_time_graph
8103  set_amp_control(0.1, obind)
8104  select_channel(2)
8105  res = Snd.catch do apply_controls(obind, 1) end
8106  if res.first == :no_such_sound
8107    snd_display("apply_controls cannot find 4.aiff: %s?", res.inspect)
8108  end
8109  newamps = maxamp(obind, true)
8110  if fneq(amps[0], newamps[0]) or
8111      fneq(amps[1], newamps[1]) or
8112      fneq_err(0.1 * amps[2], newamps[2], 0.05) or
8113      fneq(amps[3], newamps[3])
8114    snd_display(snd_format_neq(newamps, amps, "apply amps"))
8115  end
8116  undo_edit(1, obind, 2)
8117  set_amp_control(0.1, obind)
8118  make_region(0, framples(obind), obind, 1)
8119  Snd.catch do apply_controls(obind, 2) end
8120  newamps = maxamp(obind, true)
8121  if fneq(amps[0], newamps[0]) or
8122      fneq_err(0.1 * amps[1], newamps[1], 0.05) or
8123      fneq(amps[2], newamps[2]) or
8124      fneq(amps[3], newamps[3])
8125    snd_display(snd_format_neq(newamps, amps, "apply selection amps"))
8126  end
8127  #
8128  if $with_test_gui
8129    axinfo = axis_info(obind, 0, Time_graph)
8130    losamp, hisamp, x0, y0, x1, y1 = axinfo[0, 6]
8131    xpos = x0 + 0.5 * (x1 - x0.to_f)
8132    ypos = y0 + 0.75 * (y1 - y0.to_f)
8133    select_channel(0)
8134    set_cursor(100, obind)
8135    xy = cursor_position(obind)
8136    snd_test_neq(position2x(xy[0]), cursor(obind).to_f / srate(obind),
8137                 "cursor_position %s", xy[0])
8138    snd_test_neq(position2x(x2position(xpos)), xpos, "x<->position")
8139    if ((res = position2y(y2position(ypos))) - ypos).abs > 0.5
8140      snd_display(snd_format(res, ypos, "y<->position"))
8141    end
8142    snd_test_neq(left_sample(obind, 0), losamp, "axis_info[0 losamp]")
8143    snd_test_neq(right_sample(obind, 0), hisamp, "axis_info[1 hisamp]")
8144    snd_test_neq(axinfo[6], 0.0, "axis_info[6 xmin]")
8145    snd_test_neq(axinfo[7], -1.0, "axis_info[7 ymin]")
8146    snd_test_neq(axinfo[9], 1.0, "axis_info[9 ymax]")
8147    res = our_x2position(obind, x0)
8148    if (res[0] - res[1]).abs > 1
8149      snd_display(snd_format_neq(res[0], res[1], "x0->position"))
8150    end
8151    res = our_x2position(obind, x1)
8152    if (res[0] - res[1]).abs > 1
8153      snd_display(snd_format_neq(res[0], res[1], "x1->position"))
8154    end
8155    res = our_x2position(obind, 0.5 * (x0 + x1))
8156    if (res[0] - res[1]).abs > 1
8157      snd_display(snd_format_neq(res[0], res[1], "xmid->position"))
8158    end
8159    if $clmtest.zero?
8160      cp_x = lambda do |x|
8161        (axinfo[10] +
8162         ((x - x0.to_f) *
8163          ((axinfo[12] - axinfo[10].to_f) / (x1 - x0.to_f)))).floor
8164      end
8165      cp_y = lambda do |y|
8166        (axinfo[13] +
8167         ((y1.to_f - y) *
8168          ((axinfo[11] - axinfo[13].to_f) / (y1 - y0.to_f)))).floor
8169      end
8170      if ((res1 = x2position(xpos)) - (res2 = cp_x.call(xpos))).abs > 1
8171        snd_display(snd_format_neq(res2, res1, "cp_x 0.5"))
8172      end
8173      if ((res1 = y2position(ypos)) - (res2 = cp_y.call(ypos))).abs > 1
8174        snd_display(snd_format_neq(res2, res1, "cp_y 0.75"))
8175      end
8176      10.times do |i|
8177        xxpos = x0 + random(x1 - x0)
8178        yypos = y0 + random(y1 - y0)
8179        if ((res1 = x2position(xxpos)) - (res2 = cp_x.call(xxpos))).abs > 1
8180          snd_display(snd_format_neq(res2, res1, "cp_x[%d] %1.4f", i, xxpos))
8181        end
8182        if ((res1 = y2position(yypos)) - (res2 = cp_y.call(yypos))).abs > 1
8183          snd_display(snd_format_neq(res2, res1, "cp_y[%d] %1.4f", i, yypos))
8184        end
8185        snd_test_neq(position2x(cp_x.call(xxpos)), xxpos,
8186                     "x2position cp_x[%d]", i)
8187        snd_test_any_neq(position2y(cp_y.call(yypos)), yypos, :fffequal?,
8188                         "y2position cp_y[%d]", i)
8189      end
8190    end
8191    old_samp = left_sample(obind, 0)
8192    set_left_sample(1234, obind, 0)
8193    snd_test_neq(axis_info(obind, 0)[0], 1234, "axis_info[0 losamp at 1234]")
8194    set_left_sample(old_samp, obind, 0)
8195    axinfo = axis_info(obind, 0)
8196    x0 = axinfo[2]
8197    x1 = axinfo[4]
8198    res = our_x2position(obind, x0)
8199    if (res[0] - res[1]).abs > 1
8200      snd_display("x0a->position: %s?", res)
8201    end
8202    res = our_x2position(obind, x1)
8203    if (res[0] - res[1]).abs > 1
8204      snd_display("x1a->position: %s?", res)
8205    end
8206    res = our_x2position(obind, 0.5 * (x0 + x1))
8207    if (res[0] - res[1]).abs > 1
8208      snd_display("xmida->position: %s?", res)
8209    end
8210    set_y_bounds([-2.0, 3.0], obind, 0)
8211    snd_test_neq(axis_info(obind, 0)[7], -2.0, "axis_info[7 ymin]")
8212    snd_test_neq(axis_info(obind, 0)[9], 3.0, "axis_info[9 ymax]")
8213  end
8214  #
8215  close_sound(obind)
8216end
8217
8218def test_05_16
8219  ind1 = open_sound("oboe.snd")
8220  test_orig(lambda { |snd| src_sound(2.0, 1.0, snd) },
8221            lambda { |snd| src_sound(0.5, 1.0, snd) },
8222            "src_sound(2.0, 1.0, snd)",
8223            ind1)
8224  test_orig(lambda { |snd| src_channel(2.0) },
8225            lambda { |snd| src_channel(0.5) },
8226            "src_channel(2.5)",
8227            ind1)
8228  test_orig(lambda { |snd| scale_by(2.0, snd) },
8229            lambda { |snd| scale_by(0.5, snd) },
8230            "scale_by(2.0, snd)",
8231            ind1)
8232  test_orig(lambda { |snd| scale_channel(2.0) },
8233            lambda { |snd| scale_channel(0.5) },
8234            "scale_channel(2.0)",
8235            ind1)
8236  test_orig(lambda { |snd| reverse_sound(snd) },
8237            lambda { |snd| reverse_sound(snd) },
8238            "reverse_sound(snd)",
8239            ind1)
8240  test_orig(lambda { |snd| reverse_channel() },
8241            lambda { |snd| reverse_channel() },
8242            "reverse_channel()",
8243            ind1)
8244  test_orig(lambda { |snd| env_sound([0, 1.0, 1, 2.0]) },
8245            lambda { |snd| env_sound([0, 1.0, 1, 0.5]) },
8246            "env_sound([0, 1.0, 1, 2.0])",
8247            ind1)
8248  test_orig(lambda { |snd| env_sound([0, 1.0, 1, 2.0, 2, 1.0]) },
8249            lambda { |snd| env_sound([0, 1.0, 1, 0.5, 2, 1.0]) },
8250            "env_sound([0, 1.0, 1, 2.0, 2, 1.0])",
8251            ind1)
8252  test_orig(lambda { |snd|
8253        env_channel(make_env([0, 1.0, 1, 2.0], :length, framples(snd)))
8254      },
8255      lambda { |snd|
8256              env_channel(make_env([[0, 1.0], [1, 0.5]], :length, framples(snd)))
8257      }, "env_channel(make_env([0, 1.0, 1, 2.0]))", ind1)
8258  test_orig(lambda { |snd| env_channel([0, 1.0, 1, 2.0]) },
8259            lambda { |snd| env_channel([0, 1.0, 1, 0.5]) },
8260            "env_channel([0, 1.0, 1, 2.0])",
8261            ind1)
8262  test_orig(lambda { |snd|
8263              env_channel(make_env([0, 2, 1, 2, 2, 0.5, 3, 0.5],
8264                                   :base, 0, :length, framples(snd)))
8265            },
8266            lambda { |snd|
8267              env_channel(make_env([0, 0.5, 1, 0.5, 2, 2, 3, 2],
8268                                   :base, 0, :length, framples(snd)))
8269            },
8270            "env_channel(make_env([0, 2, 1, 2, 2, 0.5, 3, 0.5]))",
8271            ind1)
8272  test_orig(lambda { |snd| map_channel(lambda { |y| y * 2.0 }) },
8273            lambda { |snd| map_channel(lambda { |y| y * 0.5 }) },
8274            "map_channel(lambda { |y| y * 2.0 })",
8275            ind1)
8276  test_orig(lambda { |snd| map_channel(lambda { |y| y * 2.0 }, 1234) },
8277            lambda { |snd| map_channel(lambda { |y| y * 0.5 }, 1234) },
8278            "map_channel(lambda { |y| y * 2.0 }, 1234)",
8279            ind1)
8280  test_orig(lambda { |snd| map_channel(lambda { |y| y * 2.0 }, 12005, 10) },
8281            lambda { |snd| map_channel(lambda { |y| y * 0.5 }, 12005, 10) },
8282            "map_channel(lambda { |y| y * 2.0 }, 12005, 10)",
8283            ind1)
8284  outp = false
8285  test_orig(lambda { |snd| map_channel(lambda { |y| vct(y * 2.0, y * 2.0) }) },
8286            lambda { |snd| map_channel(lambda { |y|
8287    outp = (outp ? false : y * 0.5)
8288  }) },
8289            "map_channel(lambda { |y| vct(y * 2.0, y * 2.0) })",
8290            ind1)
8291  test_orig(lambda { |snd| map_chan(lambda { |y| y * 2.0 }) },
8292            lambda { |snd| map_chan(lambda { |y| y * 0.5 }) },
8293            "map_chan(lambda { |y| y * 2.0 })",
8294            ind1)
8295  test_orig(lambda { |snd| pad_channel(1000, 2000, snd) },
8296            lambda { |snd| delete_samples(1000, 2000, snd) },
8297            "pad_channel(1000, 2000, snd)",
8298            ind1)
8299  test_orig(lambda { |snd| clm_channel(make_one_zero(:a0, 2.0, :a1, 0.0)) },
8300            lambda { |snd| clm_channel(make_one_zero(:a0, 0.5, :a1, 0.0)) },
8301            "clm_channel(make_one_zero)",
8302            ind1)
8303  test_orig(lambda { |snd| clm_channel(make_one_pole(:a0, 2.0, :b1, 0.0)) },
8304            lambda { |snd| clm_channel(make_one_pole(:a0, 0.5, :b1, 0.0)) },
8305            "clm_channel(make_one_pole)",
8306            ind1)
8307  test_orig(lambda { |snd| filter_sound(make_one_zero(:a0, 2.0, :a1, 0.0),
8308                                        2, snd, 0) },
8309            lambda { |snd| filter_sound(make_one_zero(:a0, 0.5, :a1, 0.0),
8310                                        2, snd, 0) },
8311            "filter_sound(make_one_zero)",
8312            ind1)
8313  if (res = Snd.catch do src_sound([0, 0, 1, 1]) end).first != :out_of_range
8314    snd_display("src_sound env at 0: %s", res.inspect)
8315  end
8316  if (res = Snd.catch do src_sound([0, 1, 1, -1]) end).first != :out_of_range
8317    snd_display("src_sound env through 0: %s", res.inspect)
8318  end
8319  #
8320  scale_to(1.0, ind1)
8321  v0 = make_vct(10)
8322  v1 = channel2vct(12000, 10, ind1, 0)
8323  v0[0] = 1.0
8324  array2file("fmv3.snd", v0, 10, 22050, 1)
8325  file_copy("oboe.snd", "fmv4.snd")
8326  convolve_with("fmv3.snd", 1.0, ind1)
8327  convolve_files("fmv4.snd", "fmv3.snd", 1.0, "fmv5.snd")
8328  v2 = channel2vct(12000, 10, ind1, 0)
8329  snd_test_any_neq(v2, v1, :vfequal?, "convolve_with (orig 0)")
8330  file2array("fmv5.snd", 0, 12000, 10, v2)
8331  snd_test_any_neq(v2, v1, :vfequal?, "convolve_files (orig 0)")
8332  delete_files("fmv3.snd", "fmv5.snd")
8333  convolve_files("2.snd", "oboe.snd", 0.5, "fmv5.snd")
8334  res = mus_sound_maxamp("fmv5.snd")
8335  snd_test_neq(res[1], 0.25, "convolve_files stereo (1)")
8336  snd_test_neq(res[3], 0.50, "convolve_files stereo (2)")
8337  delete_file("fmv5.snd")
8338  scale_to(0.25, ind1)
8339  set_y_bounds([], ind1)
8340  if $with_test_gui
8341    snd_test_neq(y_bounds(ind1), [-0.25, 0.25], "y_bounds []")
8342  end
8343  revert_sound(ind1)
8344  #
8345  scale_to(1.0, ind1)
8346  v0 = make_vct(10)
8347  v1 = channel2vct(12000, 10, ind1, 0)
8348  v0[5] = 1.0
8349  array2file("fmv3.snd", v0, 10, 22050, 1)
8350  convolve_with("fmv3.snd", 1.0, ind1)
8351  convolve_files("fmv4.snd", "fmv3.snd", 1.0, "fmv5.snd")
8352  v2 = channel2vct(12005, 10, ind1, 0)
8353  snd_test_any_neq(v2, v1, :vfequal?, "convolve_with (orig 2)")
8354  file2array("fmv5.snd", 0, 12005, 10, v2)
8355  snd_test_any_neq(v2, v1, :vfequal?, "convolve_files (orig 2)")
8356  delete_files("fmv3.snd", "fmv4.snd", "fmv5.snd")
8357  revert_sound(ind1)
8358  #
8359  old_val = selection_creates_region
8360  old_regions = regions
8361  set_selection_creates_region(false)
8362  select_all(ind1)
8363  set_selection_creates_region(old_val)
8364  unless old_regions.eql?(regions)
8365    snd_display("selection_creates_region: %s -> %s", old_regions, regions)
8366  end
8367  convolve_selection_with("pistol.snd", maxamp)
8368  data = channel2vct(12000, 10, ind1, 0)
8369  convolve_with("pistol.snd", maxamp(ind1, 0, 0), ind1, 0, 0)
8370  new_data = channel2vct(12000, 10, ind1, 0)
8371  snd_test_any_neq(new_data, data, :vfequal?, "convolve_selection_with")
8372  revert_sound(ind1)
8373  #
8374  make_selection(1000, 2000, ind1)
8375  ma = maxamp(ind1)
8376  convolve_selection_with("pistol.snd", ma)
8377  if fneq(maxamp(ind1), ma)
8378    snd_display("convolve_selection_with 1000: %s %s?", ma, maxamp(ind1))
8379  end
8380  make_selection(1000, 2000, ind1)
8381  id = make_region
8382  unless region?(id)
8383    snd_display("make_region argless: %s?", id)
8384  end
8385  if (res1 = region_framples(id, 0)) != (res2 = selection_framples)
8386    snd_display("region/selection_framples: %s %s (%s)?",
8387                res1, res2, region_framples(id))
8388  end
8389  if (res1 = region_sample(id, 0)) != (res2 = sample(1000, ind1))
8390    snd_display("region_sample from make_region: %s %s?", res1, res2)
8391  end
8392  close_sound(ind1)
8393end
8394
8395def test_05_17
8396  ind = open_sound("2.snd")
8397  reg = make_region(0, 100, ind, true)
8398  if (res = region_home(reg)) != ["2.snd", 0, 100]
8399    snd_display("make + region_home: %s?", res)
8400  end
8401  if (res = region_chans(reg)) != 2
8402    snd_display("make_region chan true: %s", res)
8403  end
8404  close_sound(ind)
8405  #
8406  ind = open_sound("2.snd")
8407  v0 = channel2vct(12000, 10, ind, 0)
8408  v1 = channel2vct(12000, 10, ind, 1)
8409  swap_channels(ind)
8410  v2 = channel2vct(12000, 10, ind, 0)
8411  v3 = channel2vct(12000, 10, ind, 1)
8412  if vequal(v0, v2) or vequal(v1, v3)
8413    snd_display("swap_channels 0: no change!\n# %s\n# %s\n# %s\n# %s",
8414                v0, v2, v1, v3)
8415  end
8416  swap_channels(ind)
8417  v2 = channel2vct(12000, 10, ind, 0)
8418  v3 = channel2vct(12000, 10, ind, 1)
8419  unless vequal(v0, v2) or vequal(v1, v3)
8420    snd_display("swap_channels 1: \n# %s\n# %s\n# %s\n# %s",
8421                v0, v2, v1, v3)
8422  end
8423  set_cursor(100, ind, 0)
8424  set_cursor(200, ind, 1)
8425  if (res0 = cursor(ind, 0)) != 100 or
8426    (res1 = cursor(ind, 1)) != 200
8427    snd_display("cursor: %s %s?", res0, res1)
8428  end
8429  set_sync(1, ind)
8430  scale_by([0.5, 0.25], ind)
8431  scale_by(vct(2.0, 4.0), ind)
8432  revert_sound(ind)
8433  amps = maxamp(ind, true)
8434  swap_channels(ind, 0, ind)
8435  newamps = maxamp(ind, true)
8436  if fneq(amps[0], newamps[1]) or
8437    fneq(amps[1], newamps[0])
8438    snd_display("swap_channels with cp def: %s %s?", amps, newamps)
8439  end
8440  swap_channels(ind, 1)
8441  newamps = maxamp(ind, true)
8442  if fneq(amps[0], newamps[0]) or
8443    fneq(amps[1], newamps[1])
8444    snd_display("swap_channels with cp def 0: %s %s?", amps, newamps)
8445  end
8446  close_sound(ind)
8447end
8448
8449def test_05_18
8450  ind1 = open_sound("oboe.snd")
8451  ind2 = open_sound("2.snd")
8452  ups1 = count_matches(lambda do |n| n > 0.1 end, 0, ind1, 0)
8453  count = 0
8454  reader = make_sampler(0, ind1)
8455  framples(ind1).times do |i|
8456    if next_sample(reader) > 0.1
8457      count += 1
8458    end
8459  end
8460  ups2 = count
8461  if ups1 != ups2
8462    snd_display("scan_chan: %s %s?", ups1, ups2)
8463  end
8464  ups1 = count_matches(lambda do |n| n > 0.03 end, 0, ind2, 0)
8465  ups2 = count_matches(lambda do |n| n > 0.03 end, 0, ind2, 1)
8466  count = 0
8467  reader = make_sampler(0, ind2, 0)
8468  framples(ind2).times do |i|
8469    if next_sample(reader) > 0.03
8470      count += 1
8471    end
8472  end
8473  ups3 = count
8474  count = 0
8475  reader = make_sampler(0, ind2, 1)
8476  framples(ind2).times do |i|
8477    if next_sample(reader) > 0.03
8478      count += 1
8479    end
8480  end
8481  ups4 = count
8482  if ups1 != ups3
8483    snd_display("2[0] scan_chan: %s %s?", ups1, ups3)
8484  end
8485  if ups2 != ups4
8486    snd_display("2[1] scan_chan: %s %s?", ups2, ups4)
8487  end
8488  set_sync(true, ind2)
8489  count = 0
8490  scan_chans do |n|
8491    if n > 0.03
8492      count += 1
8493    end
8494    false
8495  end
8496  total = count
8497  if total != ups1 + ups2
8498    snd_display("scan_chans: %s %s?", total, ups1 + ups2)
8499  end
8500  set_sync(false, ind2)
8501  count = 0
8502  scan_sound_chans(0, framples(ind2), ind2) do |n|
8503    if n > 0.03
8504      count += 1
8505    end
8506    false
8507  end
8508  total = count
8509  if total != ups1 + ups2
8510    snd_display("scan_sound_chans: %s %s?", total, ups1 + ups2)
8511  end
8512  count = 0
8513  scan_across_all_chans do |data, len|
8514    data.each do |val|
8515      if val > 0.03
8516        count += 1
8517      end
8518    end
8519    false
8520  end
8521  total = count
8522  ups3 = count_matches(lambda do |n| n > 0.03 end, 0, ind1, 0)
8523  if total != ups1 + ups2 + ups3
8524    snd_display("scan_across_all_chans: %s %s?", total, ups1 + ups2 + ups3)
8525  end
8526  count = 0
8527  scan_all_chans do |n|
8528    if n > 0.03
8529      count += 1
8530    end
8531    false
8532  end
8533  total = count
8534  ups3 = count_matches(lambda do |n| n > 0.03 end, 0, ind1, 0)
8535  if total != ups1 + ups2 + ups3
8536    snd_display("scan_all_chans: %s %s?", total, ups1 + ups2 + ups3)
8537  end
8538  close_sound(ind1)
8539  close_sound(ind2)
8540end
8541
8542def get_test_args(args, snd, chn, edpos)
8543  [(args[0] or snd), (args[1] or chn), (args[2] or edpos)]
8544end
8545
8546def test_05_20
8547  ind1 = open_sound("oboe.snd")
8548  len = framples(ind1)
8549  ctr = 0
8550  map_chan(lambda do |n|
8551             ctr = (ctr == 1) ? 0 : 1
8552             ctr.zero? ? n * 2.0 : false
8553           end, 0, framples(ind1), "ignore: cut 2", ind1, 0)
8554  if framples(ind1) > (len * 2 + 1)
8555    snd_display("map_chan cut: %s %s?", len, framples(ind1))
8556  end
8557  revert_sound(ind1)
8558  ctr = 0
8559  map_chan(lambda do |n|
8560             ctr += 1
8561             ctr > 3 ? true : n
8562           end, 0, framples(ind1), "ignore: cut none", ind1, 0)
8563  if ctr > 4
8564    snd_display("map_chan no-edit count: %s?", ctr)
8565  end
8566  revert_sound(ind1)
8567  v1 = make_vct(2)
8568  map_chan(lambda do |n|
8569             v1[0] = n
8570             v1[1] = n * 3.0
8571             v1
8572           end, 0, framples(ind1), "ignore: cut 2", ind1, 0)
8573  if (framples(ind1) - len * 2).abs > 3
8574    snd_display("map_chan double: %s %s?", len, framples(ind1))
8575  end
8576  revert_sound(ind1)
8577  otime = maxamp_position(ind1)
8578  set_sample(1234, 0.9)
8579  ntime = maxamp_position(ind1)
8580  nval = maxamp(ind1)
8581  npos = edit_position(ind1, 0)
8582  if ntime != 1234
8583    snd_display("maxamp_position 1234: %s?", ntime)
8584  end
8585  ootime = maxamp_position(ind1, 0, 0)
8586  if ootime != otime
8587    snd_display("maxamp_position edpos 0: %s %s?", otime, ootime)
8588  end
8589  nntime = maxamp_position(ind1, 0, npos)
8590  if nntime != ntime
8591    snd_display("maxamp_position edpos %s: %s %s?", npos, ntime, nntime)
8592  end
8593  if fneq(nval, 0.9)
8594    snd_display("maxamp 0.9: %s?", nval)
8595  end
8596  set_sample(1234, 0.0)
8597  env_channel([0, 0, 1, 1])
8598  snd_test_neq(maxamp_position(), 35062, "env_channel maxamp_position")
8599  ootime = maxamp_position(ind1, 0, 0)
8600  snd_test_neq(ootime, otime, "maxamp_position edpos 0 (1)")
8601  nntime = maxamp_position(ind1, 0, 1)
8602  snd_test_neq(nntime, 1234, "maxamp_position edpos 1 (1)")
8603  nntime = maxamp_position(ind1, 0, Current_edit_position)
8604  snd_test_neq(nntime, 35062, "maxamp_position edpos current")
8605  revert_sound(ind1)
8606  make_selection(24000, 25000)
8607  snd_test_neq(selection_maxamp_position(), 971, "selection_maxamp_position")
8608  make_region(24000, 25000)
8609  res = region_maxamp_position(regions.first)
8610  snd_test_neq(res, 971, "region_maxamp_position")
8611  close_sound(ind1)
8612  ind1 = open_sound("oboe.snd")
8613  test_edpos(ind1, :maxamp) do | | scale_by(2.0, ind1, 0) end
8614  test_edpos(ind1, :framples) do | | src_sound(2.0, 1.0, ind1, 0) end
8615  test_edpos(ind1, :count_matches, lambda do |*args|
8616    snd, chn, edpos = get_test_args(args, 0, 0, Current_edit_position)
8617    count_matches(lambda do |n1| n1 > 0.1 end, 0, snd, chn, edpos)
8618  end) do | |
8619    scale_by(2.0, ind1, 0)
8620  end
8621  test_edpos(ind1, :find, lambda do |*args|
8622    snd, chn, edpos = get_test_args(args, 0, 0, Current_edit_position)
8623    find_channel(lambda do |n2| n2 > 0.1 end, 0, snd, chn, edpos)
8624  end) do | |
8625    delete_samples(0, 100, ind1, 0)
8626  end
8627  test_edpos(ind1, :scan_channel, lambda do |*args|
8628    snd, chn, edpos = get_test_args(args, 0, 0, Current_edit_position)
8629    samp = 0
8630    scan_channel(lambda do |n3|
8631      if n3 > 0.1
8632        samp
8633      else
8634        samp += 1
8635        false
8636      end
8637    end, 0, framples(snd, chn), snd, chn, edpos)
8638    samp
8639  end) do | |
8640    delete_samples(0, 100, ind1, 0)
8641  end
8642  #
8643  delete_samples(0, 10000, ind1, 0)
8644  save_sound_as("fmv.snd", ind1, :edit_position, 0)
8645  save_sound_as("fmv1.snd", ind1, :edit_position, 1)
8646  if (res = Snd.catch do
8647    save_sound_as("fmv2.snd", ind1, :channel, 1234)
8648  end).first != :no_such_channel
8649  snd_display("save_sound_as bad chan: %s", res)
8650  end
8651  if (res0 = mus_sound_framples("fmv.snd")) != (res1 = framples(ind1, 0, 0))
8652    snd_display("save_sound_as (edpos): %s %s?", res0, res1)
8653  end
8654  if (res0 = mus_sound_framples("fmv1.snd")) != (res1 = framples(ind1, 0, 1))
8655    snd_display("save_sound_as (edpos 1): %s %s?", res0, res1)
8656  end
8657  if (res0 = mus_sound_framples("fmv.snd")) == (res1 = framples(ind1, 0, 1))
8658    snd_display("save_sound_as (edpos 1)(2): %s %s?", res0, res1)
8659  end
8660  ind2 = open_sound("fmv.snd")
8661  ind3 = open_sound("fmv1.snd")
8662  unless vequal(res0 = channel2vct(12000, 10, ind1, 0, 0),
8663                res1 = channel2vct(12000, 10, ind2, 0))
8664    snd_display("save_sound_as (edpos 3): %s %s?", res0, res1)
8665  end
8666  unless vequal(res0 = channel2vct(12000, 10, ind1, 0, 1),
8667                res1 = channel2vct(12000, 10, ind3, 0))
8668    snd_display("save_sound_as (edpos 4): %s %s?", res0, res1)
8669  end
8670  if vequal(res0 = channel2vct(12000, 10, ind2),
8671            res1 = channel2vct(12000, 10, ind3, 0))
8672    snd_display("save_sound_as (edpos 5): %s %s?", res0, res1)
8673  end
8674  select_sound(ind3)
8675  set_comment("hiho")
8676  if comment != "hiho"
8677    snd_display("set_comment no index: %s?", comment)
8678  end
8679  close_sound(ind2)
8680  close_sound(ind3)
8681  delete_files("fmv.snd", "fmv1.snd")
8682  #
8683  test_edpos_1(:reverse_sound, ind1) do |snd, pos|
8684    reverse_sound(snd, 0, pos)
8685  end
8686  test_edpos_1(:env_sound, ind1) do |snd, pos|
8687    env_sound([0, 0, 1, 1, 2, 0], 0, 20000, 1.0, snd, 0, pos)
8688  end
8689  test_edpos_1(:src_sound, ind1) do |snd, pos|
8690    src_sound(0.5, 1.0, snd, 0, pos)
8691  end
8692  test_edpos_1(:filter_sound, ind1) do |snd, pos|
8693    filter_sound(make_fir_filter(6, vct(0.1, 0.2, 0.3, 0.3, 0.2, 0.1)),
8694                 6, snd, 0, pos)
8695  end
8696  test_edpos_1(:convolve_with, ind1) do |snd, pos|
8697    convolve_with("pistol.snd", 0.5, snd, 0, pos)
8698  end
8699  #
8700  ind = new_sound("fmv.snd")
8701  e = make_env([0.0, 0.0, 1.0, 2000 * 0.2 * PI], :length, 2001)
8702  v = make_vct!(2000) do |i|
8703    sin(env(e))
8704  end
8705  vct2channel(v, 0, 2000, ind, 0)
8706  filter_sound([0, 0, 0.09, 0, 0.1, 1, 0.11, 0, 1, 0], 1024)
8707  if maxamp > 0.025
8708    snd_display("filter_sound maxamp 1: %s?", maxamp)
8709  end
8710  undo_edit
8711  filter_sound([0, 0, 0.19, 0, 0.2, 1, 0.21, 0, 1, 0], 1024)
8712  if maxamp < 0.9
8713    snd_display("filter_sound maxamp 2: %s?", maxamp)
8714  end
8715  undo_edit
8716  filter_sound([0, 0, 0.29, 0, 0.3, 1, 0.31, 0, 1, 0], 1024)
8717  if maxamp > 0.02
8718    snd_display("filter_sound maxamp 3: %s?", maxamp)
8719  end
8720  old_ssc = show_sonogram_cursor
8721  old_tgt = transform_graph_type
8722  set_show_sonogram_cursor(true)
8723  set_with_tracking_cursor(true)
8724  snd_test_neq(with_tracking_cursor(), true, "with_tracking_cursor set to true")
8725  set_transform_graph_type(Graph_as_sonogram)
8726  play(selected_sound, :wait, true)
8727  set_transform_graph?(true)
8728  set_transform_graph_type(old_tgt)
8729  set_show_sonogram_cursor(old_ssc)
8730  close_sound(ind)
8731  close_sound(ind1)
8732end
8733
8734def peak_env_equal?(name, index, e, diff)
8735  rd = make_sampler(0, index, 0)
8736  e_size = e.first.length
8737  samps_per_bin = (framples(index) / e_size.to_f).ceil
8738  mins, maxs = e[0, 2]
8739  max_diff = 0.0
8740  e_bin = 0
8741  samp = 0
8742  mx = -10.0
8743  mn = 10.0
8744  until e_bin == e_size
8745    if samp >= samps_per_bin
8746      mxdiff = (mx - maxs[e_bin]).abs
8747      mndiff = (mn - mins[e_bin]).abs
8748      if mxdiff > max_diff
8749        max_diff = mxdiff
8750      end
8751      if mndiff > max_diff
8752        max_diff = mndiff
8753      end
8754      if mxdiff > diff or mndiff > diff
8755        snd_display("%s: peak_env_equal? [bin %s of %s]: %s %s %s?",
8756                    name, e_bin, e_size, mn, mx, [mxdiff, mndiff].max)
8757        return false
8758      end
8759      samp = 0
8760      mx = -10.0
8761      mn = 10.0
8762      e_bin += 1
8763    end
8764    val = next_sample(rd)
8765    if val < mn
8766      mn = val
8767    end
8768    if val > mx
8769      mx = val
8770    end
8771    samp += 1
8772  end
8773  true
8774end
8775
8776def test_05_22
8777  ind = open_sound("oboe.snd")
8778  mx = maxamp(ind, 0)
8779  if (e0 = channel_amp_envs(ind, 0)).nil?
8780    snd_display("no amp env data")
8781  else
8782    mx1 = vct_peak(e0[0])
8783    mx2 = vct_peak(e0[1])
8784    if fneq(mx, [mx1, mx2].max)
8785      snd_display("amp env max: %s %s %s?", mx, mx1, mx2)
8786    end
8787    peak_env_equal?("straight peak", ind, e0, 0.0001)
8788    #
8789    scale_by(3.0)
8790    e1 = channel_amp_envs(ind, 0, 1)
8791    mx3 = vct_peak(e1[0])
8792    mx4 = vct_peak(e1[1])
8793    if fneq(3.0 * mx1, mx3) or fneq(3.0 * mx2, mx4)
8794      snd_display("3.0 amp env max: %s %s %s %s?", mx1, mx2, mx3, mx4)
8795    end
8796    peak_env_equal?("scaled peak", ind, e1, 0.0001)
8797    if fneq(maxamp(ind, 0), 3.0 * mx)
8798      snd_display("maxamp after scale: %s %s?", mx, maxamp(ind, 0))
8799    end
8800    undo_edit
8801    #
8802    set_selection_member?(false, true)
8803    set_selection_member?(true, ind, 0)
8804    set_selection_position(20000, ind, 0)
8805    set_selection_framples(12000, ind, 0)
8806    scale_selection_by(3.0)
8807    e1 = channel_amp_envs(ind, 0, 1)
8808    mx3 = vct_peak(e1[0])
8809    mx4 = vct_peak(e1[1])
8810    if fneq(3.0 * mx1, mx3) or fneq(3.0 * mx2, mx4)
8811      snd_display("selection 3.0 amp env max: %s %s %s %s?",
8812                  mx1, mx2, mx3, mx4)
8813    end
8814    if fneq(maxamp(ind, 0), 3.0 * mx)
8815      snd_display("maxamp after selection scale: %s %s?",
8816                  mx, maxamp(ind, 0))
8817    end
8818    peak_env_equal?("selection peak", ind, e1, 0.0001)
8819    #
8820    map_chan(lambda do |n| n.abs end, 0, false, "test", ind, 0)
8821    e1 = channel_amp_envs(ind, 0, 2)
8822    mx3 = vct_peak(e1[0])
8823    mx4 = vct_peak(e1[1])
8824    if fneq(3.0 * mx2, mx4)
8825      snd_display("abs selection 3.0 amp env max: %s %s %s %s?",
8826                  mx1, mx2, mx3, mx4)
8827    end
8828    if fneq(maxamp(ind, 0), 3.0 * mx)
8829      snd_display("maxamp after abs selection scale: %s %s?",
8830                  mx, maxamp(ind, 0))
8831    end
8832    peak_env_equal?("map_chan peak", ind, e1, 0.0001)
8833    #
8834    delete_samples(10000, 5000)
8835    e1 = channel_amp_envs(ind, 0)
8836    mx3 = vct_peak(e1[0])
8837    mx4 = vct_peak(e1[1])
8838    if fneq(3.0 * mx2, mx4)
8839      snd_display("abs selection 3.0 amp env max: %s %s %s %s?",
8840                  mx1, mx2, mx3, mx4)
8841    end
8842    if fneq(maxamp(ind, 0), 3.0 * mx)
8843      snd_display("maxamp after abs selection scale: %s %s?",
8844                  mx, maxamp(ind, 0))
8845    end
8846    peak_env_equal?("delete peak", ind, e1, 0.0001)
8847    #
8848    scale_selection_by -0.333
8849    e1 = channel_amp_envs(ind, 0, 4)
8850    mx3 = vct_peak(e1[0])
8851    if fneq(maxamp(ind, 0), mx)
8852      snd_display("maxamp after minus selection scale: %s %s?",
8853                  mx, maxamp(ind, 0))
8854    end
8855    if fneq(maxamp(ind, 0), mx3)
8856      snd_display("mx3 maxamp after minus abs selection scale: %s %s?", mx, mx3)
8857    end
8858    peak_env_equal?("scale_selection peak", ind, e1, 0.0001)
8859  end
8860  revert_sound(ind)
8861  ramp_channel(0.0, 1.0)
8862  peak_env_equal?("ramp_channel peak", ind, channel_amp_envs(ind, 0, 1), 0.001)
8863  undo_edit
8864  env_channel([0, 0, 1, 1, 2, 0])
8865  peak_env_equal?("env_channel peak", ind, channel_amp_envs(ind, 0, 1), 0.002)
8866  undo_edit
8867  env_channel(make_env([0, 0, 1, 1, 2, 0], :scaler, 0.5, :length, framples))
8868  peak_env_equal?("scaled env_channel peak",
8869                  ind, channel_amp_envs(ind, 0, 1), 0.002)
8870  undo_edit
8871  env_channel(make_env([0, 0, 1, 1, 2, 0], 0.5, :length, framples))
8872  peak_env_equal?("scaled nokey env_channel peak",
8873                  ind, channel_amp_envs(ind, 0, 1), 0.001)
8874  undo_edit
8875  env_channel(make_env([0, 0, 1, 1, 2, 0],
8876                       :scaler, 0.5, :offset, 0.5, :length, framples))
8877  peak_env_equal?("scaled and offset env_channel peak",
8878                  ind, channel_amp_envs(ind, 0, 1), 0.001)
8879  undo_edit
8880  env_channel(make_env([0, 0, 1, 1, 2, 0.5, 3, 0],
8881                       :base, 0.0, :length, framples))
8882  peak_env_equal?("env_channel base 0.0 peak",
8883                  ind, channel_amp_envs(ind, 0, 1), 0.001)
8884  undo_edit
8885  xramp_channel(0.0, 1.0, 32.0)
8886  peak_env_equal?("xramp_channel 32.0 peak",
8887                  ind, channel_amp_envs(ind, 0, 1), 0.008)
8888  undo_edit
8889  xramp_channel(0.0, 1.0, 0.032)
8890  peak_env_equal?("xramp_channel 0.032 peak",
8891                  ind, channel_amp_envs(ind, 0, 1), 0.004)
8892  undo_edit
8893  env_channel(make_env([0, 0, 1, 1, 2, 0.5, 3, 0],
8894                       :base, 10.0, :length, framples))
8895  peak_env_equal?("env_channel base 10.0 peak",
8896                  ind, channel_amp_envs(ind, 0, 1), 0.01)
8897  undo_edit
8898  env_channel(make_env([0, 0, 1, 1, 2, 0], :base, 0.1, :length, framples))
8899  peak_env_equal?("env_channel base 0.1 peak",
8900                  ind, channel_amp_envs(ind, 0, 1), 0.003)
8901  undo_edit
8902  insert_samples(1000, 5000, make_vct(5000, 0.5))
8903  peak_env_equal?("insert_samples peak",
8904                  ind, channel_amp_envs(ind, 0, 1), 0.0001)
8905  undo_edit
8906  set_samples(500, 100, make_vct(100, 0.1))
8907  peak_env_equal?("set_samples peak",
8908                  ind, channel_amp_envs(ind, 0, 1), 0.0001)
8909  undo_edit
8910  #
8911  revert_sound(ind)
8912  ramp_channel(0.0, 1.0)
8913  ramp_channel(1.0, 0.0)
8914  peak_env_equal?("2 ramp_channel peak",
8915                  ind, channel_amp_envs(ind, 0, 2), 0.002)
8916  #
8917  revert_sound(ind)
8918  env_channel([0, 0, 1, 1])
8919  env_channel([0, 0, 1, 1, 2, 0])
8920  peak_env_equal?("2 env_channel peak",
8921                  ind, channel_amp_envs(ind, 0, 2), 0.002)
8922  revert_sound(ind)
8923  ramp_channel(0.0, 1.0, 12000, 5000)
8924  peak_env_equal?("ramp_channel peak",
8925                  ind, channel_amp_envs(ind, 0, 1), 0.002)
8926  undo_edit
8927  env_channel([0, 0, 1, 1, 2, 0], 12000, 5000)
8928  peak_env_equal?("env_channel peak",
8929                  ind, channel_amp_envs(ind, 0, 1), 0.003)
8930  undo_edit
8931  env_channel(make_env([0, 0, 1, 1, 2, 0],
8932                       :scaler, 0.5, :length, 5000), 12000, 5000)
8933  peak_env_equal?("scaled env_channel peak",
8934                  ind, channel_amp_envs(ind, 0, 1), 0.004)
8935  undo_edit
8936  env_channel(make_env([0, 0, 1, 1, 2, 0],
8937                       0.5, :length, 5000), 12000, 5000)
8938  peak_env_equal?("scaled nokey env_channel peak",
8939                  ind, channel_amp_envs(ind, 0, 1), 0.004)
8940  undo_edit
8941  env_channel(make_env([0, 0, 1, 1, 2, 0],
8942                       :scaler, 0.5, :offset, 0.5, :length, 5000), 12000, 5000)
8943  peak_env_equal?("scaled and offset env_channel peak",
8944                  ind, channel_amp_envs(ind, 0, 1), 0.002)
8945  undo_edit
8946  xramp_channel(0.0, 1.0, 32.0, 2000, 1000)
8947  peak_env_equal?("xramp_channel 32.0 peak (1)",
8948                  ind, channel_amp_envs(ind, 0, 1), 0.009)
8949  undo_edit
8950  xramp_channel(0.0, 1.0, 0.032, 2000, 1000)
8951  peak_env_equal?("xramp_channel 0.032 peak (1)",
8952                  ind, channel_amp_envs(ind, 0, 1), 0.01)
8953  undo_edit
8954  env_channel(make_env([0, 0, 1, 1, 2, 0.5, 3, 0],
8955                       :base, 10.0, :length, 5000), 12000, 5000)
8956  peak_env_equal?("env_channel base 10.0 peak",
8957                  ind, channel_amp_envs(ind, 0, 1), 0.1)
8958  undo_edit
8959  #
8960  revert_sound(ind)
8961  ramp_channel(0.0, 1.0)
8962  ramp_channel(1.0, 0.0, 2000, 1000)
8963  peak_env_equal?("2 ramp_channel peak",
8964                  ind, channel_amp_envs(ind, 0, 2), 0.002)
8965  #
8966  revert_sound(ind)
8967  env_channel([0, 0, 1, 1])
8968  env_channel([0, 0, 1, 1, 2, 0], 2000, 1000)
8969  peak_env_equal?("2 env_channel peak",
8970                  ind, channel_amp_envs(ind, 0, 2), 0.002)
8971  #
8972  revert_sound(ind)
8973  env_channel([0, 0, 1, 1])
8974  env_channel([0, 0, 1, 1, 2, 0])
8975  env_channel([0, 0, 1, 1], 12000, 5000)
8976  peak_env_equal?("3 env_channel peak",
8977                  ind, channel_amp_envs(ind, 0, 3), 0.01)
8978  revert_sound(ind)
8979  close_sound(ind)
8980  #
8981  ind = new_sound("test.snd")
8982  map_chan(lambda do |y| 1.0 end, 0, 50000)
8983  ramp_channel(0.5, 1.0, 1000, 4000)
8984  mn, mx = channel_amp_envs(ind, 0)[0, 2]
8985  (mn.length - 4).times do |i|
8986    if mn[i] < 0.5
8987      snd_display("peak min: %s %s?", mn[i], i)
8988      break
8989    end
8990    if mx[i] < 0.5
8991      snd_display("peak max: %s %s?", mx[i], i)
8992      break
8993    end
8994  end
8995  undo_edit
8996  map_chan(lambda do |y| -1.0 end, 0, 50000)
8997  ramp_channel(0.5, 1.0, 1000, 4000)
8998  mn, mx = channel_amp_envs(ind, 0)[0, 2]
8999  (mn.length - 4).times do |i|
9000    if mn[i] > -0.5
9001      snd_display("1 peak min: %s %s?", mn[i], i)
9002      break
9003    end
9004    if mx[i] > -0.5
9005      snd_display("1 peak max: %s %s?", mx[i], i)
9006      break
9007    end
9008  end
9009  close_sound(ind)
9010end
9011
9012$g_init_val = 0
9013
9014def test_channel_func(name, index, init_val, func, &val_func)
9015  len = framples(index)
9016  chns = chans(index)
9017  $g_init_val = init_val
9018  2.times do |k|
9019    val = val_func.call(len)
9020    set_sync(k, index)
9021    chns.times do |i|
9022      map_channel(lambda do |n| 0.0 end, 0, len, index, i)
9023      res = scan_channel(lambda do |n| n.abs > 0.001 end, 0, len, index, i)
9024      if res
9025        snd_display("%s init scan: %s?", name, res)
9026      end
9027    end
9028    chns.times do |i|
9029      map_channel(lambda do |n| $g_init_val end, 0, len, index, i)
9030      func.call(0, len, index, i, false)
9031      chns.times do |j|
9032        vi = channel2vct(0, len, index, j)
9033        if j == i
9034          unless vequal(vi, val)
9035            snd_display("%s chan func: %s %s?", name, vi, val)
9036          end
9037        else
9038          res = scan_channel(lambda do |n| n.abs > 0.001 end, 0, len, index, j)
9039          if res
9040            snd_display("%s chan func leaks? %s %s: %s", name, i, j, res)
9041          end
9042        end
9043      end
9044      map_channel(lambda do |n| 0.0 end, 0, len, index, i)
9045    end
9046    chns.times do |i|
9047      map_channel(lambda do |n| $g_init_val end, 0, len, index, i)
9048      ed = edit_position(index, i)
9049      map_channel(lambda do |n| $g_init_val + 1.0 end, 0, len, index, i)
9050      func.call(0, len, index, i, ed)
9051      chns.times do |j|
9052        vi = channel2vct(0, len, index, j)
9053        if j == i
9054          unless vequal(vi, val)
9055            snd_display("%s ed chan func: %s %s?", name, vi, val)
9056          end
9057        else
9058          res = scan_channel(lambda do |n| n.abs > 0.001 end, 0, len, index, j)
9059          if res
9060            snd_display("%s ed chan func leaks? %s %s %s: %s",
9061                        name, i, j, ed, res)
9062          end
9063        end
9064      end
9065      map_channel(lambda do |n| 0.0 end, 0, len, index, i)
9066    end
9067    beg = dur = (len / 3.0).floor
9068    nv = val_func.call(dur)
9069    vct_fill!(val, 0.0)
9070    i = beg
9071    dur.times do |j|
9072      val[i] = nv[j]
9073      i += 1
9074    end
9075    chns.times do |i|
9076      map_channel(lambda do |n| $g_init_val end, beg, dur, index, i)
9077      func.call(beg, dur, index, i, false)
9078      add_mark(beg, index, i)
9079      chns.times do |j|
9080        vi = channel2vct(0, len, index, j)
9081        if j == i
9082          unless vequal(vi, val)
9083            snd_display("%s chan func n: %s %s?", name, vi, val)
9084          end
9085        else
9086          res = scan_channel(lambda do |n| n.abs > 0.001 end, 0, len, index, j)
9087          if res
9088            snd_display("%s dur chan func leaks? %s %s: %s", name, i, j, res)
9089          end
9090        end
9091      end
9092      map_channel(lambda do |n| 0.0 end, 0, len, index, i)
9093    end
9094  end
9095end
9096
9097def test_05_23
9098  index = new_sound("fmv.snd", 2, 22050, Mus_bshort, Mus_next, "channel tests")
9099  insert_silence(0, 10, index, 0)
9100  insert_silence(0, 10, index, 1)
9101  test_channel_func(:env, index, 0.0,
9102                    lambda do |beg, dur, index, chan, edpos|
9103                      clm_channel(make_env(:envelope, [0, 0, 1, 1],
9104                                           :length, dur),
9105                                  beg, dur, index, chan, edpos)
9106                    end) do |dur|
9107    e = make_env(:envelope, [0, 0, 1, 1], :length, dur)
9108    make_vct!(dur) do env(e) end
9109  end
9110  test_channel_func(:oscil, index, 0.0,
9111                    lambda do |beg, dur, index, chan, edpos|
9112                      clm_channel(make_oscil(:frequency, 0.0,
9113                                             :initial_phase, PI / 2.0),
9114                                  beg, dur, index, chan, edpos)
9115                    end) do |dur| make_vct!(dur) do 1.0 end end
9116  test_channel_func(:scale_channel, index, 1.0,
9117                    lambda do |beg, dur, index, chan, edpos|
9118                      scale_channel(0.5, beg, dur, index, chan, edpos)
9119                    end) do |dur| make_vct!(dur) do 0.5 end end
9120  test_channel_func(:env_channel, index, 1.0,
9121                    lambda do |beg, dur, index, chan, edpos|
9122                      env_channel(make_env(:envelope, [0, 0, 1, 1],
9123                                           :length, dur),
9124                                  beg, dur, index, chan, edpos)
9125                    end) do |dur|
9126    e = make_env(:envelope, [0, 0, 1, 1], :length, dur)
9127    make_vct!(dur) do env(e) end
9128  end
9129  test_channel_func(:env_channel, index, 1.0,
9130                    lambda do |beg, dur, index, chan, edpos|
9131                      env_channel([0, 0, 1, 1], beg, dur, index, chan, edpos)
9132                    end) do |dur|
9133    e = make_env(:envelope, [0, 0, 1, 1], :length, dur)
9134    make_vct!(dur) do env(e) end
9135  end
9136  test_channel_func(:vct2channel, index, 1.0,
9137                    lambda do |beg, dur, index, chan, edpos|
9138                      vct2channel(make_vct!(dur) do -1.0 end,
9139                                  beg, dur, index, chan)
9140                    end) do |dur|
9141    make_vct!(dur) do -1.0 end
9142  end
9143  test_channel_func(:pad_channel, index, 1.0,
9144                    lambda do |beg, dur, index, chan, edpos|
9145                      delete_samples(beg, dur, index, chan, edpos)
9146                      pad_channel(beg, dur, index, chan, edpos)
9147                    end) do |dur|
9148    make_vct(dur)
9149  end
9150  test_channel_func(:insert_samples, index, 1.0,
9151                    lambda do |beg, dur, index, chan, edpos|
9152                      delete_samples(beg, dur, index, chan, edpos)
9153                      insert_samples(beg, dur, make_vct!(dur) do -1.0 end,
9154                                     index, chan, edpos)
9155                    end) do |dur|
9156    make_vct!(dur) do -1.0 end
9157  end
9158  test_channel_func(:set_samples, index, 1.0,
9159                    lambda do |beg, dur, index, chan, edpos|
9160                      set_samples(beg, dur, make_vct!(dur) do -1.0 end,
9161                                  index, chan, false, "test_channel", edpos)
9162                    end) do |dur| make_vct!(dur) do -1.0 end end
9163  test_channel_func(:reverse_channel, index, 1.0,
9164                    lambda do |beg, dur, index, chan, edpos|
9165                      env_channel(make_env(:envelope, [0, 0, 1, 1],
9166                                           :length, dur),
9167                                  beg, dur, index, chan, edpos)
9168                      reverse_channel(beg, dur, index, chan)
9169                    end) do |dur|
9170    e = make_env(:envelope, [0, 1, 1, 0], :length, dur)
9171    make_vct!(dur) do env(e) end
9172  end
9173  test_channel_func(:smooth_channel, index, 1.0,
9174                    lambda do |beg, dur, index, chan, edpos|
9175                      env_channel(make_env(:envelope, [0, 0, 1, 1],
9176                                           :length, dur),
9177                                  beg, dur, index, chan, edpos)
9178                      set_sample(beg + dur, 1.0, index, chan)
9179                      smooth_channel(beg, dur, index, chan)
9180                      if beg.nonzero?
9181                        set_sample(beg + dur, 0.0, index, chan)
9182                      end
9183                    end) do |dur|
9184    make_vct!(dur) do |i| 0.5 + 0.5 * cos(PI + (PI * i) / dur) end
9185  end
9186  #
9187  old_max = maxamp(index, true)
9188  regdata = Snd.regions.map do |n| region2vct(n, 0, 10) end
9189  old_reglen = Snd.regions.map do |n| region_framples(n) end
9190  s61_files = []
9191  $save_state_hook.add_hook!("snd-test") do |file|
9192    s61_files.push(file)
9193    false
9194  end
9195  delete_file("s61.rb")
9196  save_state("s61.rb")
9197  close_sound(index)
9198  Snd.regions.apply(:forget_region)
9199  load("s61.rb")
9200  if (res = Snd.regions.map do |n| region_framples(n) end) != old_reglen
9201    snd_display("region_framples after save: %s %s?", old_reglen, res)
9202  end
9203  Snd.catch(:all, lambda do |*args|
9204              snd_display("region2vct: %s", args.inspect)
9205            end) do
9206    Snd.regions.zip(regdata) do |n, data|
9207      unless vequal(res = region2vct(n, 0, 10), data)
9208        snd_display("region after save %s: %s %s?", n, data, res)
9209      end
9210    end
9211  end
9212  index = find_sound("fmv.snd")
9213  if (res = maxamp(index, true)) != old_max
9214    snd_display("maxes: %s %s?", res, old_max)
9215  end
9216  if edits(index) != [275, 0]
9217    snd_display("saved channel edits: %s?", edits(index))
9218  end
9219  10.times do |i|
9220    pos = random(edits(index).first)
9221    scale_channel(random(2.0), random(5), random(5), index, 0, pos)
9222    set_edit_position((edits(index).first * 0.7).floor, index)
9223  end
9224  close_sound(index)
9225  Snd.regions.apply(:forget_region)
9226  s61_files.each do |file| delete_file(file) end
9227  delete_file("s61.rb")
9228  $save_state_hook.reset_hook!
9229end
9230
9231def test_05_24
9232  index = new_sound("fmv.snd", 2, 22050, Mus_bshort, Mus_next, "channel tests")
9233  sw = sinc_width
9234  set_sinc_width(10)
9235  v0 = make_vct(10)
9236  v0[0] = 1.0
9237  vct2channel(v0, 0, 10, index, 0)
9238  src_channel(0.5, 0, 10, index, 0)
9239  idx = -1
9240  s = make_src(:srate, 0.5,
9241               :input, lambda do |dir|
9242                 idx += 1
9243                 idx.zero? ? 1.0 : 0.0
9244               end)
9245  v = make_vct!(10) do src(s) end
9246  unless vequal(res = channel2vct(0, 10, index, 0), v)
9247    snd_display("src_channel: %s %s?", v, res)
9248  end
9249  unless vequal(res = channel2vct(0, 10, index, 1), make_vct(10))
9250    snd_display("src_channel leaks: %s?", res)
9251  end
9252  res = Snd.catch do src_channel(120000.0) end
9253  if res.first != :mus_error
9254    snd_display("src_channel crazy srate: %s?", res.inspect)
9255  end
9256  res = Snd.catch do filter_sound(make_snd2sample()) end
9257  if res.first != :mus_error
9258    # not relevant in Ruby?
9259    snd_display("filter_sound + un-run gen: %s?", res.inspect)
9260  end
9261  revert_sound(index)
9262  vct2channel(v0, 0, 10, index, 1)
9263  vct2channel(v0, 10, 10, index, 1)
9264  src_channel(make_env(:envelope, [1, 1, 2, 2], :length, 21), 0, 20, index, 1)
9265  unless vequal(res = channel2vct(0, 10, index, 1),
9266                vct(1.000, 0.000, -0.048, 0.068, -0.059,
9267                    0.022, 0.030, -0.100, 0.273, 0.606))
9268    snd_display("src_channel env: %s?", res)
9269  end
9270  unless vequal(res = channel2vct(0, 10, index, 0), make_vct(10))
9271    snd_display("src_channel env leaks: %s?", res)
9272  end
9273  #
9274  revert_sound(index)
9275  vct2channel(v0, 0, 10, index, 1)
9276  vct2channel(v0, 10, 10, index, 1)
9277  src_channel(make_env(:envelope, [1, 1, 2, 2], :length, 21), 0, 20, index, 1)
9278  unless vequal(res = channel2vct(0, 10, index, 1),
9279                vct(1.000, 0.000, -0.048, 0.068, -0.059,
9280                    0.022, 0.030, -0.100, 0.273, 0.606))
9281    snd_display("src_channel env: %s?", res)
9282  end
9283  unless vequal(res = channel2vct(0, 10, index, 0), make_vct(10))
9284    snd_display("src_channel env leaks: %s?", res)
9285  end
9286  #
9287  revert_sound(index)
9288  vct2channel(v0, 0, 10, index, 1)
9289  vct2channel(v0, 10, 10, index, 1)
9290  src_channel([1, 1, 2, 2], 0, 20, index, 1)
9291  unless vequal(res = channel2vct(0, 10, index, 1),
9292                vct(1.000, 0.000, -0.051, 0.069, -0.056,
9293                    0.015, 0.042, -0.117, 0.320, 0.568))
9294    snd_display("src_channel lst: %s?", res)
9295  end
9296  unless vequal(res = channel2vct(0, 10, index, 0), make_vct(10))
9297    snd_display("src_channel lst leaks: %s?", res)
9298  end
9299  set_sinc_width(sw)
9300  close_sound(index)
9301end
9302
9303def test_05_25
9304  ind = open_sound("oboe.snd")
9305  rid0 = make_region(2000, 2020, ind, 0)
9306  rid0_data = region2vct_1(rid0, 0, 20)
9307  scale_sound_by(2.0)
9308  play(rid0, :wait, true)
9309  unless vequal(res = region2vct_1(rid0, 0, 20), rid0_data)
9310    snd_display("deferred region after scaling:\n# %s\n# %s", rid0_data, res)
9311  end
9312  unless vequal(res = region_to_vct(rid0, 0, 20), rid0_data)
9313    snd_display("deferred region after scaling (rs):\n# %s\n# %s",
9314                rid0_data, res)
9315  end
9316  undo_edit
9317  scale_by(4.0)
9318  play(rid0, :wait, true)
9319  unless vequal(res = region2vct_1(rid0, 0, 20), rid0_data)
9320    snd_display("file region after scaling:\n# %s\n# %s", rid0_data, res)
9321  end
9322  unless vequal(res = region_to_vct(rid0, 0, 20), rid0_data)
9323    snd_display("file region after scaling (rs):\n# %s\n# %s", rid0_data, res)
9324  end
9325  rid1 = make_region(2000, 2020, ind, 0)
9326  rid1_data = region2vct_1(rid1, 0, 20)
9327  scale_to(0.5)
9328  unless vequal(res = region2vct_1(rid1, 0, 20), rid1_data)
9329    snd_display("deferred region after scale_to:\n# %s\n# %s", rid1_data, res)
9330  end
9331  close_sound(ind)
9332  play(rid0, :wait, true)
9333  play(rid1, :wait, true)
9334  unless vequal(res = region2vct_1(rid1, 0, 20), rid1_data)
9335    snd_display("deferred region after close:\n# %s\n# %s", rid1_data, res)
9336  end
9337  unless vequal(res = region2vct_1(rid0, 0, 20), rid0_data)
9338    snd_display("file region after close:\n# %s\n# %s", rid0_data, res)
9339  end
9340  [[2000, 20, 2000, 20],
9341    [2000, 10, 2000, 20],
9342    [2000, 20, 2000, 10],
9343    [0,    20, 2000, 20],
9344    [2000, 20, 0,    20],
9345    [0,    10, 2000, 20],
9346    [2000, 20, 0,    10]].each do |s1, l1, s2, l2|
9347    ind = open_sound("2.snd")
9348    set_selection_member?(false, true)
9349    set_selection_member?(true, ind, 0)
9350    set_selection_position(s1, ind, 0)
9351    set_selection_framples(l1, ind, 0)
9352    set_selection_member?(true, ind, 1)
9353    set_selection_position(s2, ind, 1)
9354    set_selection_framples(l2, ind, 1)
9355    rid2 = make_region
9356    rid20_data = region2vct_1(rid2, 0, l1)
9357    rid21_data = region2vct_1(rid2, 1, l2)
9358    if (res = region_chans(rid2)) != 2
9359      snd_display("region_chans of synced sound: %s?", res)
9360    end
9361    swap_channels(ind, 0, ind, 1)
9362    unless vequal(res = region2vct_1(rid2, 0, l1), rid20_data)
9363      snd_display("deferred region after scaling (20):\n# %s\n# %s",
9364                  rid20_data, res)
9365    end
9366    unless vequal(res = region_to_vct(rid2, 0, l1), rid20_data)
9367      snd_display("deferred region after scaling (20 rs):\n# %s\n# %s",
9368                  rid20_data, res)
9369    end
9370    unless vequal(res = region2vct_1(rid2, 1, l2), rid21_data)
9371      snd_display("deferred region after scaling (21):\n# %s\n# %s",
9372                  rid21_data, res)
9373    end
9374    unless vequal(res = region_to_vct(rid2, 1, l2), rid21_data)
9375      snd_display("deferred region after scaling (21 rs):\n# %s\n# %s",
9376                  rid21_data, res)
9377    end
9378    close_sound(ind)
9379    unless vequal(res = region2vct_1(rid2, 0, l1), rid20_data)
9380      snd_display("deferred region after scaling (20):\n# %s\n# %s",
9381                  rid20_data, res)
9382    end
9383    unless vequal(res = region_to_vct(rid2, 0, l1), rid20_data)
9384      snd_display("deferred region after scaling (20 rs):\n# %s\n# %s",
9385                  rid20_data, res)
9386    end
9387    unless vequal(res = region2vct_1(rid2, 1, l2), rid21_data)
9388      snd_display("deferred region after scaling (21):\n# %s\n# %s",
9389                  rid21_data, res)
9390    end
9391    unless vequal(res = region_to_vct(rid2, 1, l2), rid21_data)
9392      snd_display("deferred region after scaling (21 rs):\n# %s\n# %s",
9393                  rid21_data, res)
9394    end
9395  end
9396  ind = open_sound("obtest.snd")
9397  set_read_only(true, ind)
9398  delete_samples(0, 1000, ind, 0)
9399  res = Snd.catch do save_sound(ind) end
9400  if sound?(res.first)
9401    snd_display("save_sound read_only: %s", res)
9402  end
9403  snd_test_neq(edits(ind), [1, 0], "read_only ignored")
9404  set_read_only(false, ind)
9405  revert_sound(ind)
9406  res = Snd.catch do save_sound(ind) end
9407  unless sound?(res.first)
9408    snd_display("save_sound read_write: %s", res)
9409  end
9410  key(key_to_int(?j), 4)
9411  key(key_to_int(?-), 4)
9412  key(key_to_int(?j), 4)
9413  key(key_to_int(?j), 4)
9414  key(key_to_int(?x), 4)
9415  key(key_to_int(?c), 0)
9416  Snd.catch do add_mark(123) end
9417  key(key_to_int(?u), 4)
9418  key(key_to_int(?6), 4)
9419  key(key_to_int(?j), 4)
9420  key(key_to_int(?u), 4)
9421  key(key_to_int(?6), 4)
9422  key(key_to_int(?x), 4)
9423  key(key_to_int(?c), 0)
9424  close_sound(ind)
9425  #
9426  ns = new_sound
9427  v = make_vct(1000)
9428  unselect_all
9429  1000.times do |i|
9430    v[i] = 0.001 * i
9431  end
9432  vct2channel(v, 0, 1000, ns, 0)
9433  set_selection_member?(true, ns, 0)
9434  set_selection_position(200, ns, 0)
9435  set_selection_framples(300, ns, 0)
9436  delete_selection_and_smooth
9437  snd_test_neq(framples(ns, 0), 700, "delete_selection_and_smooth framples")
9438  snd_test_neq(sample(167, ns, 0), 0.167, "delete_selection_and_smooth 167")
9439  snd_test_neq(sample(234, ns, 0), 0.534, "delete_selection_and_smooth 234")
9440  snd_test_neq(sample(210, ns, 0), 0.406, "delete_selection_and_smooth 210")
9441  v1 = channel2vct
9442  maxdiff = 0.0
9443  mindiff = 10.0
9444  ls = v1[0]
9445  (1...700).each do |i|
9446    diff = v1[i] - ls
9447    ls = v1[i]
9448    if diff > maxdiff
9449      maxdiff = diff
9450    end
9451    if diff < mindiff
9452      mindiff = diff
9453    end
9454  end
9455  snd_test_lt(mindiff, 0.0009, "delete_selection_and_smooth min diff")
9456  snd_test_gt(maxdiff, 0.007, "delete_selection_and_smooth max diff")
9457  close_sound(ns)
9458  #
9459  ns = new_sound
9460  v = make_vct(1000)
9461  unselect_all
9462  1000.times do |i|
9463    v[i] = 0.001 * i
9464  end
9465  vct2channel(v, 0, 1000, ns, 0)
9466  delete_samples_and_smooth(200, 300, ns, 0)
9467  snd_test_neq(framples(ns, 0), 700, "delete_samples_and_smooth framples")
9468  snd_test_neq(sample(167, ns, 0), 0.167, "delete_samples_and_smooth 167")
9469  snd_test_neq(sample(234, ns, 0), 0.534, "delete_samples_and_smooth 234")
9470  snd_test_neq(sample(210, ns, 0), 0.406, "delete_samples_and_smooth 210")
9471  v1 = channel2vct
9472  maxdiff = 0.0
9473  mindiff = 10.0
9474  ls = v1[0]
9475  (1...700).each do |i|
9476    diff = v1[i] - ls
9477    ls = v1[i]
9478    if diff > maxdiff
9479      maxdiff = diff
9480    end
9481    if diff < mindiff
9482      mindiff = diff
9483    end
9484  end
9485  snd_test_lt(mindiff, 0.0009, "delete_samples_and_smooth min diff")
9486  snd_test_gt(maxdiff, 0.007, "delete_samples_and_smooth max diff")
9487  close_sound(ns)
9488  #
9489  old_beg = initial_beg
9490  old_dur = initial_dur
9491  old_show = show_full_duration
9492  $initial_graph_hook.reset_hook!
9493  #
9494  set_show_full_range(true)
9495  ns = open_sound("1a.snd")
9496  snd_test_neq(y_bounds(ns, 0), [-1.0, 1.0], "show_full_range 1.0 test")
9497  close_sound(ns)
9498  with_sound(:output, "test.snd", :clipped, false) do
9499    fm_violin(0, 1, 440, 3.5)
9500  end
9501  ns = open_sound("test.snd")
9502  snd_test_neq(y_bounds(ns, 0), [-3.5, 3.5], "show_full_range 3.5 test")
9503  with_sound(:output, "test.snd", :clipped, false) do
9504    fm_violin(0, 1, 440, 1.5)
9505  end
9506  update_sound(ns = find_sound("test.snd"))
9507  snd_test_neq(y_bounds(ns, 0), [-1.5, 1.5], "show_full_range 1.5 test")
9508  close_sound(ns)
9509  set_show_full_range(false)
9510  #
9511  set_show_full_duration(true)
9512  ns = open_sound("1.snd")
9513  ls = left_sample(ns, 0)
9514  rs = right_sample(ns, 0)
9515  fr = framples(ns, 0)
9516  snd_test_neq([fr, ls, rs], [220501, 0, 220501], "show_full_duration 1")
9517  close_sound(ns)
9518  set_show_full_duration(true)
9519  set_initial_beg(0.0)
9520  set_initial_dur(0.2)
9521  ns = open_sound("1.snd")
9522  ls = left_sample(ns, 0)
9523  rs = right_sample(ns, 0)
9524  fr = framples(ns, 0)
9525  snd_test_neq([fr, ls, rs], [220501, 0, 220501], "show_full_duration 2")
9526  close_sound(ns)
9527  set_show_full_duration(false)
9528  set_initial_beg(0.0)
9529  set_initial_dur(0.2)
9530  ns = open_sound("1.snd")
9531  ls = left_sample(ns, 0)
9532  rs = right_sample(ns, 0)
9533  fr = framples(ns, 0)
9534  snd_test_neq([fr, ls, rs], [220501, 0, 4410], "show_full_duration 3")
9535  close_sound(ns)
9536  set_initial_beg(2.0)
9537  set_initial_dur(1.0)
9538  ns = open_sound("1.snd")
9539  ls = left_sample(ns, 0)
9540  rs = right_sample(ns, 0)
9541  fr = framples(ns, 0)
9542  snd_test_neq([fr, ls, rs], [220501, 44100, 66150], "show_full_duration 4")
9543  close_sound(ns)
9544  set_initial_beg(old_beg)
9545  set_initial_dur(old_dur)
9546  set_show_full_duration(old_show)
9547  old_sync = sync_style
9548  set_sync_style(Sync_none)
9549  ns = open_sound("2.snd")
9550  snd_test_neq(sync(ns), 0, "Sync_none open")
9551  set_sync(1, ns)
9552  set_sync_style(Sync_by_sound)
9553  ns1 = open_sound("1a.snd")
9554  snd_test_eq(sync(ns1), 1, "Sync_by_sound open")
9555  snd_test_neq(sync(ns), 1, "Sync_by_sound open")
9556  close_sound(ns1)
9557  close_sound(ns)
9558  set_sync_style(old_sync)
9559  #
9560  ind = view_sound("obtest.snd")
9561  delete_samples(0, 1000, ind, 0)
9562  res = Snd.catch do save_sound(ind) end
9563  if sound?(res.first)
9564    snd_display("save_viewed_sound: %s", res)
9565  end
9566  snd_test_neq(edits(ind), [1, 0], "view read_only ignored")
9567  close_sound(ind)
9568  #
9569  ind = new_sound("test.snd", 1, 22050, Mus_bfloat, Mus_next)
9570  insert_silence(0, 150000)
9571  map_channel(lambda do |y| 0.5 end)
9572  env_sound([0, 0, 1, 1, 2, 0])
9573  fp(1.0, 0.3, 20)
9574  old_cursor = with_tracking_cursor
9575  set_with_tracking_cursor(true)
9576  play(selected_sound, :wait, true)
9577  set_with_tracking_cursor(old_cursor)
9578  close_sound(ind)
9579  #
9580  ind = new_sound("test.snd", 1, 22050, Mus_bfloat, Mus_next)
9581  [150, 1500, 150000].each do |dur|
9582    insert_silence(0, dur)
9583    map_channel($init_channel)
9584    env_sound([0, 0, 1, 1, 2, 0])
9585    rd = make_sampler(framples - 1, ind, 0, -1)
9586    if (res = sampler_position(rd)) != (framples - 1)
9587      snd_display("sampler_position: %s?", res)
9588    end
9589    map_channel(lambda do |y| rd.call end)
9590    pos = 0
9591    e = make_env([0, 0, 1, 1, 2, 0], :length, dur + 1)
9592    scan_channel(lambda do |y|
9593      if fneq(val = env(e), y)
9594        snd_display("trouble in reverse read at %s %s %s", pos, val, y)
9595        true
9596      else
9597        pos += 1
9598        false
9599      end
9600    end)
9601    revert_sound
9602  end
9603  close_sound(ind)
9604  #
9605  ind = new_sound("test.snd", 1, 22050, Mus_bfloat, Mus_next)
9606  insert_silence(0, 1000)
9607  map_channel($init_channel)
9608  env_sound([0, 0, 1, 1, 2, 0])
9609  scale_channel(0.0, 100, 200)
9610  rd = make_sampler(framples - 1, ind, 0, -1)
9611  map_channel(lambda do |y| rd.call end)
9612  pos = 0
9613  e = make_env([0, 0, 1, 1, 2, 0], :length, 1001)
9614  scan_channel(lambda do |y|
9615    val = env(e)
9616    if ((pos > 900 or pos <= 700) and fneq(val, y)) or
9617      (pos > 700 and pos <= 900 and fneq(y, 0.0))
9618      snd_display("trouble in reverse read 2 at %s %s %s", pos, val, y)
9619      true
9620    else
9621      pos += 1
9622      false
9623    end
9624  end)
9625  close_sound(ind)
9626  #
9627  ind = new_sound("test.snd", 1, 22050, Mus_bfloat, Mus_next)
9628  insert_silence(0, 150000)
9629  map_channel($init_channel)
9630  edpos = edit_position
9631  7.times do |i|
9632    if i == 5
9633      scale_channel(0.5, 1000, 12345)
9634    end
9635    env_sound([0, 0, 1, 1, 2.5, 0, 3, 1, 4, 0])
9636    case i
9637    when 1
9638      delete_samples(50, 100)
9639    when 2
9640      insert_samples(300, 100, make_vct!(100) do 0.5 end)
9641    when 3
9642      scale_channel(0.0, 1000, 1000)
9643    when 4
9644      vct2channel(make_vct!(100) do 0.5 end, 500, 100)
9645    when 6
9646      env_sound([0, 1, 1, 0], 10000, 2000)
9647    end
9648    rd = make_sampler(framples - 1, ind, 0, -1)
9649    map_channel(lambda do |y| rd.call end)
9650    rd = make_sampler(framples - 1, ind, 0, -1)
9651    map_channel(lambda do |y| rd.call end)
9652    old_rd = make_sampler(0, ind, 0, 1, edit_position(ind, 0) - 2)
9653    pos = 0
9654    scan_channel(lambda do |y|
9655      if fneq(val = old_rd.call, y)
9656        snd_display("trouble in reverse (%s) read at %s %s %s", i, pos, val, y)
9657        true
9658      else
9659        pos += 1
9660        false
9661      end
9662    end)
9663  end
9664  set_edit_position(edpos, ind, 0)
9665  close_sound(ind)
9666  #
9667  reader = false
9668  last_proc = false
9669  scan_again = lambda do
9670    result = false
9671    until sampler_at_end?(reader)
9672      if val = last_proc.call(reader.call)
9673        result = [val, sampler_position(reader) - 1]
9674        break
9675      end
9676    end
9677    result
9678  end
9679  my_scan_chan = lambda do |proc|
9680    if proc
9681      last_proc = proc
9682      reader = make_sampler(0)
9683    end
9684    scan_again.call
9685  end
9686  ind = open_sound("oboe.snd")
9687  set_cursor(1000, ind, 0)
9688  if fneq(res = sample(1000), sample())
9689    snd_display("sample no args: %s %s", sample(), res)
9690  end
9691  req = [true, 4423]
9692  res = my_scan_chan.call(lambda do |y| y > 0.1 end)
9693  if res != req
9694    snd_display("my_scan_chan: res %s != req %s?", res, req)
9695  end
9696  req = [true, 4463]
9697  res = scan_again.call
9698  if res != req
9699    snd_display("scan_again: res %s != req %s?", res, req)
9700  end
9701  set_cursor(1000)
9702  # XXX: set_sample(0.5) isn't possible
9703  # Wrong_type_arg in set_sample: argument 1, 0.5, should be an integer
9704  set_sample(:undefined, 0.5)
9705  if fneq(res = sample(1000), 0.5)
9706    snd_display("set sample no arg: %s %s?", res, sample(0))
9707  end
9708  close_sound(ind)
9709end
9710
9711def test_05_26
9712  ind = new_sound("test.snd")
9713  map_chan(lambda do |y| 1.0 end, 0, 1000)
9714  env_channel(make_env([0, 1, 1, 1], :scaler, 0.5, :length, 1001))
9715  check_maxamp(ind, 0.5, "simple scaler")
9716  check_env_vals("simple scaler",
9717                 make_env([0, 1, 1, 1], :scaler, 0.5, :length, 1001))
9718  if edit_position == 2
9719    undo_edit
9720  else
9721    snd_display("env+scl was no-op")
9722  end
9723  env_channel(make_env([0, 1, 1, 1], :offset, 0.5, :length, 1001))
9724  check_maxamp(ind, 1.5, "simple offset")
9725  check_env_vals("simple offset",
9726                 make_env([0, 1, 1, 1], :offset, 0.5, :length, 1001))
9727  if edit_position == 2
9728    undo_edit
9729  else
9730    snd_display("env+offset was no-op")
9731  end
9732  env_channel(make_env([0, 0, 1, 1, 2, 0],
9733                       :offset, 0.5, :scaler, 2.0, :length, 1001))
9734  check_maxamp(ind, 2.5, "off+scl")
9735  check_env_vals("off+scl",
9736                 make_env([0, 0, 1, 1, 2, 0],
9737                          :offset, 0.5, :scaler, 2.0, :length, 1001))
9738  undo_edit
9739  env_channel(make_env([0, -0.5, 1, 0, 2, -1],
9740                       :offset, 0.5, :scaler, 2.0, :length, 1001))
9741  check_maxamp(ind, 1.5, "off+scl #2")
9742  mx = -12.0
9743  scan_channel(lambda do |y|
9744                 if y > mx
9745                   mx = y
9746                 end
9747                 false
9748               end)
9749  snd_test_neq(mx, 0.5, "non abs max (correct 0.5)")
9750  check_env_vals("off+scl #2",
9751                 make_env([0, -0.5, 1, 0, 2, -1],
9752                          :offset, 0.5, :scaler, 2.0, :length, 1001))
9753  undo_edit
9754  env_sound([0, 0.5, 1, 0.75, 2, 0.25], 0, framples(), 32.0)
9755  check_maxamp(ind, 0.75, "xramp")
9756  check_env_vals("xramp",
9757                 make_env([0, 0.5, 1, 0.75, 2, 0.25],
9758                          :base, 32.0, :length, 1001))
9759  undo_edit
9760  env_channel_with_base([0, 0.5, 1, 0.75, 2, 0.25], 32.0)
9761  check_maxamp(ind, 0.75, "xramp1")
9762  check_env_vals("xramp1",
9763                 make_env([0, 0.5, 1, 0.75, 2, 0.25],
9764                          :base, 32.0, :length, 1001))
9765  close_sound(ind)
9766  #
9767  hlb = make_hilbert_transform(8)
9768  snd_test_neq(make_vct!(20) do |i|
9769    hilbert_transform(hlb, (i == 0 ? 1.0 : 0.0))
9770  end, vct(0, -0.01, 0, -0.046, 0, -0.152, 0, -0.614, 0,
9771           0.614, 0, 0.152, 0, 0.046, 0, 0.01, 0, 0, 0, 0),
9772           "hilbert_transform 8 impulse response")
9773  hlb = make_hilbert_transform(7)
9774  snd_test_neq(make_vct!(20) do |i|
9775    hilbert_transform(hlb, (i == 0 ? 1.0 : 0.0))
9776  end, vct(-0.007, 0.0, -0.032, 0.0, -0.136, 0.0, -0.608,
9777           0.0, 0.608, 0.0, 0.136, 0.0, 0.032, 0.0, 0.007,
9778           0.0, 0.0, 0.0, 0.0, 0.0), "hilbert_transform 7 impulse response")
9779  ind = new_sound("test.snd")
9780  pad_channel(0, 1000)
9781  set_sample(100, 1.0)
9782  h = make_hilbert_transform(100)
9783  4.times do
9784    map_channel(lambda do |y| hilbert_transform(h, y) end)
9785  end
9786  snd_test_gt((sample(500) - 0.98).abs, 0.01, "hilbert impulse")
9787  set_sample(500, 0.0)
9788  snd_test_gt(maxamp(ind, 0), 0.02, "hilbert sidelobes")
9789  scale_channel(0.0)
9790  set_sample(100, 1.0)
9791  h = make_hilbert_transform(101)
9792  4.times do
9793    map_channel(lambda do |y| hilbert_transform(h, y) end)
9794  end
9795  snd_test_gt((sample(504) - 0.98).abs, 0.01, "hilbert 101 impulse")
9796  set_sample(504, 0.0)
9797  snd_test_gt(maxamp(ind, 0), 0.02, "hilbert 101 sidelobes")
9798  revert_sound
9799  pad_channel(0, 1000)
9800  set_sample(100, 1.0)
9801  lo = make_lowpass(PI * 0.1, 20)
9802  hi = make_highpass(PI * 0.1, 20)
9803  map_channel(lambda do |y| lowpass(lo, y) + highpass(hi, y) end)
9804  snd_test_neq(sample(120), 1.0, "lowpass+highpass impulse")
9805  set_sample(120, 0.0)
9806  snd_test_neq(maxamp(ind, 0), 0.0, "lowpass+highpass sidelobes")
9807  undo_edit(2)
9808  lo = make_bandpass(PI * 0.1, PI * 0.2, 20)
9809  hi = make_bandstop(PI * 0.1, PI * 0.2, 20)
9810  map_channel(lambda do |y| bandpass(lo, y) + bandpass(hi, y) end)
9811  snd_test_neq(sample(120), 1.0, "bandpass+bandstop impulse")
9812  set_sample(120, 0.0)
9813  snd_test_neq(maxamp(ind, 0), 0.0, "bandpass+bandstop sidelobes")
9814  close_sound(ind)
9815  #
9816  ind = new_sound("test.snd")
9817  map_channel(lambda do |y| mus_random(1.0) end, 0, 10000)
9818  f2 = make_bandpass_2(0.12 * PI, 0.15 * PI, 0.22 * PI, 0.25 * PI, 100)
9819  map_channel(lambda do |y| bandpass_2(f2, y) end)
9820  data = channel2vct
9821  undo_edit
9822  f1 = make_bandpass(0.12 * PI, 0.15 * PI, 100)
9823  f2 = make_bandpass(0.22 * PI, 0.25 * PI, 100)
9824  map_channel(lambda do |y| bandpass(f1, y) + bandpass(f2, y) end)
9825  data1 = channel2vct
9826  vct_subtract!(data, data1)
9827  res = vct_peak(data)
9828  if res > 0.00001
9829    snd_display(snd_format(res, 0.00001, "fir_filter 2"))
9830  end
9831  undo_edit
9832  close_sound(ind)
9833  #
9834  ind = new_sound("test.snd", 1, 22050, Mus_bfloat, Mus_next,
9835                  "ramp re-order tests", 100)
9836  map_channel(lambda do |y| 1.0 end)
9837  [["ramp-xramp", true,
9838      lambda do
9839        env_sound([0, 0, 1, 1, 2, 0])
9840        env_sound([0, 0, 1, 1], 0, 100, 2.0)
9841      end,
9842      lambda do
9843        env_sound([0, 0, 1, 1], 0, 100, 2.0)
9844        env_sound([0, 0, 1, 1, 2, 0])
9845      end],
9846    ["ramp2-xramp (1)", true,
9847      lambda do
9848        env_sound([0, 0, 1, 1, 2, 0])
9849        env_sound([0, 0, 1, 1, 3, 0])
9850        env_sound([0, 0, 1, 1], 0, 100, 2.0)
9851      end,
9852      lambda do
9853        env_sound([0, 0, 1, 1, 2, 0])
9854        env_sound([0, 0, 1, 1], 0, 100, 2.0)
9855        env_sound([0, 0, 1, 1, 3, 0])
9856      end],
9857    ["ramp2-xramp (2)", true,
9858      lambda do
9859        env_sound([0, 0, 1, 1, 2, 0])
9860        env_sound([0, 0, 1, 1])
9861        env_sound([0, 0, 1, 1, 3, 0], 0, 100, 2.0)
9862      end,
9863      lambda do
9864        env_sound([0, 0, 1, 1, 3, 0], 0, 100, 2.0)
9865        env_sound([0, 0, 1, 1, 2, 0])
9866        env_sound([0, 0, 1, 1])
9867      end],
9868    ["xramp2-ramp (1)", true,
9869      lambda do
9870        env_sound([0, 0, 1, 1, 2, 0], 0, 100, 2.0)
9871        env_sound([0, 0, 1, 1])
9872        env_sound([0, 0, 1, 1, 3, 0], 0, 100, 3.0)
9873      end,
9874      lambda do
9875        env_sound([0, 0, 1, 1, 2, 0], 0, 100, 2.0)
9876        env_sound([0, 0, 1, 1, 3, 0], 0, 100, 3.0)
9877        env_sound([0, 0, 1, 1])
9878      end],
9879    ["xramp2-ramp (2)", true,
9880      lambda do
9881        env_sound([0, 0, 1, 1, 2, 0], 0, 100, 2.0)
9882        env_sound([0, 0, 1, 1, 3, 0])
9883        env_sound([0, 0, 1, 1], 0, 100, 3.0)
9884      end,
9885      lambda do
9886        env_sound([0, 0, 1, 1, 3, 0])
9887        env_sound([0, 0, 1, 1, 2, 0], 0, 100, 2.0)
9888        env_sound([0, 0, 1, 1], 0, 100, 3.0)
9889      end],
9890    ["ramp4", true,
9891      lambda do
9892        env_sound([0, 0, 1, 1])
9893        env_sound([0, 0, 1, 1, 2, 0])
9894        env_sound([0, 0, 1, 1, 3, 0])
9895        env_sound([0, 0, 1, 1, 4, 0])
9896      end,
9897      lambda do
9898        env_sound([0, 0, 1, 1, 4, 0])
9899        env_sound([0, 0, 1, 1, 2, 0])
9900        env_sound([0, 0, 1, 1, 3, 0])
9901        env_sound([0, 0, 1, 1])
9902      end]].each do |name, try_scale, f1, f2|
9903    edpos = edit_position(ind, 0)
9904    f1.call
9905    v1 = channel2vct(0, 100, ind, 0)
9906    set_edit_position(edpos, ind, 0)
9907    f2.call
9908    v2 = channel2vct(0, 100, ind, 0)
9909    snd_test_neq(v1, v2, "env reordering test %s", name)
9910    set_edit_position(edpos, ind, 0)
9911    if try_scale
9912      scale_by(2.0)
9913      f1.call
9914      v1 = channel2vct(0, 100, ind, 0)
9915      set_edit_position(edpos, ind, 0)
9916      f2.call
9917      scale_by(2.0)
9918      v2 = channel2vct(0, 100, ind, 0)
9919      snd_test_neq(v1, v2, "scaled (2) env reordering test %s", name)
9920      set_edit_position(edpos, ind, 0)
9921      f1.call
9922      scale_by(0.5)
9923      v1 = channel2vct(0, 100, ind, 0)
9924      set_edit_position(edpos, ind, 0)
9925      scale_by(0.5)
9926      f2.call
9927      v2 = channel2vct(0, 100, ind, 0)
9928      snd_test_neq(v1, v2, "scaled (0.5) env reordering test %s", name)
9929      set_edit_position(edpos, ind, 0)
9930    end
9931  end
9932  close_sound(ind)
9933  # offset channel
9934  ind = new_sound("test.snd", 1, 22050, Mus_bfloat, Mus_next,
9935                  "offset tests", 10)
9936  offset_channel(0.1)
9937  snd_test_neq(channel2vct(0, 10), Vct.new(10, 0.1), "offset_channel (0.1)")
9938  offset_channel(-0.2, 5, 5)
9939  snd_test_neq(channel2vct(0, 10),
9940               vct(0.1, 0.1, 0.1, 0.1, 0.1, -0.1, -0.1, -0.1, -0.1, -0.1),
9941               "offset_channel (-0.1)")
9942  undo_edit
9943  offset_channel(0.9, 0, 10, ind, 0)
9944  snd_test_neq(channel2vct(0, 10), Vct.new(10, 1.0), "offset_channel (1.0)")
9945  revert_sound(ind)
9946  # sine_env and sine_ramp...
9947  map_channel($init_channel)
9948  sine_ramp(0.0, 1.0)
9949  snd_test_neq(channel2vct,
9950               vct(0.000, 0.024, 0.095, 0.206, 0.345, 0.500,
9951                   0.655, 0.794, 0.905, 0.976), "sine_ramp 0 1")
9952  revert_sound(ind)
9953  offset_channel(1.0)
9954  sine_ramp(1.0, 0.0)
9955  snd_test_neq(channel2vct,
9956               vct(1.000, 0.976, 0.905, 0.794, 0.655, 0.500,
9957                   0.345, 0.206, 0.095, 0.024), "sine_ramp 1 0")
9958  close_sound(ind)
9959  #
9960  ind = new_sound("test.snd", 1, 22050, Mus_bfloat, Mus_next,
9961                  "sine_env tests", 100)
9962  # map_channel($init_channel)
9963  map_channel(lambda do |y| 1.0 end)
9964  sine_env_channel([0, 0, 1, 1, 2, -0.5, 3, 1])
9965  snd_test_neq(channel2vct(20, 10),
9966               vct(0.664, 0.708, 0.750, 0.790, 0.827, 0.862,
9967                   0.893, 0.921, 0.944, 0.964), "sine_env_channel 0a")
9968  snd_test_neq(channel2vct(60, 10),
9969               vct(-0.381, -0.417, -0.446, -0.47, -0.486, -0.497,
9970                   -0.5, -0.497, -0.486, -0.47), "sine_env_channel 0b")
9971  snd_test_neq(edit_position(ind, 0), 2, "as_one_edit sine_env_channel")
9972  revert_sound(ind)
9973  offset_channel(-1.0)
9974  sine_env_channel([0, 0, 1, 1, 2, 1, 3, 0], 40, 20)
9975  snd_test_neq(channel2vct(40, 20),
9976               vct(0, -0.05, -0.188, -0.389, -0.611, -0.812, -0.95,
9977                   -1, -1, -1, -1, -1, -1, -1, -1, -0.95, -0.812,
9978                   -0.611, -0.389, -0.188), "off+sine_env a")
9979  snd_test_neq(channel2vct(30, 10), make_vct(10, -1.0), "off+sine_env b")
9980  revert_sound(ind)
9981  scale_by(0.0)
9982  dither_channel
9983  mx = maxamp
9984  if mx < 0.00003 or mx > 0.0001
9985    snd_display("dithering: %s", mx)
9986  end
9987  revert_sound(ind)
9988  map_channel(ring_mod(10, [0, 0, 1, hz2radians(100)]))
9989  osc_formants(0.99, vct(400, 800, 1200), vct(400, 800, 1200), vct(4, 2, 3))
9990  map_channel(zecho(0.5, 0.75, 6, 10.0))
9991  map_channel(flecho(0.5, 0.9))
9992  filtered_env([0, 0, 1, 1, 2, 0])
9993  map_channel(formant_filter(0.99, 2400))
9994  map_channel(comb_filter(0.8, 32))
9995  map_channel(zcomb(0.8, 32, [0, 0, 1, 10]))
9996  map_channel(notch_filter(0.8, 32))
9997  ind1 = open_sound("now.snd")
9998  select_sound(ind1)
9999  snd_test_neq(maxamp, 0.309, "squelch_vowels init")
10000  squelch_vowels
10001  snd_test_neq(maxamp, 0.047, "squelch_vowels maxamp")
10002  select_sound(ind)
10003  map_channel(cross_synthesis(ind1, 0.5, 128, 6.0))
10004  revert_sound(ind1)
10005  fft_edit(40, 8000)
10006  fft_squelch(0.1)
10007  close_sound(ind)
10008  revert_sound(ind1)
10009  scramble_channel(0.01)
10010  revert_sound(ind1)
10011  close_sound(ind1)
10012end
10013
10014def test_05_27
10015  ind = new_sound("test.snd", 1, 22050, Mus_bfloat, Mus_next,
10016                  "special env tests", 100)
10017  map_channel($init_channel)
10018  blackman4_ramp(0.0, 1.0)
10019  vals = channel2vct
10020  undo_edit
10021  blackman4_env_channel([0, 0, 1, 1])
10022  unless vequal(res = channel2vct, vals)
10023    snd_display("blackman4_env_channel/ramp:\n# %s\n# %s", vals, res)
10024  end
10025  undo_edit
10026  blackman4_ramp(0.0, 1.0, 0, 50)
10027  vals = channel2vct
10028  undo_edit
10029  blackman4_env_channel([0, 0, 1, 1, 2, 1])
10030  unless vequal(res = channel2vct, vals)
10031    snd_display("blackman4_env_channel/ramp 1:\n# %s\n# %s", vals, res)
10032  end
10033  undo_edit
10034  blackman4_env_channel([0, 0, 1, 1, 2, -0.5, 3, 0])
10035  unless vequal(res = channel2vct(60, 10),
10036                vct(-0.109, -0.217, -0.313, -0.392, -0.451,
10037                    -0.488, -0.499, -0.499, -0.499, -0.499))
10038    snd_display("blackman4_env_channel to -0.5: %s", res)
10039  end
10040  undo_edit
10041  #
10042  ramp_squared(0.0, 1.0)
10043  vals = channel2vct()
10044  undo_edit
10045  env_squared_channel([0, 0, 1, 1])
10046  snd_test_neq(channel2vct(), vals, "env_squared/ramp")
10047  undo_edit
10048  ramp_squared(0.0, 1.0, true, 0, 50)
10049  vals = channel2vct
10050  undo_edit
10051  env_squared_channel([0, 0, 1, 1, 2, 1])
10052  snd_test_neq(channel2vct(), vals, "env_squared/ramp 1")
10053  undo_edit
10054  env_squared_channel([0, 0, 1, 1, 2, -0.5, 3, 0])
10055  req = vct(-0.450, -0.466, -0.478, -0.488, -0.494,
10056            -0.499, -0.500, -0.500, -0.498, -0.496)
10057  snd_test_neq(channel2vct(60, 10), req, "env_squared to -0.5")
10058  undo_edit
10059  env_squared_channel([0, 0, 1, 1, 2, -0.5, 3, 0], false)
10060  req = vct(-0.004, -0.080, -0.158, -0.240, -0.324,
10061            -0.410, -0.500, -0.500, -0.498, -0.496)
10062  snd_test_neq(channel2vct(60, 10), req, "env_squared unsymmetric to -0.5")
10063  undo_edit
10064  #
10065  ramp_squared(0.0, 1.0)
10066  vals = channel2vct
10067  undo_edit
10068  env_expt_channel([0, 0, 1, 1], 2)
10069  unless vequal(res = channel2vct, vals)
10070    snd_display("env_expt2/ramp:\n# %s\n# %s", vals, res)
10071  end
10072  undo_edit
10073  env_squared_channel([0, 0, 1, 1, 2, -0.5, 3, 0])
10074  vals = channel2vct
10075  undo_edit
10076  env_expt_channel([0, 0, 1, 1, 2, -0.5, 3, 0], 2.0)
10077  unless vequal(res = channel2vct, vals)
10078    snd_display("env_expt2/env_squared:\n# %s\n# %s", vals, res)
10079  end
10080  undo_edit
10081  env_squared_channel([0, 0, 1, 1, 2, -0.5, 3, 0], false)
10082  vals = channel2vct
10083  undo_edit
10084  env_expt_channel([0, 0, 1, 1, 2, -0.5, 3, 0], 2.0, false)
10085  unless vequal(res = channel2vct, vals)
10086    snd_display("env_expt2/env_squared unsymmetric:\n# %s\n# %s", vals, res)
10087  end
10088  undo_edit
10089  #
10090  ramp_expt(0.0, 1.0, 32.0)
10091  vals = channel2vct()
10092  undo_edit
10093  env_expt_channel([0, 0, 1, 1], 32.0)
10094  snd_test_neq(channel2vct(), vals, "env_expt/ramp 32")
10095  undo_edit
10096  ramp_expt(0.0, 1.0, 32.0, false, 0, 50)
10097  vals = channel2vct()
10098  undo_edit
10099  env_expt_channel([0, 0, 1, 1, 2, 1], 32.0)
10100  snd_test_neq(channel2vct(), vals, "env_expt/ramp 1 32")
10101  undo_edit
10102  ramp_expt(0.0, 1.0, 0.1)
10103  vals = channel2vct()
10104  undo_edit
10105  env_expt_channel([0, 0, 1, 1], 0.1)
10106  snd_test_neq(channel2vct(), vals, "env_expt/ramp 0.1")
10107  undo_edit
10108  env_expt_channel([0, 0, 1, 1, 2, -0.5, 3, 0], 12.0)
10109  req = vct(0.319, 0.472, 0.691, 1.000, 0.537,
10110            0.208, -0.022, -0.182, -0.291, -0.365)
10111  snd_test_neq(channel2vct(30, 10), req, "env_expt to -0.5 12.0")
10112  undo_edit
10113  env_expt_channel([0, 0, 1, 1, 2, -0.5, 3, 0], 12.0, false)
10114  req = vct(0.319, 0.472, 0.691, 1.000, 1.000,
10115            1.000, 1.000, 1.000, 1.000, 1.000)
10116  snd_test_neq(channel2vct(30, 10), req, "env_expt ot -0.5 12.0 unsymmetric")
10117  undo_edit
10118  close_sound(ind)
10119  #
10120  ind0 = open_sound("oboe.snd")
10121  ind1 = open_sound("pistol.snd")
10122  if res = channel_clipped?(ind0, 0)
10123    snd_display("channel_clipped? oboe.snd: %s?", res)
10124  end
10125  scale_to(1.5, ind0, 0)
10126  req = 4503
10127  res = channel_clipped?(ind0, 0)
10128  if res != req
10129    snd_display("channel_clipped? after scale: res %s != req %s?", res, req)
10130  end
10131  revert_sound(ind0)
10132  4.times do ramp_channel(0.0, 1.0, 0, false, ind1, 0) end
10133  make_selection(1000, 2000, ind1, 0)
10134  set_sync(1, ind0)
10135  set_selected_sound(ind0)
10136  env_selection([0, 0, 1, 1])
10137  if (res0 = edit_position(ind0, 0)) != 0 or
10138    (res1 = edit_position(ind1)) != 5
10139    snd_display("selection override of sync field: %s %s?", res0, res1)
10140  end
10141  env_sound([0, 0, 1, 1, 2, 0])
10142  if (res0 = edit_position(ind0, 0)) != 1 or
10143    (res1 = edit_position(ind1)) != 5
10144    snd_display("sync field over selection: %s %s?", res0, res1)
10145  end
10146  close_sound(ind0)
10147  close_sound(ind1)
10148end
10149
10150def test_05
10151  $clmtest = 0
10152  test_05_00 if $with_test_gui # no set_x_axis_label
10153  test_05_01
10154  test_05_02
10155  test_05_03
10156  test_05_04
10157  test_05_05
10158  test_05_06
10159  test_05_07
10160  test_05_08
10161  test_05_09
10162  test_05_10 if $with_test_gui
10163  test_05_11
10164  test_05_12 if $with_test_gui
10165  test_05_13
10166  test_05_14 if $with_test_gui
10167  test_05_15
10168  test_05_16
10169  test_05_17
10170  test_05_18
10171  test_05_20
10172  test_05_22
10173  test_05_23 if $with_test_gui # load("s61.rb") -> set_transform_size(0)
10174  test_05_24
10175  test_05_25
10176  test_05_26
10177  test_05_27
10178end
10179
10180# ---------------- test 06: vcts ----------------
10181
10182def test_06
10183  # setting print_length (12) and vct_print_length (10) to the same size
10184  set_print_length(print_length)
10185  #
10186  v0 = make_vct(10)
10187  v1 = Vct.new(10)
10188  vlst = make_vct(3)
10189  snd_test_neq(vct?(v0), true, "v0 is not a vct?")
10190  snd_test_neq(v0.kind_of?(Vct), true, "v0 is not kind_of? Vct?")
10191  snd_test_eq(v0, 10, "v0 is 10")
10192  snd_test_neq(vct?(10), false, "10 is a vct?")
10193  snd_test_neq(v0.length, 10, "Vct#length")
10194  vct_fill!(v0, 1.0)
10195  v1.fill(0.5)
10196  if v0.eql?(v1)
10197    snd_format_eq(v0, v1, "Vct#eql?")
10198  end
10199  if v0 == v1
10200    snd_format_eq(v0, v1, "Vct#==")
10201  end
10202  v2 = v1
10203  v3 = Vct.new(10)
10204  v4 = make_vct(3)
10205  unless v1.eql?(v2)
10206    snd_format_neq(v1, v2, "not Vct#eql? (1)")
10207  end
10208  vct_fill!(v3, 0.5)
10209  unless v2.eql?(v1)
10210    snd_format_neq(v2, v1, "not Vct#eql? (2)")
10211  end
10212  if v4.eql?(v1)
10213    snd_format_eq(v4, v1, "len diff Vct#eql?")
10214  end
10215  vct_set!(v3, 0, 1.0)
10216  snd_test_neq(vct_ref(v3, 0), 1.0, "vct_set!")
10217  v3[0] = 1.0
10218  snd_test_neq(v3[0], 1.0, "Vct#[]=")
10219  vlst[1] = 0.1
10220  snd_test_neq(vct2list(vlst), [0.0, 0.1, 0.0], "vct2list")
10221  vect = [0.0, 1.0, 2.0, 3.0]
10222  v123 = vct(0.0, 1.0, 2.0, 3.0)
10223  v2 = vect.to_vct
10224  v3 = v2
10225  str = format("%s", v2.to_s)
10226  str1 = format("%s", make_vct(32).to_s)
10227  snd_test_neq(vct?(vector2vct(make_array(0))), true, "vector2vct empty vect")
10228  snd_test_neq(vct?(make_array(0).to_vct), true,
10229    "make_array(0).to_vct empty vect")
10230  snd_test_neq(str, "#<vct[len=4]: 0.000 1.000 2.000 3.000>", "Vct#to_s")
10231  snd_test_neq(v123, v2, "vector2vct")
10232  snd_test_neq(vct2vector(v123), vect, "vct2vector")
10233  snd_test_neq(v123.to_a, vect, "Vct#to_a")
10234  unless v3.eql?(v2)
10235    snd_format_neq(v3, v2, "Vct#eql?")
10236  end
10237  snd_test_neq(v2.length, 4, "vector2vct#length")
10238  snd_test_neq(v2[2], 2.0, "vector2vct[2]")
10239  vct_move!(v2, 0, 2)
10240  snd_test_neq(v2[0], 2.0, "vct_move!")
10241  v2 = Vct.new(4) do |i| i end
10242  v2.move!(3, 2, true)
10243  snd_test_neq(v2[2], 1.0, "Vct#move! back (1)")
10244  snd_test_neq(v2[3], 2.0, "Vct#move! back (2)")
10245  snd_test_neq(vct(3, 2, 1), vct_reverse!(vct(1, 2, 3)), "vct_reverse!")
10246  snd_test_neq(vct(3, 2, 1), vct(1, 2, 3).reverse, "Vct#reverse")
10247  snd_test_neq(vct(2, 1), vct_reverse!(vct(1, 2)), "vct_reverse!")
10248  snd_test_neq(vct(1), vct(1).reverse, "vct(1)#reverse")
10249  snd_test_neq(vct(4, 3, 2, 1), vct(1, 2, 3, 4).reverse(4), "Vct#reverse(4)")
10250  snd_test_neq(vct(3, 2, 1), vct_reverse!(vct(1, 2, 3), 3), "vct_reverse(3)")
10251  snd_test_neq(vct(2, 1), vct(1, 2).reverse(2), "Vct#reverse(2)")
10252  snd_test_neq(vct(1), vct_reverse!(vct(1), 1), "vct_reverse!(1)")
10253  #
10254  vv0 = Vct.new(3)
10255  snd_test_neq(Snd.catch do vct_ref(vv0, 10) end.first,
10256    :out_of_range, "vct_ref high index")
10257  snd_test_neq(Snd.catch do vv0[-4] end.first,
10258    :out_of_range, "Vct#[] low index")
10259  snd_test_neq(Snd.catch do vct_set!(vv0, 10, 1.0) end.first,
10260    :out_of_range, "vct_set! high index")
10261  snd_test_neq(Snd.catch do vv0[-1] = 1.0 end.first,
10262    :out_of_range, "Vct#[]= low index")
10263  snd_test_neq(Snd.catch do vct_move!(vv0, 10, 0, true) end.first,
10264    :out_of_range, "vct_move! high index")
10265  snd_test_neq(Snd.catch do vv0.move(0, 10, true) end.first,
10266    :out_of_range, "Vct#move high 2 index")
10267  snd_test_neq(Snd.catch do vct_move!(vv0, -10, 0, false) end.first,
10268    :out_of_range, "vct_move! back high index")
10269  snd_test_neq(Snd.catch do vv0.move!(0, -10, false) end.first,
10270    :out_of_range, "Vct#move! back high 2 index")
10271  10.times do |i|
10272    snd_test_neq(v0[i], 1.0, "fill v0[%d]", i)
10273    snd_test_neq(v1[i], 0.5, "preset v1[%d]", i)
10274  end
10275  # add
10276  v0.add(v1).each_with_index do |x, i|
10277    snd_test_neq(x, 1.5, "Vct#add[%d]", i)
10278  end
10279  (v0 + v1).each_with_index do |x, i|
10280    snd_test_neq(x, 1.5, "Vct#+[%d]", i)
10281  end
10282  vct_add!(v0, v1)
10283  v0.each_with_index do |x, i|
10284    snd_test_neq(x, 1.5, "vct_add![%d]", i)
10285  end
10286  # subtract
10287  v0.subtract(v1).each_with_index do |x, i|
10288    snd_test_neq(x, 1.0, "Vct#subtract[%d]", i)
10289  end
10290  (v0 - v1).each_with_index do |x, i|
10291    snd_test_neq(x, 1.0, "Vct#-[%d]", i)
10292  end
10293  vct_subtract!(v0, v1)
10294  v0.each_with_index do |x, i|
10295    snd_test_neq(x, 1.0, "vct_subtract![%d]", i)
10296  end
10297  # dup, vct_copy
10298  v0.dup.each_with_index do |x, i|
10299    snd_test_neq(x, 1.0, "Vct#dup[%d]", i)
10300  end
10301  v2 = vct_copy(v0)
10302  v2.each_with_index do |x, i|
10303    snd_test_neq(x, 1.0, "vct_copy[%d]", i)
10304  end
10305  # scale
10306  v2.scale(5.0).each_with_index do |x, i|
10307    snd_test_neq(x, 5.0, "Vct#scale[%d]", i)
10308  end
10309  (v2 * 5.0).each_with_index do |x, i|
10310    snd_test_neq(x, 5.0, "Vct#*[%d]", i)
10311  end
10312  vct_scale!(v2, 5.0)
10313  v2.each_with_index do |x, i|
10314    snd_test_neq(x, 5.0, "vct_scale![%d]", i)
10315  end
10316  # offset
10317  v0.offset(-1.0).each_with_index do |x, i|
10318    snd_test_neq(x, 0.0, "Vct#offset[%d]", i)
10319  end
10320  (v0 + -1.0).each_with_index do |x, i|
10321    snd_test_neq(x, 0.0, "Vct#+[%d]", i)
10322  end
10323  vct_offset!(v0, -1.0)
10324  v0.each_with_index do |x, i|
10325    snd_test_neq(x, 0.0, "vct_offset![%d]", i)
10326  end
10327  # multiply
10328  v2.multiply(v1).each_with_index do |x, i|
10329    snd_test_neq(x, 2.5, "Vct#multiply[%d]", i)
10330  end
10331  (v2 * v1).each_with_index do |x, i|
10332    snd_test_neq(x, 2.5, "Vct#*[%d]", i)
10333  end
10334  vct_multiply!(v2, v1)
10335  v2.each_with_index do |x, i|
10336    snd_test_neq(x, 2.5, "vct_multiply![%d]", i)
10337  end
10338  #
10339  snd_test_neq(vct_peak(v2), 2.5, "vct_peak (1)")
10340  snd_test_neq(v2.peak, 2.5, "Vct#peak (1)")
10341  v2[5] = 123.0
10342  snd_test_neq(vct_peak(v2), 123.0, "vct_peak (2)")
10343  snd_test_neq(v2.peak, 123.0, "Vct#peak (2)")
10344  vn = Vct.new(32) do |i| i end
10345  vb = make_vct(64)
10346  vs = make_vct(3)
10347  vss = Vct.new(1)
10348  vnew = vct_subseq(vn, 3)
10349  snd_test_neq(vnew[0], 3.0, "vct_subseq[3:]")
10350  snd_test_neq(vnew.length, 29, "vct_subseq[3:] length")
10351  vnew = vn.subseq(3, 8)
10352  snd_test_neq(vnew[0], 3.0, "Vct#subseq[3:8]")
10353  snd_test_neq(vnew.length, 6, "Vct#subseq[3:8] length")
10354  vct_subseq(vn, 3, 3, vs)
10355  snd_test_neq(vs[0], 3.0, "vct_subseq[3:3->vs] (1)")
10356  snd_test_neq(vs[1], 0.0, "vct_subseq[3:3->vs] (2)")
10357  snd_test_neq(vs[2], 0.0, "vct_subseq[3:3->vs] (3)")
10358  vn.subseq(0, 32, vs)
10359  snd_test_neq(vs.length, 3, "Vct#subseq[:32->vs] length")
10360  vn.subseq(2, 3, vss)
10361  snd_test_neq(vss[0], 2.0, "Vct#subseq[2:3->vss]")
10362  vb[8] = 123.0
10363  vct_subseq(vn, 1, 8, vb)
10364  snd_test_neq(vb[0], 1.0, "vct_subseq[1:8->vb][0]")
10365  snd_test_neq(vb[8], 123.0, "vct_subseq[1:8->vb][8]")
10366  # vct_add, vct_multiply (vct+, vct*)
10367  v1 = Vct.new(3, 0.1)
10368  v2 = make_vct(4, 0.2)
10369  snd_test_neq(vct_add(v1.dup, v2), vct(0.3, 0.3, 0.3), "vct_add 0.1 0.2")
10370  snd_test_neq(v1 + v2, vct(0.3, 0.3, 0.3), "Vct#+ 0.1 0.2")
10371  v1[1] = 0.3
10372  snd_test_neq(vct_add(v1.dup, v2), vct(0.3, 0.5, 0.3), "vct_add 0.1 0.2 (1)")
10373  snd_test_neq(v1 + v2, vct(0.3, 0.5, 0.3), "Vct#+ 0.1 0.2 (1)")
10374  snd_test_neq(vct_add(v1.dup, 2.0), vct(2.1, 2.3, 2.1), "vct_add 0.1 2.0")
10375  snd_test_neq(v1 + 2.0, vct(2.1, 2.3, 2.1), "Vct#+ 0.1 2.0")
10376  snd_test_neq(vct_add(2.0, v1.dup), vct(2.1, 2.3, 2.1), "vct_add 0.1 2.0 (1)")
10377  snd_test_neq(2.0 + v1, vct(2.1, 2.3, 2.1), "2.0#+(v1) 0.1 2.0 (1)")
10378  snd_test_neq(vct_multiply(2.0, v1.dup), vct(0.2, 0.6, 0.2), "vct_multiply 2")
10379  snd_test_neq(2.0 * v1, vct(0.2, 0.6, 0.2), "2.0#*(v1)")
10380  snd_test_neq(vct_multiply(v1.dup, 2.0), vct(0.2, 0.6, 0.2),
10381    "vct_multiply 2 (1)")
10382  snd_test_neq(v1 * 2.0, vct(0.2, 0.6, 0.2), "Vct#* 2 (1)")
10383  snd_test_neq(vct_multiply(v1.dup, v2), vct(0.02, 0.06, 0.02),
10384    "vct_multiply v1 v2")
10385  snd_test_neq(v1 * v2, vct(0.02, 0.06, 0.02), "Vct#*(v2)")
10386  #
10387  v0.map do |val| PI end.each_with_index do |x, i|
10388    snd_test_neq(x, PI, "Vct#map[%d]", i)
10389  end
10390  v0.map! do |x| 1.0 end
10391  v0.each_with_index do |x, i|
10392    snd_test_neq(x, 1.0, "Vct#map[%d] 1.0", i)
10393  end
10394  #
10395  snd_test_neq(vct(1.0, 2.0, 3.0)[1], 2.0, "vct(...)[1]")
10396  v1 = [1, 2, 3, 4].to_vct
10397  snd_test_neq(v1[1], 2.0, "Vct#[1]")
10398  #
10399  ind = open_sound("oboe.snd")
10400  set_speed_control(0.5, ind)
10401  play(selected_sound, :wait, true)
10402  apply_controls
10403  revert_sound
10404  reset_controls(ind)
10405  #
10406  # try some special cases
10407  #
10408  apply_controls
10409  snd_test_neq(edit_position(ind), 0, "apply_controls with no change")
10410  set_speed_control(-1.0, ind)
10411  apply_controls
10412  if $with_test_gui
10413    snd_test_neq(edit_position(ind), 1, "apply_controls with srate -1.0")
10414  end
10415  if ((res0 = framples(ind, 0)) - (res1 = framples(ind, 0, 0))).abs > 2
10416    snd_display("apply_controls srate -1.0 lengths: %s %s", res0, res1)
10417  end
10418  res1 = sample(9327)
10419  if fneq(res0 = maxamp, 0.147) or res1.abs < 0.01
10420    snd_display("apply_controls srate -1.0 samples: %s %s?", res0, res1)
10421  end
10422  snd_test_neq(speed_control(ind), 1.0, "apply_controls -1.0")
10423  set_speed_control(1.5)
10424  apply_controls
10425  revert_sound
10426  set_speed_control(1.5)
10427  $after_apply_controls_hook.add_hook!("snd-test") do |s|
10428    snd_test_neq(Snd.catch do apply_controls() end.first,
10429      :cannot_apply_controls,
10430      "after_apply_controls_hook: recursive attempt apply_controls")
10431  end
10432  apply_controls
10433  $after_apply_controls_hook.reset_hook!
10434  revert_sound
10435  close_sound(ind)
10436  #
10437  # Vct.new.map twice, and Vct.new twice
10438  #
10439  v1 = Vct.new(32)
10440  v1.map! do
10441    v2 = Vct.new(3)
10442    v2.map! do 0.1 end
10443    v2.first
10444  end
10445  snd_test_neq(v1[12], 0.1, "v.map! twice")
10446  Vct.new(32) do Vct.new(3) do 0.1 end.first end
10447  snd_test_neq(v1[12], 0.1, "v.new twice")
10448  hi = make_vct(3)
10449  snd_test_neq(Snd.catch do vct_subseq(hi, 1, 0) end.first,
10450   :out_of_range, "vct_subseq 1 0")
10451  snd_test_neq(vct?(vct()), true, "vct() not a vct")
10452  snd_test_neq(vct?(make_vct(0)), true, "make_vct(0) not a vct")
10453  v0 = make_vct(5, 0.1)
10454  v1 = make_vct(6, 0.2)
10455  v0.add!(v1, 2)
10456  snd_test_neq(v0, [0.1, 0.1, 0.3, 0.3, 0.3].to_vct, "v.add! + offset")
10457  #
10458  # vct methods
10459  #
10460  snd_test_neq(Vct.new(10), make_vct(10), "Vct#new 0.000")
10461  snd_test_neq(Vct.new(10, 3.14), make_vct(10, 3.14), "Vct#new 3.140")
10462  v1 = Vct.new(10) do |i| i * 0.01 end
10463  v2 = make_vct(10)
10464  ctr = -1
10465  v2.map! do |x| (ctr += 1) * 0.01 end
10466  snd_test_neq(v1, v2, "Vct#new 0.000 0.010 0.020...")
10467  snd_test_neq(vct_ref(v1, 8), v2[8], "Vct#[] (1)")
10468  snd_test_neq(v2[8], 0.08, "Vct#[] (2)")
10469  vct_set!(v1, 8, 0.5)
10470  v2[8] = 0.5
10471  snd_test_neq(vct_ref(v1, 8), v2[8], "Vct#[]= (1)")
10472  snd_test_neq(v2[8], 0.5, "Vct#[]= (2)")
10473  snd_test_neq(v1.length, vct_length(v2), "Vct#length (1)")
10474  snd_test_neq(v2.length, vct_length(v1), "Vct#length (2)")
10475  snd_test_neq(v2.length, 10, "Vct#length (3)")
10476  v1.each_with_index do |val, i|
10477    snd_test_neq(val, v2[i], "Vct#each (%d)", i)
10478  end
10479  snd_test_neq(v1 <=> v2, 0, "Vct#<=> (0)")
10480  snd_test_neq(Vct.new(10) do |i| i * 0.001 end <=> v1, -1, "Vct#<=> (-1)")
10481  snd_test_neq(v2 <=> Vct.new(10) do |i| i * 0.001 end, 1, "Vct#<=> (1)")
10482  v2.map! do |val| val + 0.5 end
10483  v3 = v1.map do |val| val + 0.5 end
10484  snd_test_neq(v2, v3, "Vct#map(!)")
10485  v2 = v1.dup
10486  snd_test_neq(v1 <=> v2, 0, "Vct#dup")
10487  vec1 = make_array(10) do |i| i * 0.01 end
10488  vec1[8] = 0.5
10489  vec2 = v2.to_a
10490  snd_test_neq(vec1, vec2, "Vct#to_a")
10491  snd_test_neq(vec1.to_vct, v1, "Array#to_vct")
10492  snd_test_neq(vct2string(v1), v2.to_str, "Vct#to_str")
10493  snd_test_neq(v2.to_str, "\
10494vct(0.000, 0.010, 0.020, 0.030, 0.040, 0.050, 0.060, 0.070, 0.500, 0.090)",
10495    "Vct#to_str")
10496  snd_test_neq(v1.peak, vct_peak(v2), "Vct#peak")
10497  v3 = v1.dup
10498  v3.add!(v2)
10499  v4 = v1.add(v2)
10500  snd_test_neq(v3, v4, "Vct#add(!)")
10501  v3 = v1.dup
10502  v3.subtract!(v2)
10503  v4 = v1.subtract(v2)
10504  snd_test_neq(v3, v4, "Vct#subtract(!)")
10505  v3 = v1.dup
10506  v3.multiply!(v2)
10507  v4 = v1.multiply(v2)
10508  snd_test_neq(v3, v4, "Vct#multiply(!)")
10509  v3 = v1.dup
10510  v3.offset!(0.5)
10511  v4 = v1.offset(0.5)
10512  snd_test_neq(v3, v4, "Vct#offset(!)")
10513  v3 = v1.dup
10514  v3.scale!(2.0)
10515  v4 = v1.scale(2.0)
10516  snd_test_neq(v3, v4, "Vct#scale(!)")
10517  v3 = Vct.new(10)
10518  v4 = Vct.new(10)
10519  v3.fill(0.5)
10520  vct_fill!(v4, 0.5)
10521  snd_test_neq(v3, v4, "Vct#fill(!)")
10522  snd_test_neq(v1.first, vct_ref(v2, 0), "Vct#first")
10523  snd_test_neq(v1.last, vct_ref(v2, vct_length(v2) - 1), "Vct#last")
10524  v1.first = 0.2
10525  vct_set!(v2, 0, 0.2)
10526  snd_test_neq(v1.first, vct_ref(v2, 0), "Vct#first (2)")
10527  snd_test_neq(v1.first, 0.2, "Vct#first (3)")
10528  v1.last = 0.3
10529  vct_set!(v2, vct_length(v2) - 1, 0.3)
10530  snd_test_neq(v1.last, vct_ref(v2, vct_length(v2) - 1), "Vct#last (2)")
10531  snd_test_neq(v1.last, 0.3, "Vct#last (3)")
10532end
10533
10534# ---------------- test 07: colors ----------------
10535
10536def test_07_00
10537  c1 = Snd.catch(:no_such_color, false) do make_color(0, 0, 1) end.first
10538  c2 = c1
10539  c3 = Snd.catch(:no_such_color, false) do make_color(0, 0, 1) end.first
10540  unless c1.equal?(c2)
10541    snd_display("color equal? %s %s", c1, c2)
10542  end
10543  unless c1.eql?(c2)
10544    snd_display("color eql? %s %s", c1, c2)
10545  end
10546  unless c1 == c2
10547    snd_display("color == %s %s", c1, c2)
10548  end
10549  if (res = color2list(c1)) != [0.0, 0.0, 1.0]
10550    snd_display("color2list: %s %s?", c1, res)
10551  end
10552  true_color_list = [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 1.0, 1.0],
10553                     [0.0, 0.0, 7.01915007248035e-4], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0],
10554                     [0.0, 0.0, 0.49999], [1.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 1.0],
10555                     [1.0, 0.0, 1.0], [0.0, 0.500007629510948, 0.4], [1.0, 0.0, 0.0],
10556                     [1.0, 0.0, 0.0], [0.0, 0.0, 1.0]]
10557  15.times do |i|
10558    cm = integer2colormap(i)
10559    if colormap?(cm)
10560      res0 = colormap_ref(cm, 0)
10561      res1 = true_color_list[i]
10562      unless vequal(res0, res1)
10563        snd_display("colormap_ref[%s]: %s (%s)", cm, res0, res1)
10564      end
10565    end
10566  end
10567  Snd.catch do
10568    [[:basic_color, Ivory2],
10569     [:cursor_color, Red],
10570     [:data_color, Black],
10571     [:enved_waveform_color, Blue],
10572     [:filter_control_waveform_color, Blue],
10573     [:graph_color, White],
10574     [:highlight_color, Ivory1],
10575     [:listener_color, Alice_blue],
10576     [:listener_text_color, Black],
10577     [:mark_color, Red],
10578     [:mix_color, Dark_gray],
10579     [:position_color, Ivory3],
10580     [:sash_color, Light_green],
10581     [:selected_data_color, Black],
10582     [:selected_graph_color, White],
10583     [:selection_color, Lightsteelblue1],
10584     [:text_focus_color, White],
10585     [:zoom_color, Ivory4]].each do |getfnc, initval|
10586      unless color?(initval)
10587        snd_display("%s not color?", initval)
10588      end
10589      set_snd_func(getfnc, Beige)
10590      if (res = snd_func(getfnc)) != Beige
10591        snd_display("set_%s != Beige (%s)?", getfnc, res)
10592      end
10593      set_snd_func(getfnc, initval)
10594    end
10595    ind = open_sound("oboe.snd")
10596    set_selected_data_color(Light_green)
10597    set_data_color(Blue)
10598    set_selected_graph_color(Light_green)
10599    if $with_test_motif
10600      red = make_color_with_catch(1.0, 0.0, 0.0)
10601      set_foreground_color(red, ind, 0, Cursor_context)
10602      if (res = foreground_color(ind, 0, Cursor_context)) != red
10603        snd_display("set_foreground_color cursor: %s %s?", res, red)
10604      end
10605      set_foreground_color(Blue)
10606      if (res = foreground_color) != Blue
10607        snd_display("set_foreground_color: %s %s?", res, Blue)
10608      end
10609      set_foreground_color(Red, ind)
10610      if (res = foreground_color(ind)) != Red
10611        snd_display("set_foreground_color with ind (Red): %s %s?", res, Red)
10612      end
10613      set_foreground_color(Black, ind)
10614      if (res = foreground_color(ind)) != Black
10615        snd_display("set_foreground_color with ind (Black): %s %s?", res, Black)
10616      end
10617    end
10618    set_selected_graph_color(make_color_with_catch(0.96, 0.96, 0.86))
10619    set_data_color(Black)
10620    set_selected_data_color(Blue)
10621    set_data_color(White)
10622    close_sound(ind)
10623  end
10624end
10625
10626def check_colormap(name, colmap, x, r, g, b, n, err)
10627  r1, g1, b1 = colormap_ref(colmap, x)
10628  if x < (1.0 - (1.0 / n)) and
10629      (fneq_err(r, r1, err) or
10630       fneq_err(g, g1, err) or
10631       fneq_err(b, b1, err))
10632    snd_display_prev_caller("%s %1.4f (%1.4f): %s %s",
10633                            name,
10634                            x,
10635                            [(r - r1).abs, (g - g1).abs, (b - b1).abs].max,
10636                            [r, g, b],
10637                            [r1, g1, b1])
10638  end
10639end
10640
10641def test_07_01
10642  [[512, 0.005], [64, 0.04]].each do |n, err|
10643    set_colormap_size(n)
10644    10.times do |i|
10645      x = random(1.0)
10646      r = (x < (3.0 / 4)) ? ((7.0 / 8) * x) : ((11.0 / 8) * x - 3.0 / 8)
10647      g = (x < (3.0 / 8)) ? ((7.0 / 8) * x) : ((x < (3.0 / 4)) ?
10648                                               ((29.0 / 24) * x - 1.0 / 8) :
10649                                               ((7.0 / 8) * x + 1.0 / 8))
10650      b = (x < (3.0 / 8)) ? ((29.0 / 24) * x) : ((7.0 / 8) * x + 1.0 / 8)
10651      check_colormap("bone", $bone_colormap, x, r, g, b, n, err)
10652    end
10653    10.times do |i|
10654      x = random(1.0)
10655      r = (x < (4.0 / 5)) ? ((5.0 / 4) * x) : 1.0
10656      g = (4.0 / 5) * x
10657      b = (1.0 / 2) * x
10658      check_colormap("copper", $copper_colormap, x, r, g, b, n, err)
10659    end
10660    10.times do |i|
10661      x = random(1.0)
10662      r = 0.0
10663      g = x
10664      b = 1.0 - g / 2.0
10665      check_colormap("winter", $winter_colormap, x, r, g, b, n, err)
10666    end
10667    10.times do |i|
10668      x = random(1.0)
10669      r = 1.0
10670      g = x
10671      b = 0.0
10672      check_colormap("autumn", $autumn_colormap, x, r, g, b, n, err)
10673    end
10674    10.times do |i|
10675      x = random(1.0)
10676      r = x
10677      g = 1.0 - r
10678      b = 1.0
10679      check_colormap("cool", $cool_colormap, x, r, g, b, n, err)
10680    end
10681    10.times do |i|
10682      x = random(1.0)
10683      r = (x < (3.0 / 8)) ? ((8.0 / 3) * x) : 1.0
10684      g = (x < (3.0 / 8)) ? 0.0 : ((x < (3.0 / 4)) ? ((8.0 / 3) * x - 1.0) : 1.0)
10685      b = (x < (3.0 / 4)) ? 0.0 : (4.0 * x - 3)
10686      check_colormap("hot", $hot_colormap, x, r, g, b, n, err)
10687    end
10688    10.times do |i|
10689      x = random(1.0)
10690      r = (x < (3.0 / 8)) ? 0.0 : ((x < (5.0 / 8)) ? (4.0 * x - 3.0 / 2) :
10691                                   ((x < (7.0 / 8)) ? 1.0 : (-4.0 * x + 9.0 / 2)))
10692      g = (x < (1.0 / 8)) ? 0.0 : ((x < (3.0 / 8)) ? (4.0 * x - 0.5) :
10693                                   (((x < (5.0 / 8)) ? 1.0 :
10694                                     ((x < (7.0 / 8)) ? (-4.0 * x + 7.0 / 2) : 0.0))))
10695      b = (x < (1.0 / 8)) ? (4.0 * x + 0.5) : ((x < (3.0 / 8)) ? 1.0 :
10696                                               ((x < (5.0 / 8)) ? (-4.0 * x + 5.0 / 2) : 0.0))
10697      check_colormap("jet", $jet_colormap, x, r, g, b, n, err)
10698    end
10699    10.times do |i|
10700      x = random(1.0)
10701      r = (x < (3.0 / 8)) ? ((14.0 / 9) * x) : ((2.0 / 3) * x + 1.0 / 3)
10702      g = (x < (3.0 / 8)) ? ((2.0 / 3) * x) :
10703        ((x < (3.0 / 4)) ? ((14.0 / 9) * x - 1.0 / 3) : ((2.0 / 3) * x + 1.0 / 3))
10704      b = (x < (3.0 / 4)) ? ((2.0 / 3) * x) : (2.0 * x - 1.0)
10705      check_colormap("pink", $pink_colormap, x, r, g, b, n, err)
10706    end
10707    10.times do |i|
10708      x = random(1.0)
10709      r = 1.0
10710      g = x
10711      b = 1.0 - g
10712      check_colormap("spring", $spring_colormap, x, r, g, b, n, err)
10713    end
10714    10.times do |i|
10715      x = random(1.0)
10716      r = x
10717      g = x
10718      b = x
10719      check_colormap("gray", $gray_colormap, x, r, g, b, n, err)
10720    end
10721    10.times do |i|
10722      x = random(1.0)
10723      r = 0.0
10724      g = 0.0
10725      b = 0.0
10726      check_colormap("black_and_white", $black_and_white_colormap, x, r, g, b, n, err)
10727    end
10728    10.times do |i|
10729      x = random(1.0)
10730      r = x
10731      g = 0.5 + r / 2.0
10732      b = 0.4
10733      check_colormap("summer", $summer_colormap, x, r, g, b, n, err)
10734    end
10735    10.times do |i|
10736      x = random(1.0)
10737      r = (x < (2.0 / 5)) ? 1.0 : ((x < (3.0 / 5)) ? (-5.0 * x + 3) :
10738                                   ((x < (4.0 / 5)) ? 0.0 : (10.0 / 3 * x - 8.0 / 3)))
10739      g = (x < (2.0 / 5)) ? ((5.0 / 2) * x) : ((x < (3.0 / 5)) ? 1.0 :
10740                                               ((x < (4.0 / 5)) ? (-5.0 * x + 4) : 0.0))
10741      b = (x < (3.0 / 5)) ? 0.0 : ((x < (4.0 / 5)) ? (5.0 * x - 3) : 1.0)
10742      check_colormap("rainbow", $rainbow_colormap, x, r, g, b, n, err)
10743    end
10744    10.times do |i|
10745      x = random(1.0)
10746      rgb = colormap_ref($prism_colormap, x)
10747      if x < 1.0 - 1.0 / n and
10748          (not vequal(rgb, [1.0, 0.0, 0.0])) and
10749          (not vequal(rgb, [1.0, 0.5, 0.0])) and
10750          (not vequal(rgb, [1.0, 1.0, 0.0])) and
10751          (not vequal(rgb, [0.0, 1.0, 0.0])) and
10752          (not vequal(rgb, [0.0, 0.0, 1.0])) and
10753          (not vequal(rgb, [0.6667, 0.0, 1.0]))
10754        snd_display("prism %s", rgb)
10755      end
10756    end
10757    10.times do |i|
10758      x = random(1.0)
10759      rgb = colormap_ref($flag_colormap, x)
10760      if x < 1.0 - 1.0 / n and
10761          (not vequal(rgb, [1.0, 0.0, 0.0])) and
10762          (not vequal(rgb, [1.0, 1.0, 1.0])) and
10763          (not vequal(rgb, [0.0, 0.0, 1.0])) and
10764          (not vequal(rgb, [0.0, 0.0, 0.0]))
10765        snd_display("flag %s", rgb)
10766      end
10767    end
10768  end
10769end
10770
10771def test_07_02(old_colormap_size)
10772  ind = add_colormap("white", lambda do |size|
10773          [make_vct(size, 1.0), make_vct(size, 1.0), make_vct(size, 1.0)]
10774        end)
10775  unless res = colormap?(ind)
10776    snd_display("add_colormap %s: %s?", ind, res)
10777  end
10778  unless vequal(res = colormap_ref(ind, 0.5), [1.0, 1.0, 1.0])
10779    snd_display("white colormap: %s?", res)
10780  end
10781  #
10782  set_colormap_size(old_colormap_size)
10783  if (res = colormap_size) != old_colormap_size
10784    snd_display("set_colormap_size: %s %s?", res, old_colormap_size)
10785  end
10786  if (res = colormap_name($black_and_white_colormap)) != "black-and-white"
10787    snd_display("black-and-white: %s?", res)
10788  end
10789  if (res = colormap_name($gray_colormap)) != "gray"
10790    snd_display("gray: %s?", res)
10791  end
10792  if (res = colormap_name($rainbow_colormap)) != "rainbow"
10793    snd_display("rainbow: %s?", res)
10794  end
10795  add_colormap("purple",
10796               lambda do |size|
10797                 r = make_vct(size)
10798                 g = make_vct(size)
10799                 b = make_vct(size)
10800                 er = [0, 60, 60, 116, 128, 252, 192, 252, 256, 60]
10801                 eg = [0,  0, 64,   0, 128, 252, 192, 252, 256,  0]
10802                 eb = [0, 80,          128, 252, 192,   0, 256, 80]
10803                 incr = 256.0 / size
10804                 x = 0.0
10805                 size.times do |i|
10806                   r[i] = envelope_interp(x, er) / 256.0
10807                   g[i] = envelope_interp(x, eg) / 256.0
10808                   b[i] = envelope_interp(x, eb) / 256.0
10809                   x += incr
10810                 end
10811                 [r, g, b]
10812               end)
10813  add_colormap("sin",
10814               lambda do |size|
10815                 r = make_vct(size)
10816                 g = make_vct(size)
10817                 b = make_vct(size)
10818                 incr = (2.0 * PI) / size
10819                 x = 0.0
10820                 size.times do |i|
10821                   r[i] = sin(1.5 * x).abs
10822                   g[i] = sin(3.5 * x).abs
10823                   b[i] = sin(2.5 * x).abs
10824                   x += incr
10825                 end
10826                 [r, g, b]
10827               end)
10828  add_colormap("another-sin",
10829               lambda do |size|
10830                 r = make_vct(size)
10831                 g = make_vct(size)
10832                 b = make_vct(size)
10833                 incr = (2.0 * PI) / size
10834                 x = 0.0
10835                 size.times do |i|
10836                   r[i] = sin(2.5 * x).abs
10837                   g[i] = sin(3.5 * x).abs
10838                   b[i] = sin(4.5 * x).abs
10839                   x += incr
10840                 end
10841                 [r, g, b]
10842               end)
10843  [1024, 256, 2, 512].each do |n|
10844    set_colormap_size(n)
10845    10.times do |i|
10846      x = random(1.0)
10847      r = (x < 4.0 / 5) ? ((5.0 / 4) * x) : 1.0
10848      g = (4.0 / 5) * x
10849      b = 0.5 * x
10850      rgb = colormap_ref($copper_colormap, x)
10851      r1, g1, b1 = rgb
10852      err = 0.01
10853      if n > 2 and
10854          x < (1.0 - (1.0 / n)) and
10855          (fneq_err(r, r1, err) or
10856           fneq_err(g, g1, err) or
10857           fneq_err(b, b1, err))
10858        snd_display("copper size reset %s: %1.4f (%1.4f): %s %s",
10859                    n,
10860                    x,
10861                    [(r - r1).abs, (g - g1).abs, (b - b1).abs].max,
10862                    [r, g, b],
10863                    [r1, g1, b1])
10864      end
10865    end
10866  end
10867  set_colormap_size(old_colormap_size)
10868end
10869
10870def test_07
10871  if $with_test_gui
10872    old_colormap_size = colormap_size
10873    old_colormap = colormap
10874    test_07_00
10875    test_07_01
10876    test_07_02(old_colormap_size)
10877    set_colormap(old_colormap)
10878  end
10879end
10880
10881# ---------------- test 08: clm ----------------
10882
10883def sweep2bins(flt, bins)
10884  ind = open_sound("sweep.snd")
10885  if mus_generator?(flt)
10886    clm_channel(flt)
10887  else
10888    map_channel(flt)
10889  end
10890  mx = maxamp()
10891  size = (22050 / bins).round
10892  resp = Vct.new(bins) do |i|
10893    channel2vct(i * size, size).peak
10894  end
10895  close_sound(ind)
10896  [mx, resp]
10897end
10898
10899def filter_response_max(f1)
10900  mx = f1.run(1.0).abs
10901  1000.times do |i|
10902    mx = [mx, f1.run(0.0).abs].max
10903  end
10904  mx
10905end
10906
10907def filter_equal?(f1, f2)
10908  f1.order == f2.order and
10909    vequal(f1.xcoeffs, f2.xcoeffs) and
10910    vequal(f1.ycoeffs, f2.ycoeffs)
10911end
10912
10913def f05equal?(f1, f2)
10914  fequal_err(f1, f2, 0.05)
10915end
10916
10917def analog_filter_tests
10918  #
10919  # Butterworth
10920  #
10921  poles = [vct(1, 1.414, 1),
10922           vct(1, 1.848, 1, 1, 0.765, 1),
10923           vct(1, 1.932, 1, 1, 1.414, 1, 1, 0.518, 1),
10924           vct(1, 1.962, 1, 1, 1.663, 1, 1, 1.111, 1, 1, 0.390, 1),
10925           vct(1, 1.975, 1, 1, 1.782, 1, 1, 1.414, 1, 1, 0.908, 1, 1, 0.313, 1)]
10926  k = 0
10927  2.step(11, 2) do |i|
10928    vals = butterworth_prototype(i)
10929    snd_test_neq(vals[1], poles[k], "butterworth_prototype poles %d", i)
10930    len = (k + 1) * 3
10931    zeros = Vct.new(len)
10932    2.step(len, 3) do |j|
10933      zeros[j] = 1.0
10934      break if j >= (k + 1) * 3
10935    end
10936    snd_test_neq(vals[0], zeros, "butterworth_prototype zeros %d", i)
10937    k += 1
10938  end
10939  cutoff = 0.1
10940  3.times do |m|
10941    k = 1
10942    2.step(16, 2) do |i|
10943      local = make_butterworth_lowpass(i, cutoff)
10944      dsp = make_butter_lp(k, mus_srate * cutoff)
10945      snd_test_any_neq(local, dsp, :filter_equal?,
10946                       "butterworth lowpass %1.4f", cutoff)
10947      local = make_butterworth_highpass(i, cutoff)
10948      dsp = make_butter_hp(k, mus_srate * cutoff)
10949      snd_test_any_neq(local, dsp, :filter_equal?,
10950                       "butterworth highpass %1.4f", cutoff)
10951      k += 1
10952    end
10953    cutoff += 0.1
10954  end
10955  #
10956  ind = open_sound("oboe.snd")
10957  hummer = make_eliminate_hum(550)
10958  map_channel(lambda do |x| eliminate_hum(hummer, x) end)
10959  peaker = make_peaking_2(500, 1000, 1.0)
10960  map_channel(peaker)
10961  map_channel(chordalize())
10962  close_sound(ind)
10963  #
10964  ind = new_sound("sweep.snd", 1, 22050, Mus_bfloat, Mus_next, false, 22050)
10965  phase = 0.0
10966  freq = 0.0
10967  incr = PI / 22050.0
10968  map_channel(lambda do |y|
10969                val = sin(phase)
10970                phase += freq
10971                freq += incr
10972                val * 0.5
10973              end)
10974  save_sound(ind)
10975  close_sound(ind)
10976  f1 = make_butterworth_lowpass(8, 0.1)
10977  vals = sweep2bins(f1, 10)
10978  snd_test_neq(vals[0], 0.5, "butterworth lp 8 max")
10979  v1 = vct(0.500, 0.500, 0.359, 0.014, 0.001, 0.000, 0.000, 0.000, 0.000, 0.000)
10980  snd_test_neq(vals[1], v1, "butterworth lp 8 0.1 spect")
10981  f1 = make_butterworth_lowpass(12, 0.25)
10982  vals = sweep2bins(f1, 10)
10983  snd_test_neq(vals[0], 0.5, "butterworth lp 12 max")
10984  v1 = vct(0.500, 0.500, 0.500, 0.500, 0.499, 0.358, 0.010, 0.000, 0.000, 0.000)
10985  snd_test_neq(vals[1], v1, "butterworth lp 12 0.25 spect")
10986  f1 = make_butterworth_lowpass(10, 0.4)
10987  vals = sweep2bins(f1, 10)
10988  snd_test_neq(vals[0], 0.5, "butterworth lp 10 max")
10989  v0 = vals[1]
10990  v1 = vct(0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.499, 0.361, 0.001)
10991  v2 = vct(0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.499, 0.360, 0.002)
10992  if (not vequal(v0, v1)) and (not vequal(v0, v2))
10993    snd_test_neq(v0, v1, "butterworth lp 10 0.4 spect (v1)")
10994    snd_test_neq(v0, v2, "butterworth lp 10 0.4 spect (v2)")
10995  end
10996  2.step(12, 2) do |i|
10997    0.1.step(0.35, 0.1) do |j|
10998      f1 = make_butterworth_lowpass(i, j)
10999      snd_test_gt(filter_response_max(f1), 1.0, "butter low max %d %d", i, j)
11000    end
11001  end
11002  #
11003  f1 = make_butterworth_highpass(8, 0.1)
11004  vals = sweep2bins(f1, 10)
11005  snd_test_neq(vals[0], 0.5, "butterworth hp 8 max")
11006  v1 = vct(0.001, 0.348, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500)
11007  snd_test_neq(vals[1], v1, "butterworth hp 8 0.1 spect")
11008  f1 = make_butterworth_highpass(12, 0.25)
11009  vals = sweep2bins(f1, 10)
11010  snd_test_neq(vals[0], 0.5, "butterworth hp 12 max")
11011  v1 = vct(0.000, 0.000, 0.000, 0.011, 0.348, 0.500, 0.500, 0.500, 0.500, 0.500)
11012  snd_test_neq(vals[1], v1, "butterworth hp 12 0.25 spect")
11013  f1 = make_butterworth_highpass(10, 0.4)
11014  vals = sweep2bins(f1, 10)
11015  snd_test_neq(vals[0], 0.5, "butterworth hp 10 max")
11016  v1 = vct(0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.005, 0.343, 0.501, 0.501)
11017  snd_test_neq(vals[1], v1, "butterworth hp 10 0.4 spect")
11018  2.step(12, 2) do |i|
11019    0.1.step(0.35, 0.1) do |j|
11020      f1 = make_butterworth_highpass(i, j)
11021      snd_test_gt(filter_response_max(f1), 1.0, "butter high max %d %d", i, j)
11022    end
11023  end
11024  #
11025  f1 = make_butterworth_bandpass(4, 0.1, 0.2)
11026  vals = sweep2bins(f1, 10)
11027  snd_test_any_neq(vals[0], 0.5, :f05equal?, "butterworth bp 4 max")
11028  v1 = vct(0.028, 0.350, 0.481, 0.479, 0.346, 0.132, 0.038, 0.009, 0.002, 0.000)
11029  snd_test_neq(vals[1], v1, "butterworth bp 4 0.1 0.2 spect")
11030  f1 = make_butterworth_bandpass(12, 0.1, 0.2)
11031  vals = sweep2bins(f1, 10)
11032  snd_test_any_neq(vals[0], 0.5, :f05equal?, "butterworth bp 12 max")
11033  v1 = vct(0.000, 0.323, 0.501, 0.500, 0.358, 0.009, 0.000, 0.000, 0.000, 0.000)
11034  snd_test_neq(vals[1], v1, "butterworth bp 12 0.1 0.2 spect")
11035  f1 = make_butterworth_bandpass(8, 0.3, 0.4)
11036  vals = sweep2bins(f1, 10)
11037  snd_test_any_neq(vals[0], 0.5, :f05equal?, "butterworth bp 8 max")
11038  v1 = vct(0.000, 0.000, 0.000, 0.003, 0.034, 0.344, 0.499, 0.499, 0.353, 0.002)
11039  snd_test_neq(vals[1], v1, "butterworth bp 8 0.3 0.4 spect")
11040  #
11041  f1 = make_butterworth_bandstop(4, 0.1, 0.2)
11042  vals = sweep2bins(f1, 10)
11043  snd_test_any_neq(vals[0], 0.5, :f05equal?, "butterworth bs 4 max")
11044  v1 = vct(0.500, 0.500, 0.347, 0.339, 0.481, 0.499, 0.500, 0.500, 0.500, 0.500)
11045  snd_test_neq(vals[1], v1, "butterworth bs 4 0.1 0.2 spect")
11046  f1 = make_butterworth_bandstop(12, 0.1, 0.2)
11047  vals = sweep2bins(f1, 10)
11048  snd_test_any_neq(vals[0], 0.5, :f05equal?, "butterworth bs 12 max")
11049  v1 = vct(0.500, 0.500, 0.365, 0.334, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500)
11050  snd_test_neq(vals[1], v1, "butterworth bs 12 0.1 0.2 spect")
11051  f1 = make_butterworth_bandstop(8, 0.3, 0.4)
11052  vals = sweep2bins(f1, 10)
11053  snd_test_any_neq(vals[0], 0.5, :f05equal?, "butterworth bs 8 max")
11054  v1 = vct(0.500, 0.500, 0.500, 0.500, 0.500, 0.498, 0.354, 0.332, 0.500, 0.500)
11055  snd_test_neq(vals[1], v1, "butterworth bs 8 0.3 0.4 spect")
11056  #
11057  # Chebyshev
11058  #
11059  # ripple 0.01 0.1 1 for 2..10 even
11060  poles_01 = [vct(1, 4.456, 10.426),
11061              vct(1, 0.822, 2.006, 1, 1.984, 1.299),
11062              vct(1, 0.343, 1.372, 1, 0.937, 0.939, 1, 1.280, 0.506),
11063              vct(1, 0.189, 1.196, 1, 0.537, 0.925, 1, 0.804, 0.542,
11064                  1, 0.948, 0.272),
11065              vct(1, 0.119, 1.121, 1, 0.347, 0.940, 1, 0.540, 0.646,
11066                  1, 0.680, 0.352, 1, 0.754, 0.170)]
11067  zeros = [vct(0, 0, 1),
11068           vct(0, 0, 0.250, 0, 0, 1),
11069           vct(0, 0, 0.062, 0, 0, 1, 0, 0, 1),
11070           vct(0, 0, 0.016, 0, 0, 1, 0, 0, 1, 0, 0, 1),
11071           vct(0, 0, 0.004, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1)]
11072  poles_1 = [vct(1, 2.372, 3.314),
11073             vct(1, 0.528, 1.330, 1, 1.275, 0.623),
11074             vct(1, 0.229, 1.129, 1, 0.627, 0.696, 1, 0.856, 0.263),
11075             vct(1, 0.128, 1.069, 1, 0.364, 0.799, 1, 0.545, 0.416,
11076                 1, 0.643, 0.146),
11077             vct(1, 0.082, 1.044, 1, 0.237, 0.862, 1, 0.369, 0.568,
11078                 1, 0.465, 0.274, 1, 0.515, 0.092)]
11079  poles_10 = [vct(1, 1.098, 1.103),
11080              vct(1, 0.279, 0.987, 1, 0.674, 0.279),
11081              vct(1, 0.124, 0.991, 1, 0.340, 0.558, 1, 0.464, 0.125),
11082              vct(1, 0.070, 0.994, 1, 0.199, 0.724, 1, 0.298, 0.341,
11083                  1, 0.352, 0.070),
11084              vct(1, 0.045, 0.996, 1, 0.130, 0.814, 1, 0.203, 0.521,
11085                  1, 0.255, 0.227, 1, 0.283, 0.045)]
11086  k = 0
11087  2.step(11, 2) do |i|
11088    vals = chebyshev_prototype(i, 0.01)
11089    snd_test_neq(vals[1], poles_01[k], "chebyshev_prototype 0.01 poles %d", i)
11090    vals = chebyshev_prototype(i, 0.1)
11091    snd_test_neq(vals[1], poles_1[k], "chebyshev_prototype 0.1 poles %d", i)
11092    vals = chebyshev_prototype(i)
11093    snd_test_neq(vals[1], poles_10[k], "chebyshev_prototype 1 poles %d", i)
11094    snd_test_neq(vals[0], zeros[k], "chebyshev_prototype 0.01 zeros %d", i)
11095    k += 1
11096  end
11097  #
11098  f1 = make_chebyshev_lowpass(8, 0.1)
11099  vals = sweep2bins(f1, 10)
11100  snd_test_any_neq(vals[0], 0.51, :ffequal?, "chebyshev lp 8 max")
11101  v0 = vals[1]
11102  v1 = vct(0.508, 0.512, 0.468, 0.001, 0, 0, 0, 0, 0, 0)
11103  v2 = vct(0.507, 0.512, 0.467, 0.001, 0, 0, 0, 0, 0, 0)
11104  v3 = vct(0.508, 0.513, 0.469, 0.001, 0, 0, 0, 0, 0, 0)
11105  v4 = vct(0.509, 0.508, 0.465, 0.001, 0, 0, 0, 0, 0, 0)
11106  if (not vequal(v0, v1)) and (not vequal(v0, v2)) and
11107     (not vequal(v0, v3)) and (not vequal(v0, v4))
11108    snd_test_neq(v0, v1, "chebyshev lp 8 0.1 spect (v1)")
11109    snd_test_neq(v0, v2, "chebyshev lp 8 0.1 spect (v2)")
11110    snd_test_neq(v0, v3, "chebyshev lp 8 0.1 spect (v3)")
11111    snd_test_neq(v0, v4, "chebyshev lp 8 0.1 spect (v4)")
11112  end
11113  f1 = make_chebyshev_lowpass(12, 0.25)
11114  vals = sweep2bins(f1, 10)
11115  snd_test_any_neq(vals[0], 0.51, :ffequal?, "chebyshev lp 12 max")
11116  v1 = vct(0.509, 0.500, 0.508, 0.508, 0.507, 0.413, 0, 0, 0, 0)
11117  snd_test_neq(vals[1], v1, "chebyshev lp 12 0.25 spect")
11118  f1 = make_chebyshev_lowpass(10, 0.4)
11119  vals = sweep2bins(f1, 10)
11120  snd_test_any_neq(vals[0], 0.51, :ffequal?, "chebyshev lp 10 max")
11121  v1 = vct(0.465, 0.493, 0.509, 0.508, 0.477, 0.507, 0.508, 0.507, 0.431, 0)
11122  snd_test_neq(vals[1], v1, "chebyshev lp 10 0.4 spect")
11123  f1 = make_chebyshev_lowpass(8, 0.1, 0.01)
11124  vals = sweep2bins(f1, 10)
11125  snd_test_any_neq(vals[0], 0.49, :ffequal?, "chebyshev lp 8 0.1 0.01 max")
11126  v1 = vct(0.492, 0.491, 0.483, 0.006, 0, 0, 0, 0, 0, 0)
11127  snd_test_neq(vals[1], v1, "chebyshev lp 8 0.1 0.01 spect")
11128  f1 = make_chebyshev_lowpass(12, 0.25, 0.1)
11129  vals = sweep2bins(f1, 10)
11130  snd_test_any_neq(vals[0], 0.49, :ffequal?, "chebyshev lp 12 0.1 max")
11131  v1 = vct(0.488, 0.488, 0.488, 0.488, 0.487, 0.403, 0, 0, 0, 0)
11132  snd_test_neq(vals[1], v1, "chebyshev lp 12 0.25 0.1 spect")
11133  f1 = make_chebyshev_lowpass(10, 0.4, 0.001)
11134  vals = sweep2bins(f1, 10)
11135  snd_test_any_neq(vals[0], 0.49, :ffequal?, "chebyshev lp 10 0.001 max")
11136  v1 = vct(0.497, 0.497, 0.497, 0.497, 0.497, 0.497, 0.497, 0.497, 0.488, 0)
11137  snd_test_neq(vals[1], v1, "chebyshev lp 10 0.4 0.001 spect")
11138  2.step(10, 2) do |i|
11139    0.1.step(0.35, 0.1) do |j|
11140      f1 = make_chebyshev_lowpass(i, j)
11141      snd_test_gt(filter_response_max(f1), 1.0, "cheby low max %d %d", i, j)
11142    end
11143  end
11144  #
11145  f1 = make_chebyshev_highpass(8, 0.1)
11146  vals = sweep2bins(f1, 10)
11147  snd_test_any_neq(vals[0], 0.55, :ffequal?, "chebyshev hp 8 max")
11148  v1 = vct(0, 0.341, 0.551, 0.509, 0.466, 0.501, 0.509, 0.505, 0.481, 0.461)
11149  snd_test_neq(vals[1], v1, "chebyshev hp 8 0.1 spect")
11150  f1 = make_chebyshev_highpass(12, 0.25)
11151  vals = sweep2bins(f1, 10)
11152  snd_test_any_neq(vals[0], 0.55, :ffequal?, "chebyshev hp 12 max")
11153  v1 = vct(0, 0, 0, 0, 0.299, 0.554, 0.509, 0.509, 0.500, 0.509)
11154  snd_test_neq(vals[1], v1, "chebyshev hp 12 0.25 spect")
11155  f1 = make_chebyshev_highpass(10, 0.4)
11156  vals = sweep2bins(f1, 10)
11157  v0 = vals[1]
11158  v1 = vct(0, 0, 0, 0, 0, 0, 0, 0.297, 0.786, 0.677)
11159  v2 = vct(0, 0, 0, 0, 0, 0, 0, 0.301, 0.788, 0.660)
11160  v3 = vct(0, 0, 0, 0, 0, 0, 0, 0.322, 0.861, 0.724)
11161  v4 = vct(0, 0, 0, 0, 0, 0, 0, 0.262, 0.571, 0.509)
11162  if (not vequal(v0, v1)) and (not vequal(v0, v2)) and
11163     (not vequal(v0, v3)) and (not vequal(v0, v4))
11164    snd_test_neq(v0, v1, "chebyshev hp 10 0.4 spect (v1)")
11165    snd_test_neq(v0, v2, "chebyshev hp 10 0.4 spect (v2)")
11166    snd_test_neq(v0, v3, "chebyshev hp 10 0.4 spect (v3)")
11167    snd_test_neq(v0, v4, "chebyshev hp 10 0.4 spect (v4)")
11168  end
11169  f1 = make_chebyshev_highpass(8, 0.1, 0.01)
11170  vals = sweep2bins(f1, 10)
11171  snd_test_any_neq(vals[0], 0.49, :ffequal?, "chebyshev hp 8 0.1 0.01 max")
11172  v1 = vct(0, 0.498, 0.498, 0.492, 0.491, 0.492, 0.492, 0.492, 0.491, 0.491)
11173  snd_test_neq(vals[1], v1, "chebyshev hp 8 0.1 0.01 spect")
11174  f1 = make_chebyshev_highpass(12, 0.25, 0.1)
11175  vals = sweep2bins(f1, 10)
11176  snd_test_any_neq(vals[0], 0.51, :ffequal?, "chebyshev hp 12 0.1 max")
11177  v1 = vct(0, 0, 0, 0, 0.453, 0.516, 0.489, 0.489, 0.488, 0.488)
11178  snd_test_neq(vals[1], v1, "chebyshev hp 12 0.25 0.1 spect")
11179  f1 = make_chebyshev_highpass(10, 0.4, 0.001)
11180  vals = sweep2bins(f1, 10)
11181  snd_test_any_neq(vals[0], 0.5, :ffequal?, "chebyshev 10 0.001 max")
11182  v0 = vals[1]
11183  v1 = vct(0, 0, 0, 0, 0, 0, 0.002, 0.501, 0.504, 0.504)
11184  v2 = vct(0, 0, 0, 0, 0, 0, 0.002, 0.503, 0.505, 0.504)
11185  v3 = vct(0, 0, 0, 0, 0, 0, 0.002, 0.503, 0.501, 0.497)
11186  if (not vequal(v0, v1)) and (not vequal(v0, v2)) and (not vequal(v0, v3))
11187    snd_test_neq(v0, v1, "chebyshev hp 10 0.4 0.001 spect (v1)")
11188    snd_test_neq(v0, v2, "chebyshev hp 10 0.4 0.001 spect (v2)")
11189    snd_test_neq(v0, v3, "chebyshev hp 10 0.4 0.001 spect (v3)")
11190  end
11191  2.step(10, 2) do |i|
11192    0.1.step(0.35, 0.1) do |j|
11193      f1 = make_chebyshev_highpass(i, j)
11194      snd_test_gt(filter_response_max(f1), 1.0, "cheby high max %d %d", i, j)
11195    end
11196  end
11197  #
11198  f1 = make_chebyshev_bandpass(4, 0.1, 0.2)
11199  vals = sweep2bins(f1, 10)
11200  snd_test_any_neq(vals[0], 0.5, :f05equal?, "chebyshev bp 4 max")
11201  v1 = vct(0.009, 0.449, 0.509, 0.505, 0.442, 0.065, 0.013, 0.003, 0, 0)
11202  snd_test_neq(vals[1], v1, "chebyshev bp 4 0.1 0.2 spect")
11203  f1 = make_chebyshev_bandpass(6, 0.1, 0.2)
11204  vals = sweep2bins(f1, 10)
11205  snd_test_any_neq(vals[0], 0.5, :f05equal?, "chebyshev bp 6 max")
11206  v1 = vct(0.001, 0.376, 0.505, 0.498, 0.412, 0.011, 0.001, 0, 0, 0)
11207  snd_test_neq(vals[1], v1, "chebyshev bp 6 0.1 0.2 spect")
11208  f1 = make_chebyshev_bandpass(8, 0.3, 0.4)
11209  vals = sweep2bins(f1, 10)
11210  snd_test_any_neq(vals[0], 0.5, :f05equal?, "chebyshev bp 8 max")
11211  v1 = vct(0, 0, 0, 0, 0.002, 0.363, 0.517, 0.513, 0.433, 0)
11212  snd_test_neq(vals[1], v1, "chebyshev bp 8 0.3 0.4 spect")
11213  f1 = make_chebyshev_bandpass(8, 0.2, 0.2, 0.01)
11214  vals = sweep2bins(f1, 10)
11215  snd_test_any_neq(vals[0], 0.5, :f05equal?, "chebyshev bp 10 0.2 max")
11216  v1 = vct(0, 0, 0.015, 0.483, 0.482, 0.021, 0.001, 0, 0, 0)
11217  snd_test_neq(vals[1], v1, "chebyshev bp 10 0.2 spect")
11218  #
11219  f1 = make_chebyshev_bandstop(4, 0.1, 0.4)
11220  vals = sweep2bins(f1, 10)
11221  snd_test_any_neq(vals[0], 0.5, :f05equal?, "chebyshev bs 4 max")
11222  v1 = vct(0.509, 0.505, 0.447, 0.033, 0.006, 0.006, 0.033, 0.445, 0.512, 0.509)
11223  snd_test_neq(vals[1], v1, "chebyshev bs 4 0.1 0.4 spect")
11224  f1 = make_chebyshev_bandstop(8, 0.1, 0.4)
11225  vals = sweep2bins(f1, 10)
11226  snd_test_any_neq(vals[0], 0.51, :f05equal?, "chebyshev bs 8 max")
11227  v0 = vals[1]
11228  v1 = vct(0.508, 0.512, 0.468, 0.001, 0, 0, 0.001, 0.345, 0.551, 0.507)
11229  v2 = vct(0.507, 0.512, 0.467, 0.001, 0, 0, 0.001, 0.344, 0.590, 0.508)
11230  v3 = vct(0.508, 0.513, 0.469, 0.001, 0, 0, 0.001, 0.345, 0.552, 0.508)
11231  v4 = vct(0.509, 0.508, 0.465, 0.001, 0, 0, 0.001, 0.343, 0.548, 0.508)
11232  if (not vequal(v0, v1)) and (not vequal(v0, v2)) and
11233     (not vequal(v0, v3)) and (not vequal(v0, v4))
11234    snd_test_neq(v0, v1, "chebyshev bs 8 0.1 0.4 spect (v1)")
11235    snd_test_neq(v0, v2, "chebyshev bs 8 0.1 0.4 spect (v2)")
11236    snd_test_neq(v0, v3, "chebyshev bs 8 0.1 0.4 spect (v3)")
11237    snd_test_neq(v0, v4, "chebyshev bs 8 0.1 0.4 spect (v4)")
11238  end
11239  f1 = make_chebyshev_bandstop(8, 0.1, 0.4, 0.01)
11240  vals = sweep2bins(f1, 10)
11241  snd_test_any_neq(vals[0], 0.5, :f05equal?, "chebyshev bs 8 0.01 max")
11242  v1 = vct(0.492, 0.491, 0.483, 0.006, 0, 0, 0.006, 0.494, 0.495, 0.492)
11243  snd_test_neq(vals[1], v1, "chebyshev bs 8 0.1 0.4 0.01 spect")
11244  #
11245  # inverse-chebyshev
11246  #
11247  f1 = make_inverse_chebyshev_lowpass(8, 0.1)
11248  vals = sweep2bins(f1, 10)
11249  snd_test_any_neq(vals[0], 0.51, :ffequal?, "inverse_chebyshev lp 8 max")
11250  v0 = vals[1]
11251  v1 = vct(0.501, 0.496, 0.001, 0, 0.001, 0, 0, 0, 0, 0.001)
11252  v2 = vct(0.500, 0.498, 0.001, 0, 0.001, 0, 0, 0, 0, 0.001)
11253  if (not vequal(v0, v1)) and (not vequal(v0, v2))
11254    snd_test_neq(v0, v1, "inverse_chebyshev lp 8 0.1 spect (v1)")
11255    snd_test_neq(v0, v2, "inverse_chebyshev lp 8 0.1 spect (v2)")
11256  end
11257  f1 = make_inverse_chebyshev_lowpass(12, 0.25)
11258  vals = sweep2bins(f1, 10)
11259  snd_test_any_neq(vals[0], 0.51, :ffequal?, "inverse_chebyshev lp 12 max")
11260  v1 = vct(0.500, 0.500, 0.500, 0.500, 0.496, 0.001, 0.001, 0.001, 0.001, 0.001)
11261  snd_test_neq(vals[1], v1, "inverse_chebyshev lp 12 0.25 spect")
11262  f1 = make_inverse_chebyshev_lowpass(10, 0.4)
11263  vals = sweep2bins(f1, 10)
11264  snd_test_any_neq(vals[0], 0.51, :ffequal?, "inverse_chebyshev lp 10 max")
11265  v0 = vals[1]
11266  v1 = vct(0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.497, 0.001, 0.001)
11267  v2 = vct(0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.497, 0.002, 0.002)
11268  if (not vequal(v0, v1)) and (not vequal(v0, v2))
11269    snd_test_neq(v0, v1, "inverse_chebyshev lp 10 0.4 spect (v1)")
11270    snd_test_neq(v0, v2, "inverse_chebyshev lp 10 0.4 spect (v2)")
11271  end
11272  f1 = make_inverse_chebyshev_lowpass(10, 0.4, 120)
11273  vals = sweep2bins(f1, 10)
11274  snd_test_any_neq(vals[0], 0.51, :ffequal?, "inverse_chebyshev lp 10 max")
11275  v1 = vct(0.501, 0.501, 0.501, 0.501, 0.501, 0.500, 0.345, 0.007, 0, 0)
11276  snd_test_neq(vals[1], v1, "inverse_chebyshev lp 10 0.4 120 spect")
11277  #
11278  2.step(10, 2) do |i|
11279    0.1.step(0.35, 0.1) do |j|
11280      f1 = make_inverse_chebyshev_lowpass(i, j)
11281      snd_test_gt(filter_response_max(f1), 1.0, "inv cheby low max %d %d", i, j)
11282    end
11283  end
11284  #
11285  f1 = make_inverse_chebyshev_highpass(8, 0.1)
11286  vals = sweep2bins(f1, 10)
11287  snd_test_any_neq(vals[0], 0.51, :ffequal?, "inverse_chebyshev hp 8 max")
11288  v1 = vct(0.001, 0.001, 0.440, 0.505, 0.505, 0.503, 0.502, 0.501, 0.501, 0.501)
11289  snd_test_neq(vals[1], v1, "inverse_chebyshev hp 8 0.1 spect")
11290  f1 = make_inverse_chebyshev_highpass(12, 0.25)
11291  vals = sweep2bins(f1, 10)
11292  snd_test_any_neq(vals[0], 0.51, :ffequal?, "inverse_chebyshev hp 12 max")
11293  v1 = vct(0.001, 0.001, 0.001, 0.001, 0.001, 0.505, 0.506, 0.503, 0.501, 0.501)
11294  snd_test_neq(vals[1], v1, "inverse_chebyshev hp 12 0.25 spect")
11295  f1 = make_inverse_chebyshev_highpass(10, 0.4)
11296  vals = sweep2bins(f1, 10)
11297  snd_test_any_neq(vals[0], 0.51, :ffequal?, "inverse_chebyshev hp 10 max")
11298  v0 = vals[1]
11299  v1 = vct(0, 0, 0, 0.001, 0.001, 0.001, 0.001, 0.001, 0.503, 0.503)
11300  v2 = vct(0, 0, 0, 0.001, 0.001, 0.001, 0.001, 0.001, 0.505, 0.503)
11301  v3 = vct(0, 0, 0, 0.001, 0.001, 0.001, 0.001, 0.001, 0.509, 0.504)
11302  if (not vequal(v0, v1)) and (not vequal(v0, v2)) and (not vequal(v0, v3))
11303    snd_test_neq(v0, v1, "inverse_chebyshev hp 10 0.4 spect (v1)")
11304    snd_test_neq(v0, v2, "inverse_chebyshev hp 10 0.4 spect (v2)")
11305    snd_test_neq(v0, v3, "inverse_chebyshev hp 10 0.4 spect (v3)")
11306  end
11307  f1 = make_inverse_chebyshev_highpass(10, 0.1, 120)
11308  vals = sweep2bins(f1, 10)
11309  snd_test_any_neq(vals[0], 0.51, :ffequal?,
11310                   "inverse_chebyshev hp 10 0.1 120 max")
11311  v1 = vct(0, 0, 0.007, 0.328, 0.502, 0.502, 0.502, 0.501, 0.501, 0.501)
11312  snd_test_neq(vals[1], v1, "inverse_chebyshev hp 10 0.1 120 spect")
11313  #
11314  2.step(10, 2) do |i|
11315    0.1.step(0.35, 0.1) do |j|
11316      f1 = make_inverse_chebyshev_highpass(i, j)
11317      snd_test_gt(filter_response_max(f1), 1.0,
11318                  "inv cheby high max %d %d", i, j)
11319    end
11320  end
11321  #
11322  f1 = make_inverse_chebyshev_bandpass(10, 0.1, 0.2)
11323  vals = sweep2bins(f1, 10)
11324  snd_test_any_neq(vals[0], 0.5, :f05equal?, "inverse_chebyshev bp 10 max")
11325  v1 = vct(0.001, 0.001, 0.498, 0.485, 0.001, 0.001, 0, 0.001, 0, 0.001)
11326  snd_test_neq(vals[1], v1, "inverse_chebyshev bp 10 0.1 0.2 spect")
11327  f1 = make_inverse_chebyshev_bandpass(10, 0.1, 0.2, 30)
11328  vals = sweep2bins(f1, 10)
11329  snd_test_any_neq(vals[0], 0.5, :f05equal?, "inverse_chebyshev bp 10 30 max")
11330  v0 = vals[1]
11331  v1 = vct(0.026, 0.025, 0.509, 0.505, 0.02, 0.016, 0.012, 0.016, 0.011, 0.016)
11332  v2 = vct(0.030, 0.042, 0.511, 0.505, 0.02, 0.016, 0.012, 0.016, 0.011, 0.016)
11333  v3 = vct(0.022, 0.017, 0.511, 0.505, 0.02, 0.016, 0.012, 0.016, 0.011, 0.016)
11334  if (not vequal(v0, v1)) and (not vequal(v0, v2)) and (not vequal(v0, v3))
11335    snd_test_neq(v0, v1, "inverse_chebyshev bp 10 0.1 0.2 30 spect (v1)")
11336    snd_test_neq(v0, v2, "inverse_chebyshev bp 10 0.1 0.2 30 spect (v2)")
11337    snd_test_neq(v0, v3, "inverse_chebyshev bp 10 0.1 0.2 30 spect (v3)")
11338  end
11339  f1 = make_inverse_chebyshev_bandpass(8, 0.1, 0.4)
11340  vals = sweep2bins(f1, 10)
11341  snd_test_any_neq(vals[0], 0.5, :f05equal?, "inverse_chebyshev bp 8 max")
11342  v1 = vct(0.001, 0.001, 0.440, 0.506, 0.505, 0.503, 0.502, 0.434, 0.001, 0.001)
11343  snd_test_neq(vals[1], v1, "inverse_chebyshev bp 8 0.1 0.4 spect")
11344  f1 = make_inverse_chebyshev_bandpass(8, 0.3, 0.4, 40)
11345  vals = sweep2bins(f1, 10)
11346  snd_test_any_neq(vals[0], 0.5, :f05equal?, "inverse_chebyshev bp 8 40 max")
11347  v1 = vct(0.002, 0.005, 0.007, 0.007, 0.005, 0.005, 0.503, 0.505, 0.006, 0.005)
11348  snd_test_neq(vals[1], v1, "inverse_chebyshev bp 8 0.3 0.4 40 spect")
11349  #
11350  f1 = make_inverse_chebyshev_bandstop(4, 0.1, 0.4)
11351  vals = sweep2bins(f1, 10)
11352  snd_test_any_neq(vals[0], 0.5, :f05equal?, "inverse_chebyshev bs 4 max")
11353  v1 = vct(0.500, 0.054, 0.001, 0.001, 0, 0, 0, 0.001, 0.055, 0.503)
11354  snd_test_neq(vals[1], v1, "inverse_chebyshev bs 4 0.1 0.4 spect")
11355  f1 = make_inverse_chebyshev_bandstop(8, 0.1, 0.4)
11356  vals = sweep2bins(f1, 10)
11357  snd_test_any_neq(vals[0], 0.51, :f05equal?, "inverse_chebyshev bs 8 max")
11358  v0 = vals[1]
11359  v1 = vct(0.501, 0.496, 0.001, 0.001, 0, 0, 0, 0.001, 0.507, 0.506)
11360  v2 = vct(0.506, 0.328, 0.001, 0.001, 0, 0, 0, 0.000, 0.268, 0.511)
11361  v3 = vct(0.500, 0.498, 0.001, 0.001, 0, 0, 0, 0.001, 0.507, 0.506)
11362  if (not vequal(v0, v1)) and (not vequal(v0, v2)) and (not vequal(v0, v3))
11363    snd_test_neq(v0, v1, "inverse_chebyshev bs 8 0.1 0.4 spect (v1)")
11364    snd_test_neq(v0, v2, "inverse_chebyshev bs 8 0.1 0.4 spect (v2)")
11365    snd_test_neq(v0, v3, "inverse_chebyshev bs 8 0.1 0.4 spect (v3)")
11366  end
11367  f1 = make_inverse_chebyshev_bandstop(8, 0.1, 0.4, 90)
11368  vals = sweep2bins(f1, 10)
11369  snd_test_any_neq(vals[0], 0.5, :f05equal?, "inverse_chebyshev bs 8 90 max")
11370  v0 = vals[1]
11371  v1 = vct(0.505, 0.325, 0, 0, 0, 0, 0, 0, 0.270, 0.506)
11372  v2 = vct(0.506, 0.328, 0, 0, 0, 0, 0, 0, 0.269, 0.509)
11373  v3 = vct(0.501, 0.327, 0, 0, 0, 0, 0, 0, 0.268, 0.506)
11374  if (not vequal(v0, v1)) and (not vequal(v0, v2)) and (not vequal(v0, v3))
11375    snd_test_neq(v0, v1, "inverse_chebyshev bs 8 0.1 0.4 90 spect (v1)")
11376    snd_test_neq(v0, v2, "inverse_chebyshev bs 8 0.1 0.4 90 spect (v2)")
11377    snd_test_neq(v0, v3, "inverse_chebyshev bs 8 0.1 0.4 90 spect (v3)")
11378  end
11379  if $with_test_gsl
11380    if defined? gsl_roots
11381      # gsl_roots isn't defined for ruby in snd-xen.c
11382      #
11383      # bessel
11384      #
11385      f1 = make_bessel_lowpass(4, 0.1)
11386      vals = sweep2bins(f1, 10)
11387      snd_test_neq(vals[0], 0.5, "bessel lp 4 0.1 max")
11388      snd_test_neq(vals[1],
11389                   vct(0.500, 0.417, 0.209, 0.062, 0.018, 0.005, 0.001, 0, 0, 0),
11390                   "bessel lp 4 0.1 spect")
11391      f1 = make_bessel_lowpass(8, 0.1)
11392      vals = sweep2bins(f1, 10)
11393      snd_test_neq(vals[0], 0.5, "bessel lp 8 max")
11394      snd_test_neq(vals[1],
11395                   vct(0.499, 0.365, 0.116, 0.010, 0.001, 0, 0, 0, 0, 0),
11396                   "bessel lp 8 0.1 spect")
11397      f1 = make_bessel_lowpass(12, 0.25)
11398      vals = sweep2bins(f1, 10)
11399      snd_test_neq(vals[0], 0.5, "bessel lp 12 max")
11400      snd_test_neq(vals[1],
11401                   vct(0.500, 0.477, 0.410, 0.309, 0.185, 0.063, 0.006, 0, 0, 0),
11402                   "bessel lp 12 0.25 spect")
11403      f1 = make_bessel_lowpass(10, 0.4)
11404      vals = sweep2bins(f1, 10)
11405      snd_test_neq(vals[0], 0.5, "bessel lp 10 max")
11406      if (not vequal(vals[1], vct(0.5, 0.498, 0.491, 0.479, 0.458, 0.423, 0.364, 0.259, 0.086, 0.001))) and
11407          (not vequal(vals[1], vct(0.5, 0.498, 0.491, 0.479, 0.458, 0.423, 0.364, 0.259, 0.086, 0.002)))
11408        snd_display(snd_format_neq(vals[1],
11409                                   vct(0.5, 0.498, 0.491, 0.479, 0.458, 0.423, 0.364, 0.259, 0.086, 0.001),
11410                                   "bessel lp 10 0.4 spect"))
11411      end
11412      2.step(11, 2) do |i|
11413        0.1.step(0.44, 0.1) do |j|
11414          f1 = make_bessel_lowpass(i, j)
11415          snd_test_gt(filter_response_max(f1), 1.0, "bess low max %d %d", i, j)
11416        end
11417      end
11418      #
11419      f1 = make_bessel_highpass(8, 0.1)
11420      vals = sweep2bins(f1, 10)
11421      snd_test_neq(vals[0], 0.5, "bessel hp 8 max")
11422      snd_test_neq(vals[1],
11423                   vct(0.001, 0.115, 0.29, 0.386, 0.435, 0.465, 0.483, 0.493, 0.498, 0.5),
11424                   "bessel hp 8 0.1 spect")
11425      f1 = make_bessel_highpass(12, 0.25)
11426      vals = sweep2bins(f1, 10)
11427      snd_test_neq(vals[0], 0.5, "bessel hp 12 max")
11428      snd_test_neq(vals[1],
11429                   vct(0, 0, 0, 0.006, 0.063, 0.181, 0.309,0.410, 0.477, 0.5),
11430                   "bessel hp 12 0.25 spect")
11431      f1 = make_bessel_highpass(10, 0.4)
11432      vals = sweep2bins(f1, 10)
11433      snd_test_any_neq(vals[0], 0.5, :ffequal?, "bessel hp 10 max")
11434      snd_test_neq(vals[1],
11435                   vct(0, 0, 0, 0, 0, 0, 0.004, 0.084, 0.343, 0.499),
11436                   "bessel hp 12 0.25 0.01 90 spect")
11437      #
11438      f1 = make_bessel_bandpass(4, 0.1, 0.2)
11439      vals = sweep2bins(f1, 10)
11440      snd_test_neq(vals[0], 0.5, "bessel bp 4 max")
11441      snd_test_neq(vals[1],
11442                   vct(0.023, 0.176, 0.245, 0.244, 0.179, 0.085, 0.031, 0.008, 0.001, 0),
11443                   "bessel bp 4 0.1 0.2 spect")
11444      #
11445      f1 = make_bessel_bandstop(12, 0.1, 0.2)
11446      vals = sweep2bins(f1, 10)
11447      snd_test_neq(vals[0], 0.5, "bessel bs 12 max")
11448      snd_test_neq(vals[1],
11449                   vct(0.498, 0.325, 0.065, 0.066, 0.177, 0.297, 0.389, 0.452, 0.488, 0.5),
11450                   "bessel bs 12 0.1 0.2 spect")
11451    end
11452    #
11453    # elliptic
11454    #
11455    f1 = make_elliptic_lowpass(8, 0.1)
11456    vals = sweep2bins(f1, 10)
11457    snd_test_any_neq(vals[0], 0.5, :fffequal?, "elliptic lp 8 max")
11458    if (not vequal(vals[1], vct(0.500, 0.515, 0.379, 0, 0, 0, 0, 0, 0, 0))) and
11459        (not vequal(vals[1], vct(0.500, 0.509, 0.385, 0, 0, 0, 0, 0, 0, 0))) and
11460        (not vequal(vals[1], vct(0.499, 0.498, 0.373, 0, 0, 0, 0, 0, 0, 0)))
11461      snd_display(snd_format_neq(vals[1],
11462                                 vct(0.500, 0.515, 0.379, 0, 0, 0, 0, 0, 0, 0),
11463                                 "elliptic lp 8 0.1 spect"))
11464    end
11465    f1 = make_elliptic_lowpass(12, 0.25)
11466    vals = sweep2bins(f1, 10)
11467    snd_test_any_neq(vals[0], 0.5, :fffequal?, "elliptic lp 12 max")
11468    if (not vequal(vals[1], vct(0.476, 0.500, 0.491, 0.499, 0.494, 0.412, 0.003, 0.001, 0, 0))) and
11469        (not vequal(vals[1], vct(0.476, 0.500, 0.491, 0.499, 0.494, 0.561, 0.004, 0, 0, 0))) and
11470        (not vequal(vals[1], vct(0.476, 0.500, 0.491, 0.499, 0.493, 0.299, 0.006, 0.001, 0, 0)))
11471      snd_display(snd_format_neq(vals[1],
11472                                 vct(0.476, 0.500, 0.491, 0.499, 0.494, 0.412, 0.003, 0.001, 0, 0),
11473                                 "elliptic lp 12 0.25 spect"))
11474    end
11475    f1 = make_elliptic_lowpass(4, 0.4)
11476    vals = sweep2bins(f1, 10)
11477    snd_test_any_neq(vals[0], 0.5, :fffequal?, "elliptic lp 4 max")
11478    snd_test_neq(vals[1],
11479                 vct(0.447, 0.453, 0.462, 0.477, 0.494, 0.500, 0.497, 0.496, 0.445, 0.003),
11480                 "elliptic lp 4 0.4 spect")
11481    f1 = make_elliptic_lowpass(8, 0.1, 0.1)
11482    vals = sweep2bins(f1, 10)
11483    snd_test_any_neq(vals[0], 0.5, :fffequal?, "elliptic lp 8 0.1 max")
11484    snd_test_neq(vals[1],
11485                 vct(0.500, 0.499, 0.475, 0, 0, 0, 0, 0, 0, 0),
11486                 "elliptic lp 8 0.1 0.1 spect")
11487    f1 = make_elliptic_lowpass(8, 0.1, 0.1, 90)
11488    vals = sweep2bins(f1, 10)
11489    snd_test_any_neq(vals[0], 0.5, :fffequal?, "elliptic lp 8 0.1 90 max")
11490    snd_test_neq(vals[1],
11491                 vct(0.500, 0.499, 0.475, 0, 0, 0, 0, 0, 0, 0),
11492                 "elliptic lp 8 0.1 0.1 90 spect")
11493    f1 = make_elliptic_lowpass(8, 0.25, 0.01, 90)
11494    vals = sweep2bins(f1, 10)
11495    snd_test_any_neq(vals[0], 0.5, :fffequal?, "elliptic lp 8 0.25 90 max")
11496    snd_test_neq(vals[1],
11497                 vct(0.500, 0.500, 0.500, 0.500, 0.499, 0.495, 0.001, 0, 0, 0),
11498                 "elliptic lp 8 0.25 0.01 90 spect")
11499    #
11500    f1 = make_elliptic_highpass(4, 0.1)
11501    vals = sweep2bins(f1, 10)
11502    snd_test_any_neq(vals[0], 0.5, :fffequal?, "elliptic hp 4 max")
11503    snd_test_neq(vals[1],
11504                 vct(0.004, 0.438, 0.516, 0.499, 0.502, 0.495, 0.478, 0.463, 0.453, 0.447),
11505                 "elliptic hp 4 0.1 spect")
11506    f1 = make_elliptic_highpass(12, 0.25)
11507    vals = sweep2bins(f1, 10)
11508    # snd_test_any_neq(vals[0], 0.5, :fffequal?, "elliptic hp 12 max")
11509    if (not vequal(vals[1], vct(0, 0.001, 0.001, 0.001, 0.026, 0.934, 0.518, 0.495, 0.503, 0.477))) and
11510        (not vequal(vals[1], vct(0, 0.001, 0.001, 0.001, 0.033, 1.185, 0.519, 0.495, 0.503, 0.477))) and
11511        (not vequal(vals[1], vct(0, 0.001, 0.001, 0.001, 0.018, 0.788, 0.520, 0.495, 0.503, 0.477)))
11512      snd_display(snd_format_neq(vals[1],
11513                                 vct(0, 0.001, 0.001, 0.001, 0.026, 0.934, 0.518, 0.495, 0.503, 0.477),
11514                                 "elliptic hp 12 0.25 spect: %s?"))
11515    end
11516    f1 = make_elliptic_highpass(12, 0.25, 0.01, 90)
11517    vals = sweep2bins(f1, 10)
11518    snd_test_any_neq(vals[0], 0.5, :fffequal?, "elliptic hp 12 90 max")
11519    snd_test_neq(vals[1],
11520                 vct(0, 0, 0, 0, 0.499, 0.517, 0.503, 0.501, 0.500, 0.500),
11521                 "elliptic hp 12 0.25 0.01 90 spect")
11522    f1 = make_elliptic_highpass(4, 0.4)
11523    vals = sweep2bins(f1, 10)
11524    snd_test_any_neq(vals[0], 0.5, :fffequal?, "elliptic hp 4 0.4 max")
11525    snd_test_neq(vals[1],
11526                 vct(0, 0, 0, 0.001, 0.001, 0.002, 0.023, 0.447, 0.515, 0.502),
11527                 "elliptic hp 4 0.4 spect")
11528    f1 = make_elliptic_highpass(8, 0.1, 0.1)
11529    vals = sweep2bins(f1, 10)
11530    snd_test_any_neq(vals[0], 0.5, :fffequal?, "elliptic hp 8 0.1 max")
11531    snd_test_neq(vals[1],
11532                 vct(0, 0.478, 0.553, 0.506, 0.499, 0.501, 0.501, 0.499, 0.497, 0.495),
11533                 "elliptic hp 8 0.1 0.1 spect")
11534    f1 = make_elliptic_highpass(8, 0.1, 0.1, 90)
11535    vals = sweep2bins(f1, 10)
11536    snd_test_any_neq(vals[0], 0.5, :fffequal?, "elliptic hp 8 0.1 90 max")
11537    snd_test_neq(vals[1],
11538                 vct(0, 0.478, 0.554, 0.506, 0.499, 0.501, 0.501, 0.499, 0.497, 0.495),
11539                 "elliptic hp 8 0.1 0.1 90 spect")
11540    f1 = make_elliptic_highpass(8, 0.25, 0.01, 90)
11541    vals = sweep2bins(f1, 10)
11542    snd_test_any_neq(vals[0], 0.5, :fffequal?, "elliptic hp 8 0.25 90 max")
11543    snd_test_neq(vals[1],
11544                 vct(0, 0, 0, 0.001, 0.516, 0.517, 0.507, 0.503, 0.501, 0.500),
11545                 "elliptic hp 8 0.25 0.01 90 spect")
11546    #
11547    f1 = make_elliptic_bandpass(4, 0.1, 0.2, 0.1)
11548    vals = sweep2bins(f1, 10)
11549    snd_test_any_neq(vals[0], 0.5, :fffequal?, "elliptic bp 4 max")
11550    snd_test_neq(vals[1],
11551                 vct(0.036, 0.546, 0.55, 0.51, 0.501, 0.032, 0.024, 0.009, 0.021, 0.024),
11552                 "elliptic bp 4 0.1 0.2 0.1 spect")
11553    f1 = make_elliptic_bandpass(6, 0.1, 0.2, 0.1, 90)
11554    vals = sweep2bins(f1, 10)
11555    snd_test_any_neq(vals[0], 0.5, :fffequal?, "elliptic bp 6 max")
11556    snd_test_neq(vals[1],
11557                 vct(0.002, 0.511, 0.532, 0.503, 0.492, 0.003, 0.001, 0.001, 0.001, 0.001),
11558                 "elliptic bp 6 0.1 0.2 0.1 90 spect")
11559    #
11560    f1 = make_elliptic_bandstop(4, 0.1, 0.3, 0.1)
11561    vals = sweep2bins(f1, 10)
11562    snd_test_any_neq(vals[0], 0.5, :fffequal?, "elliptic bs 4 max")
11563    snd_test_neq(vals[1],
11564                 vct(0.499, 0.502, 0.498, 0.037, 0.05, 0.54, 0.544, 0.527, 0.526, 0.521),
11565                 "elliptic bs 4 0.1 0.3 0.1 spect")
11566    f1 = make_elliptic_bandstop(8, 0.1, 0.3, 0.1, 120)
11567    vals = sweep2bins(f1, 10)
11568    snd_test_any_neq(vals[0], 0.5, :fffequal?, "elliptic bs 8 max")
11569    if (not vequal(vals[1], vct(0.500, 0.499, 0.476, 0, 0, 0.495, 0.526, 0.505, 0.501, 0.501))) and
11570        (not vequal(vals[1], vct(0.500, 0.499, 0.475, 0, 0, 0.495, 0.526, 0.505, 0.501, 0.501)))
11571      snd_display(snd_format_neq(vals[1],
11572                                 vct(0.500, 0.499, 0.476, 0, 0, 0.495, 0.526, 0.505, 0.501, 0.501),
11573                                 "elliptic bs 8 0.1 0.3 0.1 120 spect"))
11574    end
11575  end # $with_test_gsl
11576end
11577
11578def poly_roots_tests
11579  # degree=0
11580  res = poly(0.0).roots
11581  req = poly()
11582  snd_test_neq(res, req, "poly_roots 0.0")
11583  res = poly(12.3).roots
11584  req = poly()
11585  snd_test_neq(res, req, "poly_roots 12.3")
11586  # degree 0 + x=0
11587  res = poly(0.0, 1.0).roots
11588  req = [0.0]
11589  snd_test_neq(res, req, "poly_roots 0.0 1.0")
11590  res = poly(0.0, 0.0, 0.0, 121.0).roots
11591  req = [0.0, 0.0, 0.0]
11592  snd_test_neq(res, req, "poly_roots 0.0 0.0 0.0 121.0")
11593  # degree=1
11594  res = poly(-1.0, 1.0).roots
11595  req = [1.0]
11596  snd_test_neq(res, req, "poly_roots -1.0 1.0")
11597  res = poly(-2.0, 4.0).roots
11598  req = [0.5]
11599  snd_test_neq(res, req, "poly_roots -2.0 4.0")
11600  res = poly(Complex(0.0, -1.0), 1).roots
11601  req = [Complex(0.0, 1.0)]
11602  snd_test_neq(res, req, "poly_roots -i 1")
11603  # linear x^n
11604  res = poly(-1.0, 0.0, 0.0, 0.0, 1.0).roots
11605  req1 = [Complex(0.0, -1.0), -1.0, Complex(0.0, 1.0), 1.0]
11606  req2 = [1.0, -1.0, Complex(0.0, 1.0), Complex(-0.0, -1.0)]
11607  if vcneql(res, req1) and vcneql(res, req2)
11608    snd_format_neq(res, req1, "poly_roots -1 0 0 0 1 (a)")
11609    snd_format_neq(res, req2, "poly_roots -1 0 0 0 1 (b)")
11610  end
11611  res = poly(-16, 0, 0, 0, 1).roots
11612  req1 = [Complex(0.0, -2.0), -2.0, Complex(0.0, 2.0), 2.0]
11613  req2 = [2.0, -2.0, Complex(0.0, 2.0), Complex(-0.0, -2.0)]
11614  if vcneql(res, req1) and vcneql(res, req2)
11615    snd_format_neq(res, req1, "poly_roots -16 0 0 0 1 (a)")
11616    snd_format_neq(res, req2, "poly_roots -16 0 0 0 1 (b)")
11617  end
11618  res = poly(-32, 0, 0, 0, 0, 0, 0.5).roots
11619  req = [Complex(1.0, -1.7320), Complex(-1.0, -1.7320), -2.0,
11620         Complex(-1.0, 1.7320), Complex(1.0, 1.7320), 2.0]
11621  snd_test_any_neq(res, req, :vcequal?, "poly_roots -32 0 0 0 0 0 0.5")
11622  # linear + x=0
11623  res = poly(0, -2, 4).roots
11624  req = [0.0, 0.5]
11625  snd_test_neq(res, req, "poly_roots 0 -2 4")
11626  # degree=2
11627  res = poly(-1, 0, 1).roots
11628  req = [1.0, -1.0]
11629  snd_test_neq(res, req, "poly_roots -1 0 1")
11630  res = poly(15, -8, 1).roots
11631  req = [5.0, 3.0]
11632  snd_test_neq(res, req, "poly_roots 15 -8 1")
11633  res = poly(1, -2, 1).roots
11634  req = [1.0, 1.0]
11635  snd_test_neq(res, req, "poly_roots 1 -2 1")
11636  res = poly(-1, Complex(0.0, 2.0), 1).roots
11637  req = [Complex(0.0, -1.0), Complex(0.0, -1.0)]
11638  snd_test_neq(res, req, "poly_roots -1 2i 1")
11639  res = poly(1, 1, 5).roots
11640  req = [Complex(-0.1, 0.43589), Complex(-0.1, -0.43589)]
11641  snd_test_any_neq(res, req, :vcequal?, "poly_roots 1 1 5")
11642  # 2 + x=0
11643  res = poly(0, 0, -1, 0, 1).roots
11644  req = [0.0, 0.0, 1.0, -1.0]
11645  snd_test_neq(res, req, "poly_roots 0 0 -1 0 1")
11646  # quadratic in x^(n/2)
11647  res = poly(1, 0, -2, 0, 1).roots
11648  req1 = [-1.0, 1.0, -1.0, 1.0]
11649  req2 = [1.0, 1.0, -1.0, -1.0]
11650  if res != req1 and res != req2
11651    snd_format_neq(res, req1, "poly_roots 1 0 -2 0 1 (a)")
11652    snd_format_neq(res, req2, "poly_roots 1 0 -2 0 1 (b)")
11653  end
11654  res = poly(64, 0, 0, -16, 0, 0, 1).roots
11655  req = [Complex(-1.0, -1.73205), Complex(-1.0, 1.73205), 2.0,
11656         Complex(-1.0, -1.73205), Complex(-1.0, 1.73205), 2.0]
11657  snd_test_any_neq(res, req, :vcequal?, "poly_roots 64 0 0 -16 0 0 1")
11658  # degree=3
11659  res = poly(-15, 23, -9, 1).roots
11660  req = [5.0, 1.0, 3.0]
11661  snd_test_any_neq(res, req, :vequal?, "poly_roots -15 23 -9 1")
11662  res = poly(-126, -15, 0, 1).roots
11663  req = [6.0, Complex(-3.0, 3.46410), Complex(-3.0, -3.46410)]
11664  snd_test_any_neq(res, req, :vcequal?, "poly_roots -126 -15 0 1")
11665  res = poly(-1, 3, -3, 1).roots
11666  req = [1.0, 1.0, 1.0]
11667  snd_test_neq(res, req, "poly_roots -1 3 -3 1")
11668  res = poly(1, -1, -1, 1).roots
11669  req = [1.0, -1.0, 1.0]
11670  snd_test_any_neq(res, req, :vequal?, "poly_roots 1 -1 -1 1")
11671  res = poly(2, -2, -2, 2).roots
11672  req = [1.0, -1.0, 1.0]
11673  snd_test_any_neq(res, req, :vequal?, "poly_roots 2 -2 -2 2")
11674  # degree=4
11675  res = poly(-15, 8, 14, -8, 1).roots
11676  req = [5.0, 3.0, 1.0, -1.0]
11677  snd_test_neq(res, req, "poly_roots -15 8 14 -8 1: [5.0, 3.0, 1.0, -1.0]")
11678  res = (poly(2, 1) * poly(-3, 1) * poly(8, 1) * poly(-9, 1)).reduce.roots
11679  req = [9, 3, -2, -8]
11680  snd_test_neq(res, req, "poly_roots 4(1)")
11681  res = (poly(0.2, 1) * poly(-3, 1) * poly(0.8, 1) * poly(-9, 1)).reduce.roots
11682  req = [9, 3, -0.2, -0.8]
11683  snd_test_any_neq(res, req, :vequal?, "poly_roots 4(2)")
11684  res = (poly(0.02, 1) * poly(-32, 1) * poly(0.8, 1) * poly(-9, 1)).reduce.roots
11685  req = [32, 9, -0.02, -0.8]
11686  snd_test_any_neq(res, req, :vequal?, "poly_roots 4(3)")
11687  # degree>4
11688  res = poly(1, 1) * poly(2, 1) * poly(-3, 1) * poly(-1, 1) * poly(-2, 1)
11689  res = res.reduce.roots
11690  req = [3, 2, -1, -2, 1]
11691  snd_test_any_neq(res, req, :vequal?, "poly_roots n(1)")
11692  res = poly(1, 1) * poly(2, 1) * poly(-3, 1) * poly(8, 1) * poly(-9, 1)
11693  res = res.reduce.roots
11694  req = [9, 3, -2, -8, -1]
11695  snd_test_any_neq(res, req, :vequal?, "poly_roots n(2)")
11696  res = poly(-1, 0, 1) * poly(9, 1) * poly(-3, 1) * poly(-10, 1) * poly(-2, 1)
11697  res = res.reduce.roots
11698  req = [10, 3, -1, -9, 2, 1]
11699  snd_test_any_neq(res, req, :vequal?, "poly_roots n(3)")
11700  res = poly(-1, 0, 1) * poly(-4, 0, 1) * poly(-3, 1) *
11701        poly(-10, 1) * poly(-9, 0, 1)
11702  res = res.reduce.roots
11703  req = [10, 3, -2, -3, -1, 3, 2, 1]
11704  snd_test_any_neq(res, req, :vequal?, "poly_roots n(4)")
11705  res = poly(-1, 0, 1) * poly(-4, 0, 1) * poly(-16, 0, 1) *
11706        poly(-25, 0, 1) * poly(-9, 0, 1)
11707  res = res.reduce.roots
11708  req = [5, -3, -4, -5, 4, -2, 3, -1, 2, 1]
11709  snd_test_any_neq(res, req, :vequal?, "poly_roots n(5)")
11710  res = poly(1, 1) * poly(2, 1) * poly(-3, 1) * poly(1, 1) * poly(-2, 1)
11711  res = res.reduce.roots
11712  req = [3, -1, -1, -2, 2]
11713  snd_test_any_neq(res, req, :vequal?, "poly_roots n(6)")
11714  res = poly(-64, 0, 0, 0, 0, 0, 1).roots
11715  req = [Complex(0.999, -1.732), Complex(-1.0, -1.732), -2.0,
11716         Complex(-1.0, 1.732), Complex(1.0, 1.732), 2.0]
11717  snd_test_any_neq(res, req, :vcequal?, "poly_roots 64 6")
11718  res = poly(64, 0, 0, -16, 0, 0, 1).roots
11719  req = [Complex(-1.0, -1.732), Complex(-1.0, 1.732), 2.0,
11720         Complex(-1.0, -1.732), Complex(-1.0, 1.732), 2.0]
11721  snd_test_any_neq(res, req, :vcequal?, "poly_roots 64 16 6")
11722  10.times do poly(random(1.0), random(1.0), random(1.0)).roots end
11723  10.times do poly(mus_random(1.0), mus_random(1.0), mus_random(1.0)).roots end
11724  res = convolution(vct(1, 2, 3, 0, 0, 0, 0, 0), vct(1, 2, 3, 0, 0, 0, 0, 0), 8)
11725  req = poly(1, 2, 3, 0) * poly(1, 2, 3, 0)
11726  snd_test_any_neq(res, req, :vequal?, "poly_multiply convolve")
11727  10.times do
11728    poly(make_rectangular(mus_random(1.0), mus_random(1.0)),
11729         make_rectangular(mus_random(1.0), mus_random(1.0))).roots
11730  end
11731  10.times do
11732    poly(make_rectangular(mus_random(1.0), mus_random(1.0)),
11733         make_rectangular(mus_random(1.0), mus_random(1.0)),
11734         make_rectangular(mus_random(1.0), mus_random(1.0))).roots
11735  end
11736  10.times do
11737    poly(mus_random(1.0), mus_random(1.0),
11738         mus_random(1.0), mus_random(1.0)).roots
11739  end
11740  10.times do
11741    poly(make_rectangular(mus_random(1.0), mus_random(1.0)),
11742         make_rectangular(mus_random(1.0), mus_random(1.0)),
11743         make_rectangular(mus_random(1.0), mus_random(1.0)),
11744         make_rectangular(mus_random(1.0), mus_random(1.0))).roots
11745  end
11746  10.times do
11747    poly(mus_random(1.0), mus_random(1.0), mus_random(1.0),
11748         mus_random(1.0), mus_random(1.0)).roots
11749  end
11750  10.times do
11751    poly(make_rectangular(mus_random(1.0), mus_random(1.0)),
11752         make_rectangular(mus_random(1.0), mus_random(1.0)),
11753         make_rectangular(mus_random(1.0), mus_random(1.0)),
11754         make_rectangular(mus_random(1.0), mus_random(1.0)),
11755         make_rectangular(mus_random(1.0), mus_random(1.0))).roots
11756  end
11757  3.upto(20) do |i|
11758    v = Vct.new(i)
11759    v[0] = mus_random(1.0)
11760    v[i - 1] = 1.0
11761    poly_roots(v)
11762  end
11763  3.step(21, 2) do |i|
11764    v = Vct.new(i)
11765    v[0] = mus_random(1.0)
11766    v[i - 1] = 1.0
11767    v[(i - 1) / 2] = 1.0
11768    v.to_poly.roots
11769  end
11770  res = poly(1, -1, -1, 1).roots
11771  req = [1.0, -1.0, 1.0]
11772  snd_test_any_neq(res, req, :vequal?, "poly_roots 1 -1 -1 1")
11773  res = poly_roots(vct(2, -1, -2, 1))
11774  req = [2.0, -1.0, 1.0]
11775  snd_test_any_neq(res, req, :vequal?, "poly_roots 2 -1 -2 1")
11776  res = poly(-1, 1, 1, 1).roots
11777  req = [0.544, Complex(-0.772, 1.115), Complex(-0.772, -1.115)]
11778  snd_test_any_neq(res, req, :vcequal?, "poly_roots -1 1 1 1")
11779  res = poly_roots(vct(-1, 3, -3, 1))
11780  req = [1.0, 1.0, 1.0]
11781  snd_test_neq(res, req, "poly_roots -1 3 -3 1")
11782  res = poly_roots(vct(1, -4, 6, -4, 1))
11783  req = [1.0, 1.0, 1.0, 1.0]
11784  snd_test_neq(res, req, "poly_roots 1 -4 6 -4 1")
11785  res = poly_roots(vct(0.5, 0, 0, 1))
11786  req1 = [Complex(0.397, -0.687), -0.794, Complex(0.397, 0.687)]
11787  req2 = [Complex(0.397, 0.687), Complex(0.397, -0.687), -0.794]
11788  if vcneql(res, req1) and vcneql(res, req2)
11789    snd_format_neq(res, req1, "poly_roots 0.5 0 0 1 (a)")
11790    snd_format_neq(res, req2, "poly_roots 0.5 0 0 1 (b)")
11791  end
11792  # FIXME: reduce added (poly)
11793  # without reduce:
11794  #   3.0 -1.0 -2.0 -3.0 2.0-1.1555579666323415e-33i 1.0+2.9582283945787943e-31i
11795  res = poly(-1, 1) * poly(1, 1) * poly(-2, 1) * poly(2, 1) *
11796        poly(-3, 1) * poly(3, 1)
11797  res = res.reduce.roots
11798  req = [-3.0, 3.0, -1.0, 1.0, -2.0, 2.0]
11799  snd_test_any_neq(res, req, :vequal?, "cube in 2")
11800end
11801
11802def jc_reverb_1(decay_dur, low_pass, volume, amp_env)
11803  allpass1 = make_all_pass(-0.7, 0.7, 1051)
11804  allpass2 = make_all_pass(-0.7, 0.7,  337)
11805  allpass3 = make_all_pass(-0.7, 0.7,  113)
11806  comb1 = make_comb(0.742, 4799)
11807  comb2 = make_comb(0.733, 4999)
11808  comb3 = make_comb(0.715, 5399)
11809  comb4 = make_comb(0.697, 5801)
11810  outdel = make_delay((0.013 * srate).round)
11811  dur = decay_dur + framples / srate
11812  envA = (amp_env ? make_env(:envelope, amp_env, :scaler, volume, :duration, dur) : false)
11813  comb_sum_1 = comb_sum_2 = comb_sum = all_sums = delA = delB = 0.0
11814  map_chan(lambda do |inval|
11815             allpass_sum = all_pass(allpass3, all_pass(allpass2, all_pass(allpass1, inval)))
11816             comb_sum_2, comb_sum_1 = comb_sum_1, comb_sum
11817             comb_sum = (comb(comb1, allpass_sum) + comb(comb2, allpass_sum) +
11818                           comb(comb3, allpass_sum) + comb(comb4, allpass_sum))
11819             all_sums = if low_pass
11820                          0.25 * (comb_sum + comb_sum_2) + 0.5 * comb_sum_1
11821                        else
11822                          comb_sum
11823                        end
11824             inval + if envA
11825                       env(envA) * delay(outdel, all_sums)
11826                     else
11827                       volume * delay(outdel, all_sums)
11828                     end
11829           end, 0, (dur * srate).to_i)
11830end
11831
11832# fm_violin
11833def fm_violin_1(start, dur, freq, amp, *args)
11834    fm_index, amp_env, periodic_vibrato_rate, random_vibrato_rate = nil
11835    periodic_vibrato_amp, random_vibrato_amp, noise_amount, noise_freq = nil
11836    ind_noise_freq, ind_noise_amount, amp_noise_freq, amp_noise_amount = nil
11837    gliss_env, gliss_amount, fm1_env, fm2_env, fm3_env, fm1_rat, fm2_rat, fm3_rat = nil
11838    fm1_index, fm2_index, fm3_index, base, index_type, reverb_amount, degree, distance = nil
11839    optkey(args, binding,
11840           [:fm_index, 1.0],
11841           [:amp_env, [0, 0, 25, 1, 75, 1, 100, 0]],
11842           [:periodic_vibrato_rate, 5.0],
11843           [:random_vibrato_rate, 16.0],
11844           [:periodic_vibrato_amp, 0.0025],
11845           [:random_vibrato_amp, 0.005],
11846           [:noise_amount, 0.0],
11847           [:noise_freq, 1000.0],
11848           [:ind_noise_freq, 10.0],
11849           [:ind_noise_amount, 0.0],
11850           [:amp_noise_freq, 20.0],
11851           [:amp_noise_amount, 0.0],
11852           [:gliss_env, [0, 0, 100, 0]],
11853           [:gliss_amount, 0.0],
11854           [:fm1_env, [0, 1, 25, 0.4, 75, 0.6, 100, 0]],
11855           [:fm2_env, [0, 1, 25, 0.4, 75, 0.6, 100, 0]],
11856           [:fm3_env, [0, 1, 25, 0.4, 75, 0.6, 100, 0]],
11857           [:fm1_rat, 1.0],
11858           [:fm2_rat, 3.0],
11859           [:fm3_rat, 4.0],
11860           [:fm1_index, false],
11861           [:fm2_index, false],
11862           [:fm3_index, false],
11863           [:base, 1.0],
11864           [:reverb_amount, 0.01],
11865           [:degree, random(90)],
11866           [:distance, 1.0])
11867  frq_scl = hz2radians(freq)
11868  modulate = fm_index.nonzero?
11869  maxdev = frq_scl * fm_index
11870  logfreq = log(freq)
11871  sqrtfreq = sqrt(freq)
11872  index1 = (fm1_index or [PI, maxdev * 5.0 / logfreq].min)
11873  index2 = (fm2_index or [PI, maxdev * 3.0 * (8.5 - logfreq) / (3.0 + freq * 0.001)].min)
11874  index3 = (fm3_index or [PI, maxdev * 4.0 / sqrtfreq].min)
11875  easy_case = (noise_amount.zero? and
11876                 fm1_env == fm2_env and
11877                 fm1_env == fm3_env and
11878                 fm1_rat == fm1_rat.floor and
11879                 fm2_rat == fm2_rat.floor and
11880                 fm3_rat == fm3_rat.floor)
11881  norm = ((easy_case and modulate and 1.0) or index1)
11882  carrier = make_oscil(:frequency, freq)
11883  fmosc1 = if modulate
11884             if easy_case
11885               make_polyshape(:frequency, fm1_rat * freq,
11886                 :coeffs, partials2polynomial([fm1_rat.to_i, index1,
11887                   (fm2_rat / fm1_rat).floor, index2,
11888                   (fm3_rat / fm1_rat).floor, index3]))
11889             else
11890               make_oscil(:frequency, fm1_rat * freq)
11891             end
11892           else
11893             false
11894           end
11895  fmosc2 = (modulate and (easy_case or make_oscil(:frequency, fm2_rat * freq)))
11896  fmosc3 = (modulate and (easy_case or make_oscil(:frequency, fm3_rat * freq)))
11897  ampf = make_env(:envelope, amp_env, :scaler, amp, :duration, dur, :base, base)
11898  indf1 = (modulate and make_env(:envelope, fm1_env, :scaler, norm, :duration, dur))
11899  indf2 = (modulate and
11900             (easy_case or make_env(:envelope, fm2_env, :scaler, index2, :duration, dur)))
11901  indf3 = (modulate and
11902             (easy_case or make_env(:envelope, fm3_env, :scaler, index3, :duration, dur)))
11903  frqf = make_env(:envelope, gliss_env, :scaler, gliss_amount * frq_scl, :duration, dur)
11904  pervib = make_triangle_wave(periodic_vibrato_rate, periodic_vibrato_amp *  frq_scl)
11905  ranvib = make_rand_interp(random_vibrato_rate, random_vibrato_amp * frq_scl)
11906  fm_noi = (noise_amount.nonzero? and make_rand(noise_freq, PI * noise_amount))
11907  ind_noi = ((ind_noise_amount.nonzero? and ind_noise_freq.nonzero?) and
11908               make_rand_interp(ind_noise_freq, ind_noise_amount))
11909  amp_noi = ((amp_noise_amount.nonzero? and amp_noise_freq.nonzero?) and
11910               make_rand_interp(amp_noise_freq, amp_noise_amount))
11911  fuzz = modulation = 0.0
11912  ind_fuzz = amp_fuzz = 1.0
11913  out_data = make_vct!(seconds2samples(dur)) do
11914    if noise_amount.nonzero?
11915      fuzz = rand(fm_noi)
11916    end
11917    vib = env(frqf) + triangle_wave(pervib) + rand_interp(ranvib)
11918    if ind_noi
11919      ind_fuzz = 1.0 + rand_interp(ind_noi)
11920    end
11921    if amp_noi
11922      amp_fuzz = 1.0 + rand_interp(amp_noi)
11923    end
11924    if modulate
11925      modulation = if easy_case
11926                     env(indf1) * polyshape(fmosc1, 1.0, vib)
11927                   else
11928                     (env(indf1) * oscil(fmosc1, fm1_rat * vib + fuzz) +
11929                     env(indf2) * oscil(fmosc2, fm2_rat * vib + fuzz) +
11930                     env(indf3) * oscil(fmosc3, fm3_rat * vib + fuzz))
11931                   end
11932    end
11933    env(ampf) * amp_fuzz * oscil(carrier, vib + ind_fuzz * modulation)
11934  end
11935  beg = seconds2samples(start)
11936  loc = make_locsig(:channels, channels(false),
11937                    :degree, degree,
11938                    :reverb, reverb_amount,
11939                    :distance, distance)
11940  channels(false).times do |chn|
11941    mix_vct(vct_scale!(vct_copy(out_data), locsig_ref(loc, chn)), beg, false, chn, false)
11942  end
11943end
11944
11945def fltit
11946  coeffs = vct(0.1, 0.2, 0.3, 0.4, 0.4, 0.3, 0.2, 0.1)
11947  flt = make_fir_filter(8, coeffs)
11948  xcof = flt.xcoeffs
11949  es = make_array(8) do |i|
11950    if i == 5
11951      make_env(:envelope, [0, 0.4, 1, 1], :duration, 1.0)
11952    else
11953      make_env(:envelope, [0, coeffs[i], 1, 0], :duration, 0.5)
11954    end
11955  end
11956  lambda do |x|
11957    es.each_with_index do |en, i|
11958      xcof[i] = env(en)
11959    end
11960    fir_filter(flt, x)
11961  end
11962end
11963
11964def freq_sweep(dur)
11965  phase = 0.0
11966  freq = 0.0
11967  incr = PI / (dur * 1.05 * mus_srate)
11968  len = framples()
11969  data = Vct.new(len) do |i|
11970    val = sin(phase)
11971    phase += freq
11972    freq += incr
11973    val
11974  end.scale!(0.5)
11975  vct2channel(data)
11976end
11977
11978def make_ssb_am_1(freq, order = 40)
11979  if order.even?
11980    order += 1
11981  end
11982  freq = freq.to_f
11983  carrier_freq = freq.abs
11984  cos_carrier = make_oscil(freq, HALF_PI)
11985  sin_carrier = make_oscil(freq)
11986  dly = make_delay(order)
11987  hlb = make_hilbert_transform(order)
11988  lambda do |y, fm|
11989    ccos = oscil(cos_carrier, fm)
11990    csin = oscil(sin_carrier, fm)
11991    yh = hilbert_transform(hlb, y)
11992    yd = delay(dly, y)
11993    if carrier_freq > 0.0
11994      ccos * yd - csin * yh # shift up
11995    else
11996      ccos * yd + csin * yh # shift down
11997    end
11998  end
11999end
12000
12001def ssb_am_1(gen, y, fm = 0.0)
12002  gen.call(y, fm)
12003end
12004
12005def rough_spectrum(ind)
12006  rd = make_sampler(0, ind, 0)
12007  spect = Vct.new(10) do
12008    sum = 0.0
12009    1000.times do
12010      val = rd.call
12011      sum = sum + val * val
12012    end
12013    sum
12014  end
12015  spect.scale!(1.0 / spect.peak)
12016end
12017
12018def print_and_check(gen, name, desc, desc1 = "", desc2 = "")
12019  if gen.name != name
12020    snd_display_prev_caller("mus_name %s: %s?", name, gen.name)
12021  end
12022  if gen.name != "xen->sample"
12023    if gen.to_s != desc and gen.to_s != desc1 and gen.to_s != desc2
12024      snd_display_prev_caller("mus_describe %s: %s?", gen.name, gen)
12025    end
12026  end
12027  egen = gen
12028  unless egen.eql?(gen)
12029    snd_display_prev_caller("eql? %s: %s?", gen, egen)
12030  end
12031end
12032
12033def test_gen_equal(g0, g1, g2)
12034  # g0 = g1 at start != g2
12035  g3 = g0
12036  gad = make_vct(2)
12037  unless g0.eql?(g3)
12038    snd_display_prev_caller("let %s %s.eql? %s?", g0.name, g0, g3)
12039  end
12040  unless g0.eql?(g1)
12041    snd_display_prev_caller("arg %s %s.eql? %s?", g0.name, g0, g1)
12042  end
12043  if g0 == g1
12044    snd_display_prev_caller("%s %s == %s?", g0.name, g0, g1)
12045  end
12046  if g0 == g2
12047    snd_display_prev_caller("%s %s == %s?", g0.name, g0, g2)
12048  end
12049  if g0 == gad
12050    snd_display_prev_caller("%s == frame %s %s?", g0.name, g0, gad)
12051  end
12052  g0.run
12053  g3.run
12054  g3.run
12055  unless g0.eql?(g3)
12056    snd_display_prev_caller("run let %s %s.eql? %s?", g0.name, g0, g3)
12057  end
12058  if g0.eql?(g1)
12059    snd_display_prev_caller("arg %s %s.eql? %s?", g0.name, g0, g1)
12060  end
12061  if g0 == g1
12062    snd_display_prev_caller("run %s %s == %s?", g0.name, g0, g1)
12063  end
12064  if g0 == g2
12065    snd_display_prev_caller("run %s %s != %s?", g0.name, g0, g2)
12066  end
12067end
12068
12069def fm_test(gen)
12070  if mus_generator?(gen)
12071    gen.frequency = 0.0
12072    gen.phase = 0.0
12073    gen.run(0.0)
12074    if fneq(res = gen.phase, 0.0)
12075      snd_display_prev_caller("%s phase(0): %s?", gen, res)
12076    end
12077    gen.run(1.0)
12078    if fneq(res = gen.phase, 1.0)
12079      snd_display_prev_caller("%s phase(1): %s?", gen, res)
12080    end
12081    gen.run(0.0)
12082    if fneq(res = gen.phase, 1.0)
12083      snd_display_prev_caller("%s phase(1, 0): %s?", gen, res)
12084    end
12085    gen.frequency = radians2hz(2.0)
12086    if fneq(res = gen.increment, 2.0)
12087      snd_display_prev_caller("%s increment: %s", gen, res)
12088    end
12089    gen.increment = 2.0
12090    if fneq(res = gen.frequency, radians2hz(2.0))
12091      snd_display_prev_caller("%s set increment: %s %s", gen, gen.increment, hz2radians(res))
12092    end
12093    gen.run(0.0)
12094    if fneq(res = gen.phase, 3.0)
12095      snd_display_prev_caller("%s phase(1, 2): %s %s?", gen, res, gen.frequency)
12096    end
12097    gen.run(1.0)
12098    if fneq(res = gen.phase, 6.0)
12099      snd_display_prev_caller("%s phase(3, 2, 1): %s %s?", gen, res, gen.frequency)
12100    end
12101    10.times do gen.run(10.0) end
12102    if fneq(res = gen.phase, 26 + 100 - TWO_PI * 20)
12103      snd_display_prev_caller("%s phase (over): %s %s?", gen, res, gen.frequency)
12104    end
12105    gen.frequency = 0.0
12106    gen.phase = 0.0
12107    gen.run(1234567812345678)
12108    gen.run(-1234567812345678)
12109    gen.frequency = 0.0
12110    gen.phase = 0.0
12111    gen.run(-2.0)
12112    if fneq(res = gen.phase, -2.0) and fneq(res, TWO_PI - 2)
12113      snd_display_prev_caller("phase %s freq: %s?", res, gen.frequency)
12114    end
12115  else
12116    snd_display_prev_caller("%s not a gen?", gen.inspect)
12117  end
12118end
12119
12120def test_08_00
12121  set_mus_srate(22050)
12122  samps = seconds2samples(1.0)
12123  secs = samples2seconds(22050)
12124  if samps != 22050
12125    snd_display("seconds2samples: %s?", samps)
12126  end
12127  if fneq(secs, 1.0)
12128    snd_display("samples2seconds: %s?", secs)
12129  end
12130  set_mus_file_buffer_size($default_file_buffer_size)
12131  if (res = Snd.catch do
12132       set_mus_file_buffer_size(false)
12133      end).first != :wrong_type_arg
12134    snd_display("mus_file_buffer_size bad size: %s?", res)
12135  end
12136  set_mus_file_buffer_size(128)
12137  if (res = mus_file_buffer_size) != 128
12138    snd_display("set_mus_file_buffer_size: %s?", res)
12139  end
12140  set_mus_file_buffer_size($default_file_buffer_size)
12141  if (res = mus_array_print_length) != 8
12142    snd_display("mus_array_print_length: %s?", res)
12143  end
12144  set_mus_array_print_length(12)
12145  if (res = mus_array_print_length) != 12
12146    snd_display("mus_array_print_length: %s?", res)
12147  end
12148  set_mus_array_print_length(32)
12149  if (res = mus_array_print_length) != 32
12150    snd_display("set_mus_array_print_length: %s?", res)
12151  end
12152  set_mus_array_print_length(8)
12153  fudge = mus_float_equal_fudge_factor
12154  if (mus_float_equal_fudge_factor - 0.0000001).abs > 0.00000001
12155    snd_display("mus_float_equal_fudge_factor: %s?", mus_float_equal_fudge_factor)
12156  end
12157  set_mus_float_equal_fudge_factor(0.1)
12158  if fneq(mus_float_equal_fudge_factor, 0.1)
12159    snd_display("set_mus_float_equal_fudge_factor: %s?", mus_float_equal_fudge_factor)
12160  end
12161  set_mus_float_equal_fudge_factor(fudge)
12162  if fneq(mus_srate, 22050.0)
12163    snd_display("mus_srate: %s?", mus_srate)
12164  end
12165  if fneq(res = hz2radians(1.0), 2.84951704088598e-4)
12166    snd_display("hz2radians: %s?", res)
12167  end
12168  if fneq(res = radians2hz(2.84951704088598e-4), 1.0)
12169    snd_display("radians2hz: %s?", res)
12170  end
12171  if fneq(res = radians2degrees(1.0), 57.2957801818848)
12172    snd_display("radians2degrees: %s?", res)
12173  end
12174  if fneq(res = degrees2radians(57.2957801818848), 1.0)
12175    snd_display("degrees2radians: %s?", res)
12176  end
12177  if fneq(res = linear2db(0.25), -12.0411996841431)
12178    snd_display("linear2db: %s?", res)
12179  end
12180  if fneq(res = db2linear(-12.0411996841431), 0.25)
12181    snd_display("db2linear: %s?", res)
12182  end
12183  if fneq(res = ring_modulate(0.4, 0.5), 0.2)
12184    snd_display("ring_modulate: %s?", res)
12185  end
12186  if fneq(res = amplitude_modulate(1.0, 0.5, 0.4), 0.7)
12187    snd_display("amplitude_modulate: %s?", res)
12188  end
12189  if fneq(res = contrast_enhancement(0.1, 0.75), sin(0.1 * (PI / 2) + 0.75 * sin(0.1 * 2.0 * PI)))
12190    snd_display("contrast_enhancement: %s (0.562925306221587)", res)
12191  end
12192  if fneq(res = contrast_enhancement(1.0), 1.0)
12193    snd_display("contrast_enhancement: %s (1.0)", res)
12194  end
12195  #
12196  [[partials2polynomial([1, 1, 2, 1], Mus_chebyshev_first_kind),
12197    vct(-1.0, 1.0, 2.0)],
12198   [partials2polynomial([1, 1, 2, 1], Mus_chebyshev_second_kind),
12199    vct(1.0, 2.0, 0.0)],
12200   [partials2polynomial([1, 1, 2, 1, 3, 1, 5, 1], Mus_chebyshev_first_kind),
12201    vct(-1.0, 3.0, 2.0, -16.0, 0.0, 16.0)],
12202   [partials2polynomial([1, 1, 2, 1, 3, 1, 5, 1], Mus_chebyshev_second_kind),
12203    vct(1.0, 2.0, -8.0, 0.0, 16.0, 0.0)],
12204   [partials2polynomial([1, 1, 2, 0.5, 3, 0.1, 6, 0.01], Mus_chebyshev_first_kind),
12205    vct(-0.51, 0.7, 1.18, 0.4, -0.48, 0.0, 0.32)],
12206   [partials2polynomial([1, 1, 2, 0.5, 3, 0.1, 6, 0.01], Mus_chebyshev_second_kind),
12207    vct(0.9, 1.06, 0.4, -0.32, 0.0, 0.32, 0.0)],
12208   [partials2polynomial([1, 9, 2, 3, 3, 5, 4, 7, 5, 1]),
12209    vct(4.0, -1.0, -50.0, 0.0, 56.0, 16.0)],
12210   [partials2polynomial([7, 1]),
12211    vct(0.0, -7.0, 0.0, 56.0, 0.0, -112.0, 0.0, 64.0)],
12212   [partials2polynomial([7, 1], Mus_chebyshev_first_kind),
12213    vct(0.0, -7.0, 0.0, 56.0, 0.0, -112.0, 0.0, 64.0)],
12214   [partials2polynomial([7, 1], Mus_chebyshev_second_kind),
12215    vct(-1.0, 0.0, 24.0, 0.0, -80.0, 0.0, 64.0, 0.0)]].each_with_index do |args, i|
12216    vals, orig = args
12217    unless vequal(vals, orig)
12218      snd_display("partials2polynomial[%s]: %s?", i + 1, vals)
12219    end
12220  end
12221  #
12222  if defined? cosh
12223    lv7 = partials2polynomial([7, 1])
12224    lv8 = partials2polynomial([7, 1], Mus_chebyshev_second_kind)
12225    #
12226    if fneq(res1 = polynomial(lv7, 1.0), res2 = cosh(7.0 * acosh(1.0)))
12227      snd_display("ccosh cheb 7 1.0: %s %s?", res1, res2)
12228    end
12229    if fneq(res1 = polynomial(lv7, 1.0), res2 = cos(7.0 * acos(1.0)))
12230      snd_display("cos cheb 7 1.0: %s %s?", res1, res2)
12231    end
12232    if fneq(res1 = polynomial(lv8, 1.0), res2 = sin(7.0 * acos(1.0)) / sin(acos(1.0)))
12233      snd_display("acos cheb 7 1.0: %s %s?", res1, res2)
12234    end
12235    10.times do
12236      val = mus_random(1.0)
12237      res = polynomial(lv7, val)
12238      req = cosh(7.0 * acosh(val)).to_f
12239      snd_test_neq(res, req, "ccosh cheb 7 %s", val)
12240      res = polynomial(lv7, val)
12241      req = cos(7.0 * acos(val))
12242      snd_test_neq(res, req, "cos cheb 7 %s", val)
12243      res = polynomial(lv8, val)
12244      req = sin(7.0 * acos(val)) / sin(acos(val))
12245      snd_test_neq(res, req, "acos cheb 7 %s", val)
12246    end
12247  end
12248  #
12249  # check phase-quadrature cancellations
12250  #
12251  cos_coeffs = partials2polynomial([1, 1, 2, 1], Mus_chebyshev_first_kind)
12252  sin_coeffs = partials2polynomial([1, 1, 2, 1], Mus_chebyshev_second_kind)
12253  incr = (2 * PI * 440.0) / 22050.0
12254  a = 0.0
12255  1100.times do
12256    x = cos(a)
12257    y = sin(a)
12258    cax = polynomial(cos_coeffs, x)
12259    sax = polynomial(sin_coeffs, x)
12260    upper = cos(2 * a) * cax - sin(2 * a) * y * sax
12261    lower = cos(2 * a) * cax + sin(2 * a) * y * sax
12262    upper2 = cos(a * 3) + cos(a * 4)
12263    lower2 = 1.0 + cos(a)
12264    if fneq(upper, upper2) or fneq(lower, lower2)
12265      snd_display("%s %s, %s %s?", upper, upper2, lower, lower2)
12266    end
12267    a += incr
12268  end
12269  #
12270  if (res = Snd.catch do harmonicizer(550.0, [0.5, 0.3, 0.2], 10) end).first != :no_data
12271    snd_display("odd length arg to partials2polynomial: %s", res.inspect)
12272  end
12273  rdat = make_vct(16)
12274  idat = make_vct(16)
12275  vdat = make_vct(16)
12276  rdat[0] = 1.0
12277  vdat[0] = 1.0
12278  v0 = spectrum(rdat, idat, make_fft_window(Rectangular_window, 16), 1)
12279  v1 = snd_spectrum(vdat, Rectangular_window, 16, true)
12280  8.times do |i|
12281    if fneq(v0[i], v1[i])
12282      snd_display("spectra not equal 1: %s %s?", v0, v1)
12283    end
12284  end
12285  idat.scale!(0.0)
12286  rdat.scale!(0.0)
12287  rdat[0] = 1.0
12288  v0 = spectrum(rdat, idat, make_fft_window(Rectangular_window, 17), 1)
12289  v1 = snd_spectrum(vdat, Rectangular_window, 16, true)
12290  8.times do |i|
12291    if fneq(v0[i], v1[i])
12292      snd_display("spectra not equal 0: %s %s?", v0, v1)
12293    end
12294  end
12295  if (res = Snd.catch do spectrum(rdat, idat, false, -1) end).first != :out_of_range
12296    snd_display("spectrum bad type: %s", res.inspect)
12297  end
12298  #
12299  rdat = make_vct(16)
12300  idat = make_vct(16)
12301  xdat = make_vct(16)
12302  ydat = make_vct(16)
12303  rdat[3] = 1.0
12304  xdat[3] = 1.0
12305  fft(rdat, idat, 1)
12306  mus_fft(xdat, ydat, 16, 1)
12307  if fneq(rdat[0], xdat[0])
12308    snd_display("ffts: %s %s", rdat, xdat)
12309  end
12310  fft(rdat, idat, -1)
12311  mus_fft(xdat, ydat, 17, -1)
12312  16.times do |i|
12313    if (i == 3 and (fneq(rdat[i], 16.0) or fneq(xdat[i], 16.0))) or
12314        (i != 3 and (fneq(rdat[i], 0.0) or fneq(xdat[i], 0.0)))
12315      snd_display("fft real[%s]: %s %s?", i, rdat[i], xdat[i])
12316    end
12317    if fneq(idat[i], 0.0) or fneq(ydat[i], 0.0)
12318      snd_display("fft imag[%s]: %s %s?", i, idat[i], ydat[i])
12319    end
12320  end
12321  if (res = Snd.catch do mus_fft(xdat, ydat, -1, 0) end).first != :out_of_range
12322    snd_display("mus_fft bad len: %s", res.inspect)
12323  end
12324  #
12325  rdat = make_vct(20)
12326  idat = make_vct(19)
12327  rdat[3] = 1.0
12328  mus_fft(rdat, idat)
12329  convolution(rdat, idat)
12330  spectrum(rdat, idat, false)
12331  #
12332  v0 = make_vct(10)
12333  v1 = make_vct(10)
12334  vct_fill!(v0, 1.0)
12335  vct_fill!(v1, 0.5)
12336  v0.map_with_index! do |x, i|
12337    x * v1[i]
12338  end
12339  if fneq(res = dot_product(v0, v1), 2.5)
12340    snd_display("dot_product: %s?", res)
12341  end
12342  if fneq(res = dot_product(v0, v1, 10), 2.5)
12343    snd_display("dot_product (10): %s?", res)
12344  end
12345  if fneq(res = dot_product(v0, v1, 3), 0.75)
12346    snd_display("dot_product (3): %s?", res)
12347  end
12348  v0.map! do |x|
12349    0.0
12350  end
12351  if fneq(v0[3], 0.0)
12352    snd_display("clear v0: %s?", v0)
12353  end
12354  vct_fill!(v0, 1.0)
12355  vct_fill!(v1, 0.5)
12356  if fneq((res = rectangular2polar(v0, v1))[0], 1.118)
12357    snd_display("rectangular2polar: %s?", res)
12358  end
12359  vct_fill!(v0, 1.0)
12360  vct_fill!(v1, 1.0)
12361  rectangular2polar(v0, v1)
12362  if fneq(v0[0], sqrt(2.0)) or fneq(v1[0], -atan2(1.0, 1.0))
12363    snd_display("rectangular2polar (%s %s): %s %s?", sqrt(2.0), -atan2(1.0, 1.0), v0[0], v1[0])
12364  end
12365  polar2rectangular(v0, v1)
12366  if fneq(v0[0], 1.0) or fneq(v1[0], 1.0)
12367    snd_display("polar2rectangular (1 1): %s %s?", v0[0], v1[0])
12368  end
12369  #
12370  ind = open_sound("oboe.snd")
12371  rl = channel2vct(1200, 512)
12372  im = make_vct(512)
12373  fft(rl, im, 512)
12374  rl_copy = vct_copy(rl)
12375  im_copy = vct_copy(im)
12376  rectangular2polar(rl, im)
12377  polar2rectangular(rl, im)
12378  512.times do |i|
12379    if fneq(rl[i], rl_copy[i]) or fneq(im[i], im_copy[i])
12380      snd_display("polar2rectangular[%s]: %s %s %s %s?", i, rl[i], rl_copy[i], im[i], im_copy[i])
12381    end
12382  end
12383  close_sound(ind)
12384  #
12385  if defined? edot_product                        # edot_product in dsp.rb
12386    vals = make_vct(1, 1.0)
12387    if fneq(res = edot_product(0.0, vals), 1.0)
12388      snd_display("edot 1.0: %s?", res)
12389    end
12390    vals[0] = 0.0
12391    if fneq(res = edot_product(0.0, vals), 0.0)
12392      snd_display("edot 0.0: %s?", res)
12393    end
12394    vals = make_array(1, 1.0)
12395    if fneq(res = edot_product(0.0, vals), 1.0)
12396      snd_display("edot 1.0: %s?", res)
12397    end
12398    vals[0] = Complex(0.0)
12399    if cneq(res = edot_product(0.0, vals), Complex(0.0))
12400      snd_display("edot i: %s?", res)
12401    end
12402    vals = make_vct(4, 1.0)
12403    v1 = edot_product(0.25 * TWO_PI, vals)
12404    v2 = exp(0.00 * TWO_PI) +
12405         exp(0.25 * TWO_PI) +
12406         exp(0.50 * TWO_PI) +
12407         exp(0.75 * TWO_PI)
12408    if fneq(v1, v2)
12409      snd_display("edot 4 i: %s %s?", v1, v2)
12410    end
12411    vals = make_array(4) do |i| i + 1.0 end
12412    v1 = edot_product(0.25 * TWO_PI * Complex(0.0), vals)
12413    v2 = 1 * exp(0.00 * TWO_PI * Complex(0.0)) +
12414         2 * exp(0.25 * TWO_PI * Complex(0.0)) +
12415         3 * exp(0.50 * TWO_PI * Complex(0.0)) +
12416         4 * exp(0.75 * TWO_PI * Complex(0.0))
12417    if cneq(v1, v2)
12418      snd_display("edot 4 -i: %s %s?", v1, v2)
12419    end
12420    vals.map! do |i| i + Complex(1.0) end
12421    v1 = edot_product(0.25 * TWO_PI * Complex(0.0, -1), vals)
12422    v2 = Complex(1.0) * exp(0.00 * TWO_PI * Complex(0.0, -1)) +
12423         Complex(2.0) * exp(0.25 * TWO_PI * Complex(0.0, -1)) +
12424         Complex(3.0) * exp(0.50 * TWO_PI * Complex(0.0, -1)) +
12425         Complex(4.0) * exp(0.75 * TWO_PI * Complex(0.0, -1))
12426    if cneq(v1, v2)
12427      snd_display("edot 4 -i * i: %s %s?", v1, v2)
12428    end
12429  end
12430  #
12431  v0 = vct(1.0, 0.5, 0.1)
12432  if fneq(res0 = polynomial(v0, 0.0), 1.0) or
12433      fneq(res1 = polynomial(v0, 1.0), 1.6) or
12434      fneq(res2 = polynomial(v0, 2.0), 2.4)
12435    snd_display("polynomial: %s %s %s?", res0, res1, res2)
12436  end
12437  if fneq(res = polynomial(vct(0.0, 2.0), 0.5), 1.0)
12438    snd_display("polynomial 2.0 * 0.5: %s?", res)
12439  end
12440  if (res = Snd.catch do polynomial(false, 1.0) end).first != :wrong_type_arg
12441    snd_display("polynomial empty coeffs: %s", res.inspect)
12442  end
12443  #
12444  coeffs = vct(1.0, 0.0, -0.4999999963, 0.0, 0.0416666418,
12445               0.0, -0.0013888397, 0.0, 0.0000247609, 0.0, -0.0000002605)
12446  new_cos = lambda do |x|
12447    if (x = x.abs) <= HALF_PI
12448      polynomial(coeffs, x)
12449    elsif (nx = fmod(x, TWO_PI)) <= HALF_PI
12450      polynomial(coeffs, nx)
12451    elsif nx <= PI
12452      -polynomial(coeffs, PI - nx)
12453    elsif nx < 1.5 * PI
12454      -polynomial(coeffs, nx - PI)
12455    else
12456      polynomial(coeffs, TWO_PI - nx)
12457    end
12458  end
12459  err = 0.0
12460  x = -10.0
12461  2000.times do |i|
12462    diff = (cos(x) - new_cos.call(x)).abs
12463    if diff > err
12464      err = diff
12465    end
12466    x += 0.01
12467  end
12468  if err > 1.1e-7
12469    snd_display("new_cos poly err: %s?", err)
12470  end
12471  #
12472  # POLY
12473  #
12474  res = poly(0.1, 0.2, 0.3) + vct(0, 1, 2, 3, 4)
12475  req = vct(0.1, 1.2, 2.3, 3, 4)
12476  snd_test_neq(res, req, "poly_add 1")
12477  res = poly(0.1, 0.2, 0.3) + 0.5
12478  req = vct(0.6, 0.2, 0.3)
12479  snd_test_neq(res, req, "poly_add 2")
12480  res = 0.5 + poly(0.1, 0.2, 0.3)
12481  req = vct(0.6, 0.2, 0.3)
12482  snd_test_neq(res, req, "poly_add 3")
12483  #
12484  res = poly(1, 1) * vct(-1, 1)
12485  req = vct(-1, 0, 1, 0)
12486  snd_test_neq(res, req, "poly_multiply 1")
12487  res = poly(-5, 1) * vct(3, 7, 2)
12488  req = vct(-15, -32, -3, 2, 0)
12489  snd_test_neq(res, req, "poly_multiply 2")
12490  res = poly(-30, -4, 2) * vct(0.5, 1)
12491  req = vct(-15, -32, -3, 2, 0)
12492  snd_test_neq(res, req, "poly_multiply 3")
12493  res = poly(-30, -4, 2) * 0.5
12494  req = vct(-15, -2, 1)
12495  snd_test_neq(res, req, "poly_multiply 4")
12496  res = 2.0 * poly(-30, -4, 2)
12497  req = vct(-60, -8, 4)
12498  snd_test_neq(res, req, "poly_multiply 5")
12499  #
12500  res = poly(-1, 0, 1) / vct(1, 1)
12501  req1 = vct(-1, 1, 0)
12502  req2 = vct(0, 0, 0)
12503  unless vequal(res[0], req1) or vequal(res[1], req2)
12504    snd_format_neq(res[0], req1, "poly_div 1a")
12505    snd_format_neq(res[1], req2, "poly_div 1b")
12506  end
12507  res = poly(-15, -32, -3, 2) / vct(-5, 1)
12508  req1 = vct(3, 7, 2, 0)
12509  req2 = vct(0, 0, 0, 0)
12510  unless vequal(res[0], req1) or vequal(res[1], req2)
12511    snd_format_neq(res[0], req1, "poly_div 2a")
12512    snd_format_neq(res[1], req2, "poly_div 2b")
12513  end
12514  res = poly(-15, -32, -3, 2) / vct(3, 1)
12515  req1 = vct(-5, -9, 2, 0)
12516  req2 = vct(0, 0, 0, 0)
12517  unless vequal(res[0], req1) or vequal(res[1], req2)
12518    snd_format_neq(res[0], req1, "poly_div 3a")
12519    snd_format_neq(res[1], req2, "poly_div 3b")
12520  end
12521  res = poly(-15, -32, -3, 2) / vct(0.5, 1)
12522  req1 = vct(-30, -4, 2, 0)
12523  req2 = vct(0, 0, 0, 0)
12524  unless vequal(res[0], req1) or vequal(res[1], req2)
12525    snd_format_neq(res[0], req1, "poly_div 4a")
12526    snd_format_neq(res[1], req2, "poly_div 4b")
12527  end
12528  res = poly(-15, -32, -3, 2) / vct(3, 7, 2)
12529  req1 =  vct(-5, 1, 0, 0)
12530  req2 = vct(0, 0, 0, 0)
12531  unless vequal(res[0], req1) or vequal(res[1], req2)
12532    snd_format_neq(res[0], req1, "poly_div 5a")
12533    snd_format_neq(res[1], req2, "poly_div 5b")
12534  end
12535  res = poly(-15, -32, -3, 2) / 2.0
12536  req = vct(-7.5, -16, -1.5, 1)
12537  snd_test_neq(res[0], req, "poly_div 6")
12538  res = poly(-1, 0, 0, 0, 1) / vct(1, 0, 1)
12539  req1 = vct(-1, 0, 1, 0, 0)
12540  req2 = vct(0, 0, 0, 0, 0)
12541  unless vequal(res[0], req1) or vequal(res[1], req2)
12542    snd_format_neq(res[0], req1, "poly_div 7a")
12543    snd_format_neq(res[1], req2, "poly_div 7b")
12544  end
12545  res = poly(-1, 0, 0, 0, 0, 0, 0, 0, 1) / vct(1, 0, 0, 0, 1)
12546  req1 = vct(-1, 0, 0, 0, 1, 0, 0, 0, 0)
12547  req2 = vct(0, 0, 0, 0, 0, 0, 0, 0, 0)
12548  unless vequal(res[0], req1) or vequal(res[1], req2)
12549    snd_format_neq(res[0], req1, "poly_div 8a")
12550    snd_format_neq(res[1], req2, "poly_div 8b")
12551  end
12552  res = poly(-1, 0, 1) / vct(-1, 0, 1)
12553  req1 = vct(1, 0, 0)
12554  req2 = vct(0, 0, 0)
12555    snd_format_neq(res[0], req1, "poly_div 9a")
12556    snd_format_neq(res[1], req2, "poly_div 9b")
12557  res = poly(-1, 0, 1) / vct(2, 1)
12558  req1 = vct(-2, 1, 0)
12559  req2 = vct(3, 0, 0)
12560  unless vequal(res[0], req1) or vequal(res[1], req2)
12561    snd_format_neq(res[0], req1, "poly_div 10a")
12562    snd_format_neq(res[1], req2, "poly_div 10b")
12563  end
12564  res = poly(2, 1) / vct(-1, 0, 1)
12565  req1 = vct(0)
12566  req2 = vct(-1, 0, 1)
12567  unless vequal(res[0], req1) or vequal(res[1], req2)
12568    snd_format_neq(res[0], req1, "poly_div 11a")
12569    snd_format_neq(res[1], req2, "poly_div 11b")
12570  end
12571  res = poly(1, 2, 3, 0, 1) / vct(0, 0, 0, 1)
12572  req1 = vct(0, 1, 0, 0, 0)
12573  req2 = vct(1, 2, 3, 0, 0)
12574  unless vequal(res[0], req1) or vequal(res[1], req2)
12575    snd_format_neq(res[0], req1, "poly_div 12a")
12576    snd_format_neq(res[1], req2, "poly_div 12b")
12577  end
12578  #
12579  ind = open_sound("1a.snd")
12580  v1 = channel2vct(0, 100, ind, 0)
12581  v2 = channel2vct(0, 100, ind, 0)
12582  res = poly_div(v1, v2)[0]
12583  req = make_vct(100)
12584  req[0] = 1.0
12585  snd_test_neq(res, req, "poly1 1a")
12586  close_sound(ind)
12587  #
12588  res = poly(0.5, 1, 2, 4).derivative
12589  req = vct(1, 4, 12)
12590  snd_test_neq(res, req, "poly_derivative")
12591  #
12592  res = poly(1, 2, 3).reduce
12593  req = vct(1, 2, 3)
12594  snd_test_neq(res, req, "reduce 1")
12595  res = poly(1, 2, 3, 0, 0, 0).reduce
12596  req = vct(1, 2, 3)
12597  snd_test_neq(res, req, "reduce 2")
12598  res = poly(0, 0, 0, 0, 1, 0).reduce
12599  req = vct(0, 0, 0, 0, 1)
12600  snd_test_neq(res, req, "reduce 3")
12601  #
12602  res = (poly(2, 1) * vct(-3, 1)).reduce.gcd(vct(2, 1))
12603  req = vct(2, 1)
12604  snd_test_neq(res, req, "poly_gcd 1")
12605  res = (poly(2, 1) * vct(-3, 1)).reduce.gcd(vct(3, 1))
12606  req = vct(0)
12607  snd_test_neq(res, req, "poly_gcd 2")
12608  res = (poly(2, 1) * vct(-3, 1)).reduce.gcd(vct(-3, 1))
12609  req = vct(-3, 1)
12610  snd_test_neq(res, req, "poly_gcd 3")
12611  res = (poly(8, 1) * poly(2, 1) * poly(-3, 1)).reduce.gcd(vct(-3, 1))
12612  req = vct(-3, 1)
12613  snd_test_neq(res, req, "poly_gcd 4")
12614  res = poly(8, 1) * poly(2, 1) * [-3, 1]
12615  res = res.reduce.gcd((poly(8, 1) * [-3, 1]).reduce)
12616  req = vct(-24, 5, 1)
12617  snd_test_neq(res, req, "poly_gcd 5")
12618  res = poly(-1, 0, 1).gcd([2, -2, -1, 1])
12619  req = [0]
12620  snd_test_neq(res, req, "poly_gcd 6")
12621  res = poly(2, -2, -1, 1).gcd([-1, 0, 1])
12622  req = [1, -1]
12623  snd_test_neq(res, req, "poly_gcd 7")
12624  res = poly(2, -2, -1, 1).gcd([-2.5, 1])
12625  req = [0]
12626  snd_test_neq(res, req, "poly_gcd 8")
12627  #
12628  poly_roots_tests()
12629  #
12630  res = poly(-1, 0, 1).resultant([1, -2, 1])
12631  req = 0.0
12632  snd_test_neq(res, req, "poly_resultant 0")
12633  res = poly(-1, 0, 2).resultant([1, -2, 1])
12634  req = 1.0
12635  snd_test_neq(res, req, "poly_resultant 1")
12636  res = poly(-1, 0, 1).resultant([1, 1])
12637  req = 0.0
12638  snd_test_neq(res, req, "poly_resultant 2")
12639  res = poly(-1, 0, 1).resultant([2, 1])
12640  req = 3.0
12641  snd_test_neq(res, req, "poly_resultant 3")
12642  #
12643  res = poly(-1, 0, 1).discriminant
12644  req = -4.0
12645  snd_test_neq(res, req, "poly_discriminant 0")
12646  res = poly(1, -2, 1).discriminant
12647  req = 0.0
12648  snd_test_neq(res, req, "poly_discriminant 1")
12649  res = (poly(-1, 1) * poly(-1, 1) * poly(3, 1)).reduce.discriminant
12650  req = 0.0
12651  snd_test_neq(res, req, "poly_discriminant 2")
12652  res = (poly(-1, 1) * poly(-1, 1) *
12653         poly(3, 1) * poly(2, 1)).reduce.discriminant
12654  req = 0.0
12655  snd_test_neq(res, req, "poly_discriminant 3")
12656  res = (poly(1, 1) * poly(-1, 1) * poly(3, 1) * poly(2, 1)).reduce.discriminant
12657  req = 2304.0
12658  snd_test_neq(res, req, "poly_discriminant 4")
12659  res = (poly(1, 1) * poly(-1, 1) * poly(3, 1) * poly(3, 1)).reduce.discriminant
12660  req = 0.0
12661  snd_test_neq(res, req, "poly_discriminant 5")
12662  #
12663  v0 = make_vct!(10) do |i| i end
12664  if fneq(res = array_interp(v0, 3.5), 3.5)
12665    snd_display("array_interp: %s?", res)
12666  end
12667  if fneq(res = array_interp(v0, 13.5), 3.5)
12668    snd_display("array_interp (13.5): %s?", res)
12669  end
12670  if fneq(res = array_interp(v0, -6.5), 3.5)
12671    snd_display("array_interp (-6.5): %s?", res)
12672  end
12673  if fneq(res = array_interp(v0, 103.6), 3.6)
12674    snd_display("array_interp (103.6): %s?", res)
12675  end
12676  if fneq(res = array_interp(v0, -106.6), 3.4)
12677    snd_display("array_interp (-106.6): %s?", res)
12678  end
12679  if fneq(res = array_interp(v0, -0.5), 4.5)
12680    snd_display("array_interp (-0.5): %s?", res)
12681  end
12682  if fneq(res = array_interp(v0, -0.9), 8.1)
12683    snd_display("array_interp (-0.9): %s?", res)
12684  end
12685  if fneq(res = array_interp(v0, -0.1), 0.9)
12686    snd_display("array_interp (-0.1): %s?", res)
12687  end
12688  if fneq(res = array_interp(v0, 9.1), 8.1)
12689    snd_display("array_interp (9.1): %s?", res)
12690  end
12691  if fneq(res = array_interp(v0, 9.9), 0.9)
12692    snd_display("array_interp (9.9): %s?", res)
12693  end
12694  if fneq(res = array_interp(v0, 10.1), 0.1)
12695    snd_display("array_interp (10.1): %s?", res)
12696  end
12697  if (res = Snd.catch do array_interp(v0, 1, -10) end).first != :out_of_range
12698    snd_display("array_interp bad index: %s", res.inspect)
12699  end
12700  #
12701  v0 = make_vct!(10) do |i| i end
12702  if fneq(res = mus_interpolate(Mus_interp_linear, 1.5, v0), 1.5)
12703    snd_display("mus_interpolate linear: %s?", res)
12704  end
12705  if fneq(res = mus_interpolate(Mus_interp_all_pass, 1.5, v0), 1.5)
12706    snd_display("mus_interpolate all-pass: %s?", res)
12707  end
12708  if fneq(res = mus_interpolate(Mus_interp_none, 1.5, v0), 1.0)
12709    snd_display("mus_interpolate none: %s?", res)
12710  end
12711  if fneq(res = mus_interpolate(Mus_interp_hermite, 1.5, v0), 1.5)
12712    snd_display("mus_interpolate hermite: %s?", res)
12713  end
12714  if fneq(res = mus_interpolate(Mus_interp_bezier, 1.5, v0), 1.5)
12715    snd_display("mus_interpolate bezier: %s?", res)
12716  end
12717  if fneq(res = mus_interpolate(Mus_interp_lagrange, 1.5, v0), 1.5)
12718    snd_display("mus_interpolate lagrange: %s?", res)
12719  end
12720  v0.map_with_index! do |val, i| sin(PI * (i / 5.0)) end
12721  if fneq(res = mus_interpolate(Mus_interp_linear, 1.5, v0), 0.7694)
12722    snd_display("mus_interpolate linear sin: %s?", res)
12723  end
12724  if fneq(res = mus_interpolate(Mus_interp_all_pass, 1.5, v0), 0.7694)
12725    snd_display("mus_interpolate all-pass sin: %s?", res)
12726  end
12727  if fneq(res = mus_interpolate(Mus_interp_none, 1.5, v0), 0.5877)
12728    snd_display("mus_interpolate none sin: %s?", res)
12729  end
12730  if fneq(res = mus_interpolate(Mus_interp_hermite, 1.5, v0), 0.8061)
12731    snd_display("mus_interpolate hermite sin: %s?", res)
12732  end
12733  if fneq(res = mus_interpolate(Mus_interp_bezier, 1.5, v0), 0.6959)
12734    snd_display("mus_interpolate bezier sin: %s?", res)
12735  end
12736  if fneq(res = mus_interpolate(Mus_interp_lagrange, 1.5, v0), 0.7975)
12737    snd_display("mus_interpolate lagrange sin: %s?", res)
12738  end
12739  if (res = Snd.catch do mus_interpolate(1234, 1.0, make_vct(3)) end).first != :out_of_range
12740    snd_display("mus_interpolate 1234: %s", res.inspect)
12741  end
12742  if (res = Snd.catch do
12743        mus_interpolate(Mus_interp_linear, 1.0, make_vct(3), -1)
12744      end).first != :out_of_range
12745    snd_display("mus_interpolate size -1: %s", res.inspect)
12746  end
12747end
12748
12749def test_08_01
12750  gen = make_delay(3)
12751  gen2 = make_delay(3)
12752  gen1 = make_delay(4, :initial_contents, [1.0, 0.5, 0.25, 0.0])
12753  gen3 = make_delay(4, :initial_contents, vct(1.0, 0.5, 0.25, 0.0))
12754  print_and_check(gen, "delay", "delay line[3, step]: [0 0 0]")
12755  v0 = make_vct!(10) do |i| delay(gen, i) end
12756  v1 = make_vct!(10) do |i| delay?(gen2) ? delay(gen2, i) : -1.0 end
12757  unless vequal(v1, v0)
12758    snd_display("map delay: %s %s?", v0, v1)
12759  end
12760  unless delay?(gen)
12761    snd_display("%s not a delay?", gen)
12762  end
12763  if gen.length != 3
12764    snd_display("delay length: %s?", gen.length)
12765  end
12766  if fneq(v0[1], 0.0) or fneq(v0[4], 1.0) or fneq(v0[8], 5.0)
12767    snd_display("delay output: %s?", v0)
12768  end
12769  if fneq(delay(gen1), 1.0) or fneq(delay(gen1), 0.5) or
12770      fneq(delay(gen1), 0.25) or fneq(delay(gen1), 0.0) or fneq(delay(gen1), 0.0)
12771    snd_display("delay with list initial-contents confused")
12772  end
12773  if fneq(delay(gen3), 1.0) or fneq(delay(gen3), 0.5) or
12774      fneq(delay(gen3), 0.25) or fneq(delay(gen3), 0.0) or fneq(delay(gen3), 0.0)
12775    snd_display("delay with vct initial-contents confused")
12776  end
12777  if (res = Snd.catch do make_delay(:size, false) end).first != :wrong_type_arg
12778    snd_display("make_delay bad size false: %s", res.inspect)
12779  end
12780  if (res = Snd.catch do
12781        make_delay(3, :initial_element, make_oscil)
12782      end).first != :wrong_type_arg
12783    snd_display("make_delay bad initial element: %s", res.inspect)
12784  end
12785  if (res = Snd.catch do make_delay(-3) end).first != :out_of_range
12786    snd_display("make_delay bad size: %s", res.inspect)
12787  end
12788  d1 = make_delay(3)
12789  d2 = make_delay(3)
12790  d3 = make_delay(4)
12791  delay(d1, 1.0)
12792  delay(d2, 1.0)
12793  delay(d3, 1.0)
12794  test_gen_equal(d1, d2, d3)
12795  test_gen_equal(make_delay(3, :initial_element, 1.0),
12796                 make_delay(3, :initial_element, 1.0),
12797                 make_delay(3, :initial_element, 0.5))
12798  test_gen_equal(make_delay(3, :initial_contents, [1.0, 0.0, 0.0]),
12799                 make_delay(3, :initial_contents, [1.0, 0.0, 0.0]),
12800                 make_delay(3, :initial_contents, [1.0, 1.0, 1.0]))
12801  gen = make_delay(5)
12802  delay(gen, 1.0)
12803  delay(gen, 0.0)
12804  delay(gen, 0.5)
12805  data = vct_copy(gen.data)
12806  gen.data[0] = 0.3
12807  if fneq(gen.data[0], 0.3)
12808    snd_display("delay data 0: %s?", gen.data[0])
12809  end
12810  data[0] = 0.75
12811  gen.data = data
12812  if fneq(gen.data[0], 0.75)
12813    snd_display("delay set data 0: %s?", gen.data[0])
12814  end
12815  delay(gen, 0.0)
12816  delay(gen, 0.0)
12817  if fneq(res = delay(gen, 0.0), 0.75)
12818    snd_display("set delay data: %s %s?", res, gen.data)
12819  end
12820  if res = make_oscil.data
12821    snd_display("mus_data osc: %s?", res)
12822  end
12823  #
12824  del = make_delay(5, :max_size, 8)
12825  delay(del, 1.0)
12826  4.times do delay(del, 0.0) end
12827  v0 = make_vct!(5) do delay(del, 0.0, 0.4) end
12828  unless vequal(v0, vct(0.6, 0.4, 0.0, 0.0, 0.0))
12829    snd_display("zdelay: %s?", v0)
12830  end
12831  delay(del, 1.0)
12832  delay(del, 0.0, 0.4)
12833  if (res = del.to_s) != "delay line[5,8, linear]: [0 0 1 0 0]"
12834    snd_display("describe zdelay: %s", res)
12835  end
12836  if (res = Snd.catch do tap(make_oscil) end).first != :wrong_type_arg
12837    snd_display("tap of oscil: %s?", res.inspect)
12838  end
12839  #
12840  dly = make_delay(3)
12841  flt = make_one_zero(0.5, 0.4)
12842  v = make_vct(20)
12843  inval = 1.0
12844  v.map! do |x|
12845    res = delay(dly, inval + one_zero(flt, tap(dly)) * 0.6)
12846    inval = 0.0
12847    res
12848  end
12849  unless vequal(v, vct(0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.3, 0.24, 0.0, 0.09,
12850         0.144, 0.058, 0.027, 0.065, 0.052, 0.022, 0.026, 0.031, 0.019, 0.013))
12851    snd_display("tap with low pass: %s?", v)
12852  end
12853  #
12854  dly = make_delay(3)
12855  v = make_vct(20)
12856  inval = 1.0
12857  v.map! do |x|
12858    res = delay(dly, inval + tap(dly))
12859    inval = 0.0
12860    res
12861  end
12862  unless vequal(v, vct(0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,
12863                       0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0))
12864    snd_display("simple tap: %s?", v)
12865  end
12866  dly = make_delay(6)
12867  v = make_vct(20)
12868  inval = 1.0
12869  snd_test_neq(tap?(dly), true, "tap?")
12870  v.map! do |x|
12871    res = delay(dly, inval + tap(dly, -2.0))
12872    inval = 0.0
12873    res
12874  end
12875  unless vequal(v, vct(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0,
12876                       1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0))
12877    snd_display("tap back 2: %s?", v)
12878  end
12879  #
12880  dly = make_delay(3, :initial_element, 32.0)
12881  unless vct?(dly.data)
12882    snd_display("delay data not vct?")
12883  else
12884    if dly.data.length != 3
12885      snd_display("delay data len not 3: %s (%s)?", dly.data.length, dly.data)
12886    else
12887      if fneq(res = dly.data[1], 32.0)
12888        snd_display("delay [1] 32: %s?", res)
12889      end
12890    end
12891  end
12892  if (res = Snd.catch do dly.length = -1 end).first != :out_of_range
12893    snd_display("len to -1 -> %s?", res.inspect)
12894  end
12895  if (res = Snd.catch do dly.length = 0 end).first != :out_of_range
12896    snd_display("len to 0 -> %s?", res.inspect)
12897  end
12898  if (res = Snd.catch do dly.length = 100 end).first != :out_of_range
12899    snd_display("len to 100 -> %s?", res.inspect)
12900  end
12901  if (res = Snd.catch do dly.data[100] = 0.1 end).first != :out_of_range
12902    snd_display("data 100 to 0.1 -> %s?", res.inspect)
12903  end
12904  data = make_vct(32, 1.0)
12905  dly.data = data
12906  unless vct?(dly.data)
12907    snd_display("set delay data not vct?")
12908  end
12909  if fneq(dly.data[1], 1.0)
12910    snd_display("set delay [1] 1: %s?", dly.data[1])
12911  end
12912  if dly.data.length != 32
12913    snd_display("set delay data len(32): %s?", dly.data.length)
12914  end
12915  if (res = Snd.catch do dly.length = 100 end).first != :out_of_range
12916    snd_display("set len to 100 -> %s", res.inspect)
12917  end
12918  if (res = Snd.catch do dly.data[100] = 0.1 end).first != :out_of_range
12919    snd_display("set data 100 to 0.1 -> %s", res.inspect)
12920  end
12921  #
12922  d1 = make_delay(4)
12923  d2 = make_delay(4, :max_size, 5, :type, Mus_interp_linear)
12924  d3 = make_delay(4, :max_size, 5, :type, Mus_interp_all_pass)
12925  d4 = make_delay(4, :max_size, 5, :type, Mus_interp_none)
12926  d5 = make_delay(4, :max_size, 4, :type, Mus_interp_lagrange)
12927  d6 = make_delay(4, :max_size, 4, :type, Mus_interp_hermite)
12928  d7 = make_delay(4, :max_size, 4, :type, Mus_interp_linear)
12929  v1 = make_vct(20)
12930  v2 = make_vct(20)
12931  v3 = make_vct(20)
12932  v4 = make_vct(20)
12933  v5 = make_vct(20)
12934  v6 = make_vct(20)
12935  v7 = make_vct(20)
12936  [[d1, Mus_interp_none],
12937   [d2, Mus_interp_linear],
12938   [d3, Mus_interp_all_pass],
12939   [d4, Mus_interp_none],
12940   [d5, Mus_interp_lagrange],
12941   [d6, Mus_interp_hermite],
12942   [d7, Mus_interp_linear]].each_with_index do |args, i|
12943    dly, type = args
12944    if dly.interp_type != type
12945      snd_display("d%s interp type: %s?", i + 1, dly.interp_type)
12946    end
12947  end
12948  [[v1, d1], [v2, d2], [v3, d3], [v4, d4], [v5, d5], [v6, d6], [v7, d7]].each do |v, d|
12949    v[0] = delay(d, 1.0)
12950    delay_tick(d, 0.0)
12951  end
12952  j = -0.2
12953  (1...20).each do |i|
12954    [[v1, d1], [v2, d2], [v3, d3], [v4, d4], [v5, d5], [v6, d6], [v7, d7]].each do |v, d|
12955      v[i] = tap(d, j)
12956    end
12957    j -= 0.2
12958  end
12959  if (not vequal(v1, vct(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
12960                         1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0))) and
12961      (not vequal(v1, vct(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
12962                          0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0)))
12963    snd_display("delay interp none (1): %s?", v1)
12964  end
12965  unless vequal(v2, vct(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.2, 0.4, 0.6, 0.8,
12966                        1.0, 0.8, 0.6, 0.4, 0.2, 0.0, 0.0, 0.0, 0.0, 0.0))
12967    snd_display("delay interp linear (2): %s?", v2)
12968  end
12969  unless vequal(v3, vct(0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.6, 0.16, 0.168, -0.168,
12970                        0.334, 0.199, 0.52, 0.696, -0.696, 0.557, -0.334, 0.134, -0.027))
12971    snd_display("delay interp all-pass (3): %s?", v3)
12972  end
12973  if (not vequal(v4, vct(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
12974                         1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0))) and
12975      (not vequal(v4, vct(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
12976                          0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0)))
12977    snd_display("delay interp none (4): %s?", v4)
12978  end
12979  unless vequal(v5, vct(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.12, 0.28, 0.48, 0.72,
12980                        1.0, 0.96, 0.84, 0.64, 0.36, 0.0, -0.08, -0.12, -0.12, -0.08))
12981    snd_display("delay interp lagrange (5): %s?", v5)
12982  end
12983  unless vequal(v6, vct(0.0, -0.016, -0.048, -0.072, -0.064, 0.0, 0.168, 0.424, 0.696, 0.912,
12984                        1.0, 0.912, 0.696, 0.424, 0.168, 0.0, -0.064, -0.072, -0.048, -0.016))
12985    snd_display("delay interp hermite (6): %s?", v6)
12986  end
12987  unless vequal(v7, vct(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.2, 0.4, 0.6, 0.8,
12988                        1.0, 0.8, 0.6, 0.4, 0.2, 0.0, 0.0, 0.0, 0.0, 0.0))
12989    snd_display("delay interp linear (7): %s?", v7)
12990  end
12991  #
12992  dly = make_delay(:size, 2, :max_size, 3)
12993  impulse = 1.0
12994  data = make_vct!(5) do
12995    val = delay(dly, impulse, 0.4)
12996    impulse = 0.0
12997    val
12998  end
12999  unless vequal(data, vct(0.0, 0.0, 0.6, 0.4, 0.0))
13000    snd_display("delay size 2, max 3, off 0.4: %s", data)
13001  end
13002  dly = make_delay(:size, 2, :max_size, 3)
13003  impulse = 1.0
13004  data = make_vct!(5) do
13005    val = delay(dly, impulse, -0.4)
13006    impulse = 0.0
13007    val
13008  end
13009  unless vequal(data, vct(0.0, 0.4, 0.6, 0.0, 0.0))
13010    snd_display("delay size 2, max 3, off -0.4: %s", data)
13011  end
13012  #
13013  dly = make_delay(:size, 1, :max_size, 2)
13014  impulse = 1.0
13015  data = make_vct!(5) do
13016    val = delay(dly, impulse, 0.4)
13017    impulse = 0.0
13018    val
13019  end
13020  unless vequal(data, vct(0.0, 0.6, 0.4, 0.0, 0.0))
13021    snd_display("delay size 1, max 2, off 0.4: %s", data)
13022  end
13023  #
13024  dly = make_delay(:size, 0, :max_size, 1)
13025  impulse = 1.0
13026  data = make_vct!(5) do
13027    val = delay(dly, impulse, 0.4)
13028    impulse = 0.0
13029    val
13030  end
13031  unless vequal(data, vct(0.6, 0.4, 0.0, 0.0, 0.0))
13032    snd_display("delay size 0, max 1, off 0.4: %s", data)
13033  end
13034  dly = make_delay(:size, 0, :max_size, 1)
13035  if fneq(res = delay(dly, 0.0), 0.0)
13036    snd_display("initial delay 0 size val: %s?", res)
13037  end
13038  dly = make_delay(:size, 0, :max_size, 1)
13039  impulse = 1.0
13040  data = make_vct!(5) do
13041    val = delay(dly, impulse, -0.4)
13042    impulse = 0.0
13043    val
13044  end
13045  unless vequal(data, vct(1.4, -0.4, 0.0, 0.0, 0.0))
13046    snd_display("delay size 0, max 1, off -0.4: %s", data)
13047  end
13048  dly = make_delay(:size, 0, :max_size, 100)
13049  v = make_vct!(10) do |i| delay(dly, 0.5, i) end
13050  unless vequal(v, vct(0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0))
13051    snd_display("delay 0 -> 100: %s", v)
13052  end
13053  9.downto(0) do |i| v[i] = delay(dly, 0.5, i) end
13054  unless vequal(v, vct(0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5))
13055    snd_display("delay 100 -> 0: %s", v)
13056  end
13057  dly.reset
13058  unless vequal(dly.data, Vct.new(100, 0.0))
13059    snd_display("after reset mus-data delay peak: %s?", dly.data.peak)
13060  end
13061  10.times do |i| v[i] = delay(dly, (i.odd? ? 1.0 : 0.0), i * 0.1) end
13062  unless vequal(v, vct(0.0, 0.9, 0.0, 0.7, 0.0, 0.5, 0.0, 0.3, 0.0, 0.1))
13063    snd_display("delay 0 -> 100 0.1: %s", v)
13064  end
13065  dly.reset
13066  10.times do |i| v[i] = delay(dly, (i.odd? ? 1.0 : 0.0), 1.0 + i * 0.1) end
13067  unless vequal(v, vct(0.0, 0.0, 0.8, 0.3, 0.6, 0.5, 0.4, 0.7, 0.2, 0.9))
13068    snd_display("delay 0 -> 100 1.1: %s", v)
13069  end
13070end
13071
13072def test_08_02
13073  gen = make_all_pass(0.4, 0.6, 3)
13074  gen1 = make_all_pass(0.4, 0.6, 3)
13075  print_and_check(gen,
13076                  "all-pass",
13077                  "all-pass feedback: 0.400, feedforward: 0.600, line[3, step]:[0 0 0]")
13078  v0 = make_vct!(10) do all_pass(gen, 1.0) end
13079  v1 = make_vct(10)
13080  v1.map! do |x| all_pass?(gen1) ? all_pass(gen1, 1.0) : -1.0 end
13081  unless vequal(v0, v1)
13082    snd_display("map all-pass: %s %s?", v0, v1)
13083  end
13084  unless all_pass?(gen)
13085    snd_display("%s not all-pass?", gen)
13086  end
13087  if gen.length != 3
13088    snd_display("all-pass length: %s?", gen.length)
13089  end
13090  if gen.order != 3
13091    snd_display("all-pass order: %s?", gen.order)
13092  end
13093  if fneq(gen.feedback, 0.4)
13094    snd_display("all-pass feedback: %s?", gen.feedback)
13095  end
13096  if fneq(gen.feedforward, 0.6)
13097    snd_display("all-pass feedforward: %s?", gen.feedforward)
13098  end
13099  if fneq(v0[1], 0.6) or fneq(v0[4], 1.84) or fneq(v0[8], 2.336)
13100    snd_display("all-pass output: %s?", v0)
13101  end
13102  gen.feedback = 0.5
13103  if fneq(gen.feedback, 0.5)
13104    snd_display("all-pass set_feedback: %s?", gen.feedback)
13105  end
13106  gen.feedforward = 0.5
13107  if fneq(gen.feedforward, 0.5)
13108    snd_display("all-pass set_feedforward: %s?", gen.feedforward)
13109  end
13110  d1 = make_all_pass(0.7, 0.5, 3)
13111  d2 = make_all_pass(0.7, 0.5, 3)
13112  d3 = make_all_pass(0.7, 0.5, 4)
13113  all_pass(d1, 1.0)
13114  all_pass(d2, 1.0)
13115  all_pass(d3, 1.0)
13116  test_gen_equal(d1, d2, d3)
13117  test_gen_equal(make_all_pass(0.7, 0.5, 3, :initial_element, 1.0),
13118                 make_all_pass(0.7, 0.5, 3, :initial_element, 1.0),
13119                 make_all_pass(0.7, 0.5, 3, :initial_element, 0.5))
13120  test_gen_equal(make_all_pass(0.7, 0.5, 3, :initial_element, 1.0),
13121                 make_all_pass(0.7, 0.5, 3, :initial_element, 1.0),
13122                 make_all_pass(0.5, 0.5, 3, :initial_element, 1.0))
13123  test_gen_equal(make_all_pass(0.7, 0.5, 3, :initial_contents, [1.0, 0.0, 0.0]),
13124                 make_all_pass(0.7, 0.5, 3, :initial_contents, [1.0, 0.0, 0.0]),
13125                 make_all_pass(0.7, 0.5, 3, :initial_contents, [1.0, 1.0, 1.0]))
13126  err = Snd.catch do
13127    make_all_pass(:feedback, 0.2, :feedforward, 0.1, :size, -1)
13128  end
13129  if err.first != :out_of_range or
13130      err[1] != "make_all_pass" or
13131      err[2] != "size _1 < 0?" or
13132    snd_display("make_all_pass bad size error message: %s", err.inspect)
13133  end
13134  #
13135  gen = make_moving_average(4)
13136  gen1 = make_moving_average(4)
13137  print_and_check(gen, "moving-average",
13138                  "moving-average 0.000, line[4]:[0 0 0 0]")
13139  v0 = make_vct!(10) do moving_average(gen, 1.0) end
13140  v1 = make_vct(10)
13141  v1.map! do |x| moving_average?(gen1) ? moving_average(gen1, 1.0) : -1.0 end
13142  unless vequal(v0, v1)
13143    snd_display("map moving_average: %s %s?", v0, v1)
13144  end
13145  unless moving_average?(gen)
13146    snd_display("%s not moving_average?", gen)
13147  end
13148  if gen.length != 4
13149    snd_display("moving-average length: %s?", gen.length)
13150  end
13151  if gen.order != 4
13152    snd_display("moving-average order: %s?", gen.order)
13153  end
13154  if fneq(v0[1], 0.5) or fneq(v0[4], 1.0) or fneq(v0[8], 1.0)
13155    snd_display("moving-average output: %s?", v0)
13156  end
13157  gen = make_moving_average(8)
13158  if fneq(val = moving_average(gen), 0.0)
13159    snd_display("empty moving_average: %s?", val)
13160  end
13161  if fneq(val = moving_average(gen, 1.0), 0.125)
13162    snd_display("moving-average 1: %s?", val)
13163  end
13164  if fneq(val = moving_average(gen, 1.0), 0.25)
13165    snd_display("moving-average 2: %s?", val)
13166  end
13167  if fneq(val = moving_average(gen, 0.5), 0.3125)
13168    snd_display("moving-average 2: %s?", val)
13169  end
13170  4.times do moving_average(gen, 0.0) end
13171  if fneq(val = moving_average(gen, 0.0), 0.3125)
13172    snd_display("moving-average 6: %s?", val)
13173  end
13174  if fneq(val = moving_average(gen, 0.0), 0.1875)
13175    snd_display("moving-average 7: %s?", val)
13176  end
13177  if fneq(val = moving_average(gen, 0.0), 0.0625)
13178    snd_display("moving-average 8: %s?", val)
13179  end
13180  if fneq(val = moving_average(gen, 0.0), 0.0)
13181    snd_display("moving-average 9: %s?", val)
13182  end
13183  gen = make_moving_average(10, :initial_element, 0.5)
13184  if fneq(val = moving_average(gen, 0.5), 0.5)
13185    snd_display("moving-average initial_element: %s?", val)
13186  end
13187  gen = make_moving_average(3, :initial_contents, [1.0, 1.0, 1.0])
13188  if fneq(val = moving_average(gen, 1.0), 1.0)
13189    snd_display("moving-average initial_contents: %s?", val)
13190  end
13191  d1 = make_moving_average(3, :initial_contents, [0.7, 0.5, 3])
13192  d2 = make_moving_average(3, :initial_contents, vct(0.7, 0.5, 3))
13193  d3 = make_moving_average(4, :initial_contents, [0.7, 0.5, 0.1, 4])
13194  moving_average(d1, 1.0)
13195  moving_average(d2, 1.0)
13196  moving_average(d3, 1.0)
13197  test_gen_equal(d1, d2, d3)
13198  test_gen_equal(make_moving_average(3, :initial_element, 1.0),
13199                 make_moving_average(3, :initial_element, 1.0),
13200                 make_moving_average(3, :initial_element, 0.5))
13201  test_gen_equal(make_moving_average(3, :initial_element, 1.0),
13202                 make_moving_average(3, :initial_element, 1.0),
13203                 make_moving_average(4, :initial_element, 1.0))
13204  test_gen_equal(make_moving_average(3, :initial_contents, [1.0, 0.0, 0.0]),
13205                 make_moving_average(3, :initial_contents, [1.0, 0.0, 0.0]),
13206                 make_moving_average(3, :initial_contents, [1.0, 1.0, 1.0]))
13207  err = Snd.catch do make_moving_average(:size, -1) end
13208  if err.first != :out_of_range or
13209      err[1] != "make_moving_average" or
13210      err[2] != "size -1 < 0?" or
13211    snd_display("make_moving_average bad size error message: %s", err.inspect)
13212  end
13213  #
13214  gen = make_comb(0.4, 3)
13215  gen1 = make_comb(0.4, 3)
13216  print_and_check(gen, "comb", "comb scaler: 0.400, line[3, step]: [0 0 0]")
13217  v0 = make_vct!(10) do comb(gen, 1.0) end
13218  v1 = make_vct(10)
13219  v1.map! do |x| comb?(gen1) ? comb(gen1, 1.0) : -1.0 end
13220  unless vequal(v0, v1)
13221    snd_display("map comb: %s %s?", v0, v1)
13222  end
13223  unless comb?(gen)
13224    snd_display("%s not comb?", gen)
13225  end
13226  if gen.length != 3
13227    snd_display("comb length: %s?", gen.length)
13228  end
13229  if gen.order != 3
13230    snd_display("comb order: %s?", gen.order)
13231  end
13232  if fneq(gen.feedback, 0.4)
13233    snd_display("comb feedback: %s?", gen.feedback)
13234  end
13235  if fneq(v0[1], 0.0) or fneq(v0[4], 1.0) or fneq(v0[8], 1.4)
13236    snd_display("comb output: %s?", v0)
13237  end
13238  d1 = make_comb(0.7, 3)
13239  d2 = make_comb(0.7, 3)
13240  d3 = make_comb(0.7, 4)
13241  comb(d1, 1.0)
13242  comb(d2, 1.0)
13243  comb(d3, 1.0)
13244  test_gen_equal(d1, d2, d3)
13245  test_gen_equal(make_comb(0.7, 3, :initial_element, 1.0),
13246                 make_comb(0.7, 3, :initial_element, 1.0),
13247                 make_comb(0.7, 3, :initial_element, 0.5))
13248  test_gen_equal(make_comb(0.7, 3, :initial_element, 1.0),
13249                 make_comb(0.7, 3, :initial_element, 1.0),
13250                 make_comb(0.5, 3, :initial_element, 1.0))
13251  test_gen_equal(make_comb(0.7, 3, :initial_contents, [1.0, 0.0, 0.0]),
13252                 make_comb(0.7, 3, :initial_contents, [1.0, 0.0, 0.0]),
13253                 make_comb(0.7, 3, :initial_contents, [1.0, 1.0, 1.0]))
13254  del = make_comb(0.0, 5, :max_size, 8)
13255  comb(del, 1.0)
13256  4.times do comb(del, 0.0) end
13257  v0 = make_vct!(5) do comb(del, 0.0, 0.4) end
13258  unless vequal(v0, vct(0.600, 0.400, 0.000, 0.000, 0.000))
13259    snd_display("zcomb: %s", v0)
13260  end
13261  comb(del, 1.0)
13262  comb(del, 0.0, 0.4)
13263  if (res = del.to_s) != "comb scaler: 0.000, line[5,8, linear]: [0 0 1 0 0]"
13264    snd_display("describe zcomb: %s", res)
13265  end
13266  del.feedback = 1.0
13267  if fneq(del.feedback, 1.0)
13268    snd_display("comb feedback set: %s?", del.feedback)
13269  end
13270  #
13271  gen = make_filtered_comb(0.4, 5, :filter, make_one_zero(0.3, 0.7))
13272  print_and_check(gen,
13273                  "filtered-comb",
13274                  "filtered-comb scaler: 0.400, line[5, step]: [0 0 0 0 0], filter: [one-zero a0: 0.300, a1: 0.700, x1: 0.000]")
13275  v0 = make_vct!(20) do |i| filtered_comb(gen, (i.zero? ? 1.0 : 0.0)) end
13276  v1 = vct(0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0.12, 0.28,
13277           0, 0, 0, 0.014, 0.067, 0.078, 0, 0)
13278  snd_test_neq(v0, v1, "filtered_comb")
13279  unless filtered_comb?(gen)
13280    snd_display("%s not filtered_comb?", gen)
13281  end
13282  if gen.length != 5
13283    snd_display("filtered_comb length: %s?", gen.length)
13284  end
13285  if gen.order != 5
13286    snd_display("filtered_comb order: %s?", gen.order)
13287  end
13288  if fneq(gen.feedback, 0.4)
13289    snd_display("filtered_comb feedback: %s?", gen.feedback)
13290  end
13291  gen = make_filtered_comb(0.9, 5, :filter, make_one_zero(0.5, 0.5))
13292  print_and_check(gen,
13293                  "filtered-comb",
13294                  "filtered-comb scaler: 0.900, line[5, step]: [0 0 0 0 0], filter: [one-zero a0: 0.500, a1: 0.500, x1: 0.000]")
13295  v0 = make_vct!(20) do |i| filtered_comb(gen, (i.zero? ? 1.0 : 0.0)) end
13296  v1 = vct(0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0.45, 0.45,
13297           0, 0, 0, 0.202, 0.405, 0.202, 0, 0)
13298  snd_test_neq(v0, v1, "filtered_comb: 0.5 0.5")
13299  gen = make_filtered_comb(0.9, 5,
13300                           :filter,
13301                           make_fir_filter(5, vct(0.1, 0.2, 0.3, 0.2, 0.1)))
13302  print_and_check(gen,
13303                  "filtered-comb",
13304                  "filtered-comb scaler: 0.900, line[5, step]: [0 0 0 0 0], filter: [fir-filter order: 5, xs: [0.1 0.2 0.3 0.2 0.1]]")
13305  v0 = make_vct!(20) do |i| filtered_comb(gen, (i.zero? ? 1.0 : 0.0)) end
13306  v1 = vct(0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
13307           0.09, 0.18, 0.27, 0.18, 0.09, 0.008, 0.032, 0.081, 0.13, 0.154)
13308  snd_test_neq(v0, v1, "filtered_comb (fir)")
13309  d1 = make_filtered_comb(0.7, 3, :filter, make_one_pole(0.3, 0.7))
13310  d2 = make_filtered_comb(0.7, 3, :filter, make_one_pole(0.3, 0.7))
13311  d3 = make_filtered_comb(0.7, 4, :filter, make_one_pole(0.3, 0.7))
13312  filtered_comb(d1, 1.0)
13313  filtered_comb(d2, 1.0)
13314  filtered_comb(d3, 1.0)
13315  test_gen_equal(d1, d2, d3)
13316  test_gen_equal(make_filtered_comb(0.7, 3, :initial_element, 1.0,
13317                                    :filter, make_one_zero(0.5, 0.5)),
13318                 make_filtered_comb(0.7, 3, :initial_element, 1.0,
13319                                    :filter, make_one_zero(0.5, 0.5)),
13320                 make_filtered_comb(0.7, 3, :initial_element, 0.5,
13321                                    :filter, make_one_zero(0.5, 0.5)))
13322  test_gen_equal(make_filtered_comb(0.7, 3, :initial_element, 1.0,
13323                                    :filter, make_one_zero(0.5, 0.5)),
13324                 make_filtered_comb(0.7, 3, :initial_element, 1.0,
13325                                    :filter, make_one_zero(0.5, 0.5)),
13326                 make_filtered_comb(0.7, 3, :initial_element, 1.0,
13327                                    :filter, make_one_zero(0.25, 0.25)))
13328  test_gen_equal(make_filtered_comb(0.7, 3, :initial_contents, [1.0, 0.0, 0.0],
13329                                    :filter, make_one_zero(0.5, 0.5)),
13330                 make_filtered_comb(0.7, 3, :initial_contents, [1.0, 0.0, 0.0],
13331                                    :filter, make_one_zero(0.5, 0.5)),
13332                 make_filtered_comb(0.7, 3, :initial_contents, [1.0, 1.0, 1.0],
13333                                    :filter, make_one_zero(0.5, 0.5)))
13334  del = make_filtered_comb(0.0, 5, :max_size, 8,
13335                           :filter, make_one_zero(0.5, 0.5))
13336  filtered_comb(del, 1.0)
13337  4.times do filtered_comb(del, 0.0) end
13338  v0 = make_vct!(5) do filtered_comb(del, 0.0, 0.4) end
13339  snd_test_neq(v0, vct(0.6, 0.4, 0, 0, 0), "zfiltered_comb")
13340  filtered_comb(del, 1.0)
13341  filtered_comb(del, 0.0, 0.4)
13342  snd_test_neq(mus_describe(del), "filtered-comb scaler: 0.000, line[5,8, linear]: [0 0 1 0 0], filter: [one-zero a0: 0.500, a1: 0.500, x1: 0.000]",
13343               "describe zfiltered_comb")
13344  del.feedback = 1.0
13345  snd_test_neq(del.feedback, 1.0, "filtered_echo feedback set")
13346  #
13347  gen = make_notch(0.4, 3)
13348  gen1 = make_notch(0.4, 3)
13349  print_and_check(gen, "notch",
13350    "notch scaler: 0.400, line[3, step]: [0 0 0]")
13351  v0 = make_vct!(10) do notch(gen, 1.0) end
13352  v1 = Vct.new(10) do |x| notch?(gen1) ? notch(gen1, 1.0) : -1.0 end
13353  unless vequal(v0, v1)
13354    snd_display("map notch: %s %s?", v0, v1)
13355  end
13356  unless notch?(gen)
13357    snd_display("%s not notch?", gen)
13358  end
13359  if gen.length != 3
13360    snd_display("notch length: %s?", gen.length)
13361  end
13362  if gen.order != 3
13363    snd_display("notch order: %s?", gen.order)
13364  end
13365  if fneq(gen.feedforward, 0.4)
13366    snd_display("notch feedforward: %s?", gen.feedforward)
13367  end
13368  if fneq(v0[1], 0.4) or fneq(v0[4], 1.4) or fneq(v0[8], 1.4)
13369    snd_display("notch output: %s?", v0)
13370  end
13371  d1 = make_notch(0.7, 3)
13372  d2 = make_notch(0.7, 3)
13373  d3 = make_notch(0.7, 4)
13374  notch(d1, 1.0)
13375  notch(d2, 1.0)
13376  notch(d3, 1.0)
13377  test_gen_equal(d1, d2, d3)
13378  test_gen_equal(make_notch(0.7, 3, :initial_element, 1.0),
13379                 make_notch(0.7, 3, :initial_element, 1.0),
13380                 make_notch(0.7, 3, :initial_element, 0.5))
13381  test_gen_equal(make_notch(0.7, 3, :initial_element, 1.0),
13382                 make_notch(0.7, 3, :initial_element, 1.0),
13383                 make_notch(0.5, 3, :initial_element, 1.0))
13384  test_gen_equal(make_notch(0.7, 3, :initial_contents, [1.0, 0.0, 0.0]),
13385                 make_notch(0.7, 3, :initial_contents, [1.0, 0.0, 0.0]),
13386                 make_notch(0.7, 3, :initial_contents, [1.0, 1.0, 1.0]))
13387  # make sure all-pass is the same as comb/notch given the appropriate
13388  # feedback/forward settings
13389  [[make_comb(0.5, 5),
13390    vct(0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.5)],
13391   [make_all_pass(0.5, 0.0, 5),
13392    vct(0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.5)],
13393   [make_notch(0.5, 5),
13394    vct(0.5, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0)],
13395   [make_all_pass(0.0, 0.5, 5),
13396    vct(0.5, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0)]].each do |gen, v1|
13397    v0 = Vct.new(11) do |i|
13398      gen.run(i.zero? ? 1.0 : 0.0)
13399    end
13400    snd_test_neq(v0, v1, "0 %s (0.5, 0.0, 5)", gen.name)
13401  end
13402  # make sure all-pass is the same as zcomb/znotch given the
13403  # appropriate feedback/forward and "pm" settings
13404  [[make_comb(0.5, 5, :max_size, 20),
13405    vct(0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.5)],
13406   [make_all_pass(0.5, 0.0, 5, :max_size, 20),
13407    vct(0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.5)],
13408   [make_notch(0.5, 5, :max_size, 20),
13409    vct(0.5, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0)],
13410   [make_all_pass(0.0, 0.5, 5, :max_size, 20),
13411    vct(0.5, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0)]].each do |gen, v1|
13412    v0 = Vct.new(11) do |i|
13413      gen.run(i.zero? ? 1.0 : 0.0)
13414    end
13415    snd_test_neq(v0, v1, "1 %s (0.5, 0.0, 5)", gen.name)
13416  end
13417  # now actually use the size difference
13418  [[make_comb(0.5, 5, :max_size, 20),
13419    vct(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.8, 0.4, 0.0, 0.0,
13420        0.0, 0.0, 0.0, 0.16, 0.36, 0.2, 0.04, 0.0, 0.0, 0.0)],
13421   [make_all_pass(0.5, 0.0, 5, :max_size, 20),
13422    vct(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.8, 0.4, 0.0, 0.0,
13423        0.0, 0.0, 0.0, 0.16, 0.36, 0.2, 0.04, 0.0, 0.0, 0.0)],
13424   [make_notch(0.5, 5, :max_size, 20),
13425    vct(0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.8, 0.4, 0.0, 0.0, 0.0,
13426        0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)],
13427   [make_all_pass(0.0, 0.5, 5, :max_size, 20),
13428    vct(0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.8, 0.4, 0.0, 0.0, 0.0,
13429        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)]].each do |gen, v1|
13430    angle = -0.2
13431    v0 = Vct.new(20) do |i|
13432      gen.run((i.zero? ? 1.0 : 0.0), angle += 0.2)
13433    end
13434    snd_test_neq(v0, v1, "2 %s (0.5, 0.0, 5)", gen.name)
13435  end
13436  [[make_comb(0.5, 5, :max_size, 20),
13437    vct(0.0, 0.0, 0.0, 0.0, 0.8, 0.0, 0.0, 0.16, 0.16, 0.0,
13438        0.08, 0.064, 0.016, 0.035, 0.013, 0.018, 0.007, 0.007, 0.003, 0.002)],
13439   [make_all_pass(0.5, 0.0, 5, :max_size, 20),
13440    vct(0.0, 0.0, 0.0, 0.0, 0.8, 0.0, 0.0, 0.16, 0.16, 0.0,
13441        0.08, 0.064, 0.016, 0.035, 0.013, 0.018, 0.007, 0.007, 0.003, 0.002)],
13442   [make_notch(0.5, 5, :max_size, 20),
13443    vct(0.5, 0.0, 0.0, 0.0, 0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
13444        0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)],
13445   [make_all_pass(0.0, 0.5, 5, :max_size, 20),
13446    vct(0.5, 0.0, 0.0, 0.0, 0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
13447        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)]].each do |gen, v1|
13448    angle = 0.2
13449    v0 = Vct.new(20) do |i|
13450      gen.run((i.zero? ? 1.0 : 0.0), angle -= 0.2)
13451    end
13452    snd_test_neq(v0, v1, "3 %s (0.5, 0.0, 5)", gen.name)
13453  end
13454  [[make_comb(0.5, 5, :max_size, 20),
13455    vct(0.0, 0.0, 0.0, 0.0, 0.0, 0.95, 0.06, 0.0, 0.0, 0.0,
13456        0.428, 0.079, 0.004, 0.0, 0.0, 0.182, 0.067, 0.008, 0.0, 0.0)],
13457   [make_all_pass(0.5, 0.0, 5, :max_size, 20),
13458    vct(0.0, 0.0, 0.0, 0.0, 0.0, 0.95, 0.06, 0.0, 0.0, 0.0,
13459        0.428, 0.079, 0.004, 0.0, 0.0, 0.182, 0.067, 0.008, 0.0, 0.0)],
13460   [make_notch(0.5, 5, :max_size, 20),
13461    vct(0.5, 0.0, 0.0, 0.0, 0.0, 0.95, 0.06, 0.0, 0.0, 0.0, 0.0,
13462        0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)],
13463   [make_all_pass(0.0, 0.5, 5, :max_size, 20),
13464    vct(0.5, 0, 0, 0, 0, 0.95, 0.06, 0, 0, 0, 0,
13465        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)]].each do |gen, v1|
13466    angle = -0.01
13467    v0 = Vct.new(20) do |i|
13468      gen.run((i.zero? ? 1.0 : 0.0), angle += 0.01)
13469    end
13470    snd_test_neq(v0, v1, "4 %s (0.5, 0.0, 5)", gen.name)
13471  end
13472  # now run off either end of the delay line "by accident"
13473  [[make_comb(0.5, 5, :max_size, 10),
13474    vct(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5,
13475        1.0, 0.25, 0.125, 0.094, 0.062, 0.055, 0.047, 0.039, 0.031, 0.029)],
13476   [make_all_pass(0.5, 0.0, 5, :max_size, 10),
13477    vct(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5,
13478        1.0, 0.25, 0.125, 0.094, 0.062, 0.055, 0.047, 0.039, 0.031, 0.029)],
13479   [make_notch(0.5, 5, :max_size, 10),
13480    vct(0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 1.0,
13481        0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)],
13482   [make_all_pass(0.0, 0.5, 5, :max_size, 10),
13483    vct(0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 1.0,
13484        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)]].each do |gen, v1|
13485    angle = -0.5
13486    v0 = Vct.new(20) do |i|
13487      gen.run((i.zero? ? 1.0 : 0.0), angle += 0.5)
13488    end
13489    snd_test_neq(v0, v1, "5 %s (0.5, 0.0, 5)", gen.name)
13490  end
13491  [[make_comb(0.5, 5, :max_size, 10),
13492    vct(0.0, 0.0, 0.0, 0.5, 0.0, 0.125, 0.0, 0.031, 0.016, 0.004,
13493        1.0, 0.0, 0.25, 0.031, 0.0, 0.012, 0.002, 0.250, 0.125, 0.008)],
13494   [make_all_pass(0.5, 0.0, 5, :max_size, 10),
13495    vct(0.0, 0.0, 0.0, 0.5, 0.0, 0.125, 0.0, 0.031, 0.016, 0.004,
13496        1.0, 0.0, 0.25, 0.031, 0.0, 0.012, 0.002, 0.250, 0.125, 0.008)],
13497   [make_notch(0.5, 5, :max_size, 10),
13498    vct(0.5, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0,
13499        0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)],
13500   [make_all_pass(0.0, 0.5, 5, :max_size, 10),
13501    vct(0.5, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0,
13502        0, 0, 0, 0, 0, 0, 0, 0, 0, 0)]].each do |gen, v1|
13503    angle = 0.5
13504    v0 = Vct.new(20) do |i|
13505      gen.run((i.zero? ? 1.0 : 0.0), angle -= 0.5)
13506    end
13507    snd_test_neq(v0, v1, "6 %s (0.0, 0.5, 5)", gen.name)
13508  end
13509  #
13510  gen = make_filtered_comb(0.5, 5, :filter, make_one_zero(0.5, 0.5))
13511  v0 = Vct.new(21) do |i| filtered_comb(gen, i.zero? ? 1.0 : 0.0) end
13512  v1 = vct(0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
13513           0.25, 0.25, 0, 0, 0, 0.062, 0.125, 0.062, 0, 0, 0.016)
13514  snd_test_neq(v0, v1, "0 filtered_comb (0.5, 5)")
13515  #
13516  gen = make_filtered_comb(0.5, 5, :filter, make_one_zero(0.25, 0.75))
13517  v0 = Vct.new(21) do |i| filtered_comb(gen, i.zero? ? 1.0 : 0.0) end
13518  v1 = vct(0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
13519           0.125, 0.375, 0, 0, 0, 0.016, 0.094, 0.141, 0, 0, 0.002)
13520  snd_test_neq(v0, v1, "1 filtered_comb (0.5, 5)")
13521  #
13522  gen = make_filtered_comb(0.5, 5, :max_size, 20,
13523                           :filter, make_one_zero(0.5, 0.5))
13524  angle = -0.2
13525  v0 = Vct.new(20) do |i|
13526    filtered_comb(gen, i.zero? ? 1.0 : 0.0, angle += 0.2)
13527  end
13528  v1 = vct(0, 0, 0, 0, 0, 0, 0.8, 0.4, 0, 0,
13529           0, 0, 0, 0.08, 0.22, 0.3, 0.140, 0.04, 0, 0)
13530  snd_test_neq(v0, v1, "2 filtered_comb (0.5, 5)")
13531  #
13532  gen = make_filtered_comb(0.5, 5, :max_size, 20,
13533                          :filter, make_one_zero(0.5, 0.5))
13534  angle = 0.2
13535  v0 = Vct.new(20) do |i|
13536    filtered_comb(gen, i.zero? ? 1.0 : 0.0, angle -= 0.2)
13537  end
13538  v1 = vct(0, 0, 0, 0, 0.8, 0, 0, 0.08, 0.2, 0.04,
13539           0.02, 0.068, 0.042, 0.019, 0.026, 0.015, 0.011, 0.009, 0.006, 0.004)
13540  snd_test_neq(v0, v1, "3 filtered_comb (0.5, 5)")
13541  #
13542  gen = make_filtered_comb(0.5, 5, :max_size, 20,
13543                           :filter, make_one_zero(0.5, 0.5))
13544  angle = -0.01
13545  v0 = Vct.new(20) do |i|
13546    filtered_comb(gen, i.zero? ? 1.0 : 0.0, angle += 0.01)
13547  end
13548  v1 = vct(0, 0, 0, 0, 0, 0.95, 0.06, 0, 0, 0,
13549           0.214, 0.251, 0.043, 0.002, 0, 0.045, 0.106, 0.081, 0.023, 0.003)
13550  snd_test_neq(v0, v1, "4 filtered_comb (0.5, 5)")
13551end
13552
13553def test_08_03
13554  gen = make_one_pole(0.4, 0.7)
13555  gen1 = make_one_pole(0.4, 0.7)
13556  print_and_check(gen, "one-pole", "one-pole a0: 0.400, b1: 0.700, y1: 0.000")
13557  v0 = make_vct!(10) do one_pole(gen, 1.0) end
13558  v1 = Vct.new(10) do |x| one_pole?(gen1) ? one_pole(gen1, 1.0) : -1.0 end
13559  unless vequal(v0, v1)
13560    snd_display("map one_pole: %s %s?", v0, v1)
13561  end
13562  unless one_pole?(gen)
13563    snd_display("%s not one_pole?", gen)
13564  end
13565  if gen.order != 1
13566    snd_display("one_pole order: %s?", gen.order)
13567  end
13568  if fneq(gen.a0, 0.4)
13569    snd_display("one_pole a0: %s?", gen.a0)
13570  end
13571  if fneq(gen.b1, 0.7)
13572    snd_display("one_pole b1: %s?", gen.b1)
13573  end
13574  if fneq(v0[1], 0.12) or fneq(v0[4], 0.275) or fneq(v0[8], 0.245)
13575    snd_display("one_pole output: %s?", v0)
13576  end
13577  if fneq(gen.ycoeff(1), 0.7)
13578    snd_display("1p ycoeff 1 0.7: %s?", gen)
13579  end
13580  gen.ycoeff = 1, 0.1
13581  if fneq(gen.ycoeff(1), 0.1)
13582    snd_display("1p set_ycoeff 1 0.1: %s?", gen)
13583  end
13584  if fneq(gen.xcoeff(0), 0.4)
13585    snd_display("1p xcoeff 0 0.4: %s?", gen)
13586  end
13587  gen.xcoeff = 0, 0.3
13588  if fneq(gen.xcoeff(0), 0.3)
13589    snd_display("1p set_xcoeff 0 0.3: %s?", gen)
13590  end
13591  #
13592  gen = make_one_zero(0.4, 0.7)
13593  gen1 = make_one_zero(0.4, 0.7)
13594  print_and_check(gen, "one-zero", "one-zero a0: 0.400, a1: 0.700, x1: 0.000")
13595  v0 = make_vct!(10) do one_zero(gen, 1.0) end
13596  v1 = Vct.new(10) do |x| one_zero?(gen1) ? one_zero(gen1, 1.0) : -1.0 end
13597  unless vequal(v0, v1)
13598    snd_display("map one_zero: %s %s?", v0, v1)
13599  end
13600  unless one_zero?(gen)
13601    snd_display("%s not one_zero?", gen)
13602  end
13603  if gen.order != 1
13604    snd_display("one_zero order: %s?", gen.order)
13605  end
13606  if fneq(gen.a0, 0.4)
13607    snd_display("one_zero a0: %s?", gen.a0)
13608  end
13609  if fneq(gen.a1, 0.7)
13610    snd_display("one_zero a1: %s?", gen.a1)
13611  end
13612  if fneq(v0[1], 1.1)
13613    snd_display("one_zero output: %s?", v0)
13614  end
13615  if fneq(gen.xcoeff(0), 0.4)
13616    snd_display("1z xcoeff 0 0.4: %s?", gen)
13617  end
13618  gen.xcoeff = 0, 0.1
13619  if fneq(gen.xcoeff(0), 0.1)
13620    snd_display("1z set_xcoeff 0 0.1: %s?", gen)
13621  end
13622  #
13623  gen = make_two_zero(0.4, 0.7, 0.3)
13624  gen1 = make_two_zero(0.4, 0.7, 0.3)
13625  print_and_check(gen,
13626                  "two-zero",
13627                  "two-zero a0: 0.400, a1: 0.700, a2: 0.300, x1: 0.000, x2: 0.000")
13628  v0 = make_vct!(10) do two_zero(gen, 1.0) end
13629  v1 = Vct.new(10) do |x| two_zero?(gen1) ? two_zero(gen1, 1.0) : -1.0 end
13630  unless vequal(v0, v1)
13631    snd_display("map two_zero: %s %s?", v0, v1)
13632  end
13633  unless two_zero?(gen)
13634    snd_display("%s not two_zero?", gen)
13635  end
13636  if gen.order != 2
13637    snd_display("two_zero order: %s?", gen.order)
13638  end
13639  if fneq(gen.a0, 0.4)
13640    snd_display("two_zero a0: %s?", gen.a0)
13641  end
13642  if fneq(gen.a1, 0.7)
13643    snd_display("two_zero a1: %s?", gen.a1)
13644  end
13645  if fneq(gen.a2, 0.3)
13646    snd_display("two_zero a2: %s?", gen.a2)
13647  end
13648  if fneq(v0[1], 1.1) or fneq(v0[8], 1.4)
13649    snd_display("two_zero output: %s?", v0)
13650  end
13651  if fneq(gen.xcoeff(0), 0.4)
13652    snd_display("2z xcoeff 0 0.4: %s?", gen)
13653  end
13654  gen.xcoeff = 0, 0.1
13655  if fneq(gen.xcoeff(0), 0.1)
13656    snd_display("2z set_xcoeff 0 0.1: %s?", gen)
13657  end
13658  gen.xcoeff = 0, 1.0
13659  r = gen.scaler
13660  gen.frequency = 500.0
13661  if fneq(gen.frequency, 500.0)
13662    snd_display("set_mus_frequency two_zero: %s?", gen.frequency)
13663  end
13664  if fneq(gen.scaler, r)
13665    snd_display("set_mus_frequency two_zero hit r: %s?", gen.scaler)
13666  end
13667  gen.scaler = 0.99
13668  if fneq(gen.scaler, 0.99)
13669    snd_display("set_mus_scaler two_zero: %s?", gen.scaler)
13670  end
13671  if fneq(gen.frequency, 500.0)
13672    snd_display("set_mus_scaler hit freq two_zero: %s?", gen.frequency)
13673  end
13674  g3 = make_two_zero(:radius, 0.99, :frequency, 500.0)
13675  if fneq(gen.a0, g3.a0) or fneq(gen.a1, g3.a1) or fneq(gen.a2, g3.a2)
13676    snd_display("two_zero setters: %s %s", gen, g3)
13677  end
13678  gen = make_two_zero(0.4, 0.7, 0.3)
13679  if fneq(val = gen.call(1.0, 0.0), 0.4)
13680    snd_display("2zero->0.4: %s?", val)
13681  end
13682  if fneq(val = gen.call(0.5, 0.0), 0.9)
13683    snd_display("2zero->0.9: %s?", val)
13684  end
13685  if fneq(val = gen.call(1.0, 0.0), 1.05)
13686    snd_display("2zero->1.05: %s?", val)
13687  end
13688  #
13689  gen = make_two_pole(0.4, 0.7, 0.3)
13690  gen1 = make_two_pole(0.4, 0.7, 0.3)
13691  print_and_check(gen,
13692                  "two-pole",
13693                  "two-pole a0: 0.400, b1: 0.700, b2: 0.300, y1: 0.000, y2: 0.000")
13694  v0 = make_vct!(10) do two_pole(gen, 1.0) end
13695  v1 = Vct.new(10) do |x| two_pole?(gen1) ? two_pole(gen1, 1.0) : -1.0 end
13696  unless vequal(v0, v1)
13697    snd_display("map two_pole: %s %s?", v0, v1)
13698  end
13699  unless two_pole?(gen)
13700    snd_display("%s not two_pole?", gen)
13701  end
13702  if gen.order != 2
13703    snd_display("two_pole order: %s?", gen.order)
13704  end
13705  if fneq(gen.a0, 0.4)
13706    snd_display("two_pole a0: %s?", gen.a0)
13707  end
13708  if fneq(gen.b1, 0.7)
13709    snd_display("two_pole b1: %s?", gen.b1)
13710  end
13711  if fneq(gen.b2, 0.3)
13712    snd_display("two_pole b2: %s?", gen.b2)
13713  end
13714  if fneq(v0[1], 0.12) or fneq(v0[8], 0.201)
13715    snd_display("two_pole output: %s?", v0)
13716  end
13717  if fneq(gen.ycoeff(1), 0.7)
13718    snd_display("2p ycoeff 1 0.7: %s?", gen)
13719  end
13720  gen.ycoeff = 1, 0.1
13721  if fneq(gen.ycoeff(1), 0.1)
13722    snd_display("2p set_ycoeff 1 0.1: %s?", gen)
13723  end
13724  if fneq(gen.xcoeff(0), 0.4)
13725    snd_display("2p xcoeff 0 0.4: %s?", gen)
13726  end
13727  gen.xcoeff = 0, 0.3
13728  if fneq(gen.xcoeff(0), 0.3)
13729    snd_display("2p set_xcoeff 0 0.3: %s?", gen)
13730  end
13731  gen.xcoeff = 0, 1.0
13732  r = gen.scaler
13733  gen.frequency = 500.0
13734  if fneq(gen.frequency, 500.0)
13735    snd_display("set_mus_frequency two_pole: %s?", gen.frequency)
13736  end
13737  if fneq(gen.scaler, r)
13738    snd_display("set_mus_frequency two_pole hit r: %s?", gen.scaler)
13739  end
13740  gen.scaler = 0.99
13741  if fneq(gen.scaler, 0.99)
13742    snd_display("set_mus_scaler two_pole: %s?", gen.scaler)
13743  end
13744  if fneq(gen.frequency, 500.0)
13745    snd_display("set_mus_scaler hit freq two_pole: %s?", gen.frequency)
13746  end
13747  g3 = make_two_pole(:radius, 0.99, :frequency, 500.0)
13748  if fneq(gen.a0, g3.a0) or fneq(gen.a1, g3.a1) or fneq(gen.a2, g3.a2)
13749    snd_display("two_pole setters: %s %s", gen, g3)
13750  end
13751  gen = make_two_pole(0.4, 0.7, 0.3)
13752  if fneq(val = gen.call(1.0, 0.0), 0.4)
13753    snd_display("a0->out 2pole: %s?", val)
13754  end
13755  if fneq(val = gen.call(0.5, 0.0), -0.08)
13756    snd_display("a0->out 2pole (-0.08): %s?", val)
13757  end
13758  if fneq(val = gen.call(1.0, 0.0), 0.336)
13759    snd_display("a0->out 2pole (0.336): %s?", val)
13760  end
13761  #
13762  gen = make_oscil(440.0)
13763  gen1 = make_oscil(440.0)
13764  gen2 = make_oscil(440.0)
13765  print_and_check(gen, "oscil", "oscil freq: 440.000Hz, phase: 0.000")
13766  v0 = make_vct!(10) do oscil(gen, 0.0) end
13767  v1 = make_vct!(10) do mus_apply(gen1, 0.0, 0.0) end
13768  v2 = Vct.new(10) do |x| oscil?(gen2) ? oscil(gen2, 0.0) : -1.0 end
13769  unless vequal(v0, v2)
13770    snd_display("map oscil: %s %s?", v0, v2)
13771  end
13772  unless oscil?(gen)
13773    snd_display("%s not oscil?", gen)
13774  end
13775  if fneq(gen.phase, 1.253787)
13776    snd_display("oscil phase: %s?", gen.phase)
13777  end
13778  if fneq(gen.frequency, 440.0)
13779    snd_display("oscil frequency: %s?", gen.frequency)
13780  end
13781  if fneq(gen.length, 1)
13782    snd_display("oscil cosines: %s?", gen.length)
13783  end
13784  if fneq(v0[1], 0.125) or fneq(v0[8], 0.843)
13785    snd_display("oscil output: %s?", v0)
13786  end
13787  gen.phase = 0.0
13788  if fneq(gen.phase, 0.0)
13789    snd_display("oscil set_phase: %s?", gen.phase)
13790  end
13791  gen.frequency = 100.0
13792  if fneq(gen.frequency, 100.0)
13793    snd_display("oscil set_frequency: %s?", gen.frequency)
13794  end
13795  #
13796  v0.each_with_index do |val, i|
13797    if fneq(val, v1[i])
13798      snd_display("mus_apply oscil at %s: %s %s?", i, val, v1[i])
13799    end
13800  end
13801  if fneq(mus_apply, 0.0)
13802    snd_display("mus_apply: %s?", mus_apply)
13803  end
13804  gen1 = make_oscil(100.0)
13805  gen2 = make_oscil(-100.0)
13806  mx = 0.0
13807  100.times do mx = [mx, (gen1.run + gen2.run).abs].max end
13808  if fneq(mx, 0.0)
13809    snd_display("1 oscil +-: %s?", mx)
13810  end
13811  gen1 = make_oscil(100.0, PI * 0.5)
13812  gen2 = make_oscil(-100.0, PI * 0.5)
13813  mx = 0.0
13814  100.times do mx = [mx, (gen1.run - gen2.run).abs].max end
13815  if fneq(mx, 0.0)
13816    snd_display("2 oscil +-: %s?", mx)
13817  end
13818  fm_test(make_oscil)
13819  fm_test(make_square_wave)
13820  fm_test(make_triangle_wave)
13821  fm_test(make_ncos)
13822  fm_test(make_nsin)
13823  fm_test(make_sawtooth_wave)
13824  fm_test(make_rand)
13825  fm_test(make_rand_interp)
13826  fm_test(make_pulse_train)
13827  #
13828  gen = make_oscil(440.0)
13829  gen1 = make_oscil(440.0)
13830  10.times do
13831    if fneq(oval = oscil(gen, 0.1), mval = mus_run(gen1, 0.1))
13832      snd_display("mus_run %s but oscil %s?", oval, mval)
13833    end
13834  end
13835  gen = make_oscil(440.0)
13836  gen1 = make_oscil(440.0)
13837  gen2 = make_oscil(440.0)
13838  gen3 = make_oscil(440.0)
13839  fm_index = hz2radians(440.0)
13840  v0 = make_vct(10)
13841  v1 = make_vct(10)
13842  10.times do |i|
13843    v0[i] = oscil(gen, fm_index * oscil(gen1, 0.0))
13844    v1[i] = mus_apply(gen2, fm_index * mus_apply(gen3, 0.0, 0.0), 0.0)
13845  end
13846  if fneq(v0[1], 0.125) or fneq(v0[6], 0.83) or fneq(v0[8], 0.987)
13847    snd_display("oscil fm output: %s?", v0)
13848  end
13849  v0.each_with_index do |val, i|
13850    if fneq(val, v1[i])
13851      snd_display("mus_apply fm oscil at %s: %s %s?", i, val, v1[i])
13852    end
13853  end
13854  test_gen_equal(make_oscil(440.0), make_oscil(440.0), make_oscil(100.0))
13855  test_gen_equal(make_oscil(440.0), make_oscil(440.0), make_oscil(440.0, 1.0))
13856  gen = make_oscil(440.0)
13857  gen1 = make_oscil(440.0)
13858  pm_index = 2.0
13859  v0 = make_vct!(10) do gen.call(0.0, pm_index * gen1.call(0.0, 0.0)) end
13860  if fneq(v0[1], 0.367) or fneq(v0[6], 0.854) or fneq(v0[8], 0.437)
13861    snd_display("oscil pm output: %s?", v0)
13862  end
13863  gen = make_oscil(440.0)
13864  1100.times do |i|
13865    if fneq(val1 = sin(gen.phase), val2 = gen.call(0.0, 0.0))
13866      snd_display("oscil (sin): %s: %s %s?", i, val1, val2)
13867    end
13868  end
13869  gen = make_oscil(440.0, :initial_phase, PI * 0.5)
13870  a = 0.0
13871  900.times do |i|
13872    if fneq(val1 = cos(a), val2 = gen.call(0.0, 0.0))
13873      snd_display("oscil (cos): %s: %s %s?", i, val1, val2)
13874    end
13875    a = a + (2 * PI * 440) / 22050
13876  end
13877  gen = make_oscil(0.0)
13878  gen1 = make_oscil(40.0)
13879  a = 0.0
13880  1100.times do |i|
13881    if fneq(val1 = sin(sin(a)), val2 = oscil(gen, 0.0, oscil(gen1, 0.0)))
13882      snd_display("oscil  pm: %s: %s %s?", i, val1, val2)
13883    end
13884    a = a + (2 * PI * 40) / 22050
13885  end
13886  gen = make_oscil(0.0)
13887  gen1 = make_oscil(40.0)
13888  a = 0.0
13889  a1 = 0.0
13890  1100.times do |i|
13891    fm = sin(a)
13892    if fneq(val1 = sin(a1), val2 = oscil(gen, oscil(gen1, 0.0)))
13893      snd_display("oscil  fm: %s: %s %s?", i, val1, val2)
13894    end
13895    a = a + (2 * PI * 40) / 22050
13896    a1 += fm
13897  end
13898  #
13899  if (res = Snd.catch do mus_location(make_oscil) end).first != :mus_error
13900    snd_display("mus_location bad gen: %s", res.inspect)
13901  end
13902  if (res = Snd.catch do set_mus_location(make_oscil, 0) end).first != :mus_error
13903    snd_display("set_mus_location bad gen: %s", res.inspect)
13904  end
13905  if (res = Snd.catch do set_mus_scaler(make_oscil, 0) end).first != :mus_error
13906    snd_display("set_mus_scaler bad gen: %s", res.inspect)
13907  end
13908  if (res = Snd.catch do mus_frequency(make_one_pole) end).first != :mus_error
13909    snd_display("mus_frequency bad gen: %s", res.inspect)
13910  end
13911  if (res = Snd.catch do set_mus_frequency(make_one_pole, 0) end).first != :mus_error
13912    snd_display("set_mus_frequency bad gen: %s", res.inspect)
13913  end
13914  if (res = Snd.catch do make_delay(1024 * 1024 * 40) end).first != :out_of_range
13915    snd_display("make_delay huge line 1: %s", res.inspect)
13916  end
13917  if (res = Snd.catch do make_delay(32, :max_size, 1024 * 1024 * 40) end).first != :out_of_range
13918    snd_display("make_delay huge line 2: %s", res.inspect)
13919  end
13920end
13921
13922def test_08_04
13923  gen = make_asymmetric_fm(440.0)
13924  gen1 = make_asymmetric_fm(440.0)
13925  print_and_check(gen,
13926                  "asymmetric-fm",
13927                  "asymmetric-fm freq: 440.000Hz, phase: 0.000, ratio: 1.000, r: 1.000")
13928  v0 = make_vct!(10) do asymmetric_fm(gen, 0.0) end
13929  v1 = Vct.new(10) do |x|
13930    asymmetric_fm?(gen1) ? asymmetric_fm(gen1, 0.0) : -1.0
13931  end
13932  unless vequal(v0, v1)
13933    snd_display("map asymmetric_fm: %s %s?", v0, v1)
13934  end
13935  unless asymmetric_fm?(gen)
13936    snd_display("%s not asymmetric_fm?", gen)
13937  end
13938  if fneq(gen.phase, 1.253787)
13939    snd_display("asymmetric_fm phase: %s?", gen.phase)
13940  end
13941  gen.phase = 1.0
13942  if fneq(gen.phase, 1.0)
13943    snd_display("asymmetric_fm set_phase: %s?", gen.phase)
13944  end
13945  if fneq(gen.frequency, 440.0)
13946    snd_display("asymmetric_fm frequency: %s?", gen.frequency)
13947  end
13948  gen.frequency = 100.0
13949  if fneq(gen.frequency, 100.0)
13950    snd_display("asymmetric_fm set_frequency: %s?", gen.frequency)
13951  end
13952  if fneq(v0[2], 0.969) or fneq(v0[8], 0.538)
13953    snd_display("asymmetric_fm output: %s?", v0)
13954  end
13955  if fneq(gen.scaler, 1.0)
13956    snd_display("asymmetric_fm set_scaler: %s?", gen.scaler)
13957  end
13958  gen.scaler = 0.5
13959  if fneq(gen.scaler, 0.5)
13960    snd_display("asymmetric_fm set_scaler: %s?", gen.scaler)
13961  end
13962  if fneq(gen.offset, 1.0)
13963    snd_display("asymmetric_fm offset: %s?", gen.offset)
13964  end
13965  test_gen_equal(make_asymmetric_fm(440),
13966                 make_asymmetric_fm(440),
13967                 make_asymmetric_fm(100))
13968  test_gen_equal(make_asymmetric_fm(440),
13969                 make_asymmetric_fm(440),
13970                 make_asymmetric_fm(440, 1))
13971  test_gen_equal(make_asymmetric_fm(440),
13972                 make_asymmetric_fm(440),
13973                 make_asymmetric_fm(440, 0.0, 3))
13974  gen1 = make_asymmetric_fm(1000, 0, 1, 0.1)
13975  gen2 = make_oscil(1000, :initial_phase, HALF_PI)
13976  100.times do |i|
13977    ss = asymmetric_fm(gen1, 0.0, 0.0)
13978    os = oscil(gen2, 0.0)
13979    if fneq(ss, os)
13980      snd_display("asymmetric_fm 1: %s: os: %s ss: %s?", i, os, ss)
13981      break
13982    end
13983  end
13984  gen3 = make_asymmetric_fm(1000, 0, 1.0, 0.2)
13985  gen4 = make_oscil(1000, :initial_phase, HALF_PI)
13986  gen5 = make_oscil(200)
13987  fm1 = hz2radians(0.2 * 1000)
13988  vct0 = make_vct(2048)
13989  vct1 = make_vct!(2048) do |i|
13990    vct0[i] = asymmetric_fm(gen3, 1.0, 0.0)
13991    oscil(gen4, fm1 * oscil(gen5))
13992  end
13993  spectr1 = snd_spectrum(vct0, Rectangular_window, 2048, true)
13994  spectr2 = snd_spectrum(vct1, Rectangular_window, 2048, true)
13995  (1...512).each do |i|
13996    if fneq_err(spectr1[i], spectr2[i], 0.02)
13997      snd_display("asymmetric_fm 2: %s: %s %s?", i, spectr1[i], spectr2[i])
13998      break
13999    end
14000  end
14001  gen = make_asymmetric_fm(40.0, 0.0, 1.0, 0.1)
14002  gen1 = make_asyfm(:frequency, 40.0, :ratio, 0.1, :index, 2.0)
14003  a = 0.0
14004  1100.times do |i|
14005    val1 = asymmetric_fm(gen, 2.0)
14006    val3 = asyfm_J(gen1, 0.0)
14007    r = 1.0
14008    ratio = 0.1
14009    index = 2.0
14010    cr = 0.5 * (r - (1.0 / r))
14011    sr = 0.5 * (r + (1.0 / r))
14012    th = a
14013    mth = ratio * th
14014    val2 = exp(index * cr * (1.0 + cos(mth))) *
14015      cos(th + (index * sr * sin(mth)))
14016    if fneq(val1, val2) or fneq(val1, val3)
14017      snd_display("asyfm by hand: %s: 1 %s 2 %s 3 %s?", i, val1, val2, val3)
14018    end
14019    a = a + ((TWO_PI * 40.0) / mus_srate())
14020  end
14021  gen3 = make_asymmetric_fm(1000, 0, 2.0, 0.1)
14022  gen4 = make_asymmetric_fm(1000, 0, 0.5, 0.1)
14023  vct0 = make_vct(2048)
14024  vct1 = make_vct!(2048) do |i|
14025    vct0[i] = asymmetric_fm(gen3, 2.0, 0.0)
14026    asymmetric_fm(gen4, 2.0, 0.0)
14027  end
14028  spectr1 = snd_spectrum(vct0, Rectangular_window, 2048, true)
14029  spectr2 = snd_spectrum(vct1, Rectangular_window, 2048, true)
14030  s1_loc = 0
14031  s2_loc = 0
14032  (1...256).each do |i|
14033    if (1.0 - spectr1[i]).abs < 0.01
14034      s1_loc = i
14035    end
14036    if (1.0 - spectr2[i]).abs < 0.01
14037      s2_loc = i
14038    end
14039  end
14040  if s2_loc > s1_loc
14041    snd_display("asymmetric_fm peaks: %s %s?", s1_loc, s2_loc)
14042  end
14043  center = ((22050 / 2048.0) * 0.5 * (s1_loc + s2_loc)).round
14044  if (1000 - center).abs > 60
14045    snd_display("asymmetric_fm center: %s?", center)
14046  end
14047  gen3.scaler = 0.5
14048  2048.times do |i| vct0[i] = asymmetric_fm(gen3, 2.0, 0.0) end
14049  spectr1 = snd_spectrum(vct0, Rectangular_window, 2048, true)
14050  (1...256).each do |i|
14051    s1_loc = i if (1.0 - spectr1[i]).abs < 0.01
14052  end
14053  if s2_loc != s1_loc
14054    snd_display("asymmetric_fm set r peaks: %s %s?", s1_loc, s2_loc)
14055  end
14056  2048.times do |i| vct0[i] = asymmetric_fm(gen3, 2.0, 0.0) end
14057  snd_spectrum(vct0, Rectangular_window, 2048, true, 0.0, true)
14058  (1...256).each do |i|
14059    if (1.0 - spectr1[i]).abs < 0.01
14060      s1_loc = i
14061    end
14062  end
14063  if s2_loc != s1_loc
14064    snd_display("asymmetric_fm set r in place peaks: %s %s?", s1_loc, s2_loc)
14065  end
14066  #
14067  gen = make_asyfm(:frequency, 2000, :ratio, 0.1)
14068  asyfm_I(gen, 0.0)
14069end
14070
14071class F_filter
14072  def initialize(coeffs)
14073    @coeffs = coeffs
14074    @xs = Vct.new(coeffs.length)
14075  end
14076
14077  def f_filter(x)
14078    xlen = @xs.length
14079    @xs.move!(xlen - 1, xlen - 2, true)
14080    @xs.first = x
14081    dot_product(@coeffs, @xs, xlen)
14082  end
14083end
14084
14085def make_f_filter(coeffs)
14086  F_filter.new(coeffs)
14087end
14088
14089def f_filter(flt, x)
14090  flt.f_filter(x)
14091end
14092
14093def test_08_05
14094  gen = make_fir_filter(3, vct(0.5, 0.25, 0.125))
14095  gen1 = make_fir_filter(3, vct(0.5, 0.25, 0.125))
14096  print_and_check(gen, "fir-filter", "fir-filter order: 3, xs: [0.5 0.25 0.125]")
14097  v0 = make_vct!(10) do |i| fir_filter(gen, i.zero? ? 1.0 : 0.0) end
14098  v1 = make_vct(10)
14099  inp = -1
14100  v1.map! do |x|
14101    inp += 1
14102    fir_filter?(gen1) ? fir_filter(gen1, inp.zero? ? 1.0 : 0.0) : -1.0
14103  end
14104  unless vequal(v0, v1)
14105    snd_display("map fir_filter: %s %s?", v0, v1)
14106  end
14107  unless fir_filter?(gen)
14108    snd_display("%s not fir_filter?", gen)
14109  end
14110  if gen.length != 3
14111    snd_display("fir_filter length: %s?", gen.length)
14112  end
14113  if fneq(v0[1], 0.25) or fneq(v0[2], 0.125)
14114    snd_display("fir_filter output: %s?", v0)
14115  end
14116  data = gen.xcoeffs
14117  if fneq(data[1], 0.25)
14118    snd_display("fir_filter xcoeffs: %s?", data)
14119  end
14120  if (res = Snd.catch do mus_xcoeff(gen, 123) end).first != :mus_error
14121    snd_display("xcoeff 123: %s", res.inspect)
14122  end
14123  if (res = Snd.catch do mus_ycoeff(gen, 123) end).first != :mus_error
14124    snd_display("fir ycoeff 123: %s", res.inspect)
14125  end
14126  f1 = make_fir_filter(3, vct(0.5, 0.25, 0.125))
14127  f2 = make_fir_filter(3, vct(0.5, 0.25, 0.125))
14128  f3 = make_fir_filter(3, vct(0.75, 0.25, 0.125))
14129  fir_filter(f1, 1.0)
14130  fir_filter(f2, 1.0)
14131  fir_filter(f3, 1.0)
14132  test_gen_equal(f1, f2, f3)
14133  f1 = make_fir_filter(3, vct(0.5, 0.25, 0.125))
14134  f2 = make_fir_filter(3, vct(0.5, 0.25, 0.125))
14135  f3 = make_fir_filter(2, vct(0.5, 0.25))
14136  fir_filter(f1, 1.0)
14137  fir_filter(f2, 1.0)
14138  fir_filter(f3, 1.0)
14139  test_gen_equal(f1, f2, f3)
14140  coeffs = vct(0.1, 0.2, 0.3, 0.4, 0.4, 0.3, 0.2, 0.1)
14141  flt = make_fir_filter(8, coeffs)
14142  xcof = flt.xcoeffs
14143  es = make_array(8) do |i|
14144    make_env([0, coeffs[i], 1, 0], :length, 102)
14145  end
14146  es[5] = make_env([0, 0.4, 1, 1], :length, 102)
14147  data = make_vct!(100) do |i|
14148    val = fir_filter(flt, (i % 12).zero? ? 1.0 : 0.0)
14149    es.each_with_index do |en, j|
14150      xcof[j] = env(en)
14151    end
14152    val
14153  end
14154  if fneq(data[1], 0.2) or fneq(data[10], 0.0) or
14155      fneq(data[18], 0.166) or fneq(data[89], 0.923)
14156    snd_display("filter xcoeffs: %s?", data)
14157  end
14158  #
14159  fir1 = make_fir_filter(3, [1, 0.4, 0.1].to_vct)
14160  fir2 = make_f_filter([1, 0.4, 0.1].to_vct)
14161  10.times do |i|
14162    val1 = fir_filter(fir1, i.zero? ? 1.0 : 0.0)
14163    val2 = f_filter(fir2, i.zero? ? 1.0 : 0.0)
14164    if fneq(val1, val2)
14165      snd_display("f_filter %s -> %s %s?", i, val1, val2)
14166      break
14167    end
14168  end
14169  #
14170  gen = make_iir_filter(3, vct(0.5, 0.25, 0.125))
14171  gen1 = make_iir_filter(3, vct(0.5, 0.25, 0.125))
14172  print_and_check(gen, "iir-filter", "iir-filter order: 3, ys: [0.5 0.25 0.125]")
14173  v0 = make_vct!(10) do |i| iir_filter(gen, i.zero? ? 1.0 : 0.0) end
14174  v1 = make_vct(10)
14175  inp = -1
14176  v1.map! do |x|
14177    inp += 1
14178    iir_filter?(gen1) ? iir_filter(gen1, inp.zero? ? 1.0 : 0.0) : -1.0
14179  end
14180  unless vequal(v0, v1)
14181    snd_display("map iir_filter: %s %s?", v0, v1)
14182  end
14183  unless iir_filter?(gen)
14184    snd_display("%s not iir_filter?", gen)
14185  end
14186  if gen.length != 3
14187    snd_display("iir_filter length: %s?", gen.length)
14188  end
14189  if fneq(v0[1], -0.25) or fneq(v0[2], -0.062)
14190    snd_display("iir_filter output: %s?", v0)
14191  end
14192  data = gen.ycoeffs
14193  if fneq(data[1], 0.25)
14194    snd_display("iir_filter ycoeffs: %s?", data)
14195  end
14196  if (res = Snd.catch do mus_ycoeff(gen, 123) end).first != :mus_error
14197    snd_display("ycoeff 123: %s", res.inspect)
14198  end
14199  if (res = Snd.catch do mus_xcoeff(gen, 123) end).first != :mus_error
14200    snd_display("iir xcoeff 123: %s", res.inspect)
14201  end
14202  f1 = make_iir_filter(3, vct(0.5, 0.25, 0.125))
14203  f2 = make_iir_filter(3, vct(0.5, 0.25, 0.125))
14204  f3 = make_iir_filter(3, vct(0.75, 0.25, 0.125))
14205  iir_filter(f1, 1.0)
14206  iir_filter(f2, 1.0)
14207  iir_filter(f3, 1.0)
14208  test_gen_equal(f1, f2, f3)
14209  f1 = make_iir_filter(3, vct(0.5, 0.25, 0.125))
14210  f2 = make_iir_filter(3, vct(0.5, 0.25, 0.125))
14211  f3 = make_iir_filter(2, vct(0.5, 0.25))
14212  iir_filter(f1, 1.0)
14213  iir_filter(f2, 1.0)
14214  iir_filter(f3, 1.0)
14215  test_gen_equal(f1, f2, f3)
14216  #
14217  gen = make_filter(3, vct(0.5, 0.25, 0.125), vct(0.5, 0.25, 0.125))
14218  gen1 = make_filter(3, vct(0.5, 0.25, 0.125), vct(0.5, 0.25, 0.125))
14219  print_and_check(gen,
14220                  "filter",
14221                  "filter order: 3, xs: [0.5 0.25 0.125], ys: [0.5 0.25 0.125]")
14222  v0 = make_vct!(10) do |i| filter(gen, i.zero? ? 1.0 : 0.0) end
14223  v1 = make_vct(10)
14224  inp = -1
14225  v1.map! do |x|
14226    inp += 1
14227    filter?(gen1) ? filter(gen1, inp.zero? ? 1.0 : 0.0) : -1.0
14228  end
14229  unless vequal(v0, v1)
14230    snd_display("map filter: %s %s?", v0, v1)
14231  end
14232  unless filter?(gen)
14233    snd_display("%s not filter?", gen)
14234  end
14235  if gen.length != 3
14236    snd_display("filter length: %s?", gen.length)
14237  end
14238  if fneq(v0[1], 0.125) or fneq(v0[2], 0.031)
14239    snd_display("filter output: %s?", v0)
14240  end
14241  gen2 = make_biquad(0.1, 0.2, 0.3, 0.4, 0.5)
14242  unless filter?(gen2)
14243    snd_display("make_biquad: %s?", gen2)
14244  end
14245  xs = gen.xcoeffs
14246  ys = gen.ycoeffs
14247  if xs != vct(0.5, 0.25, 0.125) or xs != ys
14248    snd_display("mus_xcoeffs: %s %s?", xs, ys)
14249  end
14250  if (res = Snd.catch do
14251        make_filter(:order, 2, :xcoeffs, vct(1.0, 0.5), :ycoeffs, vct(2.0, 1.0, 0.5))
14252      end).first != :mus_error
14253    snd_display("make_filter bad coeffs: %s", res.inspect)
14254  end
14255  if (res = Snd.catch do
14256        make_filter(:order, 0, :xcoeffs, vct(1.0, 0.5))
14257      end).first != :out_of_range
14258    snd_display("make_filter bad order: %s", res.inspect)
14259  end
14260  if (res = Snd.catch do
14261        make_fir_filter(:order, 22, :xcoeffs, vct(1.0, 0.5))
14262      end).first != :mus_error
14263    snd_display("make_fir_filter bad coeffs: %s", res.inspect)
14264  end
14265  if (res = Snd.catch do
14266        make_iir_filter(:order, 22, :ycoeffs, vct(1.0, 0.5))
14267      end).first != :mus_error
14268    snd_display("make_iir_filter bad coeffs: %s", res.inspect)
14269  end
14270  if (res = Snd.catch do
14271        make_fir_filter(-1)
14272      end).first != :out_of_range
14273    snd_display("make_fir_filter bad order: %s", res.inspect)
14274  end
14275  unless iir_filter?(res = make_filter(:order, 2, :ycoeffs, vct(1.0, 0.5)))
14276    snd_display("make_filter with only y: %s", res)
14277  end
14278  f1 = make_filter(3, vct(0.5, 0.25, 0.125), vct(0.5, 0.25, 0.125))
14279  f2 = make_filter(3, vct(0.5, 0.25, 0.125), vct(0.5, 0.25, 0.125))
14280  f3 = make_filter(3, vct(0.5, 0.25, 0.125), vct(0.5, 0.5, 0.5))
14281  filter(f1, 1.0)
14282  filter(f2, 1.0)
14283  filter(f3, 1.0)
14284  test_gen_equal(f1, f2, f3)
14285  f1 = make_filter(3, vct(0.5, 0.25, 0.125), vct(0.5, 0.25, 0.125))
14286  f2 = make_filter(3, vct(0.5, 0.25, 0.125), vct(0.5, 0.25, 0.125))
14287  f3 = make_filter(3, vct(0.5, 0.5, 0.125), vct(0.5, 0.25, 0.0625))
14288  filter(f1, 1.0)
14289  filter(f2, 1.0)
14290  filter(f3, 1.0)
14291  test_gen_equal(f1, f2, f3)
14292  fr = make_fir_filter(6, vct(0, 1, 2, 3, 4, 5))
14293  if fr.length != 6
14294    snd_display("filter_length: %s?", fr.length)
14295  end
14296  #
14297  unless vequal(res = cascade2canonical([vct(1, 0, 0), vct(1, 0.5, 0.25)]),
14298                vct(1.000, 0.500, 0.250, 0.000, 0.000))
14299    snd_display("cascade2canonical 0: %s?", res)
14300  end
14301  unless vequal(res = cascade2canonical([vct(1, 1, 0), vct(1, 0.5, 0.25)]),
14302                vct(1.000, 1.500, 0.750, 0.250, 0.000))
14303    snd_display("cascade2canonical 1: %s?", res)
14304  end
14305  unless vequal(res = cascade2canonical([vct(1, 0.8, 0), vct(1, 1.4, 0.65), vct(1, 0, 0)]),
14306                vct(1.000, 2.200, 1.770, 0.520, 0.000, 0.000, 0.000))
14307    snd_display("cascade2canonical 2: %s?", res)
14308  end
14309  unless vequal(res = cascade2canonical([vct(1, -0.9, 0), vct(1, 1, 0.74), vct(1, -1.6, 0.8)]),
14310                vct(1.000, -1.500, 0.480, -0.330, 0.938, -0.533, 0.000))
14311    snd_display("cascade2canonical 3: %s?", res)
14312  end
14313  #
14314  ind = new_sound("test.snd", 1, 22050, Mus_bfloat, Mus_next)
14315  pad_channel(0, 10000)
14316  freq_sweep(0.45)
14317  sp = rough_spectrum(ind)
14318  if (not vequal(sp, vct(0.962, 0.998, 0.998, 0.998, 0.998, 0.999, 0.999, 0.998, 0.997, 1))) and
14319      (not vequal(sp, vct(0.963, 0.999, 0.999, 0.999, 0.999, 0.999, 1, 1, 0.998, 0.997)))
14320    snd_display("initial rough spectrum: %s?", sp)
14321  end
14322  b = make_butter_high_pass(440.0)
14323  v = make_vct!(10) do |i| butter(b, i.zero? ? 1.0 : 0.0) end
14324  unless vequal(v, vct(0.915, -0.162, -0.146, -0.131, -0.117, -0.103, -0.09, -0.078, -0.066, -0.056))
14325    snd_display("butter high: %s?", v)
14326  end
14327  b = make_butter_high_pass(1000.0)
14328  map_channel(lambda do |y| butter(b, y) end)
14329  sp = rough_spectrum(ind)
14330  if (not vequal(sp, vct(0.150, 0.833, 0.980, 0.994, 0.997, 0.998, 0.999, 0.998, 0.997, 1))) and
14331      (not vequal(sp, vct(0.150, 0.833, 0.981, 0.995, 0.998, 0.999, 1, 1, 0.998, 0.997)))
14332    snd_display("hp rough spectrum: %s?", sp)
14333  end
14334  undo_edit
14335  #
14336  b = make_butter_low_pass(440.0)
14337  v.map_with_index! do |val, i| butter(b, i.zero? ? 1.0 : 0.0) end
14338  unless vequal(v, vct(0.004, 0.014, 0.026, 0.035, 0.043, 0.049, 0.053, 0.055, 0.057, 0.057))
14339    snd_display("butter low: %s?", v)
14340  end
14341  b = make_butter_low_pass(1000.0)
14342  map_channel(lambda do |y| butter(b, y) end)
14343  sp = rough_spectrum(ind)
14344  unless vequal(sp, vct(1, 0.212, 0.024, 0.005, 0.001, 0.000, 0.000, 0.000, 0.000, 0.000))
14345    snd_display("lp rough spectrum: %s?", sp)
14346  end
14347  undo_edit
14348  #
14349  b = make_butter_band_pass(440.0, 50.0)
14350  v.map_with_index! do |val, i| butter(b, i.zero? ? 1.0 : 0.0) end
14351  unless vequal(v, vct(0.007, 0.014, 0.013, 0.013, 0.012, 0.011, 0.009, 0.008, 0.007, 0.005))
14352    snd_display("butter bandpass: %s?", v)
14353  end
14354  b = make_butter_band_pass(1000.0, 500.0)
14355  map_channel(lambda do |y| butter(b, y) end)
14356  sp = rough_spectrum(ind)
14357  unless vequal(sp, vct(0.888, 1, 0.144, 0.056, 0.027, 0.014, 0.008, 0.004, 0.002, 0))
14358    snd_display("bp rough spectrum: %s?", sp)
14359  end
14360  undo_edit
14361  #
14362  b = make_butter_band_reject(440.0, 50.0)
14363  v.map_with_index! do |val, i| butter(b, i.zero? ? 1.0 : 0.0) end
14364  unless vequal(v,
14365                vct(0.993, -0.014, -0.013, -0.013, -0.012, -0.011, -0.009, -0.008, -0.007, -0.005))
14366    snd_display("butter bandstop: %s?", v)
14367  end
14368  b = make_butter_band_reject(1000.0, 500.0)
14369  map_channel(lambda do |y| butter(b, y) end)
14370  sp = rough_spectrum(ind)
14371  if (not vequal(sp, vct(0.662, 0.687, 0.953, 0.980, 0.989, 0.994, 0.997, 0.997, 0.997, 1))) and
14372      (not vequal(sp, vct(0.664, 0.689, 0.955, 0.982, 0.992, 0.996, 0.999, 1, 0.999, 0.998)))
14373    snd_display("bs rough spectrum: %s?", sp)
14374  end
14375  undo_edit
14376  #
14377  analog_filter_tests
14378  #
14379  v = spectrum2coeffs(10, vct(0, 1.0, 0, 0, 0, 0, 0, 0, 1.0, 0))
14380  v1 = make_fir_coeffs(10, vct(0, 1.0, 0, 0, 0, 0, 0, 0, 1.0, 0))
14381  unless vequal(v, vct(-0.190, -0.118, 0.000, 0.118, 0.190, 0.190, 0.118, 0.000, -0.118, -0.190))
14382    snd_display("spectrum2coeffs: %s?", v)
14383  end
14384  unless vequal(v, v1)
14385    snd_display("spectrum2coeffs v make_fir_coeffs: %s %s?", v, v1)
14386  end
14387  notched_spectr = make_vct(20)
14388  notched_spectr[2] = 1.0
14389  v = spectrum2coeffs(20, notched_spectr)
14390  v1 = make_fir_coeffs(20, notched_spectr)
14391  unless vequal(v, vct(0.095, 0.059, 0.000, -0.059, -0.095, -0.095, -0.059, 0.000, 0.059, 0.095,
14392                       0.095, 0.059, 0.000, -0.059, -0.095, -0.095, -0.059, 0.000, 0.059, 0.095))
14393    snd_display("spectrum2coeffs (notch): %s?", v)
14394  end
14395  unless vequal(v, v1)
14396    snd_display("spectrum2coeffs v(2) make_fir_coeffs: %s %s?", v, v1)
14397  end
14398  flt = make_fir_filter(20, v)
14399  map_channel(lambda do |y| fir_filter(flt, y) end)
14400  sp = rough_spectrum(ind)
14401  unless vequal(sp, vct(0.007, 0.493, 1.000, 0.068, 0.030, 0.019, 0.014, 0.011, 0.009, 0.009))
14402    snd_display("sp->coeff rough spectrum: %s?", sp)
14403  end
14404  undo_edit
14405  #
14406  rspect = make_vct!(20) do random(1.0) end
14407  v = spectrum2coeffs(20, rspect)
14408  v1 = make_fir_coeffs(20, rspect)
14409  unless vequal(v, v1)
14410    snd_display("spectrum2coeffs v(3) make_fir_coeffs:\n# %s\n# %s", v, v1)
14411  end
14412  b = make_highpass(hz2radians(1000.0), 10)
14413  v = make_vct!(20) do |i| highpass(b, i.zero? ? 1.0 : 0.0) end
14414  unless vequal(v, vct(-0.001, -0.002, -0.005, -0.011, -0.021, -0.034, -0.049, -0.065,
14415                       -0.078, -0.087, 0.909, -0.087, -0.078, -0.065, -0.049, -0.034,
14416                       -0.021, -0.011, -0.005, -0.002))
14417    snd_display("dsp.rb high: %p?", v)
14418  end
14419  b = make_highpass(hz2radians(1000.0), 20)
14420  map_channel(lambda do |y| highpass(b, y) end)
14421  sp = rough_spectrum(ind)
14422  if (not vequal(sp, vct(0.053, 0.774, 0.998, 0.997, 0.997, 0.996, 0.996, 0.996, 0.997, 1))) and
14423      (not vequal(sp, vct(0.053, 0.776, 1.000, 0.998, 0.998, 0.998, 0.998, 0.998, 0.998, 1)))
14424    snd_display("dsp hp rough spectrum: %s?", sp)
14425  end
14426  undo_edit
14427  #
14428  b = make_lowpass(hz2radians(1000.0), 10)
14429  v = make_vct!(20) do |i| lowpass(b, i.zero? ? 1.0 : 0.0) end
14430  unless vequal(v, vct(0.001, 0.002, 0.005, 0.011, 0.021, 0.034, 0.049, 0.065,
14431                       0.078, 0.087, 0.091, 0.087, 0.078, 0.065, 0.049, 0.034,
14432                       0.021, 0.011, 0.005, 0.002))
14433    snd_display("dsp.rb low: %s?", v)
14434  end
14435  b = make_lowpass(hz2radians(1000.0), 20)
14436  map_channel(lambda do |y| lowpass(b, y) end)
14437  sp = rough_spectrum(ind)
14438  unless vequal(sp, vct(1, 0.054, 0, 0, 0, 0, 0, 0, 0, 0))
14439    snd_display("dsp lp rough spectrum: %s?", sp)
14440  end
14441  undo_edit
14442  #
14443  b = make_bandpass(hz2radians(1500.0), hz2radians(2000.0), 10)
14444  v = make_vct!(20) do |i| bandpass(b, i.zero? ? 1.0 : 0.0) end
14445  unless vequal(v, vct(0.001, -0.001, -0.005, -0.011, -0.017, -0.019, -0.013, 0.003,
14446                       0.022, 0.039, 0.045, 0.039, 0.022, 0.003, -0.013, -0.019,
14447                       -0.017, -0.011, -0.005, -0.001))
14448    snd_display("dsp.rb bp: %s?", v)
14449  end
14450  b = make_bandpass(hz2radians(1500.0), hz2radians(2000.0), 20)
14451  map_channel(lambda do |y| bandpass(b, y) end)
14452  sp = rough_spectrum(ind)
14453  unless vequal(sp, vct(0.010, 1, 0.154, 0, 0, 0, 0, 0, 0, 0))
14454    snd_display("dsp bp rough spectrum: %s?", sp)
14455  end
14456  undo_edit
14457  #
14458  b = make_bandstop(hz2radians(1500.0), hz2radians(2000.0), 10)
14459  v = make_vct!(20) do |i| bandstop(b, i.zero? ? 1.0 : 0.0) end
14460  unless vequal(v, vct(-0.001, 0.001, 0.005, 0.011, 0.017, 0.019, 0.013, -0.003,
14461                       -0.022, -0.039, 0.955, -0.039, -0.022, -0.003, 0.013, 0.019,
14462                       0.017, 0.011, 0.005, 0.001))
14463    snd_display("dsp.rb bs: %s?", v)
14464  end
14465  b = make_bandstop(hz2radians(1500.0), hz2radians(2000.0), 20)
14466  map_channel(lambda do |y| bandstop(b, y) end)
14467  sp = rough_spectrum(ind)
14468  if (not vequal(sp, vct(0.904, 0.425, 0.821, 0.998, 0.997, 0.996, 0.996, 0.996, 0.997, 1))) and
14469      (not vequal(sp, vct(0.906, 0.425, 0.822, 1.000, 0.999, 0.998, 0.998, 0.998, 0.998, 1)))
14470    snd_display("dsp bp rough spectrum: %s?", sp)
14471  end
14472  undo_edit
14473  #
14474  b = make_differentiator(10)
14475  v = make_vct!(20) do |i| differentiator(b, i.zero? ? 1.0 : 0.0) end
14476  unless vequal(v, vct(-0.008, 0.011, -0.021, 0.039, -0.066, 0.108, -0.171, 0.270, -0.456, 0.977,
14477                       0.000, -0.977, 0.456, -0.270, 0.171, -0.108, 0.066, -0.039, 0.021, -0.011))
14478    snd_display("dsp.rb df: %s?", v)
14479  end
14480  b = make_differentiator(20)
14481  map_channel(lambda do |y| differentiator(b, y) end)
14482  sp = rough_spectrum(ind)
14483  unless vequal(sp, vct(0.004, 0.027, 0.075, 0.147, 0.242, 0.362, 0.506, 0.674, 0.864, 1))
14484    snd_display("dsp df rough spectrum: %s?", sp)
14485  end
14486  undo_edit
14487  #
14488  b = make_iir_high_pass_2(440.0)
14489  v = make_vct!(10) do |i| butter(b, i.zero? ? 1.0 : 0.0) end
14490  unless vequal(v, vct(0.915, -0.162, -0.146, -0.131, -0.117, -0.103, -0.09, -0.078, -0.066, -0.056))
14491    snd_display("iir-2 high: %s?", v)
14492  end
14493  b = make_iir_high_pass_2(1000.0)
14494  map_channel(lambda do |y| butter(b, y) end)
14495  sp = rough_spectrum(ind)
14496  if (not vequal(sp, vct(0.150, 0.833, 0.980, 0.994, 0.997, 0.998, 0.999, 0.998, 0.997, 1))) and
14497      (not vequal(sp, vct(0.150, 0.833, 0.981, 0.995, 0.998, 0.999, 1, 1, 0.998, 0.997)))
14498    snd_display("iir-2 hp rough spectrum: %s?", sp)
14499  end
14500  undo_edit
14501  #
14502  b = make_iir_low_pass_2(440.0)
14503  v = make_vct!(10) do |i| butter(b, i.zero? ? 1.0 : 0.0) end
14504  unless vequal(v, vct(0.004, 0.014, 0.026, 0.035, 0.043, 0.049, 0.053, 0.055, 0.057, 0.057))
14505    snd_display("iir-2 low: %s?", v)
14506  end
14507  b = make_iir_low_pass_2(1000.0)
14508  map_channel(lambda do |y| butter(b, y) end)
14509  sp = rough_spectrum(ind)
14510  unless vequal(sp, vct(1, 0.212, 0.024, 0.005, 0.001, 0, 0, 0, 0, 0))
14511    snd_display("iir-2 lp rough spectrum: %s?", sp)
14512  end
14513  undo_edit
14514  #
14515  b = make_iir_band_pass_2(440.0, 490.0)
14516  v = make_vct!(10) do |i| butter(b, i.zero? ? 1.0 : 0.0) end
14517  unless vequal(v, vct(0.007, 0.014, 0.013, 0.013, 0.012, 0.010, 0.009, 0.008, 0.006, 0.004))
14518    snd_display("iir bp-2 bandpass: %s?", v)
14519  end
14520  b = make_iir_band_pass_2(1000.0, 1500.0)
14521  map_channel(lambda do |y| butter(b, y) end)
14522  sp = rough_spectrum(ind)
14523  unless vequal(sp, vct(0.239, 1, 0.117, 0.041, 0.019, 0.010, 0.005, 0.003, 0.001, 0))
14524    snd_display("iir bp-2 rough spectrum: %s?", sp)
14525  end
14526  undo_edit
14527  #
14528  b = make_iir_band_stop_2(440.0, 500.0)
14529  v = make_vct!(10) do |i| butter(b, i.zero? ? 1.0 : 0.0) end
14530  v1 = vct(0.992, -0.017, -0.016, -0.015, -0.014,
14531           -0.012, -0.011, -0.009, -0.007, -0.005)
14532  snd_test_neq(v, v1, "iir bp-2 bandstop: %s?")
14533  b = make_iir_band_stop_2(1000.0, 1500.0)
14534  map_channel(lambda do |y| butter(b, y) end)
14535  sp = rough_spectrum(ind)
14536  if (not vequal(sp, vct(0.836, 0.525, 0.943, 0.979, 0.989, 0.994, 0.997, 0.997, 0.997, 1))) and
14537     (not vequal(sp, vct(0.838, 0.527, 0.945, 0.981, 0.991, 0.996, 0.999, 1, 0.999, 0.998)))
14538    snd_display("iir bs-2 rough spectrum: %s?", sp)
14539  end
14540  undo_edit
14541  #
14542  b = make_butter_hp(4, 440.0)
14543  v = make_vct!(10) do |i| butter(b, i.zero? ? 1.0 : 0.0) end
14544  v1 = vct(0.725, -0.466, -0.315, -0.196, -0.104,
14545           -0.036, 0.014, 0.047, 0.0685, 0.0775)
14546  v2 = vct(0.725, -0.466, -0.315, -0.196, -0.104,
14547           -0.035, 0.015, 0.049, 0.070, 0.081)
14548  v3 = vct(0.725, -0.466, -0.315, -0.196, -0.104,
14549           -0.035, 0.014, 0.049, 0.069, 0.079)
14550  if (not vequal(v, v1)) and (not vequal(v, v2)) and (not vequal(v, v3))
14551    snd_test_neq(v, v1, "butter hp (1)")
14552    snd_test_neq(v, v2, "butter hp (2)")
14553    snd_test_neq(v, v3, "butter hp (3)")
14554  end
14555  b = make_butter_hp(4, 1000.0)
14556  map_channel(lambda do |y| butter(b, y) end)
14557  sp = rough_spectrum(ind)
14558  if (not vequal(sp, vct(0.0505, 0.982, 1.0, 1.0, 0.998, 0.998, 0.999, 0.998, 0.996, 0.999))) and
14559     (not vequal(sp, vct(0.051, 0.982, 1.0, 1.0, 0.998, 0.998, 0.998, 0.999, 0.997, 0.995))) and
14560     (not vequal(sp, vct(0.051, 0.991, 1.0, 1.0, 0.998, 0.998, 0.999, 0.999, 0.997, 0.995))) and
14561     (not vequal(sp, vct(0.045, 0.970, 1.0, 1.0, 0.998, 0.998, 0.999, 0.999, 0.997, 0.995))) and
14562     (not vequal(sp, vct(0.052, 0.971, 1.0, 1.0, 0.998, 0.998, 0.999, 0.999, 0.997, 0.995)))
14563    snd_display("butter hp rough spectrum: %s?", sp)
14564  end
14565  undo_edit
14566  #
14567  b = make_butter_lp(4, 440.0)
14568  v = make_vct!(10) do |i| butter(b, i.zero? ? 1.0 : 0.0) end
14569  unless vequal(v, make_vct(10))
14570    snd_display("butter lp: %s?", v)
14571  end
14572  b = make_butter_lp(4, 1000.0)
14573  map_channel(lambda do |y| butter(b, y) end)
14574  sp = rough_spectrum(ind)
14575  if (not vequal(sp, vct(1, 0.035, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000))) and
14576      (not vequal(sp, vct(1, 0.038, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000)))
14577    snd_display("butter lp rough spectrum: %s?", sp)
14578  end
14579  undo_edit
14580  #
14581  b = make_butter_bp(4, 440.0, 500.0)
14582  v = make_vct!(10) do |i| butter(b, i.zero? ? 1.0 : 0.0) end
14583  unless vequal(v, make_vct(10))
14584    snd_display("butter bp: %s?", v)
14585  end
14586  b = make_butter_bp(4, 1000.0, 1500.0)
14587  map_channel(lambda do |y| butter(b, y) end)
14588  undo_edit
14589  #
14590  b = make_butter_bs(4, 440.0, 500.0)
14591  v = make_vct!(10) do |i| butter(b, i.zero? ? 1.0 : 0.0) end
14592  if (not vequal(v, vct(0.978, -0.043, -0.041, -0.038, -0.035,
14593                        -0.031, -0.026, -0.0225, -0.015, -0.0085))) and
14594      (not vequal(v, vct(0.978, -0.043, -0.041, -0.038, -0.035,
14595                         -0.031, -0.027, -0.022, -0.017, -0.011))) and
14596      (not vequal(v, vct(0.978, -0.043, -0.041, -0.038, -0.035,
14597                         -0.031, -0.027, -0.021, -0.014, -0.011)))
14598    snd_display("butter bs: %s?", v)
14599  end
14600  b = make_butter_bs(4, 1000.0, 1500.0)
14601  map_channel(lambda do |y| butter(b, y) end)
14602  undo_edit
14603  #
14604  revert_sound
14605  test_scanned_synthesis(0.1, 10000, 1.0, 0.1, 0.0)
14606  close_sound(ind)
14607end
14608
14609def test_08_06
14610  gen = make_sawtooth_wave(440.0)
14611  gen1 = make_sawtooth_wave(440.0)
14612  print_and_check(gen, "sawtooth-wave", "sawtooth-wave freq: 440.000Hz, phase: 3.142, amp: 1.000")
14613  v0 = Vct.new(10) do sawtooth_wave(gen, 0.0) end
14614  v1 = make_vct(10)
14615  v1.map! do |x| sawtooth_wave?(gen1) ? sawtooth_wave(gen1, 0.0) : -1.0 end
14616  unless vequal(v0, v1)
14617    snd_display("map sawtooth_wave: %s %s?", v0, v1)
14618  end
14619  unless sawtooth_wave?(gen)
14620    snd_display("%s not sawtooth_wave?", gen)
14621  end
14622  if fneq(gen.phase, 4.39538)
14623    snd_display("sawtooth_wave phase: %s?", gen.phase)
14624  end
14625  if fneq(gen.frequency, 440.0)
14626    snd_display("sawtooth_wave frequency: %s?", gen.frequency)
14627  end
14628  gen.frequency = 100.0
14629  if fneq(gen.frequency, 100.0)
14630    snd_display("sawtooth_wave set_frequency: %s?", gen.frequency)
14631  end
14632  if fneq(gen.scaler, 1.0)
14633    snd_display("sawtooth_wave scaler: %s?", gen.scaler)
14634  end
14635  gen.scaler = 0.5
14636  if fneq(gen.scaler, 0.5)
14637    snd_display("sawtooth_wave set_scaler: %s?", gen.scaler)
14638  end
14639  if fneq(v0[1], 0.04) or fneq(v0[8], 0.319)
14640    snd_display("sawtooth_wave output: %s?", v0)
14641  end
14642  test_gen_equal(make_sawtooth_wave(440.0),
14643                 make_sawtooth_wave(440.0),
14644                 make_sawtooth_wave(120.0))
14645  test_gen_equal(make_sawtooth_wave(440.0),
14646                 make_sawtooth_wave(440.0),
14647                 make_sawtooth_wave(440.0, 1.0, 1.0))
14648  test_gen_equal(make_sawtooth_wave(440.0),
14649                 make_sawtooth_wave(440.0),
14650                 make_sawtooth_wave(440.0, 0.5))
14651  gen1 = make_sawtooth_wave(100.0)
14652  gen2 = make_sawtooth_wave(-100.0)
14653  mx = 0.0
14654  100.times do mx = [mx, (gen1.run + gen2.run).abs].max end
14655  if fneq(mx, 0.0)
14656    snd_display("sawtooth_wave +-: %s?", mx)
14657  end
14658  #
14659  gen = make_square_wave(440.0)
14660  gen1 = make_square_wave(440.0)
14661  print_and_check(gen, "square-wave", "square-wave freq: 440.000Hz, phase: 0.000, amp: 1.000")
14662  v0 = make_vct!(10) do |i| square_wave(gen, 0.0) end
14663  v1 = make_vct(10)
14664  w = 1.0
14665  v1.map! do |x|
14666    w = gen1.width
14667    square_wave?(gen1) ? square_wave(gen1, 0.0) : -1.0
14668  end
14669  if fneq(w, 0.5)
14670    snd_display("mus_width opt: %s?", w)
14671  end
14672  unless vequal(v0, v1)
14673    snd_display("map square_wave: %s %s?", v0, v1)
14674  end
14675  unless square_wave?(gen)
14676    snd_display("%s not square_wave?", gen)
14677  end
14678  if fneq(gen.phase, 1.253787)
14679    snd_display("square_wave phase: %s?", gen.phase)
14680  end
14681  if fneq(gen.frequency, 440.0)
14682    snd_display("square_wave frequency: %s?", gen.frequency)
14683  end
14684  if fneq(gen.scaler, 1.0)
14685    snd_display("square_wave scaler: %s?", gen.scaler)
14686  end
14687  gen.scaler = 0.5
14688  if fneq(gen.scaler, 0.5)
14689    snd_display("square_wave set_scaler: %s?", gen.scaler)
14690  end
14691  if fneq(gen.width, 0.5)
14692    snd_display("square_wave width: %s?", gen.width)
14693  end
14694  gen.width = 0.75
14695  if fneq(gen.width, 0.75)
14696    snd_display("square_wave set_width: %s?", gen.width)
14697  end
14698  if fneq(v0[1], 1.0) or fneq(v0[8], 1.0)
14699    snd_display("square_wave output: %s?", v0)
14700  end
14701  test_gen_equal(make_square_wave(440.0),
14702                 make_square_wave(440.0),
14703                 make_square_wave(120.0))
14704  test_gen_equal(make_square_wave(440.0),
14705                 make_square_wave(440.0),
14706                 make_square_wave(440.0, 1.0, 1.0))
14707  test_gen_equal(make_square_wave(440.0),
14708                 make_square_wave(440.0),
14709                 make_square_wave(440.0, 0.5))
14710  old_srate = mus_srate
14711  set_mus_srate(500.0)
14712  gen = make_square_wave(100.0, -0.5, HALF_PI)
14713  v0 = make_vct!(20) do |i| gen.run end
14714  unless vequal(v0, vct(-0.5, -0.5, 0.0, 0.0, -0.5, -0.5, -0.5, 0.0, 0.0, -0.5,
14715                        -0.5, -0.5, 0.0, 0.0, -0.5, -0.5, -0.5, 0.0, 0.0, -0.5))
14716    snd_display("square_wave -0.5: %s?", v0)
14717  end
14718  set_mus_srate(old_srate)
14719  #
14720  gen = make_triangle_wave(440.0)
14721  gen1 = make_triangle_wave(440.0, 1.0, PI)
14722  gen2 = make_triangle_wave(440.0)
14723  print_and_check(gen, "triangle-wave", "triangle-wave freq: 440.000Hz, phase: 0.000, amp: 1.000")
14724  v0 = make_vct!(10) do |i| triangle_wave(gen, 0.0) end
14725  v1 = make_vct(10)
14726  v1.map! do |x| triangle_wave?(gen2) ? triangle_wave(gen2, 0.0) : -1.0 end
14727  unless vequal(v0, v1)
14728    snd_display("map triangle_wave: %s %s?", v0, v1)
14729  end
14730  unless triangle_wave?(gen)
14731    snd_display("%s not triangle_wave?", gen)
14732  end
14733  if fneq(gen.phase, 1.253787)
14734    snd_display("triangle_wave phase: %s?", gen.phase)
14735  end
14736  if fneq(gen1.phase, PI)
14737    snd_display("init triangle_wave phase: %s?", gen1.phase)
14738  end
14739  if fneq(gen.frequency, 440.0)
14740    snd_display("triangle_wave frequency: %s?", gen.frequency)
14741  end
14742  if fneq(gen.scaler, 1.0)
14743    snd_display("triangle_wave scaler: %s?", gen.scaler)
14744  end
14745  gen.scaler = 0.5
14746  if fneq(gen.scaler, 0.5)
14747    snd_display("triangle_wave set_scaler: %s?", gen.scaler)
14748  end
14749  if fneq(v0[1], 0.08) or fneq(v0[8], 0.639)
14750    snd_display("triangle_wave output: %s?", v0)
14751  end
14752  test_gen_equal(make_triangle_wave(440.0),
14753                 make_triangle_wave(440.0),
14754                 make_triangle_wave(120.0))
14755  test_gen_equal(make_triangle_wave(440.0),
14756                 make_triangle_wave(440.0),
14757                 make_triangle_wave(440.0, 1.0, 1.0))
14758  test_gen_equal(make_triangle_wave(440.0),
14759                 make_triangle_wave(440.0),
14760                 make_triangle_wave(440.0, 0.5))
14761  gen1 = make_triangle_wave(100.0)
14762  gen2 = make_triangle_wave(-100.0)
14763  mx = 0.0
14764  100.times do mx = [mx, (gen1.run + gen2.run).abs].max end
14765  if fneq(mx, 0.0)
14766    snd_display("triangle_wave +-: %s?", mx)
14767  end
14768  #
14769  gen = make_pulse_train(440.0)
14770  gen1 = make_pulse_train(440.0)
14771  print_and_check(gen, "pulse-train", "pulse-train freq: 440.000Hz, phase: 0.000, amp: 1.000")
14772  v0 = make_vct!(10) do |i| pulse_train(gen, 0.0) end
14773  v1 = make_vct(10)
14774  v1.map! do |x| pulse_train?(gen1) ? pulse_train(gen1, 0.0) : -1.0 end
14775  unless vequal(v0, v1)
14776    snd_display("map pulse_train: %s %s?", v0, v1)
14777  end
14778  unless pulse_train?(gen)
14779    snd_display("%s not pulse_train?", gen)
14780  end
14781  if fneq(gen.phase, 1.253787)
14782    snd_display("pulse_train phase: %s?", gen.phase)
14783  end
14784  if fneq(gen.frequency, 440.0)
14785    snd_display("pulse_train frequency: %s?", gen.frequency)
14786  end
14787  if fneq(gen.scaler, 1.0)
14788    snd_display("pulse_train scaler: %s?", gen.scaler)
14789  end
14790  gen.scaler = 0.5
14791  if fneq(gen.scaler, 0.5)
14792    snd_display("pulse_train set_scaler: %s?", gen.scaler)
14793  end
14794  if fneq(v0[0], 1.0) or fneq(v0[8], 0.0)
14795    snd_display("pulse_train output: %s?", v0)
14796  end
14797  test_gen_equal(make_pulse_train(440.0),
14798                 make_pulse_train(440.0),
14799                 make_pulse_train(120.0))
14800  test_gen_equal(make_pulse_train(440.0),
14801                 make_pulse_train(440.0),
14802                 make_pulse_train(440.0, 1.0, 1.0))
14803  test_gen_equal(make_pulse_train(440.0),
14804                 make_pulse_train(440.0),
14805                 make_pulse_train(440.0, 0.5))
14806  old_srate = mus_srate
14807  set_mus_srate(500.0)
14808  gen = make_pulse_train(100.0, -0.5, HALF_PI)
14809  v0 = make_vct!(20) do |i| gen.run end
14810  unless vequal(v0, vct(0.0, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.0, -0.5,
14811                        0.0, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.0, -0.5))
14812    snd_display("pulse_train -0.5: %s?", v0)
14813  end
14814  set_mus_srate(old_srate)
14815  #
14816  gen = make_two_pole(1200.0, 0.1)
14817  unless two_pole?(gen)
14818    snd_display("%s not 2-polar?", gen)
14819  end
14820  if gen.order != 2
14821    snd_display("2-polar order: %s?", gen.order)
14822  end
14823  if fneq(gen.a0, 1.0)
14824    snd_display("2-polar a0: %s?", gen.a0)
14825  end
14826  if fneq(gen.b1, -0.188)
14827    snd_display("2-polar b1: %s?", gen.b1)
14828  end
14829  if fneq(gen.b2, 0.01)
14830    snd_display("2-polar b2: %s?", gen.b2)
14831  end
14832  if fneq(gen.frequency, 1200.0)
14833    snd_display("2-polar freq: %s?", gen.frequency)
14834  end
14835  if fneq(gen.scaler, 0.1)
14836    snd_display("2-polar scaler: %s?", gen.scaler)
14837  end
14838  #
14839  gen = make_two_pole(:frequency, 1200.0, :radius, 0.1)
14840  unless two_pole?(gen)
14841    snd_display("%s not f2-polar?", gen)
14842  end
14843  if gen.order != 2
14844    snd_display("f2-polar order: %s?", gen.order)
14845  end
14846  if fneq(gen.a0, 1.0)
14847    snd_display("f2-polar a0: %s?", gen.a0)
14848  end
14849  if fneq(gen.b1, -0.188)
14850    snd_display("f2-polar b1: %s?", gen.b1)
14851  end
14852  if fneq(gen.b2, 0.01)
14853    snd_display("f2-polar b2: %s?", gen.b2)
14854  end
14855  if fneq(gen.frequency, 1200.0)
14856    snd_display("f2-polar freq: %s?", gen.frequency)
14857  end
14858  if fneq(gen.scaler, 0.1)
14859    snd_display("f2-polar scaler: %s?", gen.scaler)
14860  end
14861  #
14862  gen = make_two_zero(1200.0, 0.1)
14863  unless two_zero?(gen)
14864    snd_display("%s not 2-zp?", gen)
14865  end
14866  if gen.order != 2
14867    snd_display("2-zp order: %s?", gen.order)
14868  end
14869  if fneq(gen.a0, 1.0)
14870    snd_display("2-zp a0: %s?", gen.a0)
14871  end
14872  if fneq(gen.a1, -0.188)
14873    snd_display("2-zp a1: %s?", gen.a1)
14874  end
14875  if fneq(gen.a2, 0.01)
14876    snd_display("2-zp a2: %s?", gen.a2)
14877  end
14878  if fneq(gen.frequency, 1200.0)
14879    snd_display("2-zp freq: %s?", gen.frequency)
14880  end
14881  if fneq(gen.scaler, 0.1)
14882    snd_display("2-zp scaler: %s?", gen.scaler)
14883  end
14884  #
14885  gen = make_two_zero(:frequency, 1200.0, :radius, 0.1)
14886  unless two_zero?(gen)
14887    snd_display("%s not f2-zp?", gen)
14888  end
14889  if gen.order != 2
14890    snd_display("f2-zp order: %s?", gen.order)
14891  end
14892  if fneq(gen.a0, 1.0)
14893    snd_display("f2-zp a0: %s?", gen.a0)
14894  end
14895  if fneq(gen.a1, -0.188)
14896    snd_display("f2-zp a1: %s?", gen.a1)
14897  end
14898  if fneq(gen.a2, 0.01)
14899    snd_display("f2-zp a2: %s?", gen.a2)
14900  end
14901  if fneq(gen.frequency, 1200.0)
14902    snd_display("f2-zp freq: %s?", gen.frequency)
14903  end
14904  if fneq(gen.scaler, 0.1)
14905    snd_display("f2-zp scaler: %s?", gen.scaler)
14906  end
14907  #
14908  gen = make_formant(1200.0, 0.9)
14909  gen1 = make_formant(1200.0, 0.9)
14910  print_and_check(gen, "formant", "formant frequency: 1200.000, radius: 0.900")
14911  v0 = make_vct!(10) do |i| formant(gen, i.zero? ? 1.0 : 0.0) end
14912  v1 = make_vct(10)
14913  inp = -1
14914  v1.map! do |x|
14915    inp += 1
14916    formant?(gen1) ? formant(gen1, inp.zero? ? 1.0 : 0.0) : -1.0
14917  end
14918  unless vequal(v0, v1)
14919    snd_display("map formant: %s %s?", v0, v1)
14920  end
14921  unless formant?(gen)
14922    snd_display("%s not formant?", gen)
14923  end
14924  if gen.order != 2
14925    snd_display("formant order: %s?", gen.order)
14926  end
14927  if fneq(gen.frequency, 1200.0)
14928    snd_display("formant frequency: %s?", gen.frequency)
14929  end
14930  if fneq(v0[0], 0.095) or fneq(v0[1], 0.161)
14931    snd_display("formant output: %s?", v0)
14932  end
14933  if fneq(gen.scaler, 0.9)
14934    snd_display("formant gain: %s?", gen.scaler)
14935  end
14936  gen.scaler = 2.0
14937  if fneq(gen.scaler, 2.0)
14938    snd_display("formant set_gain: %s?", gen.scaler)
14939  end
14940  f1 = make_formant(1200.0, 0.9)
14941  f2 = make_formant(1200.0, 0.9)
14942  f3 = make_formant(600.0, 0.9)
14943  formant(f1, 1.0)
14944  formant(f2, 1.0)
14945  formant(f3, 1.0)
14946  test_gen_equal(f1, f2, f3)
14947  f1 = make_formant(1200.0, 0.9)
14948  f2 = make_formant(1200.0, 0.9)
14949  f3 = make_formant(1200.0, 0.99)
14950  formant(f1, 1.0)
14951  formant(f2, 1.0)
14952  formant(f3, 1.0)
14953  test_gen_equal(f1, f2, f3)
14954  #
14955  amps = vct(0.5, 0.25)
14956  ff = [make_formant(1000.0, 0.1), make_formant(100.0, 0.2)]
14957  fs = make_formant_bank(ff, amps)
14958  f0 = make_formant(1000.0, 0.1)
14959  f1 = make_formant(100.0, 0.2)
14960  v0 = make_vct!(10) do |i|
14961    val = i.zero? ? 1.0 : 0.0
14962    (0.5 * formant(f0, val)) + (0.25 * formant(f1, val))
14963  end
14964  v1 = make_vct!(10) do |i|
14965    val = i.zero? ? 1.0 : 0.0
14966    formant_bank(fs, val)
14967  end
14968  unless vequal(v0, v1)
14969    snd_display("formant_bank 1: %s %s?", v0, v1)
14970  end
14971  #
14972  amps = vct(0.5, 0.25)
14973  ff = [make_formant(1000.0, 0.1), make_formant(100.0, 0.2)]
14974  fs = make_formant_bank(ff, amps)
14975  v = make_vct!(5) do |i|
14976    val = i.zero? ? 1.0 : 0.0
14977    formant_bank(fs, val)
14978  end
14979  unless vequal(v, vct(0.368, 0.095, -0.346, -0.091, -0.020))
14980    snd_display("run formant_bank: %s?", v)
14981  end
14982  #
14983  ob = open_sound("oboe.snd")
14984  poltergeist = lambda do |frek, amp, r, gain, frek_env, r_env|
14985    # test courtesy of Anders Vinjar
14986    filt = make_formant(frek, r)
14987    fe = make_env(:envelope, frek_env, :length, framples, :offset, frek)
14988    re = make_env(:envelope, r_env, :length, framples, :offset, r)
14989    lambda do |y|
14990      outval = gain * formant(filt, amp * y)
14991      mus_set_formant_radius_and_frequency(filt, env(re), env(fe))
14992      outval
14993    end
14994  end
14995  map_chan(poltergeist.call(300, 0.1, 0.0, 30.0, [0, 100, 1, 4000], [0, 0.99, 1, 0.9]))
14996  play(ob, :wait, true)
14997  close_sound(ob)
14998end
14999
15000def test_08_08
15001  [[:Hamming_window, 0.0,
15002     vct(0.080, 0.115, 0.215, 0.364, 0.540, 0.716, 0.865, 1.000,
15003        1.000, 0.865, 0.716, 0.540, 0.364, 0.215, 0.115, 0.080)],
15004   [:Rectangular_window, 0.0,
15005     vct(1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000,
15006         1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000)],
15007   [:Hann_window, 0.0,
15008     vct(0.000, 0.038, 0.146, 0.309, 0.500, 0.691, 0.854, 1.000,
15009         1.000, 0.854, 0.691, 0.500, 0.309, 0.146, 0.038, 0.000)],
15010   [:Welch_window, 0.0,
15011     vct(0.000, 0.234, 0.438, 0.609, 0.750, 0.859, 0.938, 1.000,
15012         1.000, 0.938, 0.859, 0.750, 0.609, 0.438, 0.234, 0.000)],
15013   [:Connes_window, 0.0,
15014     vct(0.000, 0.055, 0.191, 0.371, 0.562, 0.739, 0.879, 1.000,
15015         1.000, 0.879, 0.739, 0.562, 0.371, 0.191, 0.055, 0.000)],
15016   [:Parzen_window, 0.0,
15017     vct(0.000, 0.125, 0.250, 0.375, 0.500, 0.625, 0.750, 1.000,
15018         1.000, 0.750, 0.625, 0.500, 0.375, 0.250, 0.125, 0.000)],
15019   [:Bartlett_window, 0.0,
15020     vct(0.000, 0.125, 0.250, 0.375, 0.500, 0.625, 0.750, 1.000,
15021         1.000, 0.750, 0.625, 0.500, 0.375, 0.250, 0.125, 0.000)],
15022   [:Blackman2_window, 0.0,
15023     vct(0.005, 0.020, 0.071, 0.177, 0.344, 0.558, 0.775, 1.000,
15024         1.000, 0.775, 0.558, 0.344, 0.177, 0.071, 0.020, 0.005)],
15025   [:Blackman3_window, 0.0,
15026     vct(0.000, 0.003, 0.022, 0.083, 0.217, 0.435, 0.696, 1.000,
15027         1.000, 0.696, 0.435, 0.217, 0.083, 0.022, 0.003, 0.000)],
15028   [:Blackman4_window, 0.0,
15029     vct(0.002, 0.002, 0.003, 0.017, 0.084, 0.263, 0.562, 1.000,
15030         1.000, 0.562, 0.263, 0.084, 0.017, 0.003, 0.002, 0.002)],
15031   [:Blackman5_window, 0.0,
15032     vct(0.000, 0.000, 0.003, 0.022, 0.097, 0.280, 0.574, 1.000,
15033         1.000, 0.574, 0.280, 0.097, 0.022, 0.003, 0.000, 0.000)],
15034   [:Blackman6_window, 0.0,
15035     vct(0.000, 0.000, 0.001, 0.011, 0.064, 0.223, 0.520, 1.000,
15036         1.000, 0.520, 0.223, 0.064, 0.011, 0.001, 0.000, 0.000)],
15037   [:Blackman7_window, 0.0,
15038     vct(0.000, 0.000, 0.000, 0.006, 0.042, 0.177, 0.471, 1.000,
15039         1.000, 0.471, 0.177, 0.042, 0.006, 0.000, 0.000, 0.000)],
15040   [:Blackman8_window, 0.0,
15041     vct(0.000, 0.000, 0.000, 0.003, 0.028, 0.141, 0.426, 1.000,
15042         1.000, 0.426, 0.141, 0.028, 0.003, 0.000, 0.000, 0.000)],
15043   [:Blackman9_window, 0.0,
15044     vct(0.000, 0.000, 0.000, 0.001, 0.018, 0.112, 0.385, 1.000,
15045         1.000, 0.385, 0.112, 0.018, 0.001, 0.000, 0.000, 0.000)],
15046   [:Blackman10_window, 0.0,
15047     vct(0.000, 0.000, 0.000, 0.001, 0.012, 0.089, 0.349, 1.000,
15048         1.000, 0.349, 0.089, 0.012, 0.001, 0.000, 0.000, 0.000)],
15049   [:Rv2_window, 0.0,
15050     vct(0.000, 0.001, 0.021, 0.095, 0.250, 0.478, 0.729, 1.000,
15051         1.000, 0.729, 0.478, 0.250, 0.095, 0.021, 0.001, 0.000)],
15052   [:Rv3_window, 0.0,
15053     vct(0.000, 0.000, 0.003, 0.029, 0.125, 0.330, 0.622, 1.000,
15054         1.000, 0.622, 0.330, 0.125, 0.029, 0.003, 0.000, 0.000)],
15055   [:Rv4_window, 0.0,
15056     vct(0.000, 0.000, 0.000, 0.009, 0.062, 0.228, 0.531, 1.000,
15057         1.000, 0.531, 0.228, 0.062, 0.009, 0.000, 0.000, 0.000)],
15058   [:Exponential_window, 0.0,
15059     vct(0.000, 0.087, 0.181, 0.283, 0.394, 0.515, 0.646, 0.944,
15060         0.944, 0.646, 0.515, 0.394, 0.283, 0.181, 0.087, 0.000)],
15061   [:Riemann_window, 0.0,
15062     vct(0.000, 0.139, 0.300, 0.471, 0.637, 0.784, 0.900, 1.000,
15063         1.000, 0.900, 0.784, 0.637, 0.471, 0.300, 0.139, 0.000)],
15064   [:Kaiser_window, 2.5,
15065     vct(0.304, 0.426, 0.550, 0.670, 0.779, 0.871, 0.941, 1.000,
15066         1.000, 0.941, 0.871, 0.779, 0.670, 0.550, 0.426, 0.304)],
15067   [:Cauchy_window, 2.5,
15068     vct(0.138, 0.173, 0.221, 0.291, 0.390, 0.532, 0.719, 1.000,
15069         1.000, 0.719, 0.532, 0.390, 0.291, 0.221, 0.173, 0.138)],
15070   [:Poisson_window, 2.5,
15071     vct(0.082, 0.112, 0.153, 0.210, 0.287, 0.392, 0.535, 1.000,
15072         1.000, 0.535, 0.392, 0.287, 0.210, 0.153, 0.112, 0.082)],
15073   [:Gaussian_window, 1.0,
15074     vct(0.607, 0.682, 0.755, 0.823, 0.882, 0.932, 0.969, 1.000,
15075         1.000, 0.969, 0.932, 0.882, 0.823, 0.755, 0.682, 0.607)],
15076   [:Tukey_window, 0.0,
15077     vct(0.000, 0.038, 0.146, 0.309, 0.500, 0.691, 0.854, 1.000,
15078         1.000, 0.854, 0.691, 0.500, 0.309, 0.146, 0.038, 0.000)],
15079   [:Hann_poisson_window, 0.0,
15080     vct(0.000, 0.038, 0.146, 0.309, 0.500, 0.691, 0.854, 1.000,
15081         1.000, 0.854, 0.691, 0.500, 0.309, 0.146, 0.038, 0.000)],
15082  ].each do |win, beta, vals|
15083    Snd.catch do
15084      res = make_fft_window(Module.const_get(win), 16, beta)
15085      unless vequal(res, vals)
15086        snd_display("%s: %s?", win, res)
15087      end
15088    end
15089  end
15090  if $with_test_gsl
15091    [[:Samaraki_window, 0.0,
15092       vct(1.000, 0.531, 0.559, 0.583, 0.604, 0.620, 0.631, 0.638,
15093           0.640, 0.638, 0.631, 0.620, 0.604, 0.583, 0.559, 0.531)],
15094     [:Ultraspherical_window, 0.0,
15095       vct(1.000, 0.033, 0.034, 0.035, 0.036, 0.036, 0.037, 0.037,
15096           0.037, 0.037, 0.037, 0.036, 0.036, 0.035, 0.034, 0.033)],
15097     [:Dolph_chebyshev_window, 0.0,
15098       vct(1.000, 0.033, 0.034, 0.035, 0.036, 0.036, 0.037, 0.037,
15099           0.037, 0.037, 0.037, 0.036, 0.036, 0.035, 0.034, 0.033)],
15100     [:Dolph_chebyshev_window, 1.0,
15101       vct(1.000, 0.274, 0.334, 0.393, 0.446, 0.491, 0.525, 0.546,
15102           0.553, 0.546, 0.525, 0.491, 0.446, 0.393, 0.334, 0.274)]
15103    ].each do |win, beta, vals|
15104      Snd.catch do
15105        res = make_fft_window(Module.const_get(win), 16, beta)
15106        unless vequal(res, vals)
15107          snd_display("%s: %s?", win, res)
15108        end
15109      end
15110    end
15111    [[:Ultraspherical_window, 0.0, 0.0, :Dolph_chebyshev_window, 0.0, 0.0],
15112     [:Ultraspherical_window, 0.0, 1.0, :Samaraki_window,        0.0, 0.0],
15113     [:Ultraspherical_window, 0.5, 0.0, :Dolph_chebyshev_window, 0.5, 0.0],
15114     [:Ultraspherical_window, 0.5, 1.0, :Samaraki_window,        0.5, 0.0]
15115    ].each do |win1, beta1, alpha1, win2, beta2, alpha2|
15116      Snd.catch do
15117        val1 = make_fft_window(Module.const_get(win1), 16, beta1, alpha1)
15118        val2 = make_fft_window(Module.const_get(win2), 16, beta2, alpha2)
15119        unless vequal(val1, vals2)
15120          snd_display("%s/%s %s: %s %s?", win1, win2, beta1, val1, val2)
15121        end
15122      end
15123    end
15124    val1 = dolph(16, 1.0)
15125    val2 = make_fft_window(Dolph_chebyshev_window, 16, 1.0)
15126    unless vequal(val1, val2)
15127      snd_display("dolph/dolph 1: %s %s?", val1, val2)
15128    end
15129    val1 = dolph_1(16, 1.0).to_vct
15130    val2 = make_fft_window(Dolph_chebyshev_window, 16, 1.0)
15131    unless vequal(val1, val2)
15132      snd_display("dolph_1/dolph 1: %s %s?", val1, val2)
15133    end
15134  end # $with_test_gsl
15135  #
15136  gen = make_env(:envelope, [0, 0, 1, 1, 2, 0], :scaler, 0.5, :length, 11)
15137  gen1 = make_env(:envelope, [0, 0, 1, 1, 2, 0], :scaler, 0.5, :length, 11)
15138  print_and_check(gen,
15139                  "env",
15140                  "env linear, pass: 0 (dur: 11), index: 0, scaler: 0.5000, offset: 0.0000, data: [0 0 1 1 2 0]")
15141  unless env?(gen)
15142    snd_display("%s not env?", gen)
15143  end
15144  if fneq(gen.scaler, 0.5)
15145    snd_display("env scaler: %s?", gen.scaler)
15146  end
15147  if fneq(gen.increment, 1.0)
15148    snd_display("env base (1.0): %s?", gen.increment)
15149  end
15150  if gen.length != 11
15151    snd_display("env length: %s?", gen.length)
15152  end
15153  v0 = make_vct!(10) do env(gen) end
15154  v1 = make_vct(10)
15155  off = 123.0
15156  v1.map! do |x|
15157    off = gen1.offset
15158    env?(gen1) ? env(gen1) : -1.0
15159  end
15160  if fneq(off, 0.0)
15161    snd_display("mus_offset opt: %s?", off)
15162  end
15163  unless vequal(v0, v1)
15164    snd_display("map env: %s %s?", v0, v1)
15165  end
15166  if fneq(v0[0], 0.0) or fneq(v0[1], 0.1) or fneq(v0[6], 0.4)
15167    snd_display("env output: %s?", v0)
15168  end
15169  if fneq(res = env_interp(1.6, gen), 0.2)
15170    snd_display("env_interp %s at 1.6: %s?", gen, res)
15171  end
15172  gen = make_env(:envelope, [0, 1, 1, 0], :base, 32.0, :length, 11)
15173  if fneq(gen.increment, 32.0)
15174    snd_display("env base (32.0): %s?", gen.increment)
15175  end
15176  v0.map! do |val| env(gen) end
15177  if fneq(v0[0], 1.0) or fneq(v0[1], 0.698) or fneq(v0[8], 0.032)
15178    snd_display("%s output: %s?", gen, v0)
15179  end
15180  gen = make_env(:envelope, [0, 1, 1, 0], :base, 0.0325, :length, 11)
15181  if fneq(gen.increment, 0.0325)
15182    snd_display("env base (0.0325): %s?", gen.increment)
15183  end
15184  v0.map! do |val| env(gen) end
15185  if fneq(v0[0], 1.0) or fneq(v0[1], 0.986) or fneq(v0[8], 0.513)
15186    snd_display("%s output: %s?", gen, v0)
15187  end
15188  gen = make_env(:envelope, [0, 1, 1, 0.5, 2, 0], :base, 0.0, :length, 11, :offset, 1.0)
15189  if fneq(gen.offset, 1.0)
15190    snd_display("mus_offset: %s?", gen.offset)
15191  end
15192  if fneq(gen.increment, 0.0)
15193    snd_display("env base (0.0): %s?", gen.increment)
15194  end
15195  v0.map_with_index! do |val, i|
15196    if i == 3
15197      if gen.location != 3
15198        snd_display("env location: %s?", gen.location)
15199      end
15200    end
15201    env(gen)
15202  end
15203  if fneq(v0[0], 2.0) or fneq(v0[6], 1.5) or fneq(v0[8], 1.5)
15204    snd_display("%s output: %s?", gen, v0)
15205  end
15206  if fneq(res = env_interp(1.5, gen), 1.5)
15207    snd_display("env_interp %s at 1.5: %s?", gen, res)
15208  end
15209  gen.location = 6
15210  if gen.location != 6
15211    snd_display("set_mus_location (6): %s?", gen.location)
15212  end
15213  if fneq(val = env(gen), 1.5)
15214    snd_display("set_mus_location 6 -> %s (1.5)?", val)
15215  end
15216  gen.location = 0
15217  if fneq(val = env(gen), 2.0)
15218    snd_display("set_mus_location 0 -> %s (2.0)?", val)
15219  end
15220  gen = make_env([0, 0, 1, -1, 2, 0], :length, 11)
15221  5.times do |i|
15222    if fneq(val = env(gen), i / -5.0)
15223      snd_display("neg env: %s %s?", i, val)
15224    end
15225  end
15226  5.times do |i|
15227    if fneq(val = env(gen), -1.0 + i / 5.0)
15228      snd_display("neg env: %s %s?", i, val)
15229    end
15230  end
15231  gen = make_env([0, 0, 1, -1, 2, 0], :length, 11, :base, 0.5)
15232  vct(0.0, -0.14869, -0.31950, -0.51571, -0.74110,
15233      -1.0, -0.74110, -0.51571, -0.31950, -0.14869).each_with_index do |val, i|
15234    if fneq(res = env(gen), val)
15235      snd_display("neg exp env: %s %s?", i, res)
15236    end
15237  end
15238  mus_apply(gen)
15239  e = make_env([0, 0, 1, 1], :length, 10)
15240  if fneq(res = env_interp(1.0, e), 1.0)
15241    snd_display("env_interp 0011 at 1: %s?", res)
15242  end
15243  if fneq(res = env_interp(2.0, e), 1.0)
15244    snd_display("env_interp 0011 at 2: %s?", res)
15245  end
15246  if fneq(res = env_interp(0.0, e), 0.0)
15247    snd_display("env_interp 0011 at 0: %s?", res)
15248  end
15249  if fneq(res = env_interp(0.444, e), 0.444)
15250    snd_display("env_interp 0011 at 0.444: %s?", res)
15251  end
15252  e.reset
15253  10.times do |i|
15254    if fneq(val = env(e), i * 0.111111)
15255      snd_display("ramp env over 10: %s at %s?", val, i)
15256    end
15257  end
15258  e = make_env([0, 0, 0.5, 0.5, 1, 1], :base, 32, :length, 10)
15259  x = 0.0
15260  vct(0, 0.0243, 0.0667, 0.1412, 0.2716, 0.5, 0.5958, 0.709, 0.8425, 1).each_with_index do |val, i|
15261    if fneq(res = env_interp(x, e), val)
15262      snd_display("[0, 0.5, 1] env_interp over 10: %s at %s (%s)", res, i, val)
15263    end
15264    x += 0.111111
15265  end
15266  e = make_env([0, -1.0, 1, 1], :base, 32, :length, 10)
15267  x = 0.0
15268  vct(-1.0, -0.9697, -0.9252, -0.8597, -0.7635,
15269      -0.6221, -0.4142, -0.1088, 0.34017, 1.0).each_with_index do |val, i|
15270    if fneq(res = env_interp(x, e), val)
15271      snd_display("[-1, 1] env_interp over 10: %s at %s (%s)", res, i, val)
15272    end
15273    x += 0.111111
15274  end
15275  e = make_env([0, -1.0, 0.5, 0.5, 1, 0], :base, 32, :length, 10)
15276  x = 0.0
15277  vct(-1.0, -0.952, -0.855, -0.661, -0.274,
15278      0.5, 0.356, 0.226, 0.107, 0.0).each_with_index do |val, i|
15279    if fneq(res = env_interp(x, e), val)
15280      snd_display("[-1, 0.5, 0] env_interp over 10: %s at %s (%s)", res, i, val)
15281    end
15282    x += 0.111111
15283  end
15284  e = make_env([0, 0.0, 0.5, 0.5, 1, -1.0], :base, 32, :length, 10)
15285  x = 0.0
15286  vct(0, 0.085, 0.177, 0.276, 0.384, 0.5, -0.397, -0.775, -0.933, -1).each_with_index do |val, i|
15287    if fneq(res = env_interp(x, e), val)
15288      snd_display("[0, 0.5, -1] env_interp over 10: %s at %s (%s)", res, i, val)
15289    end
15290    x += 0.111111
15291  end
15292  #
15293  e = make_env([0, 0, 1, 1], :length, 10, :base, 4)
15294  if fneq(res = env_interp(1.0, e), 1.0)
15295    snd_display("env_interp 0011 4 at 1: %s?", res)
15296  end
15297  if fneq(res = env_interp(0.0, e), 0.0)
15298    snd_display("env_interp 0011 4 at 0: %s?", res)
15299  end
15300  if fneq(res = env_interp(0.45, e), 0.2839)
15301    snd_display("env_interp 0011 4 at 0.45: %s?", res)
15302  end
15303  e = make_env([0, 0, 1, 1], :length, 10, :base, 0.2)
15304  if fneq(res = env_interp(1.0, e), 1.0)
15305    snd_display("env_interp 0011 2 at 1: %s?", res)
15306  end
15307  if fneq(res = env_interp(0.0, e), 0.0)
15308    snd_display("env_interp 0011 2 at 0: %s?", res)
15309  end
15310  if fneq(res = env_interp(0.45, e), 0.6387)
15311    snd_display("env_interp 0011 2 at 0.45: %s?", res)
15312  end
15313  e = make_env([0, 0, 1, 1], :length, 10, :offset, 2.0)
15314  e.offset = 3.0
15315  if fneq(e.offset, 3.0)
15316    snd_display("set_mus_offset env: %s?", e.offset)
15317  end
15318  #
15319  e1 = make_env([0, 0, 1, 1], :base, 32.0, :length, 11)
15320  vct(0, 0.013, 0.032, 0.059, 0.097, 0.150, 0.226, 0.333, 0.484, 0.698, 1).each do |val|
15321    if fneq(res = env(e1), val)
15322      snd_display("exp env direct (32.0): %s %s", res, val)
15323    end
15324  end
15325  e1 = make_env([0, 1, 1, 2], :base, 32.0, :length, 11)
15326  vct(1, 1.013, 1.032, 1.059, 1.097, 1.15, 1.226, 1.333, 1.484, 1.698, 2).each do |val|
15327    if fneq(res = env(e1), val)
15328      snd_display("exp env direct (32.0) offset: %s %s", res, val)
15329    end
15330  end
15331  e1 = make_env([0, 1, 1, 2], :base, 32.0, :length, 11)
15332  vct(1, 1.013, 1.032, 1.059, 1.097, 1.15, 1.226, 1.333, 1.484, 1.698, 2).each do |val|
15333    if fneq(res = env(e1), val)
15334      snd_display("exp env direct (32.0) offset (and dur): %s %s", res, val)
15335    end
15336  end
15337  e1 = make_env([0, 0, 1, 1], :base, 0.032, :length, 11)
15338  vct(0.000, 0.301, 0.514, 0.665, 0.772, 0.848, 0.902, 0.940, 0.967, 0.986, 1.0).each do |val|
15339    if fneq(res = env(e1), val)
15340      snd_display("exp env direct (0.032): %s %s", res, val)
15341    end
15342  end
15343  #
15344  e1 = make_env([0, 0, 1, 1], :base, 0.03125, :length, 11)
15345  e2 = make_env([0, 0, 1, 1, 2, 0], :base, 32.0, :length, 11)
15346  e3 = make_env([0, 0, 0.1, 1, 2, 0], :base, 1.1, :length, 101)
15347  10.times do |i|
15348    lv1 = env_interp(i * 0.1, e1)
15349    lv2 = env(e1)
15350    lv3 = env_interp(i * 0.2, e2)
15351    lv4 = env(e2)
15352    if fneq(lv1, lv2)
15353      snd_display("env_interp[rmp %s]: %s (%s)?", i * 0.1, lv1, lv2)
15354    end
15355    if fneq(lv3, lv4)
15356      snd_display("env_interp[pyr %s]: %s (%s)?", i * 0.2, lv3, lv4)
15357    end
15358  end
15359  100.times do |i|
15360    lv5 = env_interp(i * 0.02, e3)
15361    lv6 = env(e3)
15362    if fneq(lv5, lv6)
15363      snd_display("env_interp[tri %s]: %s (%s)?", i * 0.02, lv5, lv6)
15364    end
15365  end
15366  #
15367  e1 = make_env([0, 0, 1, 1, 2, 0], :length, 10)
15368  lv1 = make_vct!(11) do env(e1) end
15369  lv2 = make_vct!(11) do env(e1) end
15370  e1.reset
15371  lv3 = make_vct!(11) do env(e1) end
15372  unless vequal(lv1, lv3)
15373    snd_display("mus_reset: %s %s?", lv1, lv3)
15374  end
15375  unless vequal(lv2, make_vct(11))
15376    snd_display("mus_reset 1: %s?", lv2)
15377  end
15378  #
15379  gen = make_env([0, 0, 1, 1, 2, 0], :length, 11)
15380  4.times do env(gen) end
15381  if fneq(res = env(gen), 0.8)
15382    snd_display("env(5): %s?", res)
15383  end
15384  gen.reset
15385  4.times do env(gen) end
15386  if fneq(res = env(gen), 0.8)
15387    snd_display("mus_reset (via reset): %s?", res)
15388  end
15389  gen.location = 6
15390  if fneq(res = env(gen), 0.8)
15391    snd_display("set_mus_location 6 -> %s (0.8)?", res)
15392  end
15393  gen = make_env([0, 0, 1, 1], :base, 0.032, :length, 12)
15394  gen.location = 5
15395  if fneq(res = env(gen), 0.817)
15396    snd_display("set env location with base: %s %s?", res, gen)
15397  end
15398  gen = make_env([0, 0, 1, 1], :base, 0.032, :length, 12)
15399  gen.location = 5
15400  if fneq(res = env(gen), 0.817)
15401    snd_display("set env location with base and dur: %s %s?", res, gen)
15402  end
15403  #
15404  test_gen_equal(make_env([0, 0, 1, 1, 2, 0], :scaler, 0.50, :length,  10),
15405                 make_env([0, 0, 1, 1, 2, 0], :scaler, 0.50, :length,  10),
15406                 make_env([0, 0, 1, 1, 2, 0], :scaler, 0.25, :length,  10))
15407  test_gen_equal(make_env([0, 0, 1, 1, 2, 0], :scaler, 0.50, :length,  10),
15408                 make_env([0, 0, 1, 1, 2, 0], :scaler, 0.50, :length,  10),
15409                 make_env([0, 0, 1, 1, 2, 0], :scaler, 0.50, :length,  11))
15410  test_gen_equal(make_env([0, 0, 1, 1, 2, 0], :scaler, 0.50, :length,  10),
15411                 make_env([0, 0, 1, 1, 2, 0], :scaler, 0.50, :length,  10),
15412                 make_env([0, 0, 1, 1, 3, 0], :scaler, 0.50, :length,  10))
15413  #
15414  if (res = Snd.catch do make_env(:envelope, []) end).first != :no_data
15415    snd_display("make_env null env: %s", res.inspect)
15416  end
15417  if (res = Snd.catch do make_env(:length, 0) end).first != :no_data
15418    snd_display("make_env no env: %s", res.inspect)
15419  end
15420  if (res = Snd.catch do make_env(:envelope, [0, 0], :length, -1) end).first != :out_of_range
15421    snd_display("make_env bad end: %s", res.inspect)
15422  end
15423  if (res = Snd.catch do make_env(:envelope, [0, 0], :length, -1) end).first != :out_of_range
15424    snd_display("make_env bad dur: %s", res.inspect)
15425  end
15426  if (res = Snd.catch do make_env(:envelope, [0, 0], :duration, -1.0) end).first != :out_of_range
15427    snd_display("make_env bad duration: %s", res.inspect)
15428  end
15429  if (res = Snd.catch do make_env(:envelope, [0, 0], :base, -1.0) end).first != :out_of_range
15430    snd_display("make_env bad base: %s", res.inspect)
15431  end
15432  if (res = Snd.catch do make_env(:envelope, [1, 1, 0, 0], :length, 11) end).first != :mus_error
15433    snd_display("make_env bad env 1 1 0 0: %s", res.inspect)
15434  end
15435  if (res = Snd.catch do make_env(:envelope, [0, 1, -1, 0], :length, 11) end).first != :mus_error
15436    snd_display("make_env bad env 0 1 -1 0: %s", res.inspect)
15437  end
15438  if (res = Snd.catch do
15439        make_env(:envelope, [0, 1, 1, 0], :length, 11, :length, 10)
15440      end).first != :mus_error
15441    snd_display("make_env bad end/dur: %s", res.inspect)
15442  end
15443end
15444
15445def test_08_09
15446  gen = make_table_lookup(440.0, :wave, partials2wave([1, 1, 2, 1]))
15447  gen1 = make_table_lookup(440.0, :wave, partials2wave([1, 1, 2, 1], make_vct(512)))
15448  gen3 = make_table_lookup
15449  gen4 = make_table_lookup(440.0, :wave, partials2wave([1, 1, 2, 1]))
15450  print_and_check(gen,
15451                  "table-lookup",
15452                  "table-lookup freq: 440.000Hz, phase: 0.000, length: 512, interp: linear")
15453  if gen.length != 512
15454    snd_display("table_lookup length: %s?", gen.length)
15455  end
15456  if gen3.length != 512
15457    snd_display("default table_lookup length: %s?", gen3.length)
15458  end
15459  v0 = make_vct!(10) do table_lookup(gen, 0.0) end
15460  v1 = make_vct!(10) do mus_apply(gen1, 0.0) end
15461  v2 = make_vct(10)
15462  v2.map! do |x| table_lookup?(gen4) ? table_lookup(gen4) : -1.0 end
15463  unless vequal(v0, v2)
15464    snd_display("map table_lookup: %s %s?", v0, v2)
15465  end
15466  gen4 = make_table_lookup(440.0, :wave, partials2wave([1, 1, 2, 1]))
15467  v2.map! do |x| table_lookup(gen4) end
15468  unless vequal(v0, v2)
15469    snd_display("map table_lookup (no fm): %s %s?", v0, v2)
15470  end
15471  unless table_lookup?(gen)
15472    snd_display("%s not table_lookup?", gen)
15473  end
15474  unless vct?(gen.data)
15475    snd_display("mus_data table_lookup: %s?", gen.data)
15476  end
15477  if fneq(gen.phase, 1.253787)
15478    snd_display("table_lookup phase: %s?", gen.phase)
15479  end
15480  gen.phase = 1.0
15481  if fneq(gen.phase, 1.0)
15482    snd_display("table_lookup set_phase: %s?", gen.phase)
15483  end
15484  if fneq(gen.frequency, 440.0)
15485    snd_display("table_lookup frequency: %s?", gen.frequency)
15486  end
15487  gen.frequency = 100.0
15488  if fneq(gen.frequency, 100.0)
15489    snd_display("table_lookup set_frequency: %s?", gen.frequency)
15490  end
15491  if fneq(v0[1], 0.373) or fneq(v0[8], 1.75)
15492    snd_display("table_lookup output: %s?", v0)
15493  end
15494  unless vequal(v0, v1)
15495    snd_display("mus_apply table_lookup: %s %s?", v0, v1)
15496  end
15497  gen = make_table_lookup(440.0, :wave, phase_partials2wave([1, 1, 0, 2, 1, HALF_PI]))
15498  v0.map! do |val| table_lookup(gen, 0.0) end
15499  if fneq(v0[1], 1.094) or fneq(v0[8], 0.421)
15500    snd_display("table_lookup phase output: %s?", v0)
15501  end
15502  if fneq(vct_peak(partials2wave([1, 1, 2, 1])), 1.76035475730896) or
15503      fneq(vct_peak(partials2wave([1, 1, 2, 1], false, true)), 1.0) or
15504      fneq(vct_peak(partials2wave([1, 1, 2, 1, 3, 1, 4, 1], false, true)), 1.0)
15505    snd_display("normalized partials?")
15506  end
15507  gen.data = phase_partials2wave([1, 1, 0, 2, 1, HALF_PI], false, true)
15508  #
15509  if (res = Snd.catch do phase_partials2wave([1, 0.3, 2, 0.2]) end).first != :wrong_type_arg
15510    snd_display("bad length arg to phase_partials2wave: %s", res.inspect)
15511  end
15512  if (res = Snd.catch do phase_partials2wave(["hiho", 0.3, 2, 0.2]) end).first != :wrong_type_arg
15513    snd_display("bad harmonic arg to phase_partials2wave: %s", res.inspect)
15514  end
15515  if (res = Snd.catch do phase_partials2wave([]) end).first != :no_data
15516    snd_display("nil list to phase_partials2wave: %s", res.inspect)
15517  end
15518  phase_partials2wave([1, 1, 0], make_vct(16), false).each_with_index do |val, i|
15519    if fneq(val, res = sin((TWO_PI * i) / 16.0))
15520      snd_display("phase_partials2wave 1 1 0 at %s: %s %s?", i, val, res)
15521    end
15522  end
15523  phase_partials2wave([1, 1, 0.25 * PI], make_vct(16), false).each_with_index do |val, i|
15524    if fneq(val, res = sin(0.25 * PI +  ((TWO_PI * i) / 16.0)))
15525      snd_display("phase_partials2wave 1 1 0.25 at %s: %s %s?", i, val, res)
15526    end
15527  end
15528  phase_partials2wave([1, 1, 0, 2, 1, 0], make_vct(16), false).each_with_index do |val, i|
15529    if fneq(val, res = sin((TWO_PI * i) / 16.0) +  sin((2.0 * TWO_PI * i) / 16.0))
15530      snd_display("phase_partials2wave 1 1 0 2 1 0 at %s: %s %s?", i, val, res)
15531    end
15532  end
15533  phase_partials2wave([1, 1, 0, 2, 1, HALF_PI], make_vct(16), false).each_with_index do |val, i|
15534    if fneq(val, res = sin((TWO_PI * i) / 16.0) +  sin(HALF_PI + ((2.0 * TWO_PI * i) / 16.0)))
15535      snd_display("phase_partials2wave 1 1 0 2 1 0.5 at %s: %s %s?", i, val, res)
15536    end
15537  end
15538  #
15539  test_gen_equal(make_table_lookup(440.0, :wave, partials2wave([1, 1, 2, 1])),
15540                 make_table_lookup(440.0, :wave, partials2wave([1, 1, 2, 1])),
15541                 make_table_lookup(100.0, :wave, partials2wave([1, 1, 2, 1])))
15542  test_gen_equal(make_table_lookup(440.0, :wave, partials2wave([1, 1, 2, 1])),
15543                 make_table_lookup(440.0, :wave, partials2wave([1, 1, 2, 1])),
15544                 make_table_lookup(440.0, :wave, partials2wave([1, 1, 2, 0.5])))
15545  #
15546  if (res = Snd.catch do partials2wave([0.5, 0.3, 0.2]) end).first != :bad_type
15547    snd_display("odd length arg to partials2wave: %s", res.inspect)
15548  end
15549  #
15550  hi = make_table_lookup(:size, 256)
15551  if hi.length != 256
15552    snd_display("table_lookup set length: %s?", hi.length)
15553  end
15554  if (res = Snd.catch do make_table_lookup(:size, 0) end).first != :out_of_range
15555    snd_display("table_lookup size 0: %s", res.inspect)
15556  end
15557  gen = make_table_lookup(440.0, :wave, partials2wave([1, 1]))
15558  a = 0.0
15559  ainc = (TWO_PI * 440.0) / 22050.0
15560  1100.times do |i|
15561    if fneq(val1 = sin(a), val2 = gen.run(0.0))
15562      snd_display("table_lookup [1, 1]: %s: %s %s?", i, val1, val2)
15563    end
15564    a += ainc
15565  end
15566  gen = make_table_lookup(4.0, :wave, partials2wave([1, 1]))
15567  a = 0.0
15568  ainc = (TWO_PI * 4.0) / 22050.0
15569  1100.times do |i|
15570    if fneq(val1 = sin(a), val2 = gen.run(0.0))
15571      snd_display("table_lookup [1, 1] 4: %s: %s %s?", i, val1, val2)
15572    end
15573    a += ainc
15574  end
15575  gen = make_table_lookup(440.0, :wave, partials2wave([1, 0.75, 3, 0.25]))
15576  a = 0.0
15577  ainc = (TWO_PI * 440.0) / 22050.0
15578  1100.times do |i|
15579    val1 = 0.75 * sin(a) + 0.25 * sin(3.0 * a)
15580    if fneq(val1, val2 = gen.run(0.0))
15581      snd_display("table_lookup [1, 0.75, 3, 0.25]: %s: %s %s?", i, val1, val2)
15582    end
15583    a += ainc
15584  end
15585  gen = make_table_lookup(0.0, :wave, partials2wave([1, 1]))
15586  gen1 = make_table_lookup(40.0, :wave, partials2wave([1, 1]))
15587  a = 0.0
15588  a1 = 0.0
15589  ainc = (TWO_PI * 40.0) / 22050.0
15590  100.times do |i|
15591    if fneq(val1 = sin(a1), val2 = gen.run(gen1.run(0.0)))
15592      snd_display("table_lookup/table_lookup fm: %s: %s %s?", i, val1, val2)
15593    end
15594    a1 += sin(a)
15595    a += ainc
15596  end
15597  [[:Mus_interp_none, vct(0, 0.000, 0.000, 0.000, 0.000, 1.000, 1.000, 1.000, 1.000, 1.000)],
15598    [:Mus_interp_linear, vct(0, 0.200, 0.400, 0.600, 0.800, 1.000, 0.800, 0.600, 0.400, 0.200)],
15599    [:Mus_interp_lagrange, vct(0, 0.120, 0.280, 0.480, 0.720, 1.000, 0.960, 0.840, 0.640, 0.360)],
15600    [:Mus_interp_all_pass, vct(1, 0.000, 0.429, 0.143, 0.095, 0.905, 0.397, 0.830, 0.793, 0.912)],
15601    [:Mus_interp_hermite, vct(0, 0.168, 0.424, 0.696, 0.912, 1.000, 0.912, 0.696, 0.424, 0.168)]
15602  ].each do |type_sym, vals|
15603    type = Module.const_get(type_sym)
15604    tbl = make_table_lookup(:frequency, 0.0, :size, 4, :type, type)
15605    tbl.data[1] = 1.0
15606    fm = (TWO_PI * 0.2) / 4.0
15607    v = make_vct!(10) do table_lookup(tbl, fm) end
15608    if (not vequal(v, vals)) and
15609        (type_sym != :Mus_interp_all_pass) and
15610        (type_sym != :Mus_interp_none or (not vequal(v, vct(0, 0, 0, 0, 0, 0, 1, 1, 1, 1))))
15611      snd_display("tbl interp %s: %s?", type_sym, v)
15612    end
15613    if tbl.interp_type != type
15614      snd_display("tbl interp_type (%s) %s?", type_sym, tbl.interp_type)
15615    end
15616  end
15617  #
15618  gen0 = make_polyshape(440.0, :coeffs, partials2polynomial([1, 1]))
15619  gen = make_polyshape(440.0, :partials, [1, 1], :kind, Mus_chebyshev_first_kind)
15620  gen1 = make_polyshape(440.0)
15621  print_and_check(gen,
15622                  "polyshape",
15623                  "polyshape freq: 440.000Hz, phase: 0.000, coeffs[2]: [0 1]")
15624  if gen.length != 2
15625    snd_display("polyshape length: %s?", gen.length)
15626  end
15627  v0 = make_vct!(10) do
15628    if fneq(val0 = polyshape(gen0, 1.0, 0.0), val = mus_apply(gen, 1.0, 0.0))
15629      snd_display("polyshape: %s != %s?", val, val0)
15630    end
15631    val
15632  end
15633  v1 = make_vct(10)
15634  v1.map! do |x| polyshape?(gen1) ? polyshape(gen1, 1.0, 0.0) : -1.0 end
15635  unless vequal(v0, v1)
15636    snd_display("map polyshape: %s %s?", v0, v1)
15637  end
15638  gen1 = make_polyshape(440.0, :coeffs, partials2polynomial([1, 1]))
15639  v1.map! do |x| polyshape(gen1, 1.0) end
15640  unless vequal(v0, v1)
15641    snd_display("map polyshape (no fm): %s %s?", v0, v1)
15642  end
15643  unless polyshape?(gen)
15644    snd_display("%s not polyshape?", gen)
15645  end
15646  if fneq(gen.phase, 1.253787)
15647    snd_display("polyshape phase: %s?", gen.phase)
15648  end
15649  gen.phase = 1.0
15650  if fneq(gen.phase, 1.0)
15651    snd_display("polyshape set_phase: %s?", gen.phase)
15652  end
15653  if fneq(gen.frequency, 440.0)
15654    snd_display("polyshape frequency: %s?", gen.frequency)
15655  end
15656  gen.frequency = 100.0
15657  if fneq(gen.frequency, 100.0)
15658    snd_display("polyshape set_frequency: %s?", gen.frequency)
15659  end
15660  unless vct?(gen.data)
15661    snd_display("mus_data polyshape: %s?", gen.data)
15662  end
15663  if fneq(v0[1], 0.992) or fneq(v0[8], 0.538)
15664    snd_display("polyshape output: %s?", v0)
15665  end
15666  gen0.data = make_vct(32)
15667  gen0.length = 32
15668  if gen0.length != 32
15669    snd_display("set_mus_length polyshape: %s?", gen0.length)
15670  end
15671  #
15672  test_gen_equal(make_polyshape(440.0, :partials, [1, 1]),
15673                 make_polyshape(440.0),
15674                 make_polyshape(100.0, :partials, [1, 1]))
15675  test_gen_equal(make_polyshape(440.0, :partials, [1, 1]),
15676                 make_polyshape(440.0),
15677                 make_polyshape(4400.0, :partials, [1, 1, 2, 0.5]))
15678  #
15679  gen = make_polyshape(440.0, :partials, [1, 1])
15680  1100.times do |i|
15681    a = gen.phase
15682    if fneq(val1 = cos(a), val2 = gen.run(1.0, 0.0))
15683      snd_display("polyshaper [1, 1] %s: %s %s?", i, val1, val2)
15684      break
15685    end
15686  end
15687  gen = make_polyshape(440.0) # check default for partials: [1, 1])
15688  1100.times do |i|
15689    a = gen.phase
15690    val1 = cos(a)
15691    if fneq(val1, val2 = gen.run(1.0, 0.0))
15692      snd_display("polyshaper [1, 1, 2, 0.5] %s: %s %s?", i, val1, val2)
15693      break
15694    end
15695  end
15696  gen = make_polyshape(440.0, :partials, [1, 1])
15697  1100.times do |i|
15698    a = gen.phase
15699    if fneq(val1 = 0.5 * cos(a), val2 = gen.run(0.5, 0.0))
15700      snd_display("polyshaper default [1, 1] 0.5 %s: %s %s?", i, val1, val2)
15701      break
15702    end
15703  end
15704  #
15705  if (res = Snd.catch do make_polyshape(440.0, :coeffs, 3.14) end).first != :wrong_type_arg
15706    snd_display("make_polyshape bad coeffs: %s", res.inspect)
15707  end
15708  gen = make_polyshape(0.0, :coeffs, partials2polynomial([1, 1]))
15709  gen1 = make_polyshape(40.0, :coeffs, partials2polynomial([1, 1]))
15710  a1 = 0.0
15711  a = 0.0
15712  400.times do |i|
15713    if ((val1 = cos(a1)) - (val2 = polyshape(gen, 1.0, polyshape(gen1, 1.0)))).abs > 0.002
15714      snd_display("polyshape fm: %s: %s %s?", i, val1, val2)
15715      break
15716    end
15717    a1 += cos(a)
15718    a = a + (TWO_PI * 40.0) / 22050.0
15719  end
15720end
15721
15722def test_08_10
15723  gen = make_wave_train(440.0, 0.0, make_vct(20))
15724  gen1 = make_wave_train(440.0, 0.0, make_vct(20))
15725  print_and_check(gen,
15726                  "wave-train",
15727                  "wave-train freq: 440.000Hz, phase: 0.000, size: 20, interp: linear")
15728  20.times do |i|
15729    gen.data[i] = i * 0.5
15730    gen1.data[i] = gen.data[i]
15731  end
15732  if gen.length != 20
15733    snd_display("wave_train length: %s?", gen.length)
15734  end
15735  v0 = make_vct!(10) do wave_train(gen, 0.0) end
15736  v1 = make_vct(10)
15737  v1.map! do |x| wave_train?(gen1) ? wave_train(gen1) : -1.0 end
15738  unless vequal(v0, v1)
15739    snd_display("map wave_train: %s %s?", v0, v1)
15740  end
15741  unless wave_train?(gen)
15742    snd_display("%s not wave_train?", gen)
15743  end
15744  if fneq(gen.phase, 0.0)
15745    snd_display("wave_train phase: %s?", gen.phase)
15746  end
15747  gen.phase = 1.0
15748  if fneq(gen.phase, 1.0)
15749    snd_display("wave_train set_phase: %s?", gen.phase)
15750  end
15751  if fneq(gen.frequency, 440.0)
15752    snd_display("wave_train frequency: %s?", gen.frequency)
15753  end
15754  gen.frequency = 100.0
15755  if fneq(gen.frequency, 100.0)
15756    snd_display("wave_train set_frequency: %s?", gen.frequency)
15757  end
15758  if fneq(v0[1], 0.5) or fneq(v0[8], 4.0)
15759    snd_display("wave_train output: %s?", v0)
15760  end
15761  gen.reset
15762  if fneq(gen.phase, 0.0)
15763    snd_display("wave_train reset phase: %s?", gen.phase)
15764  end
15765  if fneq(res = wave_train(gen, 0.0), 0.0)
15766    snd_display("wave_train data: %s?", res)
15767  end
15768  unless vct?(gen.data)
15769    snd_display("mus_data wave_train: %s?", gen.data)
15770  end
15771  gen.data = make_vct(3)
15772  #
15773  test_gen_equal(make_wave_train(440.0, 0.0, make_vct(20)),
15774                 make_wave_train(440.0, 0.0, make_vct(20)),
15775                 make_wave_train(100.0, 0.0, make_vct(20)))
15776  test_gen_equal(make_wave_train(440.0, 0.0, make_vct(20)),
15777                 make_wave_train(440.0, 0.0, make_vct(20)),
15778                 make_wave_train(440.0, 1.0, make_vct(20)))
15779  #
15780  hi = make_wave_train(:size, 256)
15781  if hi.length != 256
15782    snd_display("wave_train set_length: %s?", hi.length)
15783  end
15784  hi.length = 128
15785  if hi.length != 128
15786    snd_display("wave_train set_length: %s?", hi.length)
15787  end
15788  [[:Mus_interp_none, vct(0.000, 1.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 1.000)],
15789    [:Mus_interp_linear, vct(0.200, 0.800, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.200, 0.800)],
15790    [:Mus_interp_lagrange, vct(0.120, 0.960, -0.080, 0.000, 0.0, 0.0, 0.0, 0.0, 0.120, 0.960)],
15791    [:Mus_interp_hermite, vct(0.168, 0.912, -0.064, -0.016, 0.0, 0.0, 0.0, 0.000, 0.168, 0.912)]
15792  ].each do |type_sym, vals|
15793    type = Module.const_get(type_sym)
15794    fm = (TWO_PI * 0.2) / 4.0
15795    tbl = make_wave_train(:frequency, 3000.0, :initial_phase, fm, :size, 4, :type, type)
15796    tbl.data[1] = 1.0
15797    v = make_vct!(10) do wave_train(tbl, 0.0) end
15798    unless vequal(v, vals)
15799      snd_display("wt tbl interp %s: %s?", type_sym, v)
15800    end
15801    if tbl.interp_type != type
15802      snd_display("wt tbl interp_type (%s) %s?", type_sym, tbl.interp_type)
15803    end
15804  end
15805  if (res = Snd.catch do make_wave_train(:size, 0) end).first != :out_of_range
15806    snd_display("wave_train size 0: %s", res.inspect)
15807  end
15808  #
15809  ind = new_sound(:size, 10)
15810  if framples != 10
15811    snd_display("new_sound size 10: %s?", framples)
15812  end
15813  map_channel($init_channel, 7, 8)
15814  if framples != 15
15815    snd_display("map_channel 7 8: %s?", framples)
15816  end
15817  map_channel($init_channel)
15818  if framples != 15
15819    snd_display("map_channel (no dur): %s?", framples)
15820  end
15821  revert_sound(ind)
15822  map_channel($init_channel, 9, 10)
15823  if framples != 19
15824    snd_display("map_channel 9 10: %s?", framples)
15825  end
15826  if (res = edit_position(ind, 0)) > 2
15827    snd_display("map_channel pad edits (1): %s?", res)
15828  end
15829  revert_sound(ind)
15830  map_channel($init_channel, 10, 10)
15831  if framples != 20
15832    snd_display("map_channel 10 10: %s?", framples)
15833  end
15834  if (res = edit_position(ind, 0)) > 2
15835    snd_display("map_channel pad edits (2): %s?", res)
15836  end
15837  revert_sound(ind)
15838  map_channel($init_channel, 20, 10)
15839  if framples != 30
15840    snd_display("map_channel 20 10: %s?", framples)
15841  end
15842  if (res = edit_position(ind, 0)) > 2
15843    snd_display("map_channel pad edits (3): %s?", res)
15844  end
15845  revert_sound(ind)
15846  if scan_channel(lambda do |y| false end, 30, 10)
15847    snd_display("scan_channel past end?")
15848  end
15849  close_sound(ind)
15850  #
15851  ind = new_sound(:size, 1000)
15852  table = vct(0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6)
15853  gen = make_wave_train(1000.0, :wave, table)
15854  map_channel(lambda do |y| wave_train(gen) end)
15855  if fneq(res = maxamp, 0.6)
15856    snd_display("wave_train 0 max: %s?", res)
15857  end
15858  unless vequal(res = channel2vct(0, 30),
15859                vct(0.000, 0.100, 0.200, 0.300, 0.400, 0.500, 0.600, 0.000,
15860                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
15861                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
15862                    0.100, 0.200, 0.300, 0.400, 0.500, 0.600))
15863    snd_display("wave_train 0 data: %s?", res)
15864  end
15865  unless vequal(res = channel2vct(85, 30),
15866                vct(0.000, 0.000, 0.000, 0.000, 0.000, 0.100, 0.200, 0.300,
15867                    0.400, 0.500, 0.600, 0.000, 0.000, 0.000, 0.000, 0.000,
15868                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
15869                    0.000, 0.000, 0.000, 0.100, 0.200, 0.300))
15870    snd_display("wave_train 0 data 85: %s?", res)
15871  end
15872  undo_edit
15873  #
15874  table = make_vct(10, 0.1)
15875  gen = make_wave_train(1000.0, :initial_phase, PI, :wave, table)
15876  map_channel(lambda do |y| wave_train(gen) end)
15877  if fneq(res = maxamp, 0.1)
15878    snd_display("wave_train 1 max: %s?", res)
15879  end
15880  unless vequal(res = channel2vct(0, 30),
15881                vct(0.100, 0.100, 0.100, 0.100, 0.100, 0.000, 0.000, 0.000,
15882                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
15883                    0.000, 0.000, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100,
15884                    0.100, 0.100, 0.100, 0.100, 0.000, 0.000))
15885    snd_display("wave_train 1 data: %s?", res)
15886  end
15887  undo_edit
15888  #
15889  table = make_vct(10, 0.1)
15890  gen = make_wave_train(2000.0, :wave, table)
15891  map_channel(lambda do |y| wave_train(gen) end)
15892  if fneq(res = maxamp, 0.1)
15893    snd_display("wave_train 2 max: %s?", res)
15894  end
15895  unless vequal(res = channel2vct(0, 30),
15896                vct(0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100,
15897                    0.100, 0.100, 0.000, 0.000, 0.100, 0.100, 0.100, 0.100,
15898                    0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.000, 0.100,
15899                    0.100, 0.100, 0.100, 0.100, 0.100, 0.100))
15900    snd_display("wave_train 2 data: %s?", res)
15901  end
15902  if (not vequal(res = channel2vct(440, 30),
15903                 vct(0.000, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100,
15904                     0.100, 0.100, 0.100, 0.000, 0.000, 0.100, 0.100, 0.100,
15905                     0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.000,
15906                     0.100, 0.100, 0.100, 0.100, 0.100, 0.100))) and
15907      (not vequal(res = channel2vct(440, 30),
15908                  vct(0.000, 0.000, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100,
15909                      0.100, 0.100, 0.100, 0.100, 0.000, 0.100, 0.100, 0.100,
15910                      0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.000,
15911                      0.100, 0.100, 0.100, 0.100, 0.100, 0.100)))
15912    snd_display("wave_train 2 data 440: %s?", res)
15913  end
15914  undo_edit
15915  #
15916  table = make_vct(10, 0.1)
15917  gen = make_wave_train(3000.0, :wave, table)
15918  map_channel(lambda do |y| wave_train(gen) end)
15919  if fneq(res = maxamp, 0.2)
15920    snd_display("wave_train 3 max: %s?", res)
15921  end
15922  unless vequal(res = channel2vct(0, 30),
15923                vct(0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100,
15924                    0.200, 0.200, 0.100, 0.100, 0.100, 0.100, 0.100, 0.200,
15925                    0.200, 0.200, 0.100, 0.100, 0.100, 0.100, 0.100, 0.200,
15926                    0.200, 0.100, 0.100, 0.100, 0.100, 0.100))
15927    snd_display("wave_train 3 data: %s?", res)
15928  end
15929  unless vequal(res = channel2vct(440, 30),
15930                vct(0.100, 0.200, 0.200, 0.200, 0.100, 0.100, 0.100, 0.100,
15931                    0.100, 0.200, 0.200, 0.100, 0.100, 0.100, 0.100, 0.100,
15932                    0.200, 0.200, 0.200, 0.100, 0.100, 0.100, 0.100, 0.100,
15933                    0.200, 0.200, 0.100, 0.100, 0.100, 0.100))
15934    snd_display("wave_train 3 data 440: %s?", res)
15935  end
15936  undo_edit
15937  #
15938  table = make_vct(10, 0.1)
15939  gen = make_wave_train(5000.0, :wave, table)
15940  map_channel(lambda do |y| wave_train(gen) end)
15941  if fneq(res = maxamp, 0.3)
15942    snd_display("wave_train 4 max: %s?", res)
15943  end
15944  unless vequal(res = channel2vct(0, 30),
15945                vct(0.100, 0.100, 0.100, 0.100, 0.100, 0.200, 0.200, 0.200,
15946                    0.200, 0.300, 0.200, 0.200, 0.200, 0.200, 0.300, 0.200,
15947                    0.200, 0.200, 0.300, 0.200, 0.200, 0.200, 0.200, 0.300,
15948                    0.200, 0.200, 0.200, 0.300, 0.200, 0.200))
15949    snd_display("wave_train 4 data: %s?", res)
15950  end
15951  unless vequal(res = channel2vct(440, 30),
15952                vct(0.200, 0.200, 0.300, 0.200, 0.200, 0.200, 0.300, 0.200,
15953                    0.200, 0.200, 0.300, 0.300, 0.200, 0.200, 0.200, 0.300,
15954                    0.200, 0.200, 0.200, 0.300, 0.200, 0.200, 0.200, 0.200,
15955                    0.300, 0.200, 0.200, 0.200, 0.300, 0.200))
15956    snd_display("wave_train 4 data 440: %s?", res)
15957  end
15958  undo_edit
15959  #
15960  table = make_vct(10, 0.1)
15961  gen = make_wave_train(1000.0, :wave, table)
15962  e = make_env([0, 1, 1, 2], :length, 1001)
15963  base_freq = mus_frequency(gen)
15964  map_channel(lambda do |y|
15965                res = wave_train(gen)
15966                set_mus_frequency(gen, env(e) * base_freq)
15967                res
15968              end)
15969  if fneq(res = maxamp, 0.1)
15970    snd_display("wave_train 5 max: %s?", res)
15971  end
15972  unless vequal(res = channel2vct(0, 30),
15973                vct(0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100,
15974                    0.100, 0.100, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
15975                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.100,
15976                    0.100, 0.100, 0.100, 0.100, 0.100, 0.100))
15977    snd_display("wave_train 5 data: %s?", res)
15978  end
15979  unless vequal(res = channel2vct(440, 30),
15980                vct(0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100,
15981                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.100, 0.100,
15982                    0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100,
15983                    0.000, 0.000, 0.000, 0.000, 0.000, 0.100))
15984    snd_display("wave_train 5 data 440: %s?", res)
15985  end
15986  unless vequal(res = channel2vct(900, 30),
15987                vct(0.100, 0.000, 0.000, 0.100, 0.100, 0.100, 0.100, 0.100,
15988                    0.100, 0.100, 0.100, 0.100, 0.100, 0.000, 0.100, 0.100,
15989                    0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100,
15990                    0.000, 0.000, 0.100, 0.100, 0.100, 0.100))
15991    snd_display("wave_train 5 data 900: %s?", res)
15992  end
15993  undo_edit
15994  #
15995  table = make_vct(10, 0.1)
15996  gen = make_wave_train(500.0, :wave, table)
15997  ctr = 0
15998  map_channel(lambda do |y|
15999                res = wave_train(gen)
16000                if ctr > 22
16001                  ctr = 0
16002                  vct_scale!(mus_data(gen), 1.05)
16003                else
16004                  ctr += 1
16005                end
16006                res
16007              end)
16008  if fneq(res = maxamp, 0.704)
16009    snd_display("wave_train 6 max: %s?", res)
16010  end
16011  unless vequal(res = channel2vct(0, 30),
16012                vct(0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100,
16013                    0.100, 0.100, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
16014                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
16015                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
16016    snd_display("wave_train 6 data: %s?", res)
16017  end
16018  if (not vequal(res = channel2vct(440, 30),
16019                 vct(0.000, 0.241, 0.241, 0.241, 0.241, 0.241, 0.241, 0.241,
16020                     0.241, 0.241, 0.241, 0.000, 0.000, 0.000, 0.000, 0.000,
16021                     0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
16022                     0.000, 0.000, 0.000, 0.000, 0.000, 0.000))) and
16023      (not vequal(res = channel2vct(440, 30),
16024                  vct(0.000, 0.000, 0.241, 0.241, 0.241, 0.241, 0.241, 0.241,
16025                      0.241, 0.241, 0.241, 0.241, 0.000, 0.000, 0.000, 0.000,
16026                      0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
16027                      0.000, 0.000, 0.000, 0.000, 0.000, 0.000)))
16028    snd_display("wave_train 6 data 440: %s?", res)
16029  end
16030  unless vequal(res = channel2vct(900, 30),
16031                vct(0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
16032                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
16033                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
16034                    0.000, 0.000, 0.000, 0.639, 0.639, 0.639))
16035    snd_display("wave_train 6 data 900: %s?", res)
16036  end
16037  undo_edit
16038  fname = file_name(ind)
16039  close_sound(ind)
16040  delete_file(fname)
16041  #
16042  gen = make_readin("oboe.snd", 0, 1490)
16043  gen1 = make_readin("oboe.snd", 0, 1490)
16044  print_and_check(gen, "readin", "readin oboe.snd[chan 0], loc: 1490, dir: 1")
16045  v0 = make_vct!(10) do readin(gen) end
16046  v1 = make_vct(10)
16047  v1.map! do |x|
16048    if readin?(gen1)
16049      if gen1.channel.zero?
16050        readin(gen1)
16051      else
16052        1.0
16053      end
16054    else
16055      if gen1.file_name == "oboe.snd"
16056        -1.0
16057      else
16058        -1.0
16059      end
16060    end
16061  end
16062  unless vequal(v0, v1)
16063    snd_display("map readin: %s %s?", v0, v1)
16064  end
16065  unless readin?(gen)
16066    snd_display("%s not readin?", gen)
16067  end
16068  unless mus_input?(gen)
16069    snd_display("%s not input?", gen)
16070  end
16071  if gen.length != 50828
16072    snd_display("readin length: %s?", gen.length)
16073  end
16074  if gen.channel.nonzero?
16075    snd_display("readin chan: %s?", gen.channel)
16076  end
16077  if gen.file_name != "oboe.snd"
16078    snd_display("readin mus_file_name: %s?", gen.file_name)
16079  end
16080  if fneq(v0[1], -0.009) or fneq(v0[7], 0.029)
16081    snd_display("readin output: %s?", v0)
16082  end
16083  set_mus_location(gen, 1000)
16084  if mus_location(gen) != 1000
16085    snd_display("readin set_mus_location: %s?", mus_location(gen))
16086  end
16087  if fneq(res = readin(gen), 0.033)
16088    snd_display("readin set_mus_location data: %s?", res)
16089  end
16090  set_mus_increment(gen, -1)
16091  if fneq(mus_increment(gen), -1.0)
16092    snd_display("readin set_mus_increment: %s?", mus_increment(gen))
16093  end
16094  if (res = Snd.catch do make_readin("/baddy/hiho", 0, 124) end).first != :no_such_file
16095    snd_display("make_readin w/o file: %s", res.inspect)
16096  end
16097  if (res = Snd.catch do make_readin("oboe.snd", 123, 124) end).first != :out_of_range
16098    snd_display("make_readin with bad chan: %s", res.inspect)
16099  end
16100  #
16101  test_gen_equal(make_readin("oboe.snd", 0),
16102                 make_readin("oboe.snd", 0),
16103                 make_readin("oboe.snd", 0, 1230))
16104  test_gen_equal(make_readin("oboe.snd", 0, :size, 512),
16105                 make_readin("oboe.snd", 0, :size, 512),
16106                 make_readin("pistol.snd", 0, :size, 512))
16107  test_gen_equal(make_readin("2.snd", 1),
16108                 make_readin("2.snd", 1),
16109                 make_readin("2.snd", 0))
16110  #
16111  gen = make_readin("2.snd", 1, :size, 1024)
16112  print_and_check(gen, "readin", "readin 2.snd[chan 1], loc: 0, dir: 1")
16113  v0.map! do readin(gen) end
16114  if gen.channel != 1
16115    snd_display("readin chan 1: %s?", gen.channel)
16116  end
16117  if fneq(v0[1], 0.01) or fneq(v0[7], -0.006)
16118    snd_display("readin 1 output: %s?", v0)
16119  end
16120  print_and_check(gen, "readin", "readin 2.snd[chan 1], loc: 10, dir: 1")
16121  #
16122  gen = make_file2sample("oboe.snd")
16123  print_and_check(gen, "file->sample", "file->sample \"oboe.snd\"")
16124  unless file2sample?(gen)
16125    snd_display("%s not file2sample?", gen)
16126  end
16127  unless mus_input?(gen)
16128    snd_display("%s not input?", gen)
16129  end
16130  if gen.length != 50828
16131    snd_display("file2sample length: %s?", gen.length)
16132  end
16133  if gen.file_name != "oboe.snd"
16134    snd_display("file2sample mus_file_name: %s?", gen.file_name)
16135  end
16136  v0 = make_vct!(10) do |i| file2sample(gen, 1490 + i) end
16137  if fneq(v0[1], -0.009) or fneq(v0[7], 0.029)
16138    snd_display("file2sample output: %s?", v0)
16139  end
16140  if fneq(mus_increment(gen), 0.0)
16141    snd_display("file2sample increment: %s?", mus_increment(gen))
16142  end
16143  set_mus_increment(gen, 1)
16144  if fneq(mus_increment(gen), 1.0)
16145    snd_display("file2sample set_increment: %s?", mus_increment(gen))
16146  end
16147  mus_reset(gen)
16148  #
16149  ind = open_sound("oboe.snd")
16150  gen = make_snd2sample(ind)
16151  gen1 = make_snd2sample(ind)
16152  print_and_check(gen, "snd->sample", "snd->sample reading oboe.snd (1 chan) at 0:[no readers]")
16153  unless gen.eql?(gen)
16154    snd_display("snd2sample not eql? itself?")
16155  end
16156  if gen.eql?(gen1)
16157    snd_display("snd2sample eql? not itself?")
16158  end
16159  unless snd2sample?(gen)
16160    snd_display("%s not snd2sample?", gen)
16161  end
16162  unless mus_input?(gen)
16163    snd_display("%s not input?", gen)
16164  end
16165  if gen.length != framples(ind)
16166    snd_display("snd2sample length: %s?", gen.length)
16167  end
16168  if gen.file_name != (Dir.pwd + "/oboe.snd")
16169    snd_display("snd2sample mus_file_name: %s?", gen.file_name)
16170  end
16171  v0 = make_vct!(10) do |i| snd2sample(gen, 1490 + i) end
16172  if fneq(v0[1], -0.009) or fneq(v0[7], 0.029)
16173    snd_display("snd2sample output: %s?", v0)
16174  end
16175  if mus_channels(gen) != 1
16176    snd_display("snd2sample channels: %s?", mus_channels(gen))
16177  end
16178  if mus_location(gen) != 1499
16179    snd_display("snd2sample location: %s?", mus_location(gen))
16180  end
16181  v0.map_with_index! do |val, i| ina(1490 + i, gen) end
16182  if fneq(v0[1], -0.009) or fneq(v0[7], 0.029)
16183    snd_display("snd2sample output ina: %s?", v0)
16184  end
16185  close_sound(ind)
16186  #
16187  ind = open_sound("2.snd")
16188  gen = make_snd2sample(ind)
16189  v0 = make_vct!(10) do |i|
16190    snd2sample(gen, 1490 + i, 0)
16191    snd2sample(gen, 1490 + i, 1)
16192  end
16193  print_and_check(gen,
16194                  "snd->sample",
16195                  "snd->sample reading 2.snd (2 chans) at 1499:[#<sampler: 2.snd[0: 0] from 1490, at 1500, forward>, #<sampler: 2.snd[1: 0] from 1490, at 1500, forward>]")
16196  unless snd2sample?(gen)
16197    snd_display("%s not snd2sample?", gen)
16198  end
16199  unless mus_input?(gen)
16200    snd_display("%s not input?", gen)
16201  end
16202  if gen.length != framples(ind)
16203    snd_display("snd2sample length: %s?", gen.length)
16204  end
16205  if gen.file_name != (Dir.pwd + "/2.snd")
16206    snd_display("snd2sample mus_file_name: %s?", gen.file_name)
16207  end
16208  if mus_channels(gen) != 2
16209    snd_display("snd2sample channels (2): %s?", mus_channels(gen))
16210  end
16211  if mus_location(gen) != 1499
16212    snd_display("snd2sample location (2): %s?", mus_location(gen))
16213  end
16214  close_sound(ind)
16215end
16216
16217def test_08_11
16218  gen = make_file2frample("oboe.snd")
16219  print_and_check(gen, "file->frample", "file->frample \"oboe.snd\"")
16220  unless file2frample?(gen)
16221    snd_display("%s not file2frample?", gen)
16222  end
16223  unless mus_input?(gen)
16224    snd_display("%s not input?", gen)
16225  end
16226  if gen.length != 50828
16227    snd_display("file2frample length: %s?", gen.length)
16228  end
16229  g1 = make_vct(gen.channels)
16230  v0 = make_vct!(10) do |i|
16231    file2frample(gen, 1490 + i, g1)[0]
16232  end
16233  unless file2frample?(gen)
16234    snd_display("%s not file2frample?", gen)
16235  end
16236  if gen.file_name != "oboe.snd"
16237    snd_display("file2frample mus_file_name: %s?", gen.file_name)
16238  end
16239  if fneq(v0[1], -0.009) or fneq(v0[7], 0.029)
16240    snd_display("file2frample output: %s?", v0)
16241  end
16242  #
16243  delete_files("fmv.snd", "fmv1.snd", "fmv2.snd", "fmv3.snd")
16244  gen = make_sample2file("fmv.snd", 2, Mus_lshort, Mus_riff)
16245  print_and_check(gen, "sample->file", "sample->file \"fmv.snd\"")
16246  unless sample2file?(gen)
16247    snd_display("%s not sample2file?", gen)
16248  end
16249  unless mus_output?(gen)
16250    snd_display("%s not output?", gen)
16251  end
16252  if gen.length != mus_file_buffer_size
16253    snd_display("sample2file length: %s?", gen.length)
16254  end
16255  genx = gen
16256  unless gen.eql?(genx)
16257    snd_display("sample2file eql? %s %s", genx, gen)
16258  end
16259  if gen.file_name != "fmv.snd"
16260    snd_display("sample2file mus_file_name: %s?", gen.file_name)
16261  end
16262  100.times do |i|
16263    sample2file(gen, i, 0, i * 0.001)
16264    sample2file(gen, i, 1, i * 0.010)
16265  end
16266  outa(50, 0.015, gen)
16267  outb(50, 0.150, gen)
16268  out_any(60, 0.015, 0, gen)
16269  out_any(60, 0.150, 1, gen)
16270  mus_close(gen)
16271  gen = make_file2sample("fmv.snd")
16272  print_and_check(gen, "file->sample", "file->sample \"fmv.snd\"")
16273  val0 = in_any(20, 0, gen)
16274  val1 = in_any(20, 1, gen)
16275  val2 = ina(30, gen)
16276  val3 = inb(30, gen)
16277  val4 = file2sample(gen, 40, 0)
16278  val5 = file2sample(gen, 40, 1)
16279  val6 = in_any(50, 0, gen)
16280  val7 = in_any(50, 1, gen)
16281  val8 = in_any(60, 0, gen)
16282  val9 = in_any(60, 1, gen)
16283  if mus_channels(gen) != 2
16284    snd_display("sample2file channels: %s?", mus_channels(gen))
16285  end
16286  unless mus_input?(gen)
16287    snd_display("%s not input?", gen)
16288  end
16289  if fneq(val0, 0.02) or fneq(val1, 0.2)
16290    snd_display("in_any: %s %s?", val0, val1)
16291  end
16292  if fneq(val2, 0.03) or fneq(val3, 0.3)
16293    snd_display("ina|b: %s %s?", val2, val3)
16294  end
16295  if fneq(val4, 0.04) or fneq(val5, 0.4)
16296    snd_display("sample2file: %s %s?", val4, val5)
16297  end
16298  if fneq(val6, 0.065) or fneq(val7, 0.65)
16299    snd_display("outa|b: %s %s?", val6, val7)
16300  end
16301  if fneq(val8, 0.075) or fneq(val9, 0.75)
16302    snd_display("out_any: %s %s?", val8, val9)
16303  end
16304  #
16305  gen = Vct.new(10)
16306  let(-0.1) do |x|
16307    gen.length.times do |i| outa(i, x += 0.1, gen) end
16308  end
16309  unless vequal(gen, vct(0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9))
16310    snd_display("outa->vct ramp: %s?", gen)
16311  end
16312  let(-0.1) do |x|
16313    gen.length.times do |i| outa(i, x += 0.1, gen) end
16314  end
16315  unless vequal(gen, vct(0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9).scale!(2.0))
16316    snd_display("outa->vct ramp 2: %s?", gen)
16317  end
16318  if (res = mus_channels(gen)) != 1
16319    snd_display("mus_channels vct: %s?", res)
16320  end
16321  #
16322  gen = make_oscil(440.0)
16323  res = Snd.catch do outa(0, 0.1, gen) end
16324  if res.first != :wrong_type_arg and
16325     res.first != :mus_error
16326    snd_display("outa -> oscil: %s", res.inspect)
16327  end
16328  #
16329  gen = make_sample2file("fmv.snd", 4, Mus_lshort, Mus_riff)
16330  print_and_check(gen, "sample->file", "sample->file \"fmv.snd\"")
16331  10.times do |i|
16332    outa(i, 0.1, gen)
16333    outb(i, 0.2, gen)
16334    outc(i, 0.3, gen)
16335    outd(i, 0.4, gen)
16336  end
16337  10.times do |i|
16338    outa(i, 0.01, gen)
16339    outb(i, 0.02, gen)
16340    outc(i, 0.03, gen)
16341    outd(i, 0.04, gen)
16342  end
16343  mus_close(gen)
16344  gen = make_file2sample("fmv.snd")
16345  print_and_check(gen, "file->sample", "file->sample \"fmv.snd\"")
16346  10.times do |i|
16347    if fneq(res1 = ina(i, gen), 0.11) or
16348        fneq(res2 = inb(i, gen), 0.22) or
16349        fneq(res3 = in_any(i, 2, gen), 0.33) or
16350        fneq(res4 = in_any(i, 3, gen), 0.44)
16351      snd_display("4-chan out/in[%s]: %s %s %s %s?", i, res1, res2, res3, res4)
16352    end
16353  end
16354  if (res = Snd.catch do
16355        make_sample2file("fmv.snd", -1, Mus_lshort, Mus_next)
16356      end).first != :out_of_range
16357    snd_display("make_sample2file bad chans: %s", res.inspect)
16358  end
16359  if (res = Snd.catch do mus_location(make_oscil) end).first != :mus_error
16360    snd_display("set_mus_location(make_oscil): %s", res.inspect)
16361  end
16362  if (res = Snd.catch do
16363        make_sample2file("fmv.snd", 1, -1, Mus_next)
16364      end).first != :out_of_range
16365    snd_display("make_sample2file bad format: %s", res.inspect)
16366  end
16367  if (res = Snd.catch do
16368        make_sample2file("fmv.snd", 1, Mus_lshort, -1)
16369      end).first != :out_of_range
16370    snd_display("make_sample2file bad type: %s", res.inspect)
16371  end
16372  #
16373  gen = make_frample2file("fmv1.snd", 2, Mus_bshort, Mus_next)
16374  print_and_check(gen, "frample->file", "frample->file \"fmv1.snd\"")
16375  unless frample2file?(gen)
16376    snd_display("%s not frample2file?", gen)
16377  end
16378  unless mus_output?(gen)
16379    snd_display("%s not output?", gen)
16380  end
16381  if gen.length != mus_file_buffer_size
16382    snd_display("frample2file length: %s?", gen.length)
16383  end
16384  if gen.file_name != "fmv1.snd"
16385    snd_display("frample2file mus_file_name: %s?", gen.file_name)
16386  end
16387  gen.length = 4096
16388  if gen.length != 4096
16389    snd_display("frample2file length: %s?", gen.length)
16390  end
16391  gen.length = 8192
16392  fr0 = make_vct(2, 0.0)
16393  100.times do |i|
16394    vct_set!(fr0, 0, i * 0.001)
16395    vct_set!(fr0, 1, i * 0.010)
16396    frample2file(gen, i, fr0)
16397  end
16398  mus_close(gen)
16399  gen = make_file2frample("fmv1.snd", 1024)
16400  fr0 = make_vct(gen.channels)
16401  val4 = file2frample(gen, 40, fr0)
16402  frout = make_vct(2)
16403  if fneq(vct_ref(val4, 0), 0.04) or fneq(vct_ref(val4, 1), 0.4)
16404    snd_display("frample2file output: %s?", val4)
16405  end
16406  file2frample(gen, 40, frout)
16407  unless frout.eql?(val4)
16408    snd_display("frample2file output via frame: %s %s?", frout, val4)
16409  end
16410  #
16411  gen = make_sample2file("fmv2.snd", 4, Mus_bshort, Mus_aifc)
16412  print_and_check(gen, "sample->file", "sample->file \"fmv2.snd\"")
16413  unless sample2file?(gen)
16414    snd_display("%s not sample2file?", gen)
16415  end
16416  unless mus_output?(gen)
16417    snd_display("%s not output?", gen)
16418  end
16419  100.times do |i|
16420    sample2file(gen, i, 0, i * 0.001)
16421    sample2file(gen, i, 1, i * 0.010)
16422    sample2file(gen, i, 2, i * 0.002)
16423    sample2file(gen, i, 3, i * 0.003)
16424  end
16425  outa(50, 0.015, gen)
16426  outb(50, 0.150, gen)
16427  outc(50, 0.020, gen)
16428  outd(50, 0.030, gen)
16429  out_any(60, 0.015, 0, gen)
16430  out_any(60, 0.150, 1, gen)
16431  out_any(60, 0.020, 2, gen)
16432  out_any(60, 0.030, 3, gen)
16433  mus_close(gen)
16434  gen = make_file2sample("fmv2.snd")
16435  val0 = in_any(20, 2, gen)
16436  val1 = in_any(20, 3, gen)
16437  val2 = file2sample(gen, 50, 2)
16438  val3 = file2sample(gen, 50, 3)
16439  val4 = file2sample(gen, 60, 2)
16440  val5 = file2sample(gen, 60, 3)
16441  if mus_channels(gen) != 4
16442    snd_display("file2sample channels (4): %s?", mus_channels(gen))
16443  end
16444  if fneq(mus_increment(gen), 0.0)
16445    snd_display("file2sample increment: %s?", mus_increment(gen))
16446  end
16447  if fneq(val0, 0.04) or fneq(val1, 0.06)
16448    snd_display("in_any(0, 4): %s %s?", val0, val1)
16449  end
16450  if fneq(val2, 0.12) or fneq(val3, 0.18)
16451    snd_display("file2sample(4): %s %s?", val2, val3)
16452  end
16453  if fneq(val4, 0.14) or fneq(val5, 0.21)
16454    snd_display("in_any(4, 4): %s %s?", val4, val5)
16455  end
16456  #
16457  delete_file("fmv.snd")
16458  mus_sound_forget("fmv.snd")
16459  sf = make_sample2file("fmv.snd", 2, Mus_bshort, Mus_next, "this is a comment")
16460  10.times do |i|
16461    sample2file(sf, i, 0, i * 0.10)
16462    sample2file(sf, i, 1, i * 0.01)
16463  end
16464  mus_close(sf)
16465  if (res = mus_sound_chans("fmv.snd")) != 2
16466    snd_display("sample2file chans: %s?", res)
16467  end
16468  if (res = mus_sound_framples("fmv.snd")) != 10
16469    snd_display("sample2file framples: %s?", res)
16470  end
16471  if (res = mus_sound_samples("fmv.snd")) != 20
16472    snd_display("sample2file samples: %s?", res)
16473  end
16474  if (res = mus_sound_header_type("fmv.snd")) != Mus_next
16475    snd_display("sample2file type: %s?", res)
16476  end
16477  if (res = mus_sound_sample_type("fmv.snd")) != Mus_bshort
16478    snd_display("sample2file format: %s?", res)
16479  end
16480  if (res = mus_sound_comment("fmv.snd")) != "this is a comment"
16481    snd_display("sample2file comment: %s?", res)
16482  end
16483  rd = make_file2sample("fmv.snd")
16484  10.times do |i|
16485    if fneq(c0 = file2sample(rd, i, 0), i * 0.10) or fneq(c1 = file2sample(rd, i, 1), i * 0.01)
16486      snd_display("sample2file2sample at %s: %s %s?", i, c0, c1)
16487      break
16488    end
16489  end
16490  mus_close(rd)
16491  sf = continue_sample2file("fmv.snd")
16492  10.times do |i|
16493    sample2file(sf, i + 5, 0, i * -0.02)
16494    sample2file(sf, i + 5, 1, i * -0.01)
16495  end
16496  mus_close(sf)
16497  mus_sound_forget("fmv.snd")
16498  if (res = mus_sound_chans("fmv.snd")) != 2
16499    snd_display("continue_sample2file chans: %s?", res)
16500  end
16501  if (res = mus_sound_framples("fmv.snd")) != 15
16502    snd_display("continue_sample2file framples: %s?", res)
16503  end
16504  if (res = mus_sound_samples("fmv.snd")) != 30
16505    snd_display("continue_sample2file samples: %s?", res)
16506  end
16507  if (res = mus_sound_header_type("fmv.snd")) != Mus_next
16508    snd_display("continue_sample2file type: %s?", res)
16509  end
16510  if (res = mus_sound_sample_type("fmv.snd")) != Mus_bshort
16511    snd_display("continue_sample2file format: %s?", res)
16512  end
16513  if (res = mus_sound_comment("fmv.snd")) != "this is a comment"
16514    snd_display("continue_sample2file comment: %s?", res)
16515  end
16516  ind = open_sound("fmv.snd")
16517  unless vequal(c0 = channel2vct(0, 15, ind, 0),
16518                vct(0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.58, 0.66,
16519                    0.74, 0.82, -0.1, -0.12, -0.14, -0.16, -0.18))
16520    snd_display("continue_sample2file (0): %s", c0)
16521  end
16522  unless vequal(c0 = channel2vct(0, 15, ind, 1),
16523                vct(0.0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.05, 0.05,
16524                    0.05, 0.05, -0.05, -0.06, -0.07, -0.08, -0.09))
16525    snd_display("continue_sample2file (1): %s", c0)
16526  end
16527  close_sound(ind)
16528  #
16529  delete_file("fmv.snd")
16530  mus_sound_forget("fmv.snd")
16531  msg = "this is a comment"
16532  sf = make_frample2file("fmv.snd", 2, Mus_lfloat, Mus_riff, msg)
16533  10.times do |i|
16534    frample2file(sf, i, vct(i * 0.10, i * 0.01))
16535  end
16536  mus_close(sf)
16537  if (res = mus_sound_chans("fmv.snd")) != 2
16538    snd_display("frample2file chans: %s?", res)
16539  end
16540  if (res = mus_sound_framples("fmv.snd")) != 10
16541    snd_display("frample2file framples: %s?", res)
16542  end
16543  if (res = mus_sound_samples("fmv.snd")) != 20
16544    snd_display("frample2file samples: %s?", res)
16545  end
16546  if (res = mus_sound_header_type("fmv.snd")) != Mus_riff
16547    snd_display("frample2file type: %s?", res)
16548  end
16549  if (res = mus_sound_sample_type("fmv.snd")) != Mus_lfloat
16550    snd_display("frample2file format: %s?", res)
16551  end
16552  if (res = mus_sound_comment("fmv.snd")) != msg
16553    snd_display("frample2file comment: %s?", res)
16554  end
16555  rd = make_file2frample("fmv.snd")
16556  f0 = vct(0, 0)
16557  rd.length.times do |i|
16558    file2frample(rd, i, f0)
16559    snd_test_neq(f0.length, 2, "frample2file2frample at %d: f0.len %s", i, f0)
16560    snd_test_neq(f0[0], i * 0.10, "frample2file2frample at %d: f0[0] %s", i, f0)
16561    snd_test_neq(f0[1], i * 0.01, "frample2file2frample at %d: f0[1] %s", i, f0)
16562  end
16563  mus_close(rd)
16564  sf = continue_frample2file("fmv.snd")
16565  10.times do |i|
16566    frample2file(sf, i + 5, vct(i * -0.02, i * -0.01))
16567  end
16568  mus_close(sf)
16569  mus_sound_forget("fmv.snd")
16570  if (res = mus_sound_chans("fmv.snd")) != 2
16571    snd_display("continue_frample2file chans: %s?", res)
16572  end
16573  if (res = mus_sound_framples("fmv.snd")) != 15
16574    snd_display("continue_frample2file framples: %s?", res)
16575  end
16576  if (res = mus_sound_samples("fmv.snd")) != 30
16577    snd_display("continue_frample2file samples: %s?", res)
16578  end
16579  if (res = mus_sound_header_type("fmv.snd")) != Mus_riff
16580    snd_display("continue_frample2file type: %s?", res)
16581  end
16582  if (res = mus_sound_sample_type("fmv.snd")) != Mus_lfloat
16583    snd_display("continue_frample2file format: %s?", res)
16584  end
16585  if (res = mus_sound_comment("fmv.snd")) != "this is a comment"
16586    snd_display("continue_frample2file comment: %s?", res)
16587  end
16588  ind = open_sound("fmv.snd")
16589  c0 = channel2vct(0, 15, ind, 0)
16590  c1 = channel2vct(0, 15, ind, 1)
16591  v0 = vct(0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.58, 0.66,
16592           0.74, 0.82, -0.1, -0.12, -0.14, -0.16, -0.18)
16593  v1 = vct(0.0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.05, 0.05,
16594           0.05, 0.05, -0.05, -0.06, -0.07, -0.08, -0.09)
16595  snd_test_neq(c0, v0, "continue_frample2file (0)")
16596  snd_test_neq(c1, v1, "continue_frample2file (1)")
16597  close_sound(ind)
16598  delete_file("fmv.snd")
16599  mus_sound_forget("fmv.snd")
16600  #
16601  os = make_oscil(440.0)
16602  v0 = make_vct!(1000) do 0.1 * oscil(os) end
16603  array2file("fmv3.snd", v0, 10000, 22050, 1)     # 10000 deliberate
16604  v1 = make_vct(1000)
16605  file2array("fmv3.snd", 0, 0, 1000, v1)
16606  vct2vector(v0).zip(vct2vector(v1)) do |val1, val2|
16607    if fneq(val1, val2)
16608      snd_display("array2file2array: %s %s?", val1, val2)
16609    end
16610  end
16611  #
16612  if (res = Snd.catch do
16613        array2file("fmv3.snd", v0, -1, 1000, 1)
16614      end).first != :out_of_range
16615    snd_display("array2file bad samps: %s", res.inspect)
16616  end
16617  if (res = Snd.catch do
16618        array2file("/bad/baddy/fmv3.snd", v0, 1, 1000, 1)
16619      end).first != :mus_error
16620    snd_display("array2file bad file: %s", res.inspect)
16621  end
16622  if (res = Snd.catch do
16623        file2array("fmv3.snd", -1, 0, -1, v0)
16624      end).first != :out_of_range
16625    snd_display("file2array bad samps: %s", res.inspect)
16626  end
16627end
16628
16629def test_08_12
16630  gen = make_rand(10000.0)
16631  print_and_check(gen, "rand", "rand freq: 10000.000Hz, phase: 0.000, amp: 1.000")
16632  v0 = make_vct!(10) do rand(gen, 0.0) end
16633  unless rand?(gen)
16634    snd_display("%s not rand?", gen)
16635  end
16636  if fneq(gen.phase, 3.3624296)
16637    snd_display("rand phase: %s?", gen.phase)
16638  end
16639  if fneq(gen.frequency, 10000.0)
16640    snd_display("rand frequency %s?", gen.frequency)
16641  end
16642  gen.scaler = 0.5
16643  if fneq(gen.scaler, 0.5)
16644    snd_display("rand set_scaler: %s?", gen.scaler)
16645  end
16646  if v0[1] == v0[8]
16647    snd_display("rand output: %s", v0)
16648  end
16649  #
16650  gen = make_rand(10000.0, :envelope, [0, 0, 1, 1])
16651  print_and_check(gen,
16652                  "rand",
16653                  "rand freq: 10000.000Hz, phase: 0.000, amp: 1.000, with distribution envelope")
16654  v0 = make_vct!(10) do rand(gen, 0.0) end
16655  unless rand?(gen)
16656    snd_display("(dist) %s not rand?", gen)
16657  end
16658  if fneq(gen.frequency, 10000.0)
16659    snd_display("(dist) rand frequency %s?", gen.frequency)
16660  end
16661  if v0[1] == v0[8]
16662    snd_display("(dist) rand output: %s", v0)
16663  end
16664  if (not vct?(gen.data)) or gen.length != gen.data.length or gen.length != 512
16665    snd_display("(dist) rand data: %s %s?", gen.length, gen.data)
16666  end
16667  #
16668  gen1 = make_rand(10000.0, :envelope, [0, 0, 1, 1])
16669  gen2 = make_rand(10000.0, :envelope, [0, 1, 1, 0])
16670  up1 = 0
16671  down1 = 0
16672  bad1 = 0
16673  up2 = 0
16674  down2 = 0
16675  bad2 = 0
16676  1000.times do |i|
16677    val1 = rand(gen1)
16678    val2 = rand(gen2)
16679    if val1 >= 0.5
16680      up1 += 1
16681    else
16682      if val1 >= 0.0
16683        down1 += 1
16684      else
16685        bad1 += 1
16686      end
16687    end
16688    if val2 >= 0.5
16689      up2 += 1
16690    else
16691      if val2 >= 0.0
16692        down2 += 1
16693      else
16694        bad2 += 1
16695      end
16696    end
16697  end
16698  snd_test_neq(bad1, 0, "rand dist: down/up 1 %d/%d", down1, up1)
16699  snd_test_neq(bad2, 0, "rand dist: down/up 2 %d/%d", down2, up2)
16700  snd_test_gt(2.5 * down1, up1,
16701              "rand dist: down/up/bad 1 %d/%d/%d", down1, up1, bad1)
16702  snd_test_gt(2.5 * up2, down2,
16703              "rand dist: down/up/bad 2 %d/%d/%d", down2, up2, bad2)
16704  #
16705  gen = make_rand_interp(4000.0)
16706  print_and_check(gen, "rand-interp", gen.to_s)
16707  v0 = make_vct!(10) do rand_interp(gen, 0.0) end
16708  unless rand_interp?(gen)
16709    snd_display("%s not rand_interp?", gen)
16710  end
16711  if fneq(gen.phase, 5.114882)
16712    snd_display("rand_interp phase: %s?", gen.phase)
16713  end
16714  if fneq(gen.frequency, 4000.0)
16715    snd_display("rand_interp frequency %s?", gen.frequency)
16716  end
16717  gen.scaler = 0.5
16718  if fneq(gen.scaler, 0.5)
16719    snd_display("rand_interp set_scaler: %s?", gen.scaler)
16720  end
16721  if v0[1] == v0[8]
16722    snd_display("rand_interp output: %s", v0)
16723  end
16724  #
16725  gen = make_rand_interp(4000.0, :envelope, [-1, 1, 0, 0, 1, 1])
16726  print_and_check(gen, "rand-interp", gen.to_s)
16727  v0 = make_vct!(10) do rand_interp(gen, 0.0) end
16728  unless rand_interp?(gen)
16729    snd_display("(dist) %s not rand_interp?", gen)
16730  end
16731  if v0[1] == v0[8]
16732    snd_display("(dist) rand_interp output: %s", v0)
16733  end
16734  if (not vct?(gen.data)) or gen.length != gen.data.length or gen.length != 512
16735    snd_display("(dist) rand_interp data: %s %s?", gen.length, gen.data)
16736  end
16737  #
16738  gen = make_rand(10000.0, 1.0)
16739  gen1 = make_rand_interp(10000.0, 1.0)
16740  1000.times do
16741    val1 = gen.run(0.0)
16742    val2 = gen1.run(0.0)
16743    if val1 > 1.0 or val1 < -1.0
16744      snd_display(",rand: %s %s?", val1, gen)
16745    end
16746    if val2 > 1.0 or val2 < -1.0
16747      snd_display(",rand_interp: %s %s?", val2, gen1)
16748    end
16749  end
16750  gen = make_rand(10000.0, :distribution, inverse_integrate([0, 0, 1, 1]))
16751  print_and_check(gen,
16752                  "rand",
16753                  "rand freq: 10000.000Hz, phase: 0.000, amp: 1.000, with distribution envelope")
16754  v0.map! do rand(gen, 0.0) end
16755  unless rand?(gen)
16756    snd_display("(dist 2) %s not rand?", gen)
16757  end
16758  if fneq(gen.frequency, 10000.0)
16759    snd_display("(dist 2) rand frequency %s?", gen.frequency)
16760  end
16761  if v0[1] == v0[8]
16762    snd_display("(dist 2) rand output: %s", v0)
16763  end
16764  if (not vct?(gen.data)) or gen.length != gen.data.length or gen.length != 512
16765    snd_display("(dist 2) rand data: %s %s?", gen.length, gen.data)
16766  end
16767  #
16768  gen1 = make_rand(10000.0, :distribution, inverse_integrate([0, 0, 1, 1]))
16769  gen2 = make_rand(10000.0, :distribution, inverse_integrate([0, 1, 1, 0]))
16770  up1 = 0
16771  down1 = 0
16772  bad1 = 0
16773  up2 = 0
16774  down2 = 0
16775  bad2 = 0
16776  1000.times do |i|
16777    val1 = rand(gen1)
16778    val2 = rand(gen2)
16779    if val1 >= 0.5
16780      up1 += 1
16781    else
16782      if val1 >= 0.0
16783        down1 += 1
16784      else
16785        bad1 += 1
16786      end
16787    end
16788    if val2 >= 0.5
16789      up2 += 1
16790    else
16791      if val2 >= 0.0
16792        down2 += 1
16793      else
16794        bad2 += 1
16795      end
16796    end
16797  end
16798  if bad1.nonzero? or bad2.nonzero? or 2.5 * down1 > up1 or 2.0 * up2 > down2
16799    snd_display("rand dist 2: %s %s %s,  %s %s %s", down1, up1, bad1, down2, up2, bad2)
16800  end
16801  #
16802  v1 = inverse_integrate([-1, 1, 1, 1])
16803  if fneq(v1[4], -0.984)
16804    snd_display("inverse_integrate -1 to 1 uniform: %s?", v1)
16805  end
16806  v1 = inverse_integrate([0, 1, 1, 1])
16807  if fneq(v1[4], 0.008)
16808    snd_display("inverse_integrate 0 to 1 uniform: %s?", v1)
16809  end
16810  v1 = inverse_integrate([0, 1, 1, 0])
16811  if fneq(v1[4], 0.004)
16812    snd_display("inverse_integrate 0 to 1 1 to 0: %s?", v1)
16813  end
16814  v1 = inverse_integrate([0, 0, 0.5, 1, 1, 0])
16815  if fneq(v1[4], 0.073)
16816    snd_display("inverse_integrate triangle: %s?", v1)
16817  end
16818  v1 = inverse_integrate(gaussian_envelope(1.0))
16819  if fneq(v1[4], -0.593)
16820    snd_display("inverse_integrate gaussian: %s?", v1)
16821  end
16822end
16823
16824def test_08_13
16825  minp = 1.0
16826  maxp = -1.0
16827  1100.times do
16828    val1 = mus_random(1.0)
16829    if val1 < minp
16830      minp = val1
16831    end
16832    if val1 > maxp
16833      maxp = val1
16834    end
16835    if val1 > 1.0 or val1 < -1.0
16836      snd_display("mus_random: %s?", val1)
16837    end
16838  end
16839  if maxp < 0.9 or minp > -0.9
16840    snd_display("mus_random: %s %s", minp, maxp)
16841  end
16842  minp = 12.0
16843  maxp = -12.0
16844  1100.times do
16845    val1 = mus_random(12.0)
16846    if val1 < minp
16847      minp = val1
16848    end
16849    if val1 > maxp
16850      maxp = val1
16851    end
16852    if val1 > 12.0 or val1 < -12.0
16853      snd_display("mus_random (12): %s?", val1)
16854    end
16855  end
16856  if maxp < 11.0 or minp > -11.0
16857    snd_display("mus_random (12): %s %s", minp, maxp)
16858  end
16859  res = lambda do |n|
16860    hits = make_array(10, 0)
16861    n.times do |i| hits[(5 + mus_random(5.0)).floor] += 1 end
16862    sum = 0.0
16863    pp = n / 10.0
16864    hits.each do |val|
16865      sum = sum + (((val - pp) * (val - pp)) / pp)
16866    end
16867    sum
16868  end.call(10000)
16869  if res < 3.0
16870    snd_display("mus_random not so random (chi)? %s", res)
16871  end
16872  res = lambda do |n|
16873    hits = make_array(10, 0)
16874    gen = make_rand(22050.0, 5)
16875    n.times do |i| hits[(5 + rand(gen, 0.0)).floor] += 1 end
16876    sum = 0.0
16877    pp = n / 10.0
16878    hits.each do |val|
16879      sum = sum + (((val - pp) * (val - pp)) / pp)
16880    end
16881    sum
16882  end.call(10000)
16883  if res < 3.5
16884    snd_display("rand not so random (chi)? %s", res)
16885  end
16886  #
16887  data = make_vct!(65536) do mus_random(1.0) end
16888  ndat = snd_spectrum(data, Rectangular_window, 65536, true, 0.0, false, false)
16889  peak = vct_peak(ndat)
16890  sum = 0.0
16891  if peak > 1000.0
16892    snd_display("mus_random spectral peak: %s?", peak)
16893  end
16894  32768.times do |i| sum += ndat[i] end
16895  if (res = sum / 32768.0) > 200.0
16896    snd_display("random average: %s %s?", res, ndat[0])
16897  end
16898  data.map! do mus_random(1.0) end
16899  autocorrelate(data)
16900  data[0] = 0.0
16901  pk = vct_peak(data)
16902  if pk > 1000
16903    snd_display("random autocorrelate peak: %s?", pk)
16904  end
16905  sum = 0.0
16906  32768.times do |i| sum += ndat[i].abs end
16907  if (res = sum / 32768.0) > 200.0
16908    snd_display("random autocorrelate average: %s?", res)
16909  end
16910end
16911
16912def test_08_14
16913  set_locsig_type(Mus_interp_linear)
16914  gen = make_locsig(30.0, :channels, 2)
16915  gen1 = make_locsig(60.0, :channels, 2)
16916  gen2 = make_locsig(60.0, :channels, 4)
16917  gen200 = make_locsig(200.0, :channels, 4)
16918  gen3 = gen1
16919  locsig(gen, 0, 1.0)
16920  print_and_check(gen, "locsig", "locsig chans 2, outn: [0.667 0.333], interp: linear")
16921  unless locsig?(gen)
16922    snd_display("%s not locsig?", gen)
16923  end
16924  unless gen1.eql?(gen3)
16925    snd_display("locsig %s.eql?(%s)?", gen1, gen3)
16926  end
16927  unless gen1 == gen3
16928    snd_display("locsig %s == %s?", gen1, gen3)
16929  end
16930  if gen1.eql?(gen2)
16931    snd_display("locsig 1 %s.eql?(%s)?", gen1, gen2)
16932  end
16933  if gen == gen1
16934    snd_display("locsig 2 %s == %s?", gen, gen1)
16935  end
16936  if gen == gen2
16937    snd_display("locsig 3 %s == %s?", gen, gen2)
16938  end
16939  if fneq(res1 = locsig_ref(gen, 0), 0.667) or fneq(res2 = locsig_ref(gen, 1), 0.333)
16940    snd_display("locsig ref: %s %s?", res1, res2)
16941  end
16942  unless vequal(mus_data(gen), vct(0.667, 0.333))
16943    snd_display("locsig gen outn: %s?", mus_data(gen))
16944  end
16945  unless vequal(mus_data(gen1), vct(0.333, 0.667))
16946    snd_display("locsig gen1 outn: %s?", mus_data(gen1))
16947  end
16948  unless vequal(mus_data(gen2), vct(0.333, 0.667, 0.000, 0.000))
16949    snd_display("locsig gen2 outn: %s?", mus_data(gen2))
16950  end
16951  unless vequal(mus_data(gen200), vct(0.000, 0.000, 0.778, 0.222))
16952    snd_display("locsig gen200 outn: %s?", mus_data(gen200))
16953  end
16954  locsig_set!(gen, 0, 0.25)
16955  unless vequal(mus_data(gen), vct(0.250, 0.333))
16956    snd_display("locsig gen 0.25 outn: %s?", mus_data(gen))
16957  end
16958  locsig(gen, 0, 1.0)
16959  locsig_set!(gen, 0, 0.5)
16960  unless vequal(mus_data(gen), vct(0.500, 0.333))
16961    snd_display("locsig gen 0.5 outn: %s?", mus_data(gen))
16962  end
16963  locsig(gen, 0, 1.0)
16964  gen = make_locsig(300.0, 2.0, 0.1, :channels, 4)
16965  unless vequal(mus_data(gen), vct(0.167, 0.000, 0.000, 0.333))
16966    snd_display("locsig gen 300 outn: %s?", mus_data(gen))
16967  end
16968  locsig(gen, 0, 1.0)
16969  move_locsig(gen1, 90.0, 1.0)
16970  unless vequal(mus_data(gen1), vct(0.000, 1.000))
16971    snd_display("locsig gen1 90 outn: %s?", mus_data(gen1))
16972  end
16973  move_locsig(gen1, 0.0, 1.0)
16974  unless vequal(mus_data(gen1), vct(1.000, 0.000))
16975    snd_display("locsig gen1 0 outn: %s?", mus_data(gen1))
16976  end
16977  move_locsig(gen1, 45.0, 1.0)
16978  unless vequal(mus_data(gen1), vct(0.500, 0.500))
16979    snd_display("locsig gen1 45 outn: %s?", mus_data(gen1))
16980  end
16981  move_locsig(gen1, 135.0, 2.0)
16982  unless vequal(mus_data(gen1), vct(0.000, 0.500))
16983    snd_display("locsig gen1 135 outn: %s?", mus_data(gen1))
16984  end
16985  move_locsig(gen1, -270.0, 3.0)
16986  unless vequal(mus_data(gen1), vct(0.333, 0.000))
16987    snd_display("locsig gen1 -270 outn: %s?", mus_data(gen1))
16988  end
16989  [1, 2, 4, 8].each do |chans|
16990    m1 = make_locsig(:channels, chans)
16991    if m1.channels != chans or m1.length != chans
16992      snd_display("locsig %s chans but: %s %s?", chans, m1.channels, m1.length)
16993    end
16994    chans.times do |i| locsig_set!(m1, i, i * 0.1) end
16995    chans.times do |i|
16996      if fneq(locsig_ref(m1, i), i * 0.1)
16997        snd_display("locsig[%s] = %s (%s)?", i, locsig_ref(m1, i), i * 0.1)
16998      end
16999    end
17000  end
17001  #
17002  if (res = Snd.catch do make_locsig(:channels, 0) end).first != :mus_error
17003    snd_display("make_locsig bad (0) chans: %s", res.inspect)
17004  end
17005  if (res = Snd.catch do make_locsig(:channels, -2) end).first != :out_of_range
17006    snd_display("make_locsig bad (-2) chans: %s", res.inspect)
17007  end
17008  if (res = Snd.catch do make_locsig(:output, 1) end).first != :wrong_type_arg
17009    snd_display("make_locsig bad output: %s", res.inspect)
17010  end
17011  res = Snd.catch do locsig_ref(make_locsig, 1) end
17012  if res != [0.0] and res.car != :mus_error
17013    snd_display("locsig_ref bad chan (0): %s", res.inspect)
17014  end
17015  res = Snd.catch do
17016    locs = make_locsig(200, :channels, 2)
17017    locsig_ref(locs, -1)
17018  end
17019  if res != [0.0] and res.car != :mus_error
17020    snd_display("locsig_ref bad chan (1): %s", res.inspect)
17021  end
17022  res = Snd.catch do
17023    locs = make_locsig
17024    locsig_set!(locs, 2, 0.1)
17025  end
17026  if res != [0.1] and res.car != :mus_error
17027    snd_display("locsig_set! bad chan (2): %s", res.inspect)
17028  end
17029  res = Snd.catch do
17030    locs = make_locsig(:reverb, 0.1)
17031    locsig_reverb_ref(locs, 2)
17032  end
17033  if res != [0.0] and res.car != :mus_error
17034    snd_display("locsig_reverb_ref bad reverb chan (2): %s", res.inspect)
17035  end
17036  res = Snd.catch do
17037    locs = make_locsig(:reverb, 0.1)
17038    locsig_reverb_set!(locs, 2, 0.1)
17039  end
17040  if res != [0.1] and res.car != :mus_error
17041    snd_display("locsig_reverb_set! bad reverb chan (2): %s", res.inspect)
17042  end
17043  #
17044  locs = make_locsig(:channels, 8, :degree, 0)
17045  move_locsig(locs, 180.0, 1.0)
17046  if fneq(locsig_ref(locs, 0), 0.0)
17047    snd_display("move_locsig by jump: %s?", locs.data)
17048  end
17049  unless vequal(locs.data, vct(0.000, 0.000, 0.000, 0.000, 1.000, 0.000, 0.000, 0.000))
17050    snd_display("move_locsig by jump data: %s?", locs.data)
17051  end
17052  move_locsig(locs, 120.0, 1.0)
17053  unless vequal(locs.data, vct(0.000, 0.000, 0.333, 0.667, 0.000, 0.000, 0.000, 0.000))
17054    snd_display("move_locsig by jump 120 data: %s?", locs.data)
17055  end
17056  move_locsig(locs, -20.0, 1.0)
17057  unless vequal(locs.data, vct(0.556, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.444))
17058    snd_display("move_locsig by jump -20 data: %s?", locs.data)
17059  end
17060  #
17061  sf = make_sample2file("fmv4.snd", 8, Mus_bshort, Mus_next, "this is a comment")
17062  sfrev = make_sample2file("fmv4.reverb", 8, Mus_bshort, Mus_next, "this is a comment")
17063  locs = make_locsig(:channels, 8, :degree, 0, :distance, 1.0, :reverb, 0.1,
17064                     :output, sf, :revout, sfrev, :type, Mus_interp_linear)
17065  unless vequal(locs.data, vct(1.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
17066    snd_display("ws not move_locsig by jump data: %s?", locs.data)
17067  end
17068  unless vequal(locs.xcoeffs, vct(0.100, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
17069    snd_display("ws not move_locsig by jump rev data: %s?", locs.xcoeffs)
17070  end
17071  move_locsig(locs, 180.0, 2.0)
17072  if fneq(locsig_ref(locs, 0), 0.0)
17073    snd_display("ws move_locsig by jump: %s?", locs.data)
17074  end
17075  unless vequal(locs.data, vct(0.000, 0.000, 0.000, 0.000, 0.500, 0.000, 0.000, 0.000))
17076    snd_display("ws move_locsig by jump data: %s?", locs.data)
17077  end
17078  unless vequal(locs.xcoeffs, vct(0.000, 0.000, 0.000, 0.000, 0.071, 0.000, 0.000, 0.000))
17079    snd_display("ws move_locsig by jump rev data: %s?", locs.xcoeffs)
17080  end
17081  move_locsig(locs, 120.0, 3.0)
17082  unless vequal(locs.data, vct(0.000, 0.000, 0.111, 0.222, 0.000, 0.000, 0.000, 0.000))
17083    snd_display("ws move_locsig by jump 120 data: %s?", locs.data)
17084  end
17085  unless vequal(locs.xcoeffs, vct(0.000, 0.000, 0.019, 0.038, 0.000, 0.000, 0.000, 0.000))
17086    snd_display("ws move_locsig by jump 120 rev data: %s?", locs.xcoeffs)
17087  end
17088  move_locsig(locs, -20.0, 4.0)
17089  unless vequal(locs.data, vct(0.139, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.111))
17090    snd_display("ws move_locsig by jump -20 data: %s?", locs.data)
17091  end
17092  unless vequal(locs.xcoeffs, vct(0.028, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.022))
17093    snd_display("ws move_locsig by jump -20 rev data: %s?", locs.xcoeffs)
17094  end
17095  mus_close(sf)
17096  mus_close(sfrev)
17097  delete_files("fmv4.snd", "fmv4.reverb")
17098  mus_sound_prune
17099  #
17100  [Mus_caff,
17101   Mus_aifc,
17102   Mus_next,
17103   Mus_riff,
17104   Mus_rf64].each do |ht|
17105    ind = find_sound(with_sound(:channels, 8) do
17106                       8.times do |i|
17107                         locsig(make_locsig(:degree, i * 45, :output, $output), i, 0.5)
17108                       end
17109                     end.output)
17110    8.times do |chn|
17111      samps = channel2vct(0, 8, ind, chn)
17112      8.times do |k|
17113        if k == chn and fneq(samps[k], 0.5)
17114          snd_display("8 out %s chan %s samp %s (0.5): %s?",
17115                      mus_header_type2string(ht), chn, k, samps[k])
17116        end
17117        if k != chn and fneq(samps[k], 0.0)
17118          snd_display("8 out %s chan %s samp %s (0.0): %s?",
17119                      mus_header_type2string(ht), chn, k, samps[k])
17120        end
17121      end
17122    end
17123    close_sound(ind)
17124  end
17125  #
17126  gen = make_frample2file("fmv4.snd", 2, Mus_bshort, Mus_next)
17127  rev = make_frample2file("fmv4.reverb", 1, Mus_bshort, Mus_next)
17128  lc = make_locsig(60.0, :reverb, 0.1, :channels, 2, :output, gen, :revout, rev)
17129  100.times do |i| locsig(lc, i, 1.0) end
17130  if fneq(res = locsig_reverb_ref(lc, 0), 0.1)
17131    snd_display("locsig_reverb_ref: %s?", res)
17132  end
17133  locsig_reverb_set!(lc, 0, 0.3)
17134  if fneq(res = locsig_reverb_ref(lc, 0), 0.3)
17135    snd_display("locsig_reverb_set!: %s?", res)
17136  end
17137  locsig_reverb_set!(lc, 0, 0.2)
17138  if fneq(res = locsig_reverb_ref(lc, 0), 0.2)
17139    snd_display("locsig_reverb_set!: %s?", res)
17140  end
17141  mus_close(gen)
17142  mus_close(rev)
17143  v0 = make_vct(100)
17144  v1 = make_vct(100)
17145  v2 = make_vct(100)
17146  file2array("fmv4.snd", 0, 0, 100, v0)
17147  file2array("fmv4.snd", 1, 0, 100, v1)
17148  file2array("fmv4.reverb", 0, 0, 100, v2)
17149  if fneq(v2[0], 0.1)
17150    snd_display("locsig reverb: %s?", v2)
17151  end
17152  if fneq(2 * v0[0], v1[0])
17153    snd_display("locsig direct: %s %s?", v0[0], v1[0])
17154  end
17155  #
17156  gen = make_frample2file("fmv4.snd", 4, Mus_bshort, Mus_next)
17157  rev = make_frample2file("fmv4.reverb", 4, Mus_bshort, Mus_next)
17158  lc = make_locsig(60.0, :reverb, 0.1, :channels, 4, :distance, 4.0, :output, gen, :revout, rev)
17159  print_and_check(lc,
17160                  "locsig",
17161                  "locsig chans 4, outn: [0.083 0.167 0.000 0.000], revn: [0.017 0.033 0.000 0.000], interp: linear")
17162  100.times do |i| locsig(lc, i, 1.0) end
17163  4.times do |i|
17164    locsig_reverb_set!(lc, i, i * 0.1)
17165    if fneq(res = locsig_reverb_ref(lc, i), i * 0.1)
17166      snd_display("locsig_reverb_set![%s]: %s?", i, res)
17167    end
17168  end
17169  print_and_check(lc,
17170                  "locsig",
17171                  "locsig chans 4, outn: [0.083 0.167 0.000 0.000], revn: [0.000 0.100 0.200 0.300], interp: linear")
17172  unless vct?(lc.data)
17173    snd_display("out data locsig: %s?", lc.data)
17174  end
17175  unless vct?(lc.xcoeffs)
17176    snd_display("rev data locsig: %s?", lc.xcoeffs)
17177  end
17178  xcs = lc.xcoeffs
17179  if fneq(res = mus_xcoeff(lc, 0), xcs[0])
17180    snd_display("locsig xcoeff: %s %s?", res, xcs[0])
17181  end
17182  if fneq(res = mus_xcoeff(lc, 1), 0.1)
17183    snd_display("locsig xcoeff 1: %s %s?", res, xcs[0])
17184  end
17185  mus_close(gen)
17186  mus_close(rev)
17187  #
17188  print_and_check(make_locsig(160, :channels, 4),
17189                  "locsig",
17190                  "locsig chans 4, outn: [0.000 0.222 0.778 0.000], interp: linear")
17191  print_and_check(make_locsig(-200, :channels, 4),
17192                  "locsig",
17193                  "locsig chans 4, outn: [0.000 0.222 0.778 0.000], interp: linear")
17194  print_and_check(make_locsig(160, :channels, 4, :distance, 0.5),
17195                  "locsig",
17196                  "locsig chans 4, outn: [0.000 0.222 0.778 0.000], interp: linear")
17197  print_and_check(make_locsig(320, :channels, 4),
17198                  "locsig",
17199                  "locsig chans 4, outn: [0.556 0.000 0.000 0.444], interp: linear")
17200  print_and_check(make_locsig(-40, :channels, 4),
17201                  "locsig",
17202                  "locsig chans 4, outn: [0.556 0.000 0.000 0.444], interp: linear")
17203  print_and_check(make_locsig(320, :channels, 2),
17204                  "locsig",
17205                  "locsig chans 2, outn: [0.000 1.000], interp: linear")
17206  print_and_check(make_locsig(-40, :channels, 2),
17207                  "locsig",
17208                  "locsig chans 2, outn: [1.000 0.000], interp: linear")
17209  print_and_check(make_locsig(0, :channels, 1, :output, Vct.new(10)),
17210                  "locsig",
17211                  "locsig chans 1, outn: [1.000], interp: linear")
17212  #
17213  locsig_data = lambda do |g|
17214    make_vct!(g.channels) do |i| locsig_ref(g, i) end
17215  end
17216  gen = make_locsig(-0.1, :channels, 8)
17217  unless vequal(locsig_data.call(gen), vct(0.998, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.002))
17218    snd_display("locsig -0.1(8): %s?", locsig_data.call(gen))
17219  end
17220  gen = make_locsig(-359.9, :channels, 8)
17221  unless vequal(locsig_data.call(gen), vct(0.998, 0.002, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
17222    snd_display("locsig -359.9(8): %s?", locsig_data.call(gen))
17223  end
17224  gen = make_locsig(-359.9, :channels, 4)
17225  unless vequal(locsig_data.call(gen), vct(0.999, 0.001, 0.000, 0.000))
17226    snd_display("locsig -359.9(4): %s?", locsig_data.call(gen))
17227  end
17228  gen = make_locsig(-360.1, :channels, 8)
17229  unless vequal(locsig_data.call(gen), vct(0.998, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.002))
17230    snd_display("locsig -360.1(8): %s?", locsig_data.call(gen))
17231  end
17232  gen = make_locsig(-700, :channels, 8)
17233  unless vequal(locsig_data.call(gen), vct(0.556, 0.444, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
17234    snd_display("locsig -700(8): %s?", locsig_data.call(gen))
17235  end
17236  gen = make_locsig(-700, :channels, 2)
17237  unless vequal(locsig_data.call(gen), vct(1.000, 0.000))
17238    snd_display("locsig -700(2): %s?", locsig_data.call(gen))
17239  end
17240  gen = make_locsig(20, :channels, 2)
17241  unless vequal(locsig_data.call(gen), vct(0.778, 0.222))
17242    snd_display("locsig 20(2): %s?", locsig_data.call(gen))
17243  end
17244  gen = make_locsig(123456.0, :channels, 8)
17245  unless vequal(locsig_data.call(gen), vct(0.467, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.533))
17246    snd_display("locsig 123456(8): %s?", locsig_data.call(gen))
17247  end
17248  gen = make_locsig(336.0, :channels, 8)
17249  unless vequal(locsig_data.call(gen), vct(0.467, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.533))
17250    snd_display("locsig 336(8): %s?", locsig_data.call(gen))
17251  end
17252  gen = make_locsig(-123456.0, :channels, 8)
17253  unless vequal(locsig_data.call(gen), vct(0.467, 0.533, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
17254    snd_display("locsig -123456(8): %s?", locsig_data.call(gen))
17255  end
17256  gen = make_locsig(24.0, :channels, 8)
17257  unless vequal(locsig_data.call(gen), vct(0.467, 0.533, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
17258    snd_display("locsig 24(8): %s?", locsig_data.call(gen))
17259  end
17260  #
17261  locsig_scalers = lambda do |chans, degree, type|
17262    if chans == 1
17263      vct(1.0)
17264    else
17265      deg = chans == 2 ? [0.0, [90.0, degree].min].max : degree.divmod(360.0)[1]
17266      degs_per_chan = chans == 2 ? 90.0 : (360.0 / chans)
17267      pos = deg / degs_per_chan
17268      left = pos.floor
17269      right = (left + 1) % chans
17270      frac = pos - left
17271      v = make_vct(chans)
17272      if type == Mus_interp_linear
17273        v[left] = 1.0 - frac
17274        v[right] = frac
17275      else
17276        ldeg = HALF_PI * (0.5 - frac)
17277        norm = sqrt(2.0) * 0.5
17278        c = cos(ldeg)
17279        s = sin(ldeg)
17280        v[left] = norm * (c + s)
17281        v[right] = norm * (c - s)
17282      end
17283      v
17284    end
17285  end
17286  [0, 1, 2, 4].each do |rev_chans|
17287    delete_file("test.reverb")
17288    revfile = if rev_chans > 0
17289                make_frample2file("test.reverb", rev_chans, Mus_bshort, Mus_next)
17290              else
17291                false
17292              end
17293    [Mus_interp_linear, Mus_interp_sinusoidal].each do |type|
17294      set_locsig_type(type)
17295      if locsig_type != type
17296        snd_display("locsig_type: %s %s?", type, locsig_type)
17297      end
17298      [0.0, 45.0, 90.0, 1234.0].each do |deg|
17299        gen = make_locsig(deg, :channels, 1, :revout, revfile, :reverb, 0.1, :distance, 2.0)
17300        revs = revfile ? locsig_scalers.call(rev_chans, deg, type) : []
17301        if gen.channels != 1
17302          snd_display("locsig %s: %s?", deg, gen)
17303        end
17304        if fneq(locsig_ref(gen, 0), 0.5)
17305          snd_display("locsig scaler[%s] %s: %s?", type, deg, locsig_ref(gen, 0))
17306        end
17307        revs.each_with_index do |val, i|
17308          if fneq(res1 = locsig_reverb_ref(gen, i), res2 = ((0.1 / sqrt(2.0)) * val))
17309            snd_display("mono locrev[%s] %s at %s: %s %s?", type, gen, deg, res1, res2)
17310            break
17311          end
17312        end
17313      end
17314      [Mus_interp_linear, Mus_interp_sinusoidal].each do |ltype|
17315        [0.0, 45.0, 90.0, 1234.0].each do |deg|
17316          gen = make_locsig(deg, :channels, 1, :type, ltype)
17317          if gen.channels != 1
17318            snd_display("locsig %s: %s?", deg, gen)
17319          end
17320          if fneq(res = locsig_ref(gen, 0), 1.0)
17321            snd_display("locsig[%s] scaler %s: %s?", ltype, deg, res)
17322          end
17323        end
17324      end
17325      [2, 3, 4, 5, 8, 12, 16, 24].each do |chans|
17326        [0.0, 45.0, 90.0, 120.0, 180.0, 275.0, 315.0, 300.0, 15.0, 1234.0].each do |deg|
17327          gen = make_locsig(deg, :channels, chans, :revout, revfile, :reverb, 0.1)
17328          if gen.channels != chans
17329            snd_display("multi locsig %s: %s?", deg, gen)
17330            break
17331          end
17332          locsig_scalers.call(chans, deg, type).each_with_index do |val, i|
17333            if fneq(res = locsig_ref(gen, i), val)
17334              snd_display("locrev[%s] %s at %s: %s %s?", type, gen, deg, res, val)
17335              break
17336            end
17337          end
17338          (revfile ? locsig_scalers.call(rev_chans, deg, type) : []).each_with_index do |val, i|
17339            if fneq(res1 = locsig_reverb_ref(gen, i), res2 = 0.1 * val)
17340              snd_display("locrev[%s] %s at %s: %s %s?", type, gen, deg, res1, res2)
17341              break
17342            end
17343          end
17344        end
17345      end
17346      [2, 3, 4, 5, 8, 12, 16, 24].each do |chans|
17347        [Mus_interp_linear, Mus_interp_sinusoidal].each do |ltype|
17348          [0.0, 45.0, 90.0, 120.0, 180.0, 275.0, 315.0, 300.0, 15.0, 1234.0].each do |deg|
17349            gen = make_locsig(deg, :channels, chans, :type, ltype,
17350                              :revout, revfile, :reverb, 0.1)
17351            if gen.channels != chans
17352              snd_display("stereo locsig %s: %s?", deg, gen)
17353              break
17354            end
17355            locsig_scalers.call(chans, deg, ltype).each_with_index do |val, i|
17356              if fneq(res = locsig_ref(gen, i), val)
17357                snd_display("locrev[%s] %s at %s: %s %s?", ltype, gen, deg, res, val)
17358                break
17359              end
17360            end
17361            (revfile ? locsig_scalers.call(rev_chans,deg,ltype): []).each_with_index do |val, i|
17362              if fneq(res1 = locsig_reverb_ref(gen, i), res2 = 0.1 * val)
17363                snd_display("locrev[%s] %s at %s: %s %s?", ltype, gen, deg, res1, res2)
17364                break
17365              end
17366            end
17367          end
17368        end
17369      end
17370    end
17371    revfile and mus_close(revfile)
17372  end
17373  #
17374  set_locsig_type(Mus_interp_linear)
17375  outp = Vct.new(10)
17376  gen = make_locsig(0.0, :output, outp)
17377  if (res = mus_channels(gen)) != 1
17378    snd_display("make_locsig->vct chans (1)", res)
17379  end
17380  10.times do |i| locsig(gen, i, 1.0) end
17381  unless vequal(outp, Vct.new(10, 1.0))
17382    snd_display("locsig->vct chan 0: %s?", outp)
17383  end
17384  10.times do |i| locsig(gen, i, 0.5) end
17385  unless vequal(outp, Vct.new(10, 1.5))
17386    snd_display("locsig->vct chan 0: %s?", outp)
17387  end
17388  outp = Vct.new(10)
17389  gen = make_locsig(45.0, :channels, 2, :output, outp)
17390  if (res = mus_channels(gen)) != 2
17391    snd_display("make_locsig->vct chans (2)", res)
17392  end
17393  10.times do |i| locsig(gen, i, 1.0) end
17394  unless vequal(outp, Vct.new(10, 0.5))
17395    snd_display("locsig(2)->vct chan 0: %s?", outp)
17396  end
17397  10.times do |i| locsig(gen, i, 0.5) end
17398  unless vequal(outp, Vct.new(10, 0.75))
17399    snd_display("locsig(2)->vct chan 0: %s?", outp)
17400  end
17401  #
17402  set_mus_array_print_length(8)
17403  outf1 = make_frample2file("fmv.snd", 1, Mus_bshort, Mus_next)
17404  outf4 = make_frample2file("fmv1.snd", 4, Mus_bshort, Mus_next)
17405  revf = make_frample2file("fmv2.snd", 1, Mus_bshort, Mus_next)
17406  start = 0
17407  len = 1000
17408  dur = 1.0
17409  gen1 = make_move_sound([start, len, 1, 0,
17410                          make_delay(32),
17411                          make_env([0, 0, 1, 1], :length, 1001),
17412                          make_env([0, 0, 1, 1], :length, 1001),
17413                          [make_delay(32)],
17414                          [make_env([0, 0, 1, 1], :length, 1001)],
17415                          false,
17416                          [0, 1]],
17417                         outf1)
17418  gen2 = make_move_sound([start, len, 4, 0,
17419                          make_delay(12),
17420                          make_env([0, 0, 10, 1], :duration, dur),
17421                          false,
17422                          Array.new(4, false),
17423                          [make_env([0, 0, 1, 1, 2, 0, 3, 0, 4, 0], :duration, dur),
17424                           make_env([0, 0, 1, 0, 2, 1, 3, 0, 4, 0], :duration, dur),
17425                           make_env([0, 0, 1, 0, 2, 0, 3, 1, 4, 0], :duration, dur),
17426                           make_env([0, 0, 1, 0, 2, 0, 3, 0, 4, 1], :duration, dur)],
17427                          false,
17428                          [0, 1, 2, 3]],
17429                         outf4)
17430  gen3 = make_move_sound([start, len, 1, 1,
17431                          make_delay(32),
17432                          make_env([0, 0, 1, 1], :length, 1001),
17433                          make_env([0, 0, 1, 1], :length, 1001),
17434                          [make_delay(32)],
17435                          [make_env([0, 0, 1, 1], :length, 1001)],
17436                          [make_env([0, 1, 1, 1], :length, 1001)],
17437                          [0, 1]],
17438                         outf1, revf)
17439  print_and_check(gen1,
17440                  "move-sound",
17441                  "move-sound start: 0, end: 1000, out chans 1, rev chans: 0
17442  doppler delay line[32, step]: [0 0 0 0 0 0 0 0...(0: 0, 0: 0)]
17443  doppler env linear, pass: 0 (dur: 1001), index: 0, scaler: 1.0000, offset: 0.0000, data: [0 0 1 1]
17444  global reverb env linear, pass: 0 (dur: 1001), index: 0, scaler: 1.0000, offset: 0.0000, data: [0 0 1 1]
17445  out_delays[1]:
17446    [0]: delay line[32, step]: [0 0 0 0 0 0 0 0...(0: 0, 0: 0)]
17447  out_envs[1]:
17448    [0]: env linear, pass: 0 (dur: 1001), index: 0, scaler: 1.0000, offset: 0.0000, data: [0 0 1 1]
17449  rev_envs: nil
17450  out_map[1]: (0)
17451  free: arrays: true, gens: false
17452")
17453  print_and_check(gen2,
17454                  "move-sound",
17455                  "move-sound start: 0, end: 1000, out chans 4, rev chans: 0
17456  doppler delay line[12, step]: [0 0 0 0 0 0 0 0...(0: 0, 0: 0)]
17457  doppler env linear, pass: 0 (dur: 22050), index: 0, scaler: 1.0000, offset: 0.0000, data: [0 0 10 1]
17458  global reverb null
17459  out_delays[4]:
17460    [0]: nil
17461    [1]: nil
17462    [2]: nil
17463    [3]: nil
17464  out_envs[4]:
17465    [0]: env linear, pass: 0 (dur: 22050), index: 0, scaler: 1.0000, offset: 0.0000, data: [0 0 1 1 2 0 3 0...(0: 0, 8: 4)]
17466    [1]: env linear, pass: 0 (dur: 22050), index: 0, scaler: 1.0000, offset: 0.0000, data: [0 0 1 0 2 1 3 0...(0: 0, 8: 4)]
17467    [2]: env linear, pass: 0 (dur: 22050), index: 0, scaler: 1.0000, offset: 0.0000, data: [0 0 1 0 2 0 3 1...(0: 0, 8: 4)]
17468    [3]: env linear, pass: 0 (dur: 22050), index: 0, scaler: 1.0000, offset: 0.0000, data: [0 0 1 0 2 0 3 0...(0: 0, 8: 4)]
17469  rev_envs: nil
17470  out_map[4]: (0 1 2 3)
17471  free: arrays: true, gens: false
17472")
17473  print_and_check(gen3,
17474                  "move-sound",
17475                  "move-sound start: 0, end: 1000, out chans 1, rev chans: 1
17476  doppler delay line[32, step]: [0 0 0 0 0 0 0 0...(0: 0, 0: 0)]
17477  doppler env linear, pass: 0 (dur: 1001), index: 0, scaler: 1.0000, offset: 0.0000, data: [0 0 1 1]
17478  global reverb env linear, pass: 0 (dur: 1001), index: 0, scaler: 1.0000, offset: 0.0000, data: [0 0 1 1]
17479  out_delays[1]:
17480    [0]: delay line[32, step]: [0 0 0 0 0 0 0 0...(0: 0, 0: 0)]
17481  out_envs[1]:
17482    [0]: env linear, pass: 0 (dur: 1001), index: 0, scaler: 1.0000, offset: 0.0000, data: [0 0 1 1]
17483  rev_envs[1]:
17484    [0]: env linear, pass: 0 (dur: 1001), index: 0, scaler: 1.0000, offset: 0.0000, data: [0 1 1 1]
17485  out_map[1]: (0)
17486  free: arrays: true, gens: false
17487")
17488  #
17489  unless move_sound?(gen1)
17490    snd_display("not move_sound: %s?", gen1)
17491  end
17492  if gen1 == gen2
17493    snd_display("move_sounds are equal: %s == %s?", gen1, gen2)
17494  end
17495  if gen1.channels != 1
17496    snd_display("mus_channels move_sound (1): %s?", gen1.channels)
17497  end
17498  if gen2.channels != 4
17499    snd_display("mus_channels move_sound (4): %s?", gen2.channels)
17500  end
17501  gen1.reset                    # no-op
17502  #
17503  v = Vct.new(10) do |i|
17504    move_sound(gen1, i, 0.5) + gen2.run(i, 0.25) + move_sound(gen3, i, 0.125)
17505  end
17506  unless vequal(v, Vct.new(10, 0.875))
17507    snd_display("move_sound output: %s?", v)
17508  end
17509  if (res = Snd.catch do
17510        make_move_sound([0, 1000, 1, 0, make_oscil(32), make_env([0, 0, 1, 1], :length, 1001),
17511                         make_env([0, 0, 1, 1], :length, 1001), [make_delay(32)],
17512                         [make_env([0, 0, 1, 1], :length, 1001)], false, [0, 1]],
17513                        outf1)
17514      end).first != :wrong_type_arg
17515    snd_display("make_move_sound bad doppler delay: %s", res.inspect)
17516  end
17517  if (res = Snd.catch do
17518        make_move_sound([0, 1000, 1, 0, make_oscil(32), make_env([0, 0, 1, 1], :length, 1001),
17519                         make_env([0, 0, 1, 1], :length, 1001), [make_delay(32)]],
17520                        outf1)
17521      end).first != :wrong_type_arg
17522    snd_display("make_move_sound truncated list: %s", res.inspect)
17523  end
17524  if (res = Snd.catch do
17525        make_move_sound([0, 1000, 1, 0, make_delay(32), make_env([0, 0, 1, 1], :length, 1001),
17526                         false, [false],
17527                         [make_env([0, 0, 1, 1], :length, 1001)], false, false],
17528                        outf1)
17529      end).first != :wrong_type_arg
17530    snd_display("make_move_sound no out map: %s", res.inspect)
17531  end
17532  mus_close(outf1)
17533  mus_close(outf4)
17534  mus_close(revf)
17535  delete_file("fmv.snd")
17536  delete_file("fmv1.snd")
17537  delete_file("fmv2.snd")
17538  mus_sound_prune
17539end
17540
17541def test_08_15
17542  if (res = Snd.catch do make_src(:width, -1) end).first != :out_of_range
17543    snd_display("make_src bad width: %s", res.inspect)
17544  end
17545  #
17546  s1 = make_src(lambda do |y| 1.0 end, 2.0)
17547  src(s1, 25.0)
17548  src(s1, 25.0)
17549  src(s1, 125.0)
17550  src(s1, -25.0)
17551  src(s1, -125.0)
17552  10.times do |i|
17553    make_src(lambda do |y|
17554               1.0
17555             end,
17556             1.5,
17557             :width, 5 + i * 10)
17558  end
17559  #
17560  ctr = 0.0
17561  gen = make_src(:srate, 2.0, :input, lambda do |dir|
17562                   val = ctr
17563                   ctr += 1.0
17564                   val
17565                 end)
17566  v0 = make_vct!(10) do
17567    src(gen, 0.0)
17568  end
17569  ctr = 0.0
17570  gen.reset
17571  v0.each_with_index do |old_val, i|
17572    snd_test_neq(old_val, src(gen, 0.0), "reset src %d", i)
17573  end
17574  #
17575  so1 = lambda do |ss, pp|
17576    src(ss, env(pp))
17577  end
17578  s1 = make_src(:srate, 2.0, :input, make_readin("oboe.snd", 0, 10000))
17579  s2 = make_src(:srate, 2.0, :input, make_readin("oboe.snd", 0, 10000))
17580  s3 = make_src(:srate, 2.0, :input, make_readin("oboe.snd", 0, 10000))
17581  e1 = make_env([0, 1, 2, 0.5], :duration, 1000)
17582  e2 = make_env([0, 1, 2, 0.5], :duration, 1000)
17583  e3 = make_env([0, 1, 2, 0.5], :duration, 1000)
17584  100.times do |i|
17585    x1 = src(s1, env(e1))
17586    ex2 = env(e2)
17587    x2 = src(s2, ex2)
17588    x3 = so1.call(s3, e3)
17589    snd_test_neq(x1, x2, "%d", i)
17590    snd_test_neq(x1, x3, "%d", i)
17591  end
17592  #
17593  gen = make_granulate(:expansion, 2.0,
17594                       :input, make_readin("oboe.snd", 0, 4000, 1, 2048))
17595  gen1 = make_granulate(:expansion, 2.0)
17596  rd1 = make_readin(:file, "oboe.snd",
17597                    :channel, 0,
17598                    :start, 4000,
17599                    :direction, 1,
17600                    :size, mus_file_buffer_size)
17601  print_and_check(gen,
17602                  "granulate",
17603                  "granulate expansion: 2.000 (551/1102), scaler: 0.600, length: 0.150 secs (3308 samps), ramp: 0.060")
17604  v0 = make_vct!(1000) do
17605    granulate(gen)
17606  end
17607  v1 = make_vct(1000)
17608  v1.map! do |x|
17609    granulate?(gen1) ? granulate(gen1, lambda do |dir| readin(rd1) end) : -1.0
17610  end
17611  if (worst = (vct_peak(v0) - vct_peak(v1)).abs) > 0.01
17612    snd_display("run granulate: %s?", worst)
17613  end
17614  genx = gen1
17615  unless genx.eql?(gen1)
17616    snd_display("granulate eql? %s %s %s", genx, gen1, genx.eql?(gen1))
17617  end
17618  if gen.eql? gen1
17619    snd_display("granulate eql? %s %s?", gen, gen1)
17620  end
17621  if vct_peak(v0).zero?
17622    snd_display("granulate output peak: %s?", vct_peak(v0))
17623  end
17624  unless granulate?(gen)
17625    snd_display("%s not granulate?", gen)
17626  end
17627  if fneq(gen.increment, 2.0)
17628    snd_display("granulate increment: %s?", gen.increment)
17629  end
17630  if fneq(gen.scaler, 0.6)
17631    snd_display("granulate scaler: %s?", gen.scaler)
17632  end
17633  if ffneq(gen.frequency, 0.05)
17634    snd_display("granulate frequency: %s?", gen.frequency)
17635  end
17636  if gen.ramp != 1323
17637    snd_display("granulate ramp: %s?", gen.ramp)
17638  end
17639  if gen.length != 3308
17640    snd_display("granulate length: %s?", gen.length)
17641  end
17642  if gen.hop != 1102
17643    snd_display("granulate hop: %s?", gen.hop)
17644  end
17645  gen.hop = 1000
17646  if gen.hop != 1000
17647    snd_display("granulate set_hop: %s?", gen.hop)
17648  end
17649  gen.ramp = 1000
17650  if gen.ramp != 1000
17651    snd_display("granulate set_ramp: %s?", gen.ramp)
17652  end
17653  gen.length = 3000
17654  if gen.length != 3000
17655    snd_display("granulate set_length: %s?", gen.length)
17656  end
17657  gen.increment = 3.0
17658  if ffneq(gen.increment, 3.0)
17659    snd_display("granulate set_increment: %s?", gen.increment)
17660  end
17661  gen.location = 1
17662  if gen.location != 1
17663    snd_display("granulate set_location: %s?", gen.location)
17664  end
17665  gen.frequency = 0.1
17666  if fneq(gen.frequency, 0.1)
17667    snd_display("granulate set_frequency: %s?", gen.frequency)
17668  end
17669  #
17670  if (res = Snd.catch do
17671        make_granulate(:hop, 35.0, :length, 35.0)
17672      end).first != :out_of_range
17673    snd_display("make_granulate bad sizes: %s", res.inspect)
17674  end
17675  #
17676  ind = open_sound("oboe.snd")
17677  mx = maxamp(ind, 0)
17678  rd = make_sampler(0)
17679  grn = make_granulate(:expansion, 2.0,
17680                       :input, lambda do |dir| rd.call end,
17681                       :edit, lambda do |g|
17682                         g.data.scale!(2.0)
17683                         0
17684                       end)
17685  map_channel(lambda do |y| granulate(grn) end)
17686  if (maxamp() / mx) < 1.4 or (mx / maxamp()) > 2.5
17687    snd_display("gran edit 2* (0): %s %s?", mx, maxamp())
17688  end
17689  undo_edit
17690  rd = make_sampler(0)
17691  grn = make_granulate(:expansion, 2.0,
17692                       :input, lambda do |dir| read_sample(rd) end,
17693                       :edit, lambda do |g|
17694                         g.data.scale!(4.0)
17695                         0
17696                       end)
17697  map_channel(lambda do |y| granulate(grn) end)
17698  if (maxamp() / mx) < 3.0 or (mx / maxamp()) > 6.0
17699    snd_display("gran edit 4* (0): %s %s?", mx, maxamp())
17700  end
17701  revert_sound(ind)
17702  rd = make_sampler(0)
17703  grn = make_granulate(:expansion, 2.0,
17704                       :input, lambda do |dir| read_sample(rd) end,
17705                       :edit, lambda do |g|
17706                         g.data.scale!(2.0)
17707                         0
17708                       end)
17709  map_channel(lambda do |y| granulate(grn) end)
17710  if (maxamp() / mx) < 1.4 or (mx / maxamp()) > 2.5
17711    snd_display("gran edit 2* (1): %s %s?", mx, maxamp())
17712  end
17713  undo_edit
17714  rd = make_sampler(0)
17715  grn = make_granulate(:expansion, 2.0,
17716                       :input, lambda do |dir| read_sample(rd) end,
17717                       :edit, lambda do |g|
17718                         g.data.scale!(4.0)
17719                         0
17720                       end)
17721  map_channel(lambda do |y| granulate(grn) end)
17722  if (maxamp() / mx) < 2.9 or (mx / maxamp()) > 6.0
17723    snd_display("gran edit 4* (1): %s %s?", mx, maxamp())
17724  end
17725  revert_sound(ind)
17726  # XXX: grn = make_granulate(:expansion, 2.0, :input, make_sampler(0))
17727  # Doesn't work with Ruby; make_sampler is not a procedure.
17728  rd = make_sampler(0)
17729  input_fnc = lambda do |dir|
17730    rd.call
17731  end
17732  edit_fnc = lambda do |g|
17733    g.data.scale!(2.0)
17734    0
17735  end
17736  grn = make_granulate(:expansion, 2.0, :input, input_fnc, :edit, edit_fnc)
17737  map_channel(lambda do |y| granulate(grn) end)
17738  if (maxamp() / mx) < 1.4 or (mx / maxamp()) > 2.5
17739    snd_display("gran edit 2* (2): %s %s?", mx, maxamp())
17740  end
17741  undo_edit
17742  rd = make_sampler(0)
17743  grn = make_granulate(:expansion, 2.0)
17744  map_channel(lambda do |y|
17745    granulate(grn,
17746              lambda do |dir| rd.call end,
17747              lambda do |g|
17748                g.data.scale!(4.0)
17749                0
17750              end)
17751  end)
17752  if (maxamp() / mx) < 3.0 or (mx / maxamp()) > 6.0
17753    snd_display("gran edit 4* (2): %s %s?", mx, maxamp())
17754  end
17755  close_sound(ind)
17756  ind = open_sound("oboe.snd")
17757  rd = make_sampler(0)
17758  grn = make_granulate(:expansion, 2.0, :length, 0.01, :hop, 0.05,
17759                       :input, lambda do |dir| next_sample(rd) end)
17760  map_channel(lambda do |y| granulate(grn) end)
17761  if (res = maxamp) > 0.2
17762    snd_display("trouble in granulate len 0.01 hop 0.05: %s?", res)
17763  end
17764  undo_edit
17765  rd = make_sampler(0)
17766  grn = make_granulate(:expansion, 2.0, :length, 0.04, :hop, 0.05,
17767                       :input, lambda do |dir| next_sample(rd) end)
17768  map_channel(lambda do |y| granulate(grn) end)
17769  if (res = maxamp) > 0.2
17770    snd_display("trouble in granulate len 0.04 hop 0.05: %s?", res)
17771  end
17772  undo_edit
17773  rd = make_sampler(0)
17774  grn = make_granulate(:expansion, 2.0, :length, 0.01, :hop, 0.25,
17775                       :input, lambda do |dir| next_sample(rd) end)
17776  map_channel(lambda do |y| granulate(grn) end)
17777  if (res = maxamp) > 0.2
17778    snd_display("trouble in granulate len 0.01 hop 0.25: %s?", res)
17779  end
17780  undo_edit
17781  rd = make_sampler(0)
17782  grn = make_granulate(:expansion, 2.0, :length, 0.4, :hop, 0.5,
17783                       :input, lambda do |dir| next_sample(rd) end)
17784  map_channel(lambda do |y| granulate(grn) end)
17785  if (res = maxamp) > 0.2
17786    snd_display("trouble in granulate len 0.4 hop 0.5: %s?", res)
17787  end
17788  undo_edit
17789  close_sound(ind)
17790end
17791
17792def test_08_16
17793  ind = new_sound(:size, 1000)
17794  gen = make_granulate(:jitter, 0.0, :hop, 0.004, :length, 0.001,
17795                       :input, lambda do |dir| 0.1 end)
17796  map_channel(lambda do |y| granulate(gen) end)
17797  if fneq(res = maxamp, 0.06)
17798    snd_display("gran 0 max: %s?", res)
17799  end
17800  unless vequal(res = channel2vct(0, 30),
17801                vct(0.000, 0.007, 0.013, 0.020, 0.027, 0.033, 0.040, 0.047,
17802                    0.053, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.053,
17803                    0.047, 0.040, 0.033, 0.027, 0.020, 0.013, 0.007, 0.000,
17804                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
17805    snd_display("gran 0 data: %s?", res)
17806  end
17807  unless vequal(res = channel2vct(85, 30),
17808                vct(0.000, 0.000, 0.000, 0.000, 0.007, 0.013, 0.020, 0.027,
17809                    0.033, 0.040, 0.047, 0.053, 0.060, 0.060, 0.060, 0.060,
17810                    0.060, 0.060, 0.053, 0.047, 0.040, 0.033, 0.027, 0.020,
17811                    0.013, 0.007, 0.000, 0.000, 0.000, 0.000))
17812    snd_display("gran 0 data 85: %s?", res)
17813  end
17814  undo_edit
17815  gen = make_granulate(:jitter, 0.0, :hop, 0.002, :length, 0.001,
17816                       :input, lambda do |dir| 0.1 end)
17817  map_channel(lambda do |y| granulate(gen) end)
17818  if fneq(res = maxamp, 0.06)
17819    snd_display("gran 1 max: %s?", res)
17820  end
17821  unless vequal(res = channel2vct(0, 30),
17822                vct(0.000, 0.007, 0.013, 0.020, 0.027, 0.033, 0.040, 0.047,
17823                    0.053, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.053,
17824                    0.047, 0.040, 0.033, 0.027, 0.020, 0.013, 0.007, 0.000,
17825                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
17826    snd_display("gran 1 data: %s?", res)
17827  end
17828  unless vequal(res = channel2vct(40, 30),
17829                vct(0.000, 0.000, 0.000, 0.000, 0.000, 0.007, 0.013, 0.020,
17830                    0.027, 0.033, 0.040, 0.047, 0.053, 0.060, 0.060, 0.060,
17831                    0.060, 0.060, 0.060, 0.053, 0.047, 0.040, 0.033, 0.027,
17832                    0.020, 0.013, 0.007, 0.000, 0.000, 0.000))
17833    snd_display("gran 1 data 40: %s?", res)
17834  end
17835  undo_edit
17836  gen = make_granulate(:jitter, 0.0, :hop, 0.002, :length, 0.001, :ramp, 0.1,
17837                       :input, lambda do |dir| 0.1 end)
17838  map_channel(lambda do |y| granulate(gen) end)
17839  if fneq(res = maxamp, 0.06)
17840    snd_display("gran 2 max: %s?", res)
17841  end
17842  unless vequal(res = channel2vct(0, 30),
17843                vct(0.000, 0.030, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
17844                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
17845                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.030, 0.000,
17846                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
17847    snd_display("gran 2 data: %s?", res)
17848  end
17849  unless vequal(res = channel2vct(40, 30),
17850                vct(0.000, 0.000, 0.000, 0.000, 0.000, 0.030, 0.060, 0.060,
17851                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
17852                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
17853                    0.060, 0.060, 0.030, 0.000, 0.000, 0.000))
17854    snd_display("gran 2 data 40: %s?", res)
17855  end
17856  undo_edit
17857  gen = make_granulate(:jitter, 0.0, :hop, 0.002, :length, 0.001, :ramp, 0.5,
17858                       :input, lambda do |dir| 0.1 end)
17859  map_channel(lambda do |y| granulate(gen) end)
17860  if fneq(res = maxamp, 0.06)
17861    snd_display("gran 3 max: %s?", res)
17862  end
17863  unless vequal(res = channel2vct(0, 30),
17864                vct(0.000, 0.005, 0.011, 0.016, 0.022, 0.027, 0.033, 0.038,
17865                    0.044, 0.049, 0.055, 0.060, 0.060, 0.055, 0.049, 0.044,
17866                    0.038, 0.033, 0.027, 0.022, 0.016, 0.011, 0.005, 0.000,
17867                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
17868    snd_display("gran 3 data: %s?", res)
17869  end
17870  unless vequal(res = channel2vct(85, 30),
17871                vct(0.000, 0.000, 0.000, 0.000, 0.005, 0.011, 0.016, 0.022,
17872                    0.027, 0.033, 0.038, 0.044, 0.049, 0.055, 0.060, 0.060,
17873                    0.055, 0.049, 0.044, 0.038, 0.033, 0.027, 0.022, 0.016,
17874                    0.011, 0.005, 0.000, 0.000, 0.000, 0.000))
17875    snd_display("gran 3 data 85: %s?", res)
17876  end
17877  undo_edit
17878  gen = make_granulate(:jitter, 0.0, :hop, 0.001, :length, 0.001, :ramp, 0.5,
17879                       :input, lambda do |dir| 0.1 end)
17880  map_channel(lambda do |y| granulate(gen) end)
17881  if fneq(res = maxamp, 0.06)
17882    snd_display("gran 4 max: %s?", res)
17883  end
17884  unless vequal(res = channel2vct(0, 30),
17885                vct(0.000, 0.005, 0.011, 0.016, 0.022, 0.027, 0.033, 0.038,
17886                    0.044, 0.049, 0.055, 0.060, 0.060, 0.055, 0.049, 0.044,
17887                    0.038, 0.033, 0.027, 0.022, 0.016, 0.011, 0.005, 0.005,
17888                    0.011, 0.016, 0.022, 0.027, 0.033, 0.038))
17889    snd_display("gran 4 data: %s?", res)
17890  end
17891  unless vequal(res = channel2vct(85, 30),
17892                vct(0.022, 0.016, 0.011, 0.005, 0.005, 0.011, 0.016, 0.022,
17893                    0.027, 0.033, 0.038, 0.044, 0.049, 0.055, 0.060, 0.060,
17894                    0.055, 0.049, 0.044, 0.038, 0.033, 0.027, 0.022, 0.016,
17895                    0.011, 0.005, 0.005, 0.011, 0.016, 0.022))
17896    snd_display("gran 4 data 85: %s?", res)
17897  end
17898  undo_edit
17899  gen = make_granulate(:jitter, 0.0, :hop, 0.001, :length, 0.001, :ramp, 0.25,
17900                       :scaler, 1.0, :input, lambda do |dir| 0.1 end)
17901  map_channel(lambda do |y| granulate(gen) end)
17902  if fneq(res = maxamp, 0.1)
17903    snd_display("gran 5 max: %s?", res)
17904  end
17905  unless vequal(res = channel2vct(0, 30),
17906                vct(0.000, 0.020, 0.040, 0.060, 0.080, 0.100, 0.100, 0.100,
17907                    0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100,
17908                    0.100, 0.100, 0.100, 0.080, 0.060, 0.040, 0.020, 0.020,
17909                    0.040, 0.060, 0.080, 0.100, 0.100, 0.100))
17910    snd_display("gran 5 data: %s?", res)
17911  end
17912  unless vequal(res = channel2vct(85, 30),
17913                vct(0.080, 0.060, 0.040, 0.020, 0.020, 0.040, 0.060, 0.080,
17914                    0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100,
17915                    0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.080, 0.060,
17916                    0.040, 0.020, 0.020, 0.040, 0.060, 0.080))
17917    snd_display("gran 5 data 85: %s?", res)
17918  end
17919  undo_edit
17920  gen = make_granulate(:jitter, 0.0, :hop, 0.001, :length, 0.002, :ramp, 0.5,
17921                       :scaler, 1.0, :input, lambda do |dir| 0.1 end)
17922  map_channel(lambda do |y| granulate(gen) end)
17923  if fneq(res = maxamp, 0.105)
17924    snd_display("gran 6 max: %s?", res)
17925  end
17926  unless vequal(res = channel2vct(0, 30),
17927                vct(0.000, 0.005, 0.009, 0.014, 0.018, 0.023, 0.027, 0.032,
17928                    0.036, 0.041, 0.045, 0.050, 0.055, 0.059, 0.064, 0.068,
17929                    0.073, 0.077, 0.082, 0.086, 0.091, 0.095, 0.100, 0.105,
17930                    0.105, 0.105, 0.105, 0.105, 0.105, 0.105))
17931    snd_display("gran 6 data: %s?", res)
17932  end
17933  unless vequal(res = channel2vct(85, 30),
17934                vct(0.105, 0.105, 0.105, 0.105, 0.105, 0.105, 0.105, 0.105,
17935                    0.105, 0.105, 0.105, 0.105, 0.105, 0.105, 0.105, 0.105,
17936                    0.105, 0.105, 0.105, 0.105, 0.105, 0.105, 0.105, 0.105,
17937                    0.105, 0.105, 0.105, 0.105, 0.105, 0.105))
17938    snd_display("gran 6 data 85: %s?", res)
17939  end
17940  undo_edit
17941  gen = make_granulate(:jitter, 0.0, :hop, 0.001, :length, 0.005, :ramp, 0.5,
17942                       :scaler, 1.0, :input, lambda do |dir| 0.1 end)
17943  map_channel(lambda do |y| granulate(gen) end)
17944  if fneq(res = maxamp, 0.264)
17945    snd_display("gran 7 max: %s?", res)
17946  end
17947  unless vequal(res = channel2vct(0, 30),
17948                vct(0.000, 0.002, 0.004, 0.005, 0.007, 0.009, 0.011, 0.013,
17949                    0.015, 0.016, 0.018, 0.020, 0.022, 0.024, 0.025, 0.027,
17950                    0.029, 0.031, 0.033, 0.035, 0.036, 0.038, 0.040, 0.044,
17951                    0.047, 0.051, 0.055, 0.058, 0.062, 0.065))
17952    snd_display("gran 7 data: %s?", res)
17953  end
17954  unless vequal(res = channel2vct(85, 30),
17955                vct(0.244, 0.244, 0.244, 0.244, 0.245, 0.247, 0.249, 0.251,
17956                    0.253, 0.255, 0.256, 0.258, 0.260, 0.262, 0.264, 0.264,
17957                    0.262, 0.260, 0.258, 0.256, 0.255, 0.253, 0.251, 0.249,
17958                    0.247, 0.245, 0.245, 0.247, 0.249, 0.251))
17959    snd_display("gran 7 data 85: %s?", res)
17960  end
17961  undo_edit
17962  gen = make_granulate(:jitter, 0.0, :hop, 0.01, :length, 0.001, :ramp, 0.5,
17963                       :scaler, 1.0, :expansion, 2.0,
17964                       :input, lambda do |dir| 0.1 end)
17965  map_channel(lambda do |y| granulate(gen) end)
17966  if fneq(res = maxamp, 0.1)
17967    snd_display("gran 8 max: %s?", res)
17968  end
17969  unless vequal(res = channel2vct(0, 30),
17970                vct(0.000, 0.009, 0.018, 0.027, 0.036, 0.045, 0.055, 0.064,
17971                    0.073, 0.082, 0.091, 0.100, 0.100, 0.091, 0.082, 0.073,
17972                    0.064, 0.055, 0.045, 0.036, 0.027, 0.018, 0.009, 0.000,
17973                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
17974    snd_display("gran 8 data: %s?", res)
17975  end
17976  unless vequal(res = channel2vct(220, 30),
17977                vct(0.000, 0.009, 0.018, 0.027, 0.036, 0.045, 0.055, 0.064,
17978                    0.073, 0.082, 0.091, 0.100, 0.100, 0.091, 0.082, 0.073,
17979                    0.064, 0.055, 0.045, 0.036, 0.027, 0.018, 0.009, 0.000,
17980                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
17981    snd_display("gran 8 data 220: %s?", res)
17982  end
17983  undo_edit
17984  gen = make_granulate(:jitter, 0.0, :hop, 0.01, :length, 0.001, :ramp, 0.5,
17985                       :scaler, 1.0, :expansion, 0.5,
17986                       :input, lambda do |dir| 0.1 end)
17987  map_channel(lambda do |y| granulate(gen) end)
17988  if fneq(res = maxamp, 0.1)
17989    snd_display("gran 9 max: %s?", res)
17990  end
17991  unless vequal(res = channel2vct(0, 30),
17992                vct(0.000, 0.009, 0.018, 0.027, 0.036, 0.045, 0.055, 0.064,
17993                    0.073, 0.082, 0.091, 0.100, 0.100, 0.091, 0.082, 0.073,
17994                    0.064, 0.055, 0.045, 0.036, 0.027, 0.018, 0.009, 0.000,
17995                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
17996    snd_display("gran 9 data: %s?", res)
17997  end
17998  unless vequal(res = channel2vct(220, 30),
17999                vct(0.000, 0.009, 0.018, 0.027, 0.036, 0.045, 0.055, 0.064,
18000                    0.073, 0.082, 0.091, 0.100, 0.100, 0.091, 0.082, 0.073,
18001                    0.064, 0.055, 0.045, 0.036, 0.027, 0.018, 0.009, 0.000,
18002                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
18003    snd_display("gran 9 data 220: %s?", res)
18004  end
18005  undo_edit
18006  gen = make_granulate(:jitter, 0.0, :hop, 0.001, :length, 0.005, :ramp, 0.5, :scaler, 1.0)
18007  map_channel(lambda do |y|
18008                granulate(gen,
18009                          lambda do |dir| 0.1 end,
18010                          lambda do |g|
18011                            g.data.scale!(2.0)
18012                            0
18013                          end)
18014              end)
18015  if fneq(res = maxamp, 2 * 0.264)
18016    snd_display("gran 10 max: %s?", res)
18017  end
18018  unless vequal(vct_scale!(res = channel2vct(0, 30), 0.5),
18019                vct(0.000, 0.002, 0.004, 0.005, 0.007, 0.009, 0.011, 0.013,
18020                    0.015, 0.016, 0.018, 0.020, 0.022, 0.024, 0.025, 0.027,
18021                    0.029, 0.031, 0.033, 0.035, 0.036, 0.038, 0.040, 0.044,
18022                    0.047, 0.051, 0.055, 0.058, 0.062, 0.065))
18023    snd_display("gran 10 data: %s?", res)
18024  end
18025  unless vequal(vct_scale!(res = channel2vct(85, 30), 0.5),
18026                vct(0.244, 0.244, 0.244, 0.244, 0.245, 0.247, 0.249, 0.251,
18027                    0.253, 0.255, 0.256, 0.258, 0.260, 0.262, 0.264, 0.264,
18028                    0.262, 0.260, 0.258, 0.256, 0.255, 0.253, 0.251, 0.249,
18029                    0.247, 0.245, 0.245, 0.247, 0.249, 0.251))
18030    snd_display("gran 10 data 85: %s?", res)
18031  end
18032  undo_edit
18033  gen = make_granulate(:jitter, 0.0, :hop, 0.005, :length, 0.002,
18034                       :ramp, 0.0, :scaler, 1.0)
18035  forward = true
18036  ctr = -0.5
18037  incr = 0.001
18038  map_channel(lambda do |y|
18039                granulate(gen,
18040                          lambda do |dir|
18041                            ctr += incr
18042                            ctr
18043                          end,
18044                          lambda do |g|
18045                            len = g.length
18046                            if forward
18047                              forward = false
18048                            else
18049                              forward = true
18050                              vct_reverse!(g.data, len)
18051                            end
18052                            len
18053                          end)
18054              end)
18055  if (res = maxamp) > 0.6
18056    snd_display("gran 11 max: %s?", res)
18057  end
18058  unless vequal(res = channel2vct(0, 30),
18059                vct(-0.499, -0.498, -0.497, -0.496, -0.495, -0.494, -0.493, -0.492,
18060                    -0.491, -0.490, -0.489, -0.488, -0.487, -0.486, -0.485, -0.484,
18061                    -0.483, -0.482, -0.481, -0.480, -0.479, -0.478, -0.477, -0.476,
18062                    -0.475, -0.474, -0.473, -0.472, -0.471, -0.470))
18063    snd_display("gran 11 data: %s?", res)
18064  end
18065  unless vequal(res = channel2vct(100, 30),
18066                vct(0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
18067                    0.000, 0.000, -0.345, -0.346, -0.347, -0.348, -0.349, -0.350,
18068                    -0.351, -0.352, -0.353, -0.354, -0.355, -0.356, -0.357, -0.358,
18069                    -0.359, -0.360, -0.361, -0.362, -0.363, -0.364))
18070    snd_display("gran 11 data 100: %s?", res)
18071  end
18072  undo_edit
18073  ctr = -0.5
18074  incr = 0.001
18075  gen = make_granulate(:jitter, 0.0, :hop, 0.005, :length, 0.002, :ramp, 0.0,
18076                       :scaler, 1.0,
18077                       :input, lambda do |dir|
18078                         ctr += incr
18079                       end)
18080  map_channel(lambda do |y| granulate(gen) end)
18081  if (res = maxamp) > 0.6
18082    snd_display("gran 12 max: %s?", res)
18083  end
18084  unless vequal(res = channel2vct(0, 30),
18085                vct(-0.499, -0.498, -0.497, -0.496, -0.495, -0.494, -0.493, -0.492,
18086                    -0.491, -0.490, -0.489, -0.488, -0.487, -0.486, -0.485, -0.484,
18087                    -0.483, -0.482, -0.481, -0.480, -0.479, -0.478, -0.477, -0.476,
18088                    -0.475, -0.474, -0.473, -0.472, -0.471, -0.470))
18089    snd_display("gran 12 data: %s?", res)
18090  end
18091  unless vequal(res = channel2vct(100, 30),
18092                vct(0.0, 0.0, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
18093                    0.0, 0.0, -0.389, -0.388, -0.387, -0.386, -0.385, -0.384,
18094                    -0.383, -0.382, -0.381, -0.38,
18095                    -0.379, -0.378, -0.377, -0.376,
18096                    -0.375, -0.374, -0.373, -0.372, -0.371, -0.370))
18097    snd_display("gran 12 data 100: %s?", res)
18098  end
18099  undo_edit
18100  gen = make_granulate(:jitter, 0.0, :hop, 0.001, :length, 0.005, :ramp, 0.5,
18101                       :scaler, 1.0,
18102                       :input, lambda do |dir| 0.1 end,
18103                       :edit, lambda do |g|
18104                         g.data.scale!(2.0)
18105                         0
18106                       end)
18107  map_channel(lambda do |y| granulate(gen) end)
18108  if (res = maxamp) > 0.6
18109    snd_display("gran 13 max: %s?", res)
18110  end
18111  unless vequal(vct_scale!(res = channel2vct(0, 30), 0.5),
18112                vct(0.000, 0.002, 0.004, 0.005, 0.007, 0.009, 0.011, 0.013,
18113                    0.015, 0.016, 0.018, 0.020, 0.022, 0.024, 0.025, 0.027,
18114                    0.029, 0.031, 0.033, 0.035, 0.036, 0.038, 0.040, 0.044,
18115                    0.047, 0.051, 0.055, 0.058, 0.062, 0.065))
18116    snd_display("gran 13 data: %s?", res)
18117  end
18118  unless vequal(vct_scale!(res = channel2vct(85, 30), 0.5),
18119                vct(0.244, 0.244, 0.244, 0.244, 0.245, 0.247, 0.249, 0.251,
18120                    0.253, 0.255, 0.256, 0.258, 0.260, 0.262, 0.264, 0.264,
18121                    0.262, 0.260, 0.258, 0.256, 0.255, 0.253, 0.251, 0.249,
18122                    0.247, 0.245, 0.245, 0.247, 0.249, 0.251))
18123    snd_display("gran 13 data 85: %s?", res)
18124  end
18125  undo_edit
18126  forward = true
18127  ctr = -0.5
18128  incr = 0.001
18129  gen = make_granulate(:jitter, 0.0, :hop, 0.005, :length, 0.002, :ramp, 0.0,
18130                       :scaler, 1.0,
18131                       :input, lambda do |dir|
18132                         ctr += incr
18133                         ctr
18134                       end,
18135                       :edit, lambda do |g|
18136                         len = mus_length(g)
18137                         if forward
18138                           forward = false
18139                         else
18140                           forward = true
18141                           vct_reverse!(mus_data(g), len)
18142                         end
18143                         len
18144                       end)
18145  map_channel(lambda do |y| granulate(gen) end)
18146  if (res = maxamp) > 0.6
18147    snd_display("gran 14 max: %s?", res)
18148  end
18149  unless vequal(res = channel2vct(0, 30),
18150                vct(-0.499, -0.498, -0.497, -0.496, -0.495, -0.494, -0.493, -0.492,
18151                    -0.491, -0.490, -0.489, -0.488, -0.487, -0.486, -0.485, -0.484,
18152                    -0.483, -0.482, -0.481, -0.480, -0.479, -0.478, -0.477, -0.476,
18153                    -0.475, -0.474, -0.473, -0.472, -0.471, -0.470))
18154    snd_display("gran 14 data: %s?", res)
18155  end
18156  unless vequal(res = channel2vct(100, 30),
18157                vct(0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
18158                    0.000, 0.000, -0.345, -0.346, -0.347, -0.348, -0.349, -0.350,
18159                    -0.351, -0.352, -0.353, -0.354, -0.355, -0.356, -0.357, -0.358,
18160                    -0.359, -0.360, -0.361, -0.362, -0.363, -0.364))
18161    snd_display("gran 14 data 100: %s?", res)
18162  end
18163  undo_edit
18164  #
18165  gen = make_granulate(:jitter, 0.0, :hop, 0.004, :length, 0.001, :ramp, 0.0,
18166                       :input, lambda do |dir| 0.1 end)
18167  e = make_env(:envelope, [0, 0, 1, 0.5], :length, 1001)
18168  base_ramp_len = mus_length(gen)
18169  map_channel(lambda do |y|
18170                result = granulate(gen)
18171                set_mus_ramp(gen, (base_ramp_len * env(e)).round)
18172                result
18173              end)
18174  if fneq(res = maxamp, 0.06)
18175    snd_display("granf 0 max: %s?", res)
18176  end
18177  if (mus_ramp(gen) - 0.5 * mus_length(gen)).abs > 1
18178    snd_display("granf 0 ramp: %s %s?", gen.ramp, gen.length)
18179  end
18180  unless vequal(res = channel2vct(0, 30),
18181                vct(0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
18182                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
18183                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.000,
18184                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
18185    snd_display("granf 0 data: %s?", res)
18186  end
18187  unless vequal(res = channel2vct(440, 30),
18188                vct(0.000, 0.012, 0.024, 0.036, 0.048, 0.060, 0.060, 0.060,
18189                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
18190                    0.060, 0.060, 0.060, 0.048, 0.036, 0.024, 0.012, 0.000,
18191                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
18192    snd_display("granf 0 data 440: %s?", res)
18193  end
18194  unless vequal(res = channel2vct(880, 30),
18195                vct(0.000, 0.006, 0.012, 0.018, 0.024, 0.030, 0.036, 0.042,
18196                    0.048, 0.054, 0.060, 0.060, 0.060, 0.060, 0.054, 0.048,
18197                    0.042, 0.036, 0.030, 0.024, 0.018, 0.012, 0.006, 0.000,
18198                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
18199    snd_display("granf 0 data 880: %s?", res)
18200  end
18201  undo_edit
18202  gen = make_granulate(:jitter, 0.0, :hop, 0.004, :length, 0.001, :ramp, 0.0,
18203                       :input, lambda do |dir| 0.1 end)
18204  e = make_env(:envelope, [0, 1, 1, 0.25], :length, 1001)
18205  base_hop_len = mus_hop(gen)
18206  map_channel(lambda do |y|
18207                result = granulate(gen)
18208                set_mus_hop(gen, (base_hop_len * env(e)).round)
18209                result
18210              end)
18211  if fneq(res = maxamp, 0.06)
18212    snd_display("granf 1 max: %s?", res)
18213  end
18214  if (mus_hop(gen) - 0.001 * mus_srate).abs > 1
18215    snd_display("granf 1 hop: %s?", gen.hop)
18216  end
18217  unless vequal(res = channel2vct(0, 30),
18218                vct(0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
18219                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
18220                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.000,
18221                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
18222    snd_display("granf 1 data: %s?", res)
18223  end
18224  unless vequal(res = channel2vct(900, 30),
18225                vct(0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
18226                    0.060, 0.060, 0.060, 0.060, 0.000, 0.000, 0.000, 0.000,
18227                    0.000, 0.000, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
18228                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060))
18229    snd_display("granf 1 data 900: %s?", res)
18230  end
18231  undo_edit
18232  gen = make_granulate(:jitter, 0.0, :hop, 0.004, :length, 0.001, :ramp, 0.0,
18233                       :input, lambda do |dir| 0.1 end)
18234  e = make_env(:envelope, [0, 1, 1, 0.25], :length, 1001)
18235  base_freq = mus_frequency(gen)
18236  map_channel(lambda do |y|
18237                result = granulate(gen)
18238                set_mus_frequency(gen, base_freq * env(e))
18239                result
18240              end)
18241  if fneq(res = maxamp, 0.06)
18242    snd_display("granf 2 max: %s?", res)
18243  end
18244  if (mus_hop(gen) - 0.001 * mus_srate).abs > 1
18245    snd_display("granf 2 hop: %s?", gen.hop)
18246  end
18247  unless vequal(res = channel2vct(0, 30),
18248                vct(0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
18249                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
18250                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.000,
18251                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
18252    snd_display("granf 2 data: %s?", res)
18253  end
18254  unless vequal(res = channel2vct(900, 30),
18255                vct(0.060, 0.060, 0.060, 0.060, 0.060, 0.000, 0.000, 0.000,
18256                    0.000, 0.000, 0.000, 0.060, 0.060, 0.060, 0.060, 0.060,
18257                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
18258                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060))
18259    snd_display("granf 2 data 900: %s?", res)
18260  end
18261  undo_edit
18262  gen = make_granulate(:jitter, 0.0, :hop, 0.002, :length, 0.001, :ramp, 0.0,
18263                       :scaler, 1.0, :input, lambda do |dir| 0.1 end)
18264  base_freq = mus_frequency(gen)
18265  map_channel(lambda do |y| granulate(gen) end)
18266  if fneq(res = maxamp, 0.1)
18267    snd_display("granf 3 max: %s?", res)
18268  end
18269  unless vequal(res = channel2vct(0, 30),
18270                vct(0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100,
18271                    0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100,
18272                    0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.000,
18273                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
18274    snd_display("granf 3 data: %s?", res)
18275  end
18276  undo_edit
18277  gen = make_granulate(:jitter, 0.0, :hop, 0.004, :length, 0.001, :ramp, 0.0,
18278                       :scaler, 1.0, :input, lambda do |dir| 0.1 end)
18279  e = make_env(:envelope, [0, 1, 1, 0], :length, 1001)
18280  base_freq = mus_frequency(gen)
18281  map_channel(lambda do |y|
18282                result = granulate(gen)
18283                set_mus_scaler(gen, env(e))
18284                result
18285              end)
18286  if fneq(res = maxamp, 0.1)
18287    snd_display("granf 4 max: %s?", res)
18288  end
18289  unless vequal(res = channel2vct(0, 30),
18290                vct(0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100,
18291                    0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100,
18292                    0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.100, 0.000,
18293                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
18294    snd_display("granf 4 data: %s?", res)
18295  end
18296  unless vequal(res = channel2vct(440, 30),
18297                vct(0.056, 0.056, 0.056, 0.056, 0.056, 0.056, 0.056, 0.056,
18298                    0.056, 0.056, 0.056, 0.056, 0.056, 0.056, 0.056, 0.056,
18299                    0.056, 0.056, 0.056, 0.056, 0.056, 0.056, 0.056, 0.000,
18300                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
18301    snd_display("granf 4 data 440: %s?", res)
18302  end
18303  unless vequal(res = channel2vct(900, 30),
18304                vct(0.012, 0.012, 0.012, 0.000, 0.000, 0.000, 0.000, 0.000,
18305                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
18306                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
18307                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
18308    snd_display("granf 4 data 900: %s?", res)
18309  end
18310  undo_edit
18311  gen = make_granulate(:jitter, 0.0, :hop, 0.006, :length, 0.001, :ramp, 0.0,
18312                       :max_size, 2200, :input, lambda do |dir| 0.1 end)
18313  e = make_env(:envelope, [0, 1, 1, 5], :length, 1001)
18314  base_len = mus_length(gen)
18315  map_channel(lambda do |y|
18316                result = granulate(gen)
18317                set_mus_length(gen, (base_len * env(e)).round)
18318                result
18319              end)
18320  if fneq(res = maxamp, 0.06)
18321    snd_display("granf 5 max: %s?", res)
18322  end
18323  if (gen.length - 5 * base_len).abs > 10
18324    snd_display("granf 5 length: %s %s?", mus_length(gen), 5 * base_len)
18325  end
18326  unless vequal(res = channel2vct(0, 30),
18327                vct(0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
18328                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
18329                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.000,
18330                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
18331    snd_display("granf 5 data: %s?", res)
18332  end
18333  unless vequal(res = channel2vct(440, 30),
18334                vct(0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
18335                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.000,
18336                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
18337                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
18338    snd_display("granf 5 data 440: %s?", res)
18339  end
18340  unless vequal(res = channel2vct(800, 30),
18341                vct(0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
18342                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
18343                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
18344                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060))
18345    snd_display("granf 5 data 800: %s?", res)
18346  end
18347  undo_edit
18348  gen = make_granulate(:jitter, 0.0, :hop, 0.006, :length, 0.005, :ramp, 0.0,
18349                       :max_size, 2200, :input, lambda do |dir| 0.1 end)
18350  e = make_env(:envelope, [0, 1, 1, 0.2], :length, 1001)
18351  base_len = mus_length(gen)
18352  map_channel(lambda do |y|
18353                result = granulate(gen)
18354                set_mus_length(gen, (base_len * env(e)).round)
18355                result
18356              end)
18357  if fneq(res = maxamp, 0.06)
18358    snd_display("granf 6 max: %s?", res)
18359  end
18360  if (gen.length - 0.2 * base_len).abs > 4
18361    snd_display("granf 6 length: %s %s?", mus_length(gen), 0.2 * base_len)
18362  end
18363  unless vequal(res = channel2vct(0, 30),
18364                vct(0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
18365                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
18366                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
18367                    0.060, 0.060, 0.060, 0.060, 0.060, 0.060))
18368    snd_display("granf 6 data: %s?", res)
18369  end
18370  unless vequal(res = channel2vct(820, 30),
18371                vct(0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060, 0.060,
18372                    0.060, 0.060, 0.060, 0.060, 0.060, 0.000, 0.000, 0.000,
18373                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000,
18374                    0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
18375    snd_display("granf 6 data 820: %s?", res)
18376  end
18377  undo_edit
18378  max_list = lambda do
18379    pts = []
18380    samp = 0
18381    lasty = 0.0
18382    scan_channel(lambda do |y|
18383                   if lasty < 0.1 and y >= 0.1
18384                     pts << samp
18385                   end
18386                   lasty = y
18387                   samp += 1
18388                   false
18389                 end)
18390    pts
18391  end
18392  gen = make_granulate(:jitter, 0.0, :hop, 0.01, :length, 0.001,
18393                       :ramp, 0.5, :scaler, 1.0, :expansion, 0.5,
18394                       :input, lambda do |dir| 0.1 end)
18395  map_channel(lambda do |y| granulate(gen) end)
18396  if [11, 231, 451, 671, 891] != (res = max_list.call)
18397    snd_display("grn jitter 0 max: %s?", res)
18398  end
18399  undo_edit
18400  gen = make_granulate(:jitter, 0.3, :hop, 0.01, :length, 0.001,
18401                       :ramp, 0.5, :scaler, 1.0, :expansion, 0.5,
18402                       :input, lambda do |dir| 0.1 end)
18403  map_channel(lambda do |y| granulate(gen) end)
18404  if [11, 231, 451, 671, 891] == (res = max_list.call)
18405    snd_display("grn jitter 0.3 max: %s?", res)
18406  end
18407  old_vals = res
18408  undo_edit
18409  gen = make_granulate(:jitter, 0.3, :hop, 0.01, :length, 0.001,
18410                       :ramp, 0.5, :scaler, 1.0, :expansion, 0.5,
18411                       :input, lambda do |dir| 0.1 end)
18412  map_channel(lambda do |y| granulate(gen) end)
18413  if (res = max_list.call) == old_vals
18414    snd_display("grn jitter 0.3 max: %s %s?", res, old_vals)
18415  end
18416  undo_edit
18417  old_vals = false
18418  gen = make_granulate(:jitter, 1.0, :hop, 0.01, :length, 0.001,
18419                       :ramp, 0.5, :scaler, 1.0, :expansion, 0.5,
18420                       :input, lambda do |dir| 0.1 end)
18421  seed = gen.location
18422  map_channel(lambda do |y| granulate(gen) end)
18423  old_vals = max_list.call
18424  undo_edit
18425  gen = make_granulate(:jitter, 1.0, :hop, 0.01, :length, 0.001,
18426                       :ramp, 0.5, :scaler, 1.0, :expansion, 0.5,
18427                       :input, lambda do |dir| 0.1 end)
18428  gen.location = seed
18429  map_channel(lambda do |y| granulate(gen) end)
18430  if (res = max_list.call) != old_vals
18431    snd_display("grn jitter 1.0 max with seed: %s %s?", res, old_vals)
18432  end
18433  undo_edit
18434  fname = file_name(ind)
18435  close_sound(ind)
18436  delete_file(fname)
18437end
18438
18439def test_08_17
18440  ind = new_sound("tmp.snd", 1, 22050, Mus_bfloat, Mus_next, :size, 10000)
18441  gen = make_granulate(:expansion, 20.0,
18442                       :input, lambda do |dir| 0.01 end,
18443                       :length, 0.00995,
18444                       :hop, 0.01,
18445                       :ramp, 0.0,
18446                       :scaler, 1.0,
18447                       :jitter, 0.0)
18448  clm_channel(gen)                                # 0.01 max stable
18449  if fneq(maxamp, 0.01)
18450    snd_display("granulate stable 1: %s?", maxamp)
18451  end
18452  if minval = scan_channel(lambda do |y| y < 0.0099 end)
18453    snd_display("granulate stable 1 min: %s?", minval)
18454  end
18455  undo_edit
18456  gen = make_granulate(:expansion, 20.0,
18457                       :input, lambda do |dir| 0.1 end,
18458                       :length, 0.00995,
18459                       :hop, 0.01,
18460                       :ramp, 0.0,
18461                       :scaler, 0.5,
18462                       :jitter, 0.0)
18463  clm_channel(gen)                                # 0.05 max stable
18464  if fneq(maxamp, 0.05)
18465    snd_display("granulate stable 2: %s?", maxamp)
18466  end
18467  if minval = scan_channel(lambda do |y| y < 0.0499 end)
18468    snd_display("granulate stable 2 min: %s?", minval)
18469  end
18470  undo_edit
18471  gen = make_granulate(:expansion, 20.0,
18472                       :input, lambda do |dir| 0.05 end,
18473                       :length, 0.099975,
18474                       :hop, 0.1,
18475                       :ramp, 0.0,
18476                       :scaler, 1.0,
18477                       :jitter, 0.0)
18478  clm_channel(gen)                                # 0.05 max stable
18479  if fneq(maxamp, 0.05)
18480    snd_display("granulate stable 3: %s?", maxamp)
18481  end
18482  if minval = scan_channel(lambda do |y| y < 0.0499 end)
18483    snd_display("granulate stable 3 min: %s %s?", minval, sample(minval[1]))
18484  end
18485  undo_edit
18486  ctr = 0
18487  gen = make_granulate(:expansion, 2.0,
18488                       :input, lambda do |dir|
18489                         val = ctr * 0.0001
18490                         ctr += 1
18491                         val
18492                       end,
18493                       :length, 0.01,
18494                       :hop, 0.1,
18495                       :ramp, 0.0,
18496                       :scaler, 1.0,
18497                       :jitter, 0.0)
18498  clm_channel(gen)
18499  if fneq(maxamp, 0.462)
18500    snd_display("granulate ramped 4: %s?", maxamp)
18501  end
18502  vals = count_matches(lambda do |y| y != 0.0 end)
18503  if (vals - 1104).abs > 10
18504    snd_display("granulate ramped 4 not 0.0: %s?", vals)
18505  end
18506  if (not vequal(res1 = channel2vct(2203, 10),
18507                 vct(0.000, 0.000, 0.110, 0.110, 0.110, 0.111, 0.111, 0.111, 0.111, 0.111))) or
18508      (not vequal(res2 = channel2vct(4523, 10),
18509                  vct(0.232, 0.232, 0.232, 0.232, 0.232, 0.232, 0.232, 0.232, 0.233, 0.233))) or
18510      (not vequal(res3 = channel2vct(8928, 10),
18511                  vct(0.452, 0.452, 0.452, 0.452, 0.452, 0.452, 0.452, 0.452, 0.452, 0.452)))
18512    snd_display("granulate ramped 4 data off: %s %s %s?", res1, res2, res3)
18513  end
18514  undo_edit
18515  e = make_env([0, 0, 1, 1], :length, 10000)
18516  gen = make_granulate(:expansion, 2.0,
18517                       :input, lambda do |dir| env(e) end,
18518                       :length, 0.00995,
18519                       :hop, 0.01,
18520                       :ramp, 0.0,
18521                       :scaler, 1.0,
18522                       :jitter, 0.0)
18523  clm_channel(gen)
18524  if fneq(maxamp, 0.505)
18525    snd_display("granulate ramped 5: %s?", maxamp)
18526  end
18527  vals = count_matches(lambda do |y| y != 0.0 end)
18528  mxoff = 0.0
18529  mx = maxamp
18530  len = framples
18531  cur = 0.0
18532  incr = mx / len
18533  scan_channel(lambda do |y|
18534                 diff = (cur - y).abs
18535                 if diff > mxoff
18536                   mxoff = diff
18537                 end
18538                 cur += incr
18539                 false
18540               end)
18541  if mxoff > 0.02
18542    snd_display("granulate ramped 5 mxoff: %s?", mxoff)
18543  end
18544  undo_edit
18545  e = make_env([0, 0, 1, 1], :length, 10000)
18546  gen = make_granulate(:expansion, 2.0,
18547                       :input, lambda do |dir| env(e) end,
18548                       :length, 0.00995,
18549                       :hop, 0.01,
18550                       :ramp, 0.5,
18551                       :scaler, 1.0,
18552                       :jitter, 0.0)
18553  clm_channel(gen)
18554  if fneq(maxamp, 0.495)
18555    snd_display("granulate ramped 6: %s?", maxamp)
18556  end
18557  if (not vequal(res1 = channel2vct(2000, 10),
18558                 vct(0.018, 0.019, 0.020, 0.021, 0.022, 0.023, 0.024, 0.025, 0.026, 0.027))) or
18559      (not vequal(res2 = channel2vct(8000, 10),
18560                  vct(0.294, 0.298, 0.301, 0.305, 0.309, 0.313, 0.316, 0.320, 0.324, 0.328)))
18561    snd_display("granulate ramped 6 data: %s %s?", res1, res2)
18562  end
18563  undo_edit
18564  e = make_env([0, 0, 1, 1], :length, 10000)
18565  gen = make_granulate(:expansion, 2.0,
18566                       :input, lambda do |dir| env(e) end,
18567                       :length, 0.00995,
18568                       :hop, 0.01,
18569                       :ramp, 0.25,
18570                       :scaler, 1.0,
18571                       :jitter, 0.0)
18572  clm_channel(gen)
18573  if fneq(maxamp, 0.505)
18574    snd_display("granulate ramped 7: %s?", maxamp)
18575  end
18576  if (not vequal(res1 = channel2vct(2000, 10),
18577                 vct(0.037, 0.039, 0.040, 0.042, 0.044, 0.046, 0.048, 0.050, 0.052, 0.054))) or
18578      (not vequal(res2 = channel2vct(8000, 10),
18579                  vct(0.404, 0.404, 0.404, 0.404, 0.404, 0.405, 0.405, 0.405, 0.405, 0.405)))
18580    snd_display("granulate ramped 7 data: %s %s?", res1, res2)
18581  end
18582  undo_edit
18583  e = make_env([0, 0, 1, 1], :length, 10000)
18584  gen = make_granulate(:expansion, 2.0,
18585                       :input, lambda do |dir| env(e) end,
18586                       :length, 0.05,
18587                       :hop, 0.01,
18588                       :ramp, 0.25,
18589                       :scaler, 0.1,
18590                       :jitter, 0.0)
18591  clm_channel(gen)
18592  if fneq(maxamp, 0.201)
18593    snd_display("granulate ramped 7: %s?", maxamp)
18594  end
18595  mxoff = 0.0
18596  mx = maxamp
18597  len = framples
18598  cur = 0.0
18599  incr = mx / len
18600  scan_channel(lambda do |y|
18601                 diff = (cur - y).abs
18602                 if diff > mxoff
18603                   mxoff = diff
18604                 end
18605                 cur += incr
18606                 false
18607               end)
18608  if mxoff > 0.01
18609    snd_display("granulate ramped 7 mxoff: %s?", mxoff)
18610  end
18611  undo_edit
18612  e = make_env([0, 0, 1, 1], :length, 10000)
18613  gen = make_granulate(:expansion, 2.0,
18614                       :input, lambda do |dir| env(e) end,
18615                       :length, 0.1,
18616                       :hop, 0.01,
18617                       :ramp, 0.1,
18618                       :scaler, 0.1,
18619                       :jitter, 0.0)
18620  clm_channel(gen)
18621  if fneq(maxamp, 0.501)
18622    snd_display("granulate ramped 8: %s?", maxamp)
18623  end
18624  mxoff = 0.0
18625  mx = maxamp
18626  len = framples - 2000
18627  cur = sample(2000)
18628  incr = (mx - cur) / len
18629  scan_channel(lambda do |y|
18630                 diff = (cur - y).abs
18631                 if diff > mxoff
18632                   mxoff = diff
18633                 end
18634                 cur += incr
18635                 false
18636               end, 2000)
18637  if mxoff > 0.001
18638    snd_display("granulate ramped 8 mxoff: %s?", mxoff)
18639  end
18640  undo_edit
18641  e = make_env([0, 0, 1, 1], :length, 10000)
18642  gen = make_granulate(:expansion, 2.0,
18643                       :input, lambda do |dir| env(e) end,
18644                       :length, 0.4,
18645                       :hop, 0.01,
18646                       :ramp, 0.4,
18647                       :scaler, 0.025,
18648                       :jitter, 0.0)
18649  clm_channel(gen)
18650  if fneq(maxamp, 0.433)
18651    snd_display("granulate ramped 9: %s?", maxamp)
18652  end
18653  undo_edit
18654  close_sound(ind)
18655end
18656
18657def test_08_18
18658  v0 = make_vct(32)
18659  v1 = make_vct(256)
18660  v2 = make_vct(256)
18661  v01 = make_vct(32)
18662  v11 = make_vct(256)
18663  v21 = make_vct(256)
18664  1.upto(15) do |i| v0[i] = v01[i] = 1.0 / i end
18665  v1[0] = v11[0] = 1.0
18666  gen = make_convolve(:filter, v0)
18667  gen1 = make_convolve(:filter, v01)
18668  n = n1 = -1
18669  print_and_check(gen, "convolve", "convolve size: 64")
18670  unless convolve?(gen)
18671    snd_display("%s not convolve?", gen)
18672  end
18673  genx = gen1
18674  unless genx.eql?(gen1)
18675    snd_display("convolve %s.eql?(%s)", genx, gen1)
18676  end
18677  if gen.eql?(gen1)
18678    snd_display("convolve %s.eql?(%s)", gen, gen1)
18679  end
18680  if mus_length(gen) != 64
18681    snd_display("convolve fft len: %s?", mus_length(gen))
18682  end
18683  128.times do |i|
18684    v2[i] = convolve(gen, lambda do |dir|
18685                       n += 1
18686                       v1[n]
18687                     end)
18688  end
18689  v21.map! do |x|
18690    if convolve?(gen1)
18691      convolve(gen1, lambda do |dir|
18692        n1 += 1
18693        v11[n1]
18694      end)
18695    else
18696      -1.0
18697    end
18698  end
18699  unless vequal(v2, v21)
18700    snd_display("run gran: %s %s?", v2, v21)
18701  end
18702  if fneq(v2[0], 0.0) or fneq(v2[1], 1.0) or fneq(v2[4], 0.25) or fneq(v2[7], 0.143)
18703    snd_display("convolve output: %s?", v2)
18704  end
18705  convolve_files("oboe.snd", "fyow.snd", 0.5, "fmv.snd")
18706  if fneq(res = mus_sound_maxamp("fmv.snd")[1], 0.5)
18707    snd_display("convolve_files: %s != 0.5?", res)
18708  end
18709  #
18710  ind = new_sound("fmv.snd")
18711  set_sample(1, 0.1)
18712  save_sound(ind)
18713  if edits(ind, 0) != [0, 0]
18714    snd_display("weird: edits not cleared after save_sound: %s?", edits(ind, 0))
18715  end
18716  close_sound(ind)
18717  ind = open_sound("fmv.snd")
18718  if framples(ind, 0) != 2
18719    snd_display("save_sound 2 samps: %s?", framples(ind, 0))
18720  end
18721  if fneq(sample(0), 0.0) or fneq(sample(1), 0.1)
18722    snd_display("save_sound: %s %s?", sample(0), sample(1))
18723  end
18724  3.upto(5) do |i|
18725    set_sample(i, i * 0.1)
18726    save_sound(ind)
18727    if edits(ind, 0) != [0, 0]
18728      snd_display("weird: edits not cleared after save_sound %s: %s?", i, edits(ind, 0))
18729    end
18730    close_sound(ind)
18731    ind = open_sound("fmv.snd")
18732    if framples(ind, 0) != i + 1
18733      snd_display("save_sound %s samps: %s?", i + 1, framples(ind, 0))
18734    end
18735    if fneq(sample(0), 0.0) or fneq(sample(1), 0.1) or fneq(sample(i), i * 0.1)
18736      snd_display("save_sound %s: %s %s %s?", i, sample(0), sample(1), sample(i))
18737    end
18738  end
18739  close_sound(ind)
18740  #
18741  ind = new_sound("test.snd", :srate, 22050, :channels, 1, :size, 1000)
18742  gen = make_ssb_am(100.0)
18743  map_channel(lambda do |y| ssb_am(gen, 0.0) end)
18744  if fneq(maxamp, 0.0)
18745    snd_display("ssb_am 0.0: %s?", maxamp)
18746  end
18747  gen1 = make_oscil(220.0)
18748  map_channel(lambda do |y| 0.5 * oscil(gen1) end)
18749  gen = make_ssb_am(100.0, 100)
18750  map_channel(lambda do |y| ssb_am(gen, y) end)
18751  delete_samples(0, 200)
18752  gen1 = make_oscil(320.0, :initial_phase, asin(2.0 * sample(0)))
18753  map_channel(lambda do |y| y - 0.5 * oscil(gen1) end)
18754  if maxamp > 0.004
18755    snd_display("ssb_am cancelled: %s?", maxamp)
18756  end
18757  undo_edit(3)
18758  gen = make_ssb_am(100.0, 100)
18759  map_channel(lambda do |y| ssb_am(gen, y, hz2radians(50.0)) end)
18760  delete_samples(0, 180)
18761  if defined? asin
18762    gen1 = make_oscil(370.0, :initial_phase, asin(2.0 * sample(0)))
18763    map_channel(lambda do |y| y - 0.5 * oscil(gen1) end)
18764    if maxamp > 0.004
18765      snd_display("ssb_am fm cancelled: %s?", maxamp)
18766    end
18767  end
18768  close_sound(ind)
18769  #
18770  ind = new_sound("test.snd", :srate, 22050, :channels, 1, :size, 1000)
18771  ctr = 0
18772  map_channel(lambda do |y|
18773                val = sin((TWO_PI * ctr) / 50)
18774                ctr += 1
18775                val
18776              end)
18777  ssb_bank(441, 882, 1, 100)
18778  delete_samples(0, 217)
18779  if defined? asin
18780    gen1 = make_oscil(882.0, :initial_phase, asin(sample(0)))
18781    map_channel(lambda do |y| y - oscil(gen1) end)
18782    if maxamp > 0.04
18783      snd_display("ssb_bank cancelled: %s?", maxamp)
18784    end
18785  end
18786  close_sound(ind)
18787  #
18788  nind = new_sound("fmv.snd", 1, 22050, Mus_bshort, Mus_aifc,
18789                   "this is a comment")
18790  with_time("fm_violin_1(0, 1, 440, 0.1)") do fm_violin_1(0, 1, 440, 0.1) end
18791  play(nind, :wait, true)
18792  save_sound(nind)
18793  unless sound?(nind)
18794    snd_display("save_sound clobbered %s?", nind)
18795  end
18796  oboe_index = (find_sound("oboe.snd") or open_sound("oboe.snd"))
18797  if oboe_index == nind
18798    snd_display("find_sound found bogus case: %s (%s)?", oboe_index, nind)
18799  end
18800  cnvtest(oboe_index, nind, 0.1)
18801  select_sound(nind)
18802  select_channel(0)
18803  if selected_sound != nind
18804    snd_display("selected_sound: %s (%s)?", selected_sound, nind)
18805  end
18806  if selected_channel != 0
18807    snd_display("selected_channel: %s?", selected_channel)
18808  end
18809  jc_reverb_1(1.0, false, 0.1, false)
18810  play(nind, :wait, true)
18811  voiced2unvoiced(1.0, 256, 2.0, 2.0)
18812  pulse_voice(80, 20.0, 1.0, 1024, 0.01)
18813  map_chan(fltit)
18814  close_sound(oboe_index)
18815  unless sound?(nind)
18816    snd_display("close_sound clobbered %s?", nind)
18817  end
18818  fr = framples(nind, 0)
18819  10.times do
18820    delete_samples(10, 100, nind, 0)
18821    save_sound(nind)
18822  end
18823  if framples(nind, 0) != fr - 1000
18824    snd_display("delete_samples: %s %s?", fr, framples(nind, 0))
18825  end
18826  revert_sound(nind)
18827  close_sound(nind)
18828  delete_file("fmv.snd")
18829  nind = new_sound("fmv.snd")
18830  if (res1 = header_type(nind)) != (res2 = default_output_header_type)
18831    snd_display("new_sound default header_type: %s %s?",
18832                mus_header_type_name(res1),
18833                mus_header_type_name(res2))
18834  end
18835  if (res1 = sample_type(nind)) != (res2 = default_output_sample_type)
18836    snd_display("new_sound default sample_type: %s %s?",
18837                mus_sample_type_name(res1),
18838                mus_sample_type_name(res2))
18839  end
18840  if (res1 = channels(nind)) != (res2 = default_output_chans)
18841    snd_display("new_sound default chans: %s %s?", res1, res2)
18842  end
18843  if (res1 = srate(nind)) != (res2 = default_output_srate)
18844    snd_display("new_sound default srate: %s %s?", res1, res2)
18845  end
18846  close_sound(nind)
18847  delete_file("fmv.snd")
18848end
18849
18850def test_08_19
18851  nind = new_sound("fmv.snd", 1, 22050, Mus_bshort, Mus_nist,
18852                   "this is a comment")
18853  set_sample(0, 1.0, nind)
18854  start_progress_report(nind)
18855  convolve_with("oboe.snd")
18856  progress_report(0.1, nind)
18857  if fneq(sample(1000), 0.223)
18858    snd_display("convolve_with: %s?", sample(1000))
18859  end
18860  progress_report(0.3, nind)
18861  revert_sound(nind)
18862  progress_report(0.5, nind)
18863  set_sample(200, 0.0001)
18864  set_sample(100, 1.0)
18865  progress_report(0.8, nind)
18866  smooth_sound(0, 100)
18867  finish_progress_report(nind)
18868  if fneq(sample(50), 0.5) or fneq(sample(30), 0.20608) or fneq(sample(90), 0.9755)
18869    snd_display("smooth: %s %s %s?", sample(50), sample(30), sample(90))
18870  end
18871  undo_edit
18872  old_sw = sinc_width
18873  set_sinc_width(40)
18874  set_sample(100, 0.5)
18875  if fneq(sample(100), 0.5)
18876    snd_display("set_sample(100): %s?", sample(100))
18877  end
18878  src_sound(0.1)
18879  if fneq(sample(1000), 0.5) or fneq(sample(1024), 0.0625) or fneq(sample(1010), 0.0)
18880    snd_display("src_sound: %s %s %s?", sample(100), sample(1024), sample(1010))
18881  end
18882  set_sinc_width(old_sw)
18883  revert_sound(nind)
18884  close_sound(nind)
18885  #
18886  nind = new_sound("fmv.snd", 1, 22050, Mus_lshort, Mus_riff,
18887                   "this is a comment", 22050)
18888  if framples(nind) != 22050
18889    snd_display("new_sound initial_length: %s?", framples(nind))
18890  end
18891  mix("pistol.snd")
18892  map_chan(expsrc(2.0, nind))
18893  undo_edit
18894  eds = edits
18895  if eds[0] != 1 or eds[1] != 1
18896    snd_display("undo edits: %s?", eds)
18897  end
18898  if edit_position != eds[0]
18899    snd_display("undo edit_position: %s %s?", edit_position, eds)
18900  end
18901  expsnd([0, 1, 2, 0.4])
18902  map_chan(comb_chord(0.95, 100, 0.3))
18903  map_chan(formants(0.99, 900, 0.02, 1800, 0.01, 2700))
18904  map_chan(moving_formant(0.99, [0, 1200, 1, 2400]))
18905  scale_to(0.3)
18906  eds = edits
18907  if eds[0] != 6 or eds[1] != 0
18908    snd_display("edits(6): %s?", eds)
18909  end
18910  if edit_position != eds[0]
18911    snd_display("edit_position(6): %s %s?", edit_position, eds)
18912  end
18913  set_edit_position(1)
18914  if edit_position != 1
18915    snd_display("set_edit_position(1): %s?", edit_position)
18916  end
18917  set_edit_position(4)
18918  if edit_position != 4
18919    snd_display("set_edit_position(4): %s?", edit_position)
18920  end
18921  revert_sound(nind)
18922  mix("pistol.snd")
18923  map_chan(zecho(0.5, 0.75, 6, 10.0), 0, 65000)
18924  map_chan(am(440))
18925  add_mark(1200)
18926  add_mark(2300)
18927  key(key_to_int(?x), 4)
18928  key(key_to_int(?c), 0)        # trigger mark_define_region
18929  reverse_sound(nind)
18930  revert_sound(nind)
18931  mid = mix_sound("pistol.snd", 0).car
18932  # INFO: mix_home()
18933  # According to g_mix_home() in snd-mix.c it can be
18934  # [selected_sound(), 0, file_name() or false, 0].
18935  if mix?(mid) and mix_home(mid) != [selected_sound, 0, false, 0]
18936    snd_display("mix_sound mix_home: %s?", mix_home(mid))
18937  end
18938  hello_dentist(40.0, 0.1)
18939  fp(1.0, 0.3, 20)
18940  revert_sound(nind)
18941  enveloped_mix("oboe.snd", 0, [0, 0, 1, 1, 2, 0])
18942  pvoc(:pitch, 0.5, :time, 1.0, :snd, nind)
18943  revert_sound(nind)
18944  close_sound(nind)
18945end
18946
18947def test_08_20
18948  make_mix_output = lambda do |name, i|
18949    if i == 0 or i == 1
18950      name
18951    else
18952      continue_sample2file(name)
18953    end
18954  end
18955  make_mix_input = lambda do |name, i|
18956    if i == 0 or i == 2
18957      name
18958    else
18959      make_file2frample(name)
18960    end
18961  end
18962end
18963
18964def test_08_21
18965  Snd.sounds.apply(:close_sound)
18966  gen = make_phase_vocoder(false, 512, 4, 256, 1.0, false, false, false)
18967  if fneq((res = Snd.catch do phase_vocoder(gen) end).first, 0.0)
18968    snd_display("simple no-in pv call: %s", res.inspect)
18969  end
18970  if (res = Snd.catch do gen = make_phase_vocoder(:fft_size, 1234) end).first != :out_of_range
18971    snd_display("pv bad fft: %s?", res.inspect)
18972  end
18973  ind = open_sound("oboe.snd")
18974  rd = make_sampler(0)
18975  pv = make_phase_vocoder(lambda do |dir| next_sample(rd) end,
18976                          512, 4, 128, 1.0, false, false, false)
18977  unless phase_vocoder?(pv)
18978    snd_display("%s not phase_vocoder?", pv)
18979  end
18980  print_and_check(pv,
18981                  "phase-vocoder",
18982                  "phase-vocoder outctr: 128, interp: 128, filptr: 0, N: 512, D: 128, in_data: nil")
18983  pv = make_phase_vocoder
18984  set_mus_location(pv, 120)
18985  if (res = mus_location(pv)) != 120
18986    snd_display("pv set outctr: %s?", res)
18987  end
18988  select_sound(ind)
18989  map_chan(lambda do |val| phase_vocoder(pv) end)
18990  phase_vocoder_amp_increments(pv)[0] = 0.1
18991  if fneq(res = phase_vocoder_amp_increments(pv)[0], 0.1)
18992    snd_display("set_phase_vocoder_amp_increments: %s?", res)
18993  end
18994  phase_vocoder_amps(pv)[0] = 0.1
18995  if fneq(res = phase_vocoder_amps(pv)[0], 0.1)
18996    snd_display("set_phase_vocoder_amps: %s?", res)
18997  end
18998  phase_vocoder_phases(pv)[0] = 0.1
18999  if fneq(res = phase_vocoder_phases(pv)[0], 0.1)
19000    snd_display("set_phase_vocoder_phases: %s?", res)
19001  end
19002  phase_vocoder_phase_increments(pv)[0] = 0.1
19003  if fneq(res = phase_vocoder_phase_increments(pv)[0], 0.1)
19004    snd_display("set_phase_vocoder_phase_increments: %s?", res)
19005  end
19006  phase_vocoder_freqs(pv)[0] = 0.1
19007  if fneq(res = phase_vocoder_freqs(pv)[0], 0.1)
19008    snd_display("set_phase_vocoder_freqs: %s?", res)
19009  end
19010  undo_edit(1)
19011  free_sampler(rd)
19012  #
19013  lastphases = make_vct(512)
19014  rd = make_sampler(0)
19015  pv = make_phase_vocoder(lambda do |dir| next_sample(rd) end,
19016                          512, 4, 128, 1.0,
19017                          false,
19018                          lambda do |v|
19019                            n = mus_length(v)
19020                            d = mus_hop(v)
19021                            freqs = phase_vocoder_freqs(v)
19022                            pscl = 1.0 / d
19023                            kscl = TWO_PI / n
19024                            (n / 2).times do |k|
19025                              phasediff = freqs[k] - lastphases[k]
19026                              lastphases[k] = freqs[k]
19027                              if phasediff > PI
19028                                phasediff -= TWO_PI
19029                              else
19030                                if phasediff < -PI
19031                                  phasediff += TWO_PI
19032                                end
19033                              end
19034                              freqs[k] = 0.5 * (pscl * phasediff + k * kscl)
19035                            end
19036                            false
19037                          end,
19038                          false)
19039  map_chan(lambda do |val| phase_vocoder(pv) end)
19040  undo_edit(1)
19041  free_sampler(rd)
19042  #
19043  rd = make_sampler(0)
19044  pv = make_phase_vocoder(lambda do |dir| next_sample(rd) end,
19045                          512, 4, 128 * 2, 1.0, false, false, false)
19046  len = 1000
19047  data = make_vct!(len) do
19048    phase_vocoder(pv)
19049  end
19050  set_samples(0, len, data)
19051  undo_edit(1)
19052  free_sampler(rd)
19053  #
19054  incalls = outcalls = 0
19055  rd = make_sampler(0)
19056  pv = make_phase_vocoder(lambda do |dir| next_sample(rd) end,
19057                          512, 4, 128 * 2, 1.0,
19058                          lambda do |v, infunc|
19059                            incalls += 1
19060                            true
19061                          end,
19062                          false,
19063                          lambda do |v|
19064                            outcalls += 1
19065                            0.0
19066                          end)
19067  len = 1000
19068  data = make_vct!(len) do
19069    phase_vocoder(pv)
19070  end
19071  set_samples(0, len, data)
19072  undo_edit(1)
19073  free_sampler(rd)
19074  if incalls.zero? or outcalls.zero?
19075    snd_display("phase_vocoder incalls: %s, outcalls: %s?", incalls, outcalls)
19076  end
19077  set_mus_location(pv, mus_location(pv))
19078  if (res = Snd.catch do
19079        make_phase_vocoder(false,
19080                           512, 4, 256, 1.0,
19081                           lambda do |a, b, c| false end,
19082                           false,
19083                           false)
19084      end).first != :bad_arity
19085    snd_display("make_phase_vocoder bad analyze func: %s", res.inspect)
19086  end
19087  if (res = Snd.catch do
19088        make_phase_vocoder(false,
19089                           512, 4, 256, 1.0,
19090                           lambda do |a, b| 0.0 end,
19091                           lambda do |a, b, c| false end,
19092                           false)
19093      end).first != :bad_arity
19094    snd_display("make_phase_vocoder bad edit func: %s", res.inspect)
19095  end
19096  if (res = Snd.catch do
19097        make_phase_vocoder(false,
19098                           512, 4, 256, 1.0,
19099                           lambda do |a, b| 0.0 end,
19100                           lambda do |a| false end,
19101                           lambda do |a, b| 0 end)
19102      end).first != :bad_arity
19103    snd_display("make_phase_vocoder bad synthesize func: %s", res.inspect)
19104  end
19105  geno = make_phase_vocoder(lambda do |dir| 0.0 end)
19106  genx = make_phase_vocoder(:input, lambda do |dir| 0.0 end)
19107  if geno.eql?(genx)
19108    snd_display("phase_vocoder %s.eql?(%s)?", geno, genx)
19109  end
19110  if fneq(genx.frequency, 1.0)
19111    snd_display("mus_frequency phase_vocoder: %s?", genx.frequency)
19112  end
19113  set_mus_frequency(genx, 2.0)
19114  if fneq(genx.frequency, 2.0)
19115    snd_display("set_mus_frequency phase_vocoder: %s?", genx.frequency)
19116  end
19117  if genx.increment != 128
19118    snd_display("mus_increment phase_vocoder: %s?", genx.increment)
19119  end
19120  set_mus_increment(genx, 256)
19121  if genx.increment != 256
19122    snd_display("set_mus_increment phase_vocoder: %s?", genx.increment)
19123  end
19124  if genx.hop != 128
19125    snd_display("mus_hop phase_vocoder: %s?", genx.hop)
19126  end
19127  set_mus_hop(genx, 64)
19128  if genx.hop != 64
19129    snd_display("set_mus_hop phase_vocoder: %s?", genx.hop)
19130  end
19131  if genx.length != 512
19132    snd_display("mus_length phase_vocoder: %s?", genx.length)
19133  end
19134  genxx = genx
19135  unless genx.eql?(genxx)
19136    snd_display("phase_vocoder %s.eql?(%s)?", genxx, genx)
19137  end
19138  close_sound(ind)
19139end
19140
19141def test_08_22
19142  ind = open_sound("oboe.snd")
19143  gen = make_moog_filter(500.0, 0.1)
19144  if fneq(gen.frequency, 500.0)
19145    snd_display("moog freq: %s?", gen.frequency)
19146  end
19147  if fneq(gen.Q, 0.1)
19148    snd_display("moog Q: %s?", gen.Q)
19149  end
19150  unless vct?(gen.state)
19151    snd_display("moog state: %s?", gen.state)
19152  end
19153  if fneq(gen.A, 0.0)
19154    snd_display("moog A: %s?", gen.A)
19155  end
19156  if fneq(gen.freqtable, -0.861)
19157    snd_display("moog freqtable: %s?", gen.freqtable)
19158  end
19159  vals = make_vct!(20) do |i| moog_filter(gen, i.zero? ? 1.0 : 0.0) end
19160  unless vequal(vals, vct(0.0, 0.0, 0.0025, 0.0062, 0.0120, 0.0198, 0.0292, 0.0398,
19161                          0.0510, 0.0625, 0.0739, 0.0847, 0.0946, 0.1036, 0.1113, 0.1177,
19162                          0.1228, 0.1266, 0.1290, 0.1301))
19163    snd_display("moog output: %s?", vals)
19164  end
19165  close_sound(ind)
19166  #
19167  gen = make_ssb_am(440.0)
19168  gen1 = make_ssb_am(440.0)
19169  print_and_check(gen,
19170    "ssb-am",
19171    "ssb-am shift: up, sin/cos: 439.999975 Hz (0.000000 radians), order: 41",
19172    "ssb-am shift: up, sin/cos: 440.000000 Hz (0.000000 radians), order: 41",
19173    "ssb-am shift: up, sin/cos: 439.999969 Hz (0.000000 radians), order: 41")
19174  v0 = make_vct!(10) do ssb_am(gen, 0.0) end
19175  v1 = make_vct(10)
19176  v1.map! do |x| ssb_am?(gen1) ? ssb_am(gen1, 0.0) : -1.0 end
19177  unless vequal(v0, v1)
19178    snd_display("map ssb_am: %s %s?", v0, v1)
19179  end
19180  unless ssb_am?(gen)
19181    snd_display("%s not ssb_am?", gen)
19182  end
19183  if fneq(gen.phase, 1.253787)
19184    snd_display("ssb_am phase: %s?", gen.phase)
19185  end
19186  if fneq(gen.frequency, 440.0)
19187    snd_display("ssb_am frequency: %s?", gen.frequency)
19188  end
19189  if gen.order != 41
19190    snd_display("ssb_am order: %s?", gen.order)
19191  end
19192  if gen.length != 41
19193    snd_display("ssb_am length: %s?", gen.length)
19194  end
19195  if gen.interp_type != Mus_interp_none
19196    snd_display("ssb_am interp_type: %s?", gen.interp_type)
19197  end
19198  if fneq(gen.xcoeff(0), -0.00124)
19199    snd_display("ssb_am xcoeff 0: %s?", gen.xcoeff(0))
19200  end
19201  if fneq(gen.xcoeff(1), 0.0)
19202    snd_display("ssb_am xcoeff 1: %s?", gen.xcoeff(1))
19203  end
19204  #
19205  test_gen_equal(make_ssb_am(440.0), make_ssb_am(440.0), make_ssb_am(500.0))
19206  #
19207  o1 = make_ssb_am(400.0)
19208  o2 = make_ssb_am_1(400.0)
19209  100.times do |i|
19210    inval = sin(0.1 * i)
19211    req = ssb_am(o1, inval)
19212    res = ssb_am_1(o2, inval)
19213    if snd_test_neq(res, req, "ssb_am (up) at %d", i)
19214      break
19215    end
19216  end
19217  #
19218  o1 = make_ssb_am(400.0)
19219  o2 = make_ssb_am_1(400.0)
19220  100.times do |i|
19221    inval = sin(0.1 * i)
19222    fmval = sin(0.2 * i)
19223    req = ssb_am(o1, inval, fmval)
19224    res = ssb_am_1(o2, inval, fmval)
19225    if snd_test_neq(res, req, "ssb_am + fm (up) at %d", i)
19226      break
19227    end
19228  end
19229  #
19230  o1 = make_ssb_am(-100.0)
19231  o2 = make_ssb_am_1(-100.0)
19232  100.times do |i|
19233    inval = random(1.0)
19234    req = ssb_am(o1, inval)
19235    res = ssb_am_1(o2, inval)
19236    if snd_test_neq(res, req, "ssb_am (down) at %d", i)
19237      break
19238    end
19239  end
19240  #
19241  o1 = make_ssb_am(1000.0, 100)
19242  o2 = make_ssb_am_1(1000.0, 100)
19243  100.times do |i|
19244    inval = random(1.0)
19245    req = ssb_am(o1, inval)
19246    res = ssb_am_1(o2, inval)
19247    if snd_test_neq(res, req, "ssb_am (down) at %d", i)
19248      break
19249    end
19250  end
19251  #
19252  index = open_sound("pistol.snd")
19253  data = channel2vct(0, 100)
19254  convolve_with("oboe.snd", false)
19255  scl = maxamp
19256  convolve_with("oboe.snd", scl, index, 0, 0)
19257  snd_test_any_neq(maxamp, scl, :ffequal?, "convolve_with amps")
19258  close_sound(index)
19259  reader = make_sampler(0, "pistol.snd")
19260  10.times do |i|
19261    snd_test_neq(data[i], next_sample(reader), "external reader trouble")
19262  end
19263  free_sampler(reader)
19264  #
19265  gen = make_moving_max(4)
19266  iv = vct(0.1, 0.05, -0.2, 0.15, -1.5, 0.1, 0.01, 0.001, 0.0, 0.0)
19267  tv = vct(0.1, 0.1, 0.2, 0.2, 1.5, 1.5, 1.5, 1.5, 0.1, 0.01)
19268  ov = Vct.new(10) do |i| moving_max(gen, iv[i]) end
19269  snd_test_neq(ov, tv, "moving_max")
19270  g1 = make_moving_max(10)
19271  1000.times do |i|
19272    snd_test_neq(moving_max(g1, random(1.0)), g1.data.peak, "moving_max[%d]", i)
19273  end
19274  #
19275  data = vct(1, 0, -1.1, 1.1001, 0.1, -1.1, 1, 1, 0.5, -0.01, 0.02, 0, 0, 0, 0)
19276  g = make_moving_max(3)
19277  odata = Vct.new(15) do |i| moving_max(g, data[i]) end
19278  req = vct(1, 1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1, 1, 0.5, 0.02, 0.02, 0, 0)
19279  snd_test_neq(odata, req, "moving_max")
19280  if odata[4] == odata[7]
19281    snd_test_eq(odata[4], odata[7], "moving_max 0.0001 offset")
19282  end
19283  #
19284  data = vct(0.1, -0.2, 0.3, 0.4, -0.5, 0.6, 0.7, 0.8, -0.9, 1.0, 0.0, 0.0)
19285  g = make_moving_sum(3)
19286  odata = Vct.new(15, 0.0)
19287  data.each_with_index do |x, i| odata[i] = moving_sum(g, x) end
19288  req = vct(0.1, 0.3, 0.6, 0.9, 1.2, 1.5, 1.8, 2.1, 2.4, 2.7, 1.9, 1, 0, 0, 0)
19289  snd_test_neq(odata, req, "moving_sum")
19290  #
19291  g = make_moving_rms(4)
19292  odata = Vct.new(15, 0.0)
19293  data.each_with_index do |x, i| odata[i] = moving_rms(g, x) end
19294  req = vct(0.05, 0.112, 0.187, 0.274, 0.367, 0.464, 0.561,
19295            0.66, 0.758, 0.857, 0.783, 0.673, 0, 0, 0)
19296  snd_test_neq(odata, req, "moving_rms")
19297  #
19298  g = make_moving_length(4)
19299  odata = Vct.new(15, 0.0)
19300  data.each_with_index do |x, i| odata[i] = moving_length(g, x) end
19301  req = vct(0.1, 0.224, 0.374, 0.548, 0.735, 0.927, 1.122,
19302            1.319, 1.517, 1.715, 1.565, 1.345, 0, 0, 0)
19303  snd_test_neq(odata, req, "moving_length")
19304  #
19305  10.times do |i| data[i] = mus_random(0.5) end
19306  g = make_moving_length(4)
19307  data.each_with_index do |x, i| odata[i] = moving_length(g, x) end
19308  k = 0
19309  (-3..8).each do |i|
19310    sum = 0.0
19311    4.times do |j|
19312      if i + j >= 0
19313        sum += data[i + j] * data[i + j]
19314      end
19315    end
19316    snd_test_neq(odata[k], sqrt(sum), "moving_length ran")
19317    k += 1
19318  end
19319  #
19320  10.times do |i| data[i] = mus_random(0.5) end
19321  g = make_moving_sum(4)
19322  data.each_with_index do |x, i| odata[i] = moving_sum(g, x) end
19323  k = 0
19324  (-3..8).each do |i|
19325    sum = 0.0
19326    4.times do |j|
19327      if i + j >= 0
19328        sum += data[i + j].abs
19329      end
19330    end
19331    snd_test_neq(odata[k], sum, "moving_sum ran")
19332    k += 1
19333  end
19334  #
19335  10.times do |i| data[i] = mus_random(0.5) end
19336  g = make_moving_rms(4)
19337  data.each_with_index do |x, i| odata[i] = moving_rms(g, x) end
19338  k = 0
19339  (-3..8).each do |i|
19340    sum = 0.0
19341    4.times do |j|
19342      if i + j >= 0
19343        sum = sum + data[i + j] * data[i + j]
19344      end
19345    end
19346    snd_test_neq(odata[k], sqrt(sum / 4.0), "moving_rms ran")
19347    k += 1
19348  end
19349  #
19350  ind = open_sound("oboe.snd")
19351  harmonicizer(550.0, [1, 0.5, 2, 0.3, 3, 0.2], 10)
19352  close_sound(ind)
19353  #
19354  argslist = make_array(16) do [:frequency, 440.0] end.flatten
19355  [:make_wave_train, :make_polyshape, :make_delay,
19356   :make_moving_average, :make_comb, :make_filtered_comb,
19357   :make_notch, :make_rand, :make_rand_interp, :make_table_lookup,
19358   :make_env, :make_readin, :make_locsig, :make_granulate,
19359   :make_convolve, :make_phase_vocoder].each do |make|
19360    res = Snd.catch do argslist.apply(:snd_func, make) end
19361    if res.first != :mus_error
19362      snd_display("long arglist to %s: %s", make, res.inspect)
19363    end
19364  end
19365  #
19366  [[:table_lookup, [:wave]],
19367   [:wave_train, [:wave]],
19368   [:polyshape, [:coeffs]],
19369   [:delay, [:initial_contents]],
19370   [:filtered_comb, [:scaler, 0.5, :filter, make_one_zero(0.1, 0.2), :initial_contents]],
19371   [:rand, [:distribution]],
19372   [:fir_filter, [:xcoeffs]],
19373   [:iir_filter, [:ycoeffs]]].each do |name, args|
19374    v1 = Vct.new(10, 0.1)
19375    g1 = snd_func("make_" + name.to_s, *args + [v1])
19376    case name
19377    when :fir_filter
19378      if g1.xcoeffs != v1
19379        snd_display("%s data !=: %s %s?", name, g1.xcoeffs, v1)
19380      end
19381      v1[1] = 0.3
19382      if fneq(g1.xcoeffs[1], 0.3)
19383        snd_display("%s vct_set!: %s %s?", name, v1[1], g1.xcoeffs[1])
19384      end
19385      g1.xcoeffs[1] = 0.5
19386      if fneq(v1[1], 0.5)
19387        snd_display("%s set_data: %s %s?", name, v1[1], g1.xcoeffs[1])
19388      end
19389    when :iir_filter
19390      if g1.ycoeffs != v1
19391        snd_display("%s data !=: %s %s?", name, g1.ycoeffs, v1)
19392      end
19393      v1[1] = 0.3
19394      if fneq(g1.ycoeffs[1], 0.3)
19395        snd_display("%s vct_set!: %s %s?", name, v1[1], g1.ycoeffs[1])
19396      end
19397      g1.ycoeffs[1] = 0.5
19398      if fneq(v1[1], 0.5)
19399        snd_display("%s set_data: %s %s?", name, v1[1], g1.ycoeffs[1])
19400      end
19401    else
19402      if g1.data != v1
19403        snd_display("%s data !=: %s %s?", name, g1.data, v1)
19404      end
19405      v1[1] = 0.3
19406      if fneq(g1.data[1], 0.3)
19407        snd_display("%s vct_set!: %s %s?", name, v1[1], g1.data[1])
19408      end
19409      g1.data[1] = 0.5
19410      if fneq(v1[1], 0.5)
19411        snd_display("%s set_data: %s %s?", name, v1[1], g1.data[1])
19412      end
19413    end
19414  end
19415end
19416
19417def test_08_23
19418  [[:all_pass, false, 0.0, false],
19419   [:asymmetric_fm, false, 0.0, false],
19420   [:moving_average, false, 1.0, false],
19421   [:comb, false, 0.0, false],
19422   [:convolve, [:filter, vct(0, 1, 2)], lambda { |dir| 0.0 }, false],
19423   [:delay, false, 0.0, false],
19424   [:env, [:length, 11, :envelope, [0, 1, 1, 0]], false, false],
19425   [:filter, [:xcoeffs, vct(0, 1, 2)], 0.0, false],
19426   [:filter, [:ycoeffs, vct(0, 1, 2)], 0.0, false],
19427   [:filter, [:xcoeffs, vct(1, 2, 3), :ycoeffs, vct(0, 1, 2)], 0.0, false],
19428   [:fir_filter, [:xcoeffs, vct(0, 1, 2)], 0.0, false],
19429   [:formant, false, 0.0, false],
19430   [:granulate, false, lambda { |dir| 0.0 }, false],
19431   [:iir_filter, [:ycoeffs, vct(0, 1, 2)], 0.0, false],
19432   [:locsig, false, 0.0, lambda { |gen, a| locsig(gen, 0, a) }],
19433   [:notch, false, 0.0, false],
19434   [:one_pole, false, 0.0, false],
19435   [:one_zero, false, 0.0, false],
19436   [:oscil, false, 0.0, false],
19437   [:pulse_train, false, 0.0, false],
19438   [:rand, false, 0.0, false],
19439   [:rand_interp, false, 0.0, false],
19440   [:sawtooth_wave, false, 0.0, false],
19441   [:square_wave, false, 0.0, false],
19442   [:src, false, lambda { |dir| 0.0 }, lambda { |gen, a| src(gen, 0.0, a) }],
19443   [:table_lookup, false, 0.0, false],
19444   [:triangle_wave, false, 0.0, false],
19445   [:two_pole, false, 0.0, false],
19446   [:two_zero, false, 0.0, false],
19447   [:wave_train, false, 0.0, false],
19448   [:polyshape, false, 0.0, false],
19449   [:phase_vocoder, false, lambda { |dir| 0.0 }, false],
19450   [:ssb_am, false, 0.0, false]].each do |name_sym, make_args, arg, run_func|
19451    gen = if make_args
19452            snd_func(format("make_%s", name_sym), *make_args)
19453          else
19454            snd_func(format("make_%s", name_sym))
19455          end
19456    unless snd_func(format("%s%c", name_sym, ??), gen)
19457      snd_display("%s: %s?", name_sym, gen)
19458    end
19459    tag = if proc?(run_func)
19460            Snd.catch do
19461              arg ? run_func.call(gen, arg) : run_func.call(gen)
19462            end.first
19463          else
19464            Snd.catch do
19465              arg ? snd_func(name_sym, gen, arg) : snd_func(name_sym, gen)
19466            end.first
19467          end
19468    if (not number?(tag)) and (not frame?(tag))
19469      snd_display("%s (make_gen, gen, gen? test): %s %s?", name_sym, arg, tag)
19470    end
19471    [:mus_channel,
19472     :mus_channels,
19473     :mus_data,
19474     :mus_feedback,
19475     :mus_feedforward,
19476     :mus_frequency,
19477     :mus_hop,
19478     :mus_increment,
19479     :mus_length,
19480     :mus_location,
19481     :mus_order,
19482     :mus_phase,
19483     :mus_ramp,
19484     :mus_random,
19485     :mus_run,
19486     :mus_scaler,
19487     :mus_xcoeffs,
19488     :mus_ycoeffs].each do |func_sym|
19489      if (res = Snd.catch do snd_func(func_sym, false) end).first != :wrong_type_arg
19490        snd_display("generic function with false: %s.%s(false) -> %s",
19491                    name_sym, func_sym, res.inspect)
19492      end
19493      g1 = make_oscil
19494      g2 = make_one_pole(0.1, 0.9)
19495      res = Snd.catch do snd_func(func_sym, g1) end
19496      if symbol?(res) and
19497          res != :wrong_type_arg and
19498          res != :mus_error
19499        snd_display("generic %s of oscil: %s", name_sym, res.inspect)
19500      end
19501      res = Snd.catch do snd_func(func_sym, g2) end
19502      if symbol?(res) and
19503          res != :wrong_type_arg and
19504          res != :mus_error
19505        snd_display("generic %s of delay: %s", name_sym, res.inspect)
19506      end
19507      tag = Snd.catch do snd_func(func_sym, gen) end.first
19508      if (not symbol?(tag)) and
19509          tag != :mus_error and
19510          tag != :out_of_range and
19511          tag != :wrong_type_arg and
19512          (func_sym != :mus_data or vct?(tag))
19513        set_tag = Snd.catch do set_snd_func(func_sym, gen, tag) end.first
19514        if symbol?(set_tag) and
19515            set_tag != :mus_error and
19516            set_tag != :out_of_range and
19517            set_tag != :wrong_type_arg and
19518            set_tag != :no_method_error
19519          snd_display("%s.%s= tag: %s set_tag: %s?",
19520                      name_sym,
19521                      func_sym.to_s[4..-1],
19522                      tag.inspect,
19523                      set_tag.inspect)
19524        end
19525      end
19526    end
19527  end
19528  #
19529  functions = [
19530    [:all_pass,       false, false],
19531    [:asymmetric_fm,  false, false],
19532    [:moving_average, false, false],
19533    [:comb,           false, false],
19534    [:filtered_comb,  [:filter, make_one_zero(0.5, 0.5)], false],
19535    [:convolve,
19536      [:filter, vct(0, 1, 2), :input, lambda { |dir| 1.0 }], false],
19537    [:delay,          false, false],
19538    [:env,
19539      [:envelope, [0, 1, 1, 0], :length, 11],
19540        lambda { |gen, ignored| env(gen) }],
19541    [:filter,         [:xcoeffs, vct(0, 1, 2)], false],
19542    [:filter,         [:ycoeffs, vct(0, 1, 2)], false],
19543    [:filter,         [:xcoeffs, vct(1, 2, 3), :ycoeffs, vct(0, 1, 2)], false],
19544    [:fir_filter,     [:xcoeffs, vct(0, 1, 2)], false],
19545    [:formant,        [:radius, 0.1, :frequency, 440.0], false],
19546    [:granulate,      [:input, lambda { |dir| 1.0 }], false],
19547    [:iir_filter,     [:xcoeffs, vct(0, 1, 2)], false],
19548    [:locsig,         false, lambda { |gen, a| locsig(gen, 0, 1.0) }],
19549    [:notch,          false, false],
19550    [:one_pole,       [0.3, 0.7], false],
19551    [:one_zero,       [0.5, 0.5], false],
19552    [:oscil,          false, false],
19553    [:pulse_train,    false, false],
19554    [:sawtooth_wave,  false, false],
19555    [:square_wave,    false, false],
19556    [:table_lookup,   [:wave, make_vct(128, 0.1)], false],
19557    [:triangle_wave,  false, false],
19558    [:two_pole,       [0.1, 0.3, 0.6], false],
19559    [:two_zero,       [0.1, 0.3, 0.5], false],
19560    [:polyshape,      [:frequency, 440.0, :partials, [1, 1]], false],
19561    [:phase_vocoder,  [lambda { |dir| 1.0 }], false],
19562    [:ssb_am,         false, false]]
19563  functions.each do |name_sym, make_args, run_func|
19564    gen = if make_args
19565            snd_func(format("make_%s", name_sym), *make_args)
19566          else
19567            snd_func(format("make_%s", name_sym))
19568          end
19569    data = make_vct!(10) do |i|
19570      if proc?(run_func)
19571        run_func.call(gen, i.zero? ? 1.0 : 0.0)
19572      else
19573        snd_func(name_sym, gen, i.zero? ? 1.0 : 0.0)
19574      end
19575    end
19576    2.times do |k|
19577      mus_reset(gen)
19578      unless proc?(run_func)
19579        not_zero = false
19580        first_val = k.zero? ?
19581                    snd_func(name_sym, gen, 1.0) : mus_apply(gen, 1.0, 0.0)
19582        if data[0] != 0.0
19583          not_zero = true
19584        end
19585        if fneq(data[0], first_val)
19586          snd_display("[%s] %s: 0 %s %s?",
19587                      k.zero? ? :run : :apply, name_sym, data[0], first_val)
19588        end
19589        (1...10).each do |i|
19590          old_val = data[i]
19591          new_val = k.zero? ?
19592                    snd_func(name_sym, gen, 0.0) : mus_apply(gen, 0.0, 0.0)
19593          if old_val != 0.0
19594            not_zero = true
19595          end
19596          if fneq(old_val, new_val)
19597            snd_display("[%s] %s: %s %s %s?",
19598              k.zero? ? :run : :apply, name_sym, i, old_val, new_val)
19599          end
19600        end
19601        unless not_zero
19602          case name_sym
19603          when :polyshape, :ssb_am
19604            next
19605          else
19606            snd_display("%s not much of a reset test!", name_sym)
19607          end
19608        end
19609      end
19610    end
19611  end
19612  random_args = [1.5,
19613                 "/hiho",
19614                 [0, 1],
19615                 1234,
19616                 make_vct(3),
19617                 make_color_with_catch(0.95, 0.95, 0.95),
19618                 :mus_error,
19619                 sqrt(-1.0),
19620                 make_delay(32),
19621                 lambda do || true end,
19622                 0,
19623                 1,
19624                 -1,
19625                 make_hook("snd_test"),
19626                 false,
19627                 true,
19628                 0.0,
19629                 1.0,
19630                 -1.0,
19631                 [],
19632                 3,
19633                 4,
19634                 2,
19635                 8,
19636                 16,
19637                 32,
19638                 64,
19639                 2.0 ** 21.5,
19640                 2.0 ** -18.0]
19641  functions.each do |name_sym, make_args, run_func|
19642    gen = if make_args
19643            snd_func(format("make_%s", name_sym), *make_args)
19644          else
19645            snd_func(format("make_%s", name_sym))
19646          end
19647    random_args.each do |arg1|
19648      Snd.catch do
19649        if proc?(run_func)
19650          run_func.call(gen, arg1)
19651        else
19652          snd_func(name_sym, gen, arg1)
19653        end
19654      end
19655      random_args.each do |arg2|
19656        Snd.catch do
19657          mus_run(gen, arg1, arg2)
19658        end
19659      end
19660    end
19661  end
19662end
19663
19664def test_08_24
19665  random_args = [
19666    2.0 ** 21.5,
19667    2.0 ** -18.0,
19668    1.5,
19669    "/hiho",
19670    [0, 1],
19671    1234,
19672    make_vct(3),
19673    make_color_with_catch(0.1, 0.2, 0.3),
19674    [0, 1],
19675    Rational(3, 4),
19676    Complex(0, 1), #sqrt(-1.0),
19677    make_delay(32),
19678    lambda do || 0.0 end,
19679    lambda do |dir| 1.0 end,
19680    lambda do |a, b, c| 1.0 end,
19681    0,
19682    1,
19683    -1,
19684    false,
19685    true,
19686    key_to_int(?c),
19687    0.0,
19688    1.0,
19689    -1.0,
19690    [],
19691    32,
19692    [1, 2]]
19693  random_gen = lambda do |*args|
19694    [:make_all_pass,
19695     :make_asymmetric_fm,
19696     :make_moving_average,
19697     :make_moving_max,
19698     :make_moving_norm,
19699     :make_table_lookup,
19700     :make_triangle_wave,
19701     :make_comb,
19702     :make_delay,
19703     :make_env,
19704     :make_fft_window,
19705     :make_filter,
19706     :make_filtered_comb,
19707     :make_fir_filter,
19708     :make_formant,
19709     :make_iir_filter,
19710     :make_locsig,
19711     :make_notch,
19712     :make_one_pole,
19713     :make_one_pole_all_pass,
19714     :make_one_zero,
19715     :make_oscil,
19716     :make_pulse_train,
19717     :make_rand,
19718     :make_rand_interp,
19719     :make_sawtooth_wave,
19720     :make_polyshape,
19721     :make_polywave,
19722     :make_square_wave,
19723     :make_two_pole,
19724     :make_two_zero,
19725     :make_wave_train,
19726     :make_ssb_am].each do |make_func|
19727      gen = Snd.catch do snd_func(make_func, *args) end.first
19728      if mus_generator?(gen)
19729        random_args.each do |arg|
19730          Snd.catch do gen.call(arg) end
19731        end
19732      end
19733    end
19734  end
19735  random_gen.call()
19736  random_args.each do |arg1|
19737    random_gen.call(arg1)
19738    random_args.each do |arg2|
19739      random_gen.call(arg1, arg2)
19740      if $all_args or $bigtest_08
19741        random_args.each do |arg3|
19742          random_gen.call(arg1, arg2, arg3)
19743          if $bigtest_08
19744            random_args.each do |arg4|
19745              random_gen.call(arg1, arg2, arg3, arg4)
19746            end
19747          end
19748        end
19749      end
19750    end
19751  end
19752end
19753
19754def test_08
19755  test_08_00
19756  test_08_01
19757  test_08_02
19758  test_08_03
19759  test_08_04
19760  test_08_05
19761  test_08_06
19762  test_08_08
19763  test_08_09
19764  test_08_10
19765  test_08_11
19766  test_08_12
19767  test_08_13
19768  test_08_14
19769  test_08_15
19770  test_08_16
19771  test_08_17
19772  test_08_18
19773  test_08_19
19774  test_08_20
19775  test_08_21
19776  test_08_22
19777  test_08_23
19778  test_08_24
19779end
19780
19781# ---------------- test 09: mix ----------------
19782
19783def test_09_00
19784  new_index = new_sound("hiho.wave", 1, 22050, Mus_bshort, Mus_next)
19785  select_sound(new_index)
19786  if res = find_mix(0, new_index, 0)
19787    snd_display("found non-existent mix: %s?", res)
19788  end
19789  unless mix?(mix_id = mix("pistol.snd", 100).car)
19790    snd_display("%s not mix?", mix_id)
19791  end
19792  view_mixes_dialog
19793  pos = mix_position(mix_id)
19794  len = mix_length(mix_id)
19795  spd = mix_speed(mix_id)
19796  snd, chn = mix_home(mix_id)[0, 2]
19797  nam = mix_name(mix_id)
19798  amp = mix_amp(mix_id)
19799  mr = make_mix_sampler(mix_id)
19800  unless mix_sampler?(mr)
19801    snd_display("%s not mix_sampler?", mr)
19802  end
19803  if region_sampler?(mr)
19804    snd_display("mix_sampler: region %s?", mr)
19805  end
19806  if (res = sampler_position(mr)).nonzero?
19807    snd_display("mix_sampler_position: %s?", res)
19808  end
19809  if sampler_at_end?(mr)
19810    snd_display("mix_sampler at end? %s", mr)
19811  end
19812  unless (res = sampler_home(mr)).eql?(mix_id)
19813    snd_display("%s home: %s?", sampler_home(mr), res)
19814  end
19815  if mr.to_s[0, 16] != "#<mix-sampler mi"
19816    snd_display("mix_sampler actually got: [%s]?", mr.to_s[0, 16])
19817  end
19818  99.times do |i|
19819    mx = i.odd? ? read_mix_sample(mr) : read_mix_sample(mr)
19820    sx = sample(100 + i)
19821    if fneq(mx, sx)
19822      snd_display("read_mix_sample: %s %s?", mx, sx)
19823    end
19824  end
19825  if fneq(mx = mr.call, sx = sample(199))
19826    snd_display("mix_sample 100: %s %s?", mx, sx)
19827  end
19828  free_sampler(mr)
19829  #
19830  if pos != 100
19831    snd_display("mix_position: %s?", pos)
19832  end
19833  if len != 41623
19834    snd_display("mix_length: %s?", len)
19835  end
19836  unless snd.eql?(new_index)
19837    snd_display("snd mix_home: %s?", snd)
19838  end
19839  if chn.nonzero?
19840    snd_display("chn mix_home: %s?", chn)
19841  end
19842  if fneq(amp, 1.0)
19843    snd_display("mix_amp: %s?", amp)
19844  end
19845  if fneq(spd, 1.0)
19846    snd_display("mix_speed: %s?", spd)
19847  end
19848  unless nam.null?
19849    snd_display("mix_name: %s?", nam)
19850  end
19851  Snd.catch(:mus_error, lambda do |*args| snd_display("cannot play mix: %s", args) end) do
19852    play(mix_id)
19853  end
19854  Snd.catch(:mus_error, lambda do |*args| snd_display("cannot play mix from 1000: %s", args) end) do
19855    play(mix_id, :start, 1000)
19856  end
19857  set_mix_name(mix_id, "test-mix")
19858  if (res = mix_name(mix_id)) != "test-mix"
19859    snd_display("mix_name set: %s?", res)
19860  end
19861  id = mix_name2id("test-mix")
19862  if mix2integer(id) != mix2integer(mix_id)
19863    snd_display("mix_name2id: %s %s?", id, mix_id)
19864  end
19865  set_mix_name(mix_id, "test-mix-again")
19866  if (res = mix_name(mix_id)) != "test-mix-again"
19867    snd_display("mix_name again: %s?", res)
19868  end
19869  set_mix_name(mix_id, false)
19870  unless (res = mix_name(mix_id)).null?
19871    snd_display("mix_name false: %s?", res)
19872  end
19873  set_mix_position(mix_id, 200)
19874  set_mix_amp(mix_id, 0.5)
19875  set_mix_speed(mix_id, 2.0)
19876  set_mix_amp_env(mix_id, [0, 0, 1, 1])
19877  val = mix_amp_env(mix_id)
19878  set_mix_amp_env(mix_id, mix_amp_env(mix_id))
19879  unless vequal(res = mix_amp_env(mix_id), val)
19880    snd_display("set_mix_amp_env to self: %s %s?", val, res)
19881  end
19882  set_mix_tag_y(mix_id, 20)
19883  pos = mix_position(mix_id)
19884  spd = mix_speed(mix_id)
19885  amp = mix_amp(mix_id)
19886  my = mix_tag_y(mix_id)
19887  if pos != 200
19888    snd_display("set_mix_position: %s?", pos)
19889  end
19890  if fneq(spd, 2.0)
19891    snd_display("set_mix_speed: %s?", spd)
19892  end
19893  if my != 20
19894    snd_display("set_mix_mix_tag_y: %s?", my)
19895  end
19896  if fneq(amp, 0.5)
19897    snd_display("set_mix_amp: %s?", amp)
19898  end
19899  if (res = mix_amp_env(mix_id)) != [0, 0, 1, 1]
19900    snd_display("set_mix_amp_env: %s?", res)
19901  end
19902  #
19903  mix_vct(make_vct(3, 0.1), 100)
19904  set_cursor(0)
19905  if (not mix?(nid = find_mix(100))) or mix_position(nid) != 100
19906    snd_display("find_mix(100) %s %s %s?",
19907                nid, (mix?(nid) and mix_position(nid)),
19908                mixes(new_index, 0).map do |m| mix_position(m) end)
19909  end
19910  if (not mix?(nid = find_mix(200))) or mix_position(nid) != 200
19911    snd_display("find_mix(200) %s %s?", nid, (mix?(nid) and mix_position(nid)))
19912  end
19913  #
19914  mix_id = mix("oboe.snd", 100).car
19915  set_mix_waveform_height(40)
19916  set_mix_property(:hiho, mix_id, 123)
19917  if (res = mix_property(:hiho, mix_id)) != 123
19918    snd_display("mix_property (123): %s?", res)
19919  end
19920  if (res = mix_property(:not_there, mix_id))
19921    snd_display("mix_not_property: %s?", res)
19922  end
19923  update_time_graph
19924  set_mix_waveform_height(20)
19925  revert_sound(new_index)
19926  #
19927  v1 = envelope_interp(1.0, [0, 0, 2.0, 1.0])
19928  v2 = envelope_interp(1.0, [0, 0.0, 1, 1.0, 2, 0.0])
19929  v3 = envelope_interp(2.0, [0, 0.0, 1, 1.0])
19930  v4 = envelope_interp(0.0, [1, 0.5, 2, 0])
19931  if fneq(v1, 0.5)
19932    snd_display("envelope_interp(1): %s (0.5)?", v1)
19933  end
19934  if fneq(v2, 1.0)
19935    snd_display("envelope_interp(2): %s (1.0)?", v2)
19936  end
19937  if fneq(v3, 1.0)
19938    snd_display("envelope_interp(3): %s (1.0)?", v3)
19939  end
19940  if fneq(v4, 0.5)
19941    snd_display("envelope_interp(4): %s (0.5)?", v4)
19942  end
19943  v1 = envelope_interp( 0.0, [-1,  0, 0, 1, 1, -1])
19944  v2 = envelope_interp(-0.5, [-1,  0, 0, 1, 1, -1])
19945  v3 = envelope_interp(-0.5, [-1, -1, 0, 1, 1, -1])
19946  v4 = envelope_interp(-0.5, [-1, -1, 1, 1])
19947  v5 = envelope_interp(-1.5, [-1, -1, 1, 1])
19948  v6 = envelope_interp( 1.5, [-1, -1, 1, 1])
19949  if fneq(v1,  1.0)
19950    snd_display("envelope_interp(1a): %s ( 1.0)?", v1)
19951  end
19952  if fneq(v2,  0.5)
19953    snd_display("envelope_interp(2a): %s ( 0.5)?", v2)
19954  end
19955  if fneq(v3,  0.0)
19956    snd_display("envelope_interp(3a): %s ( 0.0)?", v3)
19957  end
19958  if fneq(v4, -0.5)
19959    snd_display("envelope_interp(4a): %s (-0.5)?", v4)
19960  end
19961  if fneq(v5, -1.0)
19962    snd_display("envelope_interp(5a): %s (-1.0)?", v5)
19963  end
19964  if fneq(v6,  1.0)
19965    snd_display("envelope_interp(6a): %s ( 1.0)?", v6)
19966  end
19967  v1 = multiply_envelopes([0.0, 0.0, 2.0, 0.5], [0.0, 0.0, 1.0, 2.0, 2.0, 1.0])
19968  v2 = window_envelope(1.0, 3.0, [0.0, 0.0, 5.0, 1.0])
19969  unless vequal(v1, [0, 0, 0.5, 0.5, 1, 0.5])
19970    snd_display("multiply_envelopes: %s?", v1)
19971  end
19972  unless vequal(v2, [1, 0.2, 3, 0.6])
19973    snd_display("window_envelope: %s?", v2)
19974  end
19975  close_sound(new_index)
19976  dismiss_all_dialogs
19977end
19978
19979def test_09_02
19980  ind = new_sound("fmv.snd", 1, 22050, Mus_bshort, Mus_next, "mix tests")
19981  insert_silence(0, 20, ind)
19982  indout = new_sound("test.snd", 1, 22050, Mus_bshort, Mus_next, "mix tests")
19983  insert_silence(0, 10, indout)
19984  set_sample(2, 0.5, indout, 0)
19985  set_sample(5, 0.25, indout, 0)
19986  save_sound(indout)
19987  close_sound(indout)
19988  tag = mix("test.snd").car
19989  samps = channel2vct(0, 20)
19990  v = make_vct(20)
19991  v[2] = 0.5
19992  v[5] = 0.25
19993  unless  vequal(samps, v)
19994    snd_display("mix 1->1: %s %s?", samps, v)
19995  end
19996  unless mix?(tag)
19997    snd_display("mix 1->1 tag: %s?", tag)
19998  end
19999  undo_edit
20000  tag = mix("test.snd", 5).car
20001  samps = channel2vct(0, 20)
20002  v = make_vct(20)
20003  v[7] = 0.5
20004  v[10] = 0.25
20005  unless  vequal(samps, v)
20006    snd_display("mix 1->1 at 5: %s %s?", samps, v)
20007  end
20008  unless mix?(tag)
20009    snd_display("mix 1->1 at 5 tag: %s?", tag)
20010  end
20011  undo_edit
20012  tag = mix("test.snd", 0, 0, ind, 0, false)
20013  samps = channel2vct(0, 20)
20014  v = make_vct(20)
20015  v[2] = 0.5
20016  v[5] = 0.25
20017  unless  vequal(samps, v)
20018    snd_display("mix 1->1 at 0: %s %s?", samps, v)
20019  end
20020  if mix?(tag)
20021    snd_display("mix 1->1 at 0 tag: %s?", tag)
20022  end
20023  undo_edit
20024  indout = new_sound("test.snd", 2, 22050, Mus_bshort, Mus_next, "mix tests")
20025  insert_silence(0, 10, indout, 0)
20026  insert_silence(0, 10, indout, 1)
20027  set_sample(2, 0.5, indout, 0)
20028  set_sample(5, 0.25, indout, 0)
20029  set_sample(2, 0.95, indout, 1)
20030  set_sample(5, 0.125, indout, 1)
20031  save_sound(indout)
20032  close_sound(indout)
20033  tag = mix("test.snd", 0, 1).car
20034  samps = channel2vct(0, 20)
20035  v = make_vct(20)
20036  v[2] = 0.95
20037  v[5] = 0.125
20038  unless  vequal(samps, v)
20039    snd_display("mix 2->1: %s %s?", samps, v)
20040  end
20041  unless mix?(tag)
20042    snd_display("mix 2->1 tag: %s?", tag)
20043  end
20044  undo_edit
20045  tag = mix("test.snd", 5, 1).car
20046  samps = channel2vct(0, 20)
20047  v = make_vct(20)
20048  v[7] = 0.95
20049  v[10] = 0.125
20050  unless  vequal(samps, v)
20051    snd_display("mix 2->1 at 5: %s %s?", samps, v)
20052  end
20053  unless mix?(tag)
20054    snd_display("mix 2->1 at 5 tag: %s?", tag)
20055  end
20056  undo_edit
20057  close_sound(ind)
20058  #
20059  ind = new_sound("fmv.snd", 2, 22050, Mus_bshort, Mus_next, "mix tests")
20060  insert_silence(0, 20, ind, 0)
20061  insert_silence(0, 20, ind, 1)
20062  tag = mix("test.snd", 0, true).car
20063  samps0 = channel2vct(0, 20, ind, 0)
20064  samps1 = channel2vct(0, 20, ind, 1)
20065  v = make_vct(20)
20066  v[2] = 0.5
20067  v[5] = 0.25
20068  unless  vequal(samps0, v)
20069    snd_display("mix 1->1 (2): %s %s?", samps0, v)
20070  end
20071  v[2] = 0.95
20072  v[5] = 0.125
20073  unless  vequal(samps1, v)
20074    snd_display("mix 1->1 (3): %s %s?", samps1, v)
20075  end
20076  unless mix?(tag)
20077    snd_display("mix 1->1 tag: %s?", tag)
20078  end
20079  undo_edit(1, ind, 0)
20080  undo_edit(1, ind, 1)
20081  tag = mix("test.snd", 0, 1, ind, 1, false)
20082  samps0 = channel2vct(0, 20, ind, 0)
20083  samps1 = channel2vct(0, 20, ind, 1)
20084  v = make_vct(20)
20085  unless  vequal(samps0, v)
20086    snd_display("mix 1->1 (4): %s %s?", samps0, v)
20087  end
20088  v[2] = 0.95
20089  v[5] = 0.125
20090  unless  vequal(samps1, v)
20091    snd_display("mix 1->1 (5): %s %s?", samps1, v)
20092  end
20093  if mix?(tag)
20094    snd_display("mix 1->1 tag: %s?", tag)
20095  end
20096  undo_edit(1, ind, 1)
20097  set_sync(1, ind)
20098  mix("test.snd", 0, true).car
20099  samps0 = channel2vct(0, 20, ind, 0)
20100  samps1 = channel2vct(0, 20, ind, 1)
20101  v = make_vct(20)
20102  v[2] = 0.5
20103  v[5] = 0.25
20104  unless  vequal(samps0, v)
20105    snd_display("mix 1->1 (6): %s %s?", samps0, v)
20106  end
20107  v[2] = 0.95
20108  v[5] = 0.125
20109  unless  vequal(samps1, v)
20110    snd_display("mix 1->1 (7): %s %s?", samps1, v)
20111  end
20112  undo_edit
20113  close_sound(ind)
20114  delete_files("test.snd", "fmv.snd")
20115  #
20116  # check ripple_mixes
20117  #
20118  ind = open_sound("oboe.snd")
20119  data = channel2vct(100, 100)
20120  m1 = mix_vct(data, 321, ind, 0, true)
20121  m2 = mix_vct(data, 123, ind, 0, true)
20122  set_mix_position(m1, 500)
20123  if (res = mix_position(m1)) != 500
20124    snd_display("mix_position m1[0]: %s?", res)
20125  end
20126  if (res = mix_position(m2)) != 123
20127    snd_display("mix_position m2[0]: %s?", res)
20128  end
20129  undo_edit
20130  set_mix_position(m2, 500)
20131  if (res = mix_position(m2)) != 500
20132    snd_display("mix_position m2[1]: %s?", res)
20133  end
20134  if (res = mix_position(m1)) != 321
20135    snd_display("mix_position m1[1]: %s?", res)
20136  end
20137  undo_edit
20138  insert_silence(0, 100)
20139  if (res = mix_position(m1)) != 321 + 100
20140    snd_display("mix_position m1[2]: %s?", res)
20141  end
20142  if (res = mix_position(m2)) != 123 + 100
20143    snd_display("mix_position m2[2]: %s?", res)
20144  end
20145  delete_samples(0, 50)
20146  if (res = mix_position(m1)) != 321 + 50
20147    snd_display("mix_position m1[3]: %s?", res)
20148  end
20149  if (res = mix_position(m2)) != 123 + 50
20150    snd_display("mix_position m2[3]: %s?", res)
20151  end
20152  undo_edit(2)
20153  set_mix_position(m2, 500)
20154  undo_edit
20155  scale_channel(0.5, 1000, 100)
20156  if (res = mix_position(m2)) != 123
20157    snd_display("mix_position m2[5]: %s?", res)
20158  end
20159  if (res = mix_position(m1)) != 321
20160    snd_display("mix_position m1[5]: %s?", res)
20161  end
20162  undo_edit
20163  set_mix_position(m2, 500)
20164  undo_edit
20165  set_mix_position(m2, 500)
20166  undo_edit
20167  ramp_channel(0.0, 1.0, 3000, 100)
20168  if (res = Snd.catch do
20169        if (res = mix_position(m2)) != 123
20170          snd_display("mix_position m2[7]: %s?", res)
20171        end
20172        if (res = mix_position(m1)) != 321
20173          snd_display("mix_position m1[7]: %s?", res)
20174        end
20175      end).first
20176    snd_display("mix_position trouble: %s", res.inspect)
20177  end
20178  close_sound(ind)
20179  #
20180  # check that current console is correct
20181  #
20182  ind = open_sound("storm.snd")
20183  set_x_bounds([0, 80])
20184  make_selection(1000000, 1050000)
20185  m1 = mix_selection(900000).car
20186  m2 = mix_selection(400000).car
20187  as_one_edit(lambda do | |
20188                set_mix_position(m1, 0)
20189                set_mix_position(m2, 1)
20190              end)
20191  if ((res1 = mix_position(m1)) != 0) or ((res2 = mix_position(m2)) != 1)
20192    snd_display("as_one_edit positions: %s %s?", res1, res2)
20193  end
20194  undo_channel
20195  if ((res1 = mix_position(m1)) != 900000) or ((res2 = mix_position(m2)) != 400000)
20196    snd_display("as_one_edit positions after undo: (%s): %s (%s): %s?", m1, res1, m2, res2)
20197  end
20198  redo_channel
20199  if (res1 = mix_position(m1)) != 0 or (res2 = mix_position(m2)) != 1
20200    snd_display("as_one_edit positions after redo: %s %s?", res1, res2)
20201  end
20202  close_sound(ind)
20203  #
20204  ind = open_sound("2.snd")
20205  make_selection(0, 10000, ind)
20206  if (res = selection_chans) != 2
20207    snd_display("stereo selection: %s?", res)
20208  end
20209  set_sync(true, ind)
20210  md = mix_selection(500, ind).car
20211  unless mix?(integer2mix(mix2integer(md) + 1))
20212    snd_display("where is 2nd mix? %s %s?", md, mixes)
20213  end
20214  if (res = edit_position(ind, 0)) != 1
20215    snd_display("edit_position 0 after stereo mix selection: %s?", res)
20216  end
20217  if (res = edit_position(ind, 1)) != 1
20218    snd_display("edit_position 1 after stereo mix selection: %s?", res)
20219  end
20220  close_sound(ind)
20221end
20222
20223def test_mix_disconnect(name, id0, chn0, id1, chn1)
20224  amp0 = mix_amp(id0)
20225  amp1 = mix_amp(id1)
20226  env0 = mix_amp_env(id0)
20227  env1 = mix_amp_env(id1)
20228  set_mix_amp(id0, mix_amp(id0) * 0.5)
20229  if fneq(mix_amp(id0), 0.5 * amp0) or
20230      fneq(mix_amp(id1), amp1)
20231    snd_display("pan_mix disconnect amp %s: %s (%s) %s (%s)?",
20232                name, mix_amp(id0), amp0, mix_amp(id1), amp1)
20233  end
20234  set_mix_amp_env(id1, [0.0, random(1.0), 1.0, random(1.0)])
20235  if mix_amp_env(id0) != env0 or (not vequal(mix_amp_env(id1), (env1 or [])))
20236    snd_display("pan_mix disconnect amp_env %s: %s (%s) %s (%s)?",
20237                name,
20238                mix_amp_env(id0), env0,
20239                mix_amp_env(id1), env1)
20240  end
20241  if id0 != id1
20242    pos0 = mix_position(id0)
20243    pos1 = mix_position(id1)
20244    spd0 = mix_speed(id0)
20245    spd1 = mix_speed(id1)
20246    set_mix_position(id0, pos0 + 12)
20247    if mix_position(id0) == pos0 or mix_position(id1) != pos1
20248      snd_display("pan_mix disconnect position %s: %s (%s) %s (%s)?",
20249                  name, mix_position(id0), pos0, mix_position(id1), pos1)
20250    end
20251    set_mix_speed(id1, mix_speed(id1) * 1.5)
20252    if fneq(mix_speed(id1), 1.5 * spd1) or fneq(mix_speed(id0), spd0)
20253      snd_display("pan_mix disconnect speed %s: %s (%s) %s (%s)?",
20254                  name, mix_speed(id0), spd0, mix_speed(id1), spd1)
20255    end
20256  end
20257end
20258
20259def test_09_03
20260  ind = new_sound("test.snd")
20261  v = Vct.new(20) do |i| i * 0.01 end
20262  vct2channel(v)
20263  v.map! do |val| -val end
20264  mx = mix_vct(v, 10)
20265  hi = make_mix_sampler(mx, 0)
20266  ho = make_mix_sampler(mx, 5)
20267  10.times do |i|
20268    ho_val = ho.call
20269    hi_val = hi.call
20270    if fneq(hi_val, i * -0.01)
20271      snd_display("mix_reader at %s from 0: %s?", i, hi_val)
20272      break
20273    end
20274    if fneq(ho_val, (i + 5)* -0.01)
20275      snd_display("mix_reader at %s from 5: %s?", i, ho_val)
20276      break
20277    end
20278  end
20279  revert_sound(ind)
20280  v = Vct.new(21)
20281  v.fill(0.5)
20282  vct2channel(v)
20283  mx = mix_vct(v, 10)
20284  set_mix_amp_env(mx, [0, 0, 1, 1])
20285  hi = make_mix_sampler(mx, 0)
20286  ho = make_mix_sampler(mx, 10)
20287  10.times do |i|
20288    ho_val = ho.call
20289    hi_val = hi.call
20290    if fneq(hi_val, i * 0.025)
20291      snd_display("mix_reader enved at %s from 0: %s?", i, hi_val)
20292      break
20293    end
20294    if fneq(ho_val, (i + 10)* 0.025)
20295      snd_display("mix_reader enved at %s from 5: %s?", i, ho_val)
20296      break
20297    end
20298  end
20299  close_sound(ind)
20300  #
20301  ind = open_sound("oboe.snd")
20302  id = mix_vct(Vct.new(10, 0.1))
20303  set_mix_position(id, 100)
20304  if (res1 = mix_position(id)) != 100 or (res2 = edit_position(ind, 0)) != 2
20305    snd_display("mix_position init: %s %s?", res1, res2)
20306  end
20307  set_mix_position(id, 100)
20308  if (res1 = mix_position(id)) != mix_position(id) or (res2 = edit_position(ind, 0)) != 2
20309    snd_display("mix_position 2 (no-op): %s %s?", res1, res2)
20310  end
20311  set_mix_amp(id, 1.0)
20312  if fneq(res1 = mix_amp(id), 1.0) or (res2 = edit_position(ind, 0)) != 2
20313    snd_display("mix_amp no-op: %s %s?", res1, res2)
20314  end
20315  set_mix_amp(id, 0.5)
20316  if fneq(res1 = mix_amp(id), 0.5) or (res2 = edit_position(ind, 0)) != 3
20317    snd_display("mix_amp 0.5: %s %s?", res1, res2)
20318  end
20319  set_mix_amp(id, mix_amp(id))
20320  if fneq(res1 = mix_amp(id), 0.5) or (res2 = edit_position(ind, 0)) != 3
20321    snd_display("mix_amp no-op: %s %s?", res1, res2)
20322  end
20323  set_mix_speed(id, 1.0)
20324  if fneq(res1 = mix_speed(id), 1.0) or (res2 = edit_position(ind, 0)) != 3
20325    snd_display("mix_speed no-op: %s %s?", res1, res2)
20326  end
20327  set_mix_speed(id, 0.5)
20328  if fneq(res1 = mix_speed(id), 0.5) or (res2 = edit_position(ind, 0)) != 4
20329    snd_display("mix_speed 0.5: %s %s?", res1, res2)
20330  end
20331  set_mix_speed(id, mix_speed(id))
20332  if fneq(res1 = mix_speed(id), 0.5) or (res2 = edit_position(ind, 0)) != 4
20333    snd_display("mix_speed 2 no-op: %s %s?", res1, res2)
20334  end
20335  set_mix_amp_env(id, [0, 0, 1, 1])
20336  if (res = edit_position(ind, 0)) != 5
20337    snd_display("mix_amp init: %s %s?", mix_amp_env(id), res)
20338  end
20339  set_mix_amp_env(id, [0, 0, 1, 1])
20340  if (res = edit_position(ind, 0)) != 5
20341    snd_display("mix_amp no-op: %s %s?", mix_amp_env(id), res)
20342  end
20343  close_sound(ind)
20344  #
20345  ind = new_sound("test.snd", 1, 22050, Mus_bfloat, Mus_next, "lock mix tests", 300)
20346  mix1 = mix_vct(Vct.new(10, 0.5), 10)
20347  set_mix_amp(mix1, 0.0)
20348  if fneq(res = maxamp(ind, 0), 0.0)
20349    snd_display("delete mix maxamp: %s?", res)
20350  end
20351  undo_channel(1, ind, 0)
20352  if fneq(res = maxamp(ind, 0), 0.5)
20353    snd_display("undelete mix maxamp: %s?", res)
20354  end
20355  redo_channel(1, ind, 0)
20356  if fneq(res = maxamp(ind, 0), 0.0)
20357    snd_display("redelete mix maxamp: %s?", res)
20358  end
20359  undo_edit(2)
20360  if number?(mix?(mix1))
20361    snd_display("undo 2 kept mix?")
20362  end
20363  if fneq(res = maxamp(ind, 0), 0.0)
20364    snd_display("no delete_mix maxamp: %s?", res)
20365  end
20366  redo_edit
20367  if fneq(res = maxamp(ind, 0), 0.5)
20368    snd_display("reundelete mix maxamp: %s?", res)
20369  end
20370  close_sound(ind)
20371end
20372
20373def test_09_04
20374  #
20375  set_with_mix_tags(true)
20376  ind = open_sound("oboe.snd")
20377  mx = mix_vct(Vct.new(100, 0.1), 1000)
20378  fr = mus_sound_framples("1a.snd")
20379  [[lambda do pad_channel(0,     100) end, 1100, false, :pad0],
20380   [lambda do pad_channel(0,    2000) end, 3000, false, :pad20],
20381   [lambda do pad_channel(800,   100) end, 1100, false, :pad800],
20382   [lambda do pad_channel(850,   100) end, 1100, false, :pad800],
20383   [lambda do pad_channel(990,   100) end, 1100, false, :pad990],
20384   [lambda do pad_channel(1010,  100) end, 1000, true,  :pad1010],
20385   [lambda do pad_channel(1050,   10) end, 1000, true,  :pad1050],
20386   [lambda do pad_channel(1110,  100) end, 1000, false, :pad1110],
20387   [lambda do pad_channel(2000,  100) end, 1000, false, :pad2000],
20388   [lambda do insert_samples(0,    100, Vct.new(100, 0.2)) end, 1100, false, :insert0],
20389   [lambda do insert_samples(800,  100, Vct.new(100, 0.2)) end, 1100, false, :insert800],
20390   [lambda do insert_samples(990,  100, Vct.new(100, 0.2)) end, 1100, false, :insert990],
20391   [lambda do insert_samples(1010, 100, Vct.new(100, 0.2)) end, 1000, true,  :insert1010],
20392   [lambda do insert_samples(1050,  10, Vct.new(100, 0.2)) end, 1000, true,  :insert1050],
20393   [lambda do insert_samples(1110, 100, Vct.new(100, 0.2)) end, 1000, false, :insert1110],
20394   [lambda do insert_samples(2000, 100, Vct.new(100, 0.2)) end, 1000, false, :insert2000],
20395   [lambda do insert_sound("1a.snd",    0) end, fr + 1000, false, :inserts0],
20396   [lambda do insert_sound("1a.snd",  800) end, fr + 1000, false, :inserts800],
20397   [lambda do insert_sound("1a.snd",  990) end, fr + 1000, false, :inserts990],
20398   [lambda do insert_sound("1a.snd", 1010) end,      1000, true,  :inserts1010],
20399   [lambda do insert_sound("1a.snd", 1050) end,      1000, true,  :inserts1050],
20400   [lambda do insert_sound("1a.snd", 1110) end,      1000, false, :inserts1110],
20401   [lambda do insert_sound("1a.snd", 2000) end,      1000, false, :inserts2000],
20402   [lambda do delete_samples(0,    100) end,  900, false, :delete0],
20403   [lambda do delete_samples(0,   2000) end, 1000, true,  :delete20],
20404   [lambda do delete_samples(800,  100) end,  900, false, :delete800],
20405   [lambda do delete_samples(850,  100) end,  900, false, :delete850],
20406   [lambda do delete_samples(950,   40) end,  960, false, :delete950],
20407   [lambda do delete_samples(990,  100) end, 1000, true,  :delete990],
20408   [lambda do delete_samples(1010, 100) end, 1000, true,  :delete1010],
20409   [lambda do delete_samples(1050,  10) end, 1000, true,  :delete1050],
20410   [lambda do delete_samples(1110, 100) end, 1000, false, :delete1110],
20411   [lambda do delete_samples(2000, 100) end, 1000, false, :delete2000],
20412   [lambda do set_samples(0,    100, Vct.new(100,  0.2)) end, 1000, false, :set0],
20413   [lambda do set_samples(0,   2000, Vct.new(2000, 0.2)) end, 1000, true,  :set0],
20414   [lambda do set_samples(800,  100, Vct.new(100,  0.2)) end, 1000, false, :set800],
20415   [lambda do set_samples(990,  100, Vct.new(100,  0.2)) end, 1000, true,  :set990],
20416   [lambda do set_samples(1010, 100, Vct.new(100,  0.2)) end, 1000, true,  :set1010],
20417   [lambda do set_samples(1050,  10, Vct.new(100,  0.2)) end, 1000, true,  :set1050],
20418   [lambda do set_samples(1110, 100, Vct.new(100,  0.2)) end, 1000, false, :set1110],
20419   [lambda do set_samples(2000, 100, Vct.new(100,  0.2)) end, 1000, false, :set2000],
20420   [lambda do scale_channel(2.0, 0,    100) end, 1000, false, :scale0],
20421   [lambda do scale_channel(2.0, 0,   2000) end, 1000, true,  :scale20],
20422   [lambda do scale_channel(2.0, 800,  100) end, 1000, false, :scale800],
20423   [lambda do scale_channel(2.0, 850,  100) end, 1000, false, :scale850],
20424   [lambda do scale_channel(2.0, 950,   40) end, 1000, false, :scale950],
20425   [lambda do scale_channel(2.0, 990,  100) end, 1000, true,  :scale990],
20426   [lambda do scale_channel(2.0, 1010, 100) end, 1000, true,  :scale1010],
20427   [lambda do scale_channel(2.0, 1050,  10) end, 1000, true,  :scale1050],
20428   [lambda do scale_channel(2.0, 1110, 100) end, 1000, false, :scale1110],
20429   [lambda do scale_channel(2.0, 2000, 100) end, 1000, false, :scale2000],
20430   [lambda do env_channel([0, 0, 1, 1], 0,    100) end, 1000, false, :env0],
20431   [lambda do env_channel([0, 0, 1, 1], 0,   2000) end, 1000, true,  :env20],
20432   [lambda do env_channel([0, 0, 1, 1], 800,  100) end, 1000, false, :env800],
20433   [lambda do env_channel([0, 0, 1, 1], 850,  100) end, 1000, false, :env850],
20434   [lambda do env_channel([0, 0, 1, 1], 950,   40) end, 1000, false, :env950],
20435   [lambda do env_channel([0, 0, 1, 1], 990,  100) end, 1000, true,  :env990],
20436   [lambda do env_channel([0, 0, 1, 1], 1010, 100) end, 1000, true,  :env1010],
20437   [lambda do env_channel([0, 0, 1, 1], 1050,  10) end, 1000, true,  :env1050],
20438   [lambda do env_channel([0, 0, 1, 1], 1110, 100) end, 1000, false, :env1110],
20439   [lambda do env_channel([0, 0, 1, 1], 2000, 100) end, 1000, false, :env2000]
20440  ].each do |func, beg, lock, name|
20441    edpos = edit_position(ind, 0)
20442    func.call
20443    set_edit_position(edpos, ind, 0)
20444  end
20445  close_sound(ind)
20446  #
20447  ind = open_sound("4.aiff")
20448  selind = open_sound("oboe.snd")
20449  make_selection(100, 500, selind, 0)
20450  mix_selection(500, ind, 2)
20451  if (res = edit_position(ind, 0)) != 0
20452    snd_display("mix_selection 0->2 0: %s?", res)
20453  end
20454  if (res = edit_position(ind, 1)) != 0
20455    snd_display("mix_selection 0->2 1: %s?", res)
20456  end
20457  if (res = edit_position(ind, 2)) != 1
20458    snd_display("mix_selection 0->2 2: %s?", res)
20459  end
20460  if (res = edit_position(ind, 3)) != 0
20461    snd_display("mix_selection 0->2 3: %s?", res)
20462  end
20463  revert_sound(ind)
20464  set_sync(1234, ind)
20465  mix_selection(500, ind, 1)
20466  if (res = edit_position(ind, 0)) != 0
20467    snd_display("mix_selection 1->2 0: %s?", res)
20468  end
20469  if (res = edit_position(ind, 1)) != 1
20470    snd_display("mix_selection 1->2 1: %s?", res)
20471  end
20472  if (res = edit_position(ind, 2)) != 0
20473    snd_display("mix_selection 1->2 2: %s?", res)
20474  end
20475  if (res = edit_position(ind, 3)) != 0
20476    snd_display("mix_selection 1->2 3: %s?", res)
20477  end
20478  revert_sound(ind)
20479  set_sync(0, ind)
20480  insert_selection(500, ind, 2)
20481  if (res = edit_position(ind, 0)) != 0
20482    snd_display("insert_selection 0->2 0: %s?", res)
20483  end
20484  if (res = edit_position(ind, 1)) != 0
20485    snd_display("insert_selection 0->2 1: %s?", res)
20486  end
20487  if (res = edit_position(ind, 2)) != 1
20488    snd_display("insert_selection 0->2 2: %s?", res)
20489  end
20490  if (res = edit_position(ind, 3)) != 0
20491    snd_display("insert_selection 0->2 3: %s?", res)
20492  end
20493  revert_sound(ind)
20494  set_sync(1234, ind)
20495  insert_selection(500, ind, 1)
20496  if (res = edit_position(ind, 0)) != 0
20497    snd_display("insert_selection 1->2 0: %s?", res)
20498  end
20499  if (res = edit_position(ind, 1)) != 1
20500    snd_display("insert_selection 1->2 1: %s?", res)
20501  end
20502  if (res = edit_position(ind, 2)) != 0
20503    snd_display("insert_selection 1->2 2: %s?", res)
20504  end
20505  if (res = edit_position(ind, 3)) != 0
20506    snd_display("insert_selection 1->2 3: %s?", res)
20507  end
20508  revert_sound(ind)
20509  set_sync(0, ind)
20510  close_sound(ind)
20511  close_sound(selind)
20512end
20513
20514def test_09
20515  if $with_test_gui
20516    test_09_00
20517    test_09_02
20518    test_09_03
20519    test_09_04
20520  end
20521end
20522
20523# ---------------- test 10: marks ----------------
20524
20525def data_max(beg, fin)
20526  maxval = 0.0
20527  Snd.sounds.each do |snd|
20528    channels(snd).times do |chn|
20529      scan_channel(lambda do |data|
20530                     maxval = [maxval, data.abs].max
20531                     false
20532                   end, 0, false, snd, chn)
20533    end
20534  end
20535  maxval
20536end
20537
20538def data_max2(beg, fin, snd)
20539  maxval = 0.0
20540  channels(snd).times do |chn|
20541    scan_channel(lambda do |data|
20542                   maxval = [maxval, data.abs].max
20543                   false
20544                 end, 0, false, snd, chn)
20545  end
20546  maxval
20547end
20548
20549def data_max1(beg, fin, snd, chn)
20550  maxval = 0.0
20551  scan_channel(lambda do |data|
20552                 maxval = [maxval, data.abs].max
20553                 false
20554               end, beg, fin, snd, chn)
20555  maxval
20556end
20557
20558def test_10_00
20559  ind0 = new_sound("fmv.snd", 2, 22050, Mus_bshort, Mus_aifc,
20560                   "this is a comment")
20561  ind1 = new_sound("fmv1.snd", 1, 22050, Mus_bshort, Mus_aifc,
20562                   "this is a comment")
20563  v0 = make_array(10, 1.0)
20564  set_sync(123, ind0)
20565  set_sync(123, ind1)
20566  insert_samples(0, 10, v0, ind0, 0)
20567  insert_samples(0, 10, v0, ind0, 1)
20568  insert_samples(0, 10, v0, ind1, 0)
20569  env_sound([0, 0, 1, 1], 0, 10, 1.0, ind0)
20570  10.times do |i|
20571    if fneq(res = sample(i, ind0, 0), i * 0.1111)
20572      snd_display("ind0:0 1 env_sound[%s]: %s?", i, res)
20573    end
20574    if fneq(res = sample(i, ind0, 1), i * 0.1111)
20575      snd_display("ind0:1 1 env_sound[%s]: %s?", i, res)
20576    end
20577    if fneq(res = sample(i, ind0, 0), i * 0.1111)
20578      snd_display("ind1:0 1 env_sound[%s]: %s?", i, res)
20579    end
20580  end
20581  undo_edit
20582  env_sound(make_env(:envelope, [0, 0, 1, 1], :length, 10), 0, 10, 1.0, ind0)
20583  10.times do |i|
20584    if fneq(res = sample(i, ind0, 0), i * 0.1111)
20585      snd_display("ind0:0 2 env_sound[%s]: %s?", i, res)
20586    end
20587    if fneq(res = sample(i, ind0, 1), i * 0.1111)
20588      snd_display("ind0:1 2 env_sound[%s]: %s?", i, res)
20589    end
20590    if fneq(res = sample(i, ind0, 0), i * 0.1111)
20591      snd_display("ind1:0 2 env_sound[%s]: %s?", i, res)
20592    end
20593  end
20594  undo_edit
20595  env_sound([0, 0, 0.5, 1, 1, 1], 0, 10, 0.0, ind0)
20596  if fneq(res1 = sample(3, ind0, 0), 0.0) or fneq(res2 = sample(8, ind0, 0), 1.0)
20597    snd_display("ind0:0 env_sound stepped: %s %s?", res1, res2)
20598  end
20599  if fneq(res1 = sample(3, ind0, 0), 0.0) or fneq(res2 = sample(8, ind0, 0), 1.0)
20600    snd_display("ind0:1 env_sound stepped: %s %s?", res1, res2)
20601  end
20602  if fneq(res1 = sample(3, ind0, 0), 0.0) or fneq(res2 = sample(8, ind0, 0), 1.0)
20603    snd_display("ind1:0 env_sound stepped: %s %s?", res1, res2)
20604  end
20605  undo_edit
20606  revert_sound(ind0)
20607  revert_sound(ind1)
20608  insert_samples(0, 10, v0, ind0, 0)
20609  insert_samples(0, 10, v0, ind0, 1)
20610  insert_samples(0, 10, v0, ind1, 0)
20611  filter_sound(make_one_zero(:a0, 0.5, :a1, 0.0), 0, ind0)
20612  10.times do |i|
20613    if fneq(res = sample(i, ind0, 0), 0.5)
20614      snd_display("ind0:0 1 filter_sound[%s]: %s?", i, res)
20615    end
20616    if fneq(res = sample(i, ind0, 1), 0.5)
20617      snd_display("ind0:1 1 filter_sound[%s]: %s?", i, res)
20618    end
20619    if fneq(res = sample(i, ind0, 0), 0.5)
20620      snd_display("ind1:0 1 filter_sound[%s]: %s?", i, res)
20621    end
20622  end
20623  close_sound(ind0)
20624  close_sound(ind1)
20625  #
20626  ind0 = new_sound("fmv.snd", 1, 22050, Mus_bshort, Mus_aifc,
20627                   "this is a comment")
20628  v0 = Vct.new(10, 0.1)
20629  old5 = sample(5, ind0)
20630  insert_samples(10, 10, v0, ind0)
20631  env_sound([0, 0, 1, 2], 10, 10, 1.0, ind0)
20632  10.times do |i|
20633    if fneq(res = sample(i + 10, ind0), i * 0.0222)
20634      snd_display("env_sound[%s]: %s?", i + 10, res)
20635    end
20636  end
20637  if fneq(res = sample(5, ind0), old5)
20638    snd_display("env_sound[5]: %s %s?", old5, res)
20639  end
20640  undo_edit
20641  env_sound([0, 0, 1, 2], 10, 10, 4.0, ind0)
20642  v0 = channel2vct(10, 10)
20643  if fneq(v0[3], 0.039) or fneq(v0[8], 0.162)
20644    snd_display("env_sound 4.0: %s?", v0)
20645  end
20646  undo_edit
20647  env_sound([0, 0, 1, 2], 10, 10, 0.05, ind0)
20648  v0 = channel2vct(10, 10)
20649  if fneq(v0[3], 0.133) or fneq(v0[8], 0.196)
20650    snd_display("env_sound 0.05: %s?", v0)
20651  end
20652  close_sound(ind0)
20653  #
20654  ind0 = new_sound("fmv.snd", 2, 22050, Mus_bshort, Mus_aifc,
20655                   "this is a comment")
20656  ind1 = new_sound("fmv1.snd", 1, 22050, Mus_bshort, Mus_next,
20657                   "this is a comment")
20658  insert_samples(0, 10, make_array(10, 1.00), ind0, 0)
20659  insert_samples(0, 10, make_array(10, 0.10), ind0, 1)
20660  insert_samples(0, 10, make_array(10, 0.01), ind1, 0)
20661  if fneq(res = data_max1(0, 9, ind0, 0), 1.00)
20662    snd_display("scan_chan[0,0]: %s?", res)
20663  end
20664  if fneq(res = data_max1(0, 9, ind0, 1), 0.10)
20665    snd_display("scan_chan[0,1]: %s?", res)
20666  end
20667  if fneq(res = data_max1(0, 9, ind1, 0), 0.01)
20668    snd_display("scan_chan[1,0]: %s?", res)
20669  end
20670  if fneq(res = data_max1(0, 9, false, false), 0.01)
20671    snd_display("scan_chans: %s?", res)
20672  end
20673  if fneq(res = data_max(0, 9), 1.00)
20674    snd_display("scan_all_chans: %s?", res)
20675  end
20676  if fneq(res = data_max2(0, 9, ind0), 1.00)
20677    snd_display("scan_across_all_chans: %s?", res)
20678  end
20679  close_sound(ind0)
20680  close_sound(ind1)
20681end
20682
20683def test_10_01
20684  ind0 = new_sound("fmv.snd", 2, 22050, Mus_bshort, Mus_aifc,
20685                   "this is a comment")
20686  mix("oboe.snd")
20687  m1 = add_mark(100)
20688  delete_sample(10)
20689  m2 = add_mark(200)
20690  delete_sample(10)
20691  m3 = add_mark(300)
20692  undo_edit
20693  save_sound
20694  if marks(ind0, 0).length != 2
20695    snd_display("marks after save: %s?", marks(ind0, 0))
20696  end
20697  if (not mark?(m1)) or mark_sample(m1) != 99
20698    snd_display("save_sound mark1: %s?", mark_sample(m1))
20699  end
20700  if (not mark?(m2)) or mark_sample(m2) != 200
20701    snd_display("save_sound mark2: %s?", mark_sample(m1))
20702  end
20703  if mark?(m3)
20704    snd_display("save_sound mark3: %s?", m3)
20705  end
20706  close_sound(ind0)
20707  #
20708  fd = open_sound("oboe.snd")
20709  m1 = add_mark(123)
20710  sync_val = mark_sync_max + 1
20711  unless mark?(m1)
20712    snd_display("mark?")
20713  end
20714  if mark_sample(m1) != 123
20715    snd_display("add_mark: %s?", mark_sample(m1))
20716  end
20717  set_mark_property(:hiho, m1, 123)
20718  if (res = mark_property(:hiho, m1)) != 123
20719    snd_display("mark_property: %s?", res)
20720  end
20721  if (res = mark_property(:not_there, m1))
20722    snd_display("mark_not_property: %s?", res)
20723  end
20724  if (res = Snd.catch do add_mark(123, 123) end).first != :no_such_sound
20725    snd_display("add_mark err: %s", res.inspect)
20726  end
20727  m2 = add_mark(12345, fd, 0)
20728  unless mark?(m2)
20729    snd_display("add_mark failed?: %s", m2)
20730  end
20731  if mark_sample(m2) != 12345
20732    snd_display("add_mark 0 0: %s?", mark_sample(m2))
20733  end
20734  if mark_sync(m2) != 0
20735    snd_display("init mark_sync: %s?", mark_sync(m2))
20736  end
20737  set_mark_sync(m2, sync_val)
20738  if (res = mark_sync(m2)) != sync_val
20739    snd_display("set_mark_sync (%s): %s?", sync_val, res)
20740  end
20741  syncs = syncd_marks(sync_val)
20742  chans = marks(fd, 0)
20743  samps = chans.map do |chn| mark_sample(chn) end
20744  if syncs != [m2]
20745    snd_display("syncd_marks: %s?", syncs)
20746  end
20747  if chans != [m1, m2]
20748    snd_display("marks: %s?", chans)
20749  end
20750  if samps != [mark_sample(m1), mark_sample(m2)]
20751    snd_display("map samps: %s?", samps)
20752  end
20753  delete_samples(200, 100, fd, 0)
20754  chans = marks(fd)
20755  samps = chans.first.map do |chn| mark_sample(chn) end
20756  if samps != [mark_sample(m1, 0), mark_sample(m2, 0) - 100]
20757    snd_display("map samps: %s?", samps)
20758  end
20759  unless (res = describe_mark(m2)) == [[:mark, m2, :sound, fd, "oboe.snd", :channel, 0], 12345, 12245]
20760    snd_display("describe_mark: %s?", res)
20761  end
20762  set_mark_sync(m1, mark_sync(m2))
20763  move_syncd_marks(sync_val, 100)
20764  chans = marks(fd)
20765  samps = chans.first.map do |chn| mark_sample(chn) end
20766  if samps != [mark_sample(m1, 0) + 100, mark_sample(m2, 0)]
20767    snd_display("syncd move samps: %s?", samps)
20768  end
20769  set_cursor(500)
20770  set_mark_sync(m1, true)
20771  if mark_sync(m1) != 1
20772    snd_display("mark_sync via bool: %s?", mark_sync(m1))
20773  end
20774  delete_mark(m1)
20775  chans = marks(fd, 0)
20776  if chans != [m2]
20777    snd_display("delete_mark: %s?", chans)
20778  end
20779  undo_edit
20780  chans = marks(fd, 0)
20781  if chans != [m1, m2]
20782    snd_display("delete_mark then undo: %s?", chans)
20783  end
20784  redo_edit
20785  if mark_name(m2) != ""
20786    snd_display("init mark_name: %s?", mark_name(m2))
20787  end
20788  set_mark_name(m2, "hiho!")
20789  if mark_name(m2) != "hiho!"
20790    snd_display("set_mark_name: %s?", mark_name(m2))
20791  end
20792  undo_edit
20793  if mark_name(m2) != ""
20794    snd_display("undo mark_name: %s?", mark_name(m2))
20795  end
20796  redo_edit
20797  if mark_name(m2) != "hiho!"
20798    snd_display("redo mark_name: %s?", mark_name(m2))
20799  end
20800  #
20801  m3 = find_mark("hiho!")
20802  m4 = find_mark(mark_sample(m2))
20803  m5 = find_mark("not-a-mark")
20804  m6 = find_mark(123456787)
20805  m7 = mark_name2id("hiho!")
20806  if (not m2 == m3) or (not m4 == m7) or (not m2 == m4)
20807    snd_display("find_mark: %s %s %s %s?", m2, m3, m4, m7)
20808  end
20809  if (not m5 == m6) or m5 != false
20810    snd_display("find-not-a-mark: %s %s?", m5, m6)
20811  end
20812  set_mark_sample(m2, 2000)
20813  m1 = add_mark(1000)
20814  m3 = add_mark(3000)
20815  m4 = add_mark(4000)
20816  insert_samples(2500, 500, Vct.new(500), fd, 0)
20817  samps = (marks(fd, 0) or []).map do |m| mark_sample(m) end
20818  if samps != [1000, 2000, 3500, 4500]
20819    snd_display("insert ripple: %s?", samps)
20820  end
20821  set_mark_sample(m3, 300)
20822  set_cursor(500)
20823  sd = open_sound("4.aiff")
20824  m3 = add_mark(1000, sd, 2)
20825  m4 = add_mark(1000, sd, 3)
20826  unless mark_home(m3) == [sd, 2]
20827    snd_display("mark->sound 4: %s?", mark_home(m3))
20828  end
20829  close_sound(sd)
20830  file = save_marks(fd)
20831  if file != Dir.pwd + "/oboe.marks"
20832    snd_display("save_marks: %s?", file)
20833  end
20834  file = save_marks(fd, "hiho.marks")
20835  if file != "hiho.marks"
20836    snd_display("save_marks with arg: %s?", file)
20837  end
20838  unless shell("diff hiho.marks %s/oboe.marks", Dir.pwd)
20839    snd_display("save marks differs")
20840  end
20841  close_sound(fd)
20842  #
20843  s1 = open_sound("oboe.snd")
20844  s2 = open_sound("oboe.snd")
20845  add_mark(123, s1, 0)
20846  add_mark(321, s2, 0)
20847  set_with_verbose_cursor(true)
20848  delete_file("s61.rb")
20849  Snd.catch do save_state("s61.rb") end
20850  set_with_verbose_cursor(false)
20851  close_sound(s1)
20852  close_sound(s2)
20853  load("s61.rb")
20854  unless with_verbose_cursor
20855    snd_display("save_state with_verbose_cursor?")
20856  end
20857  s1 = find_sound("oboe.snd", 0)
20858  s2 = find_sound("oboe.snd", 1)
20859  if (not sound?(s1)) or (not sound?(s2))
20860    snd_display("cannot re-open sounds: %s %s?", s1, s2)
20861  else
20862    m1 = marks(s1)
20863    m2 = marks(s2)
20864    if m1.length != 1 or m2.length != 1 or m1.first.length != 1 or m2.first.length != 1
20865      snd_display("save_marks via save_state to: %s %s?", m1, m2)
20866    end
20867    samp1 = mark_sample(m1[0][0])
20868    samp2 = mark_sample(m2[0][0])
20869    if samp1 != 123 or samp2 != 321
20870      snd_display("save_marks via save_state positions: %s %s?", samp1, samp2)
20871    end
20872  end
20873  sound?(s1) and close_sound(s1)
20874  sound?(s2) and close_sound(s2)
20875  fd = open_sound("pistol.snd")
20876  if file = save_marks
20877    snd_display("save_marks no marks: %s?", file)
20878  end
20879  close_sound(fd)
20880  fd = open_sound("oboe.snd")
20881  load("oboe.marks")
20882  mlst = marks(fd, 0)
20883  if mlst.length != 4
20884    snd_display("restore oboe.marks: %s?", mlst.inspect)
20885  end
20886  close_sound(fd)
20887  fd = open_sound("oboe.snd")
20888  add_mark(1000)
20889  add_mark(2500)
20890  add_mark(framples - 4000)
20891  marks(fd, 0)
20892  src_sound(-0.5)
20893  unless (res1 = marks(fd, 0)) == (res2 = marks(fd, 0, 0).reverse)
20894    snd_display("src rev marks: %s %s?", res1.inspect, res2.inspect)
20895  end
20896  unless (res = (marks(fd, 0) or []).map do |m| mark_sample(m) end) == [7998, 96654, 99654]
20897    snd_display("src rev mark locs: %s?", res)
20898  end
20899  close_sound(fd)
20900  fd = open_sound("4.aiff")
20901  add_mark(1000, fd, 0)
20902  add_mark(2000, fd, 1)
20903  add_mark(3000, fd, 2)
20904  add_mark(4000, fd, 3)
20905  if marks.length.zero?
20906    snd_display("marks (no args): %s?", marks)
20907  end
20908  save_marks(fd)
20909  close_sound(fd)
20910  fd = open_sound("4.aiff")
20911  load("4.marks")
20912  delete_file("4.marks")
20913  (marks(fd) or []).each_with_index do |mlst, i|
20914    if mlst.length != 1
20915      snd_display("save_marks[%s]: %s?", i, mlst)
20916    end
20917    if (res = mark_sample(mlst.first)) != (i + 1) * 1000
20918      snd_display("save_marks[%s] at %s?", i, res)
20919    end
20920  end
20921  close_sound(fd)
20922end
20923
20924def test_10_02
20925  ind = open_sound("pistol.snd")
20926  samp1 = 1834
20927  samp2 = 8345
20928  m1 = add_mark(samp1, ind, 0)
20929  m2 = add_mark(samp2)
20930  set_mark_sync(m1, 123)
20931  set_mark_sync(m2, 100)
20932  if (res = mark_sync_max()) != 123
20933    snd_display("mark_sync_max: %s?", res)
20934  end
20935  src_sound(-1.0)
20936  if mark_sample(m1) != 39788
20937    snd_display("src -1 m1: %s?", mark_sample(m1))
20938  end
20939  if mark_sample(m2) != 33277
20940    snd_display("src -1 m2: %s?", mark_sample(m2))
20941  end
20942  undo_edit
20943  src_sound(0.5)
20944  if mark_sample(m1) != 2 * samp1
20945    snd_display("src 0.5 m1: %s?", mark_sample(m1))
20946  end
20947  if mark_sample(m2) != 2 * samp2
20948    snd_display("src 0.5 m2: %s?", mark_sample(m2))
20949  end
20950  undo_edit
20951  delete_samples(1000, 100)
20952  if mark_sample(m1) != samp1 - 100
20953    snd_display("delete_samples 100 m1: %s?", mark_sample(m1))
20954  end
20955  insert_silence(1000, 100)
20956  if mark_sample(m1) != samp1
20957    snd_display("insert_silence 100 m1: %s?", mark_sample(m1))
20958  end
20959  revert_sound(ind)
20960  delete_samples(2000, 100)
20961  if mark_sample(m1) != samp1
20962    snd_display("delete_samples (2) 100 m1: %s?", mark_sample(m1))
20963  end
20964  if mark_sample(m2) != samp2 - 100
20965    snd_display("delete_samples (2) 100 m2: %s?", mark_sample(m2))
20966  end
20967  insert_silence(2000, 100)
20968  if mark_sample(m1) != samp1
20969    snd_display("insert_silence (2) 100 m1: %s?", mark_sample(m1))
20970  end
20971  if mark_sample(m2) != samp2
20972    snd_display("insert_silence (2) 100 m2: %s?", mark_sample(m2))
20973  end
20974  revert_sound(ind)
20975  delete_samples(10000, 100)
20976  if mark_sample(m1) != samp1
20977    snd_display("delete_samples (3) 100 m1: %s?", mark_sample(m1))
20978  end
20979  if mark_sample(m2) != samp2
20980    snd_display("delete_samples (3) 100 m2: %s?", mark_sample(m2))
20981  end
20982  insert_silence(10000, 100)
20983  if mark_sample(m1) != samp1
20984    snd_display("insert_silence (3) 100 m1: %s?", mark_sample(m1))
20985  end
20986  if mark_sample(m2) != samp2
20987    snd_display("insert_silence (3) 100 m2: %s?", mark_sample(m2))
20988  end
20989  src_sound([0, 0.5, 1, 0.5, 2, 1])
20990  if mark_sample(m1) != 2 * samp1
20991    snd_display("src env 0.5 m1: %s?", mark_sample(m1))
20992  end
20993  if mark_sample(m2) != 2 * samp2
20994    snd_display("src env 0.5 m2: %s?", mark_sample(m2))
20995  end
20996  undo_edit
20997  reverse_sound
20998  if mark_sample(m1) != 39788
20999    snd_display("reverse_sound m1: %s?", mark_sample(m1))
21000  end
21001  if mark_sample(m2) != 33277
21002    snd_display("reverse_sound m2: %s?", mark_sample(m2))
21003  end
21004  undo_edit
21005  src_sound([0, -0.5, 1, -0.5, 2, -1])
21006  if mark_sample(m1) != 68598
21007    snd_display("src -env m1: %s?", mark_sample(m1))
21008  end
21009  if mark_sample(m2) != 61160
21010    snd_display("src -env m2: %s?", mark_sample(m2))
21011  end
21012  revert_sound(ind)
21013  #
21014  src_channel(make_env(:envelope, [0, 0.5, 1, 1], :length, 8001), 2000, 10000)
21015  if mark_sample(m1) != samp1
21016    snd_display("src_channel (1) m1: %s?", mark_sample(m1))
21017  end
21018  if mark_sample(m2) != 11345
21019    snd_display("src_channel (1) m2: %s?", mark_sample(m2))
21020  end
21021  undo_edit
21022  src_channel(make_env(:envelope, [0, 0.5, 1, 1], :length, 8001), 0, 8000)
21023  if mark_sample(m1) != 3303
21024    snd_display("src_channel (2) m1: %s?", mark_sample(m1))
21025  end
21026  if mark_sample(m2) != samp2
21027    snd_display("src_channel (2) m2: %s?", mark_sample(m2))
21028  end
21029  undo_edit
21030  src_channel(make_env(:envelope, [0, 0.5, 1, 1], :length, 8001), 10000, 8000)
21031  if mark_sample(m1) != samp1
21032    snd_display("src_channel (3) m1: %s?", mark_sample(m1))
21033  end
21034  if mark_sample(m2) != samp2
21035    snd_display("src_channel (3) m2: %s?", mark_sample(m2))
21036  end
21037  close_sound(ind)
21038  #
21039  ind = open_sound("2.snd")
21040  set_sync(true, ind)
21041  m3 = add_mark(1000, ind, 0)
21042  m4 = add_mark(8000, ind, 1)
21043  swap_channels
21044  if (not (res1 = mark_home(m3)) == [ind, 1]) or (not (res2 = mark_home(m4)) == [ind, 0])
21045    snd_display("swapped mark homes: %s %s?", res1, res2)
21046  end
21047  if (res1 = mark_sample(m3)) != 1000 or (res2 = mark_sample(m4)) != 8000
21048    snd_display("swapped mark samples: %s %s?", res1, res2)
21049  end
21050  close_sound(ind)
21051  #
21052  ind = open_sound("2.snd")
21053  set_sync(true, ind)
21054  m3 = add_mark(1000, ind, 0)
21055  delete_samples(1000, 10, ind, 1)
21056  swap_channels
21057  unless (res = mark_home(m3)) == [ind, 1]
21058    snd_display("edited swapped mark home: %s?", res)
21059  end
21060  if (res = mark_sample(m3)) != 1000
21061    snd_display("edited swapped mark sample: %s?", res)
21062  end
21063  delete_marks
21064  close_sound(ind)
21065  #
21066  ind = open_sound("oboe.snd")
21067  m1 = add_mark(123, ind, 0)
21068  m2 = add_mark(234, ind, 0)
21069  define_selection_via_marks(m1, m2)
21070  if (not selection?)
21071    snd_display("define_selection_via_marks failed?")
21072  else
21073    mc = selection_members
21074    unless mc == [[ind, 0]]
21075      snd_display("selection_members after mark def: %s [[%s, 0]]", mc, ind)
21076    end
21077    if selection_position != 123
21078      snd_display("selection_position 123: %s?", selection_position)
21079    end
21080    if selection_framples != 112
21081      snd_display("selection_framples 112: %s?", selection_framples)
21082    end
21083  end
21084  m1 = add_mark(1000, ind, 0)
21085  m2 = add_mark(2000, ind, 0)
21086  define_selection_via_marks(m1, m2)
21087  if (not selection?)
21088    snd_display("define_selection_via_marks repeat failed?")
21089  else
21090    mc = selection_members
21091    unless mc == [[ind, 0]]
21092      snd_display("selection_members after 2nd mark def: %s [[%s, 0]]", mc, ind)
21093    end
21094    if selection_position != 1000
21095      snd_display("selection_position 1000: %s?", selection_position)
21096    end
21097    if selection_framples != 1001
21098      snd_display("selection_framples 1001: %s?", selection_framples)
21099    end
21100  end
21101  set_selection_member?(false, true)
21102  if selection?
21103    snd_display("cannot clear selection via selection_members?")
21104  end
21105  set_selection_member?(true, ind, 0)
21106  set_selection_position(2000, ind, 0)
21107  set_selection_framples(1234, ind, 0)
21108  snap_marks
21109  unless mark?(m1 = find_mark(2000, ind, 0))
21110    snd_display("snap_marks start: %s?", Snd.marks(ind, 0).map do |m| mark_sample(m) end)
21111  end
21112  unless mark?(m2 = find_mark(2000 + 1234, ind, 0))
21113    snd_display("snap_marks end: %s?", Snd.marks(ind, 0).map do |m| mark_sample(m) end)
21114  end
21115  set_selection_position(framples(ind, 0) + 1234, ind, 0)
21116  if (res = selection_position(ind, 0)) != framples(ind) - 1
21117    snd_display("selection_position past eof: %s %s?", res, framples(ind) - 1)
21118  end
21119  revert_sound(ind)
21120  src_sound([0, 0.5, 1, 1.75665])
21121  # trying to hit previous dur on the nose "by accident..."
21122  # try to hit mark_size segfault
21123  as_one_edit(lambda do | |
21124                add_mark(10)
21125                mix("oboe.snd")
21126                20.times do |i|
21127                  scale_channel(1.2)
21128                  add_mark(i * 2)
21129                end
21130              end)
21131  scale_channel(0.5)
21132  close_sound(ind)
21133  #
21134  ind = open_sound("oboe.snd")
21135  100.times do |i|
21136    current_marks = Snd.marks(ind, 0)
21137    current_samples = []
21138    if current_marks and (not current_marks.empty?)
21139      current_samples = current_marks.map do |m| mark_sample(m) end
21140      id = current_marks[random(current_marks.length - 1)]
21141      unless find_mark(mark_sample(id)).eql?(id)
21142        snd_display("two marks at %s: %s?",
21143                    mark_sample(id), current_marks.map do |m| mark_sample(m) end)
21144      end
21145      if res = find_mark("not-a-mark")
21146        snd_display("find-bogus-mark: %s?", res)
21147      end
21148    end
21149    case random(15)
21150    when 0
21151      beg = random(framples)
21152      dur = [1, random(100)].max
21153      insert_silence(beg, dur)
21154      if current_marks and (not current_marks.empty?)
21155        current_marks.zip(current_samples) do |id, old_loc|
21156          if old_loc > beg
21157            if mark?(id)
21158              if (res = mark_sample(id)) != old_loc + dur
21159                snd_display("insert, mark %s %s -> %s (%s)?", id, old_loc, res, dur)
21160              end
21161            else
21162              snd_display("insert clobbered mark: %s?", id)
21163            end
21164          end
21165        end
21166      end
21167    when 1
21168      if edits(ind, 0)[0] > 0
21169        undo_edit
21170      end
21171    when 2
21172      if edits(ind, 0)[1] > 0
21173        redo_edit
21174      end
21175    when 3
21176      scale_channel((maxamp(ind, 0) > 0.1) ? 0.5 : 2.0)
21177      unless (res = Snd.marks(ind, 0)) == current_marks
21178        snd_display("scaling changed marks: %s %s?", res, current_marks)
21179      end
21180      unless (res = Snd.marks(ind, 0).map do |m| mark_sample(m) end) == current_samples
21181        snd_display("scaling changed mark locations: %s %s?", res, current_samples)
21182      end
21183    when 4
21184      set_sample(random(framples - 1), 0.5)
21185      unless (res = Snd.marks(ind, 0)) == current_marks
21186        snd_display("set_sample changed marks: %s %s?", res, current_marks)
21187      end
21188      unless (res = Snd.marks(ind, 0).map do |m| mark_sample(m) end) == current_samples
21189        snd_display("set_sample changed mark location: %s %s?", res, current_samples)
21190      end
21191    when 5
21192      beg = random(framples)
21193      dur = [1, random(100)].max
21194      len = beg + dur
21195      delete_samples(beg, dur)
21196      if current_marks and (not current_marks.empty?)
21197        current_marks.zip(current_samples) do |id, old_loc|
21198          if old_loc > beg and old_loc < len and mark?(id)
21199            snd_display("delete did not clobber mark: %s %s [%s, %s]?", id, old_loc, beg, dur)
21200          else
21201            if old_loc > len and (res = mark_sample(id)) != old_loc - dur
21202              snd_display("delete ripple mark, mark %s %s -> %s (%s)?", id, old_loc, res, dur)
21203            else
21204              if old_loc < beg and (res = mark_sample(id)) != old_loc
21205                snd_display("delete but mark before: %s %s %s %s?", id, old_loc, res, dur)
21206              end
21207            end
21208          end
21209        end
21210      end
21211    when 6
21212      revert_sound
21213    when 7
21214      if current_marks and current_marks.length > 1
21215        id = current_marks[random(current_marks.length - 1)]
21216        delete_mark(id)
21217        if mark?(id)
21218          snd_display("delete_mark failed: %s?", id)
21219        end
21220        if (res = marks(ind, 0)).length != current_marks.length - 1
21221          snd_display("delete_mark list trouble: %s %s %s?", id, current_marks, res)
21222        end
21223      end
21224    when 8
21225      rate = (framples > 200000) ? 2.0 : 0.5
21226      src_channel(rate)
21227      if current_marks and (not current_marks.empty?)
21228        current_marks.zip(current_samples) do |id, old_loc|
21229          unless mark?(id)
21230            snd_display("src_channel clobbered mark: %s?", id)
21231          else
21232            if ((old_loc / rate) - (res = mark_sample(id))).abs > 2
21233              snd_display("src_channel moved mark: %s?", id)
21234            end
21235          end
21236        end
21237      end
21238    when 9
21239      reverse_channel
21240      if current_marks and (not current_marks.empty?)
21241        current_marks.zip(current_samples) do |id, old_loc|
21242          unless mark?(id)
21243            snd_display("reverse_channel clobbered mark: %s?", id)
21244          else
21245            if ((framples - old_loc) - (res = mark_sample(id))).abs > 2
21246              snd_display("reverse_channel moved mark: %s %s %s (%s)?",
21247                          id, old_loc, framples - old_loc, res)
21248            end
21249          end
21250        end
21251      end
21252    else
21253      add_mark(random(framples - 1))
21254    end
21255  end
21256  close_sound(ind)
21257  #
21258  defined?(mark_sync_color) and $with_test_motif and mark_sync_color("blue")
21259  ind = open_sound("oboe.snd")
21260  m0 = add_mark(4321)
21261  delete_sample(100)
21262  m1 = add_mark(1234)
21263  val0 = describe_mark(m0)
21264  val1 = describe_mark(m1)
21265  if mark2integer(val0[0][1]) != mark2integer(m0) or
21266      val0[0][3] != ind or
21267      val0[0][6] != 0 or
21268      val0[1] != 4321 or
21269      val0[2] != 4320
21270    snd_display("describe_mark m0: %s?", val0)
21271  end
21272  if mark2integer(val1[0][1]) != mark2integer(m1) or
21273      val1[0][3] != ind or
21274      val1[0][6] != 0 or
21275      val1[1] != false or
21276      val1[2] != 1234
21277    snd_display("describe_mark m1: %s?", val1)
21278  end
21279  delete_mark(m0)
21280  delete_sample(5000)
21281  val0 = describe_mark(m0)
21282  val1 = describe_mark(m1)
21283  if mark2integer(val0[0][1]) != mark2integer(m0) or
21284      val0[0][3] != ind or
21285      val0[0][6] != 0 or
21286      val0[1] != 4321 or
21287      val0[2] != false or
21288      val0[3] != false
21289    snd_display("describe_mark m0 (1): %s?", val0)
21290  end
21291  if mark2integer(val1[0][1]) != mark2integer(m1) or
21292      val1[0][3] != ind or
21293      val1[0][6] != 0 or
21294      val1[1] != false or
21295      val1[2] != 1234 or
21296      val1[3] != 1234
21297    snd_display("describe_mark m1 (1): %s?", val1)
21298  end
21299  revert_sound(ind)
21300  $draw_mark_hook.add_hook!("snd-test") do |id| true end
21301  m0 = add_mark(4321)
21302  m1 = add_mark(1234)
21303  dur = framples(ind) / srate(ind).to_f
21304  pad_marks([m0, m1], 0.01)
21305  if fneq(res = framples(ind) / srate(ind).to_f, dur + 0.02)
21306    snd_display("pad_marks: %s %s?", dur, res)
21307  end
21308  if mark_sample(m0) != 4763 and mark_sample(m0) != 4761
21309    snd_display("pad_marks m0 pos: %s", mark_sample(m0))
21310  end
21311  if fneq(res = sample(1235), 0.0)
21312    snd_display("pad_marks 1235: %s?", res)
21313  end
21314  close_sound(ind)
21315  $draw_mark_hook.reset_hook!
21316  #
21317  ind = open_sound("oboe.snd")
21318  if res = find_mark(12345)
21319    snd_display("find_mark when no marks: %s?", res)
21320  end
21321  add_mark(123, ind, 0)
21322  delete_sample(0)
21323  m1 = add_mark(23, ind, 0)
21324  set_mark_name(m1, "23")
21325  delete_sample(0)
21326  unless find_mark(123, ind, 0, 0)
21327    snd_display("cannot find 00th mark")
21328  end
21329  unless find_mark("23")
21330    snd_display("cannot find 01th mark")
21331  end
21332  unless find_mark(121)
21333    snd_display("cannot find 02th mark")
21334  end
21335  delete_mark(find_mark("23"))
21336  scale_by(2.0)
21337  m1 = add_mark(1234)
21338  set_mark_name(m1, "23")
21339  if (m10 = find_mark("23"))
21340    if (res = mark_sample(m10)) != 1234
21341      snd_display("mark 10th: %s?", res)
21342    end
21343  else
21344    snd_display("cannot find 10th mark?")
21345  end
21346  if (m11 = find_mark("23", ind, 0, 1))
21347    if (res = mark_sample(m11, 1)) != 23
21348      snd_display("mark 11th: %s?", res)
21349    end
21350  else
21351    snd_display("cannot find 11th mark?")
21352  end
21353  if (m12 = find_mark("23", ind, 0, 2))
21354    snd_display("found 12th mark: %s %s %s?", m12, mark_sample(m12, 2), mark_name(m12))
21355  end
21356  set_mark_name(m1, false)
21357  close_sound(ind)
21358  #
21359  ind = open_sound("oboe.snd")
21360  add_mark(123)
21361  add_mark(234, ind, 0, "hiho", 1)
21362  add_mark(345, ind, 0, false, 1)
21363  add_mark(456, ind, 0, "a mark", 2)
21364  add_mark(567, ind, 0, false, 1)
21365  save_marks(ind, "oboe.marks")
21366  close_sound(ind)
21367  ind = open_sound("oboe.snd")
21368  add_mark(1, ind, 0, "new mark", 1)
21369  load("oboe.marks")
21370  if mark?(m = find_mark(123, ind, 0))
21371    if mark_name(m).length.nonzero?
21372      snd_display("saved mark 123 name: %s?", mark_name(m))
21373    end
21374    if mark_sync(m).nonzero?
21375      snd_display("saved mark 123 sync: %s?", mark_sync(m))
21376    end
21377  else
21378    snd_display("saved marks missed 123: %s?", m.inspect)
21379  end
21380  m1_sync = 0
21381  if mark?(m = find_mark(234, ind, 0))
21382    if mark_name(m) != "hiho"
21383      snd_display("saved mark 234 name: %?", mark_name(m))
21384    end
21385    if mark_sync(m) == 0 or mark_sync(m) == 1
21386      snd_display("saved mark 234 sync: %s?", mark_sync(m))
21387    end
21388    m1_sync = mark_sync(m)
21389  else
21390    snd_display("saved marks missed 234: %s?", m.inspect)
21391  end
21392  if mark?(m = find_mark(345, ind, 0))
21393    if mark_name(m).length.nonzero?
21394      snd_display("saved mark 345 name: %?", mark_name(m))
21395    end
21396    if mark_sync(m) != m1_sync
21397      snd_display("saved mark 345 sync: %s %s?", mark_sync(m), m1_sync)
21398    end
21399  else
21400    snd_display("saved marks missed 345: %s?", m.inspect)
21401  end
21402  if mark?(m = find_mark(456, ind, 0))
21403    if mark_name(m) != "a mark"
21404      snd_display("saved mark 456 name: %?", mark_name(m))
21405    end
21406    if mark_sync(m) == m1_sync or
21407        mark_sync(m) == 0 or
21408        mark_sync(m) == 1
21409      snd_display("saved mark 456 sync: %s %s?", mark_sync(m), m1_sync)
21410    end
21411  else
21412    snd_display("saved marks missed 456: %s?", m.inspect)
21413  end
21414  if mark?(m = find_mark(567, ind, 0))
21415    if mark_name(m).length.nonzero?
21416      snd_display("saved mark 567 name: %?", mark_name(m))
21417    end
21418    if mark_sync(m) != m1_sync
21419      snd_display("saved mark 567 sync: %s %s?", mark_sync(m), m1_sync)
21420    end
21421  else
21422    snd_display("saved marks missed 567: %s?", m.inspect)
21423  end
21424  delete_file("oboe.marks")
21425  #
21426  ind1 = open_sound("2a.snd")
21427  add_mark(1, ind1, 0)
21428  add_mark(2, ind1, 1)
21429  add_mark(3, ind1, 0, "hi3")
21430  add_mark(6, ind1, 1, "hi6")
21431  add_mark(4, ind1, 0, false, 4)
21432  add_mark(8, ind1, 1, false, 5)
21433  add_mark(5, ind1, 0, false, 9)
21434  add_mark(10, ind1, 1, false, 9)
21435  add_mark(20, ind1, 0, false, 12)
21436  add_mark(40, ind1, 1, false, 12)
21437  add_mark(60, ind1, 1, false, 12)
21438  save_marks(ind1, "test.marks")
21439  close_sound(ind)
21440  close_sound(ind1)
21441  #
21442  ind = open_sound("2a.snd")
21443  load("test.marks")
21444  m1 = find_mark(1, ind, 0)
21445  m2 = find_mark(2, ind, 1)
21446  if mark?(m1) and mark?(m2)
21447    if mark_sync(m1).nonzero? or mark_sync(m2).nonzero?
21448      snd_display("save_marks 2a 1, 2 syncs: %s %s?", mark_sync(m1), mark_sync(m2))
21449    end
21450  else
21451    snd_display("save_marks 2a 1, 2: %s %s?", m1.inspect, m2.inspect)
21452  end
21453  m1 = find_mark(5, ind, 0)
21454  m2 = find_mark(10, ind, 1)
21455  if mark?(m1) and mark?(m2)
21456    if mark_sync(m1).zero? or mark_sync(m1) != mark_sync(m2)
21457      snd_display("save_marks 2a 5, 10 syncs: %s %s?", mark_sync(m1), mark_sync(m2))
21458    end
21459  else
21460    snd_display("save_marks 2a 5, 10: %s %s?", m1.inspect, m2.inspect)
21461  end
21462  m1 = find_mark(4, ind, 0)
21463  m2 = find_mark(8, ind, 1)
21464  m3 = find_mark(5, ind, 0)
21465  if mark?(m1) and mark?(m2)
21466    if mark_sync(m1).zero? or
21467        mark_sync(m2).zero? or
21468        mark_sync(m1) == mark_sync(m2) or
21469        mark_sync(m1) == mark_sync(m3)
21470      snd_display("save_marks 2a 4, 8 syncs: %s %s?", mark_sync(m1), mark_sync(m2), mark_sync(m3))
21471    end
21472  else
21473    snd_display("save_marks 2a 4, 8: %s %s?", m1.inspect, m2.inspect)
21474  end
21475  m1 = find_mark(3, ind, 0)
21476  m2 = find_mark(6, ind, 1)
21477  if mark?(m1) and mark?(m2)
21478    if mark_sync(m1).nonzero? or mark_sync(m2).nonzero?
21479      snd_display("save_marks 2a 3, 6 syncs: %s %s?", mark_sync(m1), mark_sync(m2))
21480    end
21481    if mark_name(m1) != "hi3"
21482      snd_display("save_marks 2a 3 name: %s?", mark_name(m1))
21483    end
21484    if mark_name(m2) != "hi6"
21485      snd_display("save_marks 2a 6 name: %s?", mark_name(m1))
21486    end
21487  else
21488    snd_display("save_marks 2a 3, 6: %s %s?", m1.inspect, m2.inspect)
21489  end
21490  m1 = find_mark(4, ind, 0)
21491  m2 = find_mark(5, ind, 0)
21492  m3 = find_mark(20, ind, 0)
21493  m4 = find_mark(40, ind, 1)
21494  m5 = find_mark(60, ind, 1)
21495  if mark?(m3) and mark?(m4) and mark?(m5)
21496    if mark_sync(m3).zero? or
21497        (m1 and mark_sync(m1) == mark_sync(m3)) or
21498        (m2 and mark_sync(m2) == mark_sync(m3)) or
21499        mark_sync(m3) != mark_sync(m4) or
21500        mark_sync(m3) != mark_sync(m5)
21501      snd_display("save_marks 2a 20... syncs: %s %s %s?",
21502                  mark_sync(m3),mark_sync(m4), mark_sync(m5))
21503    end
21504  else
21505    snd_display("save_marks 2a 20...: %s %s %s?",
21506                m3.inspect, m4.inspect, m5.inspect)
21507  end
21508  delete_file("test.marks")
21509  close_sound(ind)
21510  #
21511  ind = new_sound(:size, 1000)
21512  add_mark(123)
21513  add_mark(234, ind, 0, "hiho", 1)
21514  add_mark(345, ind, 0, false, 1)
21515  add_mark(456, ind, 0, "a mark", 2)
21516  add_mark(567, ind, 0, false, 1)
21517  $output_comment_hook.add_hook!("mark2string") do |str|
21518    marks2string(selected_sound)
21519  end
21520  save_sound_as("tst.snd")
21521  new_file_name = file_name(ind)
21522  close_sound(ind)
21523  delete_file(new_file_name)
21524  ind = open_sound("tst.snd")
21525  $output_comment_hook.reset_hook!
21526  if string?(str = comment(ind))
21527    Snd.catch do eval(str, TOPLEVEL_BINDING, "(eval-header)", 1) end
21528  end
21529  if (ms = marks(ind, 0)).nil?
21530    ms = []
21531  end
21532  if ms.length != 5
21533    snd_display("eval_header + marks2string: %s?", ms.inspect)
21534  end
21535  samps = ms.apply(:mark_sample)
21536  if (not samps.member?(123)) or (not samps.member?(567))
21537    snd_display("eval marked header samps: %s?", samps.inspect)
21538  end
21539  unless find_mark(234)
21540    snd_display("eval mark header no mark at 234?")
21541  end
21542  if mr = find_mark(456)
21543    if (res = mark_sync(mr)) != 2
21544      snd_display("eval mark header sync: %s?", res)
21545    end
21546  else
21547    snd_display("saved marks missed 456: %s?", mr)
21548  end
21549  close_sound(ind)
21550  mus_sound_forget("tst.snd")
21551  delete_file("tst.snd")
21552  # mark_explode
21553  ind = new_sound(:size, 31)
21554  ctr = -1
21555  map_channel(lambda do |y|
21556                ctr += 1
21557                if ctr < 10
21558                  0.1
21559                elsif ctr < 20
21560                  0.4
21561                else
21562                  0.8
21563                end
21564              end)
21565  add_mark(10)
21566  add_mark(20)
21567  add_mark(30)
21568  mark_explode
21569  if File.exist?("mark-0.snd")
21570    ind1 = open_sound("mark-0.snd")
21571    if framples(ind1, 0) != 10
21572      snd_display("mark-0 framples: %s?", framples(ind1, 0))
21573    end
21574    unless vequal(res = channel2vct, Vct.new(10, 0.1))
21575      snd_display("mark-0 vals: %s?", res)
21576    end
21577    close_sound(ind1)
21578    delete_file("mark-0.snd")
21579  else
21580    snd_display("mark_explode did not write mark-0.snd?")
21581  end
21582  if File.exist?("mark-1.snd")
21583    ind1 = open_sound("mark-1.snd")
21584    if framples(ind1, 0) != 10
21585      snd_display("mark-1 framples: %s?", framples(ind1, 0))
21586    end
21587    unless vequal(res = channel2vct, Vct.new(10, 0.4))
21588      snd_display("mark-1 vals: %s?", res)
21589    end
21590    close_sound(ind1)
21591    delete_file("mark-1.snd")
21592  else
21593    snd_display("mark_explode did not write mark-1.snd?")
21594  end
21595  if File.exist?("mark-2.snd")
21596    ind1 = open_sound("mark-2.snd")
21597    if framples(ind1, 0) != 10
21598      snd_display("mark-2 framples: %s?", framples(ind1, 0))
21599    end
21600    unless vequal(res = channel2vct, Vct.new(10, 0.8))
21601      snd_display("mark-2 vals: %s?", res)
21602    end
21603    close_sound(ind1)
21604    delete_file("mark-2.snd")
21605  else
21606    snd_display("mark_explode did not write mark-2.snd?")
21607  end
21608  if File.exist?("mark-3.snd")
21609    snd_display("mark_explode wrote too many files?")
21610    delete_file("mark-3.snd")
21611  end
21612  name = file_name(ind)
21613  close_sound(ind)
21614  delete_file(name)
21615end
21616
21617def test_10
21618  test_10_00
21619  test_10_01 if $with_test_gui # load("s61.rb") -> set_transform_size(0)
21620  test_10_02
21621end
21622
21623# ---------------- test 11: dialogs ----------------
21624
21625def string_equal_ignore_white_space(s1, s2)
21626  s1 == s2 or s1.delete(":()-_, \n") == s2.delete(":()-_, \n")
21627end
21628
21629define_envelope("env4", [0, 1, 1, 0]) # defines $env4
21630
21631def test_11
21632  if $with_test_gui
21633    Snd.catch do peaks() end
21634    enved_dialog
21635    color_orientation_dialog
21636    transform_dialog
21637    view_regions_dialog
21638    Snd.catch do edit_header_dialog() end
21639    open_file_dialog(false)
21640    mix_file_dialog(false)
21641    insert_file_dialog(false)
21642    help_dialog("Test", "snd-test here")
21643    save_envelopes("hiho.env")
21644    load("hiho.env")
21645    if $env4 != [0.0, 1.0, 1.0, 0.0]
21646      snd_display("save_envelopes: %s?", $env4)
21647    end
21648    delete_file("hiho.env")
21649    help_dialog("test2", "this is the next test",
21650                ["string 1{open-sound}", "{env-sound}string2", "string{close-sound}3"],
21651                ["extsnd.html#sndopen", "extsnd.html#sndenv", "extsnd.html#sndclose"])
21652    dismiss_all_dialogs
21653    #
21654    ind = open_sound("oboe.snd")
21655    edit_header_dialog(ind)
21656    dismiss_all_dialogs
21657    close_sound(ind)
21658    #
21659    if (res = snd_url(:open_sound)) != "extsnd.html#opensound"
21660      snd_display("snd_url :open_sound: %s?", res.inspect)
21661    end
21662    if (res = snd_url("open_sound")) != "extsnd.html#opensound"
21663      snd_display("snd_url \"open_sound\": %s?", res.inspect)
21664    end
21665    unless array?(res = snd_urls)
21666      snd_display("snd_urls: %s?", res.inspect)
21667    end
21668    # XXX: snd_help(:open_sound) => "keyword"
21669    # str2 = snd_help(:open_sound) => "keyword"
21670    str2 = snd_help(:open_sound.to_s)
21671    str3 = snd_help("open_sound")
21672    unless string_equal_ignore_white_space(str2, str3)
21673      snd_display("snd_help open_sound: expected %s, got %s?", str2, str3)
21674    end
21675    str1 = "(enved-base): envelope editor exponential base value (1.0)"
21676    str2 = snd_help(:enved_base.to_s)
21677    str3 = snd_help("enved_base")
21678    unless string_equal_ignore_white_space(str1, str2)
21679      snd_display("snd_help :enved_base: expected %s, got %s", str1, str2)
21680    end
21681    unless string_equal_ignore_white_space(str1, str3)
21682      snd_display("snd_help \"enved_base\": expected %s, got %s", str1, str3)
21683    end
21684    old_val = Hamming_window
21685    str1 = snd_help(:Hamming_window.to_s)
21686    str2 = snd_help("Hamming_window")
21687    if (not string_equal_ignore_white_space(str1, str2)) or
21688       (not string_equal_ignore_white_space(str1, "A raised cosine"))
21689      snd_display("snd_help Hamming_window: expected %s, got %s?", str1, str2)
21690    end
21691    if (not number?(Hamming_window)) or Hamming_window != old_val
21692      snd_display("snd_help clobbered out-of-module variable: %s %s?", old_val, Hamming_window)
21693    end
21694    #
21695    urls = snd_urls[0...25]
21696    urls.each do |fnc, url|
21697      if function?(fnc)
21698        snd_help(fnc, false)
21699      end
21700    end
21701    urls.each do |fnc, url|
21702      if function?(fnc)
21703        help_dialog(fnc, snd_help(fnc, false))
21704      end
21705    end
21706    set_show_indices(false)
21707    #
21708    define_envelope("test_ramp", [0, 0, 1, 1])
21709    if $test_ramp != [0, 0, 1, 1]
21710      snd_display("define_envelope $test_ramp: %s?", $test_ramp)
21711    end
21712    define_envelope("test_ramp", [0, 1, 1, 0])
21713    if $test_ramp != [0, 1, 1, 0]
21714      snd_display("re-define-envelope $test_ramp: %s?", $test_ramp)
21715    end
21716  end
21717end
21718
21719# ---------------- test 12: extensions ----------------
21720
21721def spectral_difference(snd1, snd2)
21722  size = [framples(snd1), framples(snd2)].max
21723  pow2 = (log(size) / log(2)).ceil
21724  fftlen = (2.0 ** pow2).to_i
21725  fdr1 = channel2vct(0, fftlen, snd1, 0)
21726  fdr2 = channel2vct(0, fftlen, snd2, 0)
21727  spectr1 = snd_spectrum(fdr1, Blackman2_window, fftlen, true)
21728  spectr2 = snd_spectrum(fdr2, Blackman2_window, fftlen, true)
21729  diff = 0.0
21730  diffs = spectr1.subtract(spectr2)
21731  diffs.each do |d| diff += d.abs end
21732  diff
21733end
21734
21735def test_spectral_difference(snd1, snd2, maxok)
21736  s1 = open_sound(snd1)
21737  s2 = open_sound(snd2)
21738  if (not sound?(s1)) or (not sound?(s2))
21739    snd_display_prev_caller("open_sound %s or %s failed?", snd1, snd2)
21740  end
21741  diff = spectral_difference(s1, s2)
21742  close_sound(s1)
21743  close_sound(s2)
21744  if diff > maxok
21745    snd_display_prev_caller("translate spectral difference %s %s: %s > %s?",
21746                            snd1, snd2, diff, maxok)
21747  end
21748end
21749
21750def test_12
21751  if $with_test_gui
21752    sf_dir_files = []
21753    if string?($sf_dir)
21754      sound_files_in_directory($sf_dir).each do |file|
21755        dir = $sf_dir + file
21756        #Snd.catch(:mus_error) do
21757        Snd.catch do
21758          mus_sound_chans(dir).between?(1, 255) and
21759            mus_sound_sample_type(dir) >= 0 and
21760            mus_sound_srate(dir) > 0 and
21761            mus_sound_framples(dir) >= 0 and
21762            sf_dir_files.push(dir)
21763        end
21764      end
21765    end
21766    if sound_file_extensions.null?
21767      set_sound_file_extensions($original_sound_file_extensions)
21768    end
21769    open_files = []
21770    open_ctr = 0
21771    add_sound_file_extension("wave")
21772    unless (exts = sound_file_extensions).member?("wave")
21773      snd_display("sound_file_extensions: %s?", exts)
21774    end
21775    set_sound_file_extensions([])
21776    unless (res = sound_file_extensions).nil?
21777      snd_display("sound_file_extensions set []: %s?", res)
21778    end
21779    set_sound_file_extensions(exts)
21780    unless (res = sound_file_extensions).member?("wave")
21781      snd_display("sound_file_extensions reset: %s?", res)
21782    end
21783    until open_ctr == 32
21784      len = open_files.length
21785      open_chance = (8 - len) * 0.125
21786      close_chance = len * 0.125
21787      if len.zero? or random(1.0) > 0.5
21788        name = sf_dir_files[random(sf_dir_files.length).floor]
21789        ht = Snd.catch(:all, 0) do mus_sound_header_type(name) end.first
21790        df = Snd.catch(:all, 0) do mus_sound_sample_type(name) end.first
21791        fd = if ht == Mus_raw or
21792                ht == Mus_unknown_header or
21793                df == Mus_unknown_sample
21794               -1
21795             else
21796               Snd.catch(:all, -1) do view_sound(name) end.first or -1
21797             end
21798        if fd != -1
21799          open_ctr += 1
21800          open_files.push(fd)
21801        end
21802      else
21803        if len > 0 and random(1.0) > 0.3
21804          if sound?(fd = open_files.delete_at(random(open_files.length)))
21805            close_sound(fd)
21806          end
21807        end
21808      end
21809    end
21810    open_files.apply(:close_sound)
21811    open_files = []
21812    if Snd.sounds.length != 0
21813      snd_display("active_sounds: %s %s?",
21814                  sounds.inspect, Snd.sounds.map do |s| short_file_name(s) end)
21815    end
21816    fd = open_raw_sound(:file, $sf_dir + "addf8.nh",
21817                        :channels, 1, :srate, 8012, :sample_type, Mus_mulaw)
21818    if sample_type(fd) != Mus_mulaw
21819      snd_display("open_raw_sound: %s?", mus_sample_type_name(sample_type(fd)))
21820    end
21821    close_sound(fd)
21822    #
21823    $bad_header_hook.reset_hook!
21824    test_spectral_difference($sf_dir + "o2.wave", $sf_dir + "o2_dvi.wave", 10.0)
21825    test_spectral_difference($sf_dir + "wood.riff", $sf_dir + "wood.sds", 4.0)
21826    test_spectral_difference($sf_dir + "nist-10.wav",
21827                             $sf_dir + "nist-shortpack.wav", 1.0)
21828    $bad_header_hook.add_hook!("snd-test") do |n| true end
21829    #
21830    # dangling readers (overall)
21831    #
21832    ind = open_sound("oboe.snd")
21833    hi = make_sampler(0, ind, 0)
21834    close_sound(ind)
21835    unless sampler?(hi)
21836      snd_display("dangling reader: %s?", hi)
21837    end
21838    unless string?(hi.to_s)
21839      snd_display("dangling reader format: %s?", hi)
21840    end
21841    val = hi.call
21842    val1 = next_sample(hi)
21843    val2 = previous_sample(hi)
21844    val3 = read_sample(hi)
21845    if fneq(val, 0.0) or fneq(val1, 0.0) or fneq(val2, 0.0) or fneq(val3, 0.0)
21846      snd_display("dangling read: %s %s %s %s?", val, val1, val2, val3)
21847    end
21848    if res = sampler_home(hi)
21849      snd_display("dangling reader home: %s?", res)
21850    end
21851    if (res = sampler_position(hi)).nonzero?
21852      snd_display("dangling sampler_position: %s?", res)
21853    end
21854    unless (res = sampler_at_end?(hi))
21855      snd_display("dangling reader eof: %s?", res)
21856    end
21857    free_sampler(hi)
21858    #
21859    # same (pruned edit)
21860    #
21861    ind = open_sound("oboe.snd")
21862    delete_samples(100, 100)
21863    hi = make_sampler(0, ind, 0)
21864    revert_sound
21865    delete_samples(100, 100)
21866    unless sampler?(hi)
21867      snd_display("pruned dangling reader: %s?", hi)
21868    end
21869    unless string?(hi.to_s)
21870      snd_display("pruned dangling reader format: %s?", hi)
21871    end
21872    val = hi.call
21873    val1 = next_sample(hi)
21874    val2 = previous_sample(hi)
21875    val3 = read_sample(hi)
21876    if fneq(val, 0.0) or fneq(val1, 0.0) or fneq(val2, 0.0) or fneq(val3, 0.0)
21877      snd_display("pruned dangling read: %s %s %s %s?", val, val1, val2, val3)
21878    end
21879    if (res = sampler_home(hi)) != [ind, 0]
21880      snd_display("pruned dangling reader home: %s?", res)
21881    end
21882    unless (res = sampler_at_end?(hi))
21883      snd_display("pruned dangling reader eof: %s?", res)
21884    end
21885    free_sampler(hi)
21886    close_sound(ind)
21887    #
21888    # region reader
21889    #
21890    ind = open_sound("oboe.snd")
21891    reg = make_region(1000, 2000, ind, 0)
21892    rd = make_region_sampler(reg, 0)
21893    if mix_sampler?(rd)
21894      snd_display("region_sampler mix: %s?", rd)
21895    end
21896    unless region_sampler?(rd)
21897      snd_display("region_sampler region: %s?", rd)
21898    end
21899    if sampler?(rd)
21900      snd_display("region_sampler normal: %s?", rd)
21901    end
21902    if (res = sampler_position(rd)).nonzero?
21903      snd_display("region_sampler position: %s?", res)
21904    end
21905    if (res = sampler_home(rd)) != [reg, 0]
21906      snd_display("region_sampler home: %s?", res)
21907    end
21908    if (res = sampler_at_end?(rd))
21909      snd_display("region_sampler_at_end?: %s?", res)
21910    end
21911    val = rd.call
21912    if fneq(val, 0.0328)
21913      snd_display("region_sampler at start: %s?", val)
21914    end
21915    unless string?(res = rd.to_s)
21916      snd_display("region_sampler: %s?", res)
21917    end
21918    close_sound(ind)
21919    forget_region(reg)
21920    val = read_sample(rd)
21921    if fneq(val, 0.0)
21922      snd_display("region_sampler at end: %s?", val)
21923    end
21924    unless sampler_at_end?(rd)
21925      snd_display("region_sampler after deletion?")
21926    end
21927    free_sampler(rd)
21928    #
21929    # mix reader
21930    #
21931    save_md = 0
21932    $mix_click_hook.add_hook!("mix-click-sets-amp") do |id| mix_click_sets_amp(id) end
21933    ind = open_sound("oboe.snd")
21934    reg = make_region(1000, 2000, ind, 0)
21935    md = mix_region(reg, 0, ind, 0, 0).car
21936    rd = make_mix_sampler(md)
21937    set_mix_property(:hi, md, "hi")
21938    save_md = md
21939    if (res = mix_property(:hi, md)) != "hi"
21940      snd_display("mix_property (hi): %s?", res)
21941    end
21942    val = rd.call
21943    if fneq(val, 0.0328)
21944      snd_display("mix_sampler at start: %s?", val)
21945    end
21946    unless string?(res = rd.to_s)
21947      snd_display("mix_sampler: %s?", res)
21948    end
21949    close_sound(ind)
21950    if (res = Snd.catch do mix_property(:hi, md) end).first != :no_such_mix
21951      snd_display("mix_property bad mix: %s", res.inspect)
21952    end
21953    if (res = rd.to_s) != "#<mix-sampler: inactive>"
21954      snd_display("mix_sampler released: %s?", res)
21955    end
21956    free_sampler(rd)
21957    $mix_click_hook.reset_hook!
21958    $close_hook.reset_hook!
21959    #
21960    sfiles = []
21961    ffiles = []
21962    old_dir = Dir.pwd
21963    Dir.chdir($sf_dir)
21964    each_sound_file do |file|
21965      Snd.catch do
21966        if mus_sound_chans(file) > 16
21967          ffiles.push(file)
21968        end
21969      end
21970    end
21971    map_sound_files do |file|
21972      Snd.catch do
21973        if mus_sound_chans(file) > 16
21974          sfiles.push(file)
21975        end
21976      end
21977    end
21978    if File.exist?("s24.snd") and
21979        (ffiles != [$sf_dir + "s24.snd"] or
21980         sfiles != [$sf_dir + "s24.snd"])
21981      snd_display("map|for_each_sound_file(s): %s %s?", ffiles, sfiles)
21982    end
21983    Dir.chdir(old_dir)
21984  end
21985  sf_dir_files.each do |n| mus_sound_forget($sf_dir + n) end
21986end
21987
21988# ---------------- test 13: menus, edit lists, hooks, etc ----------------
21989
21990def loop_through_files(description, select, &make_cmd)
21991  data = if select
21992           selection_to_temps(Mus_next, Mus_out_format)
21993         else
21994           sound_to_temps(Mus_next, Mus_out_format)
21995         end
21996  cont = true
21997  output_names = make_array(data.length) do |i|
21998    break unless cont
21999    outname = format("/tmp/snd_test_%s.snd", random(1.0).object_id)
22000    cont = shell(make_cmd.call(data[i], outname))
22001    outname
22002  end
22003  if select
22004    temps_to_selection(data, output_names, description)
22005  else
22006    temps_to_sound(data, output_names, description)
22007  end
22008end
22009
22010def copyfile(select)
22011  loop_through_files("(cp)", select) do |input, output| format("cp %s %s", input, output) end
22012end
22013
22014def carg0(hook)
22015  hook.call
22016end
22017
22018def carg1(hook)
22019  hook.call(1)
22020end
22021
22022def carg2(hook)
22023  hook.call(1, 2)
22024end
22025
22026def carg3(hook)
22027  hook.call(1, 2, 3)
22028end
22029
22030def carg4(hook)
22031  hook.call(1, 2, 3, 4)
22032end
22033
22034def carg5(hook)
22035  hook.call(1, 2, 3, 4, 5)
22036end
22037
22038def carg6(hook)
22039  hook.call(1, 2, 3, 4, 5, 6)
22040end
22041
22042def carg7(hook)
22043  hook.call(1, 2, 3, 4, 5, 6, 7)
22044end
22045
22046def harg0
22047  32
22048end
22049
22050def harg1(a)
22051  a + 32
22052end
22053
22054def harg2(a, b)
22055  a + b + 32
22056end
22057
22058def harg3(a, b, c)
22059  a + b + c + 32
22060end
22061
22062def harg4(a, b, c, d)
22063  a + b + c + d + 32
22064end
22065
22066def harg5(a, b, c, d, e)
22067  a + b + c + d + e + 32
22068end
22069
22070def harg6(a, b, c, d, e, f)
22071  a + b + c + d + e + f + 32
22072end
22073
22074def harg7(a, b, c, d, e, f, g)
22075  a + b + c + d + e + f + g + 32
22076end
22077
22078def test_hooks
22079  funcs = [[:harg0, :carg0, 32],
22080           [:harg1, :carg1, 33],
22081           [:harg2, :carg2, 35],
22082           [:harg3, :carg3, 38],
22083           [:harg4, :carg4, 42],
22084           [:harg5, :carg5, 47],
22085           [:harg6, :carg6, 53],
22086           [:harg7, :carg7, 60]]
22087  Snd_hooks.each do |hook|
22088    if hook? hook
22089      if hook.arity.between?(0, 7)
22090        vals = funcs[hook.arity]
22091        hook.add_hook!(get_func_name, &method(vals[0]))
22092        if (res = snd_func(vals[1], hook)) != vals[2]
22093          snd_display("hook.call: %s (%s) %s?", res.inspect, vals[2], hook.inspect)
22094        end
22095      else
22096        snd_display("hook arity: %s %s?", hook.arity, hook.inspect)
22097      end
22098    end
22099  end
22100  reset_almost_all_hooks
22101  Snd_hooks.each do |hook|
22102    if hook?(hook)
22103      next if hook.name == "$snd_error_hook"
22104      next if hook.name == "$mus_error_hook"
22105      unless hook.empty?
22106        snd_display("%s not empty?", hook.inspect)
22107      end
22108    end
22109  end
22110end
22111
22112def mdt_test(a, b, c, d)
22113  false
22114end
22115
22116def test_13_00
22117  fd = view_sound("oboe.snd")
22118  mb = add_to_main_menu("clm")
22119  if (res = Snd.catch do
22120        add_to_menu(-1, "fm-violin", lambda do | | false end)
22121      end).first != :no_such_menu
22122    snd_display("add_to_menu bad menu: %s", res.inspect)
22123  end
22124  if (res = Snd.catch do
22125        add_to_main_menu("oops", make_delay(11))
22126      end).first != :bad_arity
22127    snd_display("add_to_main_menu non-thunk: %s", res.inspect)
22128  end
22129  if (res = Snd.catch do
22130        add_to_menu(3, "oops", lambda do |a, b| make_delay(12) end)
22131      end).first != :bad_arity
22132    snd_display("add_to_menu non-thunk: %s", res.inspect)
22133  end
22134  set_cursor(2000, fd)
22135  set_transform_graph_type(Graph_once)
22136  set_transform_graph?(true, fd)
22137  if $with_test_gui
22138    add_to_menu(mb, "not here", lambda do | | snd_display("oops") end)
22139    remove_from_menu(mb,"not here")
22140  end
22141  $help_hook.reset_hook!
22142  hi = snd_help(:cursor_position)
22143  $help_hook.add_hook!("snd-test") do |a, b|
22144    if a != "cursor_position"
22145      snd_display("in $help_hook subject: %s?", a)
22146    end
22147    if b != "(cursor-position :optional snd chn): current cursor position (x y in pixels) in snd's channel chn"
22148      snd_display("in $help_hook text: %s?", b)
22149    end
22150    "hiho:" + b
22151  end
22152  ho = snd_help(:cursor_position)
22153  if ho.length != hi.length
22154    snd_display("length $help_hook\n\t<[%s]%s>\n\t<[%s]%s>?",
22155                hi.length, hi, ho.length, ho)
22156  end
22157  $help_hook.reset_hook!
22158  $help_hook.add_hook!("snd-test") do |a, b| false end
22159  ho = snd_help(:cursor_position)
22160  if hi != ho
22161    snd_display("$help_hook false: %s %s?", hi, ho)
22162  end
22163  $help_hook.reset_hook!
22164  #
22165  fr = framples(fd)
22166  chn = chans(fd)
22167  sr = srate(fd)
22168  mx = maxamp(fd)
22169  copyfile(false)
22170  if (res = edit_fragment) != ["(cp)", "set", 0, 50828]
22171    snd_display("copyfile: %s?", res)
22172  end
22173  if fr != framples(fd) or chn != chans(fd) or fneq(mx, maxamp(fd)) or fneq(sr, srate(fd))
22174    snd_display("copyfile (1): %s %s %s %s?", framples(fd), chans(fd), srate(fd), maxamp(fd))
22175  end
22176  eds = edits
22177  select_all
22178  copyfile(true)
22179  if (res = edit_fragment) != ["(cp)", "set", 0, 50828]
22180    snd_display("copyfile (select): %s?", res)
22181  end
22182  if (res = edits) != [eds[0] + 1, eds[1]]
22183    snd_display("copyfile (select eds): %s %s?", eds, res)
22184  end
22185  if fr != framples(fd) or chn != chans(fd) or fneq(mx, maxamp(fd)) or fneq(sr, srate(fd))
22186    snd_display("copyfile (2): %s %s %s %s?", framples(fd), chans(fd), srate(fd), maxamp(fd))
22187  end
22188  #
22189  set_transform_size(256, fd, 0)
22190  dpys = [Graph_once, Graph_as_sonogram, Graph_as_spectrogram] * 2
22191  ffts = [transform2integer($fourier_transform)] * 3 + [transform2integer($autocorrelation)] * 3
22192  dpys.zip(ffts) do |dpy_type, fft_type|
22193    set_transform_graph_type(dpy_type, fd, 0)
22194    set_transform_type(integer2transform(fft_type), fd, 0)
22195    update_transform_graph(fd, 0)
22196    vals = transform2vct(fd, 0)
22197    if vals
22198      if fneq(res = transform_sample(0, 0, fd, 0), vals[0])
22199        snd_display("transform_sample %s %s -> %s %s?", dpy_type, fft_type, vals[0], res)
22200      end
22201      if vals.length < 256
22202        snd_display("transform2vct size: %s?", vals.length)
22203      end
22204    else
22205      snd_display("transform %s %s -> %s?", dpy_type, fft_type, vals)
22206    end
22207  end
22208  if (res = Snd.catch do transform_sample(5000, 0, fd, 0) end).first != :no_such_sample
22209    snd_display("access invalid (bin) transform sample: %s", res.inspect)
22210  end
22211  if (res = Snd.catch do transform_sample(0, 5000, fd, 0) end).first != :no_such_sample
22212    snd_display("access invalid (slice) transform sample: %s", res.inspect)
22213  end
22214  close_sound(fd)
22215  set_transform_type($fourier_transform)
22216  $after_open_hook.add_hook!("snd-test") do |snd|
22217    set_x_axis_style(X_axis_in_samples, snd, true)
22218  end
22219  fd = open_sound("2.snd")
22220  close_sound(fd)
22221  $after_open_hook.reset_hook!
22222  $after_open_hook.add_hook!("snd-test") do |snd|
22223    set_x_axis_style(X_axis_in_percentage, snd, true)
22224  end
22225  $initial_graph_hook.add_hook!("snd-test") do |snd, chn, dur|
22226    if mus_sound_maxamp_exists?(file_name(snd))
22227      amp_vals = mus_sound_maxamp(file_name(snd))
22228      max_val = amp_vals[chn * 2 + 1]
22229      [0.0, dur, -max_val, max_val]
22230    else
22231      [0.0, dur, -1.0, 1.0]
22232    end
22233  end
22234  $after_open_hook.reset_hook!
22235  $initial_graph_hook.reset_hook!
22236  $initial_graph_hook.add_hook!("snd-test") do |snd, chn, dur|
22237    [0.0, dur, -1.0, 1.0, "a label", -4.0, 4.0]
22238  end
22239  fd = open_sound("2.snd")
22240  if defined? axis_info                           # snd-nogui hasn't axis_info
22241    ax = axis_info
22242    if array?(ax) and (fneq(ax[2], 0.0) or
22243                         fneq(ax[3], -1.0) or
22244                         fneq(ax[4], mus_sound_duration("2.snd")) or
22245                         fneq(ax[5], 1.0) or
22246                         fneq(ax[6], 0.0) or
22247                         fneq(ax[7], -4.0) or
22248                         fneq(ax[8], mus_sound_duration("2.snd")) or
22249                         fneq(ax[9], 4.0))
22250      snd_display("$initial_graph_hook with ymin/max: %s?", ax)
22251    end
22252  end
22253  $initial_graph_hook.reset_hook!
22254  set_selection_position(1000, fd, 1)
22255  set_selection_framples(10, fd, 1)
22256  set_selection_member?(true, fd, 1)
22257  if selection_member?(fd, 0)
22258    snd_display("chan 0 is selection_member?")
22259  end
22260  2.times do |chn|
22261    set_selection_position(1000, fd, chn)
22262    set_selection_framples(10, fd, chn)
22263    set_selection_member?(true, fd, chn)
22264  end
22265  scale_selection_to([0.5, 0.25].to_vct)
22266  if fneq(maxamp(fd, 0), 0.5) or fneq(maxamp(fd, 1), 0.25)
22267    snd_display("scale_selection_to with vector: %s?", maxamp(fd, true))
22268  end
22269  close_sound(fd)
22270  #
22271  fd = open_sound("obtest.snd")
22272  Snd.sounds.apply(:close_sound)
22273  test_hooks
22274  $bad_header_hook.add_hook!("snd-hook") do |n| true end
22275  ind = open_sound("oboe.snd")
22276  set_cursor(2000)
22277  key(key_to_int(?u), 4, ind)
22278  key(key_to_int(?1), 0, ind)
22279  key(key_to_int(?0), 0, ind)
22280  key(key_to_int(?0), 0, ind)
22281  key(key_to_int(?x), 4, ind)
22282  key(key_to_int(?z), 4, ind)
22283  if (res = edit_fragment) != ["smooth_channel(2000, 100", "set", 2000, 100]
22284    snd_display("C-x C-z fragment: %s?", res)
22285  end
22286  set_cursor(0)
22287  select_all
22288  key(key_to_int(?x), 4, ind)
22289  key(key_to_int(?o), 0, ind)
22290  key(key_to_int(?-), 4, ind)
22291  key(key_to_int(?x), 4, ind)
22292  key(key_to_int(?o), 0, ind)
22293  key(key_to_int(?x), 4, ind)
22294  key(key_to_int(?o), 0, ind)
22295  key(key_to_int(?x), 4, ind)
22296  key(key_to_int(?p), 0, ind)
22297  set_selection_member?(false, true)
22298  revert_sound(ind)
22299  close_sound(ind)
22300end
22301
22302def test_13_01
22303  with_file("addf8.nh") do |file|
22304    unless $open_raw_sound_hook.empty?
22305      $open_raw_sound_hook.reset_hook!
22306    end
22307    $open_raw_sound_hook.add_hook!("snd-hook") do |file, choice| [1, 22050, Mus_bshort] end
22308    ind = open_sound(file)
22309    play(ind, :wait, true)
22310    $open_raw_sound_hook.remove_hook!("snd-hook")
22311    if (res = [chans(ind),
22312               srate(ind),
22313               sample_type(ind),
22314               framples(ind)]) != [1, 22050, Mus_bshort, 23808]
22315      snd_display("open_raw: %s?", res)
22316    end
22317    set_search_procedure(lambda do |n| n > 0.2 end)
22318    close_sound(ind)
22319  end
22320  save_as_dialog = true
22321  save_as_name = "hiho"
22322  save_as_index = false
22323  $after_save_as_hook.reset_hook!
22324  $after_save_as_hook.add_hook!("snd-test") do |ind, name, dial|
22325    save_as_index = ind
22326    save_as_name = name
22327    save_as_dialog = dial
22328  end
22329  ind = open_sound("oboe.snd")
22330  save_sound_as("test.snd", ind, :header_type, Mus_raw)
22331  close_sound(ind)
22332  $open_raw_sound_hook.reset_hook!
22333  $after_save_as_hook.reset_hook!
22334  if save_as_dialog
22335    snd_display("$after_save_as_hook dialog: %s?", save_as_dialog)
22336  end
22337  if save_as_index != ind
22338    snd_display("$after_save_as_hook index: %s (%s)?", save_as_index, ind)
22339  end
22340  if Dir.pwd + "/test.snd" != save_as_name
22341    snd_display("$after_save_as_hook name: %s (%s)?", save_as_name, Dir.pwd + "/test.snd")
22342  end
22343  $open_raw_sound_hook.add_hook!("snd-hook-1") do |file, choice|
22344    if File.basename(file) != "test.snd"
22345      snd_display("$open_raw_sound_hook file: %s?", file)
22346    end
22347    unless choice == false
22348      snd_display("$open_raw_sound_hook choice 1: %s?", choice)
22349    end
22350    [2, 44100, Mus_mulaw]
22351  end
22352  ind = open_sound("test.snd")
22353  if (res = [header_type(ind), sample_type(ind), chans(ind), srate(ind), framples(ind)]) \
22354    != [Mus_raw, Mus_mulaw, 2, 44100, 50828]
22355    snd_display("$open_raw_sound_hook 1: %s?", res)
22356  end
22357  close_sound(ind)
22358  $open_raw_sound_hook.add_hook!("snd-hook-2") do |file, choice|
22359    if choice != [2, 44100, Mus_mulaw]
22360      snd_display("$open_raw_sound_hook choice 2: %s?", choice)
22361    end
22362    [1, 22050, Mus_lint]
22363  end
22364  ind = open_sound("test.snd")
22365  if (res = [header_type(ind), sample_type(ind), chans(ind), srate(ind), framples(ind)]) \
22366    != [Mus_raw, Mus_lint, 1, 22050, 50828 / 2]
22367    snd_display("$open_raw_sound_hook 2: %s?", res)
22368  end
22369  close_sound(ind)
22370  $open_raw_sound_hook.reset_hook!
22371  $open_raw_sound_hook.add_hook!("snd-hook-3") do |file, choice|
22372    [2]
22373  end
22374  ind = open_sound("test.snd")
22375  if (res = [header_type(ind), sample_type(ind), chans(ind), srate(ind)]) \
22376    != [Mus_raw, Mus_lint, 2, 22050]
22377    snd_display("$open_raw_sound_hook 3: %s?", res)
22378  end
22379  close_sound(ind)
22380  $open_raw_sound_hook.reset_hook!
22381  $open_raw_sound_hook.add_hook!("snd-hook-4") do |file, choice|
22382    [1, 22050, Mus_bshort, 120, 320]
22383  end
22384  ind = open_sound("test.snd")
22385  if (res = [header_type(ind), sample_type(ind), chans(ind), srate(ind),
22386             data_location(ind), data_size(ind), framples(ind)]) \
22387    != [Mus_raw, Mus_bshort, 1, 22050, 120, 320, 160]
22388    snd_display("$open_raw_sound_hook 4: %s?", res)
22389  end
22390  close_sound(ind)
22391  $open_raw_sound_hook.reset_hook!
22392  $during_open_hook.reset_hook!
22393  #
22394  ind = op = sl = aop = dop = cl = ig = scl = other = false
22395  $open_hook.add_hook!("snd-test") do |filename|
22396    if filename != mus_expand_filename("oboe.snd")
22397      snd_display("$open_hook: %s?", filename)
22398    end
22399    op = true
22400    false
22401  end
22402  $after_open_hook.add_hook!("snd-test") do |snd|
22403    aop = snd
22404  end
22405  $during_open_hook.add_hook!("snd-test") do |fd, filename, reason|
22406    if filename != mus_expand_filename("oboe.snd")
22407      snd_display("$during_open_hook filename: %s?", filename)
22408    end
22409    if reason != 1
22410      snd_display("$during_open_hook reason: %s?", reason)
22411    end
22412    dop = true
22413  end
22414  $initial_graph_hook.add_hook!("snd-test") do |snd, chn, dur|
22415    if chn.nonzero?
22416      snd_display("$initial_graph_hook (channel): %s not 0?", chn)
22417    end
22418    ig = true
22419    false
22420  end
22421  ind = open_sound("oboe.snd")
22422  unless op
22423    snd_display("$open_hook not called?")
22424  end
22425  unless dop
22426    snd_display("$during_open_hook not called?")
22427  end
22428  unless ig
22429    snd_display("$initial_graph_hook not called?")
22430  end
22431  unless sound?(aop)
22432    snd_display("$after_open_hook not called?")
22433  end
22434  if aop != ind
22435    snd_display("$after_open_hook %s but ind: %s?", aop, ind)
22436  end
22437  select_all
22438  $open_hook.reset_hook!
22439  $during_open_hook.reset_hook!
22440  $after_open_hook.reset_hook!
22441  $initial_graph_hook.reset_hook!
22442  $open_hook.add_hook!("snd-test") do |filename| true end
22443  unless (res = open_sound("pistol.snd")) == false
22444    snd_display("$open_hook true, but open_sound -> %s?", res)
22445    if sound?(res)
22446      close_sound(res)
22447    end
22448  end
22449  $open_hook.reset_hook!
22450  #
22451  gr = agr = gbf = abf = false
22452  $before_transform_hook.reset_hook!
22453  $after_transform_hook.reset_hook!
22454  $after_graph_hook.reset_hook!
22455  $graph_hook.reset_hook!
22456  $graph_hook.add_hook!("snd-test") do |snd, chn, y0, y1|
22457    unless snd.eql?(ind)
22458      snd_display("$graph_hook: %s not %s?", snd, ind)
22459    end
22460    if chn.nonzero?
22461      snd_display("$graph_hook: (channel): %s not 0?", chn)
22462    end
22463    gr = true
22464    false
22465  end
22466  $after_graph_hook.add_hook!("snd-test") do |snd, chn|
22467    unless snd.eql?(ind)
22468      snd_display("$after_graph_hook: %s not %s?", snd, ind)
22469    end
22470    if chn.nonzero?
22471      snd_display("$after_graph_hook: (channel): %s not 0?", chn)
22472    end
22473    agr = true
22474  end
22475  $before_transform_hook.add_hook!("snd-test") do |snd, chn|
22476    gbf = true
22477    cursor
22478  end
22479  $after_transform_hook.add_hook!("snd-test") do |snd, chn, scale|
22480    abf = true
22481    if transform_graph?(snd, chn) and
22482      transform_graph_type(snd, chn) == Graph_once
22483      num = (2.0 * transform2vct(snd, chn).peak / transform_size(snd, chn)).to_s
22484      status_report(num, snd)
22485    end
22486    false
22487  end
22488  set_transform_graph?(true, ind, 0)
22489  set_time_graph?(true, ind, 0)
22490  update_transform_graph(ind, 0)
22491  if $with_test_motif
22492    unless gr
22493      app = main_widgets.car
22494      1000.times do
22495        msg = RXtAppPending(app)
22496        if (msg & (RXtIMXEvent | RXtIMAlternateInput)).zero?
22497          break
22498        else
22499          RXtDispatchEvent(RXtAppNextEvent(app))
22500        end
22501      end
22502    end
22503  end
22504  unless gr
22505    snd_display("$graph_hook not called? %s %s %s %s?",
22506                time_graph?(ind), short_file_name(ind), ind, sounds)
22507  end
22508  unless agr
22509    snd_display("$after_graph_hook not called?")
22510  end
22511  unless gbf
22512    snd_display("$before_transform_hook not called?")
22513  end
22514  unless abf
22515    snd_display("$after_transform_hook not called?")
22516  end
22517  $before_transform_hook.reset_hook!
22518  set_transform_graph?(false, ind, 0)
22519  $graph_hook.reset_hook!
22520  $after_graph_hook.reset_hook!
22521  #
22522  other = open_sound("pistol.snd")
22523  $select_sound_hook.add_hook!("snd-test") do |snd|
22524    unless snd.eql?(ind)
22525      snd_display("$select_sound_hook: %s not %s?", snd, ind)
22526    end
22527    sl = true
22528  end
22529  $select_channel_hook.add_hook!("snd-test") do |snd, chn|
22530    unless snd.eql?(ind)
22531      snd_display("$select_channel_hook: %s not %s?", snd, ind)
22532    end
22533    if chn.nonzero?
22534      snd_display("$select_channel_hook: (channel): %s not 0?", chn)
22535    end
22536    scl = true
22537  end
22538  select_sound(ind)
22539  unless sl
22540    snd_display("$select_sound_hook not called?")
22541  end
22542  unless scl
22543    snd_display("$select_channel_hook not called?")
22544  end
22545  $select_sound_hook.reset_hook!
22546  $select_channel_hook.reset_hook!
22547  #
22548  spl = stl = ph = ph1 = false
22549  $start_playing_hook.add_hook!("snd-test") do |snd|
22550    spl = true
22551    unless snd.eql?(ind)
22552      snd_display("$start_playing_hook: %s not %s?", snd, ind)
22553    end
22554    false
22555  end
22556  $stop_playing_hook.add_hook!("snd-test") do |snd|
22557    unless snd.eql?(ind)
22558      snd_display("$stop_playing_hook: %s not %s?", snd, ind)
22559    end
22560    stl = true
22561    false
22562  end
22563  $play_hook.add_hook!("snd-test") do |n|
22564    if n < 128
22565      snd_display("$play_hook samps: %s?", n)
22566    end
22567    set_expand_control_hop(expand_control_hop)
22568    set_expand_control_length(expand_control_length)
22569    set_expand_control_ramp(expand_control_ramp)
22570    set_contrast_control_amp(contrast_control_amp)
22571    set_reverb_control_lowpass(reverb_control_lowpass)
22572    set_reverb_control_feedback(reverb_control_feedback)
22573    ph = true
22574  end
22575  set_expand_control?(true, ind)
22576  set_reverb_control?(true, ind)
22577  play(ind, :wait, true)
22578  set_expand_control?(false, ind)
22579  set_reverb_control?(false, ind)
22580  unless spl
22581    snd_display("$start_playing_hook not called?")
22582  end
22583  unless stl
22584    snd_display("$stop_playing_hook not called?")
22585  end
22586  unless ph
22587    snd_display("$play_hook not called?")
22588  end
22589  $start_playing_hook.reset_hook!
22590  $start_playing_selection_hook.reset_hook!
22591  $stop_playing_hook.reset_hook!
22592  $play_hook.reset_hook!
22593  $play_hook.add_hook!("snd-test") do |n|
22594    set_expand_control_hop(0.02)
22595    set_expand_control_length(0.02)
22596    set_expand_control_ramp(0.2)
22597    set_contrast_control_amp(0.5)
22598    set_reverb_control_lowpass(0.02)
22599    set_reverb_control_feedback(0.02)
22600  end
22601  # play(ind, :wait, true)
22602  $play_hook.reset_hook!
22603  $start_playing_hook.add_hook!("snd-test") do |snd| true end
22604  play("4.aiff")
22605  $start_playing_hook.reset_hook!
22606  #
22607  ss = false
22608  old_reg = selection_creates_region
22609  set_selection_creates_region(true)
22610  $stop_playing_selection_hook.add_hook!("snd-test") do | | ss = true end
22611  reg = select_all
22612  play(selection, :wait, true)
22613  play(reg, :wait, true)
22614  unless ss
22615    snd_display("$stop_playing_selection_hook not called?")
22616  end
22617  $stop_playing_selection_hook.reset_hook!
22618  set_selection_creates_region(old_reg)
22619  play(ind, :wait, true)
22620  #
22621  e0 = e1 = u0 = u1 = a0 = a1 = false
22622  edit_hook(ind, 0).add_hook!("snd-test-1")         do | | e0 = true end
22623  edit_hook(other, 0).add_hook!("snd-test-2")       do | | e1 = true; false end
22624  undo_hook(ind, 0).add_hook!("snd-test-1")         do | | u0 = true end
22625  undo_hook(other, 0).add_hook!("snd-test-2")       do | | u1 = true end
22626  after_edit_hook(ind, 0).add_hook!("snd-test-1")   do | | a0 = true end
22627  after_edit_hook(other, 0).add_hook!("snd-test-2") do | | a1 = true end
22628  #
22629  delete_sample(0, ind, 0)
22630  if edit_position(ind, 0) != 0
22631    snd_display("edit_hook true did not disallow edit!")
22632  end
22633  unless e0
22634    snd_display("edit_hook true not called?")
22635  end
22636  if a0
22637    snd_display("after_edit_hook 0 called?")
22638  end
22639  undo_edit(1, ind, 0)
22640  if u0
22641    snd_display("undo_hook called?")
22642  end
22643  #
22644  delete_sample(0, other, 0)
22645  if edit_position(other, 0) != 1
22646    snd_display("edit_hook false did not allow edit!")
22647  end
22648  unless e1
22649    snd_display("edit_hook false not called?")
22650  end
22651  unless a1
22652    snd_display("after_edit_hook 1 not called?")
22653  end
22654  undo_edit(1, other, 0)
22655  unless u1
22656    snd_display("undo_hook not called?")
22657  end
22658  #
22659  edit_hook(ind, 0).reset_hook!
22660  edit_hook(other, 0).reset_hook!
22661  undo_hook(ind, 0).reset_hook!
22662  undo_hook(other, 0).reset_hook!
22663  after_edit_hook(ind, 0).reset_hook!
22664  after_edit_hook(other, 0).reset_hook!
22665  #
22666  $snd_error_hook.reset_hook!
22667  $snd_warning_hook.reset_hook!
22668  $mus_error_hook.reset_hook!
22669  se = false
22670  sw = false
22671  me = false
22672  se_msg = "se_msg"
22673  sw_msg = "sw_msg"
22674  me_msg = "me_msg"
22675  $snd_error_hook.add_hook!("snd-test") do |msg|
22676    se_msg = msg
22677    se = true
22678  end
22679  $snd_warning_hook.add_hook!("snd-test") do |msg|
22680    sw_msg = msg
22681    sw = true
22682  end
22683  $mus_error_hook.add_hook!("snd-test") do |type, msg|
22684    me_msg = msg
22685    me = true
22686  end
22687  snd_error("uhoh")
22688  snd_warning("hiho")
22689  mus_sound_samples("/bad/baddy")
22690  unless se
22691    snd_display("$snd_error_hook not called (%s != uhoh)?", se_msg)
22692  end
22693  unless sw
22694    snd_display("$snd_warning_hook not called (%s != hiho)?", sw_msg)
22695  end
22696  unless me
22697    snd_display("$mus_error_hook not called (%s)?", me_msg)
22698  end
22699  $snd_error_hook.reset_hook!
22700  $snd_warning_hook.reset_hook!
22701  $mus_error_hook.reset_hook!
22702  $snd_error_hook.add_hook!("snd-test") do |msg|
22703    se = msg
22704    true
22705  end
22706  snd_error("not an error")
22707  if se != "not an error"
22708    snd_display("$snd_error_hook saw: %s?", se)
22709  end
22710  #
22711  $before_exit_hook.add_hook!("snd-test-1") do | | false end
22712  $before_exit_hook.add_hook!("snd-test-2") do | | true end
22713  $exit_hook.add_hook!("snd-test-3") do | | false end
22714  $exit_hook.reset_hook!
22715  $before_exit_hook.reset_hook!
22716  #
22717  sh = false
22718  delete_file("baddy.snd")
22719  $save_hook.add_hook!("snd-test") do |snd, filename|
22720    if (not string?(filename)) or filename != mus_expand_filename("baddy.snd")
22721      snd_display("$save_hook filename: %s?", filename)
22722    end
22723    unless snd.eql?(ind)
22724      snd_display("$save_hook: %s not %s?", snd, ind)
22725    end
22726    sh = true
22727  end
22728  save_sound_as("baddy.snd", ind)
22729  unless sh
22730    snd_display("$save_hook not called?")
22731  end
22732  if File.exist?("baddy.snd")
22733    snd_display("$save_hook did not cancel save?")
22734    delete_file("baddy.snd")
22735  end
22736  $save_hook.reset_hook!
22737  $close_hook.add_hook!("snd-test") do |snd|
22738    unless snd.eql?(ind)
22739      snd_display("$close_hook: %s not %s?", snd, ind)
22740    end
22741    cl = true
22742  end
22743  close_sound(ind)
22744  unless cl
22745    snd_display("$close_hook not called?")
22746  end
22747  $close_hook.reset_hook!
22748  close_sound(other)
22749end
22750
22751def test_13_02
22752  unless $with_test_alsa
22753    in1 = open_sound("oboe.snd")
22754    in2 = open_sound("2.snd")
22755    set_sync(1, in1)
22756    set_sync(1, in2)
22757    play(selected_sound, :wait, true)
22758    close_sound(in1)
22759    close_sound(in2)
22760  end
22761  #
22762  ind = open_sound("oboe.snd")
22763  if $with_test_motif
22764    edhist = channel_widgets(ind, 0)[7]
22765    edp = RXtParent(edhist)
22766    RXtUnmanageChild(edp)
22767    RXtVaSetValues(edp, [RXmNpaneMinimum, 100])
22768    RXtManageChild(edp)
22769  end
22770  edit_hook_ctr = 0
22771  after_edit_hook_ctr = 0
22772  edit_hook(ind, 0).add_hook!("snd-test") do | |
22773    edit_hook_ctr += 1
22774    true
22775  end
22776  after_edit_hook(ind, 0).add_hook!("snd-test") do | |
22777    after_edit_hook_ctr += 1
22778    true
22779  end
22780  all_tests = [[:apply_controls, lambda { | |
22781                  set_amp_control(0.5, ind, 0)
22782                  apply_controls(ind)
22783                  set_amp_control(1.0, ind, 0)
22784                }],
22785               [:clm_channel, lambda { | | clm_channel(make_two_zero(1, -1)) }],
22786               [:convolve_selection_with, lambda { | |
22787                  reg = select_all(ind, 0)
22788                  convolve_selection_with("1a.snd", 0.5)
22789                  region?(reg) and forget_region(reg)
22790                }],
22791               [:convolve_with, lambda { | | convolve_with("1a.snd", 0.5, ind, 0)}],
22792               [:delete_sample, lambda { | | delete_sample(123, ind, 0) }],
22793               [:delete_samples, lambda { | | delete_samples(123, 123, ind, 0) }],
22794               [:delete_selection, lambda { | |
22795                  reg = select_all(ind, 0)
22796                  delete_selection
22797                  region?(reg) and forget_region(reg)
22798                }],
22799               [:env_channel, lambda { | | env_channel([0, 0, 1, 1]) }],
22800               [:env_selection, lambda { | |
22801                  reg = select_all(ind, 0)
22802                  env_selection([0, 0, 1, 1], 1.0)
22803                  region?(reg) and forget_region(reg)
22804                }],
22805               [:env_sound, lambda { | | env_sound([0, 0, 1, 1]) }],
22806               [:filter_sound, lambda { | | filter_sound([0, 1, 1, 0], 1024) }],
22807               [:filter_selection, lambda { | |
22808                  reg = select_all(ind, 0)
22809                  filter_selection([0, 0, 1, 1], 6)
22810                  region?(reg) and forget_region(reg)
22811                }],
22812               [:insert_region, lambda { | |
22813                  reg = make_region(0, 100, ind, 0)
22814                  insert_region(reg, 123, ind, 0)
22815                  region?(reg) and forget_region(reg)
22816                }],
22817               [:insert_sample, lambda { | | insert_sample(123, 0.5, ind, 0) }],
22818               [:insert_samples, lambda { | | insert_samples(123, 3, make_vct(3, 1.0), ind, 0) }],
22819               [:insert_selection, lambda { | |
22820                  reg = select_all(ind, 0)
22821                  insert_selection(120, ind, 0)
22822                  region?(reg) and forget_region(reg)
22823                }],
22824               [:insert_silence, lambda { | | insert_silence(123, 456, ind, 0) }],
22825               [:insert_sound, lambda { | | insert_sound("1a.snd", 123) }],
22826               [:map_chan, lambda { | | map_chan(lambda { |y| y + 0.2 }) }],
22827               [:map_channel, lambda { | | map_channel(lambda { |y| y + 0.2 }) }],
22828               [:mix, lambda { | | mix("1a.snd", 123) }],
22829               [:mix_amp, lambda { | |
22830                  mx = mix_vct(make_vct(3, 1.0), 123)
22831                  mix?(mx) and set_mix_amp(mx, 0.123)
22832                }],
22833               [:mix_amp_env, lambda { | |
22834                  mx = mix_vct(make_vct(3, 1.0), 123)
22835                  mix?(mx) and set_mix_amp_env(mx, [0, 0, 1, 1])
22836                }],
22837               [:mix_position, lambda { | |
22838                  mx = mix_vct(make_vct(3, 1.0), 123)
22839                  mix?(mx) and set_mix_position(mx, 123)
22840                }],
22841               [:mix_speed, lambda { | |
22842                  mx = mix_vct(make_vct(3, 1.0), 123)
22843                  mix?(mx) and set_mix_speed(mx, 0.123)
22844                }],
22845               [:mix_region, lambda { | |
22846                  reg = make_region(0, 100, ind, 0)
22847                  mix_region(reg, 123, ind, 0)
22848                  region?(reg) and forget_region(reg)
22849                }],
22850               [:mix_selection, lambda { | |
22851                  reg = select_all(ind, 0)
22852                  mix_selection(1234, ind, 0)
22853                  region?(reg) and forget_region(reg)
22854                }],
22855               [:mix_vct, lambda { | | mix_vct(make_vct(10, 0.3), 123) }],
22856               [:pad_channel, lambda { | | pad_channel(123, 456, ind, 0) }],
22857               [:ramp_channel, lambda { | | ramp_channel(0.0, 0.5, 123, 456) }],
22858               [:reverse_channel, lambda { | | reverse_channel(123, 456, ind, 0) }],
22859               [:reverse_sound, lambda { | | reverse_sound(ind, 0) }],
22860               [:reverse_selection, lambda { | |
22861                  reg = select_all(ind, 0)
22862                  reverse_selection
22863                  region?(reg) and forget_region(reg)
22864                }],
22865               [:scale_by, lambda { | | scale_by(2.0) }],
22866               [:scale_channel, lambda { | | scale_channel(0.5, 123, 456, ind, 0) }],
22867               [:scale_selection_by, lambda { | |
22868                  reg = select_all(ind, 0)
22869                  scale_selection_by(2.0)
22870                  region?(reg) and forget_region(reg)
22871                }],
22872               [:scale_selection_to, lambda { | |
22873                  reg = select_all(ind, 0)
22874                  scale_selection_to(0.5)
22875                  region?(reg) and forget_region(reg)
22876                }],
22877               [:scale_to, lambda { | | scale_to(0.4) }],
22878               [:scale_sound_to, lambda { | | scale_sound_to(0.5) }],
22879               [:smooth_channel, lambda { | | smooth_channel(123, 456, ind, 0) }],
22880               [:smooth_sound, lambda { | | smooth_sound(123, 456, ind, 0) }],
22881               [:smooth_selection, lambda { | |
22882                  reg = select_all(ind, 0)
22883                  smooth_selection
22884                  region?(reg) and forget_region(reg)
22885                }],
22886               [:src_channel, lambda { | | src_channel(0.5, 123, 456, ind, 0) }],
22887               [:src_sound, lambda { | | src_sound([0, 0.5, 1, 1]) }],
22888               [:src_selection, lambda { | |
22889                  reg = select_all(ind, 0)
22890                  src_selection(0.5)
22891                  region?(reg) and forget_region(reg)
22892                }],
22893               [:swap_channels, lambda { | |
22894                  ind1 = open_sound("1a.snd")
22895                  swap_channels(ind, 0, ind1, 0)
22896                  close_sound(ind1)
22897                }],
22898               [:vct2channel, lambda { | | vct2channel(make_vct(3), 123, 3, ind, 0) }],
22899               [:xramp_channel, lambda { | | xramp_channel(0.5, 1.0, 32.0, 123, 456, ind, 0) }]]
22900  #
22901  all_tests.each do |name, func|
22902    Snd.catch do func.call end
22903    if (res = edit_position(ind, 0)) != 0
22904      snd_display("%s: blocked edit: %s?", name, res)
22905    end
22906    if edit_hook_ctr != 1
22907      snd_display("%s: edit_hook calls: %s?", name, edit_hook_ctr)
22908    end
22909    if after_edit_hook_ctr != 0
22910      snd_display("%s: after_edit_hook calls: %s?", name, after_edit_hook_ctr)
22911    end
22912    edit_hook_ctr = 0
22913    if (res = mixes(ind, 0)) != nil
22914      snd_display("%s: mixes: %s?", name, res)
22915    end
22916  end
22917  #
22918  edit_hook_ctr = 0
22919  after_edit_hook_ctr = 0
22920  edit_hook(ind, 0).reset_hook!
22921  after_edit_hook(ind, 0).reset_hook!
22922  edit_hook(ind, 0).add_hook!("snd-test") do | |
22923    edit_hook_ctr += 1
22924    false
22925  end
22926  after_edit_hook(ind, 0).add_hook!("snd-test") do | |
22927    after_edit_hook_ctr += 1
22928    true
22929  end
22930  #
22931  all_tests.each do |name, func|
22932    func.call
22933    unless (res = edit_position(ind, 0)) > 0
22934      snd_display("%s: unblocked edit: %s?", name, res)
22935    end
22936    unless edit_hook_ctr > 0
22937      snd_display("%s: unblocked edit_hook calls: %s?", name, edit_hook_ctr)
22938    end
22939    unless after_edit_hook_ctr > 0
22940      snd_display("%s: unblocked after_edit_hook calls: %s?", name, after_edit_hook_ctr)
22941    end
22942    edit_hook_ctr = 0
22943    after_edit_hook_ctr = 0
22944    revert_sound(ind)
22945  end
22946  if $with_test_motif
22947    edhist = channel_widgets(ind, 0)[7]
22948    edp = RXtParent(edhist)
22949    RXtUnmanageChild(edp)
22950    RXtVaSetValues(edp, [RXmNpaneMinimum, 1])
22951    RXtManageChild(edp)
22952  end
22953  close_sound(ind)
22954  reset_all_hooks
22955  #
22956  # before|after-save-as-hook
22957  #
22958  hook_called = false
22959  $before_save_as_hook.add_hook!("snd-test") do |s1, f, sel, sr, type, fmt, com|
22960    if sr != srate(s1)
22961      channels(s1).times do |chn|
22962        src_channel(srate(s1).to_f / sr, 0, false, s1, chn)
22963      end
22964      Snd.catch do
22965        save_sound_as(f, s1,
22966                      :header_type, fmt,
22967                      :sample_type, type,
22968                      :srate, sr,
22969                      :comment, com)
22970      end
22971      channels(s1).times do |chn|
22972        undo_edit(1, s1, chn)
22973      end
22974      hook_called = true
22975      true
22976    else
22977      false
22978    end
22979  end
22980  ind = open_sound("2.snd")
22981  save_sound_as("test.snd", :srate, 44100)
22982  if (res = edit_position(ind, 0)).nonzero?
22983    snd_display("$before_save_as_hook undo_edit: %s?", res)
22984  end
22985  unless hook_called
22986    snd_display("$before_save_as_hook not called?")
22987  end
22988  close_sound(ind)
22989  ind = open_sound("test.snd")
22990  if (res = srate(ind)) != 44100
22991    snd_display("$before_save_as_hook src: %s?", res)
22992  end
22993  close_sound(ind)
22994  $before_save_as_hook.remove_hook!("snd-test")
22995  #
22996  need_save_as_undo = false
22997  $before_save_as_hook.add_hook!("snd-test") do |s1, f, sel, sr, type, fmt, com|
22998    need_save_as_undo = false
22999    if sr != srate(s1)
23000      src_sound(srate(s1).to_f / sr, 1.0, s1)
23001      need_save_as_undo = true
23002    end
23003    false
23004  end
23005  $after_save_as_hook.add_hook!("snd-test") do |snd, fname, dialog|
23006    if need_save_as_undo
23007      undo_edit
23008    end
23009  end
23010  ind = open_sound("oboe.snd")
23011  save_sound_as("test.snd", :srate, 44100)
23012  if (res = edit_position(ind, 0)).nonzero?
23013    snd_display("$after_save_as_hook undo_edit: %s?", res)
23014  end
23015  close_sound(ind)
23016  ind = open_sound("test.snd")
23017  if (res = srate(ind)) != 44100
23018    snd_display("$before|after_save_as_hook src: %s?", res)
23019  end
23020  close_sound(ind)
23021  $before_save_as_hook.reset_hook!
23022  $after_save_as_hook.reset_hook!
23023  #
23024  old_clip = clipping
23025  old_mus_clip = mus_clipping
23026  set_clipping(true)
23027  set_mus_clipping(true)
23028  $clip_hook.reset_hook!
23029  index = new_sound("test.snd", 1, 22050, Mus_bshort, Mus_next,
23030                    "clip-hook test", 10)
23031  map_channel(lambda do |y| mus_random(0.999) end)
23032  set_sample(2,  1.0001)
23033  set_sample(4, -1.0)
23034  set_sample(6,  1.5)
23035  set_sample(8, -1.5)
23036  hook_called = 0
23037  vals = channel2vct(0, 10, index)
23038  $clip_hook.add_hook!("test-13-clip") do |val|
23039    if fneq(val, 1.0) and
23040        fneq(val, 1.5) and
23041        fneq(val, -1.5)
23042      snd_display("$clip_hook called upon: %s?", val)
23043    end
23044    hook_called += 1
23045    0.0
23046  end
23047  save_sound(index)
23048  $clip_hook.reset_hook!
23049  if hook_called != 3
23050    snd_display("$clip_hook called %s times?", hook_called)
23051  end
23052  close_sound(index)
23053  index = open_sound("test.snd")
23054  new_vals = channel2vct(0, 10, index)
23055  fixed_vals = vct_copy(vals)
23056  fixed_vals[2] = 0.0
23057  fixed_vals[6] = 0.0
23058  fixed_vals[8] = 0.0
23059  unless vequal(fixed_vals, new_vals)
23060    snd_display("$clip_hook results:\n%s\n%s\n%s?", new_vals, fixed_vals, vals)
23061  end
23062  close_sound(index)
23063  set_clipping(old_clip)
23064  set_mus_clipping(old_mus_clip)
23065end
23066
23067def test_13
23068  if $with_test_gui
23069    reset_almost_all_hooks
23070    test_13_00
23071    test_13_01
23072    test_13_02
23073  end
23074end
23075
23076# ---------------- test 14: all together now ----------------
23077
23078def test_panel(func)
23079  val = snd_func(func, true)
23080  val1 = Snd.sounds.apply(:snd_func, func)
23081  val2 = Snd.sounds.reverse.apply(:snd_func, func)
23082  if (not vequal(val, val1)) and (not vequal(val, val2))
23083    snd_display_prev_caller("%s %s:\n\t%s\n\t%s\n\t%s?", get_func_name, func, val, val1, val2)
23084  end
23085end
23086
23087def all_chans_zipped_reverse
23088  new_list = []
23089  Snd.sounds.reverse.each do |snd|
23090    channels(snd).times do |chn|
23091      new_list.push([snd, chn])
23092    end
23093  end
23094  new_list
23095end
23096
23097def test_channel(func)
23098  val = snd_func(func, true, true).flatten
23099  val1 = all_chans_zipped.map do |snd, chn| snd_func(func, snd, chn) end.flatten
23100  val2 = all_chans_zipped_reverse.map do |snd, chn| snd_func(func, snd, chn) end.flatten
23101  if (not val.eql?(val1)) and (not val.eql?(val2))
23102    snd_display_prev_caller("%s %s:\n\t%s\n\t%s\n\t%s?", get_func_name, func, val, val1, val2)
23103  end
23104end
23105
23106def duration(snd)
23107  framples(snd) / srate(snd).to_f
23108end
23109
23110def safe_make_selection(beg, fin, snd)
23111  len = framples(snd)
23112  old_choice = selection_creates_region()
23113  set_selection_creates_region(true)
23114  if len > 1
23115    if fin < len
23116      make_selection(beg, fin, snd)
23117    else
23118      if beg < len
23119        make_selection(beg, len - 1, snd)
23120      else
23121        make_selection(0, len - 1, snd)
23122      end
23123    end
23124  end
23125  set_selection_creates_region(old_choice)
23126end
23127
23128def clone_sound_as(new_name, snd = false)
23129  string?(save_dir) or set_save_dir("/tmp")
23130  old_snd = Snd.snd(snd)
23131  fdir, fbase = File.split(snd_tempnam)
23132  rb = fdir + "/" + File.basename(fbase, ".snd") + ".rb"
23133  save_edit_history(rb, old_snd)
23134  file_copy(file_name(old_snd), new_name)
23135  sfile = open_sound(new_name)
23136  eval(File.open(rb).read)
23137  delete_file(rb)
23138  sfile
23139end
23140
23141def test_14
23142  if $with_test_gui
23143    cur_dir_files = []
23144    sound_files_in_directory(".").each do |f|
23145      if Snd.catch(:all, 0) do mus_sound_framples(f) end.first > 0
23146        cur_dir_files.push(f)
23147      end
23148    end
23149    $after_open_hook.add_hook!("make_player") do |snd| make_player(snd, 0) end
23150    open_ctr = 0
23151    stereo_files = []
23152    quad_files = []
23153    mono_files = []
23154    octo_files = []
23155    open_files = []
23156    cur_dir_files.each do |name|
23157      ht = mus_sound_header_type(name)
23158      df = mus_sound_sample_type(name)
23159      len = mus_sound_framples(name)
23160      if ht != Mus_raw and len.nonzero? and df != -1
23161        case mus_sound_chans(name)
23162        when 1
23163          mono_files.push(name)
23164        when 2
23165          stereo_files.push(name)
23166        when 4
23167          quad_files.push(name)
23168        when 8
23169          octo_files.push(name)
23170        end
23171      end
23172    end
23173    with_buffers_menu
23174    Snd.sounds.each do |snd|
23175      mxpos = 0
23176      channels(snd).times do |chn| mxpos += edit_position(snd, chn) end
23177      if mxpos > 100 or channels(snd) > 4
23178        snd_display("revert %s at %s?", file_name(snd), mxpos)
23179        revert_sound(snd)
23180      end
23181    end
23182    files = Snd.sounds.length
23183    delete_file("s61.rb")
23184    Snd.sounds.each do |s|
23185      if channels(s) > 4
23186        open_files.delete_if do |f| f == s end
23187        close_sound(s)
23188      end
23189    end
23190    save_state("s61.rb")
23191    Snd.sounds.apply(:close_sound)
23192    Snd.regions.apply(:forget_region)
23193    load("s61.rb")
23194    if Snd.sounds.length != files
23195      snd_display("save_state restart from %s to %s sounds?", files, Snd.sounds.length)
23196    end
23197    open_files = Snd.sounds
23198    len = open_files.length
23199    open_chance = [0.0, (8.0 - len) * 0.125].max
23200    close_chance = len * 0.125
23201    if len.zero?
23202      name = cur_dir_files[random(cur_dir_files.length)]
23203      ht = mus_sound_header_type(name)
23204      df = mus_sound_sample_type(name)
23205      fd = (ht == Mus_raw or df == -1) ? -1 : view_sound(name)
23206      if number?(fd) and fd != -1
23207        open_files.push(fd)
23208      else
23209        close_sound(fd)
23210      end
23211    end
23212    if len > 0
23213      fd = open_files[random(open_files.length)]
23214      close_sound(fd)
23215      open_files.delete_if do |f| f == fd end
23216    end
23217    open_ctr = open_files.length
23218    if open_ctr.zero?
23219      fd = view_sound("oboe.snd")
23220      open_ctr = 1
23221      open_files.push(fd)
23222    end
23223    choose_fd = lambda do Snd.sounds[random(Snd.sounds.length)] end
23224    curfd = choose_fd.call
23225    curloc = [0, [1200, framples(curfd, 0)].min].max
23226    old_marks = Snd.marks(curfd, 0).length
23227    if (dur = duration(curfd)) > 0.0
23228      set_x_bounds([0.0, [dur, 1.0].min], curfd)
23229      xb = x_bounds(curfd)
23230      if fneq(xb[0], 0.0) or fneq(xb[1], [dur, 1.0].min)
23231        snd_display("x_bounds: %s?", xb)
23232      end
23233    end
23234    set_y_bounds([-0.5, 0.5], curfd)
23235    yb = y_bounds(curfd)
23236    if fneq(yb[0], -0.5) or fneq(yb[1], 0.5)
23237      snd_display("y_bounds: %s?", yb)
23238    end
23239    set_cursor(curloc, curfd, 0)
23240    cl = cursor(curfd, 0)
23241    if cl != curloc and (res = framples(curfd, 0)) > curloc
23242      snd_display("cursor %s != %s (framples: %s)?", cl, curloc, res)
23243      curloc = cursor(curfd, 0)
23244    end
23245    if curloc >= framples(curfd, 0)
23246      curloc = 0
23247    end
23248    id = Snd.catch(:all, -1) do add_mark(curloc, curfd) end.car
23249    if number?(id) and id != -1
23250      cl = mark_sample(id)
23251      new_marks = Snd.marks(curfd, 0).length
23252      if cl != curloc
23253        snd_display("mark %s != %s?", cl, curloc)
23254      end
23255      if new_marks != (old_marks + 1)
23256        snd_display("marks %s %s?", new_marks, old_marks)
23257      end
23258      new_id = find_mark(curloc, curfd)
23259      if (not mark?(new_id)) or id != new_id
23260        snd_display("find_mark (by sample): %s %s (%s for %s %s)?",
23261                    id, new_id, curloc, mark_sample(id), mark_sample(new_id))
23262      end
23263      set_mark_name(id, "hiho")
23264      new_id = find_mark("hiho", curfd)
23265      if (not mark?(new_id)) or id != new_id
23266        snd_display("find_mark (by name): %s %s (%s for %s %s)?", id, new_id)
23267      end
23268      if (res = mark_name(id)) != "hiho"
23269        snd_display("mark_name: %s?", res)
23270      end
23271      set_mark_sample(id, [0, curloc - 100].max)
23272      cl = mark_sample(id)
23273      if cl != [0, curloc - 100].max
23274        snd_display("set_mark_sample %s != %s?", cl, curloc)
23275      end
23276      delete_mark(id)
23277    end
23278    if duration(curfd) > 1.2
23279      set_x_bounds([1.0, 1.1], curfd)
23280    end
23281    if framples(curfd) > 25
23282      add_mark(10, curfd)
23283      add_mark(20, curfd)
23284      key(key_to_int(?m), 0, curfd)
23285      set_cursor(0, curfd)
23286      new_marks = Snd.marks(curfd, 0).length
23287      delete_marks(curfd)
23288      if duration(curfd) > 0.0
23289        set_x_bounds([0.0, [duration(curfd), 0.1].min], curfd)
23290      end
23291      set_y_bounds([-1.0, 1.0], curfd)
23292      if Snd.marks(curfd, 0).length > 0 or new_marks != (old_marks + 3)
23293        snd_display("delete marks: %s %s?", new_marks, old_marks)
23294      end
23295    end
23296    revert_sound
23297    old_settings = selection_creates_region()
23298    set_selection_creates_region(true)
23299    reg = select_all()
23300    Snd.catch do
23301      if region?(reg) and selection?()
23302        r1 = region_rms(regions.first)
23303        r2 = selection_rms
23304        snd_test_neq(r1, r2, "region_rms")
23305        set_selection_creates_region(old_settings)
23306      end
23307    end
23308    Snd.catch do
23309      if region?(regions[2])
23310        play(regions[2], :wait, true)
23311      end
23312    end
23313    Snd.catch do
23314      mix_region(regions[2])
23315    end
23316    framples < 100000 and play(selected_sound, :wait, true)
23317    scale_to(0.1, choose_fd.call)
23318    scale_by(2.0, choose_fd.call)
23319    save_controls
23320    set_amp_control(0.5)
23321    test_panel(:amp_control)
23322    restore_controls
23323    Snd.catch do
23324      cfd = choose_fd.call
23325      safe_make_selection(1000, 2000, cfd)
23326      src_selection(0.5)
23327      undo_edit(1, cfd)
23328      cfd = choose_fd.call
23329      safe_make_selection(1000, 2000, cfd)
23330      src_selection(-1.5)
23331      undo_edit(1, cfd)
23332      cfd = choose_fd.call
23333      safe_make_selection(1000, 2000, cfd)
23334      scale_selection_by(0.5)
23335      undo_edit(1, cfd)
23336      cfd = choose_fd.call
23337      safe_make_selection(1000, 2000, cfd)
23338      env_selection([0, 0, 1, 1, 2, 0])
23339      undo_edit(1, cfd)
23340      cfd = choose_fd.call
23341      safe_make_selection(1000, 2000, cfd)
23342      scale_selection_to(0.5)
23343      reverse_selection
23344      undo_edit(2, cfd)
23345      Snd.regions.length > 2 and forget_region(regions[2])
23346    end
23347    open_files.apply(:revert_sound)
23348    Snd.catch do
23349      cfd = open_files.first
23350      set_sync(1, cfd)
23351      open_files.length > 1 and set_sync(1, open_files[1])
23352      safe_make_selection(1000, 2000, cfd)
23353      src_selection(0.5)
23354      undo_edit(1, cfd)
23355      safe_make_selection(1000, 2000, cfd)
23356      src_selection(-1.5)
23357      undo_edit(1, cfd)
23358      safe_make_selection(1000, 2000, cfd)
23359      env_selection([0, 0, 1, 1, 2, 0])
23360      undo_edit(1, cfd)
23361      safe_make_selection(1000, 2000, cfd)
23362      reverse_selection
23363      undo_edit(1, cfd)
23364      safe_make_selection(1000, 2000, cfd)
23365      filter_selection([0, 0, 0.1, 1, 1, 0], 40)
23366      undo_edit(1, cfd)
23367      safe_make_selection(1000, 2000, cfd)
23368      convolve_selection_with("oboe.snd")
23369      undo_edit(1, cfd)
23370      safe_make_selection(1000, 2000, cfd)
23371      smooth_selection
23372      undo_edit(1, cfd)
23373      safe_make_selection(1000, 2000, cfd)
23374      scale_selection_by(0.5)
23375      undo_edit(1, cfd)
23376      scale_selection_to(0.5)
23377      reverse_selection
23378      undo_edit(2, cfd)
23379      src_selection([0, 0.5, 1, 1])
23380      undo_edit
23381      revert_sound(cfd)
23382      open_files.length > 1 and revert_sound(open_files[1])
23383    end
23384    #
23385    frms = framples()
23386    if frms > 1 and frms < 10000
23387      make_region(0, frms)
23388      convolve_selection_with("fyow.snd", 0.5)
23389      play(selected_sound, :wait, true)
23390    end
23391    if frms > 1 and frms < 10000
23392      convolve_with("fyow.snd", 0.25)
23393    end
23394    insert_sound("oboe.snd")
23395    $graph_hook.reset_hook!
23396    $after_transform_hook.reset_hook!
23397    open_files.apply(:revert_sound)
23398    #
23399    ind = choose_fd.call
23400    select_sound(ind)
23401    [[lambda { |beg| insert_sound("2a.snd", beg) },   lambda { |beg| insert_sound("4a.snd", beg) }],
23402     [lambda { |beg| reverse_sound },                 lambda { |beg| reverse_sound }],
23403     [lambda { |beg|
23404        if framples(ind) < 10000
23405          convolve_with("2a.snd", 0.5)
23406        else
23407          scale_by(2.0)
23408        end },  lambda { |beg| src_sound(2.0) }],
23409     [lambda { |beg| env_sound([0, 0, 1, 1, 2, 0]) }, lambda { |beg| env_sound([0, 0, 1, 1]) }],
23410     [lambda { |beg| smooth_sound },                  lambda { |beg| insert_silence(beg, 100) }]
23411    ].each do |func, func1|
23412      pad_channel(0, 100, ind, 0)
23413      func.call(0)
23414      pad_channel(0, 100, ind, 0)
23415      func1.call(0)
23416      revert_sound(ind)
23417      if channels(ind) > 1
23418        pad_channel(0, 100, ind, 1)
23419        func.call(0)
23420        pad_channel(0, 100, ind, 1)
23421        func1.call(0)
23422        revert_sound(ind)
23423      end
23424      delete_samples(0, 1000, ind, 0)
23425      func.call(2 * framples(ind, 0))
23426      delete_samples(0, 1000, ind, 0)
23427      func1.call(2 * framples(ind, 0))
23428      revert_sound(ind)
23429      if channels(ind) > 1
23430        delete_samples(0, 1000, ind, 1)
23431        func.call(2 * framples(ind, 1))
23432        delete_samples(0, 1000, ind, 1)
23433        func1.call(2 * framples(ind, 1))
23434        revert_sound(ind)
23435      end
23436    end
23437    #
23438    ind = open_sound("z.snd")
23439    restore_controls
23440    if framples(ind).nonzero?
23441      snd_display("framples z.snd: %s?", framples(ind))
23442    end
23443    if samples != false
23444      snd_display("samples of empty file (z): %s?", samples)
23445    end
23446    if channel2vct != false
23447      snd_display("channel2vct of empty file (z): %s?", channel2vct)
23448    end
23449    if fneq(maxamp(ind), 0.0)
23450      snd_display("maxamp z.snd: %s?", maxamp(ind))
23451    end
23452    if fneq(sample(100, ind), 0.0)
23453      snd_display("sample 100 z.snd: %s?", sample(100, ind))
23454    end
23455    scale_by(2.0)
23456    if (res = edit_position(ind, 0)).nonzero?
23457      snd_display("scale z: %s?", res)
23458    end
23459    env_sound([0, 0, 1, 1])
23460    if (res = edit_position(ind, 0)).nonzero?
23461      snd_display("env_sound z: %s?", res)
23462    end
23463    smooth_sound
23464    if (res = edit_position(ind, 0)).nonzero?
23465      snd_display("smooth_sound z: %s?", res)
23466    end
23467    reverse_sound
23468    if (res = edit_position(ind, 0)).nonzero?
23469      snd_display("reverse_sound z: %s?", res)
23470    end
23471    src_sound(2.0)
23472    if (res = edit_position(ind, 0)).nonzero?
23473      snd_display("src_sound z: %s?", res)
23474    end
23475    insert_sound("z.snd")
23476    if (res = edit_position(ind, 0)).nonzero?
23477      snd_display("insert_sound z: %s?", res)
23478    end
23479    mix("z.snd")
23480    if (res = edit_position(ind, 0)).nonzero?
23481      snd_display("mix z: %s?", res)
23482    end
23483    filter_sound(make_one_zero(:a0, 2.0, :a1, 0.0))
23484    if (res = edit_position(ind, 0)).nonzero?
23485      snd_display("filter_sound z: %s?", res)
23486    end
23487    if fneq(res = mus_sound_duration("z.snd"), 0.0)
23488      snd_display("mus_sound_duration z.snd: %s?", res)
23489    end
23490    Snd.catch(:io_error) do convolve_with("z.snd", 1.0) end
23491    if (res = edit_position(ind, 0)).nonzero?
23492      snd_display("convolve_with z: %s?", res)
23493    end
23494    if (res = Snd.catch do find_channel(lambda do |y| y > 0.1 end) end).first != :no_such_sample
23495      snd_display("find z: %s", res.inspect)
23496    end
23497    if (res = Snd.catch do count_matches(lambda do |y| y > 0.1 end) end).first != :no_such_sample
23498      snd_display("count_matches z: %s", res.inspect)
23499    end
23500    reader = make_sampler(0)
23501    val = next_sample(reader)
23502    if fneq(val, 0.0)
23503      snd_display("sampler z.snd: %s?", val)
23504    end
23505    unless string?(reader.to_s)
23506      snd_display("z.snd reader: %s?", reader.to_s)
23507    end
23508    if (res = cursor_position) != [0, 0]
23509      snd_display("cursor_position z: %s?", res)
23510    end
23511    if (res = cursor).nonzero?
23512      snd_display("cursor z: %ws?", res)
23513    end
23514    outer = make_player(ind, 0)
23515    pl = make_player(ind, 0)
23516    add_player(pl)
23517    start_playing(1, 22050, false)
23518    revert_sound(ind)
23519    set_transform_graph?(true, ind, 0)
23520    $lisp_graph_hook.add_hook!("display_energy") do |snd, chn| display_energy(snd, chn) end
23521    set_x_bounds([0.0, 0.01])
23522    set_sample(0, 0.5)
23523    set_x_bounds([0.0, 0.001])
23524    close_sound(ind)
23525    if (res = Snd.catch do add_player(outer) end).first != :no_such_player
23526      snd_display("dangling player: %s", res.inspect)
23527    end
23528    if res = channel_amp_envs("z.snd", 0, 100)
23529      snd_display("channel_amp_envs of empty file: %s?", res)
23530    end
23531    #
23532    zz = view_sound("z.snd")
23533    select_sound(zz)
23534    mix("4.aiff").car
23535    add_mark(0)
23536    add_mark(1200)
23537    delete_marks
23538    revert_sound(zz)
23539    editctr = edit_position(zz)
23540    if (res = edit_position(zz)).nonzero?
23541      snd_display("revert_sound edit_position: %s?", res)
23542    end
23543    s8_snd = (File.exist?("s8.snd") ? "s8.snd" : "oboe.snd")
23544    as_one_edit_rb do
23545      mix(s8_snd, 24000)
23546      reg = select_all
23547      if selection?
23548        filter_selection([0, 0, 0.2, 1, 0.5, 0, 1, 0], 40)
23549        delete_selection
23550        mix_region(reg)
23551      end
23552    end
23553    if (res = edit_position(zz)) != 1
23554      snd_display("as_one_edit mix zz: %s -> %s?", editctr, res)
23555    end
23556    close_sound(zz)
23557    s8 = view_sound(s8_snd)
23558    select_sound(s8)
23559    if channels(s8) == 8
23560      select_channel(5)
23561      if (not number?(selected_channel)) or selected_channel != 5
23562        snd_display("select_channel: %s?", select_channel)
23563      end
23564    end
23565    editctr = edit_position
23566    as_one_edit_rb do
23567      reg = select_all
23568      delete_selection
23569      mix("4.aiff")
23570      set_sync(1)
23571      mix("oboe.snd", 60000)
23572      scale_by(0.1)
23573      set_sync(1)
23574      if channels(s8) > 3
23575        select_channel(3)
23576      end
23577      if region?(reg)
23578        insert_region(reg, 80000)
23579      end
23580    end
23581    snd_test_neq(edit_position(), editctr + 1, "as_one_edit s8")
23582    revert_sound(s8)
23583    close_sound(s8)
23584    #
23585    cfd = choose_fd.call
23586    if channels(cfd) > 1
23587      uval = random(3)
23588      set_channel_style(uval, cfd)
23589      snd_test_neq(channel_style(cfd), uval, "channel_style")
23590    end
23591    if framples(cfd) < 200000
23592      src_sound(2.5, 1.0, cfd)
23593      src_sound(-2.5, 1.0, cfd)
23594      src_sound(0.5, 1.0, cfd)
23595      revert_sound(cfd)
23596      src_sound(-0.5, 1.0, cfd)
23597      src_sound([0, 0.5, 1, 1.5], 1.0, cfd)
23598      if framples(cfd) > 0
23599        src_sound(make_env([0, 0.5, 1, 1.5], :length, framples(cfd)), 1.0, cfd)
23600      end
23601      revert_sound(cfd)
23602      filter_sound([0, 1, 0.2, 0, 0.5, 1, 1, 0], 20, cfd)
23603      filter_sound([0, 0, 0.1, 0, 0.11, 1, 0.12, 0, 1, 0], 2048, cfd)
23604      env_sound([0, 0, 0.5, 1, 1, 0], 0, framples(cfd), 1.0, cfd)
23605      insert_sample(1200, 0.1, cfd)
23606      snd_test_neq(sample(1200, cfd), 0.1, "insert_sample(looped)")
23607    end
23608    revert_sound(cfd)
23609    #
23610    cfd = open_sound("obtest.snd")
23611    select_sound(cfd)
23612    cfd2 = open_sound("pistol.snd")
23613    select_sound(cfd2)
23614    set_amp_control(0.5)
23615    set_speed_control(2.0)
23616    test_panel(:speed_control)
23617    apply_controls
23618    framples < 100000 and play(selected_sound, :wait, true)
23619    if fneq(res1 = reverb_control_decay(cfd), res2 = reverb_control_decay)
23620      snd_display("reverb_control_decay local: %s, global: %s?", res1, res2)
23621    end
23622    set_reverb_control?(true)
23623    set_reverb_control_scale(0.2)
23624    test_panel(:reverb_control_scale)
23625    test_panel(:reverb_control_length)
23626    test_panel(:reverb_control_lowpass)
23627    test_panel(:reverb_control_feedback)
23628    apply_controls
23629    framples < 100000 and play(selected_sound, :wait, true)
23630    set_contrast_control?(true)
23631    set_contrast_control(0.5)
23632    test_panel(:contrast_control)
23633    test_panel(:contrast_control_amp)
23634    apply_controls
23635    framples < 100000 and play(selected_sound, :wait, true)
23636    set_expand_control?(true)
23637    set_expand_control(2.5)
23638    test_panel(:expand_control)
23639    test_panel(:expand_control_length)
23640    test_panel(:expand_control_hop)
23641    test_panel(:expand_control_ramp)
23642    apply_controls
23643    framples < 100000 and play(selected_sound, :wait, true)
23644    set_filter_control?(true)
23645    set_filter_control_order(40)
23646    test_panel(:filter_control_order)
23647    set_filter_control_envelope([0, 0, 0.1, 1, 0.2, 0, 1, 0])
23648    filter_control_envelope
23649    apply_controls
23650    framples < 100000 and play(selected_sound, :wait, true)
23651    set_amp_control(1.5)
23652    test_panel(:amp_control)
23653    apply_controls
23654    framples < 100000 and play(selected_sound, :wait, true)
23655    swap_channels(cfd, 0, cfd2, 0)
23656    set_amp_control(0.75, true)
23657    test_panel(:amp_control)
23658    if (res = amp_control(cfd2) - 0.75).abs > 0.05
23659      snd_display("set_amp_control 0.75, true: %s?", res)
23660    end
23661    set_contrast_control_amp(0.75, true)
23662    if fneq(res = contrast_control_amp(cfd2), 0.75)
23663      snd_display("set_contrast_control_amp 0.75, true: %s?", res)
23664    end
23665    set_contrast_control_bounds([2.0, 3.0], cfd2)
23666    unless vequal(res = contrast_control_bounds(cfd2), [2.0, 3.0])
23667      snd_display("set_contrast_control_bound (cfd2): %s?", res)
23668    end
23669    set_expand_control_length(0.025, true)
23670    if fneq(res = expand_control_length(cfd2), 0.025)
23671      snd_display("set_expand_control_length 0.025, true: %s?", res)
23672    end
23673    set_expand_control_hop(0.025, true)
23674    if fneq(res = expand_control_hop(cfd2), 0.025)
23675      snd_display("set_expand_control_hop 0.025, true: %s?", res)
23676    end
23677    set_expand_control_jitter(0.025, true)
23678    if fneq(res = expand_control_jitter(cfd2), 0.025)
23679      snd_display("set_expand_control_jitter 0.025, true: %s?", res)
23680    end
23681    set_expand_control_ramp(0.025, true)
23682    if fneq(res = expand_control_ramp(cfd2), 0.025)
23683      snd_display("set_expand_control_ramp 0.025, true: %s?", res)
23684    end
23685    clone = clone_sound_as("/tmp/cloned.snd", cfd2)
23686    if framples(cfd2) != framples(clone)
23687      snd_display("clone framples: %s %s?", framples(cfd2), framples(clone))
23688    end
23689    close_sound(clone)
23690    delete_file("/tmp/cloned.snd")
23691    mus_sound_forget("/tmp/cloned.snd")
23692    close_sound(cfd2)
23693    close_sound(cfd)
23694    edit_hook.add_hook!("snd-test") do | | false end
23695    editctr = edit_position
23696    as_one_edit_rb do
23697      set_sample(200, 0.2)
23698      set_sample(300, 0.3)
23699    end
23700    if (res = edit_position) != editctr + 1
23701      snd_display("as_one_edit: %s -> %s?", editctr, res)
23702    end
23703    as_one_edit_rb do false end
23704    if (res = edit_position) != editctr + 1
23705      snd_display("as_one_edit nil: %s -> %s?", editctr, res)
23706    end
23707    delete_sample(250)
23708    undo_hook.add_hook!("snd-test") do | | false end
23709    undo_edit
23710    delete_sample(250)
23711    undo_edit
23712    as_one_edit_rb do
23713      set_sample(20, 0.2)
23714      set_sample(30, 0.3)
23715    end
23716    undo_edit(1)
23717    as_one_edit_rb do
23718      set_sample(2, 0.2)
23719      as_one_edit_rb do set_sample(3, 0.3) end
23720    end
23721    undo_edit(2)
23722    undo_hook.reset_hook!
23723    edit_hook.reset_hook!
23724    sw_msg = "sw_msg"
23725    $snd_warning_hook.add_hook!("snd-test") do |msg|
23726      sw_msg = msg
23727      if msg != "hiho"
23728        snd_display("$snd_warning_hook: %s?", msg)
23729      end
23730      true
23731    end
23732    snd_warning("hiho")
23733    if sw_msg != "hiho"
23734      snd_display("$snd_warning_hook not called (%s != hiho)?", sw_msg)
23735    end
23736    $snd_error_hook.reset_hook!
23737    $snd_warning_hook.reset_hook!
23738    if proc? $my_snd_error_hook
23739      $snd_error_hook.add_hook!("sndtestrc", &$my_snd_error_hook)
23740    end
23741    if proc? $my_mus_error_hook
23742      $mus_error_hook.add_hook!("sndtestrc", &$my_mus_error_hook)
23743    end
23744    $name_click_hook.add_hook!("snd-test") do |n| true end
23745    redo_edit(1)
23746    $name_click_hook.reset_hook!
23747    set_transform_graph?(true)
23748    test_channel(:transform_graph?)
23749    test_channel(:time_graph?)
23750    test_channel(:lisp_graph?)
23751    test_channel(:framples)
23752    test_channel(:cursor)
23753    test_channel(:cursor_size)
23754    test_channel(:cursor_style)
23755    test_channel(:tracking_cursor_style)
23756    test_channel(:left_sample)
23757    test_channel(:right_sample)
23758    test_channel(:squelch_update)
23759    test_channel(:x_zoom_slider)
23760    test_channel(:y_zoom_slider)
23761    test_channel(:x_position_slider)
23762    test_channel(:y_position_slider)
23763    test_channel(:edit_position)
23764    test_channel(:maxamp)
23765    test_channel(:edit_hook)
23766    test_channel(:after_edit_hook)
23767    test_channel(:undo_hook)
23768    func = lambda do |len, fd|
23769      steps = len / 16
23770      step = 1.0 / len
23771      v = Vct.new(len, 0.0)
23772      v.length.times do |i|
23773        val = next_sample(fd).abs
23774        bin = (val * 16.0).round
23775        if bin < steps
23776          steps.times do |j| v[j + bin] += step end
23777        end
23778      end
23779      v
23780    end
23781    set_transform_type(add_transform("histogram", "bins", 0.0, 1.0, func))
23782    set_x_bounds([0.1, 0.2])
23783    set_transform_type($fourier_transform)
23784    set_x_bounds([0.1, 0.2])
23785    $lisp_graph_hook.add_hook!("display_energy") do |snd, chn|
23786      display_energy(snd, chn)
23787    end
23788    $graph_hook.reset_hook!
23789    if channels() == 2
23790      $graph_hook.add_hook!("correlate") do |snd, chn, y0, y1|
23791        display_correlate(snd, chn, y0, y1)
23792      end
23793      set_x_bounds([0.1, 0.12])
23794      set_x_bounds([0.1, 0.2])
23795      $graph_hook.remove_hook!("correlate")
23796    end
23797    set_lisp_graph?(false)
23798    sum_of_squares = 0.0
23799    buffer = Vct.new(128)
23800    position = 0
23801    current_sample = 0
23802    chan_samples = framples
23803    map_chan_rb do |y|
23804      old_y = buffer[position]
23805      sum_of_squares = (sum_of_squares + y * y) - old_y * old_y
23806      buffer[position] = y
23807      position += 1
23808      if position == 128
23809        position = 0
23810      end
23811      current_sample += 1
23812      if sum_of_squares > 0.01
23813        if current_sample == chan_samples
23814          Vct.new(128) do |i|
23815            final_y = buffer[position]
23816            val = sum_of_squares > 0.01 ? final_y : 0.0
23817            sum_of_squares = sum_of_squares - final_y * final_y
23818            position += 1
23819            if position == 128
23820              position = 0
23821            end
23822            val
23823          end
23824        else
23825          old_y
23826        end
23827      else
23828        false
23829      end
23830    end
23831    #
23832    maxval1 = maxamp + 0.01
23833    unless every_sample? do |y| y < maxval1 end
23834      res = scan_channel(lambda do |y| y >= maxval1 end)
23835      snd_display("%s, every_sample?: %s %s [%s: %s]?",
23836                  short_file_name, maxval1, res, cursor, sample(cursor))
23837      edit_position.times do |i|
23838        snd_display("%s: %s %s", i, maxamp(false, 0, i), edit_fragment(i))
23839      end
23840    end
23841    map_chan(echo(0.5, 0.75), 0, 60000)
23842    $after_transform_hook.reset_hook!
23843    $lisp_graph_hook.reset_hook!
23844    $lisp_graph_hook.add_hook!("snd-test") do |snd, chn| graph(vct(0, 1, 2)) end
23845    Snd.sounds.each do |snd| set_sync((random(3)), snd) end
23846    $graph_hook.add_hook!("superimpose_ffts") do |snd, chn, y0, y1|
23847      superimpose_ffts(snd, chn, y0, y1)
23848    end
23849    10.times do |i|
23850      Snd.sounds.each do |snd|
23851        if framples(snd) > 0
23852          dur = (framples(snd) / srate(snd).to_f).floor.to_f
23853          start = [0.0, [dur - 0.1, random(dur)].min].max
23854          if dur > 0.0
23855            set_x_bounds([start, [start + 0.1, dur].min], snd, 0)
23856          end
23857        end
23858      end
23859    end
23860    $graph_hook.reset_hook!
23861    $lisp_graph_hook.reset_hook!
23862    #
23863    # new variable settings
23864    #
23865    [[:amp_control, true, 0.1, 1.0],
23866     [:auto_update, false, false, true],
23867     [:channel_style, false, 0, 2],
23868     [:color_cutoff, false, 0.0,0.2],
23869     [:color_inverted, false, false, true],
23870     [:color_scale, false, 0.1, 1000.0],
23871     [:contrast_control, true, 0.0, 1.0],
23872     [:contrast_control_amp, true, 0.0, 1.0],
23873     [:contrast_control?, true, false, true],
23874     [:auto_update_interval, false, 60.0, 120.0],
23875     [:cursor_update_interval, false, 0.05, 0.1],
23876     [:cursor_location_offset, false, 0, 1024],
23877     [:with_tracking_cursor, false, false, true],
23878     [:cursor_size, false, 15, 25],
23879     [:cursor_style, false, Cursor_cross, Cursor_line],
23880     [:tracking_cursor_style, false, Cursor_line, Cursor_cross],
23881     [:clipping, false, false, true],
23882     [:dot_size, false, 1, 10],
23883     [:enved_base, false, 0.01, 100.0],
23884     [:enved_clip?, false, false, true],
23885     [:enved_in_dB, false, false, true],
23886     [:enved_style, false, Envelope_linear, Envelope_exponential],
23887     [:enved_power, false, 3.0, 3.5],
23888     [:enved_target, false, 0, 2],
23889     [:enved_wave?, false, false, true],
23890     [:expand_control, true, 0.1, 5.0],
23891     [:expand_control_hop, true, 0.01, 0.5],
23892     [:expand_control_jitter, true, 0.01, 0.5],
23893     [:expand_control_length, true, 0.1, 0.25],
23894     [:expand_control_ramp, true, 0.1, 0.4],
23895     [:expand_control?, true, false, true],
23896     [:fft_window_alpha, false, 0.0, 1.0],
23897     [:fft_window_beta, false, 0.0, 1.0],
23898     [:fft_log_frequency, false, false, true],
23899     [:fft_log_magnitude, false, false, true],
23900     [:fft_with_phases, false, false, true],
23901     [:transform_size, false, 16, 128],
23902     [:transform_graph_type, false, Graph_once, Graph_as_spectrogram],
23903     [:transform_graph?, true, false, true],
23904     [:filter_control_in_dB, true, false, true],
23905     [:filter_control_in_hz, true, false, true],
23906     [:filter_control_order, true, 2, 400],
23907     [:filter_control?, true, false, true],
23908     # [:graph_cursor, false, 0, 35],
23909     [:time_graph_style, false, 0, 4],
23910     [:lisp_graph_style, false, 0, 4],
23911     [:transform_graph_style, false, 0, 4],
23912     [:graphs_horizontal, false, false, true],
23913     [:max_transform_peaks, false, 1, 100],
23914     [:max_regions, false, 1, 32],
23915     [:min_dB, false, -120.0, -30.0],
23916     [:log_freq_start, false, 50.0, 5.0],
23917     [:selection_creates_region, false, false, true],
23918     [:transform_normalization, false, Dont_normalize, Normalize_globally],
23919     [:play_arrow_size, false, 2, 32],
23920     [:print_length, false, 2, 32],
23921     [:region_graph_style, false, Graph_lines, Graph_lollipops],
23922     [:reverb_control_decay, false, 0.0, 2.0],
23923     [:reverb_control_feedback, true, 1.0, 1.1],
23924     [:reverb_control_length, true, 1.0, 2.0],
23925     [:reverb_control_lowpass, true, 0.2, 0.99],
23926     [:reverb_control_scale, true, 0.0, 0.2],
23927     [:reverb_control?, true, false, true],
23928     [:show_axes, false, 0, 2],
23929     [:show_transform_peaks, false, false, true],
23930     [:show_indices, false, false, true],
23931     [:show_marks, false, false, true],
23932     [:show_mix_waveforms, true, false, true],
23933     [:show_selection_transform, false, false, true],
23934     [:show_y_zero, false, false, true],
23935     [:show_grid, false, false, true],
23936     [:grid_density, true, 0.1, 4.0],
23937     [:show_sonogram_cursor, false, false, true],
23938     [:sinc_width, false, 4, 100],
23939     [:spectrum_end, false, 0.5, 0.8],
23940     [:spectro_hop, false, 2, 20],
23941     [:spectrum_start, false, 0.0, 0.1],
23942     [:spectro_x_angle, false, 0.0, 90.0],
23943     [:spectro_x_scale, false, 0.1, 2.0],
23944     [:spectro_y_angle, false, 0.0, 90.0],
23945     [:spectro_y_scale, false, 0.1, 2.0],
23946     [:spectro_z_angle, false, 0.0, 359.0],
23947     [:spectro_z_scale, false, 0.1, 0.2],
23948     [:speed_control, true, 0.1, 5.0],
23949     [:speed_control_style, false, 0, 2],
23950     [:speed_control_tones, false, 2, 100],
23951     [:sync, true, 0, 5],
23952     [:sync_style, false, 0, 3],
23953     [:with_verbose_cursor, false, false, true],
23954     [:wavelet_type, false, 0, 10],
23955     [:time_graph?, true, false, true],
23956     [:x_axis_style, false, 0, 2],
23957     [:beats_per_minute, false, 60.0, 120.0],
23958     [:beats_per_measure, false, 4, 120],
23959     [:zero_pad, false, 0, 2],
23960     [:zoom_focus_style, false, 0, 3]].each do |func, index_p, minval, maxval|
23961      index = index_p ? choose_fd.call : false
23962      if index
23963        if minval == false
23964          set_snd_func(func, true, index)
23965        else
23966          val = minval + (maxval - minval) * random(1.0)
23967          set_snd_func(func, (integer?(minval) and val.floor or val), index)
23968        end
23969      else
23970        if minval == false
23971          set_snd_func(func, true)
23972        else
23973          val = minval + (maxval - minval) * random(1.0)
23974          set_snd_func(func, (integer?(minval) and val.floor or val))
23975        end
23976      end
23977    end
23978    if transform_type != $fourier_transform
23979      set_transform_graph?(false, true, true)
23980      set_transform_size([transform_size, 128].min)
23981    end
23982    open_files.apply(:close_sound)
23983    set_sync_style(Sync_none)
23984    set_mus_rand_seed(1234)
23985    if mus_rand_seed != 1234
23986      snd_display("mus_rand_seed: %s (1234)?", mus_rand_seed)
23987    end
23988    val = mus_random(1.0)
23989    val1 = mus_random(1.0)
23990    if fneq(val, -0.7828) or fneq(val1, -0.8804)
23991      snd_display("mus_random: %s %s?", val, val1)
23992    end
23993    if mus_rand_seed == 1234
23994      snd_display("mus_rand_seed: %s?", mus_rand_seed)
23995    end
23996    set_mus_rand_seed(1234)
23997    val = mus_random(1.0)
23998    val1 = mus_random(1.0)
23999    if fneq(val, -0.7828) or fneq(val1, -0.8804)
24000      snd_display("mus_random repeated: %s %s?", val, val1)
24001    end
24002    $after_open_hook.reset_hook!
24003    $close_hook.reset_hook!
24004    $open_hook.reset_hook!
24005  end
24006end
24007
24008# ---------------- test 15: chan-local vars ----------------
24009
24010def prefix_it(n, id)
24011  key(key_to_int(?u), 0, id)
24012  n.to_s.each_byte do |c| key(c, 0, id) end
24013end
24014
24015def prefix_uit(n, id)
24016  n.to_s.each_byte do |c| key(c, 0, id) end
24017end
24018
24019def test_history_channel(func, new_val, snd1, snd2, snd3)
24020  test_equal = lambda do |nv, new_val|
24021    if float?(nv)
24022      (not fneq(nv, new_val))
24023    else
24024      nv == new_val
24025    end
24026  end
24027  chan_equal_p = lambda do |vals, new_val|
24028    if vals.null?
24029      true
24030    elsif list_p(vals)
24031      (not vals.detect do |val| val != new_val end)
24032    else
24033      test_equal.call(vals, new_val)
24034    end
24035  end
24036  test_channel(func)
24037  old_value = snd_func(func)
24038  old_chan_value = snd_func(func, snd1, 0)
24039  set_snd_func(func, new_val, snd1, 0)
24040  unless test_equal.call(nv = snd_func(func, snd1, 0), new_val)
24041    snd_display_prev_caller("%s: set_%s[1]: %s %s?", get_func_name, func, new_val, nv)
24042  end
24043  set_snd_func(func, new_val, snd3, 2)
24044  unless test_equal.call(nv = snd_func(func, snd3, 2), new_val)
24045    snd_display_prev_caller("%s: set_%s[2]: %s %s?", get_func_name, func, new_val, nv)
24046  end
24047  unless test_equal.call(old_value, new_val)
24048    if test_equal.call(nv = snd_func(func, snd3, 1), new_val)
24049      snd_display_prev_caller("%s: set_%s[3]: %s %s?", get_func_name, func, new_val, nv)
24050    end
24051  end
24052  set_snd_func(func, new_val, snd2, true)
24053  unless test_equal.call(nv = snd_func(func, snd2, 1), new_val)
24054    snd_display_prev_caller("%s: set_%s[4]: %s %s?", get_func_name, func, new_val, nv)
24055  end
24056  set_snd_func(func, new_val)
24057  unless chan_equal_p.call(nv = snd_func(func, true, true).flatten, new_val)
24058    snd_display_prev_caller("%s: set_%s[5]: %s %s?", get_func_name, func, new_val, nv)
24059  end
24060  set_snd_func(func, old_value)
24061end
24062
24063def freq_peak(beg, ind, size)
24064  interpolated_peak_offset = lambda do |la, ca, ra|
24065    pk = 0.001 + [la, ca, ra].max
24066    logla = log([la, 0.0000001].max / pk) / log(10)
24067    logca = log([ca, 0.0000001].max / pk) / log(10)
24068    logra = log([ra, 0.0000001].max / pk) / log(10)
24069    0.5 * (logla - logra) / ((logla + logra) - 2 * logca)
24070  end
24071  data = channel2vct(beg, size, ind, 0)
24072  spectr = snd_spectrum(data, Blackman2_window, size)
24073  peak0 = 0.0
24074  pk0loc = 0
24075  (size / 2).times do |i|
24076    if spectr[i] > peak0
24077      peak0 = spectr[i]
24078      pk0loc = i
24079    end
24080  end
24081  [((pk0loc + (pk0loc > 0 ? interpolated_peak_offset.call(spectr[pk0loc - 1],
24082                                                          spectr[pk0loc],
24083                                                          spectr[pk0loc + 1]) :
24084                       0.0)) * srate) / size,
24085   peak0]
24086end
24087
24088def smoother(y0, y1, num)
24089  angle = y1 > y0 ? PI : 0.0
24090  off = 0.5 * (y0 + y1)
24091  incr = PI / num
24092  scale = 0.5 * (y1 - y0).abs
24093  Vct.new(num + 1) do |i| off + scale * cos(angle + i * incr) end
24094end
24095
24096def test_selection(ind, beg, len, scaler)
24097  set_selection_member?(true, ind, 0)
24098  set_selection_position(beg)
24099  set_selection_framples(len)
24100  scale_selection_by(scaler)
24101  diff = 0.0
24102  pos = edit_position(ind, 0)
24103  old_reader = make_sampler(beg, ind, 0, 1, pos - 1)
24104  new_reader = make_sampler(beg, ind, 0, 1, pos)
24105  len.times do |i|
24106    ov = scaler * old_reader.call
24107    nv = next_sample(new_reader)
24108    val = (ov - nv).abs
24109    diff += val
24110  end
24111  if diff > 0.0
24112    snd_display_prev_caller("diff (%s %s): %s?", beg, len, diff)
24113  end
24114  diff = 0.0
24115  100.times do |i|
24116    ov = next_sample(old_reader)
24117    nv = next_sample(new_reader)
24118    val = (ov - nv).abs
24119    diff += val
24120  end
24121  if diff > 0.0
24122    snd_display_prev_caller("zdiff (%s %s): %s?", beg, len, diff)
24123  end
24124  free_sampler(old_reader)
24125  free_sampler(new_reader)
24126end
24127
24128def test_selection_to(ind, beg, len, maxval)
24129  set_selection_member?(true, ind, 0)
24130  set_selection_position(beg)
24131  set_selection_framples(len)
24132  scale_selection_to(maxval)
24133  newmax = 0.0
24134  new_reader = make_sampler(beg, ind, 0)
24135  len.times do
24136    nv = next_sample(new_reader).abs
24137    if nv > newmax
24138      newmax = nv
24139    end
24140  end
24141  if fneq(newmax, maxval)
24142    snd_display_prev_caller("%s (%s %s) %s: %s?", get_func_name, beg, len, maxval, newmax)
24143  end
24144  free_sampler(new_reader)
24145end
24146
24147def play_with_amps_1(snd, *amps)
24148  channels(snd).times do |chn|
24149    player = make_player(snd, chn)
24150    unless player?(player)
24151      snd_display("player? %s -> false?", player)
24152    end
24153    unless players.member?(player)
24154      snd_display("player: %s, but players: %s?", player, players)
24155    end
24156    if (res = player_home(player)) != [snd, chn]
24157      snd_display("player_home %s %s?", res, [snd, chn])
24158    end
24159    set_amp_control(amps[chn], player)
24160    set_speed_control(0.5, player)
24161    set_expand_control?(true, player)
24162    set_expand_control(2.0, player)
24163    set_contrast_control?(true, player)
24164    set_contrast_control(1.0, player)
24165    set_reverb_control?(true, player)
24166    set_reverb_control_scale(0.02, player)
24167  end
24168  start_playing(channels(snd), srate(snd), false)
24169end
24170
24171def test_15_00
24172  snds = match_sound_files do |file|
24173    File.exist?(file) and              # for $tests > 1
24174    mus_sound_header_type(file) != Mus_raw and
24175    mus_sound_chans(file) == 1
24176  end
24177  if snds.length > 0
24178    obi = open_sound(snds.first)
24179    if all_chans != [[obi], [0]]
24180      snd_display("all_chans (1): %s?", all_chans)
24181    end
24182    snds1 = match_sound_files do |file|
24183      File.exist?(file) and            # for $tests > 1
24184      mus_sound_chans(file) == 2
24185    end
24186    if snds1.length > 0
24187      s2i = open_sound(snds1.first)
24188      res = all_chans
24189      req1 = [[obi, s2i, s2i], [0, 0, 1]]
24190      req2 = [[s2i, s2i, obi], [0, 1, 0]]
24191      if res != req1 and res != req2
24192        snd_test_neq(res, req1, "all_chans (2a)")
24193        snd_test_neq(res, req2, "all_chans (2b)")
24194      end
24195      res = finfo("oboe.snd")
24196      req = "oboe.snd: chans: 1, srate: 22050, Sun/Next, big endian short (16 bits), len: 2.305"
24197      snd_test_neq(res, req, "finfo")
24198      close_sound(s2i)
24199    else
24200      snd_display("No sound file found for s2i: %s", snds1)
24201    end
24202    close_sound(obi)
24203  else
24204    snd_display("No sound file found obi: %p", snds)
24205  end
24206  res = all_chans
24207  req = [[], []]
24208  snd_test_neq(res, req, "all_chans(0) (3)")
24209  obi = open_sound("oboe.snd")
24210  set_cursor(1000, obi)
24211  snd_test_neq(locate_zero(0.001), 1050, "locate_zero")
24212  $graph_hook.add_hook!("auto_dot") do |snd, chn, y0, y1|
24213    auto_dot(snd, chn, y0, y1)
24214  end
24215  $graph_hook.add_hook!("superimpose_ffts") do |snd, chn, y0, y1|
24216    superimpose_ffts(snd, chn, y0, y1)
24217  end
24218  set_transform_graph?(true, obi, 0)
24219  update_graphs
24220  #
24221  snds = match_sound_files do |file|
24222    File.exist?(file) and              # for $tests > 1
24223    mus_sound_chans(file) == 2
24224  end
24225  if snds.length > 0
24226    s2i = open_sound(snds.first)
24227    snd_test_neq(channels(s2i), 2, "match 2 got %s", short_file_name(s2i))
24228    update_graphs
24229    $graph_hook.remove_hook!("auto_dot")
24230    $graph_hook.remove_hook!("superimpose_ffts")
24231    set_transform_graph?(false, obi, 0)
24232    select_sound(obi)
24233    m1 = add_mark(100, obi, 0)
24234    first_mark_in_window_at_left
24235    res = left_sample(obi, 0) - 100
24236    snd_test_gt(res, 1, "first_mark_in_window_at_left %s", mark_sample(m1))
24237    delete_mark(m1)
24238    close_sound(s2i)
24239  else
24240    $graph_hook.remove_hook!("auto_dot")
24241    $graph_hook.remove_hook!("superimpose_ffts")
24242    snd_display("No sound file found: %p", snds)
24243  end
24244  safe_make_selection(1000, 2000, obi)
24245  delete_selection_and_smooth
24246  res = edit_fragment(0, obi, 0)
24247  req = ["", "init", 0, 50828]
24248  snd_test_neq(res, req, "edit_fragment (0)")
24249  res = edit_fragment(1, obi, 0)
24250  req = ["delete_samples(1000, 1001", "delete", 1000, 1001]
24251  snd_test_neq(res, req, "edit_fragment (1)")
24252  res = edit_fragment(2, obi, 0)
24253  req = ["delete-selection-and-smooth", "set", 968, 64]
24254  snd_test_neq(res, req, "edit_fragment (2)")
24255  #
24256  maxa = maxamp(obi)
24257  normalized_mix("pistol.snd", 1000, 0, obi, 0)
24258  nmaxa = maxamp(obi)
24259  snd_test_neq(nmaxa, maxa, "normalized_mix")
24260  revert_sound(obi)
24261  snds = match_sound_files do |file|
24262    File.exist?(file) and              # for $tests > 1
24263    mus_sound_chans(file) == 2 and
24264    mus_sound_framples(file) > 1000
24265  end
24266  if snds.length > 0
24267    s2i = open_sound(snds.first)
24268    res = channels(s2i)
24269    snd_test_neq(res, 2,
24270      "match_sound_files: 2+1000 got %s with", short_file_name(s2i))
24271    o1 = sample(1000, obi, 0)
24272    s1 = sample(1000, s2i, 0)
24273    s2 = sample(1000, s2i, 1)
24274    do_all_chans("double all samples") do |val|
24275      (val ? (2.0 * val) : false)
24276    end
24277    o11 = sample(1000, obi, 0)
24278    s11 = sample(1000, s2i, 0)
24279    s21 = sample(1000, s2i, 1)
24280    reso1 = 2.0 * o1
24281    ress1 = 2.0 * s1
24282    ress2 = 2.0 * s2
24283    if fneq(reso1, o11) or fneq(ress1, s11) or fneq(ress2, s21)
24284      snd_test_neq(reso1, o11, "do_all_chans (a)")
24285      snd_test_neq(ress1, s11, "do_all_chans (b)")
24286      snd_test_neq(ress2, s21, "do_all_chans (c)")
24287    end
24288    update_graphs
24289    m1 = maxamp(obi, 0)
24290    m2 = maxamp(s2i, 0)
24291    m3 = maxamp(s2i, 1)
24292    mc = [[obi, 0], [s2i, 0], [s2i, 1]].map do |snd, chn|
24293      maxamp(snd, chn)
24294    end
24295    if fneq(m1, mc[0]) or fneq(m2, mc[1]) or fneq(m3, mc[2])
24296      snd_test_neq(m1, mc[0], "map maxamp (a)")
24297      snd_test_neq(m2, mc[1], "map maxamp (b)")
24298      snd_test_neq(m3, mc[2], "map maxamp (c)")
24299    end
24300    set_sync(1, obi)
24301    set_sync(1, s2i)
24302    do_chans("*2") do |val|
24303      (val ? (2.0 * val) : false)
24304    end
24305    mc1 = [[obi, 0], [s2i, 0], [s2i, 1]].map do |snd, chn|
24306      maxamp(snd, chn)
24307    end
24308    resm1 = 2.0 * m1
24309    resm2 = 2.0 * m2
24310    resm3 = 2.0 * m3
24311    if fneq(resm1, mc1[0]) or fneq(resm2, mc1[1]) or fneq(resm3, mc1[2])
24312      snd_test_neq(resm1, mc1[0], "do_chans (a)")
24313      snd_test_neq(resm2, mc1[1], "do_chans (b)")
24314      snd_test_neq(resm3, mc1[2], "do_chans (c)")
24315    end
24316    set_sync(0, obi)
24317    set_sync(0, s2i)
24318    select_sound(s2i)
24319    do_sound_chans("/2") do |val|
24320      (val ? (0.5 * val) : false)
24321    end
24322    mc2 = [[obi, 0], [s2i, 0], [s2i, 1]].map do |snd, chn|
24323      maxamp(snd, chn)
24324    end
24325    m1 *= 2.0
24326    if fneq(m1, mc2[0]) or fneq(m2, mc2[1]) or fneq(m3, mc2[2])
24327      snd_test_neq(m1, mc2[0], "do_sound_chans (a)")
24328      snd_test_neq(m2, mc2[1], "do_sound_chans (b)")
24329      snd_test_neq(m3, mc2[2], "do_sound_chans (c)")
24330    end
24331    if every_sample? do |val| val > 0.5 end
24332      snd_display("every_sample? (0)?")
24333    end
24334    unless every_sample? do |val| val < 5.0 end
24335      snd_display("every_sample? (1)?")
24336    end
24337    select_sound(obi)
24338    res = sort_samples(32)[1]
24339    snd_test_neq(res, 4504, "sort_samples")
24340    revert_sound(s2i)
24341    revert_sound(obi)
24342    set_sync(3, obi)
24343    set_sync(3, s2i)
24344    half_way = (0.5 * framples(obi)).floor
24345    o1 = sample(half_way, obi, 0)
24346    s1 = sample(half_way, s2i, 0)
24347    s2 = sample(half_way, s2i, 1)
24348    place_sound(obi, s2i, [0, 0.5, 1, 0.5])
24349    s21 = sample(half_way, s2i, 0)
24350    s22 = sample(half_way, s2i, 1)
24351    revert_sound(s2i)
24352    place_sound(obi, s2i, 45.0)
24353    s31 = sample(half_way, s2i, 0)
24354    s32 = sample(half_way, s2i, 1)
24355    res1 = s1 + 0.5 * o1
24356    res2 = s2 + 0.5 * o1
24357    if fneq(res1, s21) or fneq(res2, s22) or fneq(s21, s31) or fneq(s22, s32)
24358      snd_test_neq(res1, s21, "place_sound (a)")
24359      snd_test_neq(res2, s22, "place_sound (b)")
24360      snd_test_neq(s21, s31, "place_sound (c)")
24361      snd_test_neq(s22, s32, "place_sound (d)")
24362    end
24363    revert_sound(s2i)
24364    revert_sound(obi)
24365    set_sync(0, obi)
24366    set_sync(0, s2i)
24367    res1 = compand.call(0.0)
24368    res2 = compand.call(1.0)
24369    res3 = compand.call(0.1)
24370    res4 = compand.call(0.99)
24371    res5 = compand.call(0.95)
24372    if fneq(res1, 0.0) or
24373       fneq(res2, 1.0) or
24374       fneq(res3, 0.2) or
24375       fneq(res4, 0.997) or
24376       fneq(res5, 0.984)
24377      snd_test_neq(res1, 0.0, "compand (a)")
24378      snd_test_neq(res2, 1.0, "compand (b)")
24379      snd_test_neq(res3, 0.2, "compand (c)")
24380      snd_test_neq(res4, 0.997, "compand (d)")
24381      snd_test_neq(res5, 0.984, "compand (e)")
24382    end
24383    close_sound(obi)
24384    revert_sound(s2i)
24385    #
24386    s1 = sample(1000, s2i, 0)
24387    s2 = sample(1000, s2i, 1)
24388    set_sync(4, s2i)
24389    select_all
24390    if selection_chans != 2
24391      snd_display("selection_chans (2): %s?", selection_chans)
24392      Snd.sounds.each do |snd|
24393        channels(snd).times do |chn|
24394          if selection_member?(snd, chn)
24395            snd_display("%s[%s] at %s?",
24396              short_file_name(snd), chn, selection_position(snd, chn))
24397          end
24398        end
24399      end
24400    end
24401    res = selection_srate
24402    req = srate(s2i)
24403    snd_test_neq(res, req, "selection_srate")
24404    if selection_chans == 2
24405      swap_selection_channels
24406      res1 = sample(1000, s2i, 1)
24407      res2 = sample(1000, s2i, 0)
24408      if fneq(res1, s1) or fneq(res2, s2)
24409        snd_test_neq(res1, s1, "swap_selection_channels (a)")
24410        snd_test_neq(res2, s2, "swap_selection_channels (b)")
24411      end
24412    end
24413    revert_sound(s2i)
24414    close_sound(s2i)
24415  else
24416    snd_display("No sound file found s2i: %p", snds)
24417  end
24418  #
24419  obi = open_sound("oboe.snd")
24420  if $with_test_gui
24421    select_all
24422    Snd.regions.apply(:forget_region)
24423    if regions != nil
24424      snd_display("no regions: %s?", regions.inspect)
24425    end
24426    id = make_region(100, 200, obi, 0)
24427    if (!(regions.eql?([id])))
24428      snd_display("make_region regions: %s?", regions.inspect)
24429    end
24430    revert_sound(obi)
24431    oldlen = framples(obi)
24432    env_sound_interp([0, 0, 1, 1, 2, 0], 2.0, obi, 0)
24433    newlen = framples(obi)
24434    if (2 * oldlen - newlen).abs > 3
24435      snd_display("env_sound_interp: %s %s?", oldlen, newlen)
24436    end
24437  end
24438  #
24439  revert_sound(obi)
24440  granulated_sound_interp([0, 0, 1, 0.1, 2, 1], 1.0, 0.2, [0, 0, 1, 1, 2, 0])
24441  snd_test_neq(edit_position(obi, 0), 1, "granulated_sound_interp no-op 1")
24442  snd_test_lt(maxamp(obi, 0), 0.15, "granulated_sound_interp 1 maxamp")
24443  res = (framples(obi, 0) - 50828).abs
24444  snd_test_gt(res, 1000, "granulated_sound_interp 1 framples")
24445  revert_sound(obi)
24446  granulated_sound_interp([0, 0, 1, 1], 2.0)
24447  snd_test_neq(edit_position(obi, 0), 1, "granulated_sound_interp no-op 2")
24448  snd_test_lt(maxamp(obi, 0), 0.145, "granulated_sound_interp 2 maxamp")
24449  res = (framples(obi, 0) - 101656).abs
24450  snd_test_gt(res, 1000, "granulated_sound_interp 2 framples")
24451  revert_sound(obi)
24452  granulated_sound_interp([0, 0, 1, 0.1, 2, 1], 1.0, 0.2,
24453                          [0, 0, 1, 1, 2, 0], 0.02)
24454  snd_test_neq(edit_position(obi, 0), 1, "granulated_sound_interp no-op 3")
24455  snd_test_lt(maxamp(obi, 0), 0.2, "granulated_sound_interp 3 maxamp")
24456  res = (framples(obi, 0) - 50828).abs
24457  snd_test_gt(res, 1000, "granulated_sound_interp 3 framples")
24458  close_sound(obi)
24459end
24460
24461def test_15_01
24462  ind = new_sound("test.snd", :size, 20)
24463  offset_channel(1.0)
24464  env_sound([0, 0, 1, 1])
24465  osc = make_oscil(:frequency, 1000.0, :initial_phase, PI + HALF_PI)
24466  reader = make_sound_interp(0, ind, 0)
24467  len = framples(ind, 0) - 1
24468  map_channel_rb do |val|
24469    sound_interp(reader, len * (0.5 + 0.5 * oscil(osc)))
24470  end
24471  snd_test_neq(channel2vct(),
24472               vct(0.000, 0.020, 0.079, 0.172, 0.291, 0.427, 0.569, 0.706,
24473                   0.825, 0.919, 0.979, 1.000, 0.981, 0.923, 0.831, 0.712,
24474                   0.576, 0.434, 0.298, 0.177),
24475               "sound_interp")
24476  undo_edit
24477  osc = make_oscil(:frequency, 0.5, :initial_phase, PI + HALF_PI)
24478  reader = make_sound_interp(0, ind, 0)
24479  len = framples(ind, 0) - 1
24480  map_channel(lambda do |val|
24481                sound_interp(reader, len * (0.5 + 0.5 * oscil(osc)))
24482              end)
24483  undo_edit
24484  env_sound_interp([0, 0, 1, 1])
24485  snd_test_neq(channel2vct(),
24486               vct(0.000, 0.053, 0.105, 0.158, 0.211, 0.263, 0.316, 0.368,
24487                   0.421, 0.474, 0.526, 0.579, 0.632, 0.684, 0.737, 0.789,
24488                   0.842, 0.895, 0.947, 1.000),
24489               "env_sound_interp no change")
24490  undo_edit
24491  env_sound_interp([0, 0, 1, 0.95, 2, 0], 2.0)
24492  snd_test_neq(channel2vct(),
24493               vct(0.000, 0.050, 0.100, 0.150, 0.200, 0.250, 0.300, 0.350,
24494                   0.400, 0.450, 0.500, 0.550, 0.600, 0.650, 0.700, 0.750,
24495                   0.800, 0.850, 0.900, 0.950, 1.000, 0.950, 0.900, 0.850,
24496                   0.800, 0.750, 0.700, 0.650, 0.600, 0.550, 0.500, 0.450,
24497                   0.400, 0.350, 0.300, 0.250, 0.200, 0.150, 0.100, 0.050),
24498               "env_sound_interp twice len and back")
24499  revert_sound(ind)
24500  set_sample(10, 0.5)
24501  remove_clicks
24502  snd_test_neq(sample(10), 0.0, "remove_clicks")
24503  undo_edit
24504  val = scan_channel(search_for_click)
24505  snd_test_neq(val, 11, "search_for_click")
24506  close_sound(ind)
24507  #
24508  id = open_sound("oboe.snd")
24509  fr = framples(id, 0)
24510  mx = maxamp(id, 0)
24511  set_framples(25000, id, 0)
24512  if (res = framples(id, 0)) != 25000
24513    snd_display("set_framples 25000: %s?", res)
24514  end
24515  if (res = edit_position(id, 0)) != 1
24516    snd_display("set_framples 25000 edit: %s?", res)
24517  end
24518  set_framples(75000, id, 0)
24519  if (res = framples(id, 0)) != 75000
24520    snd_display("set_framples 75000: %s?", res)
24521  end
24522  if (res = edit_position(id, 0)) != 2
24523    snd_display("set_framples 75000 edit: %s?", res)
24524  end
24525  if fneq(res = sample(30000, id, 0), 0.0)
24526    snd_display("set_framples 75000 zeros: %s?", res)
24527  end
24528  set_framples(0, id, 0)
24529  if (res = framples(id, 0)) != 0
24530    snd_display("set_framples 0: %s?", res)
24531  end
24532  set_framples(100, id, 0)
24533  if (res = framples(id, 0)) != 100
24534    snd_display("set_framples 100: %s?", res)
24535  end
24536  revert_sound
24537  if fneq(res = sample(30000, id, 0), -0.0844)
24538    snd_display("revert from set_framples: %s?", res)
24539  end
24540  if (res = framples(id, 0)) != fr
24541    snd_display("revert set_framples: %s != %s?", res, fr)
24542  end
24543  set_maxamp(0.5, id, 0)
24544  if fneq(res = maxamp(id, 0), 0.5)
24545    snd_display("set_maxamp: %s?", res)
24546  end
24547  if (res = edit_position(id, 0)) != 1
24548    snd_display("set_maxamp edit: %s?", res)
24549  end
24550  set_maxamp(0.1, id, 0)
24551  if fneq(res = maxamp(id, 0), 0.1)
24552    snd_display("set_maxamp 0.1: %s?", res)
24553  end
24554  if (res = edit_position(id, 0)) != 2
24555    snd_display("set_maxamp 0.1 edit: %s?", res)
24556  end
24557  revert_sound
24558  if fneq(res = maxamp(id, 0), mx)
24559    snd_display("maxamp after set: %s %s?", res, mx)
24560  end
24561  set_x_position_slider(0.1, id, 0)
24562  if fneq(res = x_position_slider(id, 0), 0.1)
24563    snd_display("set_x_position_slider 0.1: %s?", res)
24564  end
24565  set_x_zoom_slider(0.5, id, 0)
24566  if fneq(res = x_zoom_slider(id, 0), 0.5)
24567    snd_display("set_x_zoom_slider 0.5: %s?", res)
24568  end
24569  if (res1 = (fr - 2 * ((res2 = right_sample(id, 0)) - (res3 = left_sample(id, 0)))).abs) > 10
24570    snd_display("set_x_zoom_slider: %s %s --> %s?", res2, res3, res1)
24571  end
24572  set_y_position_slider(0.1, id, 0)
24573  if $with_test_motif and fneq(res = y_position_slider(id, 0), 0.1)
24574    snd_display("set_y_position_slider 0.1: %s?", res)
24575  end
24576  set_y_zoom_slider(0.5, id, 0)
24577  if fneq(res = y_zoom_slider(id, 0), 0.5)
24578    snd_display("set_y_zoom_slider 0.5: %s?", res)
24579  end
24580  #
24581  len = (channel_properties(id, 0) or []).length
24582  if res = channel_property(:hiho, id, 0)
24583    snd_display("channel_property :hiho: %s?", res)
24584  end
24585  set_channel_property(:hiho, 123, id, 0)
24586  if (res = channel_property(:hiho, id, 0)) != 123
24587    snd_display("channel_property :hiho (123): %s?", res)
24588  end
24589  if res = channel_property(:hi, id, 0)
24590    snd_display("channel_property :hi: %s?", res)
24591  end
24592  set_channel_property(:hi, PI, id, 0)
24593  if (res = channel_property(:hi, id, 0)) != PI
24594    snd_display("channel_property :hi (PI): %s?", res)
24595  end
24596  if (res = channel_property(:hiho, id, 0)) != 123
24597    snd_display("channel_property 2nd :hiho (123): %s?", res)
24598  end
24599  if (res = (channel_properties or []).length) != len + 2
24600    snd_display("channel_properties: %s?", res)
24601  end
24602  #
24603  len = (sound_properties(id) or []).length
24604  if res = sound_property(:hiho, id)
24605    snd_display("sound_property :hiho: %s?", res)
24606  end
24607  set_sound_property(:hiho, 123, id)
24608  if (res = sound_property(:hiho, id)) != 123
24609    snd_display("sound_property :hiho (123): %s?", res)
24610  end
24611  if res = sound_property(:hi, id)
24612    snd_display("sound_property :hi: %s?", res)
24613  end
24614  set_sound_property(:hi, PI, id)
24615  if (res = sound_property(:hi, id)) != PI
24616    snd_display("sound_property :hi (PI): %s?", res)
24617  end
24618  if (res = sound_property(:hiho, id)) != 123
24619    snd_display("sound_property 2nd :hiho (123): %s?", res)
24620  end
24621  if (res = (sound_properties(id) or []).length) != len + 2
24622    snd_display("sound_properties: %s?", res)
24623  end
24624  # XXX: S7 has here :wrong_type_arg
24625  # XXX: Ruby has still :bad_type
24626  res = Snd.catch do map_channel(lambda do |y| "hiho" end) end
24627  snd_test_neq(res.first, :bad_type, "map_channel bad val")
24628  close_sound(id)
24629  #
24630  id = open_sound("oboe.snd")
24631  prefix_it(1000, id)
24632  key(key_to_int(?x), 4, id)
24633  key(key_to_int(?b), 4, id)
24634  if (left = left_sample(id)) != 1000
24635    snd_display("u1000: %s?", left)
24636  end
24637  prefix_it(0, id)
24638  key(key_to_int(?x), 4, id)
24639  key(key_to_int(?b), 4, id)
24640  if (left = left_sample(id)) != 0
24641    snd_display("u0: %s?", left)
24642  end
24643  set_cursor(1234, id)
24644  prefix_it(0, id)
24645  key(key_to_int(?f), 4, id)
24646  if (cr = cursor(id)) != 1234
24647    snd_display("0f: %s?", cr)
24648  end
24649  prefix_it(100, id)
24650  key(key_to_int(?f), 4, id)
24651  if (cr = cursor(id)) != 1334
24652    snd_display("100f: %s?", cr)
24653  end
24654  prefix_it(-100, id)
24655  key(key_to_int(?f), 4, id)
24656  if (cr = cursor(id)) != 1234
24657    snd_display("-100f: %s?", cr)
24658  end
24659  prefix_it(1, id)
24660  key(key_to_int(?f), 4, id)
24661  if (cr = cursor(id)) != 1235
24662    snd_display("1f: %s?", cr)
24663  end
24664  prefix_it(1000, id)
24665  key(key_to_int(?x), 4, id)
24666  key(key_to_int(?p), 4, id)
24667  if ((right = right_sample(id)) - (left = left_sample(id)) - 1000).abs > 2
24668    snd_display("1000xp: %s %s?", left, right)
24669  end
24670  prefix_it(1, id)
24671  key(key_to_int(?.), 0, id)
24672  key(key_to_int(?2), 0, id)
24673  key(key_to_int(?x), 4, id)
24674  key(key_to_int(?p), 4, id)
24675  if ((right = right_sample(id)) - (left = left_sample(id)) - (22050 * 1.2)).abs > 2
24676    snd_display("1.2xp: %s %s?", left, right)
24677  end
24678  #
24679  prefix_uit(1000, id)
24680  key(key_to_int(?x), 4, id)
24681  key(key_to_int(?b), 4, id)
24682  if (left = left_sample(id)) != 1000 and left != 1001
24683    snd_display("uu1000: %s?", left)
24684  end
24685  prefix_uit(0, id)
24686  key(key_to_int(?x), 4, id)
24687  key(key_to_int(?b), 4, id)
24688  if (left = left_sample(id)) != 0
24689    snd_display("uu0: %s?", left)
24690  end
24691  set_cursor(1234, id)
24692  prefix_uit(0, id)
24693  key(key_to_int(?f), 4, id)
24694  if (cr = cursor(id)) != 1234
24695    snd_display("u0f: %s?", cr)
24696  end
24697  prefix_uit(100, id)
24698  key(key_to_int(?f), 4, id)
24699  if (cr = cursor(id)) != 1334
24700    snd_display("u100f: %s?", cr)
24701  end
24702  prefix_uit(-100, id)
24703  key(key_to_int(?f), 4, id)
24704  if (cr = cursor(id)) != 1234
24705    snd_display("u-100f: %s?", cr)
24706  end
24707  prefix_uit(1, id)
24708  key(key_to_int(?f), 4, id)
24709  if (cr = cursor(id)) != 1235
24710    snd_display("u1f: %s?", cr)
24711  end
24712  prefix_uit(1000, id)
24713  key(key_to_int(?x), 4, id)
24714  key(key_to_int(?p), 4, id)
24715  if ((right = right_sample(id)) - (left = left_sample(id)) - 1000).abs > 2
24716    snd_display("u1000xp: %s %s?", left, right)
24717  end
24718  prefix_uit(1, id)
24719  key(key_to_int(?.), 0, id)
24720  key(key_to_int(?2), 0, id)
24721  key(key_to_int(?x), 4, id)
24722  key(key_to_int(?p), 4, id)
24723  if ((right = right_sample(id)) - (left = left_sample(id)) - (22050 * 1.2)).abs > 2
24724    snd_display("u1.2xp: %s %s?", left, right)
24725  end
24726  close_sound(id)
24727  #
24728  snds = match_sound_files do |file|
24729    File.exist?(file) and # for $tests > 1
24730      mus_sound_chans(file) >= 2 and
24731      mus_sound_framples(file) > 1000
24732  end
24733  if snds.length > 0
24734    id = open_sound(snds.first)
24735    set_sync(1, id)
24736    select_sound(id)
24737    make_region(200, 500, id)
24738    select_channel(1)
24739    key(key_to_int(?x), 4, id)
24740    key(key_to_int(?v), 0, id)
24741    if $with_test_gui
24742      x0 = x_bounds(id, 0)
24743      x1 = x_bounds(id, 1)
24744      if fneq(x0[0], x1[0]) or fneq(x0[1], x1[1])
24745        snd_display("C-x v: %s %s?", x0, x1)
24746      end
24747      key(key_to_int(?u), 4, id)
24748      key(key_to_int(?1), 0, id)
24749      key(key_to_int(?x), 4, id)
24750      key(key_to_int(?q), 0, id)
24751    end
24752    close_sound(id)
24753  else
24754    snd_display("No sound file found id: %s", snds)
24755  end
24756end
24757
24758def f3neq(a, b)
24759  fneq_err(a, b, 10)
24760end
24761
24762def f4neq(a, b)
24763  fneq_err(a, b, 1)
24764end
24765
24766def f5neq(a, b)
24767  fneq_err(a, b, 0.05 * [a, b].max)
24768end
24769
24770def test_15_02
24771  snd1 = open_sound("oboe.snd")
24772  snd2 = open_sound("2.snd")
24773  snd3 = open_sound("4.aiff")
24774  [[:time_graph_type, Graph_as_wavogram],
24775   [:wavo_hop, 12],
24776   [:wavo_trace, 512],
24777   [:max_transform_peaks, 3],
24778   [:show_transform_peaks, true],
24779   [:zero_pad, 32],
24780   [:transform_graph_type, Graph_as_sonogram],
24781   [:fft_window, Cauchy_window],
24782   [:with_verbose_cursor, true],
24783   [:fft_log_frequency, true],
24784   [:fft_log_magnitude, true],
24785   [:fft_with_phases, true],
24786   [:min_dB, -120.0],
24787   [:wavelet_type, 3],
24788   [:transform_size, 32],
24789   [:fft_window_alpha, 0.5],
24790   [:fft_window_beta, 0.5],
24791   [:transform_type, $autocorrelation],
24792   [:transform_normalization, 0],
24793   [:show_mix_waveforms, true],
24794   [:graph_style, Graph_lollipops],
24795   [:dot_size, 8],
24796   [:show_axes, Show_no_axes],
24797   [:show_y_zero, true],
24798   [:show_grid, true],
24799   [:show_marks, false],
24800   [:grid_density, 1.0],
24801   [:spectro_x_angle, 32.0],
24802   [:spectro_x_scale, 0.5],
24803   [:spectro_y_angle, 32.0],
24804   [:spectro_y_scale, 0.5],
24805   [:spectro_z_angle, 32.0],
24806   [:spectro_z_scale, 0.5],
24807   [:spectro_hop, 14],
24808   [:spectrum_end, 0.3],
24809   [:spectrum_start, 0.1],
24810   [:graphs_horizontal, false],
24811   [:x_axis_style, X_axis_in_samples],
24812   [:beats_per_minute, 120.0],
24813   [:beats_per_measure, 3],
24814   [:cursor_size, 15],
24815   [:cursor_style, Cursor_cross],
24816   [:tracking_cursor_style, Cursor_cross],
24817   [:show_sonogram_cursor, true]].each do |func, nv|
24818    test_history_channel(func, nv, snd1, snd2, snd3)
24819  end
24820  [snd1, snd2].apply(:close_sound)
24821  #
24822  set_time_graph_style(Graph_filled, snd3, true)
24823  4.times do |chn|
24824    if (res = time_graph_style(snd3, chn)) != Graph_filled
24825      snd_display("set_time_graph_style %s %s (filled): %s?", snd3, chn, res)
24826    end
24827  end
24828  set_time_graph_style(Graph_lines, snd3, 2)
24829  4.times do |chn|
24830    if chn == 2
24831      if (res = time_graph_style(snd3, chn)) != Graph_lines
24832        snd_display("set_time_graph_style %s %s (lines): %s?", snd3, chn, res)
24833      end
24834    else
24835      if (res = time_graph_style(snd3, chn)) != Graph_filled
24836        snd_display("set_time_graph_style %s %s (filled): %s?", snd3, chn, res)
24837      end
24838    end
24839  end
24840  set_time_graph_style(Graph_dots, snd3, true)
24841  4.times do |chn|
24842    if (res = time_graph_style(snd3, chn)) != Graph_dots
24843      snd_display("set_time_graph_style %s %s (dots): %s?", snd3, chn, res)
24844    end
24845  end
24846  set_graph_style(Graph_dots_and_lines)
24847  4.times do |chn|
24848    if (res = time_graph_style(snd3, chn)) != Graph_dots_and_lines
24849      snd_display("set_time_graph_style %s %s (dots and lines): %s?", snd3, chn, res)
24850    end
24851  end
24852  set_lisp_graph_style(Graph_filled, snd3, true)
24853  4.times do |chn|
24854    if (res = lisp_graph_style(snd3, chn)) != Graph_filled
24855      snd_display("set_lisp_graph_style %s %s (filled): %s?", snd3, chn, res)
24856    end
24857  end
24858  set_lisp_graph_style(Graph_lines, snd3, 2)
24859  4.times do |chn|
24860    if chn == 2
24861      if (res = lisp_graph_style(snd3, chn)) != Graph_lines
24862        snd_display("set_lisp_graph_style %s %s (lines): %s?", snd3, chn, res)
24863      end
24864    else
24865      if (res = lisp_graph_style(snd3, chn)) != Graph_filled
24866        snd_display("set_lisp_graph_style %s %s (filled): %s?", snd3, chn, res)
24867      end
24868    end
24869  end
24870  set_lisp_graph_style(Graph_lines, snd3, true)
24871  4.times do |chn|
24872    if (res = lisp_graph_style(snd3, chn)) != Graph_lines
24873      snd_display("set_lisp_graph_style %s %s (lines): %s?", snd3, chn, res)
24874    end
24875  end
24876  set_transform_graph_style(Graph_filled, snd3, true)
24877  4.times do |chn|
24878    if (res = transform_graph_style(snd3, chn)) != Graph_filled
24879      snd_display("set_transform_graph_style %s %s (filled): %s?", snd3, chn, res)
24880    end
24881  end
24882  set_transform_graph_style(Graph_lines, snd3, 2)
24883  4.times do |chn|
24884    if chn == 2
24885      if (res = transform_graph_style(snd3, chn)) != Graph_lines
24886        snd_display("set_transform_graph_style %s %s (lines): %s?", snd3, chn, res)
24887      end
24888    else
24889      if (res = transform_graph_style(snd3, chn)) != Graph_filled
24890        snd_display("set_transform_graph_style %s %s (filled): %s?", snd3, chn, res)
24891      end
24892    end
24893  end
24894  4.times do |chn|
24895    if (res = time_graph_style(snd3, chn)) != Graph_dots_and_lines
24896      snd_display("set fft and lisp -> time_graph_style: %s?", snd3, chn, res)
24897    end
24898  end
24899  4.times do |chn|
24900    if (res = lisp_graph_style(snd3, chn)) != Graph_lines
24901      snd_display("set fft and lisp -> lisp_graph_style: %s?", snd3, chn, res)
24902    end
24903  end
24904  close_sound(snd3)
24905  snd2 = open_sound("2.snd")
24906  sound?(snd2) and play_with_amps_1(snd2, 0.2, 0.1)
24907  close_sound(snd2)
24908  #
24909  old_bp = with_background_processes
24910  set_with_background_processes(false)
24911  ind = open_sound("1a.snd")
24912  player = make_player(ind, 0)
24913  len = framples(ind, 0)
24914  incr = dac_size
24915  e = make_env(:envelope, [0, 0, 1, 1], :length, (len.to_f / incr).floor + 1)
24916  samp = 0
24917  add_player(player, 0, -1, -1, lambda do |reason|
24918               $play_hook.reset_hook!
24919               close_sound(ind)
24920             end)
24921  $play_hook.add_hook!("snd-test") do |fr|
24922    set_amp_control(env(e), player)
24923    if fneq(res = amp_control(ind), 1.0)
24924      snd_display("amp_control snd: %s?", res)
24925    end
24926    if ((res1 = amp_control(player)) - (res2 = samp / len.to_f)).abs > 1.0
24927      snd_display("amp_control player: %s %s?", res1, res2)
24928    end
24929    samp += incr
24930  end
24931  start_playing(1, srate(ind))
24932  if find_sound("1a.snd")
24933    snd_display("stop proc did not close?")
24934    Snd.catch do close_sound(ind) end
24935  end
24936  set_with_background_processes(old_bp)
24937  #
24938  ind = open_sound("pistol.snd")
24939  if res = selection_member?(ind, 0)
24940    snd_display("initial selection_member?: %s %s?", res, selection?)
24941  end
24942  set_selection_member?(true, ind, 0)
24943  if (not (res1 = selection_member?(ind, 0))) or (not (res2 = selection_member?(ind)))
24944    snd_display("selection_member? %s %s %s?", res1, res2, selection?)
24945  end
24946  if (res = selection_framples) != 1
24947    snd_display("initial selection_framples: %s?", res)
24948  end
24949  set_selection_framples(1200)
24950  if (res = selection_framples) != 1200
24951    snd_display("selection_framples 1200: %s?", res)
24952  end
24953  delete_selection
24954  if selection?
24955    snd_display("selection active after cut?")
24956  end
24957  undo_edit
24958  unless selection?
24959    snd_display("selection inactive after undo?")
24960  end
24961  if (not (res1 = selection_member?(ind, 0))) or (not (res2 = selection_member?(ind)))
24962    snd_display("selection_member? after undo %s %s %s?", res1, res2, selection?)
24963  end
24964  if (res1 = selection_framples) != 1200 or (res2 = selection_position) != 0
24965    snd_display("selection after undo: [0, 1200] [%s, %s]?", res2, res1)
24966  end
24967  set_selection_position(1000)
24968  if (res1 = selection_framples) != 200 or (res2 = selection_position) != 1000
24969    snd_display("selection after undo: [1000, 200] [%s, %s]?", res2, res1)
24970  end
24971  reverse_selection
24972  if (res1 = selection_framples) != 200 or (res2 = selection_position) != 1000
24973    snd_display("selection after reverse: [1000, 200] [%s, %s]?", res2, res1)
24974  end
24975  old_framples = framples(ind)
24976  src_selection(0.5)
24977  if (framples(ind) - (200 + old_framples)).abs > 5 or
24978      ((res = selection_framples) - 400).abs > 5
24979    snd_display("selection after src 0.5: [1000, 400] [%s, %s]?", res, selection_position)
24980  end
24981  undo_edit
24982  redo_edit
24983  if (framples(ind) - (200 + old_framples)).abs > 5 or
24984      ((res = selection_framples) - 400).abs > 5
24985    snd_display("selection after src 0.5 with undo/redo: [1000, 400] [%s, %s]?",
24986                res, selection_position)
24987  end
24988  undo_edit(3)
24989  close_sound(ind)
24990  #
24991  # src-duration tests
24992  #
24993  ind = new_sound("test.snd", 1, 22050, Mus_bfloat, Mus_next,
24994                  "src-* tests", 10000)
24995  osc = make_oscil(:frequency, 500)
24996  if fneq(res1 = src_duration([0, 1, 1, 2]), 0.693147180559945) or
24997      fneq(res2 = src_duration([0, 2, 1, 1]), src_duration([0, 1, 1, 2])) or
24998      fneq(res3 = src_duration([0, 1, 0.5, 2]), src_duration([0, 1, 1, 2])) or
24999      fneq(res4 = src_duration([0.5, 1, 0.75, 2]), src_duration([0, 1, 1, 2]))
25000    snd_display("src_duration test1: %s %s %s %s?", res1, res2, res3, res4)
25001  end
25002  if fneq(res1 = src_duration([0, 1, 1, 0.5]), 1.38629436111989) or
25003      fneq(res2 = src_duration([0, 0.5, 1, 1]), src_duration([0, 1, 1, 0.5])) or
25004      fneq(res3 = src_duration([0, 1, 0.5, 0.5]), src_duration([0, 1, 1, 0.5])) or
25005      fneq(res4 = src_duration([0.5, 1, 0.75, 0.5]), src_duration([0, 1, 1, 0.5]))
25006    snd_display("src_duration test2: %s %s %s %s?", res1, res2, res3, res4)
25007  end
25008  if fneq(res1 = src_duration([0, 1, 1, 1]), 1.0) or
25009      fneq(res2 = src_duration([0, 2, 1, 2]), 0.5)
25010    snd_display("src_duration test3: %s %s?", res1, res2)
25011  end
25012  if fneq(res = src_duration([0, 0.5, 0.5, 3, 0.6, 1, 0.7, 0.1, 0.8, 1.5, 1, 1]), 1.02474349685432)
25013    snd_display("src_duration test4: %s?", res)
25014  end
25015  if fneq(res = src_duration([0, 1, 1, 2, 2, 1]), 0.693147180559945)
25016    snd_display("src_duration test5: %s?", res)
25017  end
25018  map_channel_rb do |y| 0.5 * oscil(osc) end
25019  vals = freq_peak(0, ind, 8192)
25020  if f4neq(vals[0], 500.0) or fneq(vals[1], 1.0)
25021    snd_display("src no-test: %s?", vals)
25022  end
25023  #
25024  src_lists1 = [[2.0, 0.5], [0.5, 2.0], [5.0, 0.2], [0.2, 5.0]]
25025  src_lists2 = [[[0, 1, 1, 2], 500.0, 1000.0],
25026                [[0, 2, 1, 1], 1000.0, 500.0],
25027                [[0, 1, 1, 2, 2, 1], 500.0, 500.0],
25028                [[0, 0.5, 1, 1], 250.0, 500.0],
25029                [[0, 0.5, 1, 2], 250.0, 1000.0]]
25030  src_lists3 = [[0, 1, 1, 2], [0, 2, 1, 1], [0, 1, 1, 2, 2, 1], [0, 0.5, 1, 1], [0, 0.5, 1, 2]]
25031  # src_sound
25032  src_lists1.each do |sr, dur|
25033    src_sound(sr, 1.0, ind, 0)
25034    if fneq(res = framples(ind, 0) / 10000.0, dur)
25035      snd_display("src_sound %s: %s (%s)?", sr, res, dur)
25036    end
25037    vals = freq_peak(0, ind, 8192)
25038    if f4neq(vals[0], 500 * sr) or fneq(vals[1], 1.0)
25039      snd_display("src_sound %s freq: %s?", sr, vals)
25040    end
25041    undo_edit
25042  end
25043  src_lists2.each do |e, f0, f1|
25044    src_sound(e, 1.0, ind, 0)
25045    if fneq(res1 = framples(ind, 0) / 10000.0, res2 = src_duration(e))
25046      snd_display("src_sound (env) %s: %s (%s)?", e, res1, res2)
25047    end
25048    vals = freq_peak(0, ind, 256)
25049    if f5neq(vals[0], f0)
25050      snd_display("src_sound (env) 0 %s freq: %s?", f0, vals)
25051    end
25052    vals = freq_peak((src_duration(e) * 10000.0).floor - 256, ind, 256)
25053    if f5neq(vals[0], f1)
25054      snd_display("src_sound (env) 1 %s freq: %s?", f1, vals)
25055    end
25056    undo_edit
25057  end
25058  src_lists2.each do |e, f0, f1|
25059    src_sound(make_env(:envelope, e, :length, framples), 1.0, ind, 0)
25060    if fneq(res1 = framples(ind, 0) / 10000.0, res2 = src_duration(e))
25061      snd_display("src_sound (make_env) %s: %s (%s)?", e, res1, res2)
25062    end
25063    vals = freq_peak(0, ind, 256)
25064    if f5neq(vals[0], f0)
25065      snd_display("src_sound (make_env) 0 %s freq: %s?", f0, vals)
25066    end
25067    vals = freq_peak((src_duration(e) * 10000.0).floor - 256, ind, 256)
25068    if f5neq(vals[0], f1)
25069      snd_display("src_sound (make_env) 1 %s freq: %s?", f1, vals)
25070    end
25071    undo_edit
25072  end
25073  # src_channel
25074  src_lists1.each do |sr, dur|
25075    src_channel(sr)
25076    if fneq(res = framples(ind, 0) / 10000.0, dur)
25077      snd_display("src_channel %s: %s (%s)?", sr, res, dur)
25078    end
25079    vals = freq_peak(0, ind, 8192)
25080    if f4neq(vals[0], 500 * sr) or fneq(vals[1], 1.0)
25081      snd_display("src_channel %s freq: %s?", sr, vals)
25082    end
25083    undo_edit
25084  end
25085  src_lists2.each do |e, f0, f1|
25086    src_channel(e)
25087    if fneq(res1 = framples(ind, 0) / 10000.0, res2 = src_duration(e))
25088      snd_display("src_channel (env) %s: %s (%s)?", e, res1, res2)
25089    end
25090    vals = freq_peak(0, ind, 256)
25091    if f5neq(vals[0], f0)
25092      snd_display("src_channel (env f0) %s freq: %s?", f0, vals)
25093    end
25094    vals = freq_peak((src_duration(e) * 10000.0).floor - 256, ind, 256)
25095    if f5neq(vals[0], f1)
25096      snd_display("src_channel (env f1) %s freq: %s?", f1, vals)
25097    end
25098    undo_edit
25099  end
25100  src_lists1.each do |sr, dur|
25101    src_channel(sr, 1000, 2500)
25102    if f4neq(res1 = framples(ind, 0), (res2 = 7500 + dur * 2500))
25103      snd_display("src_channel section: %s %s?", res1, res)
25104    end
25105    vals = freq_peak(0, ind, 512)
25106    if f5neq(vals[0], 500.0)
25107      snd_display("src_channel section 0 %s freq: %s?", sr, vals)
25108    end
25109    vals = freq_peak(((dur * 2500.0).floor + 7500) - 512, ind, 512)
25110    if f5neq(vals[0], 500.0)
25111      snd_display("src_channel section 8000 %s freq: %s?", sr, vals)
25112    end
25113    vals = freq_peak(1000, ind, 512)
25114    if f5neq(vals[0], 500.0 * sr)
25115      snd_display("src_channel section %s freq: %s?", sr, vals)
25116    end
25117    undo_edit
25118  end
25119  src_lists3.each do |e|
25120    src_channel(make_env(:envelope, e, :length, 2501), 1000, 2500)
25121    if f3neq(res1 = framples(ind, 0), (res2 = 7500 + src_duration(e) * 2500))
25122      snd_display("src_channel section (make_env duration) %s: %s (%s %s)?",
25123                  e, src_duration(e), res1, res2)
25124    end
25125    vals = freq_peak(0, ind, 256)
25126    if f5neq(vals[0], 500.0)
25127      snd_display("src_channel section (make_env 0): %s?", vals)
25128    end
25129    vals = freq_peak(((src_duration(e) * 2500).floor + 7500) - 256, ind, 256)
25130    if f5neq(vals[0], 500.0)
25131      snd_display("src_channel section (make_env 1): %s?", vals)
25132    end
25133    undo_edit
25134  end
25135  # src_selection
25136  make_selection(1000, 3500, ind, 0)
25137  src_lists1.each do |sr, dur|
25138    src_selection(sr)
25139    if f3neq(res1 = framples(ind, 0), (res2 = 7500 + dur * 2500))
25140      snd_display("src_selection section: %s %s?", res1, res)
25141    end
25142    vals = freq_peak(0, ind, 512)
25143    if f5neq(vals[0], 500.0)
25144      snd_display("src_selection section 0 %s freq: %s?", sr, vals)
25145    end
25146    vals = freq_peak(((dur * 2500.0).floor + 7500) - 512, ind, 512)
25147    if f5neq(vals[0], 500.0)
25148      snd_display("src_selection section 8000 %s freq: %s?", sr, vals)
25149    end
25150    vals = freq_peak(1000, ind, 512)
25151    if f5neq(vals[0], 500.0 * sr)
25152      snd_display("src_selection section %s freq: %s?", sr, vals)
25153    end
25154    undo_edit
25155  end
25156  src_lists3.each do |e|
25157    src_selection(make_env(:envelope, e, :length, 2501))
25158    if f3neq(res1 = framples(ind, 0), (res2 = 7500 + src_duration(e) * 2500))
25159      snd_display("src_selection section (make_env duration) %s: %s (%s %s)?",
25160                  e, src_duration(e), res1, res2)
25161    end
25162    vals = freq_peak(0, ind, 256)
25163    if f5neq(vals[0], 500.0)
25164      snd_display("src_selection section (make_env 0): %s?", vals)
25165    end
25166    vals = freq_peak(((src_duration(e) * 2500).floor + 7500) - 256, ind, 256)
25167    if f5neq(vals[0], 500.0)
25168      snd_display("src_selection section (make_env 1): %s?", vals)
25169    end
25170    undo_edit
25171  end
25172  src_lists3.each do |e|
25173    src_selection(e)
25174    if f3neq(res1 = framples(ind, 0), (res2 = 7500 + src_duration(e) * 2500))
25175      snd_display("src_selection section (env duration) %s: %s (%s %s)?",
25176                  e, src_duration(e), res1, res2)
25177    end
25178    vals = freq_peak(0, ind, 256)
25179    if f5neq(vals[0], 500.0)
25180      snd_display("src_selection section (env 0): %s?", vals)
25181    end
25182    vals = freq_peak(((src_duration(e) * 2500).floor + 7500) - 256, ind, 256)
25183    if f5neq(vals[0], 500.0)
25184      snd_display("src_selection section (env 1): %s?", vals)
25185    end
25186    undo_edit
25187  end
25188  close_sound(ind)
25189end
25190
25191def test_15_03
25192  ind = new_sound("hi.snd")
25193  10.times do |i| set_sample(i, i * 0.1, ind) end
25194  select_all(ind)
25195  set_sample(10, 1.0, ind)
25196  smooth_selection
25197  unless vequal(channel2vct(0, 11, ind).subseq(0, 9), smoother(0.0, 1.0, 10).subseq(0, 9))
25198    snd_display("smooth_selection: %s %s?", channel2vct(0, 11, ind), smoother(0.0, 1.0, 10))
25199  end
25200  revert_sound
25201  10.times do |i| set_sample(i, 1.0 - i * 0.1, ind) end
25202  select_all(ind)
25203  set_sample(10, 0.0, ind)
25204  smooth_selection
25205  unless vequal(channel2vct(0, 11, ind).subseq(0, 9), smoother(1.0, 0.0, 10).subseq(0, 9))
25206    snd_display("smooth_selection back: %s %s?", channel2vct(0, 11, ind), smoother(1.0, 0.0, 10))
25207  end
25208  close_sound(ind)
25209  #
25210  ind = new_sound("hi.snd")
25211  10.times do |i| set_sample(i, i * 0.1, ind) end
25212  set_sample(10, 1.0, ind)
25213  smooth_sound(0, 10, ind)
25214  unless vequal(channel2vct(0, 11, ind).subseq(0, 9), smoother(0.0, 1.0, 10).subseq(0, 9))
25215    snd_display("smooth_sound: %s %s?", channel2vct(0, 11, ind), smoother(0.0, 1.0, 10))
25216  end
25217  revert_sound
25218  10.times do |i| set_sample(i, 1.0 - i * 0.1, ind) end
25219  set_sample(10, 0.0, ind)
25220  smooth_sound(0, 10, ind)
25221  unless vequal(channel2vct(0, 11, ind).subseq(0, 9), smoother(1.0, 0.0, 10).subseq(0, 9))
25222    snd_display("smooth_sound back: %s %s?", channel2vct(0, 11, ind), smoother(1.0, 0.0, 10))
25223  end
25224  close_sound(ind)
25225  delete_file("hi.snd")
25226  #
25227  ind = open_sound("oboe.snd")
25228  len = framples(ind)
25229  set_cursor(1200, ind)
25230  key(key_to_int(?u), 4, ind)
25231  key(key_to_int(?1), 0, ind)
25232  key(key_to_int(?0), 0, ind)
25233  key(key_to_int(?0), 0, ind)
25234  key(key_to_int(?o), 4, ind)
25235  snd_test_neq(framples(ind), 100 + len, "C-o len")
25236  data = channel2vct(1200, 100, ind)
25237  snd_test_neq(vct_peak(data), 0.0, "C-o")
25238  revert_sound(ind)
25239  set_cursor(1200, ind)
25240  key(key_to_int(?u), 4, ind)
25241  key(key_to_int(?1), 0, ind)
25242  key(key_to_int(?0), 0, ind)
25243  key(key_to_int(?0), 0, ind)
25244  key(key_to_int(?z), 4, ind)
25245  snd_test_neq(framples(ind), len, "C-z len")
25246  data = channel2vct(1200, 100, ind)
25247  snd_test_neq(vct_peak(data), 0.0, "C-z")
25248  set_cursor(0, ind)
25249  key(key_to_int(?u), 4, ind)
25250  key(key_to_int(?3), 0, ind)
25251  key(key_to_int(?.), 0, ind)
25252  key(key_to_int(?0), 0, ind)
25253  key(key_to_int(?z), 4, ind)
25254  if fneq(maxamp(ind, 0), 0.0)
25255    snd_display("C-z full: %s?", maxamp)
25256  end
25257  revert_sound(ind)
25258  set_cursor(1200, ind)
25259  key(key_to_int(?u), 4, ind)
25260  key(key_to_int(?1), 0, ind)
25261  key(key_to_int(?.), 0, ind)
25262  key(key_to_int(?0), 0, ind)
25263  key(key_to_int(?o), 4, ind)
25264  snd_test_neq(framples(ind), len + srate(ind), "C-o 1.0 len")
25265  data = channel2vct(1200, 100, ind)
25266  snd_test_neq(vct_peak(data), 0.0, "C-o 1.0")
25267  revert_sound(ind)
25268  set_cursor(1200, ind)
25269  key(key_to_int(?u), 4, ind)
25270  key(key_to_int(?1), 0, ind)
25271  key(key_to_int(?.), 0, ind)
25272  key(key_to_int(?0), 0, ind)
25273  key(key_to_int(?z), 4, ind)
25274  snd_test_neq(framples(ind), len, "C-z 1.0 len")
25275  data = channel2vct(1200, srate(ind), ind)
25276  snd_test_neq(vct_peak(data), 0.0, "C-z 1.0")
25277  close_sound(ind)
25278  #
25279  ind = open_sound("2.snd")
25280  set_sync(1, ind)
25281  key(key_to_int(?>), 4)
25282  key(key_to_int(?\s), 4)
25283  key(key_to_int(?<), 4)
25284  if (not (res1 = selection_member?(ind, 0))) or
25285      (not (res2 = selection_member?(ind, 1))) or
25286      (res3 = selection_position(ind, 0)) != 0 or
25287      (res4 = selection_position(ind, 1)) != 0 or
25288      (res5 = selection_framples(ind, 0)) != framples(ind, 0) or
25289      (res6 = selection_framples(ind, 1)) != framples(ind, 1)
25290    snd_display("sync selection via <-: %s %s %s %s %s %s?", res1, res2, res3, res4, res5, res6)
25291  end
25292  key(key_to_int(?\s), 4)
25293  key(key_to_int(?>), 4)
25294  if (not (res1 = selection_member?(ind, 0))) or
25295      (not (res2 = selection_member?(ind, 1))) or
25296      (res3 = selection_position(ind, 0)) != 0 or
25297      (res4 = selection_position(ind, 1)) != 0 or
25298      (res5 = selection_framples(ind, 0)) != framples(ind, 0) or
25299      (res6 = selection_framples(ind, 1)) != framples(ind, 1)
25300    snd_display("sync selection via ->: %s %s %s %s %s %s?", res1, res2, res3, res4, res5, res6)
25301  end
25302  set_cursor(0, ind, 1)
25303  set_cursor(1000, ind, 0)
25304  if (res = cursor(ind, 1)) != 1000
25305    snd_display("syncd cursors: %s %s?", cursor(ind, 0), res)
25306  end
25307  close_sound(ind)
25308  #
25309  ind = open_sound("oboe.snd")
25310  test_selection(ind, 1200, 100, 2.0)
25311  test_selection(ind, 600, 1200, 2.0)
25312  test_selection(ind, 0, 100, 2.0)
25313  test_selection(ind, 22500, 50827 - 22500, 0.5)
25314  test_selection(ind, 0, 50828, 0.5)
25315  #
25316  test_selection_to(ind, 1200, 100, 1.0)
25317  test_selection_to(ind, 600, 1200, 0.1)
25318  test_selection_to(ind, 0, 100, 0.5)
25319  test_selection_to(ind, 22500, 50827 - 22500, 2.0)
25320  test_selection_to(ind, 0, 50828, 0.5)
25321  #
25322  revert_sound(ind)
25323  make_selection(1200, 1200)
25324  unless selection?
25325    snd_display("no selection from 1 samp region?")
25326  end
25327  if (res = selection_framples) != 1
25328    snd_display("1 samp selection: %s samps?", res)
25329  end
25330  scale_selection_to(1.0)
25331  if fneq(res = sample(1200, ind, 0).abs, 1.0)
25332    snd_display("scale 1 samp selection: %s?", res)
25333  end
25334  revert_sound(ind)
25335  id = make_region(500, 1000)
25336  src_selection(0.5)
25337  if ((res = region_framples(id)) - 500).abs > 1
25338    snd_display("region_framples after src_selection: %s?", res)
25339  end
25340  reg_mix_id = mix_region(id, 1500, ind, 0).car
25341  if (res1 = mix_length(reg_mix_id)) != (res2 = region_framples(id))
25342    snd_display("mix_region: %s != %s?", res1, res2)
25343  end
25344  if (res = mix_home(reg_mix_id)) != [ind, 0, false, 0]
25345    snd_display("mix_region mix_home %s [%s, 0, false, 0]?", res, ind)
25346  end
25347  sel_mix_id = mix_selection(2500, ind, 0).car
25348  if (res1 = mix_length(sel_mix_id)) != (res2 = selection_framples)
25349    snd_display("mix_selection framples: %s != %s?", res1, res2)
25350  end
25351  if ((res1 = mix_length(reg_mix_id)) * 2 - (res2 = mix_length(sel_mix_id))).abs > 3
25352    snd_display("mix selection and region: %s %s %s %s?",
25353                res1, res2, region_framples(id), selection_framples)
25354  end
25355  if (res = mix_home(reg_mix_id)) != [ind, 0, false, 0]
25356    snd_display("mix_selection mix_home %s [%s, 0, false, 0]?", res, ind)
25357  end
25358  insert_selection(3000, ind, 0)
25359  insert_selection(3000, ind)
25360  mix_selection(3000, ind)
25361  delete_selection
25362  revert_sound(ind)
25363  close_sound(ind)
25364  #
25365  if File.exist?("storm.snd")
25366    ind = open_sound("storm.snd")
25367    set_sinc_width(10)
25368    with_time("src_sound(1.3)") do src_sound(1.3) end
25369    with_time("env_sound([0, 0, 1, 1, 2, 0])") do env_sound([0, 0, 1, 1, 2, 0]) end
25370    with_time("filter_sound, FIR direct form") do
25371      filter_sound([0, 1, 0.2, 0, 0.5, 1, 1, 0], 20)
25372    end
25373    with_time("filter_sound, convolution") do
25374      filter_sound([0, 0, 0.1, 0, 0.11, 1, 0.12, 0, 1, 0], 2048)
25375    end
25376    revert_sound(ind)
25377    reg = make_region(0, 123000, ind, 0)
25378    region2vct(reg, 0, 10, 0, Vct.new(10))
25379    ramp_channel(0.0, 1.0)
25380    ramp_channel(0.0, 1.0)
25381    ramp_channel(0.0, 1.0)
25382    ramp_channel(0.0, 1.0)
25383    close_sound(ind)
25384  end
25385  if File.exist?("1a.snd") and $all_args
25386    ind = open_sound("1a.snd")
25387    with_time("rubber_sound(1.25)") do rubber_sound(1.25) end
25388    close_sound(ind)
25389  end
25390  oboe = open_sound("oboe.snd")
25391  a4 = open_sound("4.aiff")
25392  sr = srate(oboe)
25393  save_sound_as("test.aif", oboe, :header_type, Mus_aifc)
25394  oboe_aif = open_sound("test.aif")
25395  if (res = header_type(oboe_aif)) != Mus_aifc
25396    snd_display("oboe_aif header: %s?", mus_header_type_name(res))
25397  end
25398  set_srate(oboe_aif, sr * 2)
25399  if fneq(res = srate(oboe_aif), sr * 2)
25400    snd_display("set_srate: %s %s?", sr * 2, res)
25401  end
25402  set_header_type(oboe_aif, Mus_next)
25403  if (res = header_type(oboe_aif)) != Mus_next
25404    snd_display("set_header: %s?", mus_header_type_name(res))
25405  end
25406  set_data_location(oboe_aif, 28)
25407  if (res = data_location(oboe_aif)) != 28
25408    snd_display("set_data_location: %s?", res)
25409  end
25410  set_sample_type(oboe_aif, Mus_mulaw)
25411  if (res = sample_type(oboe_aif)) != Mus_mulaw
25412    snd_display("set_sample_type: %s?", mus_sample_type_name(res))
25413  end
25414  save_sound_as("test.aif", oboe_aif, 22050, Mus_bshort, Mus_aifc, 0)
25415  close_sound(oboe_aif)
25416  delete_file("test.aif")
25417  set_selected_sound(a4)
25418  if selected_sound != a4
25419    snd_display("set_selected_sound: %s %s?", selected_sound, a4)
25420  end
25421  set_selected_channel(a4, 2)
25422  if selected_channel != 2
25423    snd_display("set_selected_channel a4: %s?", selected_channel(a4))
25424  end
25425  set_selected_channel(a4, 3)
25426  if selected_channel(a4) != 3
25427    snd_display("set_selected_channel a4: %s?", selected_channel(a4))
25428  end
25429  close_sound(a4)
25430  close_sound(oboe)
25431end
25432
25433def test_15_04
25434  if fneq(res = envelope_interp(0.1, [0, 0, 1, 1]), 0.1)
25435    snd_display("envelope_interp 0.1: %s?", res)
25436  end
25437  if fneq(res = envelope_interp(0.1, [0, 0, 1, 1], 32.0), 0.01336172)
25438    snd_display("envelope_interp 0.013: %s?", res)
25439  end
25440  if fneq(res = envelope_interp(0.1, [0, 0, 1, 1], 0.012), 0.36177473)
25441    snd_display("envelope_interp 0.361: %s?", res)
25442  end
25443  if fneq(res = envelope_interp(0.3, [0, 0, 0.5, 1, 1, 0]), 0.6)
25444    snd_display("envelope_interp 0.3 [0, 0, 0.5, 1, 1, 0]: %s?", res)
25445  end
25446  unless vequal(res = window_envelope(1.0, 3.0, [0, 0, 5, 1]), [1, 0.2, 3, 0.6])
25447    snd_display("window_envelope: %s?", res)
25448  end
25449  unless vequal(res = multiply_envelopes([0, 0, 1, 1], [0, 0, 1, 1, 2, 0]), [0, 0, 0.5, 0.5, 1, 0])
25450    snd_display("multiply_envelopes: %s?", res)
25451  end
25452  if fneq(res = max_envelope([0, 0, 1, 1, 2, 3, 4, 0]), 3.0)
25453    snd_display("0 max_envelope: %s?", res)
25454  end
25455  if fneq(res = max_envelope([0, 1]), 1.0)
25456    snd_display("1 max_envelope: %s?", res)
25457  end
25458  if fneq(res = max_envelope([0, 1, 1, 1, 2, 2]), 2.0)
25459    snd_display("2 max_envelope: %s?", res)
25460  end
25461  if fneq(res = max_envelope([0, -1, 1, -2]), -1.0)
25462    snd_display("3 max_envelope: %s?", res)
25463  end
25464  if fneq(res = max_envelope([0, -2, 1, -1]), -1.0)
25465    snd_display("4 max_envelope: %s?", res)
25466  end
25467  if fneq(res = min_envelope([0, 0, 1, 1, 2, 3, 4, 0]), 0.0)
25468    snd_display("0 min_envelope: %s?", res)
25469  end
25470  if fneq(res = min_envelope([0, 1]), 1.0)
25471    snd_display("1 min_envelope: %s?", res)
25472  end
25473  if fneq(res = min_envelope([0, 1, 1, 1, 2, 2]), 1.0)
25474    snd_display("2 min_envelope: %s?", res)
25475  end
25476  if fneq(res = min_envelope([0, -1, 1, -2]), -2.0)
25477    snd_display("3 min_envelope: %s?", res)
25478  end
25479  if fneq(res = min_envelope([0, -2, 1, -1]), -2.0)
25480    snd_display("4 min_envelope: %s?", res)
25481  end
25482  if fneq(res = integrate_envelope([0, 0, 1, 1]), 0.5)
25483    snd_display("0 integrate_envelope: %s?", res)
25484  end
25485  if fneq(res = integrate_envelope([0, 1, 1, 1]), 1.0)
25486    snd_display("1 integrate_envelope: %s?", res)
25487  end
25488  if fneq(res = integrate_envelope([0, 0, 1, 1, 2, 0.5]), 1.25)
25489    snd_display("2 integrate_envelope: %s?", res)
25490  end
25491  unless vequal(res = stretch_envelope([0, 0, 1, 1], 0.1, 0.2), [0, 0, 0.2, 0.1, 1, 1])
25492    snd_display("stretch_envelope att: %s?", res)
25493  end
25494  unless vequal(res = stretch_envelope([0, 0, 1, 1, 2, 0], 0.1, 0.2, 1.5, 1.6),
25495                [0, 0, 0.2, 0.1, 1.1, 1, 1.6, 0.5, 2, 0])
25496    snd_display("stretch_envelope dec: %s?", res)
25497  end
25498  unless vequal(res = add_envelopes([0, 0, 1, 1, 2, 0], [0, 0, 1, 1]), [0, 0, 0.5, 1.5, 1, 1])
25499    snd_display("add_envelopes: %s?", res)
25500  end
25501  unless vequal(res = scale_envelope([0, 0, 1, 1], 2.0), [0, 0, 1, 2])
25502    snd_display("scale_envelope: %s?", res)
25503  end
25504  unless vequal(res = scale_envelope([0, 0, 1, 1], 2.0, 1.0), [0, 1, 1, 3])
25505    snd_display("scale_envelope offset: %s?", res)
25506  end
25507  unless vequal(res = reverse_envelope([0, 0, 1, 1]), [0, 1, 1, 0])
25508    snd_display("0 reverse_envelope ramp: %s?", res)
25509  end
25510  unless vequal(res = reverse_envelope([0, 0, 0.5, 1, 2, 0]), [0, 0, 1.5, 1, 2, 0])
25511    snd_display("1 reverse_envelope ramp 2: %s?", res)
25512  end
25513  unless vequal(res = reverse_envelope([0, 0, 0.5, 1, 2, 1]), [0, 1, 1.5, 1, 2, 0])
25514    snd_display("2 reverse_envelope ramp 2: %s?", res)
25515  end
25516  unless vequal(res = concatenate_envelopes([0, 0, 1, 1], [0, 1, 1, 0]),
25517                [0, 0, 1, 1, 2, 0])
25518    snd_display("0 concatenate_envelopes: %s?", res)
25519  end
25520  unless vequal(res = concatenate_envelopes([0, 0, 1, 1.5], [0, 1, 1, 0]),
25521                [0, 0, 1, 1.5, 1.01, 1, 2.01, 0])
25522    snd_display("1 concatenate_envelopes: %s?", res)
25523  end
25524  unless vequal(res = repeat_envelope([0, 0, 1, 100], 2), [0, 0, 1, 100, 1.01, 0, 2.01, 100])
25525    snd_display("0 repeat_envelope: %s?", res)
25526  end
25527  unless vequal(res = repeat_envelope([0, 0, 1.5, 1, 2, 0], 2), [0, 0, 1.5, 1, 2, 0, 3.5, 1, 4, 0])
25528    snd_display("1 repeat_envelope: %s?", res)
25529  end
25530  unless vequal(res = repeat_envelope([0, 0, 1.5, 1, 2, 0], 2, false, true),
25531                [0, 0, 0.75, 1, 1, 0, 1.75, 1, 2, 0])
25532    snd_display("2 repeat_envelope: %s?", res)
25533  end
25534  unless vequal(res = repeat_envelope([0, 0, 1.5, 1, 2, 0], 2, true),
25535                [0, 0, 1.5, 1, 2, 0, 2.5, 1, 4, 0])
25536    snd_display("3 repeat_envelope: %s?", res)
25537  end
25538  unless vequal(res = repeat_envelope([0, 0, 1.5, 1, 2, 0], 3),
25539                [0, 0, 1.5, 1, 2, 0, 3.5, 1, 4, 0, 5.5, 1, 6, 0])
25540    snd_display("4 repeat_envelope: %s?", res)
25541  end
25542  unless vequal(res = normalize_envelope([0, 0, 1, 1.5, 2, 1.0]), [0, 0.0, 1, 1.0, 2, 0.667])
25543    snd_display("0 normalize_envelope: %s?", res)
25544  end
25545  unless vequal(res = normalize_envelope([0, 0, 1, 0.5, 2, -0.8]), [0, 0.0, 1, 0.625, 2, -1.0])
25546    snd_display("1 normalize_envelope: %s?", res)
25547  end
25548  unless vequal(res = envelope_exp([0, 0, 1, 1], 2.0, 10),
25549                [0.000, 0.000, 0.100, 0.010, 0.200, 0.040, 0.300, 0.090, 0.400, 0.160, 0.500,
25550                 0.250, 0.600, 0.360, 0.700, 0.490, 0.800, 0.640, 0.900, 0.810, 1.000, 1.000])
25551    snd_display("0 envelope_exp: %s?", res)
25552  end
25553  unless vequal(res = envelope_exp([0, 0, 1, 1, 2, 0], 1.0, 10),
25554                [0.000, 0.000, 0.200, 0.200, 0.400, 0.400, 0.600, 0.600, 0.800, 0.800, 1.000,
25555                 1.000, 1.200, 0.800, 1.400, 0.600, 1.600, 0.400, 1.800, 0.200, 2.000, 0.000])
25556    snd_display("1 envelope_exp: %s?", res)
25557  end
25558  #
25559  ind = new_sound("fmv.snd")
25560  vct2channel(Vct.new(20, 1.0))
25561  if selection?
25562    set_selection_member?(false, true)
25563  end
25564  make_selection(5, 9, ind, 0)
25565  scale_selection_to(0.5)
25566  insert_selection(15, ind)
25567  if (res = framples(ind)) != 25
25568    snd_display("insert_selection 5: %s?", res)
25569  end
25570  unless vequal(res = channel2vct(0, 25),
25571                vct(1.0, 1.0, 1.0, 1.0, 1.0, 0.5, 0.5, 0.5, 0.5, 0.5, 1.0, 1.0,
25572                    1.0, 1.0, 1.0, 0.5, 0.5, 0.5, 0.5, 0.5, 1.0, 1.0, 1.0, 1.0, 1.0))
25573    snd_display("insert_selection: %s?", res)
25574  end
25575  mix_selection(1, ind, 0)
25576  unless vequal(res = channel2vct(0, 10, ind, 0),
25577                vct(1.0, 1.5, 1.5, 1.5, 1.5, 1.0, 0.5, 0.5, 0.5, 0.5))
25578    snd_display("mix_selection vals: %s?", res)
25579  end
25580  close_sound(ind)
25581  #
25582  ind = new_sound("fmv.snd")
25583  old_size = transform_size.zero? ? 128 : transform_size
25584  old_type = transform_type
25585  old_norm = transform_normalization
25586  old_grf = transform_graph_type
25587  e = make_env([0, 0, 1, 2000 * 0.2 * PI], :length, 2001)
25588  v = Vct.new(2000) do |i|
25589    sin(env(e))
25590  end
25591  vct2channel(v, 0, 2000, ind, 0)
25592  set_transform_size(256, ind)
25593  set_transform_type($fourier_transform)
25594  set_transform_normalization(Normalize_by_channel)
25595  set_transform_graph_style(Graph_once)
25596  set_zero_pad(0)
25597  set_transform_graph?(true)
25598  make_selection(0, 200)
25599  set_show_selection_transform(true)
25600  set_selection_framples(300)
25601  update_transform_graph
25602  if vct?(data = transform2vct)
25603    pk = data.peak
25604    if pk.zero?
25605      snd_display("transform selection peak: %s?", pk)
25606    end
25607    if fneq(res = transform_sample(0), data[0])
25608      snd_display("transform_sample: %s, data: %s?", res, data[0])
25609    end
25610  else
25611    snd_display("transform2vct -> %s?", data)
25612  end
25613  set_zero_pad(100000)
25614  if zero_pad > 1000
25615    snd_display("zero_pad: %s?", zero_pad)
25616  end
25617  set_zero_pad(0)
25618  set_transform_size(old_size)
25619  set_transform_type(old_type)
25620  set_transform_normalization(old_norm)
25621  set_transform_graph_style(old_grf)
25622  close_sound(ind)
25623end
25624
25625def test_15
25626  set_transform_type($fourier_transform)
25627  test_15_00
25628  if $with_test_gui
25629    test_15_01
25630    test_15_02 # set_transform_size(0) in test_history_channel
25631    test_15_03
25632    test_15_04
25633  end
25634end
25635
25636# ---------------- test 16: regularized funcs ----------------
25637
25638def undo_env(snd, chn)
25639  if (len = (edits(snd, chn) or []).first) > 0
25640    1.upto(len) do |i|
25641      if (ed = edit_fragment(i, snd, chn)) and ed[1] == "env"
25642        set_edit_position(i - 1, snd, chn)
25643        return true
25644      end
25645    end
25646    false
25647  else
25648    false
25649  end
25650end
25651
25652def opt_test(choice)
25653  cursnd = Snd.sounds.pick
25654  curchn = random(channels(cursnd))
25655  cur_maxamps = []
25656  cur_edits = []
25657  cur_framples = []
25658  all_chans_zipped.each do |s, c|
25659    cur_maxamps << maxamp(s, c)
25660    cur_edits << edit_position(s, c)
25661    cur_framples << framples(s, c)
25662  end
25663  cur_amp = maxamp(cursnd, curchn)
25664  cur_edit = edit_position(cursnd, curchn)
25665  cur_frame = framples(cursnd, curchn)
25666  snd_lst, chn_lst = all_chans
25667  case choice
25668  when 0 # scale_channel
25669    scaler = (cur_amp < 1.0) ? (random(1.0) + 1.0) : (random(0.5) + 0.5)
25670    cur_loc = random(cur_frame)
25671    cur_samp = sample(cur_loc, cursnd, curchn)
25672    scale_channel(scaler, 0, cur_frame, cursnd, curchn)
25673    if (res = edit_position(cursnd, curchn)) != cur_edit + 1 and res != cur_edit
25674      snd_display("scale_channel %s[%s] edit pos: %s %s?",
25675                  short_file_name(cursnd), curchn, res, cur_edit)
25676    end
25677    if (res = framples(cursnd, curchn)) != cur_frame
25678      snd_display("scale_channel %s[%s] framples: %s %s?",
25679                  short_file_name(cursnd), curchn, res, cur_frame)
25680    end
25681    if fneq(res1 = maxamp(cursnd, curchn), res2 = scaler * cur_amp)
25682      snd_display("scale_channel %s[%s] maxamp: %s %s (%s, scaler: %s)?",
25683                  short_file_name(cursnd), curchn, res1, res2, (res1 - res2).abs, scaler)
25684    end
25685    if fneq(res1 = sample(cur_loc, cursnd, curchn), res2 = scaler * cur_samp)
25686      snd_display("scale_channel %s[%s] cur_samp: %s %s?",
25687                  short_file_name(cursnd), curchn, res1, res2)
25688    end
25689    snd_lst.zip(chn_lst, cur_maxamps, cur_edits, cur_framples) do |s, c, amp, ed, fr|
25690      if (not s == cursnd and c == curchn)
25691        if (res = edit_position(s, c)) != ed
25692          snd_display("scale_channel %s[%s] wrong edit pos: %s %s?", short_file_name(s), c, res, ed)
25693        end
25694        if (res = framples(s, c)) != fr
25695          snd_display("scale_channel %s[%s] wrong framples: %s %s?", short_file_name(s), c, res, fr)
25696        end
25697        if fneq(res = maxamp(s, c), amp)
25698          snd_display("scale_channel %s[%s] wrong maxamp: %s %s?", short_file_name(s), c, res, amp)
25699        end
25700      end
25701    end
25702  when 1 # scale_by
25703    maxscl = cur_maxamps.max
25704    scaler = (maxscl < 1.0) ? (random(1.0) + 1.0) : (random(0.5) + 0.5)
25705    scale_by(scaler, cursnd, curchn)
25706    snd_lst.zip(chn_lst, cur_maxamps, cur_edits, cur_framples) do |s, c, amp, ed, fr|
25707      if (sync(cursnd) == 0 and (s != cursnd or c != curchn)) or (sync(s) != sync(cursnd))
25708        if (res = edit_position(s, c)) != ed
25709          snd_display("scale_by %s[%s] wrong edit pos: %s %s?", short_file_name(s), c, res, ed)
25710        end
25711        if (res = framples(s, c)) != fr
25712          snd_display("scale_by %s[%s] wrong framples: %s %s?", short_file_name(s), c, res, fr)
25713        end
25714        if fneq(res = maxamp(s, c), amp)
25715          snd_display("scale_by %s[%s] wrong maxamp: %s %s?", short_file_name(s), c, res, amp)
25716        end
25717      else
25718        if (res = edit_position(s, c)) != ed + 1 and res != ed
25719          snd_display("scale_by %s[%s] wrong edit pos: %s %s?", short_file_name(s), c, res, ed + 1)
25720        end
25721        if (res = framples(s, c)) != fr
25722          snd_display("scale_by %s[%s] wrong framples: %s %s?", short_file_name(s), c, res, fr)
25723        end
25724        if fneq(res1 = maxamp(s, c), res2 =  amp * scaler)
25725          snd_display("scale_by %s[%s] wrong maxamp: %s %s?",
25726            short_file_name(s), c, res1, res2)
25727        end
25728      end
25729    end
25730  when 2 # env_channel
25731    pts = random(6) + 1
25732    maxpt = 0.0
25733    x = y = 0.0
25734    e = make_array(pts)
25735    0.step(pts - 1, 2) do |i|
25736      e[i] = x
25737      if random(3) > 0
25738        y = mus_random(1.0)
25739      end
25740      e[i + 1] = y
25741      if y.abs > maxpt
25742        maxpt = y.abs
25743      end
25744      x += 0.01 + random(1.0)
25745    end
25746    if undo_env(cursnd, curchn)
25747      cur_maxamps = []
25748      cur_edits = []
25749      cur_framples = []
25750      all_chans_zipped.each do |s, c|
25751        cur_maxamps << maxamp(s, c)
25752        cur_edits << edit_position(s, c)
25753        cur_framples << framples(s, c)
25754        cur_amp = maxamp(cursnd, curchn)
25755        cur_edit = edit_position(cursnd, curchn)
25756        cur_frame = framples(cursnd, curchn)
25757      end
25758    end
25759    env_channel(e, 0, cur_frame, cursnd, curchn)
25760    if (res = edit_position(cursnd, curchn)) != cur_edit + 1 and res != cur_edit
25761      snd_display("env_channel %s[%s] edit pos: %s %s?",
25762                  short_file_name(cursnd), curchn, res, cur_edit + 1)
25763    end
25764    if (res = framples(cursnd, curchn)) != cur_frame
25765      snd_display("env_channel %s[%s] framples: %s %s?",
25766                  short_file_name(cursnd), curchn, res, cur_frame)
25767    end
25768    if (res1 = maxamp(cursnd, curchn)) - 0.01 > (res2 = maxpt * cur_amp)
25769      snd_display("env_channel %s[%s] maxamp: %s %s from %s?",
25770                  short_file_name(cursnd), curchn, res1, res2, e)
25771      Snd.throw(:mus_error, "env_channel maxamp", short_file_name(cursnd))
25772    end
25773    snd_lst.zip(chn_lst, cur_maxamps, cur_edits, cur_framples) do |s, c, amp, ed, fr|
25774      unless s == cursnd and c == curchn
25775        if (res = edit_position(s, c)) != ed
25776          snd_display("env_channel %s[%s] wrong edit pos: %s %s?", short_file_name(s), c, res, ed)
25777        end
25778        if (res = framples(s, c)) != fr
25779          snd_display("env_channel %s[%s] wrong framples: %s %s?", short_file_name(s), c, res, fr)
25780        end
25781        if fneq(res = maxamp(s, c), amp)
25782          snd_display("env_channel %s[%s] wrong maxamp: %s %s?", short_file_name(s), c, res, amp)
25783        end
25784      end
25785    end
25786  when 3 # env_sound
25787    pts = random(6) + 1
25788    maxpt = 0.0
25789    x = y = 0.0
25790    e = make_array(pts)
25791    0.step(pts - 1, 2) do |i|
25792      e[i] = x
25793      if random(3) > 0
25794        y = mus_random(1.0)
25795      end
25796      e[i + 1] = y
25797      if y.abs > maxpt
25798        maxpt = y.abs
25799      end
25800      x += 0.01 + random(1.0)
25801    end
25802    recalc = false
25803    minfr = cur_framples.min
25804    beg = random((minfr / 2.0).floor)
25805    all_chans_zipped.each do |s, c|
25806      unless (sync(cursnd) == 0 and (s != cursnd or c != curchn)) or sync(s) != sync(cursnd)
25807        recalc = (recalc or undo_env(s, c))
25808      end
25809    end
25810    if recalc
25811      cur_maxamps = []
25812      cur_edits = []
25813      cur_framples = []
25814      all_chans_zipped.each do |s, c|
25815        cur_maxamps << maxamp(s, c)
25816        cur_edits << edit_position(s, c)
25817        cur_framples << framples(s, c)
25818      end
25819      cur_amp = maxamp(cursnd, curchn)
25820      cur_edit = edit_position(cursnd, curchn)
25821      cur_frame = framples(cursnd, curchn)
25822    end
25823    env_sound(e, beg, [pts, minfr - beg].max, 1.0, cursnd, curchn)
25824    snd_lst.zip(chn_lst, cur_maxamps, cur_edits, cur_framples) do |s, c, amp, ed, fr|
25825      if (sync(cursnd) == 0 and (s != cursnd or c != curchn)) or sync(s) != sync(cursnd)
25826        if (res = edit_position(s, c)) != ed
25827          snd_display("env_sound %s[%s] wrong edit pos: %s %s?", short_file_name(s), c, res, ed)
25828        end
25829        if (res = framples(s, c)) != fr
25830          snd_display("env_sound %s[%s] wrong framples: %s %s?", short_file_name(s), c, res, fr)
25831        end
25832        if fneq(res = maxamp(s, c), amp)
25833          snd_display("env_sound %s[%s] wrong maxamp: %s %s?", short_file_name(s), c, res, amp)
25834        end
25835      else
25836        if (res = edit_position(s, c)) != ed + 1 and res != ed
25837          snd_display("env_sound %s[%s] edit pos: %s %s?", short_file_name(s), c, res, ed + 1)
25838        end
25839        if (res = framples(s, c)) != fr
25840          snd_display("env_sound %s[%s] framples: fr %s orig_fr %s?", short_file_name(s), c, res, fr)
25841        end
25842      end
25843    end
25844  when 4 # scale_sound_by
25845    maxscl = cur_maxamps.max
25846    scaler = (maxscl < 1.0) ? (random(1.0) + 1.0) : (random(0.5) + 0.5)
25847    scale_sound_by(scaler, 1000, 1000, cursnd)
25848    snd_lst.zip(chn_lst, cur_maxamps, cur_edits, cur_framples) do |s, c, amp, ed, fr|
25849      if s != cursnd
25850        if (res = edit_position(s, c)) != ed
25851          snd_display("scale_sound_by %s[%s] wrong edit pos: %s %s?",
25852                      short_file_name(s), c, res, ed)
25853        end
25854        if (res = framples(s, c)) != fr
25855          snd_display("scale_sound_by %s[%s] wrong framples: %s %s?", short_file_name(s), c, res, fr)
25856        end
25857        if fneq(res = maxamp(s, c), amp)
25858          snd_display("scale_sound_by %s[%s] wrong maxamp: %s %s?", short_file_name(s), c, res, amp)
25859        end
25860      else
25861        if (res = edit_position(s, c)) != ed + 1 and res != ed
25862          snd_display("scale_sound_by %s[%s] wrong edit pos: %s %s?",
25863                      short_file_name(s), c, res, ed + 1)
25864        end
25865        if (res = framples(s, c)) != fr
25866          snd_display("scale_sound_by %s[%s] wrong framples: %s %s?", short_file_name(s), c, res, fr)
25867        end
25868      end
25869    end
25870  when 5
25871    if (pos = edit_position(cursnd, curchn)) > 0
25872      undo_edit(random(pos), cursnd, curchn)
25873    end
25874  when 6
25875    if (len = framples(cursnd, curchn)) > 10000
25876      delete_samples(random((len / 2).floor), random(100) + 10, cursnd, curchn)
25877    end
25878  when 7
25879    set_samples(random(framples(cursnd, curchn) + 100), random(100) + 10,
25880                Vct.new(10, 1.0), cursnd, curchn)
25881  when 8
25882    insert_samples(random(framples(cursnd, curchn) + 100), random(100) + 10,
25883                   Vct.new(10, 1.0), cursnd, curchn)
25884  when 9
25885    add_mark(random(framples(cursnd, curchn)), cursnd, curchn)
25886  when 10
25887    mix_vct(Vct.new(random(100) + 10, random(1.0)),
25888            random(framples(cursnd, curchn) + 100), cursnd, curchn)
25889  when 11
25890    pad_channel(random(framples(cursnd, curchn) + 100), random(100) + 10, cursnd, curchn)
25891  when 12
25892    pts = random(8) + 1
25893    maxpt = 0.0
25894    x = y = 0.0
25895    e = make_array(pts)
25896    0.step(pts - 1, 2) do |i|
25897      e[i] = x
25898      if random(3) > 0
25899        y = mus_random(1.0)
25900      end
25901      e[i + 1] = y
25902      if y.abs > maxpt
25903        maxpt = y.abs
25904      end
25905      x += 0.01 + random(1.0)
25906    end
25907    beg = random(framples(cursnd, curchn) - 300)
25908    dur = random(200) + 80
25909    reader0 = make_sampler(beg, cursnd, curchn)
25910    env_channel(e, beg, dur, cursnd, curchn)
25911    reader1 = make_sampler(beg, cursnd, curchn)
25912    en = make_env(:envelope, e, :length, dur)
25913    dur.times do |i|
25914      e0 = env(en)
25915      val00 = reader0.call
25916      val0 = e0 * val00
25917      val1 = reader1.call
25918      if (val0 - val1).abs > 0.005
25919        delete_file("baddy.rb")
25920        save_state("baddy.rb")
25921        snd_display("read env off by %s:\n# (%s) at %s: %s %s (%s %s) [%s %s]\n# %s",
25922                    (val0 - val1).abs, e, i, val0, val1, reader0, reader1, e0, val00,
25923                    safe_display_edits(cursnd, curchn))
25924        Snd_throw(:mus_error, "read env off at", i)
25925      end
25926    end
25927  when 13
25928    scale_channel(0.5, random(framples(cursnd, curchn) - 100), random(100) + 10, cursnd, curchn)
25929  when 14
25930    beg = random(framples(cursnd, curchn) - 200)
25931    scale_channel(0.5, beg, random(100) + 10, cursnd, curchn)
25932    scale_channel(0.5, beg + 10, random(100) + 10, cursnd, curchn)
25933  when 15
25934    beg = random(framples(cursnd, curchn) - 200)
25935    scale_channel(0.5, beg, random(100) + 10, cursnd, curchn)
25936    scale_channel(2.0, beg, random(100) + 10, cursnd, curchn)
25937  when 16
25938    beg = random(framples(cursnd, curchn) - 200)
25939    pad_channel(beg, random(100) + 10, cursnd, curchn)
25940    pad_channel(beg + 10, random(100) + 10, cursnd, curchn)
25941  when 17
25942    beg = random(framples(cursnd, curchn) - 200)
25943    pad_channel(beg, random(100) + 10, cursnd, curchn)
25944    pad_channel(beg, random(100) + 10, cursnd, curchn)
25945  when 18
25946    beg = random(framples(cursnd, curchn) - 200)
25947    delete_sample(beg, cursnd, curchn)
25948    delete_sample(beg + random(100), cursnd, curchn)
25949  when 19
25950    beg = random(framples(cursnd, curchn) + 200)
25951    set_sample(beg, 0.1, cursnd, curchn)
25952    set_sample(beg + random(100), 0.2, cursnd, curchn)
25953  when 20
25954    beg = random(framples(cursnd, curchn) - 200)
25955    ramp_channel(random(2.0) - 1.0, random(2.0) - 1.0, beg, random(100) + 10, cursnd, curchn)
25956  end
25957end
25958
25959def amp_envs_equal?(snd, chn, pos0, pos1, df)
25960  env0 = channel_amp_envs(snd, chn, pos0)
25961  env1 = channel_amp_envs(snd, chn, pos1)
25962  len0 = (env0 and list_p(env0) and env0.length == 2 and env0[1].length)
25963  len1 = (env1 and list_p(env1) and env1.length == 2 and env1[1].length)
25964  if len0 and len1
25965    minlen = [len0, len1].min
25966    inc0 = len0 / minlen
25967    inc1 = len1 / minlen
25968    e0 = env0[1]
25969    e1 = env1[1]
25970    if integer?(inc0) and integer?(inc1)
25971      minlen.times do |i|
25972        max0 = -1.0
25973        max1 = -1.0
25974        if inc0 == 1
25975          max0 = e0[i]
25976        else
25977          inc0.times do |j|
25978            nmx = e0[j + inc0 * i]
25979            if nmx > max0
25980              max0 = nmx
25981            end
25982          end
25983        end
25984        if inc1 == 1
25985          max1 = e1[i]
25986        else
25987          inc1.times do |j|
25988            nmx = e1[j + inc1 * i]
25989            if nmx > max1
25990              max1 = nmx
25991            end
25992          end
25993        end
25994        if (max0 - max1).abs > df
25995          snd_display_prev_caller(snd_format_neq(max0, max1, "amp_env[%d of %d], df %1.4f",
25996                                                 i, minlen, df))
25997        end
25998      end
25999    else
26000      snd_display_prev_caller("lens: %s %s?", len0, len1)
26001    end
26002  end
26003  true
26004end
26005
26006def vequal_at(v0, v1)
26007  v0.each_with_index do |val, i|
26008    if fneq_err(val, v1[i], 0.001)
26009      return [i, val, v1[i]]
26010    end
26011  end
26012  false
26013end
26014
26015def edits_not_equal?(tl0, tl1)
26016  tl0.each_with_index do |t0, i|
26017    t1 = tl1[i]
26018    if t0[0] != t1[0] or
26019        t0[1] != t1[1] or
26020        t0[2] != t1[2] or
26021        t0[3] != t1[3] or
26022        fneq(t0[4], t1[4]) or
26023        fneq(t0[5], t1[5]) or
26024        fneq(t0[6], t1[6])
26025      return [i, t0, t1]
26026    end
26027  end
26028  false
26029end
26030
26031def check_edit_tree(expected_tree, expected_vals, name)
26032  current_vals = channel2vct
26033  len = current_vals.length
26034  if expected_vals and len != expected_vals.length
26035    snd_display_prev_caller("%s: lengths differ: %s %s?", name, len, expected_vals.length)
26036  else
26037    if expected_vals and (not vequal(current_vals, expected_vals))
26038      snd_display_prev_caller("checking %s, vals disagree (loc, dur, expect):\n# %s?",
26039                              name, vequal_at(current_vals, expected_vals))
26040    else
26041      tree = edit_tree
26042      if bad_data = edits_not_equal?(tree, expected_tree)
26043        snd_display_prev_caller("checking %s, trees disagree (loc, cur, expect):\n# %s\n# in %s?",
26044                                name, bad_data, tree)
26045      end
26046      if len > 5
26047        split_loc = 2 + random(len - 3)
26048        fread = make_sampler(split_loc)
26049        bread = make_sampler(split_loc - 1, false, false, -1)
26050        split_vals = Vct.new(len)
26051        split_loc.upto(len - 1) do |i| split_vals[i] = fread.call end
26052        (split_loc - 1).downto(0) do |i| split_vals[i] = bread.call end
26053        if expected_vals and (not vequal(split_vals, expected_vals))
26054          snd_display_prev_caller("checking %s, split vals disagree (loc, cur, expect):\n# %s?",
26055                                  name, vequal_at(split_vals, expected_vals))
26056        end
26057      end
26058    end
26059  end
26060end
26061
26062def reversed_read(snd, chn)
26063  len = framples(snd, chn)
26064  sf  = make_sampler(len - 1, snd, chn, -1)
26065  Vct.new(len) do read_sample(sf) end.reverse
26066end
26067
26068def init_sound(val, dur, chns)
26069  ind = new_sound("test.snd", chns, 22050, Mus_bshort, Mus_next)
26070  chns.times do |chn|
26071    insert_silence(0, dur, ind, chn)
26072    map_channel(lambda do |y| val end, 0, framples, ind, chn)
26073  end
26074  ind
26075end
26076
26077def check_back_and_forth(ind, name, v)
26078  happy = true
26079  unless vequal(res = channel2vct(0, framples, ind, 0), v)
26080    happy = false
26081    snd_display_prev_caller("%s forth: %s %s?", name, res, v)
26082  end
26083  unless vequal(res = reversed_read(ind, 0), v)
26084    happy = false
26085    snd_display_prev_caller("%s back: %s %s?", name, res, v)
26086  end
26087  happy
26088end
26089
26090def check_both_chans(ind, name, f0, f1)
26091  if (c0 = scan_channel(f0, 0, framples, ind, 0))
26092    snd_display_prev_caller("%s swap c0: %s?", name, c0)
26093  end
26094  if (c1 = scan_channel(f1, 0, framples, ind, 1))
26095    snd_display_prev_caller("%s swap c1: %s?", name, c1)
26096  end
26097end
26098
26099def test_16_00
26100  oboe = open_sound("oboe.snd")
26101  [[lambda do scale_channel(2.0, 0, 0, oboe) end, :scale_channel],
26102   [lambda do
26103      env_channel(make_env([0, 0, 1, 1], :length, 123), 0, 0, oboe)
26104    end, :env_channel],
26105   [lambda do clm_channel(make_oscil, 0, 0, oboe) end, :clm_channel],
26106   [lambda do vct2channel(make_vct(3), 0, 0, oboe) end, :vct2channel],
26107   [lambda do smooth_channel(0, 0, oboe) end, :smooth_channel],
26108   [lambda do pad_channel(0, 0, oboe) end, :pad_channel],
26109   [lambda do src_channel(2.0, 0, 0, oboe) end, :src_channel],
26110   [lambda do mix_channel("pistol.snd", 0, 0, oboe) end, :mix_channel],
26111   [lambda do insert_channel("pistol.snd", 0, 0, oboe) end, :insert_channel],
26112   [lambda do reverse_channel(0, 0, oboe) end, :reverse_channel],
26113   [lambda do scale_sound_by(2.0, 0, 0, oboe) end, :scale_sound_by],
26114   [lambda do env_sound([0, 0, 1, 1], 0, 0, oboe) end, :env_sound],
26115   [lambda do set_samples(0, 0, Vct.new(3), oboe) end, :set_samples],
26116   [lambda do smooth_sound(0, 0, oboe) end, :smooth_soundxs],
26117   [lambda do
26118      insert_silence(0, 0, oboe)
26119    end, :insert_silence]].each do |func, name|
26120    func.call
26121    if (res = edit_position(oboe)) != 0
26122      snd_display("dur: 0 %s: %s %s?", name, res, edit_fragment)
26123    end
26124  end
26125  [[lambda do scale_channel(2.0, -1, 123, oboe) end, :scale_channel],
26126   [lambda do
26127      env_channel(make_env([0, 0, 1, 1], :length, 123), -1, 123, oboe)
26128    end, :env_channel],
26129   [lambda do clm_channel(make_oscil, -1, 123, oboe) end, :clm_channel],
26130   [lambda do vct2channel(make_vct(3), -1, 123, oboe) end, :vct2channel],
26131   [lambda do smooth_channel(-1, 123, oboe) end, :smooth_channel],
26132   [lambda do pad_channel(-1, 123, oboe) end, :pad_channel],
26133   [lambda do src_channel(2.0, -1, 123, oboe) end, :src_channel],
26134   [lambda do mix_channel("pistol.snd", -1, 123, oboe) end, :mix_channel],
26135   [lambda do insert_channel("pistol.snd", -1, 123, oboe) end, :insert_channel],
26136   [lambda do reverse_channel(-1, 123, oboe) end, :reverse_channel],
26137   [lambda do scale_sound_by(2.0, -1, 123, oboe) end, :scale_sound_by],
26138   [lambda do env_sound([0, 0, 1, 1], -1, 123, oboe) end, :env_sound],
26139   [lambda do set_samples(-1, 123, Vct.new(3), oboe) end, :set_samples],
26140   [lambda do smooth_sound(-1, 123, oboe) end, :smooth_soundxs],
26141   [lambda do
26142      insert_silence(-1, 123, oboe)
26143    end, :insert_silence]].each do |func, name|
26144    if (res = Snd.catch do func.call end).first != :no_such_sample
26145      snd_display("%s beg -1 -> %s", name, res.inspect)
26146    end
26147    if (res = edit_position(oboe)) != 0
26148      snd_display("beg: -1 %s: %s %s?", name, res, edit_fragment)
26149    end
26150  end
26151  [[lambda do scale_channel(2.0, 12345678, 123, oboe) end, :scale_channel],
26152   [lambda do
26153      env_channel(make_env([0, 0, 1, 1], :length, 123), 12345678, 123, oboe)
26154    end, :env_channel],
26155   [lambda do smooth_channel(12345678, 123, oboe) end, :smooth_channel],
26156   [lambda do src_channel(2.0, 12345678, 123, oboe) end, :src_channel],
26157   [lambda do
26158      reverse_channel(12345678, 123, oboe)
26159    end, :reverse_channel]].each do |func, name|
26160    func.call
26161    if (res = edit_position(oboe)) != 0
26162      snd_display("beg: 12345678 %s: %s %s?", name, res, edit_fragment)
26163    end
26164  end
26165  pos = 0
26166  [[lambda do scale_channel(2.0, 0, 123, oboe, 0) end, :scale_channel],
26167   [lambda do
26168      env_channel(make_env([0, 0, 1, 1], :length, 123), 0, 123, oboe, 0)
26169    end, :env_channel],
26170   [lambda do clm_channel(make_oscil, 0, 123, oboe, 0) end, :clm_channel],
26171   [lambda do vct2channel(make_vct(3), 0, 123, oboe, 0) end, :vct2channel],
26172   [lambda do smooth_channel(0, 123, oboe, 0) end, :smooth_channel],
26173   [lambda do pad_channel(0, 123, oboe, 0) end, :pad_channel],
26174   [lambda do src_channel(2.0, 0, 123, oboe, 0) end, :src_channel],
26175   [lambda do mix_channel("pistol.snd", 0, 123, oboe, 0) end, :mix_channel],
26176   [lambda do
26177      insert_channel("pistol.snd", 0, 123, oboe, 0)
26178    end, :insert_channel],
26179   [lambda do reverse_channel(0, 123, oboe, 0) end, :reverse_channel],
26180   [let(rd = make_sampler(0),
26181        make_src(:srate, 2.0,
26182                 :input, lambda do |dir| rd.call end)) do |rd, sr|
26183      lambda do clm_channel(sr, 0, 12345, oboe, 0) end
26184    end, "clm_channel src"],
26185   [let(rd = make_sampler(0),
26186        make_granulate(:expansion, 2.0,
26187                       :input, lambda do |dir| rd.call end)) do |rd, gr|
26188      lambda do clm_channel(gr, 0, 12345, oboe, 0) end
26189    end, "clm_channel granulate"],
26190   [let(rd = make_sampler(0),
26191        make_convolve(:input, lambda do |dir| rd.call end,
26192                      :filter, vct(1, 0, 0))) do |rd, cv|
26193      lambda do clm_channel(cv, 0, 12345, oboe, 0) end
26194    end, "clm_channel convolve"],
26195   [let(rd = make_sampler(0),
26196        make_phase_vocoder(:input, lambda do |dir| rd.call end)) do |rd, pv|
26197      lambda do clm_channel(pv, 0, 12345, oboe, 0) end
26198    end, "clm_channel phase_vocoder"]].each do |func, name|
26199    func.call
26200    if (res = edit_position(oboe)) != pos += 1
26201      snd_display("%s[%s]: %s %s?", name, pos, res, edit_fragment)
26202    end
26203  end
26204  #
26205  revert_sound(oboe)
26206  [[lambda do scale_channel(2.0, 0, 123, oboe, 0, 123) end, :scale_channel],
26207   [lambda do
26208      env_channel(make_env([0, 0, 1, 1], :length, 123), 0, 123, oboe, 0, 123)
26209    end, :env_channel],
26210   [lambda do clm_channel(make_oscil, 0, 123, oboe, 0, 123) end, :clm_channel],
26211   [lambda do vct2channel(make_vct(3), 0, 123, oboe, 0, 123) end, :vct2channel],
26212   [lambda do smooth_channel(0, 123, oboe, 0, 123) end, :smooth_channel],
26213   [lambda do pad_channel(0, 123, oboe, 0, 123) end, :pad_channel],
26214   [lambda do src_channel(2.0, 0, 123, oboe, 0, 123) end, :src_channel],
26215   [lambda do
26216      mix_channel("pistol.snd", 0, 123, oboe, 0, 123)
26217    end, :mix_channel],
26218   [lambda do
26219      insert_channel("pistol.snd", 0, 123, oboe, 0, 123)
26220    end, :insert_channel],
26221   [lambda do
26222      reverse_channel(0, 123, oboe, 0, 123)
26223    end, :reverse_channel]].each do |func, name|
26224    if (res = Snd.catch do func.call end).first != :no_such_edit
26225      snd_display("bad edpos %s: %s", name, res.inspect)
26226    end
26227    if (res = edit_position(oboe)) != 0
26228      snd_display("edpos: 123 %s: %s %s?", name, res, edit_fragment)
26229    end
26230  end
26231  revert_sound(oboe)
26232  oldv = channel2vct(1000, 10, oboe)
26233  mix_channel("oboe.snd", 0)
26234  oldv.scale!(2.0)
26235  unless vequal(res = channel2vct(1000, 10, oboe), oldv)
26236    snd_display("mix_channel at 0: %s %s?", oldv, res)
26237  end
26238  revert_sound(oboe)
26239  oldv.scale!(0.5)
26240  insert_channel("oboe.snd", 0)
26241  unless vequal(res = channel2vct(1000, 10, oboe), oldv)
26242    snd_display("insert_channel at 0: %s %s?", oldv, res)
26243  end
26244  if (res1 = framples(oboe, 0)) != (res2 = framples(oboe, 0, 0)) * 2
26245    snd_display("insert_channel framples: %s %s?", res1, res2)
26246  end
26247  revert_sound(oboe)
26248  close_sound(oboe)
26249end
26250
26251def funcs_equal?(name, func0, func1, oboe0, oboe1)
26252  func0.call(false, false, oboe0)
26253  func1.call(false, false, oboe1)
26254  res1 = channel2vct(1000, 100, oboe0)
26255  res2 = channel2vct(1000, 100, oboe1)
26256  snd_test_neq(channel2vct(1000, 100, oboe0), channel2vct(1000, 100, oboe1),
26257               "%s via false", name)
26258  revert_sound(oboe0)
26259  revert_sound(oboe1)
26260  select_sound(oboe0)
26261  func0.call
26262  select_sound(oboe1)
26263  func1.call
26264  snd_test_neq(channel2vct(1000, 100, oboe0), channel2vct(1000, 100, oboe1),
26265               "%s via none", name)
26266  revert_sound(oboe0)
26267  revert_sound(oboe1)
26268  func0.call(0, framples(oboe0), oboe0)
26269  func1.call(0, framples(oboe1), oboe1)
26270  snd_test_neq(channel2vct(1000, 100, oboe0), channel2vct(1000, 100, oboe1),
26271               "%s via 0 framples", name)
26272  revert_sound(oboe0)
26273  revert_sound(oboe1)
26274end
26275
26276def test_16_01
26277  if default_output_chans != 1
26278    set_default_output_chans(1)
26279  end
26280  ind = new_sound("fmv.snd")
26281  v0 = Vct.new(20, 1.0)
26282  vct2channel(v0)
26283  if framples != 20
26284    snd_display("vct2channel new 20: %s?", framples)
26285  end
26286  if fneq(maxamp, 1.0)
26287    snd_display("vct 1->new: %s?", maxamp)
26288  end
26289  env_channel(make_env(:envelope, [0, 0, 1, 1, 2, 1], :base, 0, :length, 20))
26290  if (res = channel2vct) != vct(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
26291    snd_display("env_channel step 1: %s?", res)
26292  end
26293  undo_edit
26294  env_channel(make_env(:envelope, [0, 0, 1, 1, 2, 1], :base, 0, :length, 20), 8)
26295  if (res = channel2vct) != vct(1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1)
26296    snd_display("env_channel step 1 at 8: %s?", res)
26297  end
26298  undo_edit
26299  env_channel(make_env(:envelope, [0, 0, 1, 1, 2, 1], :base, 0, :length, 12))
26300  if (res = channel2vct) != vct(0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
26301    snd_display("env_channel step 1 at 0: %s?", res)
26302  end
26303  undo_edit
26304  env_channel(make_env(:envelope, [0, 0, 1, 1, 2, 1], :base, 0, :length, 12), 4)
26305  if (res = channel2vct) != vct(1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
26306    snd_display("env_channel step 1 at 4: %s?", res)
26307  end
26308  undo_edit
26309  env_channel(make_env(:envelope, [0, 0, 1, 1, 2, 1], :base, 0, :length, 12), 4, 3)
26310  if (res = channel2vct) != vct(1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
26311    snd_display("env_channel step 1 at 4 by 3: %s?", res)
26312  end
26313  undo_edit
26314  env_channel(make_env(:envelope, [0, 1, 1, 0, 2, 0], :base, 0, :length, 8), 0, 12)
26315  if (res = channel2vct) != vct(1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1)
26316    snd_display("env_channel step 1 at 0 for 7: %s?", res)
26317  end
26318  undo_edit
26319  env_channel(make_env(:envelope, [0, 0, 1, 1, 2, 1, 3, 0, 4, 0], :base, 0, :length, 20))
26320  if (res = channel2vct) != vct(0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0)
26321    snd_display("env_channel step 1: %s?", res)
26322  end
26323  undo_edit
26324  env_channel(make_env(:envelope, [0, 0, 1, 0.5, 2, 0.25, 3, 0, 4, 0], :base, 0, :length, 21))
26325  if (res = channel2vct) != vct(0, 0, 0, 0, 0, 0, 0.5, 0.5, 0.5, 0.5,
26326                                0.5, 0.25, 0.25, 0.25, 0.25, 0.25, 0, 0, 0, 0)
26327    snd_display("env_channel step 1 (0.5): %s?", res)
26328  end
26329  close_sound(ind)
26330  #
26331  set_x_axis_style(X_axis_as_percentage)
26332  ind = open_sound("2.snd")
26333  fr = framples
26334  m0 = maxamp(ind, 0)
26335  m1 = maxamp(ind, 1)
26336  set_sync(64, ind)
26337  insert_sound("2.snd")
26338  insert_sound("2.snd")
26339  if framples != fr * 3
26340    snd_display("2.snd 3x = %s %s?", fr, framples)
26341  end
26342  if (res1 = framples(ind, 0)) != (res2 = framples(ind, 1))
26343    snd_display("insert synced: %s %s?", res1, res2)
26344  end
26345  swap_channels
26346  if fneq(res1 = maxamp(ind, 1), m0) or fneq(res2 = maxamp(ind, 0), m1)
26347    snd_display("swapped: %s %s -> %s %s?", m0, m1, res1, res2)
26348  end
26349  close_sound(ind)
26350  set_x_axis_style(X_axis_in_seconds)
26351  new_snd = mono_files2stereo("test.snd", "oboe.snd", "pistol.snd")
26352  if channels(new_snd) != 2
26353    snd_display("mono_files2stereo not stereo: %s?", channels(new_snd))
26354  end
26355  if (res = short_file_name(new_snd)) != "test.snd"
26356    snd_display("mono_files2stereo filename: %s?", res)
26357  end
26358  if (res = framples(new_snd)) != 50828
26359    snd_display("mono_files2stereo framples: %s?", res)
26360  end
26361  close_sound(new_snd)
26362  #
26363  oboe0 = open_sound("oboe.snd")
26364  oboe1 = open_sound("oboe.snd")
26365  funcs_equal?(:scale_sound_by,
26366               lambda { |*args| scale_sound_by(2.0, *args)},
26367               lambda { |*args| scale_channel(2.0, *args)},
26368               oboe0, oboe1)
26369  funcs_equal?(:scale_and_ramp_0,
26370               lambda { |*args| scale_sound_by(0.0, *args)},
26371               lambda { |*args| ramp_channel(0.0, 0.0, *args)},
26372               oboe0, oboe1)
26373  funcs_equal?(:scale_and_ramp_2,
26374               lambda { |*args| scale_sound_by(2.0, *args)},
26375               lambda { |*args| ramp_channel(2.0, 2.0, *args)},
26376               oboe0, oboe1)
26377  funcs_equal?(:smooth_sound,
26378               lambda { |*args| smooth_sound(*args)},
26379               lambda { |*args| smooth_channel(*args)},
26380               oboe0, oboe1)
26381  funcs_equal?(:env_sound,
26382               lambda { |*args|
26383                 beg = (args[0] or 0)
26384                 len = (args[1] and number?(args[1])) ? (args[1] - 1) : false
26385                 snd = (args[2] or selected_sound)
26386                 env_sound([0, 0, 1, 1], beg, len, 1.0, snd)
26387               },
26388               lambda { |*args|
26389                 snd = (args[2] or selected_sound)
26390                 len = (args[1] and number?(args[1])) ? args[1] : (framples(snd) - 1)
26391                 env_channel(make_env(:envelope, [0, 0, 1, 1], :length, len), *args)
26392               },
26393               oboe0, oboe1)
26394  funcs_equal?(:map_chan,
26395               lambda { |*args|
26396                 beg = (args[0] or 0)
26397                 len = (args[1] and number?(args[1])) ? (args[1] - 1) : false
26398                 snd = (args[2] or selected_sound)
26399                 map_chan(lambda { |n| n * 2 }, beg, len, "testing...", snd)
26400               },
26401               lambda { |*args|
26402                 beg = (args[0] or 0)
26403                 len = (args[1] and number?(args[1])) ? (args[1] - 1) : false
26404                 snd = (args[2] or selected_sound)
26405                 map_channel(lambda { |n| n * 2 }, beg, len, snd)
26406               }, oboe0, oboe1)
26407  funcs_equal?(:src_sound,
26408               lambda { |*args| src_sound(2.0, 1.0, (args[2] or false)) },
26409               lambda { |*args| src_channel(2.0, *args) },
26410               oboe0, oboe1)
26411  funcs_equal?(:reverse_sound,
26412               lambda { |*args| reverse_sound((args[2] or false)) },
26413               lambda { |*args| reverse_channel(*args) },
26414               oboe0, oboe1)
26415  funcs_equal?(:mix,
26416               lambda { |*args| mix("pistol.snd", 0, 0, (args[2] or false)) },
26417               lambda { |*args| mix_channel("pistol.snd", *args) },
26418               oboe0, oboe1)
26419  funcs_equal?(:insert_sound,
26420               lambda { |*args| insert_sound("pistol.snd", 0, 0, (args[2] or false)) },
26421               lambda { |*args| insert_channel("pistol.snd", *args) },
26422               oboe0, oboe1)
26423  close_sound(oboe0)
26424  close_sound(oboe1)
26425  #
26426  ind = open_sound("oboe.snd")
26427  scale_by(0.5)
26428  scale_by(0.25)
26429  undo_edit
26430  [[lambda { |n| scale_channel(0.5, 0, false, n, 0, 2) }, :scale_channel],
26431   [lambda { |n| env_channel([0, 0, 1, 1, 2, 0], 0, false, n, 0, 2) }, :env_channel],
26432   [lambda { |n| pad_channel(0, 100, n, 0, 2) }, :pad_channel_0],
26433   [lambda { |n| pad_channel(100, 100, n, 0, 2) }, :pad_channel_100],
26434   [lambda { |n| delete_sample(100, n, 0, 2) }, :delete_sample],
26435   [lambda { |n| set_sample(100, 0.52, n, 0, 2) }, :set_sample]].each do |func, name|
26436    if (res = Snd.catch do func.call(ind) end).first != :no_such_edit
26437      snd_display("%s upon about-to-be-clobbered data: %s", name, res.inspect)
26438    end
26439  end
26440  close_sound(ind)
26441  #
26442  ind = open_sound("oboe.snd")
26443  ind1 = new_sound("test.snd")
26444  old_save_dir = save_dir
26445  set_save_dir(false)
26446  map_channel(lambda do |y| 0.5 end, 0, 100, ind1, 0)
26447  save_sound(ind1)
26448  close_sound(ind1)
26449  insert_sound("test.snd", 12345)
26450  delete_file("hiho.rb")
26451  vals = channel2vct(12345 - 50, 200, ind, 0)
26452  save_state("hiho.rb")
26453  close_sound(ind)
26454  Snd.regions.apply(:forget_region)
26455  load("hiho.rb")
26456  ind = find_sound("oboe.snd")
26457  if sound?(ind)
26458    unless vequal(res = channel2vct(12345 - 50, 200, ind, 0), vals)
26459      snd_display("save_state hiho vals:\n# %s\n# %s?", vals, res)
26460    end
26461  else
26462    snd_display("save hiho failed?")
26463  end
26464  close_sound(ind)
26465  set_save_dir(old_save_dir)
26466  #
26467  set_x_axis_style(X_axis_in_beats)
26468  ind = open_sound("storm.snd")
26469  reverse_channel(500000, 1000000)
26470  set_sample(0, 0.1, ind, 0, Current_edit_position)
26471  if fneq(res = sample(0, ind, 0, Current_edit_position), 0.1)
26472    snd_display("set_sample + edpos: %s?", res)
26473  end
26474  close_sound(ind)
26475  set_x_axis_style(X_axis_in_seconds)
26476  #
26477  [1, 2, 4].each do |out_chans|
26478    ind = new_sound("new.snd", out_chans, 22050, Mus_bfloat, Mus_next,
26479                    "edpos testing")
26480    mx = Snd.sounds.map do |s| sync(s) end.max
26481    set_sync(mx + 1, ind)
26482    ["2a.snd", "1a.snd", "4a.snd"].each do |in_snd|
26483      [lambda do |posfunc|
26484         chn = [random(out_chans + 1), out_chans - 1].min
26485         res = channel2vct(0, framples(ind, chn), ind, chn, 0)
26486         unless vequal(res, vct(0.0))
26487           snd_display("start bad: %s?", res)
26488         end
26489         set_sample(0, 0.1, ind, chn)
26490         res = channel2vct(0, framples(ind, chn), ind, chn)
26491         unless vequal(res, vct(0.1))
26492           snd_display("set bad: %s?", res)
26493         end
26494         pad_channel(0, 1, ind, chn, posfunc.call)
26495         if proc?(pos = posfunc.call)
26496           pos = pos.call(ind, chn)
26497         end
26498         data = channel2vct(0, framples(ind, chn), ind, chn)
26499         if (pos.zero? and (not vequal(data, vct(0.0, 0.0)))) or
26500            ((pos == Current_edit_position or
26501              pos == edit_position(ind, chn)) and
26502             (not vequal(data, vct(0.0, 0.1)))) or
26503            (pos == edit_position(ind, chn) - 1 and
26504             (not vequal(data, vct(0.0, 0.0))))
26505           snd_display("pos[%s]: edpos %s of %s, pad result[%s, %s]: %s?",
26506                       chn, pos,
26507                       edit_position(ind, chn),
26508                       framples(ind, chn, pos),
26509                       framples(ind, chn),
26510                       data)
26511         end
26512         if channels(ind) > 1
26513           channels(ind).times do |i|
26514             next if chn == i
26515             res = channel2vct(0, framples(ind, i), ind, i)
26516             unless vequal(res, vct(0.0))
26517               snd_display("pad[%s / %s] empty: %s?", i, chn, data)
26518             end
26519           end
26520         end
26521       end,
26522       lambda do |posfunc|
26523         chn = [random(out_chans + 1), out_chans - 1].min
26524         set_sample(0, 0.1, ind, chn)
26525         set_sample(0, sample(0, ind, chn, posfunc.call()) * 2.0,
26526                    ind, chn, posfunc.call())
26527         if proc?(pos = posfunc.call)
26528           pos = pos.call(ind, chn)
26529         end
26530         data = channel2vct(0, framples(ind, chn), ind, chn)
26531         if (pos.zero? and (not vequal(data, vct(0.0)))) or
26532            ((pos == Current_edit_position or
26533              pos == edit_position(ind, chn)) and
26534             (not vequal(data, vct(0.2)))) or
26535            (pos == edit_position(ind, chn) - 1 and
26536             (not vequal(data, vct(0.0))))
26537           snd_display("pos[%s]: edpos %s of %s, set *2 result[%s, %s]: %s?",
26538                       chn, pos,
26539                       edit_position(ind, chn),
26540                       framples(ind, chn, pos),
26541                       framples(ind, chn),
26542                       data)
26543         end
26544         if channels(ind) > 1
26545           channels(ind).times do |i|
26546             next if chn == i
26547             res = channel2vct(0, framples(ind, i), ind, i)
26548             unless vequal(res, vct(0.0))
26549               snd_display("scale[%s / %s] empty: %s?", i, chn, data)
26550             end
26551           end
26552         end
26553       end].each do |func|
26554        [lambda do Current_edit_position end,
26555         lambda do 0 end,
26556         lambda do edit_position(ind, 0) - 1 end,
26557         lambda do edit_position(ind, 0) end].each do |edpos|
26558          func.call(edpos)
26559          revert_sound(ind)
26560        end
26561      end
26562    end
26563    close_sound(ind)
26564  end
26565  #
26566  ind = open_sound("oboe.snd")
26567  map_channel(lambda do |y| false end)
26568  if framples(ind) != 0
26569    snd_display("map_channel false framples: %s?", framples(ind))
26570  end
26571  if edits(ind) == [0, 0]
26572    snd_display("map_channel false edits backed up")
26573  end
26574  undo_edit(1, ind)
26575  if framples(ind) == 0
26576    snd_display("map_channel false framples after undo: %s?", framples(ind))
26577  end
26578  if (res = Snd.catch do
26579        map_channel(lambda do |y| "hiho" end)
26580      end).first != :bad_type
26581    snd_display("map_channel bad_type: %s", res.inspect)
26582  end
26583  ctr = 0
26584  if (res = Snd.catch do
26585        scan_channel(lambda do |y|
26586                       ctr += 1
26587                       asdf
26588                     end)
26589      end).first != :name_error
26590    snd_display("scan_channel unbound: %s", res.inspect)
26591  end
26592  if ctr != 1
26593    snd_display("scan_channel error exit: %s?", ctr)
26594  end
26595  if res = scan_channel(lambda do |y| false end)
26596    snd_display("scan_channel func false: %s?", res)
26597  end
26598  if res = scan_channel(lambda do |y| false end, 1234)
26599    snd_display("scan_channel func false with beg: %s?", res)
26600  end
26601  if res = scan_channel(lambda do |y| false end, 1234, 4321)
26602    snd_display("scan_channel func false with beg+dur: %s?", res)
26603  end
26604  revert_sound(ind)
26605  del = make_delay(1000)
26606  len = framples
26607  clm_channel(del, 0, len, ind, 0, 0, 2000)
26608  if framples(ind) != len + 2000
26609    snd_display("clm_channel overlap length: %s %s?", len, framples)
26610  end
26611  if edit_tree != [[0, 1, 0, 52827, 1.0, 0.0, 0.0, 0], [52828, -2, 0, 0, 0.0, 0.0, 0.0, 0]]
26612    snd_display("clm_channel overlaps: %s?", edit_tree)
26613  end
26614  reader = make_sampler(0)
26615  preader = make_sampler(0, ind, 0, 1, 0)
26616  1000.times do |i|
26617    if fneq(res = reader.call, 0.0)
26618      snd_display("clm_channel overlap delayed[%s]: %s?", i, res)
26619      break
26620    end
26621  end
26622  len.times do |i|
26623    if fneq(res1 = reader.call, res2 = preader.call)
26624      snd_display("clm_channel overlap main[%s]: %s %s?", i + 1000, res1, res2)
26625      break
26626    end
26627  end
26628  1000.times do |i|
26629    if fneq(res = reader.call, 0.0)
26630      snd_display("clm_channel overlap trailing garbage[%s]: %s?", i, res)
26631      break
26632    end
26633  end
26634  close_sound(ind)
26635  #
26636  ind = open_sound("oboe.snd")
26637  oldamp = 0.0
26638  oldloc = 0
26639  ctr = 0
26640  scan_channel(lambda { |y|
26641                 if y.abs >= oldamp
26642                   oldloc = ctr
26643                   oldamp = y.abs
26644                 end
26645                 ctr += 1
26646                 false
26647               })
26648  scale_by(10.0)
26649  scale_by(0.1)
26650  reverse_channel(0, false, ind, 0, 1)
26651  amp = 0.0
26652  loc = 0
26653  ctr = framples - 1
26654  scan_channel(lambda { |y|
26655                 if y.abs > amp
26656                   amp = y.abs
26657                   loc = ctr
26658                 end
26659                 ctr -= 1
26660                 false
26661               })
26662  if fneq(oldamp, amp * 0.1) or loc != oldloc
26663    snd_display("reverse edpos screwup: %s at %s, %s at %s?", oldamp, oldloc, amp, loc)
26664  end
26665  reverse_channel(0, false, ind, 0, 2)
26666  amp = 0.0
26667  loc = 0
26668  ctr = framples - 1
26669  scan_channel(lambda { |y|
26670                 if y.abs > amp
26671                   amp = y.abs
26672                   loc = ctr
26673                 end
26674                 ctr -= 1
26675                 false
26676               })
26677  if fneq(oldamp, amp) or loc != oldloc
26678    snd_display("reverse unscaled edpos screwup: %s at %s, %s at %s?", oldamp, oldloc, amp, loc)
26679  end
26680  close_sound(ind)
26681end
26682
26683class Mus
26684  alias old_call call
26685  alias call run
26686end
26687
26688def check_env(name, r, e, dur)
26689  dur.times do |i|
26690    if fneq(rv = r.call, ev = e.call)
26691      snd_display("%s env check [%s]: %s %s?", name, i, rv, ev)
26692      return
26693    end
26694  end
26695end
26696
26697def test_16_02
26698  mus_clipping and set_mus_clipping(false)
26699  clipping and set_clipping(false)
26700  ind = new_sound("fmv.snd", 1, 22050, Mus_bfloat, Mus_next, "edit trees")
26701  select_sound(ind)
26702  select_channel(0)
26703  check_edit_tree([[0, 0, 0, 0, 0.0, 0.0, 0.0, 1],
26704                   [1, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
26705                  Vct.new(1), "initial new_sound")
26706  vals = Vct.new(100, 1.0)
26707  set_samples(0, 100, vals)
26708  check_edit_tree([[0, 1, 0, 99, 1.0, 0.0, 0.0, 1],
26709                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
26710                  vals, "set first samps to one")
26711  scale_channel(0.5, 10, 20)
26712  10.upto(29) do |i| vals[i] = 0.5 end
26713  check_edit_tree([[0, 1, 0, 9, 1.0, 0.0, 0.0, 1],
26714                   [10, 1, 10, 29, 0.5, 0.0, 0.0, 0],
26715                   [30, 1, 30, 99, 1.0, 0.0, 0.0, 0],
26716                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
26717                  vals, "scale_channel(0.5, 10, 20)")
26718  env_channel(make_env(:envelope, [0, 0, 1, 1], :length, 11), 15, 10)
26719  e = make_env(:envelope, [0, 0, 1, 1], :length, 11)
26720  15.upto(24) do |i| vals[i] *= env(e) end
26721  check_edit_tree([[0, 1, 0, 9, 1.0, 0.0, 0.0, 0],
26722                   [10, 1, 10, 14, 0.5, 0.0, 0.0, 0],
26723                   [15, 1, 15, 24, 0.5, 0.0, 0.1, 1],
26724                   [25, 1, 25, 29, 0.5, 0.0, 0.0, 0],
26725                   [30, 1, 30, 99, 1.0, 0.0, 0.0, 0],
26726                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
26727                  vals, "env_channel(15, 10)")
26728  normalize_channel(1.0)
26729  check_edit_tree([[0, 1, 0, 9, 1.0, 0.0, 0.0, 0],
26730                   [10, 1, 10, 14, 0.5, 0.0, 0.0, 0],
26731                   [15, 1, 15, 24, 0.5, 0.0, 0.1, 1],
26732                   [25, 1, 25, 29, 0.5, 0.0, 0.0, 0],
26733                   [30, 1, 30, 99, 1.0, 0.0, 0.0, 0],
26734                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
26735                  vals, "env_channel(15, 10) a")
26736  select_all
26737  if fneq(res = selection_maxamp, 1.0)
26738    snd_display("selection_maxamp in checker: %s?", res)
26739  end
26740  scale_selection_to(1.0)
26741  check_edit_tree([[0, 1, 0, 9, 1.0, 0.0, 0.0, 0],
26742                   [10, 1, 10, 14, 0.5, 0.0, 0.0, 0],
26743                   [15, 1, 15, 24, 0.5, 0.0, 0.1, 1],
26744                   [25, 1, 25, 29, 0.5, 0.0, 0.0, 0],
26745                   [30, 1, 30, 99, 1.0, 0.0, 0.0, 0],
26746                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
26747                  vals, "env_channel(15, 10) b")
26748  set_selection_position(5)
26749  set_selection_framples(10)
26750  scale_selection_to(0.5)
26751  5.upto(14) do |i| vals[i] *= 0.5 end
26752  check_edit_tree([[0, 1, 0, 4, 1.0, 0.0, 0.0, 0],
26753                   [5, 1, 5, 9, 0.5, 0.0, 0.0, 0],
26754                   [10, 1, 10, 14, 0.25, 0.0, 0.0, 0],
26755                   [15, 1, 15, 24, 0.5, 0.0, 0.1, 1],
26756                   [25, 1, 25, 29, 0.5, 0.0, 0.0, 0],
26757                   [30, 1, 30, 99, 1.0, 0.0, 0.0, 0],
26758                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
26759                  vals, "scale_selection_to(0.5)")
26760  set_sample(20, 0.1)
26761  vals[20] = 0.1
26762  check_edit_tree([[0, 1, 0, 4, 1.0, 0.0, 0.0, 0],
26763                   [5, 1, 5, 9, 0.5, 0.0, 0.0, 0],
26764                   [10, 1, 10, 14, 0.25, 0.0, 0.0, 0],
26765                   [15, 1, 15, 19, 0.5, 0.0, 0.1, 1],
26766                   [20, 2, 0, 0, 1.0, 0.0, 0.0, 0],
26767                   [21, 1, 21, 24, 0.5, 0.6, 0.1, 4],
26768                   [25, 1, 25, 29, 0.5, 0.0, 0.0, 0],
26769                   [30, 1, 30, 99, 1.0, 0.0, 0.0, 0],
26770                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
26771                  vals, "set_sample(20, 0.1)")
26772  reverse_channel(5, 10)
26773  j = 14
26774  5.upto(9) do |i|
26775    vals[i], vals[j] = vals[j], vals[i]
26776    j -= 1
26777  end
26778  check_edit_tree([[0, 1, 0, 4, 1.0, 0.0, 0.0, 0],
26779                   [5, 3, 0, 9, 1.0, 0.0, 0.0, 0],
26780                   [15, 1, 15, 19, 0.5, 0.0, 0.1, 1],
26781                   [20, 2, 0, 0, 1.0, 0.0, 0.0, 0],
26782                   [21, 1, 21, 24, 0.5, 0.6, 0.1, 4],
26783                   [25, 1, 25, 29, 0.5, 0.0, 0.0, 0],
26784                   [30, 1, 30, 99, 1.0, 0.0, 0.0, 0],
26785                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
26786                  vals, "reverse_channel(5, 10)")
26787  if fneq(res = selection_maxamp, 0.5)
26788    snd_display("selection_maxamp before: %s?", res)
26789  end
26790  mixvals = Vct.new(10, 0.1)
26791  old_sample4 = sample(4)
26792  old_sample5 = sample(5)
26793  id = mix_vct(mixvals, 4)
26794  4.upto(13) do |i| vals[i] += mixvals[i - 4] end
26795  check_edit_tree([[0, 1, 0, 3, 1.0, 0.0, 0.0, 0],
26796                   [4, 1, 4, 4, 1.0, 0.0, 0.0, 1],
26797                   [5, 3, 0, 8, 1.0, 0.0, 0.0, 1],
26798                   [14, 3, 9, 9, 1.0, 0.0, 0.0, 0],
26799                   [15, 1, 15, 19, 0.5, 0.0, 0.1, 4],
26800                   [20, 2, 0, 0, 1.0, 0.0, 0.0, 0],
26801                   [21, 1, 21, 24, 0.5, 0.6, 0.1, 4],
26802                   [25, 1, 25, 29, 0.5, 0.0, 0.0, 0],
26803                   [30, 1, 30, 99, 1.0, 0.0, 0.0, 0],
26804                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
26805                  vals,
26806                  format("mix_vct(id: %s (%s) [%s, %s] + 0.1 -> [%s, %s] [%s, %s]) 4 (0.1)",
26807                         id, ind, old_sample4, old_sample5, sample(4), sample(5), vals[4], vals[5]))
26808  delete_samples(28, 12)
26809  insert_silence(28, 12)
26810  28.upto(39) do |i| vals[i] = 0.0 end
26811  old_vals = vals.dup
26812  check_edit_tree([[0, 1, 0, 3, 1.0, 0.0, 0.0, 0],
26813                   [4, 1, 4, 4, 1.0, 0.0, 0.0, 1],
26814                   [5, 3, 0, 8, 1.0, 0.0, 0.0, 1],
26815                   [14, 3, 9, 9, 1.0, 0.0, 0.0, 0],
26816                   [15, 1, 15, 19, 0.5, 0.0, 0.1, 4],
26817                   [20, 2, 0, 0, 1.0, 0.0, 0.0, 0],
26818                   [21, 1, 21, 24, 0.5, 0.6, 0.1, 4],
26819                   [25, 1, 25, 27, 0.5, 0.0, 0.0, 0],
26820                   [28, -1, 0, 11, 0.0, 0.0, 0.0, 0],
26821                   [40, 1, 40, 99, 1.0, 0.0, 0.0, 0],
26822                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
26823                  vals, "delete_samples(28, 12); insert_silence(28, 12)")
26824  if fneq(res = selection_maxamp, 0.6)
26825    snd_display("selection_maxamp after: %s?", res)
26826  end
26827  set_selection_position(50)
26828  set_selection_framples(10)
26829  scale_selection_by(0.1)
26830  if fneq(res = selection_maxamp, 0.1)
26831    snd_display("re-selection_maxamp: %s?", res)
26832  end
26833  50.upto(59) do |i| vals[i] = 0.1 end
26834  check_edit_tree([[0, 1, 0, 3, 1.0, 0.0, 0.0, 0],
26835                   [4, 1, 4, 4, 1.0, 0.0, 0.0, 1],
26836                   [5, 3, 0, 8, 1.0, 0.0, 0.0, 1],
26837                   [14, 3, 9, 9, 1.0, 0.0, 0.0, 0],
26838                   [15, 1, 15, 19, 0.5, 0.0, 0.1, 1],
26839                   [20, 2, 0, 0, 1.0, 0.0, 0.0, 0],
26840                   [21, 1, 21, 24, 0.5, 0.6, 0.1, 4],
26841                   [25, 1, 25, 27, 0.5, 0.0, 0.0, 0],
26842                   [28, -1, 0, 11, 0.0, 0.0, 0.0, 0],
26843                   [40, 1, 40, 49, 1.0, 0.0, 0.0, 0],
26844                   [50, 1, 50, 59, 0.1, 0.0, 0.0, 0],
26845                   [60, 1, 60, 99, 1.0, 0.0, 0.0, 0],
26846                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
26847                  vals, "scale_selection_by(0.1)")
26848  env_channel(make_env(:envelope, [0, 0, 1, 1, 2, 0, 3, 0], :length, 31, :base, 0), 50, 30)
26849  e = make_env(:envelope, [0, 0, 1, 1, 2, 0, 3, 0], :length, 31, :base, 0)
26850  50.upto(79) do |i| vals[i] *= env(e) end
26851  check_edit_tree([[0, 1, 0, 3, 1.0, 0.0, 0.0, 0],
26852                   [4, 1, 4, 4, 1.0, 0.0, 0.0, 1],
26853                   [5, 3, 0, 8, 1.0, 0.0, 0.0, 1],
26854                   [14, 3, 9, 9, 1.0, 0.0, 0.0, 0],
26855                   [15, 1, 15, 19, 0.5, 0.0, 0.1, 4],
26856                   [20, 2, 0, 0, 1.0, 0.0, 0.0, 0],
26857                   [21, 1, 21, 24, 0.5, 0.6, 0.1, 4],
26858                   [25, 1, 25, 27, 0.5, 0.0, 0.0, 0],
26859                   [28, -1, 0, 11, 0.0, 0.0, 0.0, 0],
26860                   [40, 1, 40, 49, 1.0, 0.0, 0.0, 0],
26861                   [50, 1, 50, 59, 0.0, 0.0, 0.0, 0],
26862                   [60, 1, 60, 60, 0.0, 0.0, 0.0, 0],
26863                   [61, 1, 61, 70, 1.0, 0.0, 0.0, 0],
26864                   [71, 1, 71, 79, 0.0, 0.0, 0.0, 0],
26865                   [80, 1, 80, 99, 1.0, 0.0, 0.0, 0],
26866                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
26867                  vals, "step env 30")
26868  undo_channel(2)
26869  check_edit_tree([[0, 1, 0, 3, 1.0, 0.0, 0.0, 0],
26870                   [4, 1, 4, 4, 1.0, 0.0, 0.0, 1],
26871                   [5, 3, 0, 8, 1.0, 0.0, 0.0, 1],
26872                   [14, 3, 9, 9, 1.0, 0.0, 0.0, 0],
26873                   [15, 1, 15, 19, 0.5, 0.0, 0.1, 4],
26874                   [20, 2, 0, 0, 1.0, 0.0, 0.0, 0],
26875                   [21, 1, 21, 24, 0.5, 0.6, 0.1, 4],
26876                   [25, 1, 25, 27, 0.5, 0.0, 0.0, 0],
26877                   [28, -1, 0, 11, 0.0, 0.0, 0.0, 0],
26878                   [40, 1, 40, 99, 1.0, 0.0, 0.0, 0],
26879                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
26880                  old_vals, "undo to delete/insert (over step env)")
26881  redo_channel(2)
26882  check_edit_tree([[0, 1, 0, 3, 1.0, 0.0, 0.0, 0],
26883                   [4, 1, 4, 4, 1.0, 0.0, 0.0, 1],
26884                   [5, 3, 0, 8, 1.0, 0.0, 0.0, 1],
26885                   [14, 3, 9, 9, 1.0, 0.0, 0.0, 0],
26886                   [15, 1, 15, 19, 0.5, 0.0, 0.1, 4],
26887                   [20, 2, 0, 0, 1.0, 0.0, 0.0, 0],
26888                   [21, 1, 21, 24, 0.5, 0.6, 0.1, 4],
26889                   [25, 1, 25, 27, 0.5, 0.0, 0.0, 0],
26890                   [28, -1, 0, 11, 0.0, 0.0, 0.0, 0],
26891                   [40, 1, 40, 49, 1.0, 0.0, 0.0, 0],
26892                   [50, 1, 50, 59, 0.0, 0.0, 0.0, 0],
26893                   [60, 1, 60, 60, 0.0, 0.0, 0.0, 0],
26894                   [61, 1, 61, 70, 1.0, 0.0, 0.0, 0],
26895                   [71, 1, 71, 79, 0.0, 0.0, 0.0, 0],
26896                   [80, 1, 80, 99, 1.0, 0.0, 0.0, 0],
26897                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
26898                  vals, "redo past step env 30")
26899  set_sample(75, -0.5)
26900  vals[75] = -0.5
26901  flt = make_one_zero(0.5, 0.5)
26902  flt1 = make_one_zero(0.5, 0.5)
26903  clm_channel(flt, 75, 10)
26904  75.upto(84) do |i| vals[i] = one_zero(flt1, vals[i]) end
26905  check_edit_tree([[0, 1, 0, 3, 1.0, 0.0, 0.0, 0],
26906                   [4, 1, 4, 4, 1.0, 0.0, 0.0, 1],
26907                   [5, 3, 0, 8, 1.0, 0.0, 0.0, 1],
26908                   [14, 3, 9, 9, 1.0, 0.0, 0.0, 0],
26909                   [15, 1, 15, 19, 0.5, 0.0, 0.1, 4],
26910                   [20, 2, 0, 0, 1.0, 0.0, 0.0, 0],
26911                   [21, 1, 21, 24, 0.5, 0.6, 0.1, 4],
26912                   [25, 1, 25, 27, 0.5, 0.0, 0.0, 0],
26913                   [28, -1, 0, 11, 0.0, 0.0, 0.0, 0],
26914                   [40, 1, 40, 49, 1.0, 0.0, 0.0, 0],
26915                   [50, 1, 50, 59, 0.0, 0.0, 0.0, 0],
26916                   [60, 1, 60, 60, 0.0, 0.0, 0.0, 0],
26917                   [61, 1, 61, 70, 1.0, 0.0, 0.0, 0],
26918                   [71, 1, 71, 74, 0.0, 0.0, 0.0, 0],
26919                   [75, 6, 0, 9, 1.0, 0.0, 0.0, 0],
26920                   [85, 1, 85, 99, 1.0, 0.0, 0.0, 0],
26921                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
26922                  vals, "clm_channel(flt, 75, 10)")
26923  map_channel(lambda do |y| y * 0.5 end, 3, 11)
26924  3.upto(13) do |i| vals[i] *= 0.5 end
26925  check_edit_tree([[0, 1, 0, 2, 1.0, 0.0, 0.0, 0],
26926                   [3, 8, 0, 10, 1.0, 0.0, 0.0, 0],
26927                   [14, 7, 10, 11, 1.0, 0.0, 0.0, 0],
26928                   [16, 1, 16, 19, 0.5, 0.1, 0.1, 4],
26929                   [20, 2, 0, 0, 1.0, 0.0, 0.0, 0],
26930                   [21, 1, 21, 24, 0.5, 0.6, 0.1, 4],
26931                   [25, 1, 25, 27, 0.5, 0.0, 0.0, 0],
26932                   [28, -1, 0, 11, 0.0, 0.0, 0.0, 2],
26933                   [40, 1, 40, 49, 1.0, 0.0, 0.0, 0],
26934                   [50, 1, 50, 59, 0.0, 0.0, 0.0, 0],
26935                   [60, 1, 60, 60, 0.0, 0.0, 0.0, 0],
26936                   [61, 1, 61, 70, 1.0, 0.0, 0.0, 0],
26937                   [71, 1, 71, 74, 0.0, 0.0, 0.0, 0],
26938                   [75, 6, 0, 9, 1.0, 0.0, 0.0, 0],
26939                   [85, 1, 85, 99, 1.0, 0.0, 0.0, 0],
26940                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
26941                  vals, "map_channel 3 14")
26942  reader = make_sampler(50)
26943  map_channel(lambda do |y| y - reader.call end, 0, 25)
26944  25.times do |i| vals[i] -= vals[i + 50] end
26945  check_edit_tree([[0, 9, 0, 24, 1.0, 0.0, 0.0, 0],
26946                   [25, 1, 25, 27, 0.5, 0.0, 0.0, 0],
26947                   [28, -1, 0, 11, 0.0, 0.0, 0.0, 2],
26948                   [40, 1, 40, 49, 1.0, 0.0, 0.0, 0],
26949                   [50, 1, 50, 59, 0.0, 0.0, 0.0, 2],
26950                   [60, 1, 60, 60, 0.0, 0.0, 0.0, 2],
26951                   [61, 1, 61, 70, 1.0, 0.0, 0.0, 0],
26952                   [71, 1, 71, 74, 0.0, 0.0, 0.0, 2],
26953                   [75, 6, 0, 9, 1.0, 0.0, 0.0, 0],
26954                   [85, 1, 85, 99, 1.0, 0.0, 0.0, 0],
26955                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
26956                  vals, "back set via map_channel")
26957  set_selection_position(20)
26958  set_selection_framples(70)
26959  env_selection([0, 0, 1, 1])
26960  if fneq(res = selection_maxamp(ind, 0), 1.0)
26961    snd_display("selection_maxamp after env_selection: %s?", res)
26962  end
26963  x = 0.0
26964  incr = 1.0 / 69.0
26965  20.upto(89) do |i|
26966    vals[i] *= x
26967    x += incr
26968  end
26969  check_edit_tree([[0, 9, 0, 19, 1.0, 0.0, 0.0, 0],
26970                   [20, 9, 20, 24, 1.0, 0.0, 0.0145, 4],
26971                   [25, 1, 25, 27, 0.5, 0.072, 0.0145, 4],
26972                   [28, -1, 0, 11, 0.0, 0.0, 0.0, 2],
26973                   [40, 1, 40, 49, 1.0, 0.2898, 0.0145, 4],
26974                   [50, 1, 50, 59, 0.0, 0.0, 0.0, 2],
26975                   [60, 1, 60, 60, 0.0, 0.0, 0.0, 2],
26976                   [61, 1, 61, 70, 1.0, 0.5942, 0.0145, 4],
26977                   [71, 1, 71, 74, 0.0, 0.0, 0.0, 2],
26978                   [75, 6, 0, 9, 1.0, 0.7971, 0.0145, 4],
26979                   [85, 1, 85, 89, 1.0, 0.942, 0.0145, 4],
26980                   [90, 1, 90, 99, 1.0, 0.0, 0.0, 0],
26981                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
26982                  vals, "env_selection([0, 0, 1, 1])")
26983  normalize_channel(0.5)
26984  vals.scale!(0.5)
26985  check_edit_tree([[0, 9, 0, 19, 0.5, 0.0, 0.0, 0],
26986                   [20, 9, 20, 24, 0.5, 0.0, 0.0145, 4],
26987                   [25, 1, 25, 27, 0.25, 0.0725, 0.0145, 4],
26988                   [28, -1, 0, 11, 0.0, 0.0, 0.0, 2],
26989                   [40, 1, 40, 49, 0.5, 0.2898, 0.0145, 4],
26990                   [50, 1, 50, 59, 0.0, 0.0, 0.0, 2],
26991                   [60, 1, 60, 60, 0.0, 0.0, 0.0, 2],
26992                   [61, 1, 61, 70, 0.5, 0.5942, 0.0145, 4],
26993                   [71, 1, 71, 74, 0.0, 0.0, 0.0, 2],
26994                   [75, 6, 0, 9, 0.5, 0.7971, 0.0145, 4],
26995                   [85, 1, 85, 89, 0.5, 0.942, 0.0145, 4],
26996                   [90, 1, 90, 99, 0.5, 0.0, 0.0, 0],
26997                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
26998                  vals, "normalize_channel(0.5)")
26999  if fneq(res = selection_maxamp, 0.5)
27000    snd_display("selection_maxamp after scl: %s?", res)
27001  end
27002  delete_samples(0, 100)
27003  insert_silence(0, 100)
27004  vals.fill(0.0)
27005  check_edit_tree([[0, -1, 0, 99, 0.0, 0.0, 0.0, 0],
27006                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27007                  vals, "second set...")
27008  set_sample(50, 0.5)
27009  vals[50] = 0.5
27010  check_edit_tree([[0, -1, 0, 49, 0.0, 0.0, 0.0, 2],
27011                   [50, 10, 0, 0, 1.0, 0.0, 0.0, 0],
27012                   [51, -1, 51, 99, 0.0, 0.0, 0.0, 2],
27013                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27014                  vals, "split silence")
27015  map_channel($init_channel, 0, 25)
27016  25.times do |i| vals[i] = 1.0 end
27017  check_edit_tree([[0, 11, 0, 24, 1.0, 0.0, 0.0, 0],
27018                   [25, -1, 25, 49, 0.0, 0.0, 0.0, 2],
27019                   [50, 10, 0, 0, 1.0, 0.0, 0.0, 0],
27020                   [51, -1, 51, 99, 0.0, 0.0, 0.0, 2],
27021                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27022                  vals, "clobber silence start")
27023  map_channel($init_channel, 75, 25)
27024  75.upto(99) do |i| vals[i] = 1.0 end
27025  check_edit_tree([[0, 11, 0, 24, 1.0, 0.0, 0.0, 0],
27026                   [25, -1, 25, 49, 0.0, 0.0, 0.0, 2],
27027                   [50, 10, 0, 0, 1.0, 0.0, 0.0, 0],
27028                   [51, -1, 51, 74, 0.0, 0.0, 0.0, 2],
27029                   [75, 12, 0, 24, 1.0, 0.0, 0.0, 0],
27030                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27031                  vals, "clobber silence end")
27032  scale_channel(0.0, 0, 100)
27033  vals.fill(0.0)
27034  check_edit_tree([[0, 0, 0, 99, 0.0, 0.0, 0.0, 1],
27035                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27036                  vals, "scale_channel(0.0, 0, 100)")
27037  e = make_env(:envelope, [0, 0, 1, 1], :length, 101)
27038  e1 = make_env(:envelope, [0, 0, 1, 1], :length, 101)
27039  map_channel(lambda do |y| env(e) end)
27040  vals.map! do |val| env(e1) end
27041  check_edit_tree([[0, 13, 0, 99, 1.0, 0.0, 0.0, 0],
27042                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27043                  vals, "env start")
27044  set_sample(50, -0.5)
27045  vals[50] = -0.5
27046  check_edit_tree([[0, 13, 0, 49, 1.0, 0.0, 0.0, 0],
27047                   [50, 14, 0, 0, 1.0, 0.0, 0.0, 0],
27048                   [51, 13, 51, 99, 1.0, 0.0, 0.0, 0],
27049                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27050                  vals, "split env segment")
27051  map_channel($init_channel, 0, 25)
27052  25.times do |i| vals[i] = 1.0 end
27053  check_edit_tree([[0, 15, 0, 24, 1.0, 0.0, 0.0, 0],
27054                   [25, 13, 25, 49, 1.0, 0.0, 0.0, 0],
27055                   [50, 14, 0, 0, 1.0, 0.0, 0.0, 0],
27056                   [51, 13, 51, 99, 1.0, 0.0, 0.0, 0],
27057                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27058                  vals, "clobber env start")
27059  map_channel($init_channel, 75, 25)
27060  75.upto(99) do |i| vals[i] = 1.0 end
27061  check_edit_tree([[0, 15, 0, 24, 1.0, 0.0, 0.0, 0],
27062                   [25, 13, 25, 49, 1.0, 0.0, 0.0, 0],
27063                   [50, 14, 0, 0, 1.0, 0.0, 0.0, 0],
27064                   [51, 13, 51, 74, 1.0, 0.0, 0.0, 0],
27065                   [75, 16, 0, 24, 1.0, 0.0, 0.0, 0],
27066                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27067                  vals, "clobber env end")
27068  env_channel(make_env(:envelope, [0, 1, 1, 0, 2, 1], :length, 20), 50, 20)
27069  e = make_env(:envelope, [0, 1, 1, 0, 2, 1], :length, 20)
27070  50.upto(69) do |i| vals[i] *= env(e) end
27071  check_edit_tree([[0, 15, 0, 24, 1.0, 0.0, 0.0, 0],
27072                   [25, 13, 25, 49, 1.0, 0.0, 0.0, 0],
27073                   [50, 14, 0, 0, 1.0, 1.0, -0.1, 4],
27074                   [51, 13, 51, 59, 1.0, 0.8999, -0.1, 4],
27075                   [60, 13, 60, 69, 1.0, 0.0, 0.1111, 4],
27076                   [70, 13, 70, 74, 1.0, 0.0, 0.0, 0],
27077                   [75, 16, 0, 24, 1.0, 0.0, 0.0, 0],
27078                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27079                  vals, "env on env")
27080  env_channel(make_env(:envelope, [0, 1, 1, 0, 2, 1], :length, 80), 10, 80)
27081  e = make_env(:envelope, [0, 1, 1, 0, 2, 1], :length, 80)
27082  10.upto(89) do |i| vals[i] *= env(e) end
27083  check_edit_tree([[0, 15, 0, 9, 1.0, 0.0, 0.0, 0],
27084                   [10, 15, 10, 24, 1.0, 1.0, -0.025, 4],
27085                   [25, 13, 25, 49, 1.0, 0.625, -0.025, 4],
27086                   [50, 14, 0, 0, 1.0, 1.0, -0.1, 6],
27087                   [51, 13, 51, 59, 1.0, 0.8999, -0.1, 6],
27088                   [60, 13, 60, 69, 1.0, 0.0, 0.1111, 6],
27089                   [70, 13, 70, 74, 1.0, 0.5128, 0.025, 4],
27090                   [75, 16, 0, 14, 1.0, 0.641, 0.026, 4],
27091                   [90, 16, 15, 24, 1.0, 0.0, 0.0, 0],
27092                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27093                  vals, "env on env 2")
27094  env_channel(make_env(:envelope, [0, 1, 1, 0, 2, 1], :length, 20), 50, 20)
27095  e = make_env(:envelope, [0, 1, 1, 0, 2, 1], :length, 20)
27096  50.upto(69) do |i| vals[i] *= env(e) end
27097  check_edit_tree([[0, 15, 0, 9, 1.0, 0.0, 0.0, 0],
27098                   [10, 15, 10, 24, 1.0, 1.0, -0.025, 4],
27099                   [25, 13, 25, 49, 1.0, 0.625, -0.025, 4],
27100                   [50, 14, 0, 0, 1.0, 1.0, -0.1, 10],
27101                   [51, 13, 51, 59, 1.0, 0.8999, -0.1, 10],
27102                   [60, 13, 60, 69, 1.0, 0.0, 0.1111, 10],
27103                   [70, 13, 70, 74, 1.0, 0.5128, 0.0256, 4],
27104                   [75, 16, 0, 14, 1.0, 0.641, 0.0256, 4],
27105                   [90, 16, 15, 24, 1.0, 0.0, 0.0, 0],
27106                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27107                  vals, "env on env 3")
27108  delete_samples(10, 20)
27109  insert_silence(10, 20)
27110  10.upto(29) do |i| vals[i] = 0.0 end
27111  check_edit_tree([[0, 15, 0, 9, 1.0, 0.0, 0.0, 0],
27112                   [10, -1, 0, 19, 0.0, 0.0, 0.0, 2],
27113                   [30, 13, 30, 49, 1.0, 0.5, -0.025, 4],
27114                   [50, 14, 0, 0, 1.0, 1.0, -0.1, 10],
27115                   [51, 13, 51, 59, 1.0, 0.8999, -0.1, 10],
27116                   [60, 13, 60, 69, 1.0, 0.0, 0.1111, 10],
27117                   [70, 13, 70, 74, 1.0, 0.5128, 0.026, 4],
27118                   [75, 16, 0, 14, 1.0, 0.641, 0.026, 4],
27119                   [90, 16, 15, 24, 1.0, 0.0, 0.0, 0],
27120                   [100, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27121                  vals, "env preclobbered")
27122  close_sound(ind)
27123  #
27124  [10, 10000].each do |dur|
27125    i1 = new_sound
27126    vct2channel(Vct.new(dur, 1.0))
27127    env_sound([0, 0, 1, 1])
27128    check_env(:ramp, make_sampler(0), make_env([0, 0, 1, 1], :length, dur), dur)
27129    reverse_channel
27130    check_env(:rev_ramp, make_sampler(0), make_env([0, 1, 1, 0], :length, dur), dur)
27131    undo_edit(2)
27132    env_sound([0, 0, 1, 1, 2, 0])
27133    check_env(:ramp, make_sampler(0), make_env([0, 0, 1, 1, 2, 0], :length, dur), dur)
27134    cur_read = make_sampler(0)
27135    reverse_channel
27136    check_env(:rev_pyr_1, cur_read, make_sampler(dur - 1, i1, 0, -1), dur)
27137    undo_edit(2)
27138    env_sound([0, 0, 1, 1, 2, 0, 3, 1])
27139    check_env(:ramp_3, make_sampler(0), make_env([0, 0, 1, 1, 2, 0, 3, 1],:length, dur), dur)
27140    cur_read = make_sampler(0)
27141    reverse_channel
27142    check_env(:rev_pyr_2, cur_read, make_sampler(dur - 1, i1, 0, -1), dur)
27143    undo_edit(2)
27144    env_sound([0, 0, 1, 1, 2, 1, 3, 0])
27145    check_env(:sqoff, make_sampler(0), make_env([0, 0, 1, 1, 2, 1, 3, 0], :length, dur), dur)
27146    undo_edit(1)
27147    env_sound([0, 0, 1, 0.5, 2, 0.5, 3, 0])
27148    check_env(:sqoff_5, make_sampler(0),
27149              make_env([0, 0, 1, 0.5, 2, 0.5, 3, 0], :length, dur), dur)
27150    undo_edit(1)
27151    scale_channel(0.5)
27152    env_sound([0, 0, 1, 1])
27153    check_env(:scl_ramp, make_sampler(0),
27154              make_env([0, 0, 1, 1], :length, dur, :scaler, 0.5), dur)
27155    reverse_channel
27156    check_env(:scl_rev_ramp, make_sampler(0),
27157              make_env([0, 1, 1, 0], :length, dur, :scaler, 0.5), dur)
27158    undo_edit(2)
27159    env_sound([0, 0, 1, 1, 2, 0])
27160    check_env(:scl_ramp_3, make_sampler(0),
27161              make_env([0, 0, 1, 1, 2, 0], :length, dur, :scaler, 0.5), dur)
27162    cur_read = make_sampler(0)
27163    reverse_channel
27164    check_env(:scl_rev_pyr, cur_read, make_sampler(dur - 1, i1, 0, -1), dur)
27165    undo_edit(3)
27166    #
27167    if dur == 10000
27168      [[   0, 1000],
27169       [   0, 6000],
27170       [1000, 1000],
27171       [1000, 4000],
27172       [4000, 2000],
27173       [5000, 1000],
27174       [6000, 1000],
27175       [5000, 5000]].each do |beg, local_dur|
27176        env_sound([0, 0, 1, 1, 2, 0])
27177        scale_channel(0.5, beg, local_dur)
27178        e = make_env([0, 0, 1, 1, 2, 0], :length, dur)
27179        ctr = 0
27180        check_env(:env_and_scl, make_sampler(0),
27181                  lambda {
27182                    val = env(e)
27183                    ctr += 1
27184                    if ctr.between?(beg + 1, beg + local_dur)
27185                      val * 0.5
27186                    else
27187                      val
27188                    end
27189                  }, dur)
27190        undo_edit(2)
27191      end
27192      [[   0, 1000,  500,   200],
27193       [   0, 6000,    0, 10000],
27194       [1000, 1000,    0,  1500],
27195       [1000, 4000, 2000,  1000],
27196       [4000, 2000, 5000,   500],
27197       [5000, 1000, 4000,  2000],
27198       [6000, 1000,    0,  2000],
27199       [5000, 5000, 8000,  2000]].each do |env_beg, env_dur, scl_beg, scl_dur|
27200        env_channel([0, 0, 1, 1, 2, 1, 3, 0], env_beg, env_dur)
27201        scale_channel(0.5, scl_beg, scl_dur)
27202        e = make_env([0, 0, 1, 1, 2, 1, 3, 0], :length, env_dur)
27203        ctr = 0
27204        check_env(:env_scl_partial, make_sampler(0),
27205                  lambda {
27206                    val = 1.0
27207                    ctr += 1
27208                    if ctr.between?(env_beg + 1, env_beg + env_dur)
27209                      val *= env(e)
27210                    end
27211                    if ctr.between?(scl_beg + 1, scl_beg + scl_dur)
27212                      val *= 0.5
27213                    end
27214                    val
27215                  }, dur)
27216        undo_edit(2)
27217      end
27218    end
27219    env_sound([0, 0, 1, 1])
27220    env_sound([0, 0, 1, 1])
27221    e = make_env([0, 0, 1, 1], :length, dur)
27222    check_env(:unenv_ramp, make_sampler(0),
27223              lambda {
27224                val = env(e)
27225                val * val
27226              }, dur)
27227    undo_edit(2)
27228    env_sound([0, 0, 1, 1])
27229    vct2channel(Vct.new(3, 1.0), 3, 3)
27230    unless vequal(res = channel2vct(0, 10),
27231                  vct(0, 1.111 / dur, 2.222 / dur, 1, 1, 1, 6.66 / dur,
27232                      7.77 / dur, 8.88 / dur, 10.0 / dur))
27233      snd_display("1 vals: %s?", res)
27234    end
27235    undo_edit(2)
27236    env_sound([0, 0, 1, 1])
27237    delete_samples(3, 3)
27238    insert_samples(3, 3, Vct.new(3, 1.0))
27239    unless vequal(res = channel2vct(0, 10),
27240                  vct(0, 1.111 / dur, 2.222 / dur, 1, 1, 1, 6.66 / dur,
27241                      7.77 / dur, 8.88 / dur, 10.0 / dur))
27242      snd_display("2 vals: %s?", res)
27243    end
27244    undo_edit(3)
27245    env_sound([0, 0, 1, 1])
27246    insert_samples(3, 3, Vct.new(3, 1.0))
27247    delete_samples(3, 3)
27248    check_env(:ramp_5, make_sampler(0), make_env([0, 0, 1, 1], :length, dur), dur)
27249    undo_edit(3)
27250    env_sound([0, 0, 1, 1, 2, 0])
27251    if dur == 10
27252      vct2channel(Vct.new(3, 1.0), 3, 3)
27253      unless vequal(res = channel2vct(0, 10), vct(0, 0.2, 0.4, 1, 1, 1, 0.75, 0.5, 0.25, 0))
27254        snd_display("4 vals (%s): %s?", dur, res)
27255      end
27256    else
27257      vct2channel(Vct.new(3, 0.0), 4998, 3)
27258      unless vequal(res = channel2vct(4995, 10),
27259                    vct(0.999, 0.999, 1, 0, 0, 0, 1, 0.999, 0.999, 0.999))
27260        snd_display("4 vals (%s): %s?", dur, res)
27261      end
27262    end
27263    undo_edit(2)
27264    if dur == 10
27265      env_sound([0, 0, 1, 1, 2, 0])
27266      delete_samples(3, 3)
27267      insert_samples(3, 3, Vct.new(3, 1.0))
27268      unless vequal(res = channel2vct(0, 10), vct(0, 0.2, 0.4, 1, 1, 1, 0.75, 0.5, 0.25, 0))
27269        snd_display("2 vals: %s?", res)
27270      end
27271      undo_edit(3)
27272      env_sound([0, 0, 1, 1, 2, 0])
27273      vct2channel(Vct.new(3, 1.0), 0, 3)
27274      unless vequal(res = channel2vct(0, 10), vct(1, 1, 1, 0.6, 0.8, 1, 0.75, 0.5, 0.25, 0))
27275        snd_display("4 vals: %s?", res)
27276      end
27277      undo_edit(2)
27278      env_sound([0, 0, 1, 1, 2, 0])
27279      vct2channel(Vct.new(3, 1.0), 7, 3)
27280      unless vequal(res = channel2vct(0, 10), vct(0, 0.2, 0.4, 0.6, 0.8, 1, 0.75, 1, 1, 1))
27281        snd_display("5 vals: %s?", res)
27282      end
27283      undo_edit(2)
27284    end
27285    file = file_name(i1)
27286    close_sound(i1)
27287    delete_file(file)
27288  end
27289  if $initial_graph_hook.empty?
27290    $update_hook.reset_hook!
27291    $close_hook.reset_hook!
27292    $exit_hook.reset_hook!
27293    require "env"
27294  end
27295end
27296
27297def test_16_03
27298  ind = new_sound("fmv.snd", 1, 22050, Mus_bfloat, Mus_next, "envd edit trees")
27299  vals = Vct.new(10000, 1.0)
27300  select_sound(ind)
27301  select_channel(0)
27302  check_edit_tree([[0, 0, 0, 0, 0.0, 0.0, 0.0, 1],
27303                   [1, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27304                  Vct.new(1), "initial new_sound")
27305  set_samples(0, 10000, vals)
27306  check_edit_tree([[0, 1, 0, 9999, 1.0, 0.0, 0.0, 0],
27307                   [10000, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27308                  vals, "envd set first samps to one")
27309  env_sound([0, 0, 1, 1])
27310  e = make_env(:envelope, [0, 0, 1, 1], :length, 10000)
27311  vals.map! do |val| e.run end
27312  check_edit_tree([[0, 1, 0, 9999, 1.0, 0.0, 1.0e-4, 4],
27313                   [10000, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27314                  vals, "env frag [0, 0, 1, 1]")
27315  delete_samples(1000, 1000)
27316  v1 = Vct.new(9000)
27317  1000.times do |i| v1[i] = vals[i] end
27318  1000.upto(8999) do |i| v1[i] = vals[i + 1000] end
27319  check_edit_tree([[0, 1, 0, 999, 1.0, 0.0, 1.0e-4, 4],
27320                   [1000, 1, 2000, 9999, 1.0, 0.2, 1.0e-4, 4],
27321                   [9000, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27322                  v1, "env frag del")
27323  undo_edit(1)
27324  delete_samples(9000, 1000)
27325  insert_samples(3000, 1000, Vct.new(1000))
27326  9999.downto(4000) do |i| vals[i] = vals[i - 1000] end
27327  3000.upto(3999) do |i| vals[i] = 0.0 end
27328  check_edit_tree([[0, 1, 0, 2999, 1.0, 0.0, 1.0e-4, 4],
27329                   [3000, 2, 0, 999, 1.0, 0.0, 0.0, 0],
27330                   [4000, 1, 3000, 8999, 1.0, 0.3, 1.0e-4, 4],
27331                   [10000, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27332                  vals, "envd ins/del")
27333  delete_samples(0, 1000)
27334  insert_samples(0, 1000, Vct.new(1000))
27335  0.upto(999) do |i| vals[i] = 0.0 end
27336  check_edit_tree([[0, 3, 0, 999, 1.0, 0.0, 0.0, 0],
27337                   [1000, 1, 1000, 2999, 1.0, 0.1, 1.0e-4, 4],
27338                   [3000, 2, 0, 999, 1.0, 0.0, 0.0, 0],
27339                   [4000, 1, 3000, 8999, 1.0, 0.3, 1.0e-4, 4],
27340                   [10000, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27341                  vals, "envd predel")
27342  scale_by(0.5)
27343  vals.scale!(0.5)
27344  check_edit_tree([[0, 3, 0, 999, 0.5, 0.0, 0.0, 0],
27345                   [1000, 1, 1000, 2999, 0.5, 0.1, 1.0e-4, 4],
27346                   [3000, 2, 0, 999, 0.5, 0.0, 0.0, 0],
27347                   [4000, 1, 3000, 8999, 0.5, 0.3, 1.0e-4, 4],
27348                   [10000, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27349                  vals, "envd scl")
27350  reverse_channel
27351  j = 9999
27352  5000.times do |i|
27353    vals[i], vals[j] = vals[j], vals[i]
27354    j -= 1
27355  end
27356  check_edit_tree([[0, 4, 0, 9999, 1.0, 0.0, 0.0, 0],
27357                   [10000, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27358                  vals, "envd rev")
27359  revert_sound(ind)
27360  vals = Vct.new(100000, 1.0)
27361  vct2channel(vals, 0, 100000)
27362  env_channel(make_env(:envelope, [0, 0, 1, 1, 2, 0], :length, 10000), 30000, 10000)
27363  e = make_env(:envelope, [0, 0, 1, 1, 2, 0], :length, 10000)
27364  30000.upto(39999) do |i| vals[i] = e.run end
27365  check_edit_tree([[0, 1, 0, 29999, 1.0, 0.0, 0.0, 0],
27366                   [30000, 1, 30000, 34999, 1.0, 0.0, 1.9e-4, 4],
27367                   [35000, 1, 35000, 39999, 1.0, 1.0, -2.0e-4, 4],
27368                   [40000, 1, 40000, 99999, 1.0, 0.0, 0.0, 0],
27369                   [100000, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27370                  vals, "partial env")
27371  scale_channel(0.5, 10000, 10000)
27372  env_channel(make_env(:envelope, [0, 0, 1, 1, 2, 0], :length, 10000), 30000, 10000)
27373  e = make_env(:envelope, [0, 0, 1, 1, 2, 0], :length, 10000)
27374  30000.upto(39999) do |i| vals[i] *= e.run end
27375  10000.upto(19999) do |i| vals[i] *= 0.5 end
27376  check_edit_tree([[0, 1, 0, 9999, 1.0, 0.0, 0.0, 0],
27377                   [10000, 1, 10000, 19999, 0.5, 0.0, 0.0, 0],
27378                   [20000, 1, 20000, 29999, 1.0, 0.0, 0.0, 0],
27379                   [30000, 1, 30000, 34999, 1.0, 0.0, 1.9e-4, 6],
27380                   [35000, 1, 35000, 39999, 1.0, 1.0, -2.0e-4, 6],
27381                   [40000, 1, 40000, 99999, 1.0, 0.0, 0.0, 0],
27382                   [100000, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27383                  vals, "env over env")
27384  env_channel(make_env(:envelope, [0, 0, 1, 1, 2, 0], :length, 10000), 5000, 10000)
27385  e = make_env(:envelope, [0, 0, 1, 1, 2, 0], :length, 10000)
27386  5000.upto(14999) do |i| vals[i] *= e.run end
27387  check_edit_tree([[0, 1, 0, 4999, 1.0, 0.0, 0.0, 0],
27388                   [5000, 1, 5000, 9999, 1.0, 0.0, 1.9e-4, 4],
27389                   [10000, 1, 10000, 14999, 0.5, 1.0, -2.0e-4, 4],
27390                   [15000, 1, 15000, 19999, 0.5, 0.0, 0.0, 0],
27391                   [20000, 1, 20000, 29999, 1.0, 0.0, 0.0, 0],
27392                   [30000, 1, 30000, 34999, 1.0, 0.0, 1.9e-4, 6],
27393                   [35000, 1, 35000, 39999, 1.0, 1.0, -2.0e-4, 6],
27394                   [40000, 1, 40000, 99999, 1.0, 0.0, 0.0, 0],
27395                   [100000, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27396                  vals, "env over scl")
27397  ramp_channel(0.5, -0.5, 25000, 1000)
27398  e = make_env(:envelope, [0, 0.5, 1, -0.5], :length, 1000)
27399  25000.upto(25999) do |i| vals[i] *= e.run end
27400  check_edit_tree([[0, 1, 0, 4999, 1.0, 0.0, 0.0, 0],
27401                   [5000, 1, 5000, 9999, 1.0, 0.0, 1.9e-4, 4],
27402                   [10000, 1, 10000, 14999, 0.5, 1.0, -2.0e-4, 4],
27403                   [15000, 1, 15000, 19999, 0.5, 0.0, 0.0, 0],
27404                   [20000, 1, 20000, 24999, 1.0, 0.0, 0.0, 0],
27405                   [25000, 1, 25000, 25999, 1.0, 0.5, -0.001, 4],
27406                   [26000, 1, 26000, 29999, 1.0, 0.0, 0.0, 0],
27407                   [30000, 1, 30000, 34999, 1.0, 0.0, 1.9e-4, 6],
27408                   [35000, 1, 35000, 39999, 1.0, 1.0, -2.0e-4, 6],
27409                   [40000, 1, 40000, 99999, 1.0, 0.0, 0.0, 0],
27410                   [100000, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27411                  vals, "ramp")
27412  scale_by(-1.0)
27413  vals.scale!(-1.0)
27414  check_edit_tree([[0, 1, 0, 4999, -1.0, 0.0, 0.0, 0],
27415                   [5000, 1, 5000, 9999, -1.0, 0.0, 1.9e-4, 4],
27416                   [10000, 1, 10000, 14999, -0.5, 1.0, -2.0e-4, 4],
27417                   [15000, 1, 15000, 19999, -0.5, 0.0, 0.0, 0],
27418                   [20000, 1, 20000, 24999, -1.0, 0.0, 0.0, 0],
27419                   [25000, 1, 25000, 25999, -1.0, 0.5, -0.001, 4],
27420                   [26000, 1, 26000, 29999, -1.0, 0.0, 0.0, 0],
27421                   [30000, 1, 30000, 34999, -1.0, 0.0, 1.9e-4, 6],
27422                   [35000, 1, 35000, 39999, -1.0, 1.0, -2.0e-4, 6],
27423                   [40000, 1, 40000, 99999, -1.0, 0.0, 0.0, 0],
27424                   [100000, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27425                  vals, "invert")
27426  reader = make_sampler(0, ind, 0, 1, edit_position - 1)
27427  map_channel(lambda { |y| y + reader.call })
27428  check_edit_tree([[0, 2, 0, 99999, 1.0, 0.0, 0.0, 0],
27429                   [100000, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27430                  Vct.new(100000), "invert and add")
27431  if fneq(maxamp, 0.0)
27432    snd_display("invert-and-add maxamp: %s?", maxamp)
27433  end
27434  undo_edit
27435  ramp_channel(-1.0, 1.0, 50000, 30000)
27436  e = make_env(:envelope, [0, -1, 1, 1], :length, 30000)
27437  50000.upto(79999) do |i| vals[i] *= e.run end
27438  check_edit_tree([[0, 1, 0, 4999, -1.0, 0.0, 0.0, 0],
27439                   [5000, 1, 5000, 9999, -1.0, 0.0, 1.9e-4, 4],
27440                   [10000, 1, 10000, 14999, -0.5, 1.0, -2.0e-4, 4],
27441                   [15000, 1, 15000, 19999, -0.5, 0.0, 0.0, 0],
27442                   [20000, 1, 20000, 24999, -1.0, 0.0, 0.0, 0],
27443                   [25000, 1, 25000, 25999, -1.0, 0.5, -0.001, 4],
27444                   [26000, 1, 26000, 29999, -1.0, 0.0, 0.0, 0],
27445                   [30000, 1, 30000, 34999, -1.0, 0.0, 1.9e-4, 6],
27446                   [35000, 1, 35000, 39999, -1.0, 1.0, -2.0e-4, 6],
27447                   [40000, 1, 40000, 49999, -1.0, 0.0, 0.0, 0],
27448                   [50000, 1, 50000, 79999, -1.0, -1.0, 6.6e-5, 4],
27449                   [80000, 1, 80000, 99999, -1.0, 0.0, 0.0, 0],
27450                   [100000, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27451                  vals, "ramp")
27452  env_sound([0, 0, 1, 1])
27453  reverse_channel
27454  delete_samples(1, 99999)
27455  if fneq(sample(0), -1.0)
27456    snd_display("sample at end: %s?", sample(0))
27457  end
27458  if framples != 1
27459    snd_display("length at end: %s?", framples)
27460  end
27461  check_edit_tree([[0, 2, 0, 0, 1.0, 0.0, 0.0, 0],
27462                   [1, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27463                  Vct.new(1, -1.0), "at end")
27464  close_sound(ind)
27465  #
27466  ind = open_sound("oboe.snd")
27467  env_channel([0.0, 0.984011617147162, 0.644050741979388, 0.110976689002195,
27468               1.17272046995914, 0.384709990674106, 1.25650287720397, 0.551452668245628,
27469               1.4389507801877, 0.843827758574229, 2.16614272265275, 0.226832341237953])
27470  if (not number?(val = sample(50827))) or fneq(val, 0.0)
27471    snd_display("round-off env: %s?", val)
27472  end
27473  check_edit_tree([[0, 0, 0, 15111, 1.0, 0.984, -5.77e-5, 4],
27474                   [15112, 0, 15112, 27516, 1.0, 0.111, 2.2e-5, 4],
27475                   [27517, 0, 27517, 29482, 1.0, 0.3848, 8.48e-5, 4],
27476                   [29483, 0, 29483, 33763, 1.0, 0.5515, 6.83e-5, 4],
27477                   [33764, 0, 33764, 50827, 1.0, 0.8438, -3.62e-5, 4],
27478                   [50828, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27479                  false, "round-off test")
27480  revert_sound(ind)
27481  map_channel($init_channel)
27482  env_channel([0, 0, 1, 1, 2, 0])
27483  scale_channel(0.5, 1000, 1000)
27484  if fneq(val = sample(800), 0.0314)
27485    snd_display("scl on env trouble: %s?", val)
27486  end
27487  check_edit_tree([[0, 1, 0, 999, 1.0, 0.0, 3.93e-5, 4],
27488                   [1000, 1, 1000, 1999, 0.5, 0.0393, 3.93e-5, 4],
27489                   [2000, 1, 2000, 25413, 1.0, 0.0786, 3.93e-5, 4],
27490                   [25414, 1, 25414, 50827, 1.0, 1.0, -3.93e-5, 4],
27491                   [50828, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27492                  false, "scl on env")
27493  revert_sound(ind)
27494  map_channel($init_channel)
27495  ramp_channel(0.0, 1.0)
27496  ramp_channel(0.0, 1.0)
27497  ramp_channel(0.0, 1.0)
27498  if fneq(val = sample(20000), (20000.0 / 50828) ** 3)
27499    snd_display("ramp_channels piled up: %s?", val)
27500  end
27501  check_edit_tree([[0, 1, 0, 50827, 1.0, 0.0, 1.9e-5, 10],
27502                   [50828, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27503                  false, "ramp upon ramp")
27504  revert_sound(ind)
27505  map_channel($init_channel)
27506  ramp_channel(0.5, 1.0) # val = 0.5 + (20000/50828)*0.5
27507  ramp_channel(0.0, 0.5) # val * (20000/50828)*0.5
27508  ramp_channel(0.1, 0.4) # val * (0.1 + (20000/50828)*0.3)
27509  val = sample(20000)
27510  ratio = 20000.0 / 50828
27511  val1 = 0.5 + 0.5 * ratio
27512  val2 = val1 * 0.5 * ratio
27513  val3 = val2 * (0.1 + ratio * 0.3)
27514  if fneq(val, val3)
27515    snd_display("ramp-channels piled up (2): %s %s?", val, val3)
27516  end
27517  revert_sound(ind)
27518  env_channel([0, 0, 1, 1, 2, 0])
27519  check_edit_tree([[0, 0, 0, 25413, 1.0, 0.0, 3.9e-5, 4],
27520                   [25414, 0, 25414, 50827, 1.0, 1.0, -3.93e-5, 4],
27521                   [50828, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27522                  false, "env+scl 0")
27523  scale_channel(0.5, 0, 1000)
27524  check_edit_tree([[0, 0, 0, 999, 0.5, 0.0, 3.93e-5, 4],
27525                   [1000, 0, 1000, 25413, 1.0, 0.0393, 3.93e-5, 4],
27526                   [25414, 0, 25414, 50827, 1.0, 1.0, -3.93e-5, 4],
27527                   [50828, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27528                  false, "env+scl 1")
27529  undo_edit
27530  scale_channel(0.5, 1000, 1000)
27531  check_edit_tree([[0, 0, 0, 999, 1.0, 0.0, 3.93e-5, 4],
27532                   [1000, 0, 1000, 1999, 0.5, 0.0393, 3.93e-5, 4],
27533                   [2000, 0, 2000, 25413, 1.0, 0.0786, 3.93e-5, 4],
27534                   [25414, 0, 25414, 50827, 1.0, 1.0, -3.93e-5, 4],
27535                   [50828, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27536                  false, "env+scl 2")
27537  undo_edit
27538  scale_channel(0.5, 0, 25415)
27539  check_edit_tree([[0, 0, 0, 25413, 0.5, 0.0, 3.93e-5, 4],
27540                   [25414, 0, 25414, 25414, 0.5, 1.0, -3.93e-5, 4],
27541                   [25415, 0, 25415, 50827, 1.0, 0.999, -3.93e-5, 4],
27542                   [50828, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27543                  false, "env+scl 3")
27544  undo_edit
27545  scale_channel(0.5, 20000, 10000)
27546  check_edit_tree([[0, 0, 0, 19999, 1.0, 0.0, 3.93e-5, 4],
27547                   [20000, 0, 20000, 25413, 0.5, 0.7869, 3.93e-5, 4],
27548                   [25414, 0, 25414, 29999, 0.5, 1.0, -3.93e-5, 4],
27549                   [30000, 0, 30000, 50827, 1.0, 0.8195, -3.93e-5, 4],
27550                   [50828, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27551                  false, "env+scl 4")
27552  undo_edit
27553  scale_channel(0.5, 30000, 1000)
27554  check_edit_tree([[0, 0, 0, 25413, 1.0, 0.0, 3.93e-5, 4],
27555                   [25414, 0, 25414, 29999, 1.0, 1.0, -3.93e-5, 4],
27556                   [30000, 0, 30000, 30999, 0.5, 0.8195, -3.93e-5, 4],
27557                   [31000, 0, 31000, 50827, 1.0, 0.7802, -3.93e-5, 4],
27558                   [50828, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27559                  false, "env+scl 5")
27560  undo_edit
27561  scale_channel(0.5, 25415, 1000)
27562  check_edit_tree([[0, 0, 0, 25413, 1.0, 0.0, 3.935e-5, 4],
27563                   [25414, 0, 25414, 25414, 1.0, 1.0, -3.935e-5, 4],
27564                   [25415, 0, 25415, 26414, 0.5, 0.9999, -3.935e-5, 4],
27565                   [26415, 0, 26415, 50827, 1.0, 0.96, -3.93e-5, 4],
27566                   [50828, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27567                  false, "env+scl 6")
27568  undo_edit
27569  scale_channel(0.5, 40000, 10828)
27570  check_edit_tree([[0, 0, 0, 25413, 1.0, 0.0, 3.935e-5, 4],
27571                   [25414, 0, 25414, 39999, 1.0, 1.0, -3.935e-5, 4],
27572                   [40000, 0, 40000, 50827, 0.5, 0.426, -3.935e-5, 4],
27573                   [50828, -2, 0, 0, 0.0, 0.0, 0.0, 0]],
27574                  false, "env+scl 7")
27575  undo_edit
27576  close_sound(ind)
27577end
27578
27579def check_envs(name, r_maker, e_maker, dur, i1, i2)
27580  check_env(format("%s-i1-0", name), r_maker.call(i1, 0), e_maker.call(i1, 0), dur)
27581  check_env(format("%s-i2-0", name), r_maker.call(i2, 0), e_maker.call(i2, 0), dur)
27582  check_env(format("%s-i2-1", name), r_maker.call(i2, 1), e_maker.call(i2, 1), dur)
27583end
27584
27585def test_16_04
27586  [10, 10000].each do |dur|
27587    i1 = new_sound
27588    i2 = new_sound("fmv1.snd", 2, 44100, Mus_bfloat, Mus_next)
27589    v = Vct.new(dur, 1.0)
27590    vct2channel(v, 0, dur, i1)
27591    vct2channel(v, 0, dur, i2, 0)
27592    vct2channel(v, 0, dur, i2, 1)
27593    set_sync(1, i1)
27594    set_sync(1, i2)
27595    env_sound([0, 0, 1, 1])
27596    check_envs(:ramps,
27597               lambda do |s, c| make_sampler(0, s, c) end,
27598               lambda do |s, c|
27599                 make_env(:envelope, [0, 0, 1, 1], :length, dur)
27600               end, dur, i1, i2)
27601    reverse_sound
27602    check_envs(:rev_ramps,
27603               lambda { |s, c| make_sampler(0, s, c) },
27604               lambda { |s, c| make_env(:envelope, [0, 1, 1, 0], :length, dur) },
27605               dur, i1, i2)
27606    undo_edit(2)
27607    env_sound([0, 0, 1, 1, 2, 0])
27608    check_envs(:ramps_2,
27609               lambda { |s, c| make_sampler(0, s, c) },
27610               lambda { |s, c| make_env(:envelope, [0, 0, 1, 1, 2, 0], :length, dur) },
27611               dur, i1, i2)
27612    undo_edit(1)
27613    scale_by(0.5)
27614    env_sound([0, 0, 1, 1])
27615    check_envs(:scl_ramps,
27616               lambda { |s, c| make_sampler(0, s, c) },
27617               lambda { |s, c| make_env(:envelope, [0, 0, 1, 1], :length, dur, :scaler, 0.5) },
27618               dur, i1, i2)
27619    reverse_sound
27620    check_envs(:scl_rev_ramps,
27621               lambda { |s, c| make_sampler(0, s, c) },
27622               lambda { |s, c| make_env(:envelope, [0, 1, 1, 0], :length, dur, :scaler, 0.5) },
27623               dur, i1, i2)
27624    undo_edit(3)
27625    env_sound([0, 0, 1, 1])
27626    env_sound([0, 0, 1, 1])
27627    check_envs(:unenv_ramps,
27628               lambda { |s, c| make_sampler(0, s, c) },
27629               lambda { |s, c|
27630                 e = make_env(:envelope, [0, 0, 1, 1], :length, dur)
27631                 lambda {
27632                   val = env(e)
27633                   val * val
27634                 }
27635               },
27636               dur, i1, i2)
27637    undo_edit(2)
27638    env_sound([0, 0, 1, 1])
27639    v1 = Vct.new(3, 1.0)
27640    vct2channel(v1, 3, 3, i1)
27641    vct2channel(v1, 3, 3, i2, 0)
27642    vct2channel(v1, 3, 3, i2, 1)
27643    unless vequal(res = channel2vct(0, 10, i1, 0),
27644                  vct(0, 1.111 / dur, 2.222 / dur, 1, 1, 1, 6.66 / dur,
27645                      7.77 / dur, 8.88 / dur, 10.0 / dur))
27646      snd_display("1 0 vals: %s?", res)
27647    end
27648    unless vequal(res = channel2vct(0, 10, i2, 0),
27649                  vct(0, 1.111 / dur, 2.222 / dur, 1, 1, 1, 6.66 / dur,
27650                      7.77 / dur, 8.88 / dur, 10.0 / dur))
27651      snd_display("2 0 vals: %s?", res)
27652    end
27653    unless vequal(res = channel2vct(0, 10, i2, 1),
27654                  vct(0, 1.111 / dur, 2.222 / dur, 1, 1, 1, 6.66 / dur,
27655                      7.77 / dur, 8.88 / dur, 10.0 / dur))
27656      snd_display("2 1 vals: %s?", res)
27657    end
27658    file = file_name(i1)
27659    close_sound(i1)
27660    delete_file(file)
27661    file = file_name(i2)
27662    close_sound(i2)
27663    delete_file(file)
27664  end
27665  #
27666  data = ["1a.snd", "oboe.snd", "storm.snd"].map do |sound|
27667    if File.exist?(sound)
27668      ind = view_sound(sound)
27669      set_squelch_update(true, ind)
27670      tms = [lambda { scale_channel(2.0) },
27671             lambda { reverse_channel },
27672             lambda { env_channel([0, 0, 1, 1]) },
27673             lambda { map_channel(lambda { |y| y * 2 }) },
27674             lambda { scan_channel(lambda { |y| y > 1.0 }) },
27675             lambda { pad_channel(0, 2000) },
27676             lambda { vct2channel(Vct.new(1000, 0.1), 0, 1000) },
27677             lambda { clm_channel(make_two_zero(0.5, 0.5)) },
27678             lambda { mix("pistol.snd", 12345) },
27679             lambda { src_channel(2.0) },
27680             lambda { delete_samples(10, 200) }].map do |func|
27681        with_time(&func).first
27682      end
27683      close_sound(ind)
27684      tms
27685    end
27686  end
27687  if $VERBOSE
27688    snd_info("          scl   rev   env   map   scn   pad   wrt   clm   mix   src")
27689    str = ""
27690    data[0].each do |x| str << "%6.2f" % x end
27691    snd_info("    1a: %s", str)
27692    str = ""
27693    data[1].each do |x| str << "%6.2f" % x end
27694    snd_info("  oboe: %s", str)
27695    str = ""
27696    data[2].each do |x| str << "%6.2f" % x end
27697    snd_info(" storm: %s", str)
27698  end
27699  #
27700  ind = new_sound("fmv.snd", :header_type, Mus_next, :sample_type, Mus_bfloat)
27701  set_sinc_width(10)
27702  pad_channel(0, 1000, ind)
27703  set_sample(100, 0.5)
27704  if fneq(res = sample(100, ind, 0, 2), 0.5)
27705    snd_display("sample(100 (2): %s?", res)
27706  end
27707  if fneq(res = sample(100, ind, 0, 1), 0.0)
27708    snd_display("sample(100 (1): %s?", res)
27709  end
27710  src_channel(0.5)
27711  if fneq(res = maxamp(ind, 0), 0.5)
27712    snd_display("src_channel max 0.5: %s?", res)
27713  end
27714  if fneq(res = sample(200), 0.5)
27715    snd_display("src_channel 0.5 200: %s?", res)
27716  end
27717  unless vequal(res = channel2vct(180, 40, ind, 0),
27718                vct(0.000, -0.000, 0.000, 0.001, -0.000, -0.003, 0.000, 0.007,
27719                    -0.000, -0.012, 0.000, 0.020, -0.000, -0.033, 0.000, 0.054,
27720                    -0.000, -0.100, -0.000, 0.316, 0.500, 0.316, -0.000, -0.100,
27721                    -0.000, 0.054, 0.000, -0.033, -0.000, 0.020, 0.000, -0.012,
27722                    -0.000, 0.007, 0.000, -0.003, -0.000, 0.001, 0.000, -0.000))
27723    snd_display("src_channel 0.5: %s?", res)
27724  end
27725  undo_edit(1, ind, 0)
27726  src_channel(0.25)
27727  if fneq(res = maxamp(ind, 0), 0.5)
27728    snd_display("src_channel max 0.25: res %1.4f != req 0.500?", res)
27729  end
27730  if fneq(res = sample(400), 0.5)
27731    snd_display("src_channel 0.25 400: res %1.4f != req 0.500?", res)
27732  end
27733  unless vequal(res = channel2vct(360, 80, ind, 0),
27734                vct(0.000, -0.000, -0.000, -0.000, 0.000, 0.000, 0.001, 0.001,
27735                    -0.000, -0.002, -0.003, -0.003, 0.000, 0.004, 0.007, 0.006,
27736                    -0.000, -0.008, -0.012, -0.010, 0.000, 0.013, 0.020, 0.016,
27737                    -0.000, -0.021, -0.033, -0.026, 0.000, 0.034, 0.054, 0.044,
27738                    -0.000, -0.060, -0.100, -0.087, -0.000, 0.148, 0.316, 0.449,
27739                    0.500, 0.449, 0.316, 0.148, -0.000, -0.087, -0.100, -0.060,
27740                    -0.000, 0.044, 0.054, 0.034, 0.000, -0.026, -0.033, -0.021,
27741                    -0.000, 0.016, 0.020, 0.013, 0.000, -0.010, -0.012, -0.008,
27742                    -0.000, 0.006, 0.007, 0.004, 0.000, -0.003, -0.003, -0.002,
27743                    -0.000, 0.001, 0.001, 0.000, 0.000, -0.000, -0.000, -0.000))
27744    snd_display("src_channel 0.25: %s?", res)
27745  end
27746  undo_edit(2, ind, 0)
27747  i = 0
27748  pi_div_100 = PI / 100.0
27749  map_channel_rb do |y|
27750    val = sin(i * pi_div_100)
27751    i += 1
27752    val * 0.5
27753  end
27754  [[2.00, 0.008],
27755   [1.50, 0.010],
27756   [3.00, 0.015],
27757   [3.14, 0.025]].each do |sr, df|
27758    src_channel(sr)
27759    if ((res = maxamp(ind, 0)) - 0.5).abs > df
27760      snd_display("src_channel sine %s: %s?", sr, res)
27761    end
27762    if integer?(sr)
27763      r0 = make_sampler(0)
27764      r1 = make_sampler(0, ind, 0, 1, edit_position - 1)
27765      500.times do |i|
27766        diff = (r0.call - r1.call).abs
27767        if diff > df
27768          snd_display("src_channel %s diff %s: %s?", sr, i, diff)
27769        end
27770        1.upto(sr - 1) do r1.call end
27771      end
27772    end
27773    50.times do |i|
27774      s1 = sample(i, ind, 0, edit_position)
27775      s2 = sample((sr * i).round, ind, 0, edit_position - 1)
27776      s3 = sample(i, ind, 0, 1)
27777      if (s1 - s2).abs > df
27778        snd_display("sample %s src(%s): %s %s?", i, sr, s1, s2)
27779      end
27780      if fneq(s3, 0.0)
27781        snd_display("sample %s (1): %s?", i, s3)
27782      end
27783    end
27784    undo_edit(1, ind, 0)
27785  end
27786  close_sound(ind)
27787  #
27788  ind = open_sound("oboe.snd")
27789  orig_max = maxamp(ind, 0)
27790  [[2.00, 0.008],
27791   [1.50, 0.010],
27792   [3.00, 0.015],
27793   [3.14, 0.025]].each do |sr, df|
27794    src_channel(sr)
27795    if ((res = maxamp(ind, 0)) - orig_max).abs > df
27796      snd_display(snd_format_neq(res, orig_max,
27797                                       "src_channel oboe (1) sr %1.4f, df %1.4f", sr, df))
27798    end
27799    undo_edit(1, ind, 0)
27800  end
27801  #
27802  [[0.50, 0.001],
27803   [0.25, 0.001],
27804   [0.90, 0.001],
27805   [0.10, 0.001]].each do |sr, df|
27806    src_channel(sr)
27807    if ((res = maxamp(ind, 0)) - orig_max).abs > df
27808      snd_display(snd_format_neq(res, orig_max,
27809                                       "src_channel oboe (2) sr %1.4f, df %1.4f", sr, df))
27810    end
27811    50.times do |i|
27812      samp = i * 100
27813      s1 = sample(samp, ind, 0, edit_position)
27814      s2 = sample((sr * samp).floor, ind, 0, edit_position - 1)
27815      if (s1 - s2).abs > df
27816        snd_display(snd_format_neq(s1, s2,
27817                                   "sample %d oboe (2) sr %1.4f, df %1.4f", i, sr, df))
27818      end
27819    end
27820    undo_edit(1, ind, 0)
27821    amp_envs_equal?(ind, 0, edit_position, edit_position + 1, 0.01)
27822  end
27823  #
27824  revert_sound(ind)
27825  scale_by(2.0)
27826  scale_by(0.5)
27827  amp_envs_equal?(ind, 0, edit_position, edit_position - 2, 0.001)
27828  revert_sound(ind)
27829  close_sound(ind)
27830  #
27831  ind = open_sound("oboe.snd")
27832  [[lambda { |beg, dur| env_channel([0, 0, 1, 1], beg, dur) },           0, 1000, 50828],
27833   [lambda { |beg, dur| map_channel(lambda { |y| y * 0.5 }, beg, dur) }, 0, 1000, 50828],
27834   [lambda { |beg, dur| reverse_channel(beg, dur) },                     0, 1000, 50828],
27835   [lambda { |beg, dur| scale_channel(2.0, beg, dur) },                  0, 1000, 50828],
27836   [lambda { |beg, dur| vct2channel(Vct.new(dur), beg, dur) },           0, 1000, 50828],
27837   [lambda { |beg, dur| smooth_channel(beg, dur) },                      0, 1000, 50828],
27838   [lambda { |beg, dur| pad_channel(beg, dur) },                         0, 1000, 51828],
27839   [lambda { |beg, dur| src_channel(0.5, beg, dur) },                    0, 1000, 52829],
27840   [lambda { |beg, dur| insert_silence(beg, dur) },                      0, 1000, 53829]
27841  ].each do |func, beg, dur, len|
27842    old_len = framples(ind)
27843    func.call(beg, dur)
27844    if (res = framples(ind)) != len
27845      snd_display("(%s %s %s) with %s: %s (%s)?", func, beg, dur, old_len, res, len)
27846    end
27847  end
27848  revert_sound(ind)
27849  [[ 1000, 1000, 51828],
27850   [60000, 1000, 61000],
27851   [    0, 1000, 62000],
27852   [62000,    1, 62001],
27853   [62000,    2, 62003],
27854   [62004,    1, 62005]].each do |beg, dur, len|
27855    old_len = framples(ind)
27856    pad_channel(beg, dur)
27857    if (res = framples(ind)) != len
27858      snd_display("(pad_channel %s %s) with %s: %s (%s)?", beg, dur, old_len, res, len)
27859    end
27860  end
27861  revert_sound(ind)
27862  [[lambda { |beg, dur| env_channel([0, 0, 1, 1], beg, dur) }, 1000, 50828],
27863   [lambda { |beg, dur| reverse_channel(beg, dur) },           1000, 50828],
27864   [lambda { |beg, dur| scale_channel(2.0, beg, dur) },        1000, 50828],
27865   [lambda { |beg, dur| scale_sound_by(2.0, beg, dur) },       1000, 50828],
27866   [lambda { |beg, dur| vct2channel(Vct.new(dur), beg, dur) }, 1000, 51928],
27867   [lambda { |beg, dur| smooth_channel(beg, dur) },            1000, 51928],
27868   [lambda { |beg, dur| pad_channel(beg, dur) },               1000, 53028],
27869   [lambda { |beg, dur| src_channel(0.5, beg, dur) },          1000, 53028],
27870   [lambda { |beg, dur| insert_silence(beg, dur) },            1000, 54028],
27871   [lambda { |beg, dur| env_sound([0, 0, 1, 1], beg, dur) },   1000, 54028]
27872  ].each do |func, dur, len|
27873    old_len = framples(ind)
27874    func.call(old_len + 100, dur)
27875    if (res = framples(ind)) != len
27876      snd_display("(%s %s) with %s: %s (%s)?", func, dur, old_len, res, len)
27877    end
27878  end
27879  revert_sound(ind)
27880  len = (1.25 * framples()).floor
27881  100.times do
27882    case random(10)
27883    when 0
27884      pad_channel(random(len), random(1000))
27885    when 1
27886      env_channel([0, 0, 1, 1, 2, 0], random(len), random(1000))
27887    when 2
27888      env_sound([0, 0, 1, 1, 2, 0], random(len), random(1000))
27889    when 3
27890      scale_channel(random(1.0), random(len), random(1000))
27891    when 4
27892      scale_sound_by(random(1.0), random(len), random(1000))
27893    when 5
27894      src_channel(random(0.2) + 0.9, random(len), random(1000))
27895    when 6
27896      ramp_channel(random(1.0), random(1.0), random(len), random(1000))
27897    when 7
27898      reverse_channel(random(len), random(1000))
27899    when 8
27900      dur = [2, random(100)].max
27901      vct2channel(Vct.new(dur), random(len), dur)
27902    when 9
27903      map_channel(lambda { |y| y * 2 }, random((0.5 * framples()).floor), random(1000))
27904    end
27905  end
27906  close_sound(ind)
27907end
27908
27909def test_16_05
27910  ind0 = open_sound("oboe.snd")
27911  ind1 = open_sound("2.snd")
27912  ind2 = open_sound("4.aiff")
27913  set_squelch_update(true, ind0, true)
27914  set_squelch_update(true, ind1, true)
27915  set_squelch_update(true, ind2, true)
27916  Snd.catch(:mus_error, lambda do |*args| snd_display("caught error: %s", args) end) do
27917    500.times do
27918      set_sync(random(3), ind0)
27919      set_sync(random(3), ind1)
27920      set_sync(random(3), ind2)
27921      opt_test(random(22))
27922    end
27923  end
27924  set_squelch_update(false, ind0, true)
27925  set_squelch_update(false, ind1, true)
27926  set_squelch_update(false, ind2, true)
27927  close_sound(ind0)
27928  close_sound(ind1)
27929  close_sound(ind2)
27930  #
27931  ind = init_sound(0.5, 10, 2)
27932  save_sound(ind)
27933  scale_channel(2.0, 0, framples, ind, 1)
27934  swap_channels
27935  check_both_chans(ind, "1", lambda { |y| fneq(y, 1.0) }, lambda { |y| fneq(y, 0.5) })
27936  undo_edit(1, ind, 0)
27937  undo_edit(2, ind, 1)
27938  scale_channel(0.5, 0, framples, ind, 0)
27939  scale_channel(2.0, 0, framples, ind, 1)
27940  swap_channels
27941  check_both_chans(ind, "2", lambda { |y| fneq(y, 1.0) }, lambda { |y| fneq(y, 0.25) })
27942  undo_edit(2, ind, 0)
27943  undo_edit(2, ind, 1)
27944  delete_samples(2, 3, ind, 0)
27945  env_channel([0, 0, 1, 1, 2, 0], 0, framples(ind, 1), ind, 1)
27946  swap_channels
27947  undo_edit(2, ind, 0)
27948  undo_edit(2, ind, 1)
27949  delete_samples(2, 7, ind, 0)
27950  swap_channels(ind, 0, ind, 1, 5, 4)
27951  revert_sound(ind)
27952  m0 = add_mark(3, ind, 0)
27953  m1 = add_mark(4, ind, 1)
27954  m2 = add_mark(5, ind, 1)
27955  scale_channel(0.5)
27956  swap_channels
27957  if (res = mark_sample(m0)) != 3
27958    snd_display("swapped m0: %s?", res)
27959  end
27960  if (res = mark_sample(m1)) != 4
27961    snd_display("swapped m1: %s?", res)
27962  end
27963  if (res = mark_sample(m2)) != 5
27964    snd_display("swapped m2: %s?", res)
27965  end
27966  if (res = mark_home(m0)) != [ind, 1]
27967    snd_display("mark_home m0: %s?", res)
27968  end
27969  if (res = mark_home(m1)) != [ind, 0]
27970    snd_display("mark_home m1: %s?", res)
27971  end
27972  if (res = mark_home(m2)) != [ind, 0]
27973    snd_display("mark_home m2: %s?", res)
27974  end
27975  undo_edit(1, ind, 0)
27976  undo_edit(1, ind, 1)
27977  if (res = mark_sample(m0)) != 3
27978    snd_display("swapped m0 (2): %s?", res)
27979  end
27980  if (res = mark_sample(m1)) != 4
27981    snd_display("swapped m1 (2): %s?", res)
27982  end
27983  if (res = mark_sample(m2)) != 5
27984    snd_display("swapped m2 (2): %s?", res)
27985  end
27986  if (res = mark_home(m0)) != [ind, 0]
27987    snd_display("mark_home m0 (2): %s?", res)
27988  end
27989  if (res = mark_home(m1)) != [ind, 1]
27990    snd_display("mark_home m1 (2): %s?", res)
27991  end
27992  if (res = mark_home(m2)) != [ind, 1]
27993    snd_display("mark_home m2 (2): %s?", res)
27994  end
27995  close_sound(ind)
27996  delete_file("test.snd")
27997  #
27998  ind = init_sound(0.5, 10, 4)
27999  scale_channel(0.5, 0, framples, ind, 1)
28000  scale_channel(0.25, 0, framples, ind, 2)
28001  scale_channel(0.125, 0, framples, ind, 3)
28002  swap_channels(ind, 1, ind, 2)
28003  maxs = maxamp(ind, true)
28004  if fneq(maxs[0], 0.5) or
28005      fneq(maxs[1], 0.125) or
28006      fneq(maxs[2], 0.25) or
28007      fneq(maxs[3], 0.0625)
28008    snd_display("swap midchans: %s?", maxs)
28009  end
28010  close_sound(ind)
28011  #
28012  ind0 = open_sound("oboe.snd")
28013  ind1 = open_sound("pistol.snd")
28014  mx0 = maxamp(ind0, 0)
28015  mx1 = maxamp(ind1, 0)
28016  swap_channels(ind0, 0, ind1, 0)
28017  if fneq(res = maxamp(ind0, 0), mx1)
28018    snd_display("maxamp cross swap 0: %s?", res)
28019  end
28020  if fneq(res = maxamp(ind1, 0), mx0)
28021    snd_display("maxamp cross swap 1: %s?", res)
28022  end
28023  close_sound(ind0)
28024  close_sound(ind1)
28025  #
28026  ind = init_sound(1.0, 10, 1)
28027  #
28028  # ramp+ramp
28029  #
28030  ramp_channel(0.0, 1.0)
28031  check_back_and_forth(ind, "ramp 1",
28032                       vct(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1))
28033  ramp_channel(0.0, 1.0)
28034  check_back_and_forth(ind, "ramp 2",
28035                       vct(0, 0.01, 0.04, 0.09, 0.16, 0.25, 0.36, 0.49, 0.64, 0.81, 1))
28036  undo_edit
28037  ramp_channel(1.0, 0.0)
28038  check_back_and_forth(ind, "ramp 3",
28039                       vct(0, 0.09, 0.16, 0.21, 0.24, 0.25, 0.24, 0.21, 0.16, 0.09, 0))
28040  undo_edit
28041  env_channel([0, 0, 1, 1, 2, 0])
28042  check_back_and_forth(ind, "ramp 4",
28043                       vct(0, 0.020, 0.080, 0.180, 0.320, 0.500, 0.480, 0.420, 0.320, 0.180, 0))
28044  undo_edit(2)
28045  env_channel([0, 0, 1, 1, 2, 0])
28046  check_back_and_forth(ind, "ramp 5",
28047                       vct(0, 0.200, 0.400, 0.600, 0.800, 1.000, 0.800, 0.600, 0.400, 0.200, 0))
28048  ramp_channel(0.0, 1.0)
28049  check_back_and_forth(ind, "ramp 6",
28050                       vct(0, 0.020, 0.080, 0.180, 0.320, 0.500, 0.480, 0.420, 0.320, 0.180, 0))
28051  scale_channel(0.5)
28052  check_back_and_forth(ind, "ramp 7",
28053                       vct(0, 0.010, 0.040, 0.090, 0.160, 0.250, 0.240, 0.210, 0.160, 0.090, 0))
28054  undo_edit(3)
28055  scale_channel(0.5)
28056  env_channel([0, 0, 1, 1, 2, 0])
28057  check_back_and_forth(ind, "ramp 8",
28058                       vct(0, 0.100, 0.200, 0.300, 0.400, 0.500, 0.400, 0.300, 0.200, 0.100, 0))
28059  ramp_channel(0.0, 1.0)
28060  check_back_and_forth(ind, "ramp 9",
28061                       vct(0, 0.010, 0.040, 0.090, 0.160, 0.250, 0.240, 0.210, 0.160, 0.090, 0))
28062  undo_edit(3)
28063  ramp_channel(0.0, 1.0)
28064  ramp_channel(0.0, 1.0)
28065  ramp_channel(0.0, 1.0)
28066  check_back_and_forth(ind, "ramp 10",
28067                       vct(0, 0.001, 0.008, 0.027, 0.064, 0.125, 0.216, 0.343, 0.512, 0.729, 1))
28068  undo_edit(3)
28069  #
28070  # ramp+scl (checking split loc)
28071  #
28072  ramp_channel(0.0, 1.0, 0, 5)
28073  scale_channel(0.5, 3, 3)
28074  check_back_and_forth(ind, "ramp+scl 1",
28075                       vct(0, 0.250, 0.500, 0.375, 0.500, 0.500, 1, 1, 1, 1, 1))
28076  undo_edit(2)
28077  ramp_channel(1.0, 0.0, 5, 5)
28078  scale_channel(0.5, 4, 3)
28079  check_back_and_forth(ind, "ramp+scl 2",
28080                       vct(1, 1, 1, 1, 0.500, 0.500, 0.375, 0.500, 0.250, 0, 1))
28081  undo_edit(2)
28082  close_sound(ind)
28083  #
28084  if $all_args
28085    [[:scale_channel,
28086      lambda do |snd, i| scale_channel(i * 0.01) end],
28087     [:set_sample,
28088      lambda do |snd, i| set_sample(i, 0.5) end],
28089     [:env_channel,
28090      lambda do |snd, i| env_channel([0, 0, 1, 1]) end],
28091     [:env_channel_with_base,
28092      lambda do |snd, i| env_channel_with_base([0, 0, 1, 1], 32.0) end],
28093     [:env_channel_with_base,
28094      lambda do |snd, i| env_channel_with_base([0, 0, 1, 1], 0.0) end],
28095     [:delete_sample,
28096      lambda do |snd, i| delete_sample(i * 10) end],
28097     [:insert_sample,
28098      lambda do |snd, i| insert_sample(i * 10, 0.5) end],
28099     [:pad_channel,
28100      lambda do |snd, i| pad_channel(i * 10, i * 10) end],
28101     [:mix_no_tag,
28102      lambda do |snd, i| mix("pistol.snd", 10 * i, 0, snd, 0, false) end],
28103     [:mix_tag,
28104      lambda do |snd, i| mix("pistol.snd", 10 * i, 0, snd, 0, true) end],
28105     [:mix_scale_to,
28106      lambda do |snd, i| set_mix_amp(mix("pistol.snd", 100 * i).car, 0.01) end],
28107     [:mix_amp,
28108      lambda do |snd, i| mix("pistol.snd", 100 * i); scale_to(0.5) end],
28109     [:src_sound_1,
28110      lambda do |snd, i| src_sound(2.0); undo_edit end],
28111     [:src_sound_2,
28112      lambda do |snd, i| src_sound(2.01); undo_edit end],
28113     [:filter_channel_1,
28114      lambda do |snd, i| filter_channel(vct(0.25, 0.5, 0.25, 0.1), 4) end],
28115     [:filter_channel_2,
28116      lambda do |snd, i| filter_channel(vct(0.25, 0.5, 0.5, 0.25), 4) end],
28117     [:filter_channel_3,
28118      lambda do |snd, i|
28119       filter_channel(vct(0.1, 0.2, 0.1, 0.1, 0.1, 0.1, 0.1, 0.2, 0.1, 0.1), 10)
28120      end],
28121     [:filter_channel_4,
28122      lambda do |snd, i|
28123       filter_channel(vct(0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1), 10)
28124      end],
28125     [:clm_channel,
28126      lambda do |snd, i| clm_channel(make_two_zero(0.5, 0.5)) end],
28127     [:reverse_channel,
28128      lambda do |snd, i|
28129        reverse_channel(i * 10, i * 100)
28130      end]].each do |name, func|
28131     ["1.snd", "oboe.snd", "1a.snd"].each do |sound|
28132        ind = open_sound(sound)
28133        with_time do
28134          set_squelch_update(true, ind, 0)
28135          with_time(format("%s() [%s]", name, sound)) do
28136            256.times do |i|
28137              revert_sound(ind) if (i % 10).zero?
28138              func.call(ind, i)
28139            end
28140          end
28141          revert_sound(ind)
28142          set_squelch_update(false, ind, 0)
28143          close_sound(ind)
28144        end
28145      end
28146    end
28147  end
28148end
28149
28150def test_16
28151  test_16_00
28152  test_16_01 if $with_test_gui # load("hiho.rb") -> set_transform_size(0)
28153  test_16_02
28154  test_16_03
28155  test_16_04
28156  test_16_05
28157end
28158
28159# ---------------- test 17: dialogs and graphics ----------------
28160
28161add_help(:arrow2right,
28162         "arrow2right(x, y, size, snd, chn, cr)  \
28163draw an arrow pointing (from the left) at the point [x, y]")
28164
28165def arrow2right(x, y, size, snd, chn, cr)
28166  size2 = size * 2
28167  fill_polygon([x, y,
28168                x - size2, y - size,
28169                x - size2, y + size,
28170                x, y],
28171               snd, chn, Time_graph, cr)
28172  fill_rectangle(x - 4 * size, (y - 0.4 * size).floor,
28173                 size2, (0.8 * size).floor,
28174                 snd, chn, Time_graph, false, cr)
28175end
28176
28177def test_17
28178  if $with_test_gui
28179    $after_graph_hook.add_hook!(get_func_name, &method(:display_previous_edits).to_proc)
28180    $lisp_graph_hook.add_hook!(get_func_name) do |snd, chn|
28181      lambda do | |
28182        cr = channel_widgets(snd, chn)[17]
28183        draw_string("hi",
28184                    x2position(0.5, snd, chn, Lisp_graph),
28185                    y2position(0.5, snd, chn, Lisp_graph),
28186                    snd, chn, Lisp_graph, cr)
28187      end
28188    end
28189    ind = open_sound("oboe.snd")
28190    wids = channel_widgets
28191    wids1 = channel_widgets(selected_sound)
28192    wids2 = channel_widgets(selected_sound, selected_channel)
28193    1.upto(3) do |i|
28194      scale_by(0.5)
28195      set_x_bounds([0, i * 0.3])
28196    end
28197    revert_sound(ind)
28198    draw_bass_clef(100, 100, 100, 0, ind, 0)
28199    update_time_graph(ind, 0)
28200    draw_fermata(200, 100, 60, 0, ind, 0)
28201    cr = channel_widgets(ind, 0)[17]
28202    draw_line(100, 100, 200, 200, ind, 0, Time_graph, cr)
28203    draw_dot(300, 300, 10, ind, 0, Time_graph, cr)
28204    draw_string("hiho", 20, 20, ind, 0, Time_graph, cr)
28205    draw_dots([25, 25, 50, 50, 100, 100], 10, ind, 0, Time_graph, cr)
28206    arrow2right(100, 50, 10, ind, 0, cr)
28207    fill_rectangle(20, 20, 100, 100, ind, 0, Time_graph, false, cr)
28208    make_bezier(0, 0, 20, 20, 40, 30, 60, 10, 10)
28209    update_time_graph(ind, 0)
28210    $after_graph_hook.reset_hook!
28211    $lisp_graph_hook.reset_hook!
28212    #
28213    ind = open_sound("oboe.snd")
28214    set_time_graph?(false, ind, 0)
28215    graph([vct(0, 1, 2), vct(3, 2, 1), vct(1, 2, 3), vct(1, 1, 1), vct(0, 1, 0), vct(3, 1, 2)])
28216    update_lisp_graph
28217    $lisp_graph_hook.add_hook!("snd-test") do |snd, chn|
28218      [basic_color, zoom_color, data_color, selected_data_color, mix_color]
28219    end
28220    graph([vct(0, 1, 2), vct(3, 2, 1), vct(1, 2, 3), vct(1, 1, 1), vct(0, 1, 0), vct(3, 1, 2)])
28221    update_lisp_graph
28222    $lisp_graph_hook.reset_hook!
28223    close_sound(ind)
28224    #
28225    ind1 = open_sound("2.snd")
28226    wids3 = channel_widgets(ind1, 0)
28227    wids4 = channel_widgets(ind1, 1)
28228    if (not list_p(wids)) or (not list_p(wids3)) or
28229        ($with_test_motif and (wids1.length != 11 or wids2.length != 11))
28230      snd_display("channel_widgets confused: %s %s %s %s %s?", wids, wids1, wids2, wids3, wids4)
28231    end
28232    hide_widget(channel_widgets.first)
28233    show_widget(channel_widgets.first)
28234    close_sound(true)
28235  end
28236end
28237
28238# ---------------- test 18: enved ----------------
28239
28240def test_18
28241  if $with_test_gui
28242    start_enveloping
28243    ind = open_sound("oboe.snd")
28244    if (res = channel_envelope(ind, 0)) != [0.0, 1.0, 1.0, 1.0]
28245      snd_display("channel_envelope: %s?", res)
28246    end
28247    set_channel_envelope([0, 0, 1, 1, 2, 0], ind, 0)
28248    if (res = channel_envelope(ind, 0)) != [0, 0, 1, 1, 2, 0]
28249      snd_display("set_channel_envelope: %s?", res)
28250    end
28251    close_sound(ind)
28252    stop_enveloping
28253  end
28254end
28255
28256# ---------------- test 19: save and restore ----------------
28257
28258def local_neq?(a, b)
28259  if float?(a) or float?(b)
28260    fneq(a, b)
28261  else
28262    a != b
28263  end
28264end
28265
28266def insert_vct(v, beg = 0, dur = false, snd = false, chn = false)
28267  insert_samples(beg, dur, v, snd, chn, false, false,
28268                 format("%s(%s, %s, %s", get_func_name, v.to_str, beg, dur))
28269end
28270
28271def clm_channel_test(snd = false, chn = false)
28272  clm_channel(make_two_zero(1, -1), 0, false, snd, chn, false, false, "clm_channel_test(")
28273end
28274
28275def make_v_mix(snd = false, chn = false)
28276  mix_vct([0.1, 0.2, 0.3].to_vct, 100, snd, chn, true, "mix_vct(vct(0.1, 0.2, 0.3)")
28277end
28278
28279def test_19_00
28280  nind = open_sound("oboe.snd")
28281  add_mark(123)
28282  delete_sample(12)
28283  set_x_bounds([0.2, 0.4])
28284  old_bounds = x_bounds
28285  set_show_axes(Show_all_axes)
28286  set_transform_graph_type(Graph_as_sonogram)
28287  set_speed_control_style(Speed_control_as_ratio)
28288  set_channel_style(Channels_superimposed)
28289  set_enved_target(Enved_srate)
28290  set_sound_property(:hi, "hi", nind)
28291  set_sound_property("ho", 1234, nind)
28292  set_channel_property(:ha, 3.14, nind, 0)
28293  $before_save_state_hook.reset_hook!
28294  $before_save_state_hook.add_hook!("snd-test") do |fname|
28295    File.open(File.expand_path(fname), "w") do |f|
28296      f.printf("# this comment will be at the top of the saved state file.\n")
28297    end
28298    true
28299  end
28300  delete_file(save_state_file)
28301  save_state(save_state_file)
28302  # save_options("test.temp")
28303  close_sound(nind)
28304  Snd.regions.apply(:forget_region)
28305  load(save_state_file)
28306  ind = find_sound("oboe.snd")
28307  if fneq_err(old_bounds[0], x_bounds(ind, 0)[0], 0.05) or
28308     fneq_err(old_bounds[1], x_bounds(ind, 0)[1], 0.05)
28309    snd_display("save bounds: %s?", x_bounds(ind, 0))
28310  end
28311  if marks(ind, 0).length != 1
28312    snd_display("save marks: %s?", marks(ind, 0))
28313  end
28314  if (res = mark_sample(marks(ind, 0)[0])) != 122
28315    snd_display("save mark: %s?", res)
28316  end
28317  if (res = edit_position(ind, 0)) != 1
28318    snd_display("save edit_position: %s?", res)
28319  end
28320  if (res = edit_fragment(1, ind, 0)) != ["delete_samples(12, 1", "delete", 12, 1]
28321    snd_display("save edits: %s?", res)
28322  end
28323  if (res = edit_tree(ind, 0)) != [[0, 0, 0, 11, 1.0, 0.0, 0.0, 0],
28324                                   [12, 0, 13, 50827, 1.0, 0.0, 0.0, 0],
28325                                   [50827, -2, 0, 0, 0.0, 0.0, 0.0, 0]]
28326    snd_display("save edit_tree: %s?", res)
28327  end
28328  if (res = sound_property("ho", ind)) != 1234
28329    snd_display("sound_property saved: 1234 -> %s?", res.inspect)
28330  end
28331  if (res = sound_property(:hi, ind)) != "hi"
28332    snd_display("sound_property saved: hi -> %s?", res.inspect)
28333  end
28334  if (res = channel_property(:ha, ind, 0)) != 3.14
28335    snd_display("channel_property saved: 3.14 -> %s?", res.inspect)
28336  end
28337  close_sound(ind)
28338  $before_save_state_hook.reset_hook!
28339  $after_save_state_hook.reset_hook!
28340  if (res = Snd.catch(:cannot_save, 12345) do save_state("/bad/bad.save") end).first != 12345
28341    snd_display("save_state err: %s", res.inspect)
28342  end
28343  if (res = Snd.catch(:cannot_save, 12345) do save_listener("/bad/bad.save") end).first != 12345
28344    snd_display("save_listener err: %s", res.inspect)
28345  end
28346  #
28347  nind = open_sound("oboe.snd")
28348  set_sample(1, 0.5)
28349  delete_sample(100)
28350  insert_sample(10, 0.5)
28351  scale_channel(2.0)
28352  insert_silence(100, 20)
28353  save_edit_history("hiho.rb")
28354  revert_sound(nind)
28355  sfile = nind
28356  eval(File.open("hiho.rb").read)
28357  if (res = edit_fragment(1)) != ["set_sample(1, 0.5000", "set", 1, 1]
28358    snd_display("save_edit_history 1: %s?", res)
28359  end
28360  if (res = edit_fragment(2)) != ["delete_samples(100, 1", "delete", 100, 1]
28361    snd_display("save_edit_history 2: %s?", res)
28362  end
28363  if (res = edit_fragment(3)) != ["insert_sample(10, 0.5000", "insert", 10, 1]
28364    snd_display("save_edit_history 3: %s?", res)
28365  end
28366  if (res = edit_fragment(4)) != ["scale_channel(2.000, 0, false", "scale", 0, 50828]
28367    snd_display("save_edit_history 4: %s?", res)
28368  end
28369  if (res = edit_fragment(5)) != ["pad-channel", "zero", 100, 20]
28370    snd_display("save_edit_history 5: %s?", res)
28371  end
28372  save_edit_history("hiho.rb", nind, 0)
28373  scale_sound_to(1.0, 0, framples(nind, 0), nind, 0)
28374  eds = edit_position(nind, 0)
28375  val = insert_sound("zero.snd")
28376  if val.nonzero? or eds != edit_position(nind, 0)
28377    snd_display("insert_sound zero.snd, was an edit? %s %s %s", val, eds, edit_position(nind, 0))
28378  end
28379  revert_sound(nind)
28380  scale_sound_to(0.5, 0, framples(nind, 0), nind, 0)
28381  if fneq(res = maxamp(nind, 0), 0.5)
28382    snd_display("scale_sound_to(0.5): %s?", res)
28383  end
28384  close_sound(nind)
28385  #
28386  nind = open_sound("oboe.snd")
28387  ramp_channel(0.0, 1.0)
28388  xramp_channel(0.0, 1.0, 32.0)
28389  save_edit_history("hiho.rb")
28390  revert_sound(nind)
28391  sfile = nind
28392  eval(File.open("hiho.rb").read)
28393  if (res = edit_fragment(1)) != ["ramp_channel(0.000, 1.000, 0, false", "env", 0, 50828]
28394    snd_display("save_edit_history ramp 1: %s?", res)
28395  end
28396  if (res = edit_fragment(2)) != ["xramp_channel(0.000, 1.000, 32.000, 0, false", "env", 0, 50828]
28397    snd_display("save_edit_history xramp 2: %s?", res)
28398  end
28399  revert_sound(nind)
28400  if (res = IO.readlines("hiho.rb")) != ["      ramp_channel(0.000, 1.000, 0, false, sfile, 0, false)\n",
28401                                         "      xramp_channel(0.000, 1.000, 32.000, 0, false, sfile, 0, false)\n"]
28402    snd_display("IO.readlines (file2string): %s?", res)
28403  end
28404  close_sound(nind)
28405  #
28406  add_sound_file_extension("ogg")
28407  add_sound_file_extension("OGG")
28408  add_sound_file_extension("sf")
28409  add_sound_file_extension("SF2")
28410  add_sound_file_extension("mp3")
28411  add_sound_file_extension("MP3")
28412  add_sound_file_extension("W01")
28413  add_sound_file_extension("W02")
28414  add_sound_file_extension("W03")
28415  add_sound_file_extension("W04")
28416  add_sound_file_extension("W05")
28417  add_sound_file_extension("W06")
28418  add_sound_file_extension("W07")
28419  add_sound_file_extension("W08")
28420  add_sound_file_extension("W09")
28421  add_sound_file_extension("W10")
28422  add_sound_file_extension("w01")
28423  add_sound_file_extension("w02")
28424  add_sound_file_extension("w03")
28425  add_sound_file_extension("w04")
28426  add_sound_file_extension("w05")
28427  add_source_file_extension("gad")
28428  #
28429  ind = new_sound("fmv.snd")
28430  set_sample(10, 0.1)
28431  save_sound(ind)
28432  set_sample(1, 0.1)
28433  eds = safe_display_edits(ind)
28434  delete_file("t1.rb")
28435  save_state("t1.rb")
28436  close_sound(ind)
28437  # If savehook.snd doesn't exist, an IO-error will be raised.
28438  Snd.regions.each do |r| Snd.catch(:io_error) do forget_region(r) end end
28439  load("t1.rb")
28440  ind = find_sound("fmv.snd")
28441  unless sound?(ind)
28442    snd_display("save_state restored but no sound?")
28443  end
28444  3.upto(5) do |i|
28445    set_sample(i, i * 0.1)
28446    eds = safe_display_edits(ind)
28447    delete_file("t1.rb")
28448    save_state("t1.rb")
28449    close_sound(ind)
28450    Snd.regions.apply(:forget_region)
28451    load("t1.rb")
28452    ind = find_sound("fmv.snd")
28453    unless sound?(ind)
28454      snd_display("save_state %s restored but no sound?", i)
28455    end
28456  end
28457  close_sound(ind)
28458  delete_file("t1.rb")
28459  #
28460  ind = new_sound("fmv.snd", 8, 22050, Mus_bshort, Mus_next,
28461                  "this is an 8-channel save-state test")
28462  ind1 = new_sound("fmv1.snd", 2, 22050, Mus_bshort, Mus_next,
28463                   "this is an 2-channel save-state test")
28464  set_sample(10, 0.1, ind, 0)
28465  set_sample(10, 0.2, ind, 1)
28466  set_sample(10, 0.3, ind, 2)
28467  set_sample(10, 0.4, ind, 3)
28468  set_sample(10, -0.1, ind1, 0)
28469  set_sample(10, -0.2, ind1, 1)
28470  save_sound(ind)
28471  save_sound(ind1)
28472  set_sample(1, 0.1, ind, 0)
28473  set_sample(1, 0.2, ind, 1)
28474  set_sample(1, 0.3, ind, 2)
28475  set_sample(1, 0.4, ind, 3)
28476  set_sample(1, -0.1, ind1, 0)
28477  set_sample(1, -0.2, ind1, 1)
28478  eds = safe_display_edits(ind)
28479  eds1 = safe_display_edits(ind1)
28480  delete_file("t1.rb")
28481  save_state("t1.rb")
28482  close_sound(ind)
28483  close_sound(ind1)
28484  Snd.regions.apply(:forget_region)
28485  load("t1.rb")
28486  ind = find_sound("fmv.snd")
28487  ind1 = find_sound("fmv1.snd")
28488  if (not sound?(ind)) or (not sound?(ind1))
28489    snd_display("save_state (2) restored but no sound? %s %s", ind, ind1)
28490  end
28491  close_sound(ind)
28492  close_sound(ind1)
28493  delete_file("t1.rb")
28494  #
28495  ind = open_sound("oboe.snd")
28496  old_save_dir = save_dir
28497  old_eps_file = eps_file
28498  set_save_dir(false)
28499  set_samples(100, 32, Vct.new(32, 1.0))
28500  map_channel(lambda do |y| y + 0.1 end, 1000, 10000)
28501  set_show_axes(Show_no_axes, ind, 0)
28502  set_zoom_focus_style(Zoom_focus_middle)
28503  set_transform_normalization(Dont_normalize, ind, 0)
28504  set_graph_style(Graph_filled, ind, 0)
28505  set_transform_graph_type(Graph_as_spectrogram, ind, 0)
28506  set_time_graph_type(Graph_as_wavogram, ind, 0)
28507  set_x_axis_style(X_axis_as_percentage, ind, 0)
28508  set_speed_control_style(Speed_control_as_semitone, ind, 0)
28509  set_cursor(1234, ind, 0)
28510  set_eps_file("hiho.eps")
28511  set_amp_control_bounds([0.0, 2.5], ind)
28512  set_speed_control_bounds([1.0, 2.5], ind)
28513  set_reverb_control_scale_bounds([0.0, 2.5], ind)
28514  set_reverb_control_length_bounds([0.0, 2.5], ind)
28515  set_contrast_control_bounds([0.0, 2.5], ind)
28516  set_x_axis_label("time-x", ind, 0, Time_graph)
28517  set_y_axis_label("amp-y", ind, 0, Time_graph)
28518  old_srate = mus_srate
28519  old_file_buffer_size = mus_file_buffer_size
28520  old_array_print_length = mus_array_print_length
28521  old_clm_table_size = clm_table_size
28522  set_mus_srate(48000)
28523  set_mus_array_print_length(24)
28524  set_mus_file_buffer_size(4096)
28525  set_clm_table_size(256)
28526  delete_file("s61.rb")
28527  save_state("s61.rb")
28528  close_sound(ind)
28529  Snd.regions.apply(:forget_region)
28530  load("s61.rb")
28531  if fneq(res = mus_srate, 48000.0)
28532    snd_display("save/restore mus_srate: %s", res)
28533  end
28534  if (res = mus_file_buffer_size) != 4096
28535    snd_display("save/restore mus_file_buffer_size: %s", res)
28536  end
28537  if (res = mus_array_print_length) != 24
28538    snd_display("save/restore mus_array_print_length: %s", res)
28539  end
28540  if (res = clm_table_size) != 256
28541    snd_display("save/restore clm_table_size: %s", res)
28542  end
28543  set_mus_srate(old_srate)
28544  set_mus_array_print_length(old_array_print_length)
28545  set_mus_file_buffer_size(old_file_buffer_size)
28546  set_clm_table_size(old_clm_table_size)
28547  set_save_dir(old_save_dir)
28548  ind = find_sound("oboe.snd")
28549  if (res = show_axes(ind, 0)) != Show_no_axes
28550    snd_display("save Show_no_axes: %s?", res.inspect)
28551  end
28552  if (res = zoom_focus_style) != Zoom_focus_middle
28553    snd_display("save Zoom_focus_middle: %s?", res.inspect)
28554  end
28555  if (res = transform_normalization(ind, 0)) != Dont_normalize
28556    snd_display("save Dont_normalize: %s?", res.inspect)
28557  end
28558  if (res = graph_style(ind, 0)) != Graph_filled
28559    snd_display("save Graph_filled: %s?", res.inspect)
28560  end
28561  if (res = transform_graph_type(ind, 0)) != Graph_as_spectrogram
28562    snd_display("save Graph_as_spectrogram: %s?", res.inspect)
28563  end
28564  if (res = time_graph_type(ind, 0)) != Graph_as_wavogram
28565    snd_display("save Graph_as_wavogram: %s?", res.inspect)
28566  end
28567  if (res = x_axis_style(ind, 0)) != X_axis_as_percentage
28568    snd_display("save X_axis_as_percentage: %s?", res.inspect)
28569  end
28570  if (res = speed_control_style(ind)) != Speed_control_as_semitone
28571    snd_display("save Speed_control_as_semitone: %s?", res.inspect)
28572  end
28573  if (res = cursor(ind, 0)) != 1234
28574    snd_display("save cursor 1234: %s?", res.inspect)
28575  end
28576  if (res = eps_file) != "hiho.eps"
28577    snd_display("save eps_file: %s?", res.inspect)
28578  end
28579  if defined? set_x_axis_label
28580    if (res = x_axis_label(ind, 0, Time_graph)) != "time-x"
28581      snd_display("save x_axis_label: %s?", res.inspect)
28582    end
28583    if (res = y_axis_label(ind, 0, Time_graph)) != "amp-y"
28584      snd_display("save y_axis_label: %s?", res.inspect)
28585    end
28586  end
28587  if amp_control_bounds(ind) != [0.0, 2.5]
28588    snd_display("save amp_control_bounds: %s?", res.inspect)
28589  end
28590  if speed_control_bounds(ind) != [1.0, 2.5]
28591    snd_display("save speed_control_bounds: %s?", res.inspect)
28592  end
28593  if contrast_control_bounds(ind) != [0.0, 2.5]
28594    snd_display("save contrast_control_bounds: %s?", res.inspect)
28595  end
28596  if reverb_control_scale_bounds(ind) != [0.0, 2.5]
28597    snd_display("save reverb_control_scale_bounds: %s?", res.inspect)
28598  end
28599  if reverb_control_length_bounds(ind) != [0.0, 2.5]
28600    snd_display("save reverb_control_length_bounds: %s?", res.inspect)
28601  end
28602  set_eps_file(old_eps_file)
28603  delete_file("s61.rb")
28604  close_sound(ind)
28605  #
28606  ind = open_sound("oboe.snd")
28607  old_tiny_font = tiny_font
28608  old_peaks_font = peaks_font
28609  old_bold_peaks_font = bold_peaks_font
28610  old_amp = amp_control_bounds
28611  old_speed = speed_control_bounds
28612  old_contrast = contrast_control_bounds
28613  old_revlen = reverb_control_length_bounds
28614  old_revscl = reverb_control_scale_bounds
28615  set_tiny_font("8x13")
28616  set_peaks_font("8x13")
28617  set_bold_peaks_font("8x13")
28618  set_amp_control_bounds([0.0, 2.5])
28619  set_speed_control_bounds([1.0, 2.5])
28620  set_reverb_control_scale_bounds([0.0, 2.5])
28621  set_reverb_control_length_bounds([0.0, 2.5])
28622  set_contrast_control_bounds([0.0, 2.5])
28623  save_state("s61.rb")
28624  close_sound(ind)
28625  Snd.regions.apply(:forget_region)
28626  load("s61.rb")
28627  ind = find_sound("oboe.snd")
28628  if (res = tiny_font) != "8x13"
28629    snd_display("save tiny_font: %s?", res)
28630  end
28631  if (res = peaks_font) != "8x13"
28632    snd_display("save peaks_font: %s?", res)
28633  end
28634  if (res = bold_peaks_font) != "8x13"
28635    snd_display("save bold_peaks_font: %s?", res)
28636  end
28637  if amp_control_bounds() != [0.0, 2.5]
28638    snd_display("save amp_control_bounds: %s?", res)
28639  end
28640  if speed_control_bounds() != [1.0, 2.5]
28641    snd_display("save speed_control_bounds: %s?", res)
28642  end
28643  if contrast_control_bounds() != [0.0, 2.5]
28644    snd_display("save contrast_control_bounds: %s?", res)
28645  end
28646  if reverb_control_scale_bounds() != [0.0, 2.5]
28647    snd_display("save reverb_control_scale_bounds: %s?", res)
28648  end
28649  if reverb_control_length_bounds() != [0.0, 2.5]
28650    snd_display("save reverb_control_length_bounds: %s?", res)
28651  end
28652  set_tiny_font(old_tiny_font)
28653  set_peaks_font(old_peaks_font)
28654  set_bold_peaks_font(old_bold_peaks_font)
28655  set_amp_control_bounds(old_amp)
28656  set_speed_control_bounds(old_speed)
28657  set_contrast_control_bounds(old_contrast)
28658  set_reverb_control_length_bounds(old_revlen)
28659  set_reverb_control_scale_bounds(old_revscl)
28660  delete_file("s61.rb")
28661  close_sound(ind)
28662end
28663
28664def test_19_01
28665  #                                   new_globals         new_locals
28666  funcs = [[:transform_graph_type,    Graph_as_sonogram,  Graph_once],
28667           [:time_graph_type,         Graph_as_wavogram,  Graph_once],
28668           [:show_axes,               Show_all_axes,      Show_x_axis],
28669           [:transform_normalization, Normalize_by_sound, Normalize_by_channel],
28670           [:graph_style,             Graph_dots,         Graph_lines],
28671           [:x_axis_style,            X_axis_in_samples,  X_axis_in_seconds],
28672           [:spectro_x_scale,         0.1,                1.0],
28673           [:transform_size,          32,                 256],
28674           [:fft_window,              Bartlett_window,    Blackman2_window],
28675           [:dot_size,                4,                  1],
28676           [:max_transform_peaks,     10,                 100],
28677           [:with_verbose_cursor,     true,               false],
28678           [:zero_pad,                1,                  0],
28679           [:min_dB,                  -90,                -60],
28680           [:spectro_hop,             12,                 4],
28681           [:spectrum_end,            0.1,                1.0],
28682           [:cursor_size,             15,                 25],
28683           [:cursor_style,            Cursor_cross,       Cursor_line]]
28684  old_globals = funcs.map do |func, global, local| snd_func(func) end
28685  ind = open_sound("oboe.snd")
28686  funcs.each do |func, global, local|
28687    set_snd_func(func, global)
28688    set_snd_func(func, local, ind, 0)
28689  end
28690  set_zoom_focus_style(Zoom_focus_right)
28691  set_channel_style(Channels_combined)
28692  set_channel_style(Channels_separate, ind)
28693  delete_file("s61.rb")
28694  save_state("s61.rb")
28695  close_sound(ind)
28696  Snd.regions.apply(:forget_region)
28697  load("s61.rb")
28698  ind = find_sound("oboe.snd")
28699  funcs.each do |func, global, local|
28700    if $with_test_nogui
28701      next if func == :transform_normalization
28702      next if func == :spectro_x_scale
28703      next if func == :spectro_hop
28704      next if func == :spectrum_end
28705    end
28706    if local_neq?(res1 = snd_func(func), global) or
28707        local_neq?(res2 = snd_func(func, ind, 0), local)
28708      snd_display("save %s reversed: %s [%s] %s [%s]?", func, res1, global, res2, local)
28709    end
28710  end
28711  if (res = channel_style(ind)) != Channels_separate
28712    snd_display("save channel_style reversed: %s %s?", channel_style, res)
28713  end
28714  funcs.zip(old_globals) do |args, old_global|
28715    set_snd_func(args.first, old_global)
28716  end
28717  close_sound(ind)
28718  set_zoom_focus_style(Zoom_focus_active)
28719  set_channel_style(Channels_separate)
28720  delete_file("s61.rb")
28721  #
28722  ind0 = open_sound("oboe.snd")
28723  ind1 = open_sound("oboe.snd")
28724  if (res = find_sound("oboe.snd", 0)) != ind0
28725    snd_display("find_sound 0: ind0 %s res %s?", ind0, res)
28726  end
28727  if (res = find_sound("oboe.snd", 1)) != ind1
28728    snd_display("find_sound 1: ind1 %s res %s?", ind1, res)
28729  end
28730  add_mark(123, ind0)
28731  add_mark(321, ind1)
28732  delete_file("s61.rb")
28733  save_state("s61.rb")
28734  close_sound(ind0)
28735  close_sound(ind1)
28736  load("s61.rb")
28737  ind0 = find_sound("oboe.snd", 0)
28738  ind1 = find_sound("oboe.snd", 1)
28739  if (not ind0) or (not ind1)
28740    snd_display("saved 2oboes, found: %s", Snd.sounds.map do |s| short_file_name(s) end)
28741  end
28742  unless find_mark(123, ind0)
28743    snd_display("saved 2oboes mark 0?")
28744  end
28745  if find_mark(123, ind1)
28746    snd_display("saved 2oboes mark 1->0?")
28747  end
28748  unless find_mark(321, ind1)
28749    snd_display("saved 2oboes mark 1?")
28750  end
28751  if find_mark(321, ind0)
28752    snd_display("saved 2oboes mark 0->1?")
28753  end
28754  close_sound(ind0)
28755  close_sound(ind1)
28756  # basic choices
28757  [[lambda { |ind| insert_sample(10, 0.5, ind, 0) },
28758    lambda { |ind|
28759      if fneq(sample(10), 0.5)
28760        snd_display("insert_sample save_state: %s?", channel2vct(5, 10, ind, 0))
28761      end
28762      if (res = framples(ind, 0)) != 101
28763        snd_display("insert_sample save_state len: %s?", res)
28764      end
28765    }],
28766   [lambda { |ind| delete_sample(10, ind, 0) },
28767    lambda { |ind|
28768      if fneq(sample(10), 0.0)
28769        snd_display("delete_sample save_state: %s?", channel2vct(5, 10, ind, 0))
28770      end
28771      if (res = framples(ind, 0)) != 99
28772        snd_display("delete_sample save_state len: %s?", res)
28773      end
28774    }],
28775   [lambda { |ind| set_sample(10, 0.5, ind, 0) },
28776    lambda { |ind|
28777      if fneq(sample(10), 0.5)
28778        snd_display("set_sample save_state: %s?", channel2vct(5, 10, ind, 0))
28779      end
28780      if (res = framples(ind, 0)) != 100
28781        snd_display("set_sample save_state len: %s?", res)
28782      end
28783    }],
28784   [lambda { |ind| set_sample(10, 0.5, ind, 0); scale_channel(0.5) },
28785    lambda { |ind|
28786      if fneq(sample(10), 0.25)
28787        snd_display("scl sample save_state: %s?", channel2vct(5, 10, ind, 0))
28788      end
28789      if (res = framples(ind, 0)) != 100
28790        snd_display("scl sample save_state len: %s?", res)
28791      end
28792      if (res = edit_position(ind, 0)) != 2
28793        snd_display("scl sample save_state edpos: %s?", res)
28794      end
28795    }],
28796   [lambda { |ind| vct2channel(Vct.new(10, 0.5), 10, 5, ind, 0); pad_channel(12, 5, ind, 0) },
28797    lambda { |ind|
28798      if (res = framples(ind, 0)) != 105
28799        snd_display("pad sample save_state len: %s?", res)
28800      end
28801      if (res = edit_position(ind, 0)) != 2
28802        snd_display("pad sample save_state edpos: %s?", res)
28803      end
28804      unless vequal(res = channel2vct(10, 10, ind, 0),
28805                    vct(0.5, 0.5, 0, 0, 0, 0, 0, 0.5, 0.5, 0.5))
28806        snd_display("pad sample save_state: %s?", res)
28807      end
28808    }],
28809   [lambda { |ind| map_channel(lambda { |y| 1.0 }); env_channel([0, 0, 1, 1], 0, 11, ind, 0) },
28810    lambda { |ind|
28811      if (res = framples(ind, 0)) != 100
28812        snd_display("env sample save_state len: %s?", res)
28813      end
28814      if (res = edit_position(ind, 0)) != 2
28815        snd_display("env sample save_state edpos: %s?", res)
28816      end
28817      unless vequal(res = channel2vct(0, 15, ind, 0),
28818                    vct(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1, 1, 1, 1))
28819        snd_display("env sample save_state: %s?", res)
28820      end
28821    }],
28822   # map_channel as backup
28823   [lambda { |ind|
28824      ctr = 0
28825      map_channel(lambda { |y|
28826                    ctr += 1
28827                    ctr.even? ? 0.1 : false
28828                  })
28829    },
28830    lambda { |ind|
28831      if (res = framples(ind, 0)) != 50
28832        snd_display("map false save_state len: %s?", res)
28833      end
28834      if (res = edit_position(ind, 0)) != 1
28835        snd_display("map false save_state edpos: %s?", res)
28836      end
28837      if fneq(res = maxamp(ind, 0), 0.1)
28838        snd_display("map false save_state max: %s?", res)
28839      end
28840      unless vequal(res = channel2vct(0, 10, ind, 0), Vct.new(10, 0.1))
28841        snd_display("map false save_state: %s?", res)
28842      end
28843    }],
28844   # as_one_edit
28845   [lambda { |ind|
28846      as_one_edit(lambda { | |
28847                    vct2channel(Vct.new(10) { |i| (i + 1) * 0.1 },  0, 10, ind, 0)
28848                    vct2channel(Vct.new(10) { |i| (i + 1) * 0.1 }, 20, 10, ind, 0)
28849                  })
28850    },
28851    lambda { |ind|
28852      if (res = edit_position(ind, 0)) != 1
28853        snd_display("save_state backup 2 vcts edpos: %s?", res)
28854      end
28855      unless vequal(res = channel2vct( 0, 10, ind, 0), Vct.new(10) { |i| (i + 1) * 0.1 })
28856        snd_display("as_one_edit save_state 1: %s?", res.to_str)
28857      end
28858      unless vequal(res = channel2vct(20, 10, ind, 0), Vct.new(10) { |i| (i + 1) * 0.1 })
28859        snd_display("as_one_edit save_state 2: %s?", res.to_str)
28860      end
28861    }],
28862   [lambda { |ind|
28863      as_one_edit(lambda { | |
28864                    vct2channel(Vct.new(10) { |i| (i + 1) * 0.1 },  0, 10, ind, 0)
28865                    scale_by(0.5)
28866                  })
28867    },
28868    lambda { |ind|
28869      if (res = edit_position(ind, 0)) != 1
28870        snd_display("save_state backup vct+scl edpos: %s?", res)
28871      end
28872      unless vequal(res = channel2vct(0, 10, ind, 0),
28873                    Vct.new(10) { |i| (i + 1) * 0.1 }.scale(0.5))
28874        snd_display("as_one_edit save_state 3: %s?", res)
28875      end
28876    }],
28877   [lambda { |ind|
28878      as_one_edit(lambda { | |
28879                    vct2channel(Vct.new(10) { |i| (i + 1) * 0.1 },  0, 10, ind, 0)
28880                    delete_samples(5, 5)
28881                  })
28882    },
28883    lambda { |ind|
28884      if (res = edit_position(ind, 0)) != 1
28885        snd_display("save_state backup vct+del edpos: %s?", res)
28886      end
28887      unless vequal(res = channel2vct(0, 10, ind, 0), Vct.new(10) { |i|
28888                      if i < 5
28889                        (i + 1) * 0.1
28890                      else
28891                        0.0
28892                      end
28893                    })
28894        snd_display("as_one_edit save_state 4: %s?", res)
28895      end
28896    }],
28897   [lambda { |ind|
28898      as_one_edit(lambda { | |
28899                    delete_samples(5, 5)
28900                    insert_samples(5, 2, vct(0.1, 0.2))
28901                  })
28902    },
28903    lambda { |ind|
28904      if (res = edit_position(ind, 0)) != 1
28905        snd_display("save_state backup del+insert edpos: %s?", res)
28906      end
28907      unless vequal(res = channel2vct(0, 10, ind, 0), Vct.new(10) { |i|
28908                      case i
28909                      when 5
28910                        0.1
28911                      when 6
28912                        0.2
28913                      else
28914                        0.0
28915                      end
28916                    })
28917        snd_display("as_one_edit save_state 5: %s?", res)
28918      end
28919      if (res = framples(ind, 0)) != 97
28920        snd_display("save_state backup del+insert len: %s?", res)
28921      end
28922    }],
28923   # 2 embedded as_one_edits
28924   [lambda { |ind|
28925      map_channel(lambda { |y| -1.0 })
28926      as_one_edit(lambda { | |
28927                    delete_samples(5, 5)
28928                    insert_samples(5, 2, vct(0.1, 0.2))
28929                  })
28930      scale_channel(2.0)
28931      as_one_edit(lambda { | |
28932                    vct2channel(Vct.new(10) { |i| (i + 1) * 0.1 }, 10, 10, ind, 0)
28933                    vct2channel(Vct.new(10) { |i| (i + 1) * 0.1 }, 20, 10, ind, 0)
28934                  })
28935      delete_samples(15, 10)
28936    },
28937    lambda { |ind|
28938      if (res = edit_position(ind, 0)) != 5
28939        snd_display("embed save_state edpos: %s?", res)
28940      end
28941      if (res = framples(ind, 0)) != 87
28942        snd_display("embed save_state len: %s?", res)
28943      end
28944      unless vequal(res = channel2vct(0, 25, ind, 0),
28945                    vct(-2, -2, -2, -2, -2, 0.2, 0.4, -2, -2, -2, 0.1, 0.2, 0.3,
28946                        0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, -2, -2, -2, -2, -2))
28947        snd_display("embed save_state 9: %s?", res.to_str)
28948      end
28949    }]].each_with_index do |args, i|
28950    func = args[0]
28951    test = args[1]
28952    ind = new_sound("test.snd", 1, 22050, Mus_bfloat, Mus_next,
28953                    "mono save-state tests", 100)
28954    func.call(ind)
28955    delete_file("s61.rb")
28956    save_state("s61.rb")
28957    close_sound(ind)
28958    load("s61.rb")
28959    if sound?(ind = find_sound("test.snd"))
28960      test.call(ind)
28961      close_sound(ind)
28962    else
28963      snd_display("save_state test %s no test.snd?", i)
28964    end
28965  end
28966end
28967
28968def test_19_02
28969  #
28970  # edit_list2function
28971  #
28972  ind = open_sound("oboe.snd")
28973  mx0 = maxamp
28974  frs = framples
28975  # simple scale
28976  scale_channel(2.0)
28977  if fneq(res = maxamp, 2 * mx0)
28978    snd_display("edit_list2function off to a bad start: %s?", res)
28979  end
28980  unless proc?(func = edit_list2function)
28981    snd_display("edit_list2function 1: %s", func)
28982  end
28983  if (res = func.source) != "Proc.new {|snd, chn|  scale_channel(2.000, 0, false, snd, chn) }"
28984    snd_display("edit_list2function 1: %s", res)
28985  end
28986  func.call(ind, 0)
28987  if fneq(res = maxamp, 4 * mx0)
28988    snd_display("edit_list2function called (1): %s %s?", res, mx0)
28989  end
28990  revert_sound(ind)
28991  scale_by(2.0)
28992  unless proc?(func = edit_list2function)
28993    snd_display("edit_list2function 1a: %s", func)
28994  end
28995  if (res = func.source) != "Proc.new {|snd, chn|  scale_channel(2.000, 0, false, snd, chn) }"
28996    snd_display("edit_list2function 1a: %s", res)
28997  end
28998  revert_sound(ind)
28999  normalize_channel(1.001)      # normalize_channel(1.0) seems to do nothing
29000  unless proc?(func = edit_list2function)
29001    snd_display("edit_list2function 1c: %s", func)
29002  end
29003  if (res = func.source) != "Proc.new {|snd, chn|  normalize_channel(1.001, 0, false, snd, chn) }"
29004    snd_display("edit_list2function 1c: %s", res)
29005  end
29006  revert_sound(ind)
29007  # simple delete
29008  delete_samples(10, 100)
29009  if (res = framples) != frs - 100
29010    snd_display("edit_list2function delete: %s %s?", frs, res)
29011  end
29012  unless proc?(func = edit_list2function)
29013    snd_display("edit_list2function 2: %s", func)
29014  end
29015  if (res = func.source) != "Proc.new {|snd, chn|  delete_samples(10, 100, snd, chn) }"
29016    snd_display("edit_list2function 2: %s", res)
29017  end
29018  func.call(ind, 0)
29019  if (res = framples) != frs - 200
29020    snd_display("edit_list2function called (2): %s %s?", frs, res)
29021  end
29022  revert_sound(ind)
29023  delete_sample(100)
29024  if (res = framples) != frs - 1
29025    snd_display("edit_list2function delete (2a): %s %s?", frs, res)
29026  end
29027  unless proc?(func = edit_list2function)
29028    snd_display("edit_list2function 2a: %s", func)
29029  end
29030  if (res = func.source) != "Proc.new {|snd, chn|  delete_samples(100, 1, snd, chn) }"
29031    snd_display("edit_list2function 2a: %s", res)
29032  end
29033  func.call(ind, 0)
29034  if (res = framples) != frs - 2
29035    snd_display("edit_list2function called (2a): %s %s?", frs, res)
29036  end
29037  revert_sound(ind)
29038  # simple zero pad
29039  pad_channel(10, 100)
29040  if (res = framples) != frs + 100
29041    snd_display("edit_list2function pad: %s %s?", frs, res)
29042  end
29043  unless proc?(func = edit_list2function)
29044    snd_display("edit_list2function 3: %s", func)
29045  end
29046  if (res = func.source) != "Proc.new {|snd, chn|  pad_channel(10, 100, snd, chn) }"
29047    snd_display("edit_list2function 3: %s", res)
29048  end
29049  func.call(ind, 0)
29050  if (res = framples) != frs + 200
29051    snd_display("edit_list2function called (3): %s %s?", frs, res)
29052  end
29053  revert_sound(ind)
29054  insert_silence(10, 100)
29055  if (res = framples) != frs + 100
29056    snd_display("edit_list2function pad (3a): %s %s?", frs, res)
29057  end
29058  unless proc?(func = edit_list2function)
29059    snd_display("edit_list2function 3a: %s", func)
29060  end
29061  if (res = func.source) != "Proc.new {|snd, chn|  pad_channel(10, 100, snd, chn) }"
29062    snd_display("edit_list2function 3a: %s", res)
29063  end
29064  func.call(ind, 0)
29065  if (res = framples) != frs + 200
29066    snd_display("edit_list2function called (3a): %s %s?", frs, res)
29067  end
29068  revert_sound(ind)
29069  # simple ramp
29070  ramp_channel(0.2, 0.9)
29071  snd_test_neq(maxamp(), 0.0899, "edit_list2function ramp")
29072  unless proc?(func = edit_list2function)
29073    snd_display("edit_list2function 4: %s", func)
29074  end
29075  if (res = func.source) != "Proc.new {|snd, chn|  ramp_channel(0.200, 0.900, 0, false, snd, chn) }"
29076    snd_display("edit_list2function 4: %s", res)
29077  end
29078  func.call(ind, 0)
29079  snd_test_neq(maxamp(), 0.061, "edit_list2function called (4)")
29080  revert_sound(ind)
29081  # simple xramp
29082  xramp_channel(0.2, 0.9, 32.0)
29083  snd_test_neq(maxamp(), 0.055, "edit_list2function xramp")
29084  unless proc?(func = edit_list2function)
29085    snd_display("edit_list2function 5: %s", func)
29086  end
29087  if (res = func.source) != "Proc.new {|snd, chn|  xramp_channel(0.200, 0.900, 32.000, 0, false, snd, chn) }"
29088    snd_display("edit_list2function 5: %s", res)
29089  end
29090  func.call(ind, 0)
29091  if fneq(res = maxamp, 0.0266)
29092    snd_display("edit_list2function called (5): %s?", res)
29093  end
29094  revert_sound(ind)
29095  # simple env
29096  env_sound([0, 0, 1, 1])
29097  snd_test_neq(maxamp(), 0.0906, "edit_list2function env")
29098  unless proc?(func = edit_list2function)
29099    snd_display("edit_list2function 6: %s", func)
29100  end
29101  if (res = func.source) != "Proc.new {|snd, chn|  env_channel([0.000, 0.000, 1.000, 1.000], 0, false, snd, chn) }"
29102    snd_display("edit_list2function 6: %s", res)
29103  end
29104  func.call(ind, 0)
29105  snd_test_neq(maxamp(), 0.0634, "edit_list2function called (6)")
29106  revert_sound(ind)
29107  # less simple env
29108  env_sound([0, 0, 1, 0.3, 2, 0.8, 3, 0])
29109  snd_test_neq(maxamp(), 0.107, "edit_list2function env (7)")
29110  unless proc?(func = edit_list2function)
29111    snd_display("edit_list2function 7: %s", func)
29112  end
29113  if (res = func.source) != "Proc.new {|snd, chn|  env_channel([0.000, 0.000, 1.000, 0.300, 2.000, 0.800, 3.000, 0.000], 0, false, snd, chn) }"
29114    snd_display("edit_list2function 7: %s", res)
29115  end
29116  func.call(ind, 0)
29117  if fneq(res = maxamp, 0.0857)
29118    snd_display("edit_list2function called (7): %s?", res)
29119  end
29120  revert_sound(ind)
29121  env_sound([0, 0, 1, 0.3, 2, 0.8, 3, 0])
29122  unless proc?(func = edit_list2function)
29123    snd_display("edit_list2function 7a: %s", func)
29124  end
29125  if (res = func.source) != "Proc.new {|snd, chn|  env_channel([0.000, 0.000, 1.000, 0.300, 2.000, 0.800, 3.000, 0.000], 0, false, snd, chn) }"
29126    snd_display("edit_list2function 7a: %s", res)
29127  end
29128  revert_sound(ind)
29129  env_sound([0, 0, 1, 0.3, 2, 0.8, 3, 0], 1000, 2000)
29130  unless proc?(func = edit_list2function)
29131    snd_display("edit_list2function 7b: %s", func)
29132  end
29133  if (res = func.source) != "Proc.new {|snd, chn|  env_channel(make_env([0.000, 0.000, 1.000, 0.300, 2.000, 0.800, 3.000, 0.000], :base, 1.0000, :end, 1999), 1000, 2000, snd, chn) }"
29134    snd_display("edit_list2function 7b: %s", res)
29135  end
29136  revert_sound(ind)
29137  env_sound(make_env(:envelope, [0, 0, 1, 0.3, 2, 0.8, 3, 0], :base, 32.0, :length, 2000), 1000, 2000)
29138  mxenv0 = maxamp
29139  unless proc?(func = edit_list2function)
29140    snd_display("edit_list2function 7c: %s", func)
29141  end
29142  if (res = func.source) != "Proc.new {|snd, chn|  env_channel(make_env([0.000, 0.000, 1.000, 0.300, 2.000, 0.800, 3.000, 0.000], :base, 32.0000, :end, 1999), 1000, 2000, snd, chn) }"
29143    snd_display("edit_list2function 7c: %s", res)
29144  end
29145  revert_sound(ind)
29146  env_sound(make_env(:envelope, [0, 0, 1, 0.3, 2, 0.8, 3, 0],
29147                     :offset, 2.0,
29148                     :scaler, 3.0,
29149                     :length, 2000),
29150            1000, 2000)
29151  mxenv1 = maxamp
29152  unless proc?(func = edit_list2function)
29153    snd_display("edit_list2function 7d: %s", func)
29154  end
29155  if (res = func.source) != "Proc.new {|snd, chn|  env_channel(make_env([0.000, 2.000, 1.000, 2.900, 2.000, 4.400, 3.000, 2.000], :base, 1.0000, :end, 1999), 1000, 2000, snd, chn) }"
29156    snd_display("edit_list2function 7d: %s", res)
29157  end
29158  revert_sound(ind)
29159  func.call(ind, 0)
29160  if fneq(res = maxamp, mxenv1)
29161    snd_display("edit_list2function 7d max: %s %s %s?", res, mxenv1, mxenv0)
29162  end
29163  revert_sound(ind)
29164  5.times do |i| env_channel([0, 0, 1, 1, 2, 0]) end
29165  unless proc?(func = edit_list2function)
29166    snd_display("edit_list2function 7e: %s", func)
29167  end
29168  if (res = func.source) != "Proc.new {|snd, chn|  env_channel([0.000, 0.000, 1.000, 1.000, 2.000, 0.000], 0, false, snd, chn); env_channel([0.000, 0.000, 1.000, 1.000, 2.000, 0.000], 0, false, snd, chn); env_channel([0.000, 0.000, 1.000, 1.000, 2.000, 0.000], 0, false, snd, chn); env_channel([0.000, 0.000, 1.000, 1.000, 2.000, 0.000], 0, false, snd, chn); env_channel([0.000, 0.000, 1.000, 1.000, 2.000, 0.000], 0, false, snd, chn) }"
29169    snd_display("edit_list2function 7e: %s", res)
29170  end
29171  revert_sound(ind)
29172  func.call(ind, 0)
29173  snd_test_neq(maxamp(), 0.146, "edit_list2function 7e max")
29174  if (res = edit_position) != 5
29175    snd_display("edit_list2function 7e edpos: %s?", res)
29176  end
29177  revert_sound(ind)
29178  env_sound([0, 0, 1, 1, 2, 0], 0, framples, 32.0)
29179  snd_test_neq(maxamp(), 0.146, "edit_list2function 7f max")
29180  unless proc?(func = edit_list2function)
29181    snd_display("edit_list2function 7f: %s", func)
29182  end
29183  if (res = func.source) != "Proc.new {|snd, chn|  env_channel_with_base([0.000, 0.000, 1.000, 1.000, 2.000, 0.000], 32.0000, 0, false, snd, chn) }"
29184    snd_display("edit_list2function 7f: %s", res)
29185  end
29186  revert_sound(ind)
29187  func.call(ind, 0)
29188  snd_test_neq(maxamp(), 0.146, "edit_list2function called (7f)")
29189  revert_sound(ind)
29190  env_sound([0, 0, 1, 1, 2, 1, 3, 0], 0, framples, 0.0)
29191  if fneq(res = sample(4000), 0.0)
29192    snd_display("edit_list2function env 7g: %s?", res)
29193  end
29194  unless proc?(func = edit_list2function)
29195    snd_display("edit_list2function 7g: %s", func)
29196  end
29197  if (res = func.source) != "Proc.new {|snd, chn|  env_channel_with_base([0.000, 0.000, 1.000, 1.000, 2.000, 1.000, 3.000, 0.000], 0.0000, 0, false, snd, chn) }"
29198    snd_display("edit_list2function 7g: %s", res)
29199  end
29200  revert_sound(ind)
29201  func.call(ind, 0)
29202  if fneq(res = sample(4000), 0.0)
29203    snd_display("edit_list2function called (7g): %s?", res)
29204  end
29205  revert_sound(ind)
29206  # simple 1 sample insert
29207  insert_sample(100, 0.1)
29208  if (res = framples) != frs + 1
29209    snd_display("edit_list2function insert_sample: %s %s?", frs, res)
29210  end
29211  unless proc?(func = edit_list2function)
29212    snd_display("edit_list2function 9: %s", func)
29213  end
29214  if (res = func.source) != "Proc.new {|snd, chn|  insert_sample(100, 0.1000, snd, chn) }"
29215    snd_display("edit_list2function 9: %s", res)
29216  end
29217  func.call(ind, 0)
29218  unless vequal(res = channel2vct(99, 4), vct(0.0, 0.1, 0.1, 0.0))
29219    snd_display("edit_list2function func 9: %s?", res)
29220  end
29221  if (res = framples) != frs + 2
29222    snd_display("edit_list2function called (9): %s %s?", frs, res)
29223  end
29224  revert_sound(ind)
29225  # insert_samples with data
29226  insert_samples(0, 100, Vct.new(100, 0.1))
29227  if (res = framples) != frs + 100
29228    snd_display("edit_list2function insert_samples (100): %s %s?", frs, res)
29229  end
29230  unless proc?(func = edit_list2function)
29231    snd_display("edit_list2function 9a: %s", func)
29232  end
29233  func.call(ind, 0)
29234  if (res = framples) != frs + 200
29235    snd_display("edit_list2function insert_samples (200): %s %s?", frs, res)
29236  end
29237  unless vequal(res = channel2vct(0, 5), vct(0.1, 0.1, 0.1, 0.1, 0.1))
29238    snd_display("edit_list2function func 9a: %s?", res)
29239  end
29240  revert_sound(ind)
29241  # set_samples with data
29242  set_samples(0, 100, Vct.new(100, 0.1))
29243  if (res = framples) != frs
29244    snd_display("edit_list2function set_samples (1): %s %s?", frs, res)
29245  end
29246  unless proc?(func = edit_list2function)
29247    snd_display("edit_list2function 9b: %s", func)
29248  end
29249  func.call(ind, 0)
29250  if (res = framples) != frs
29251    snd_display("edit_list2function set_samples (2): %s %s?", frs, res)
29252  end
29253  unless vequal(res = channel2vct(0, 5), vct(0.1, 0.1, 0.1, 0.1, 0.1))
29254    snd_display("edit_list2function func 9b: %s?", res)
29255  end
29256  revert_sound(ind)
29257  # simple 1 sample set
29258  val = sample(100)
29259  set_sample(100, 0.1)
29260  if (res = framples) != frs
29261    snd_display("edit_list2function set_sample framples: %s %s?", frs, res)
29262  end
29263  if fneq(res = sample(100), 0.1)
29264    snd_display("edit_list2function set_sample val: %s %s?", val, res)
29265  end
29266  func = edit_list2function
29267  revert_sound(ind)
29268  if fneq(res = sample(100), val)
29269    snd_display("edit_list2function unset_sample val: %s %s?", val, res)
29270  end
29271  unless proc?(func)
29272    snd_display("edit_list2function 10: %s", func)
29273  end
29274  if (res = func.source) != "Proc.new {|snd, chn|  set_sample(100, 0.1000, snd, chn) }"
29275    snd_display("edit_list2function 10: %s", res)
29276  end
29277  func.call(ind, 0)
29278  unless vequal(res = channel2vct(99, 4), vct(0.0, 0.1, 0.0, 0.0))
29279    snd_display("edit_list2function func 10: %s?", res)
29280  end
29281  revert_sound(ind)
29282  pfrs = mus_sound_framples("pistol.snd")
29283  insert_sound("pistol.snd", 1000)
29284  if (res = framples) != frs + pfrs
29285    snd_display("edit_list2function insert_sound framples: %s %s?", frs, res)
29286  end
29287  unless proc?(func = edit_list2function)
29288    snd_display("edit_list2function 10a: %s", func)
29289  end
29290  if (res = func.source) != format("Proc.new {|snd, chn|  insert_sound(%s, 1000, 0, snd, chn) }", File.expand_path("pistol.snd").inspect)
29291    snd_display("edit_list2function 10a: %s", res)
29292  end
29293  revert_sound(ind)
29294  func.call(ind, 0)
29295  if (res = framples) != frs + pfrs
29296    snd_display("edit_list2function called (10a): %s %s?", frs, res)
29297  end
29298  revert_sound(ind)
29299  pfrs = mus_sound_framples("pistol.snd")
29300  insert_samples(1000, pfrs, "pistol.snd")
29301  if (res = framples) != frs + pfrs
29302    snd_display("edit_list2function insert_samples framples: %s %s?", frs, res)
29303  end
29304  unless proc?(func = edit_list2function)
29305    snd_display("edit_list2function 11: %s", func)
29306  end
29307  if (res = func.source) != format("Proc.new {|snd, chn|  insert_samples(1000, %s, %s, snd, chn) }",
29308                                   mus_sound_samples("pistol.snd"),
29309                                   File.expand_path("pistol.snd").inspect)
29310    snd_display("edit_list2function 11: %s", res)
29311  end
29312  revert_sound(ind)
29313  func.call(ind, 0)
29314  if (res = framples) != frs + pfrs
29315    snd_display("edit_list2function called (11): %s %s?", frs, res)
29316  end
29317  revert_sound(ind)
29318  smooth_channel(1000, 100)
29319  val = sample(1050)
29320  unless proc?(func = edit_list2function)
29321    snd_display("edit_list2function 12: %s", func)
29322  end
29323  if (res = func.source) != "Proc.new {|snd, chn|  smooth_channel(1000, 100, snd, chn) }"
29324    snd_display("edit_list2function 12: %s", res)
29325  end
29326  revert_sound(ind)
29327  func.call(ind, 0)
29328  if fneq(res = sample(1050), val)
29329    snd_display("edit_list2function called (12): %s %s?", res, val)
29330  end
29331  revert_sound(ind)
29332  smooth_channel(1000, 100)
29333  unless proc?(func = edit_list2function)
29334    snd_display("edit_list2function 12a: %s", func)
29335  end
29336  if (res = func.source) != "Proc.new {|snd, chn|  smooth_channel(1000, 100, snd, chn) }"
29337    snd_display("edit_list2function 12a: %s", res)
29338  end
29339  revert_sound(ind)
29340  # selection stuff
29341  make_selection(1000, 11000)
29342  scale_selection_by(2.0)
29343  unless proc?(func = edit_list2function)
29344    snd_display("edit_list2function 13: %s", func)
29345  end
29346  if (res = func.source) != "Proc.new {|snd, chn|  scale_channel(2.000, 1000, 10001, snd, chn) }"
29347    snd_display("edit_list2function 13: %s", res)
29348  end
29349  revert_sound(ind)
29350  func.call(ind, 0)
29351  snd_test_neq(maxamp(), 0.269, "edit_list2function called (13)")
29352  revert_sound(ind)
29353  scale_selection_to(1.0)
29354  unless proc?(func = edit_list2function)
29355    snd_display("edit_list2function 13:a %s", func)
29356  end
29357  if (res = func.source) != "Proc.new {|snd, chn|  normalize_channel(1.000, 1000, 10001, snd, chn) }"
29358    snd_display("edit_list2function 13a: %s", res)
29359  end
29360  revert_sound(ind)
29361  env_selection([0, 0, 1, 1, 2, 0])
29362  snd_test_neq(sample(4000), 0.0173, "edit_list2function 14 samp")
29363  unless proc?(func = edit_list2function)
29364    snd_display("edit_list2function 14: %s", func)
29365  end
29366  if (res = func.source) != "Proc.new {|snd, chn|  env_channel(make_env([0.000, 0.000, 1.000, 1.000, 2.000, 0.000], :base, 1.0000, :end, 10000), 1000, 10001, snd, chn) }"
29367    snd_display("edit_list2function 14: %s", res)
29368  end
29369  revert_sound(ind)
29370  func.call(ind, 0)
29371  snd_test_neq(sample(4000), 0.0173, "edit_list2function called (14)")
29372  revert_sound(ind)
29373  make_selection(1000, 1100)
29374  smooth_selection
29375  val = sample(1050)
29376  unless proc?(func = edit_list2function)
29377    snd_display("edit_list2function 14a: %s", func)
29378  end
29379  if (res = func.source) != "Proc.new {|snd, chn|  smooth_channel(1000, 101, snd, chn) }"
29380    snd_display("edit_list2function 14a: %s", res)
29381  end
29382  revert_sound(ind)
29383  func.call(ind, 0)
29384  if fneq(res = sample(1050), val)
29385    snd_display("edit_list2function called (14a): %s?", res)
29386  end
29387  revert_sound(ind)
29388  reverse_selection
29389  unless proc?(func = edit_list2function)
29390    snd_display("edit_list2function 14b: %s", func)
29391  end
29392  if (res = func.source) != "Proc.new {|snd, chn|  reverse_channel(1000, 101, snd, chn) }"
29393    snd_display("edit_list2function 14b: %s", res)
29394  end
29395  revert_sound(ind)
29396  func.call(ind, 0)
29397  revert_sound(ind)
29398  delete_selection
29399  unless proc?(func = edit_list2function)
29400    snd_display("edit_list2function 14c: %s", func)
29401  end
29402  if (res = func.source) != "Proc.new {|snd, chn|  delete_samples(1000, 101, snd, chn) }"
29403    snd_display("edit_list2function 14c: %s", res)
29404  end
29405  revert_sound(ind)
29406  func.call(ind, 0)
29407  revert_sound(ind)
29408  # simple reapply
29409  env_channel([0, 0, 1, 1, 2, 0])
29410  func = edit_list2function
29411  close_sound(ind)
29412  ind = new_sound("tmp.snd", 1, 22050, Mus_bfloat, Mus_next,
29413                  :size, 20, :comment, false)
29414  map_channel(lambda do |y| 1.0 end)
29415  func.call(ind, 0)
29416  unless vequal(res = channel2vct,
29417                vct(0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,
29418                    1.0, 0.889, 0.778, 0.667, 0.556, 0.444, 0.333, 0.222, 0.111, 0.0))
29419    snd_display("edit_list2function env reapply: %s?", res)
29420  end
29421  close_sound(ind)
29422  ind = open_sound("oboe.snd")
29423  # insert-region
29424  reg = make_region(1000, 1100)
29425  insert_region(reg, 2000)
29426  val = sample(2050)
29427  unless proc?(func = edit_list2function)
29428    snd_display("edit_list2function 16: %s", func)
29429  end
29430  if (res = func.source) != format("Proc.new {|snd, chn|  insert_region(integer2region(%s), 2000, snd, chn) }", region2integer(reg))
29431    snd_display("edit_list2function 16: %s", res)
29432  end
29433  revert_sound(ind)
29434  func.call(ind, 0)
29435  if fneq(res = sample(2050), val)
29436    snd_display("edit_list2function called (16): %s?", res)
29437  end
29438  revert_sound(ind)
29439  # reverse
29440  reverse_channel
29441  val = sample(2000)
29442  unless proc?(func = edit_list2function)
29443    snd_display("edit_list2function 17: %s", func)
29444  end
29445  if (res = func.source) != "Proc.new {|snd, chn|  reverse_channel(0, false, snd, chn) }"
29446    snd_display("edit_list2function 17: %s", res)
29447  end
29448  if fneq(val, -0.002)
29449    snd_display("edit_list2function 17 val: %s?", val)
29450  end
29451  revert_sound(ind)
29452  func.call(ind, 0)
29453  if fneq(val, -0.002)
29454    snd_display("edit_list2function 17 re-val: %s?", val)
29455  end
29456  revert_sound(ind)
29457  reverse_channel
29458  val = sample(2000)
29459  unless proc?(func = edit_list2function)
29460    snd_display("edit_list2function 17a: %s", func)
29461  end
29462  if (res = func.source) != "Proc.new {|snd, chn|  reverse_channel(0, false, snd, chn) }"
29463    snd_display("edit_list2function 17a: %s", res)
29464  end
29465  if fneq(val, -0.002)
29466    snd_display("edit_list2function 17a val: %s?", val)
29467  end
29468  revert_sound(ind)
29469  reverse_channel(1000, 500)
29470  unless proc?(func = edit_list2function)
29471    snd_display("edit_list2function 17b: %s", func)
29472  end
29473  if (res = func.source) != "Proc.new {|snd, chn|  reverse_channel(1000, 500, snd, chn) }"
29474    snd_display("edit_list2function 17b: %s", res)
29475  end
29476  revert_sound(ind)
29477  # src
29478  src_sound(2.0)
29479  if (framples - 25415).abs > 2
29480    snd_display("edit_list2function 18 len: %s?", framples)
29481  end
29482  unless proc?(func = edit_list2function)
29483    snd_display("edit_list2function 18: %s", func)
29484  end
29485  if (res = func.source) != "Proc.new {|snd, chn|  src_channel(2.0000, 0, false, snd, chn) }"
29486    snd_display("edit_list2function 18: %s", res)
29487  end
29488  revert_sound(ind)
29489  func.call(ind, 0)
29490  if (framples - 25415).abs > 2
29491    snd_display("edit_list2function 18 re-len: %s?", framples)
29492  end
29493  revert_sound(ind)
29494  src_channel(2.0, 1000, 500)
29495  frs = framples
29496  unless proc?(func = edit_list2function)
29497    snd_display("edit_list2function 18a: %s", func)
29498  end
29499  if (res = func.source) != "Proc.new {|snd, chn|  src_channel(2.0000, 1000, 500, snd, chn) }"
29500    snd_display("edit_list2function 18a: %s", res)
29501  end
29502  revert_sound(ind)
29503  func.call(ind, 0)
29504  if framples != frs
29505    snd_display("edit_list2function 18a re-len: %s?", framples)
29506  end
29507  revert_sound(ind)
29508  src_sound([0, 1, 1, 2, 2, 1])
29509  frs = framples
29510  unless proc?(func = edit_list2function)
29511    snd_display("edit_list2function 18b: %s", func)
29512  end
29513  if (res = func.source) != "Proc.new {|snd, chn|  src_channel([0.000, 1.000, 1.000, 2.000, 2.000, 1.000], 0, false, snd, chn) }"
29514    snd_display("edit_list2function 18b: %s", res)
29515  end
29516  revert_sound(ind)
29517  func.call(ind, 0)
29518  if framples != frs
29519    snd_display("edit_list2function 18b re-len: %s?", framples)
29520  end
29521  revert_sound(ind)
29522  src_channel([0, 1, 1, 2], 1000, 500)
29523  frs = framples
29524  unless proc?(func = edit_list2function)
29525    snd_display("edit_list2function 18c: %s", func)
29526  end
29527  if (res = func.source) != "Proc.new {|snd, chn|  src_channel([0.000, 1.000, 1.000, 2.000], 1000, 500, snd, chn) }"
29528    snd_display("edit_list2function 18c: %s", res)
29529  end
29530  revert_sound(ind)
29531  func.call(ind, 0)
29532  if framples != frs
29533    snd_display("edit_list2function 18c re-len: %s?", framples)
29534  end
29535  revert_sound(ind)
29536  # filter-channel
29537  filter_channel([0, 1, 1, 0], 10)
29538  mx = maxamp
29539  unless proc?(func = edit_list2function)
29540    snd_display("edit_list2function 19: %s", func)
29541  end
29542  if (res = func.source) != "Proc.new {|snd, chn|  filter_channel([0.000, 1.000, 1.000, 0.000], 10, 0, false, snd, chn) }"
29543    snd_display("edit_list2function 19: %s", res)
29544  end
29545  revert_sound(ind)
29546  func.call(ind, 0)
29547  if fneq(res = maxamp, mx)
29548    snd_display("edit_list2function 19 re-filter: %s %s?", mx, res)
29549  end
29550  revert_sound(ind)
29551  [[lambda { insert_vct(vct(1.0, 0.5), 0, 2) },
29552    "Proc.new {|snd, chn|  insert_vct(vct(1.000, 0.500), 0, 2, snd, chn) }"],
29553   [lambda { clm_channel_test },
29554    "Proc.new {|snd, chn|  clm_channel_test(snd, chn) }"],
29555   # examp.rb
29556   [lambda { fft_edit(1000, 3000) },
29557    "Proc.new {|snd, chn|  fft_edit(1000, 3000, snd, chn) }"],
29558   [lambda { fft_squelch(0.01) },
29559    "Proc.new {|snd, chn|  fft_squelch(0.01, snd, chn) }"],
29560   [lambda { fft_cancel(1000, 3000) },
29561    "Proc.new {|snd, chn|  fft_cancel(1000, 3000, snd, chn) }"],
29562   [lambda { squelch_vowels },
29563    "Proc.new {|snd, chn|  squelch_vowels(snd, chn) }"],
29564   [lambda { fft_env_edit([0, 0, 1, 1, 2, 0]) },
29565    "Proc.new {|snd, chn|  fft_env_edit([0, 0, 1, 1, 2, 0], snd, chn) }"],
29566   [lambda { fft_env_interp([0, 0, 1, 1, 2, 0], [0, 1, 1, 0, 2, 0], [0, 0, 1, 1]) },
29567    "Proc.new {|snd, chn|  fft_env_interp([0, 0, 1, 1, 2, 0], [0, 1, 1, 0, 2, 0], [0, 0, 1, 1], snd, chn) }"],
29568   [lambda { hello_dentist(10.0, 0.1) },
29569    "Proc.new {|snd, chn|  hello_dentist(10.0, 0.1, snd, chn) }"],
29570   [lambda { fp(1.0, 0.3, 20.0) },
29571    "Proc.new {|snd, chn|  fp(1.0, 0.3, 20.0, snd, chn) }"],
29572   [lambda { expsnd([0, 1, 1, 2]) },
29573    "Proc.new {|snd, chn|  expsnd([0, 1, 1, 2], snd, chn) }"],
29574   [lambda { voiced2unvoiced(1.0, 256, 2.0, 2.0) },
29575    "Proc.new {|snd, chn|  voiced2unvoiced(1.0, 256, 2.0, 2.0, snd, chn) }"],
29576   [lambda { env_sound_interp([0, 0, 1, 1, 2, 0], 2.0) },
29577    "Proc.new {|snd, chn|  env_sound_interp([0, 0, 1, 1, 2, 0], 2.0, snd, chn) }"],
29578   [lambda { add_notes([["1a.snd"], ["pistol.snd", 1.0, 2.0]]) },
29579    "Proc.new {|snd, chn|  add_notes([[\"1a.snd\"], [\"pistol.snd\", 1.0, 2.0]], snd, chn) }"],
29580   [lambda { filtered_env([0, 0, 1, 1, 2, 0]) },
29581    "Proc.new {|snd, chn|  filtered_env([0, 0, 1, 1, 2, 0], snd, chn) }"],
29582   [lambda { reverse_by_blocks(0.1) },
29583    "Proc.new {|snd, chn|  reverse_by_blocks(0.1, snd, chn) }"],
29584   [lambda { reverse_within_blocks(0.1) },
29585    "Proc.new {|snd, chn|  reverse_within_blocks(0.1, snd, chn) }"],
29586   # extensions.rb
29587   [lambda { mix_channel("1a.snd", 1200) },
29588    "Proc.new {|snd, chn|  mix_channel(\"1a.snd\", 1200, false, snd, chn) }"],
29589   [lambda { insert_channel("1a.snd", 1200) },
29590    "Proc.new {|snd, chn|  insert_channel(\"1a.snd\", 1200, false, snd, chn) }"],
29591   [lambda { sine_ramp(0.5, 0.9) },
29592    "Proc.new {|snd, chn|  sine_ramp(0.5, 0.9, 0, false, snd, chn) }"],
29593   [lambda { sine_env_channel([0, 0, 1, 1, 2, -0.5, 3, 1]) },
29594    "Proc.new {|snd, chn|  sine_env_channel([0, 0, 1, 1, 2, -0.5, 3, 1], 0, false, snd, chn) }"],
29595   [lambda { blackman4_ramp(0.0, 1.0) },
29596    "Proc.new {|snd, chn|  blackman4_ramp(0.0, 1.0, 0, false, snd, chn) }"],
29597   [lambda { blackman4_env_channel([0, 0, 1, 1, 2, -0.5, 3, 1]) },
29598    "Proc.new {|snd, chn|  blackman4_env_channel([0, 0, 1, 1, 2, -0.5, 3, 1], 0, false, snd, chn) }"],
29599   [lambda { ramp_squared(0.2, 0.8, true) },
29600    "Proc.new {|snd, chn|  ramp_squared(0.2, 0.8, true, 0, false, snd, chn) }"],
29601   [lambda { env_squared_channel([0, 0, 1, 1], true) },
29602    "Proc.new {|snd, chn|  env_squared_channel([0, 0, 1, 1], true, 0, false, snd, chn) }"],
29603   [lambda { ramp_expt(0.2, 0.8, 32.0, true) },
29604    "Proc.new {|snd, chn|  ramp_expt(0.2, 0.8, 32.0, true, 0, false, snd, chn) }"],
29605   [lambda { env_expt_channel([0, 0, 1, 1], 32.0, true) },
29606    "Proc.new {|snd, chn|  env_expt_channel([0, 0, 1, 1], 32.0, true, 0, false, snd, chn) }"],
29607   [lambda { offset_channel(0.1) },
29608    "Proc.new {|snd, chn|  offset_channel(0.1, 0, false, snd, chn) }"],
29609   [lambda { dither_channel(0.1) },
29610    "Proc.new {|snd, chn|  dither_channel(0.1, 0, false, snd, chn) }"],
29611   [lambda { contrast_channel(0.1) },
29612    "Proc.new {|snd, chn|  contrast_channel(0.1, 0, false, snd, chn) }"],
29613   # dsp.rb
29614   [lambda { ssb_bank(550, 600, 10) },
29615    "Proc.new {|snd, chn|  ssb_bank(550, 600, 10, 40, 50.0, 0, false, snd, chn) }"],
29616   [lambda { ssb_bank_env(550, 660, [0, 1, 1, 2], 10) },
29617    "Proc.new {|snd, chn|  ssb_bank_env(550, 660, [0, 1, 1, 2], 10, 40, 50.0, 0, false, snd, chn) }"],
29618   [lambda { down_oct(1) },
29619    "Proc.new {|snd, chn|  down_oct(1, snd, chn) }"],
29620   [lambda { freqdiv(8) },
29621    "Proc.new {|snd, chn|  freqdiv(8, snd, chn) }"],
29622   [lambda { adsat(8) },
29623    "Proc.new {|snd, chn|  adsat(8, false, false, snd, chn) }"],
29624   [lambda { spike },
29625    "Proc.new {|snd, chn|  spike(snd, chn) }"],
29626   [lambda { zero_phase },
29627    "Proc.new {|snd, chn|  zero_phase(snd, chn) }"],
29628   [lambda { rotate_phase(lambda { |x| random(PI) })  },
29629    format("Proc.new {|snd, chn|  rotate_phase(Proc.new {|val_r| rotate_phase_%s(val_r) }, snd, chn) }", edit_list_proc_counter + 1)],
29630   [lambda { brighten_slightly(0.5) },
29631    "Proc.new {|snd, chn|  brighten_slightly(0.5, snd, chn) }"],
29632   [lambda { shift_channel_pitch(100) },
29633    "Proc.new {|snd, chn|  shift_channel_pitch(100, 40, 0, false, snd, chn) }"],
29634   [lambda { channel_polynomial(vct(0, 0.5)) },
29635    "Proc.new {|snd, chn|  channel_polynomial(vct(0.000, 0.500), snd, chn) }"],
29636   [lambda { spectral_polynomial(vct(0, 0.5)) },
29637    "Proc.new {|snd, chn|  spectral_polynomial(vct(0.000, 0.500), snd, chn) }"],
29638   [lambda { notch_channel([60.0, 120.0, 240.0], false, false, false) },
29639    "Proc.new {|snd, chn|  notch_channel([60.0, 120.0, 240.0], false, false, false, snd, chn) }"],
29640   # effects.rb
29641   [lambda { effects_squelch_channel(0.1, 128) },
29642    "Proc.new {|snd, chn|  effects_squelch_channel(0.1, 128, snd, chn) }"],
29643   [lambda { effects_echo(false, 0.5, 0.1, 0, false) },
29644    "Proc.new {|snd, chn|  effects_echo(false, 0.5, 0.1, 0, false, snd, chn) }"],
29645   [lambda { effects_flecho_1(0.5, 0.1, false, 0, false) },
29646    "Proc.new {|snd, chn|  effects_flecho_1(0.5, 0.1, false, 0, false, snd, chn) }"],
29647   [lambda { effects_zecho_1(0.75, 0.75, 6.0, 10.0, false, 0, false) },
29648    "Proc.new {|snd, chn|  effects_zecho_1(0.75, 0.75, 6.0, 10.0, false, 0, false, snd, chn) }"],
29649   #[lambda { effects_comb_filter(0.1, 50, 0, false) },
29650   #"Proc.new {|snd, chn|  effects_comb_filter(0.1, 50, 0, false, snd, chn) }"],
29651   [lambda { effects_moog(10000, 0.5, 0, false) },
29652    "Proc.new {|snd, chn|  effects_moog(10000, 0.5, 0, false, snd, chn) }"],
29653   [lambda { effects_remove_dc },
29654    "Proc.new {|snd, chn|  effects_remove_dc(snd, chn) }"],
29655   [lambda { effects_compand },
29656    "Proc.new {|snd, chn|  effects_compand(snd, chn) }"],
29657   [lambda { effects_am(100.0, false) },
29658    "Proc.new {|snd, chn|  effects_am(100.0, false, 0, false, snd, chn) }"],
29659   [lambda { effects_rm(100.0, false) },
29660    "Proc.new {|snd, chn|  effects_rm(100.0, false, 0, false, snd, chn) }"],
29661   [lambda { effects_bbp(1000.0, 100.0, 0, false) },
29662    "Proc.new {|snd, chn|  effects_bbp(1000.0, 100.0, 0, false, snd, chn) }"],
29663   [lambda { effects_bbr(1000.0, 100.0, 0, false) },
29664    "Proc.new {|snd, chn|  effects_bbr(1000.0, 100.0, 0, false, snd, chn) }"],
29665   [lambda { effects_bhp(1000.0, 0, false) },
29666    "Proc.new {|snd, chn|  effects_bhp(1000.0, 0, false, snd, chn) }"],
29667   [lambda { effects_blp(1000.0, 0, false) },
29668    "Proc.new {|snd, chn|  effects_blp(1000.0, 0, false, snd, chn) }"],
29669   [lambda { effects_hello_dentist(50.0, 0.5, 0, false) },
29670    "Proc.new {|snd, chn|  effects_hello_dentist(50.0, 0.5, 0, false, snd, chn) }"],
29671   [lambda { effects_fp(1.0, 0.3, 20.0, 0, false) },
29672    "Proc.new {|snd, chn|  effects_fp(1.0, 0.3, 20.0, 0, false, snd, chn) }"],
29673   [lambda { effects_flange(5.0, 2.0, 0.001, 0, false) },
29674    "Proc.new {|snd, chn|  effects_flange(5.0, 2.0, 0.001, 0, false, snd, chn) }"],
29675   [lambda { effects_jc_reverb_1(0.1, 0, false) },
29676    "Proc.new {|snd, chn|  effects_jc_reverb_1(0.1, 0, false, snd, chn) }"]
29677  ].each_with_index do |args, i|
29678    func, descr = args
29679    func.call
29680    unless proc?(func = edit_list2function)
29681      snd_display("edit_list2function proc 20[%s]: %s", i, func.inspect)
29682    end
29683    if func.source != descr
29684      snd_display("edit_list2function source 20[%s]: %s", i, func.source)
29685    end
29686    revert_sound(ind)
29687    func.call(ind, 0)
29688    revert_sound(ind)
29689  end
29690  close_sound(ind)
29691end
29692
29693def test_19_03
29694  #
29695  # apply controls edit lists
29696  #
29697  ind = open_sound("oboe.snd")
29698  original_maxamp = maxamp
29699  reset_controls
29700  controls2channel([2.0])
29701  if fneq(res = amp_control(ind), 1.0)
29702    snd_display("controls2channel amp: %s?", res)
29703  end
29704  if fneq(res = maxamp, 2 * original_maxamp)
29705    snd_display("controls2channel maxamp: %s?", res)
29706  end
29707  func = edit_list2function
29708  if (res = func.source) != "Proc.new {|snd, chn|  scale_channel(2.000, 0, false, snd, chn) }"
29709    snd_display("edit_list2function controls2channel 1: %s", res)
29710  end
29711  func.call(ind, 0)
29712  revert_sound(ind)
29713  #
29714  controls2channel([false, 2.0])
29715  if fneq(res = channel2vct(22000, 22100).peak, 0.0479)
29716    snd_display("dp->end screwed up again!?!: %s?", res)
29717  end
29718  func = edit_list2function
29719  if (res = func.source) != "Proc.new {|snd, chn|  controls2channel([false, 2.0], 0, false, snd, chn) }"
29720    snd_display("edit_list2function controls2channel 2: %s", res)
29721  end
29722  revert_sound(ind)
29723  func.call(ind, 0)
29724  revert_sound(ind)
29725  snd_test_neq(speed_control(ind), 1.0, "controls2channel speed")
29726  #
29727  controls2channel([false, false, [0.5]])
29728  func = edit_list2function
29729  if (res = func.source) != "Proc.new {|snd, chn|  controls2channel([false, false, [0.5]], 0, false, snd, chn) }"
29730    snd_display("edit_list2function controls2channel 3: %s", res)
29731  end
29732  revert_sound(ind)
29733  func.call(ind, 0)
29734  revert_sound(ind)
29735  if fneq(res = contrast_control(ind), 0.0)
29736    snd_display("controls2channel contrast: %s?", res)
29737  end
29738  #
29739  controls2channel([false, false, [0.5, 2.0]])
29740  func = edit_list2function
29741  if (res = func.source) != "Proc.new {|snd, chn|  controls2channel([false, false, [0.5, 2.0]], 0, false, snd, chn) }"
29742    snd_display("edit_list2function controls2channel 3a: %s", res)
29743  end
29744  revert_sound(ind)
29745  func.call(ind, 0)
29746  revert_sound(ind)
29747  if fneq(res = contrast_control(ind), 0.0)
29748    snd_display("controls2channel contrast 3a: %s?", res)
29749  end
29750  #
29751  controls2channel([false, false, false, [0.5]])
29752  func = edit_list2function
29753  if (res = func.source) != "Proc.new {|snd, chn|  controls2channel([false, false, false, [0.5]], 0, false, snd, chn) }"
29754    snd_display("edit_list2function controls2channel 4: %s", res)
29755  end
29756  revert_sound(ind)
29757  func.call(ind, 0)
29758  revert_sound(ind)
29759  if fneq(res = expand_control(ind), 1.0)
29760    snd_display("controls2channel expand: %s?", res)
29761  end
29762  #
29763  controls2channel([false, false, false, [0.5, 0.1, 0.2, 0.06, 0.0]])
29764  func = edit_list2function
29765  if (res = func.source) != "Proc.new {|snd, chn|  controls2channel([false, false, false, [0.5, 0.1, 0.2, 0.06, 0.0]], 0, false, snd, chn) }"
29766    snd_display("edit_list2function controls2channel 4a: %s", res)
29767  end
29768  revert_sound(ind)
29769  func.call(ind, 0)
29770  revert_sound(ind)
29771  if fneq(res = expand_control(ind), 1.0)
29772    snd_display("controls2channel expand 4a: %s?", res)
29773  end
29774  #
29775  controls2channel([false, false, false, false, [0.1]])
29776  func = edit_list2function
29777  if (res = func.source) != "Proc.new {|snd, chn|  controls2channel([false, false, false, false, [0.1]], 0, false, snd, chn) }"
29778    snd_display("edit_list2function controls2channel 5: %s", res)
29779  end
29780  revert_sound(ind)
29781  func.call(ind, 0)
29782  revert_sound(ind)
29783  if fneq(res = reverb_control_scale(ind), 0.0)
29784    snd_display("controls2channel reverb: %s?", res)
29785  end
29786  #
29787  controls2channel([false, false, false, false, [0.1, 1.2, 0.9, 0.9, 2.0]])
29788  func = edit_list2function
29789  if (res = func.source) != "Proc.new {|snd, chn|  controls2channel([false, false, false, false, [0.1, 1.2, 0.9, 0.9, 2.0]], 0, false, snd, chn) }"
29790    snd_display("edit_list2function controls2channel 5a: %s", res)
29791  end
29792  revert_sound(ind)
29793  func.call(ind, 0)
29794  revert_sound(ind)
29795  if fneq(res = reverb_control_scale(ind), 0.0)
29796    snd_display("controls2channel reverb 5a: %s?", res)
29797  end
29798  #
29799  order = filter_control_order(ind)
29800  controls2channel([false, false, false, false, false, [10, [0, 0, 1, 1]]])
29801  func = edit_list2function
29802  if (res = func.source) != "Proc.new {|snd, chn|  controls2channel([false, false, false, false, false, [10, [0, 0, 1, 1]]], 0, false, snd, chn) }"
29803    snd_display("edit_list2function controls2channel 6: %s", res)
29804  end
29805  revert_sound(ind)
29806  func.call(ind, 0)
29807  revert_sound(ind)
29808  if (res = filter_control_order(ind)) != order
29809    snd_display("controls2channel filter: %s?", res)
29810  end
29811  #
29812  # mix stuff
29813  #
29814  id = make_v_mix(ind, 0)
29815  # mix-position
29816  set_mix_position(id, 200)
29817  if (res = mix_position(id)) != 200
29818    snd_display("edit_list2function mix off to a bad start: %s?", res)
29819  end
29820  unless proc?(func = edit_list2function)
29821    snd_display("edit_list2function mix 1: %s?", func)
29822  end
29823  if (res = func.source) != format("Proc.new {|snd, chn| _mix_%s = false;  _mix_%s = mix_vct(vct(0.1, 0.2, 0.3), 100, snd, chn); set_mix_position(_mix_%s, 200) }", mix2integer(id), mix2integer(id), mix2integer(id))
29824    snd_display("edit_list2function mix 1: %s", res)
29825  end
29826  revert_sound(ind)
29827  func.call(ind, 0)
29828  res1 = mixes(ind, 0)
29829  res2 = if res1.nil?
29830           false
29831         else
29832           res1.detect do |m| mix?(m) and mix_position(m) == 200 end
29833         end
29834  unless mix?(res2)
29835    snd_display("edit_list2function mix 1 repos: %s %s?", res1, res2)
29836  end
29837  revert_sound(ind)
29838  # mix-amp
29839  id = make_v_mix(ind, 0)
29840  set_mix_amp(id, 0.5)
29841  unless proc?(func = edit_list2function)
29842    snd_display("edit_list2function mix 4: %s?", func)
29843  end
29844  if (res = func.source) != format("Proc.new {|snd, chn| _mix_%s = false;  _mix_%s = mix_vct(vct(0.1, 0.2, 0.3), 100, snd, chn); set_mix_amp(_mix_%s, 0.5000) }", mix2integer(id), mix2integer(id), mix2integer(id))
29845    snd_display("edit_list2function mix 4: %s", res)
29846  end
29847  revert_sound(ind)
29848  func.call(ind, 0)
29849  revert_sound(ind)
29850  # mix-speed
29851  id = make_v_mix(ind, 0)
29852  set_mix_speed(id, 0.5)
29853  unless proc?(func = edit_list2function)
29854    snd_display("edit_list2function mix 5: %s?", func)
29855  end
29856  if (res = func.source) != format("Proc.new {|snd, chn| _mix_%s = false;  _mix_%s = mix_vct(vct(0.1, 0.2, 0.3), 100, snd, chn); set_mix_speed(_mix_%s, 0.5000) }", mix2integer(id), mix2integer(id), mix2integer(id))
29857    snd_display("edit_list2function mix 5: %s", res)
29858  end
29859  revert_sound(ind)
29860  func.call(ind, 0)
29861  revert_sound(ind)
29862  close_sound(ind)
29863  #
29864  ind = open_sound("2.snd")
29865  src_sound(3.0, 1.0, ind)
29866  save_sound_as("test.snd")
29867  close_sound(ind)
29868  ind = open_sound("test.snd")
29869  if (res = chans(ind)) != 2
29870    snd_display("src_sound/save_sound_as: %s chans?", res)
29871  end
29872  close_sound(ind)
29873  #
29874  ind = open_sound("oboe.snd")
29875  if (res = Snd.catch do save_sound_as("test.snd", :edit_position, 1) end).first != :no_such_edit
29876    snd_display("save_sound_as bad edpos: %s", res.inspect)
29877  end
29878  if (res = Snd.catch do
29879        save_sound_as("test.snd", :channel, 1, :edit_position, 1)
29880      end).first != :no_such_channel
29881    snd_display("save_sound_as bad chan: %s", res.inspect)
29882  end
29883  save_sound_as("test.snd", :comment, "this is a comment")
29884  close_sound(ind)
29885  ind = open_sound("test.snd")
29886  if (res = comment(ind)) != "this is a comment"
29887    snd_display("save_sound_as with comment: %s?", res)
29888  end
29889  close_sound(true)
29890end
29891
29892def test_19
29893  if $with_test_gui # load(save_state_file) -> set_transform_size(0)
29894    test_19_00
29895    test_19_01
29896  end
29897  test_19_02
29898  test_19_03
29899  mus_sound_prune
29900end
29901
29902# ---------------- test 20: transforms ----------------
29903
29904def bes_test(func_sym)
29905  [0.0, 0.5, 1.0, 2.0, 20.0].each do |x|
29906    snd_test_neq(snd_func(func_sym, x), snd_func("#{func_sym.to_s}_1", x), "%s(%1.1f)", func_sym, x)
29907  end
29908  10.times do
29909    x = random(100.0)
29910    snd_test_neq(snd_func(func_sym, x), snd_func("#{func_sym.to_s}_1", x), "%s(%1.1f)", func_sym, x)
29911  end
29912end
29913
29914def bes_j0_1(x)
29915  if x.abs < 8.0
29916    y = x * x
29917    ans1 = 57568490574.0 +
29918           y * (-13362590354.0 + \
29919                y * (651619640.7 + \
29920                     y * (-11214424.18 + \
29921                          y * (77392.33017 + \
29922                               y * -184.9052456))))
29923    ans2 = 57568490411.0 +
29924           y * (1029532985.0 + \
29925                y * (9494680.718 + \
29926                     y * (59272.64853 + \
29927                          y * (267.8532712 + y))))
29928    ans1 / ans2
29929  else
29930    ax = x.abs
29931    z = 8.0 / ax
29932    y = z * z
29933    xx = ax - 0.785398164
29934    ans1 = 1.0 +
29935           y * (-0.1098628627e-2 + \
29936                y * (0.2734510407e-4 + \
29937                     y * (-0.2073370639e-5 + \
29938                          y * 0.2093887211e-6)))
29939    ans2 = -0.1562499995e-1 +
29940           y * (0.1430488765e-3 + \
29941                y * (-0.6911147651e-5 + \
29942                     y * (0.7621095161e-6 + \
29943                          y * -0.934945152e-7)))
29944    sqrt(0.636619772 / ax) * (cos(xx) * ans1 - sin(xx) * z * ans2)
29945  end
29946end
29947
29948def bes_j1_1(x)
29949  if x.abs < 8.0
29950    y = x * x
29951    ans1 = x *
29952           (72362614232.0 + \
29953            y * (-7895059235.0 + \
29954                 y * (242396853.1 + \
29955                      y * (-2972611.439 + \
29956                           y * (15704.48260 + \
29957                                y * -30.16036606)))))
29958    ans2 = 144725228442.0 +
29959           y * (2300535178.0 + \
29960                y * (18583304.74 + \
29961                     y * (99447.43394 + \
29962                          y * (376.9991397 + y))))
29963    ans1 / ans2
29964  else
29965    ax = x.abs
29966    z = 8.0 / ax
29967    y = z * z
29968    xx = ax - 2.356194491
29969    ans1 = 1.0 +
29970           y * (0.183105e-2 + \
29971                y * (-0.3516396496e-4 + \
29972                     y * (0.2457520174e-5 + \
29973                          y * -0.240337019e-6)))
29974    ans2 = 0.04687499995 +
29975           y * (-0.2002690873e-3 + \
29976                y * (0.8449199096e-5 + \
29977                     y * (-0.88228987e-6 + \
29978                          y * 0.105787412e-6)))
29979    sqrt(0.636619772 / ax) * (cos(xx) * ans1 - sin(xx) * z * ans2) * (x.zero? ? 0 : (x < 0 ? -1 : 1))
29980  end
29981end
29982
29983def bes_jn_1(nn, x)
29984  n = nn.abs
29985  besn = if n.zero?
29986           bes_j0_1(x)
29987         elsif n == 1
29988           bes_j1_1(x)
29989         elsif x.zero?
29990           0.0
29991         else
29992           iacc = 40.0
29993           ans = 0.0
29994           bigno = 1.0e10
29995           bigni = 1.0e-10
29996           tox = 2.0 / x.abs
29997           if x.abs > n
29998             bjm = bes_j0_1(x.abs)
29999             bj = bes_j1_1(x.abs)
30000             bjp = 0.0
30001             (1...n).each do |i|
30002               bjp = i * tox * bj - bjm
30003               bjm, bj = bj, bjp
30004             end
30005             ans = bj
30006           else
30007             m = 2 * ((sqrt(iacc * n) + n) / 2.0).floor
30008             jsum = 0
30009             bjm = 0.0
30010             sum = 0.0
30011             bjp = 0.0
30012             bj = 1.0
30013             m.downto(1) do |i|
30014               bjm = i * tox * bj - bjp
30015               bjp, bj = bj, bjm
30016               if bj.abs > bigno
30017                 bj *= bigni
30018                 bjp *= bigni
30019                 ans *= bigni
30020                 sum *= bigni
30021               end
30022               if jsum.nonzero?
30023                 sum += bj
30024               end
30025               jsum = 1 - jsum
30026               if i == n
30027                 ans = bjp
30028               end
30029             end
30030             sum = 2.0 * sum - bj
30031             ans = ans / sum
30032           end
30033           if x < 0 and n.odd?
30034             -ans
30035           else
30036             ans
30037           end
30038         end
30039  if nn < 0 and nn.odd?
30040    -besn
30041  else
30042    besn
30043  end
30044end
30045
30046def bes_test_jn
30047  10.times do |k|
30048    10.times do |i|
30049      x = random(100.0)
30050      snd_test_neq(bes_jn(k, x), bes_jn_1(k, x), "bes_jn(%k, %1.1f)", k, x)
30051    end
30052  end
30053end
30054
30055def bes_y0_1(x)
30056  if x < 8.0
30057    y = x * x
30058    ans1 = -2957821389.0 +
30059           y * (7062834065.0 + \
30060                y * (-512359803.6 + \
30061                     y * (10879881.29 + \
30062                          y * (-86327.92757 + \
30063                               y * 228.4622733))))
30064    ans2 = 40076544269.0 +
30065           y * (745249964.8 + \
30066                y * (7189466.438 + \
30067                     y * (47447.26470 + \
30068                          y * (226.1030244 + y))))
30069    ans1 / ans2 + 0.636619772 * bes_j0(x) * log(x)
30070  else
30071    z = 8.0 / x
30072    y = z * z
30073    xx = x - 0.785398164
30074    ans1 = 1.0 +
30075           y * (-0.1098628627e-2 + \
30076                y * (0.2734510407e-4 + \
30077                     y * (-0.2073370639e-5 + \
30078                          y * 0.2093887211e-6)))
30079    ans2 = -0.1562499995e-1 +
30080           y * (0.1430488765e-3 + \
30081                y * (-0.6911147651e-5 + \
30082                     y * (0.7621095161e-6 + \
30083                          y * -0.934945152e-7)))
30084    sqrt(0.636619772 / x) * (sin(xx) * ans1 + cos(xx) * z * ans2)
30085  end
30086end
30087
30088def bes_y1_1(x)
30089  if x < 8.0
30090    y = x * x
30091    ans1 = x *
30092           (-0.4900604943e13 + \
30093            y * (0.1275274390e13 + \
30094                 y * (-0.5153438139e11 + \
30095                      y * (0.7349264551e9 + \
30096                           y * (-0.4237922726e7 + \
30097                                y * 0.8511937935e4)))))
30098    ans2 = 0.2499580570e14 +
30099           y * (0.4244419664e12 + \
30100                y * (0.3733650367e10 + \
30101                     y * (0.2245904002e8 + \
30102                          y * (0.1020426050e6 + \
30103                               y * (0.3549632885e3 + y)))))
30104    ans1 / ans2 + 0.636619772 * (bes_j1(x) * log(x) - 1.0 / x)
30105  else
30106    z = 8.0 / x
30107    y = z * z
30108    xx = x - 2.356194491
30109    ans1 = 1.0 +
30110           y * (0.183105e-2 + \
30111                y * (-0.3516396496e-4 + \
30112                     y * (0.2457520174e-5 + \
30113                          y * -0.240337019e-6)))
30114    ans2 = 0.04687499995 +
30115           y * (-0.2002690873e-3 + \
30116                y * (0.8449199096e-5 + \
30117                     y * (-0.88228987e-6 + \
30118                          y * 0.105787412e-6)))
30119    sqrt(0.636619772 / x) * (sin(xx) * ans1 + cos(xx) * z * ans2)
30120  end
30121end
30122
30123def bes_test_y(func_sym)
30124  [0.5, 1.0, 2.0, 20.0].each do |x|
30125    snd_test_neq(snd_func(func_sym, x), snd_func("#{func_sym.to_s}_1", x), "%s(%1.1f)", func_sym, x)
30126  end
30127  10.times do
30128    x = random(100.0)
30129    snd_test_neq(snd_func(func_sym, x), snd_func("#{func_sym.to_s}_1", x), "%s(%1.1f)", func_sym, x)
30130  end
30131end
30132
30133def bes_yn_1(n, x)
30134  if n.zero?
30135    bes_y0_1(x)
30136  elsif n == 1
30137    bes_y1_1(x)
30138  else
30139    tox = 2.0 / x
30140    byp = 0.0
30141    by = bes_y1_1(x)
30142    bym = bes_y0_1(x)
30143    (1...n).each do |i|
30144      byp = i * tox * by - bym
30145      bym, by = by, byp
30146    end
30147    by
30148  end
30149end
30150
30151def bes_test_yn
30152  10.times do |k|
30153    10.times do |i|
30154      x = random(100.0)
30155      snd_test_neq(bes_yn(k, x) / bes_yn_1(k, x), 1.0, "bes_yn(%d, %1.1f)", k, x)
30156    end
30157  end
30158end
30159
30160def bes_i0_1(x)
30161  if x.abs < 3.75
30162    y = (x / 3.75) ** 2
30163    1.0 +
30164      y * (3.5156229 + \
30165           y * (3.0899424 + \
30166                y * (1.2067492 + \
30167                     y * (0.2659732 + \
30168                          y * (0.360768e-1 + \
30169                               y * 0.45813e-2)))))
30170  else
30171    ax = x.abs
30172    y = 3.75 / ax
30173    (exp(ax) / sqrt(ax)) *
30174              (0.39894228 + \
30175               y * (0.1328592e-1 + \
30176                    y * (0.225319e-2 + \
30177                         y * (-0.157565e-2 + \
30178                              y * (0.916281e-2 + \
30179                                   y * (-0.2057706e-1 + \
30180                                        y * (0.2635537e-1 + \
30181                                             y * (-0.1647633e-1 + \
30182                                                  y * 0.392377e-2))))))))
30183  end
30184end
30185
30186def bes_test_i0
30187  [0.0, 0.5, 1.0, 2.0, 0.01].each do |x|
30188    snd_test_neq(bes_i0(x), bes_i0_1(x), "bes_i0(%1.1f)", x)
30189  end
30190  10.times do
30191    x = random(1.0)
30192    snd_test_neq(bes_i0(x), bes_i0_1(x), "bes_i0(%1.1f)", x)
30193  end
30194end
30195
30196def bes_i1(x)
30197  if x.abs < 3.75
30198    y = (x / 3.75) ** 2
30199    x * (0.5 + \
30200         y * (0.87890594 + \
30201              y * (0.51498869 + \
30202                   y * (0.15084934 + \
30203                        y * (0.2658733e-1 + \
30204                             y * (0.301532e-2 + \
30205                                  y * 0.32411e-3))))))
30206  else
30207    ax = x.abs
30208    y = 3.75 / ax
30209    ans1 = 0.2282967e-1 +
30210           y * (-0.2895312e-1 + \
30211                y * (0.1787654e-1 + \
30212                     y * -0.420059e-2))
30213    ans2 = 0.39894228 +
30214           y * (-0.3988024e-1 + \
30215                y * (-0.362018e-2 + \
30216                     y * (0.163801e-2 + \
30217                          y * (-0.1031555e-1 + y * ans1))))
30218    exp(ax) / sqrt(ax) * ans2 * (x < 0 ? -1 : 1)
30219  end
30220end
30221
30222def bes_test_i1
30223  [[ 1.0,    0.565159],
30224   [ 2.0,    1.59063685],
30225   [ 5.0,   24.33564],
30226   [10.0, 2670.9883]].each do |n, x|
30227    snd_test_neq(bes_i1(n), x, "bes_i1 %1.1f", n)
30228  end
30229end
30230
30231def bes_in(n, x)
30232  if n.zero?
30233    bes_i0(x)
30234  elsif n == 1
30235    bes_i1(x)
30236  elsif x.zero?
30237    0.0
30238  else
30239    iacc = 40.0
30240    ans = 0.0
30241    bigno = 1.0e10
30242    bigni = 1.0e-10
30243    tox = 2.0 / x.abs
30244    bip = 0.0
30245    bi = 1.0
30246    bim = 0.0
30247    m = 2 * (n + sqrt(iacc * n).floor)
30248    m.downto(1) do |i|
30249      bim = bip + i * tox * bi
30250      bip, bi = bi, bim
30251      if bi.abs > bigno
30252        ans *= bigni
30253        bi *= bigni
30254        bip *= bigni
30255      end
30256      if i == n
30257        ans = bip
30258      end
30259    end
30260    if x < 0 and n.odd?
30261      ans = -ans
30262    end
30263    ans * (bes_i0(x) / bi)
30264  end
30265end
30266
30267def bes_test_in
30268  [[ 1, 0.565159,     1.5906368,  24.33564],
30269   [ 2, 0.13574767,   0.6889484,  17.505615],
30270   [ 3, 0.02216842,   0.21273995, 10.331150],
30271   [ 5, 2.71463e-4,   0.009825679, 2.157974],
30272   [10, 2.752948e-10, 3.016963e-7, 0.004580044]].each do |n, x1, x2, x5|
30273    snd_test_neq(bes_in(n, 1.0), x1, "bes_in %d 1.0", n)
30274    snd_test_neq(bes_in(n, 2.0), x2, "bes_in %d 2.0", n)
30275    snd_test_neq(bes_in(n, 5.0), x5, "bes_in %d 5.0", n)
30276  end
30277end
30278
30279def bes_k0(x)
30280  if x <= 2.0
30281    y = x * (x / 4.0)
30282    -log(x / 2.0) * bes_i0(x) + -0.57721566 +
30283                   y * (0.42278420 + \
30284                        y * (0.23069756 + \
30285                             y * (0.3488590e-1 + \
30286                                  y * (0.262698e-2 + \
30287                                       y * (0.10750e-3 + \
30288                                            y * 0.74e-5)))))
30289  else
30290    y = 2.0 / x
30291    (exp(-x) / sqrt(x)) * \
30292    (1.25331414 + \
30293     y * (-0.7832358e-1 + \
30294          y * (0.2189568e-1 + \
30295               y * (-0.1062446e-1 + \
30296                    y * (0.587872e-2 + \
30297                         y * (-0.251540e-2 + \
30298                              y * -0.53208e-3))))))
30299  end
30300end
30301
30302def bes_test_k0
30303  [[ 1.0, 0.4210244],
30304   [ 2.0, 0.1138938],
30305   [10.0, 1.7780e-5]].each do |n, x|
30306    snd_test_neq(bes_k0(n), x, "bes_k0 %1.1f", n)
30307  end
30308end
30309
30310def bes_k1(x)
30311  if x <= 2.0
30312    y = x * (x / 4.0)
30313    log(x / 2.0) * bes_i1(x) + 1.0 / x *
30314                  (1.0 + \
30315                   y * (0.15443144 + \
30316                        y * (-0.67278579 + \
30317                             y * (-0.18156897 + \
30318                                  y * (-0.1919402e-1 + \
30319                                       y * (-0.110404e-2 + \
30320                                            y * -0.4686e-4))))))
30321  else
30322    y = 2.0 / x
30323    (exp(-x) / sqrt(x)) * \
30324    (1.25331414 + \
30325     y * (0.23498619 + \
30326          y * (-0.3655620e-1 + \
30327               y * (0.1504268e-1 + \
30328                    y * (0.780353e-2 + \
30329                         y * (0.325614e-2 + \
30330                              y * -0.68245e-3))))))
30331  end
30332end
30333
30334def bes_test_k1
30335  [[ 1.0, 0.60190723],
30336   [ 2.0, 0.1398658],
30337   [10.0, 1.86487e-5]].each do |n, x|
30338    snd_test_neq(bes_k1(n), x, "bes_k1 %1.1f", n)
30339  end
30340end
30341
30342def bes_kn(n, x)
30343  if n.zero?
30344    bes_k0(x)
30345  elsif n == 1
30346    bes_k1(x)
30347  else
30348    tox = 2.0 / x
30349    bkp = 0.0
30350    bk = bes_k1(x)
30351    bkm = bes_k0(x)
30352    (1...n).each do |i|
30353      bkp = i * tox * bk + bkm
30354      bkm, bk = bk, bkp
30355    end
30356    bk
30357  end
30358end
30359
30360def bes_test_kn
30361  [[1,   0.6019072, 0.139865,  0.00404461],
30362   [2,   1.6248389, 0.2537597, 0.0053089],
30363   [3,   7.1012629, 0.6473854, 0.0082917],
30364   [5, 360.96059,   9.431049,  0.0327062]].each do |n, x1, x2, x5|
30365    snd_test_neq(bes_kn(n, 1.0), x1, "bes_kn %d 1.0", n)
30366    snd_test_neq(bes_kn(n, 2.0), x2, "bes_kn %d 2.0", n)
30367    snd_test_neq(bes_kn(n, 5.0), x5, "bes_kn %d 5.0", n)
30368  end
30369end
30370
30371def gammln(x)
30372  stp = 2.5066282746310005
30373  tmp = x + 5.5
30374  tmp1 = tmp - ((x + 0.5) * log(tmp))
30375  ser = 1.000000000190015 +
30376        76.18009172947146 / (x + 1.0) +
30377           -86.50532032941677 / (x + 2.0) +
30378               24.01409824083091 / (x + 3.0) +
30379                  -1.231739572450155 / (x + 4.0) +
30380                     0.1208650973866179e-2 / (x + 5.0) +
30381                       -0.5395239384953e-5 / (x + 6.0)
30382  log((stp * ser) / x) - tmp1
30383end
30384
30385def test_lgamma
30386  10.times do
30387    x = random(100.0)
30388    res1 = lgamma(x)
30389    res2 = gammln(x)
30390    if array?(res1)
30391      # XXX: Ruby 1.9+ returns an array
30392      res1 = res1[0]
30393    end
30394    snd_test_neq(res1, res2, "lgamma(%1.1f)", x)
30395  end
30396end
30397
30398def test_erf
30399  [[0.0, 0.0],
30400   [0.5, 0.5204998],
30401   [1.0, 0.8427007]].each do |n, x|
30402    snd_test_neq(erf(n), x, "erf(%1.1f)", n)
30403  end
30404  10.times do
30405    val = random(2.0)
30406    res1 = erf(val)
30407    res2 = erfc(val)
30408    snd_test_neq(res1 + res2, 1.0, "erf+erfc erf %1.4f erfc %1.4f)", res1, res2)
30409  end
30410end
30411
30412def inverse_haar(f)
30413  n = f.length
30414  g = Vct.new(n)
30415  s2 = sqrt(2.0)
30416  v = 1.0 / sqrt(n)
30417  f[0] *= v
30418  m = 2
30419  until m > n
30420    mh = m / 2
30421    k = 0
30422    0.step(m - 1, 2) do |j|
30423      x = f[k]
30424      y = f[mh + k] * v
30425      g[j] = x + y
30426      g[j + 1] = x - y
30427      k += 1
30428    end
30429    (m - 1).downto(0) do |i| f[i] = g[i] end
30430    v *= s2
30431    m *= 2
30432  end
30433  f
30434end
30435
30436def wavelet(data, n, isign, wf, cc)
30437  cc_size = cc.length
30438  sig = -1.0
30439  j = cc_size - 1
30440  ccr = Vct.new(cc_size)
30441  cc.each do |val|
30442    ccr[j] = val * sig
30443    j -= 1
30444    sig = -sig
30445  end
30446  if n >= 4
30447    if isign >= 0
30448      nn = n
30449      until nn < 4
30450        snd_func(wf, data, nn, isign, cc, ccr)
30451        nn /= 2
30452      end
30453    else
30454      nn = 4
30455      until nn > n
30456        snd_func(wf, data, nn, isign, cc, ccr)
30457        nn *= 2
30458      end
30459    end
30460  end
30461end
30462
30463def pwt(data, n, isign, cc, cr)
30464  data1 = Vct.new(n)
30465  n1 = n - 1
30466  ncof = cc.length
30467  nmod = ncof * n
30468  nh = (n / 2.0).floor
30469  ioff = joff = -(ncof / 2.0).floor
30470  ii = 0
30471  if isign >= 0
30472    1.step(n, 2) do |i|
30473      ni = i + nmod + ioff
30474      nj = i + nmod + joff
30475      1.upto(ncof) do |k|
30476        jf = n1 & (ni + k)
30477        jr = n1 & (nj + k)
30478        data1[ii] = data1[ii] + cc[k - 1] * data[jf]
30479        data1[ii + nh] = data1[ii + nh] + cr[k - 1] * data[jr]
30480      end
30481      ii += 1
30482    end
30483  else
30484    1.step(n, 2) do |i|
30485      ai = data[ii]
30486      ai1 = data[ii + nh]
30487      ni = i + nmod + ioff
30488      nj = i + nmod + joff
30489      1.upto(ncof) do |k|
30490        jf = n1 & (ni + k)
30491        jr = n1 & (nj + k)
30492        data1[jf] = data1[jf] + cc[k - 1] * ai
30493        data1[jr] = data1[jr] + cr[k - 1] * ai1
30494      end
30495      ii += 1
30496    end
30497  end
30498  data1.map_with_index do |val, i|
30499    data[i] = val
30500  end
30501end
30502
30503def corr(x, y, n, m)
30504  r = Vct.new(m + 1)
30505  (m + 1).times do |i|
30506    r[i] = 0.0
30507    (n - i).times do |j|
30508      r[i] = r[i] + x[j + i] * y[j]
30509    end
30510  end
30511  r
30512end
30513
30514def cross_correlate_3(rl1, rl2, fftlen)
30515  fftscale = 1.0 / fftlen
30516  im1 = Vct.new(fftlen)
30517  im2 = Vct.new(fftlen)
30518  fft(rl1, im1, 1)
30519  fft(rl2, im2, 1)
30520  tmprl = rl1.dup
30521  tmpim = im1.dup
30522  tmprl *= rl2
30523  tmpim *= im2
30524  im2 *= rl1
30525  rl2 *= im1
30526  tmprl += tmpim
30527  im2 -= rl2
30528  fft(tmprl, im2, -1).scale(fftscale)
30529end
30530
30531def automorph(a, b, c, d, snd = false, chn = false)
30532  len = framples(snd, chn)
30533  pow2 = (log(len) / log(2)).ceil
30534  fftlen = (2 ** pow2).round
30535  fftscale = 1.0 / fftlen
30536  rl = channel2vct(0, fftlen, snd, chn)
30537  im = Vct.new(fftlen)
30538  fft(rl, im, 1)
30539  rl.scale!(fftscale)
30540  im.scale!(fftscale)
30541  c1 = Complex(rl[0], im[0])
30542  val = (a * c1 + b) / (c * c1 + d)
30543  rval = val.real
30544  ival = val.imag
30545  rl[0] = rval
30546  im[0] = ival
30547  k = fftlen - 1
30548  (1..(fftlen / 2)).each do |i|
30549    c1 = Complex(rl[i], im[i])
30550    val = (a * c1 + b) / (c * c1 + d)
30551    rval = val.real
30552    ival = val.imag
30553    rl[i] = rval
30554    im[i] = ival
30555    rl[k] = rval
30556    im[k] = -ival
30557    k -= 1
30558  end
30559  fft(rl, im, -1)
30560  vct2channel(rl, 0, len, snd, chn, false, format("%s(%s, %s, %s, %s", get_func_name, a, b, c, d))
30561end
30562
30563sqrt2 = 1.41421356237309504880168872420969808
30564sqrt15 = 3.87298334620741688517927
30565$wts = {[:daub4, 0] =>
30566        vct(0.4829629131445341, 0.8365163037378079, 0.2241438680420134, -0.1294095225512604),
30567        [:daub6, 1] =>
30568        vct(0.332670552950, 0.806891509311, 0.459877502118, -0.135011020010,
30569            -0.085441273882, 0.035226291886),
30570        [:daub8, 2] =>
30571        vct(0.230377813309, 0.714846570553, 0.630880767930, -0.027983769417,
30572            -0.187034811719, 0.030841381836, 0.032883011667, -0.010597401785),
30573        [:daub10, 3] =>
30574        vct(0.160102397974, 0.603829269797, 0.724308528438, 0.138428145901,
30575            -0.242294887066, -0.032244869585, 0.077571493840, -0.006241490213,
30576            -0.012580751999, 0.003335725285),
30577        [:daub12, 4] =>
30578        vct(0.111540743350, 0.494623890398, 0.751133908021, 0.315250351709,
30579            -0.226264693965, -0.129766867567, 0.097501605587, 0.027522865530,
30580            -0.031582039317, 0.000553842201, 0.004777257511, -0.001077301085),
30581        [:daub14, 5] =>
30582        vct(0.077852054085, 0.396539319482, 0.729132090846, 0.469782287405,
30583            -0.143906003929, -0.224036184994, 0.071309219267, 0.080612609151,
30584            -0.038029936935, -0.016574541631, 0.012550998556, 0.000429577973,
30585            -0.001801640704, 0.000353713800),
30586        [:daub16, 6] =>
30587        vct(0.054415842243, 0.312871590914, 0.675630736297, 0.585354683654,
30588            -0.015829105256, -0.284015542962, 0.000472484574, 0.128747426620,
30589            -0.017369301002, -0.044088253931, 0.013981027917, 0.008746094047,
30590            -0.004870352993, -0.000391740373, 0.000675449406, -0.000117476784),
30591        [:daub18, 7] =>
30592        vct(0.038077947364, 0.243834674613, 0.604823123690, 0.657288078051,
30593            0.133197385825, -0.293273783279, -0.096840783223, 0.148540749338,
30594            0.030725681479, -0.067632829061, 0.000250947115, 0.022361662124,
30595            -0.004723204758, -0.004281503682, 0.001847646883, 0.000230385764,
30596            -0.000251963189, 0.000039347320),
30597        [:daub20, 8] =>
30598        vct(0.026670057901, 0.188176800077, 0.527201188931, 0.688459039453,
30599            0.281172343661, -0.249846424327, -0.195946274377, 0.127369340336,
30600            0.093057364604, -0.071394147166, -0.029457536822, 0.033212674059,
30601            0.003606553567, -0.010733175483, 0.001395351747, 0.001992405295,
30602            -0.000685856695, -0.000116466855, 0.000093588670, -0.000013264203),
30603        [:battle_lemarie, 9] =>
30604        vct(sqrt2 * -0.002, sqrt2 * -0.003, sqrt2 *  0.006, sqrt2 *  0.006,
30605            sqrt2 * -0.013, sqrt2 * -0.012, sqrt2 *  0.030, sqrt2 *  0.023,
30606            sqrt2 * -0.078, sqrt2 * -0.035, sqrt2 *  0.307, sqrt2 *  0.542,
30607            sqrt2 *  0.307, sqrt2 * -0.035, sqrt2 * -0.078, sqrt2 *  0.023,
30608            sqrt2 *  0.030, sqrt2 * -0.012, sqrt2 * -0.013, sqrt2 *  0.006,
30609            sqrt2 *  0.006, sqrt2 * -0.003, sqrt2 * -0.002, 0.0),
30610        [:burt_adelson, 10] =>
30611        vct(sqrt2 * (-1.0 / 20.0), sqrt2 * (5.0 / 20.0), sqrt2 * (12.0 / 20.0),
30612            sqrt2 * (5.0 / 20.0), sqrt2 * (-1.0 / 20.0), 0.0),
30613        [:beylkin, 11] =>
30614        vct(0.099305765374353, 0.424215360812961, 0.699825214056600, 0.449718251149468,
30615            -0.110927598348234, -0.264497231446384, 0.026900308803690, 0.155538731877093,
30616            -0.017520746266529, -0.088543630622924, 0.019679866044322, 0.042916387274192,
30617            -0.017460408696028, -0.014365807968852, 0.010040411844631, 0.0014842347824723,
30618            -0.002736031626258, 0.0006404853285212),
30619        [:coif2, 12] =>
30620        vct((sqrt2 * (sqrt15 - 3)) / 32.0, (sqrt2 * (1 - sqrt15)) / 32.0,
30621            (sqrt2 * (6 - 2 * sqrt15)) / 32.0, (sqrt2 * (2 * sqrt15 + 6)) / 32.0,
30622            (sqrt2 * (sqrt15 + 13)) / 32.0, (sqrt2 * (9 - sqrt15)) / 32.0),
30623        [:coif4, 13] =>
30624        vct(0.0011945726958388, -0.01284557955324, 0.024804330519353, 0.050023519962135,
30625            -0.15535722285996, -0.071638282295294, 0.57046500145033, 0.75033630585287,
30626            0.28061165190244, -0.0074103835186718, -0.014611552521451, -0.0013587990591632),
30627        [:coif6, 14] =>
30628        vct(-0.0016918510194918, -0.00348787621998426, 0.019191160680044, 0.021671094636352,
30629            -0.098507213321468, -0.056997424478478, 0.45678712217269, 0.78931940900416,
30630            0.38055713085151, -0.070438748794943, -0.056514193868065, 0.036409962612716,
30631            0.0087601307091635, -0.011194759273835, -0.0019213354141368, 0.0020413809772660,
30632            0.00044583039753204, -0.00021625727664696),
30633        [:sym2, 15] =>
30634        vct(sqrt2 * -0.125, sqrt2 *  0.25, sqrt2 *  0.75, sqrt2 *  0.25, sqrt2 * -0.125),
30635        [:sym3, 16] =>
30636        vct(sqrt2 / 8.0, (sqrt2 * 3.0) / 8.0, (sqrt2 * 3.0) / 8.0, sqrt2 / 8.0),
30637        [:sym4, 17] =>
30638        vct((sqrt2 *   3.0) / 128.0, (sqrt2 * -6.0) / 128.0, (sqrt2 * -16.0) / 128.0,
30639            (sqrt2 *  38.0) / 128.0, (sqrt2 * 90.0) / 128.0, (sqrt2 *  38.0) / 128.0,
30640            (sqrt2 * -16.0) / 128.0, (sqrt2 * -6.0) / 128.0, (sqrt2 *  3.0) / 128.0, 0.0),
30641        [:sym5, 18] =>
30642        vct((sqrt2 *  3.0) / 64.0, (sqrt2 * -9.0) / 64.0, (sqrt2 * -7.0) / 64.0,
30643            (sqrt2 * 45.0) / 64.0, (sqrt2 * 45.0) / 64.0, (sqrt2 * -7.0) / 64.0,
30644            (sqrt2 * -9.0) / 64.0, (sqrt2 *  3.0) / 64.0),
30645        [:sym6, 19] =>
30646        vct((sqrt2 *   -35.0) / 16384.0, (sqrt2 *  -105.0) / 16384.0,
30647            (sqrt2 *  -195.0) / 16384.0, (sqrt2 *   865.0) / 16384.0,
30648            (sqrt2 *   363.0) / 16384.0, (sqrt2 * -3489.0) / 16384.0,
30649            (sqrt2 *  -307.0) / 16384.0, (sqrt2 * 11025.0) / 16384.0,
30650            (sqrt2 * 11025.0) / 16384.0, (sqrt2 *  -307.0) / 16384.0,
30651            (sqrt2 * -3489.0) / 16384.0, (sqrt2 *   363.0) / 16384.0,
30652            (sqrt2 *   865.0) / 16384.0, (sqrt2 *  -195.0) / 16384.0,
30653            (sqrt2 *  -105.0) / 16384.0, (sqrt2 *   -35.0) / 16384.0)}
30654
30655def test_20_00
30656  # check small transform cases
30657  index = open_sound("oboe.snd")
30658  set_transform_graph?(true)
30659  [$fourier_transform, $wavelet_transform, $autocorrelation,
30660   $walsh_transform, $cepstrum, $haar_transform].each do |transform|
30661    set_transform_type(transform)
30662    [8, 7, -7, 4, 3, 2, 1, 0].each do |size|
30663      Snd.catch do
30664        set_transform_size(size)
30665        update_transform_graph
30666      end
30667    end
30668  end
30669  close_sound(index)
30670  #
30671  # fft
30672  #
30673  d0 = Vct.new(16)
30674  d0[0] = 1.0
30675  snd_transform($fourier_transform, d0, 0)
30676  d0.each_with_index do |val, i|
30677    if fneq(val, 1.0)
30678      snd_display("fourier (1.0) [%s]: %s?", i, val)
30679    end
30680  end
30681  d0 = Vct.new(16)
30682  d0[0] = 1.0
30683  snd_transform($fourier_transform, d0, 0)
30684  d0.each_with_index do |val, i|
30685    if fneq(val, 1.0)
30686      snd_display("fourier (1.0) [%s]: %s?", i, val)
30687    end
30688  end
30689  snd_transform($fourier_transform, d0, 0)
30690  d0.each_with_index do |val, i|
30691    if i.zero?
30692      if fneq(val, 256.0) and fneq(val, 361.0)
30693        snd_display("fourier (256.0) [%s]: %s?", i, val)
30694      end
30695    else
30696      if fneq(val, 0.0)
30697        snd_display("fourier (0.0) [%s]: %s?", i, val)
30698      end
30699    end
30700  end
30701  #
30702  r0 = Vct.new(8)
30703  i0 = Vct.new(8)
30704  r1 = Vct.new(8)
30705  i1 = Vct.new(8)
30706  r2 = Vct.new(8)
30707  i2 = Vct.new(8)
30708  r0[1] = 0.5
30709  r1[3] = 0.75
30710  r2[1] = 0.25
30711  r2[3] = 0.25
30712  mus_fft(r0, i0)
30713  mus_fft(r1, i1)
30714  mus_fft(r2, i2)
30715  r0.scale!(0.5)
30716  i0.scale!(0.5)
30717  r1.scale!(0.3333)
30718  i1.scale!(0.3333)
30719  r0.add!(r1)
30720  i0.add!(i1)
30721  if (not vequal(r0, r2)) or (not vequal(i0, i2))
30722    snd_display("fft additions/scaling: %s %s: %s %s?", r2, i2, r0, i0)
30723  end
30724  #
30725  d0 = Vct.new(8)
30726  d1 = Vct.new(8)
30727  d0[2] = 1.0
30728  mus_fft(d0, d1, 8, 1)
30729  if (not vequal(d0, vct(1.000, 0.000, -1.000, -0.000, 1.000, 0.000, -1.000, -0.000))) or
30730      (not vequal(d1, vct(0.000, 1.000, 0.000, -1.000, 0.000, 1.000, 0.000, -1.000)))
30731    snd_display("mus_fft 1: %s %s?", d0, d1)
30732  end
30733  mus_fft(d0, d1, 8, -1)
30734  if (not vequal(d0, vct(0.000, 0.000, 8.000, 0.000, 0.000, 0.000, 0.000, 0.000))) or
30735      (not vequal(d1, vct(0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000)))
30736    snd_display("mus_fft -1: %s %s?", d0, d1)
30737  end
30738  d0.fill(1.0)
30739  d1.fill(0.0)
30740  mus_fft(d0, d1, 8)
30741  if (not vequal(d0, vct(8.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000))) or
30742      (not vequal(d1, vct(0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000)))
30743    snd_display("mus_fft 2: %s %s?", d0, d1)
30744  end
30745  mus_fft(d0, d1, 8, -1)
30746  if (not vequal(d0, vct(8.000, 8.000, 8.000, 8.000, 8.000, 8.000, 8.000, 8.000))) or
30747      (not vequal(d1, vct(0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000)))
30748    snd_display("mus_fft -2: %s %s?", d0, d1)
30749  end
30750  d1.fill 0.0
30751  d0.map! do |val| random(1.0) end
30752  fn = d0.dup
30753  mus_fft(d0, d1, 8)
30754  mus_fft(d0, d1, 8, -1)
30755  d0.scale! 1.0 / 8.0
30756  unless vequal(d0, fn)
30757    snd_display("mus_fft 3: %s %s?", d0, fn)
30758  end
30759  d0 = Vct.new(8) do 1.0 - random(2.0) end
30760  d1 = Vct.new(8) do 1.0 - random(2.0) end
30761  save_d0 = d0.dup
30762  save_d1 = d1.dup
30763  reversed_d0 = Vct.new(8) do |i| d0[7 - i] end
30764  reversed_d1 = Vct.new(8) do |i| d1[7 - i] end
30765  mus_fft(d0, d1, 8)
30766  mus_fft(d0, d1, 8)
30767  d0.scale!(0.125)
30768  d1.scale!(0.125)
30769  7.times do |i|
30770    if fneq(d0[i + 1], reversed_d0[i])
30771      snd_display("mus_fft d0 reversed: %s %s?", d0, reversed_d0)
30772    end
30773    if fneq(d1[i + 1], reversed_d1[i])
30774      snd_display("mus_fft d1 reversed: %s %s?", d1, reversed_d1)
30775    end
30776  end
30777  mus_fft(d0, d1, 8)
30778  mus_fft(d0, d1, 8)
30779  d0.scale!(0.125)
30780  d1.scale!(0.125)
30781  unless vequal(d0, save_d0)
30782    snd_display("mus_fft d0 saved: %s %s?", d0, saved_d0)
30783  end
30784  unless vequal(d1, save_d1)
30785    snd_display("mus_fft d1 saved: %s %s?", d1, saved_d1)
30786  end
30787  catch(:done) do
30788    [8, 16].each do |size|
30789      d0 = Vct.new(size)
30790      d0[0] = 1.0
30791      dcopy = d0.dup
30792      d1 = snd_spectrum(d0, Rectangular_window, size)
30793      unless vequal(d0, dcopy)
30794        snd_display("snd_specrum not in-place?: %s %s?", d0, dcopy)
30795      end
30796      (size / 2).times do |i|
30797        if fneq(d1[i], 1.0)
30798          snd_display("snd_spectrum (1.0) [%s: %s]: %s?", i, size, d1[i])
30799        end
30800      end
30801      d0 = Vct.new(size, 1.0)
30802      d1 = snd_spectrum(d0, Rectangular_window)
30803      if fneq(d1[0], 1.0)
30804        snd_display("snd_spectrum back (1.0 %s): %s?", size, d1[0])
30805      end
30806      (1...(size / 2)).each do |i|
30807        if fneq(d1[i], 0.0)
30808          snd_display("snd_spectrum (0.0) [%s: %s]: %s?", i, size, d1[i])
30809          throw(:done)
30810        end
30811      end
30812      d0 = Vct.new(size)
30813      d0[0] = 1.0
30814      d1 = snd_spectrum(d0, Rectangular_window, size, false) # dB (0.0 = max)
30815      (size / 2).times do |i|
30816        if fneq(d1[i], 0.0)
30817          snd_display("snd_spectrum dB (0.0) [%s: %s]: %s?", i, size, d1[i])
30818          throw(:done)
30819        end
30820      end
30821      d0 = Vct.new(size, 1.0)
30822      d1 = snd_spectrum(d0, Rectangular_window, size, false)
30823      if fneq(d1[0], 0.0)
30824        snd_display("snd_spectrum dB back (0.0 %s): %s?", size, d1[0])
30825      end
30826      (1...(size / 2)).each do |i|
30827        if fneq(d1[i], -90.0)     # currently ignores min-dB (snd-sig.c 5023)
30828          snd_display("snd_spectrum dB (1.0) [%s: %s]): %s?", i, size, d1[i])
30829          throw(:done)
30830        end
30831      end
30832      d0 = Vct.new(size)
30833      d0[0] = 1.0
30834      dcopy = d0.dup
30835      d1 = snd_spectrum(d0, Rectangular_window, size, true, 1.0, true) # in-place
30836      if vequal(d0, dcopy)
30837        snd_display("snd_spectrum in-place: %s %s?", d0, dcopy)
30838      end
30839      unless vequal(d0, d1)
30840        snd_display("snd_spectrum returns in-place: %s %s?", d0, d1)
30841      end
30842      (size / 2).times do |i|
30843        if fneq(d1[i], 1.0)
30844          snd_display("snd_spectrum dB (1.0 true) [%s: %s]: %s?", i, size, d1[i])
30845          throw(:done)
30846        end
30847      end
30848      d0 = Vct.new(size)
30849      d0[0] = 1.0
30850      dcopy = d0.dup
30851      d1 = snd_spectrum(d0, Rectangular_window, size, false, 1.0, true) # in-place dB
30852      if vequal(d0, dcopy)
30853        snd_display("snd_spectrum dB in-place: %s %s?", d0, dcopy)
30854      end
30855      unless vequal(d0, d1)
30856        snd_display("snd_spectrum returns dB in-place: %s %s?", d0, d1)
30857      end
30858      (size / 2).times do |i|
30859        if fneq(d1[i], 0.0)
30860          snd_display("snd_spectrum dB (1.0 true) [%s: %s]: %s?", i, size, d1[i])
30861          throw(:done)
30862        end
30863      end
30864      d0 = Vct.new(size, 1.0)
30865      d1 = snd_spectrum(d0, Rectangular_window, size, true, 0.0, false, false) # linear (in-place)
30866      if fneq(d1[0], size.to_f)
30867        snd_display("snd_spectrum no more 0: %s?", d1)
30868      end
30869      (1...(size / 2)).each do |i|
30870        if fneq(d1[i], 0.0)
30871          snd_display("snd_spectrum no more (0.0) [%s: %s]: %s?", i, size, d1[i])
30872          throw(:done)
30873        end
30874      end
30875      d0 = Vct.new(size, 1.0)
30876      d1 = snd_spectrum(d0, Blackman2_window, size)
30877      if (not vequal(d1, vct(1.000, 0.721, 0.293, 0.091))) and
30878          (not vequal(d1, vct(1.000, 0.647, 0.173, 0.037, 0.024, 0.016, 0.011, 0.005)))
30879        snd_display("blackman2 snd_spectrum: %s?", d1)
30880      end
30881      d0 = Vct.new(size, 1.0)
30882      d1 = snd_spectrum(d0, Gaussian_window, size, true, 0.5)
30883      if (not vequal(d1, vct(1.000, 0.900, 0.646, 0.328))) and
30884          (not vequal(d1, vct(1.000, 0.870, 0.585, 0.329, 0.177, 0.101, 0.059, 0.028)))
30885        snd_display("gaussian 0.5  snd_spectrum: %s?", d1)
30886      end
30887      d0 = Vct.new(size, 1.0)
30888      d1 = snd_spectrum(d0, Gaussian_window, size, true, 0.85)
30889      if (not vequal(d1, vct(1.000, 0.924, 0.707, 0.383))) and
30890          (not vequal(d1, vct(1.000, 0.964, 0.865, 0.725, 0.566, 0.409, 0.263, 0.128)))
30891        snd_display("gaussian 0.85 snd_spectrum: %s?", d1)
30892      end
30893    end
30894  end
30895  #
30896  catch(:done) do
30897    [16, 128, 512, 1024].each do |len|
30898      rl = Vct.new(len, 1.0)
30899      xrl = Vct.new(len, 1.0)
30900      len2 = len / 2
30901      snd_transform($fourier_transform, rl)
30902      snd_transform($fourier_transform, xrl, true)
30903      len2.times do |i|
30904        if fneq(rl[i], xrl[i])
30905          snd_display("flat fft: %s at %s: %s %s?", len, i, rl[i], xrl[i])
30906          throw(:done)
30907        end
30908      end
30909      if fneq(rl[0], len * len.to_f)
30910        snd_display("%s at 0: %s?", len, rl[0])
30911      end
30912      rl[0] = 0.0
30913      if rl.peak > 0.001
30914        snd_display("%s impulse: %s?", len, rl.peak)
30915      end
30916    end
30917  end
30918  catch(:done) do
30919    [16, 128, 512, 1024].each do |len|
30920      rl = Vct.new(len)
30921      xrl = Vct.new(len)
30922      len2 = len / 2
30923      rl[len2] = 1.0
30924      xrl[len2] = 1.0
30925      snd_transform($fourier_transform, rl)
30926      snd_transform($fourier_transform, xrl, true)
30927      len2.times do |i|
30928        if fneq(rl[i], xrl[i])
30929          snd_display("impulse fft: %s at %s: %s %s?", len, i, rl[i], xrl[i])
30930          throw(:done)
30931        end
30932      end
30933      if fneq(rl[0], 1.0)
30934        snd_display("flat %s at 0: %s?", len, rl[0])
30935      end
30936    end
30937  end
30938  catch(:done) do
30939    [16, 128, 512, 1024, 4096].each do |len|
30940      rl = Vct.new(len)
30941      xrl = Vct.new(len) do |i| rl[i] = random(1.0) end
30942      len2 = len / 2
30943      rl[len2] = 1.0
30944      xrl[len2] = 1.0
30945      snd_transform($fourier_transform, rl)
30946      rl.scale!(1.0 / len)
30947      snd_transform($fourier_transform, xrl, true)
30948      xrl.scale!(1.0 / len)
30949      len2.times do |i|
30950        if fneq(rl[i], xrl[i])
30951          snd_display("random fft: %s at %s: %s %s?", len, i, rl[i], xrl[i])
30952          throw(:done)
30953        end
30954      end
30955    end
30956  end
30957  catch(:done) do
30958    [16, 128, 512, 1024, 4096].each do |len|
30959      rl = Vct.new(len)
30960      xrl = Vct.new(len) do |i| rl[i] = sin((TWO_PI * 10.0 * i) / len) end
30961      len2 = len / 2
30962      rl[len2] = 1.0
30963      xrl[len2] = 1.0
30964      snd_transform($fourier_transform, rl)
30965      rl.scale!(1.0 / len)
30966      snd_transform($fourier_transform, xrl, true)
30967      xrl.scale!(1.0 / len)
30968      len2.times do |i|
30969        if fneq(rl[i], xrl[i])
30970          snd_display("sin fft: %s at %s: %s %s?", len, i, rl[i], xrl[i])
30971          throw(:done)
30972        end
30973      end
30974    end
30975  end
30976  #
30977  # autocorrelation
30978  #
30979  rl = Vct.new(16)
30980  rl[0] = 1.0
30981  autocorrelate(rl)
30982  unless vequal(rl, vct(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
30983    snd_display("autocorrelate 1: %s?", rl)
30984  end
30985  rl = Vct.new(16)
30986  rl[0] = 1.0
30987  rl[1] = -1.0
30988  autocorrelate(rl)
30989  unless vequal(rl, vct(2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
30990    snd_display("autocorrelate 1 -1: %s?", rl)
30991  end
30992  rl = Vct.new(16)
30993  rl[0] = 1.0
30994  rl[4] = -1.0
30995  autocorrelate(rl)
30996  unless vequal(rl, vct(2, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
30997    snd_display("autocorrelate 1 0 0 0 -1: %s?", rl)
30998  end
30999  rl = Vct.new(16)
31000  rl1 = Vct.new(16)
31001  8.times do |i| rl[i] = rl1[i] = 8.0 - 1 end
31002  nr = vct_subseq(corr(rl, rl, 16, 16), 0, 15)
31003  autocorrelate(rl1)
31004  unless vequal(rl1, nr)
31005    snd_display("autocorrelate/corr (ramp): %s?", rl1, nr)
31006  end
31007  rl = Vct.new(16)
31008  rl1 = Vct.new(16)
31009  8.times do |i| rl[i] = rl1[i] = 1.0 - random(2.0) end
31010  nr = vct_subseq(corr(rl, rl, 16, 16), 0, 15)
31011  autocorrelate(rl1)
31012  unless vequal(rl1, nr)
31013    snd_display("autocorrelate/corr: %s?", rl1, nr)
31014  end
31015  #
31016  catch(:done) do
31017    [16, 64, 256, 512].each do |len|
31018      rl = Vct.new(len)
31019      rla = Vct.new(len)
31020      xim = Vct.new(len)
31021      xrl = Vct.new(len)
31022      len2 = len / 2
31023      rl[0] = 1.0
31024      rl[4] = 1.0
31025      snd_transform($autocorrelation, rl, 0)
31026      if fneq(rl[0], 2.0)
31027        snd_display("autocorrelation %s 0: %s?", len, rl[0])
31028      end
31029      if fneq(rl[4], 1.0)
31030        snd_display("autocorrelation %s 4: %s?", len, rl[0])
31031      end
31032      rla[0] = 1.0
31033      rla[4] = 1.0
31034      autocorrelate(rla)
31035      if fneq(rla[0], 2.0)
31036        snd_display("autocorrelate %s 0: %s?", len, rla[0])
31037      end
31038      if fneq(rla[4], 1.0)
31039        snd_display("autocorrelate %s 4: %s?", len, rla[0])
31040      end
31041      xrl[0] = 1.0
31042      xrl[4] = 1.0
31043      mus_fft(xrl, xim, len, 1)
31044      xrl.map_with_index! do |val, i| val * val + xim[i] * xim[i] end
31045      xim.scale! 0.0
31046      mus_fft(xrl, xim, len, -1)
31047      xrl.scale! 1.0 / len
31048      len2.times do |i|
31049        if fneq(rl[i], xrl[i])
31050          snd_display("%s at %s: %s %s?", len, i, rl[i], xrl[i])
31051          throw(:done)
31052        end
31053      end
31054      rl[0] = 0.0
31055      rl[4] = 0.0
31056      (len / 2).upto(len - 1) do |i| rl[i] = 0.0 end
31057      if rl.peak > 0.001
31058        snd_display("autocorrelate peak: %s?", rl.peak)
31059      end
31060    end
31061  end
31062  catch(:done) do
31063    [16, 64, 256, 512].each do |len|
31064      rl = Vct.new(len)
31065      xim = Vct.new(len)
31066      xrl = Vct.new(len)
31067      len2 = len / 2
31068      ones = [2, random(len2)].max
31069      ones.times do
31070        ind = random(len)
31071        rl[ind] = xrl[ind] = random(1.0)
31072      end
31073      snd_transform($autocorrelation, rl, 0)
31074      mus_fft(xrl, xim, len, 1)
31075      xrl[0] *= xrl[0]
31076      xrl[len2] *= xrl[len2]
31077      j = len - 1
31078      (1...len2).each do |i|
31079        xrl[j] = xrl[i] = xrl[i] * xrl[i] + xim[j] * xim[j]
31080        j -= 1
31081      end
31082      xim.scale! 0.0
31083      mus_fft(xrl, xim, len, -1)
31084      xrl.scale! 1.0 / len
31085      len2.times do |i|
31086        if fneq(rl[i], xrl[i])
31087          snd_display("random %s at %s: %s %s?", len, i, rl[i], xrl[i])
31088          throw(:done)
31089        end
31090      end
31091    end
31092  end
31093  #
31094  # cepstrum
31095  #
31096  rl = vct(0.423618, 0.259318, -0.048365, 1.140571, -0.811856, -0.994098, -0.998613, -2.453642,
31097           -0.438549, -1.520463, -0.312065, -0.724707, 1.154010, 1.466936, 0.110463, -1.520854)
31098  nrl = snd_transform($cepstrum, rl, 0).scale(1.399)
31099  unless vequal(nrl, vct(1.3994950, 0.1416877, 0.0952407, 0.0052814, -0.0613192, 0.0082986,
31100                         -0.0233993, -0.0476585, 0.0259498, -0.0476585, -0.0233993, 0.0082986,
31101                         -0.0613192, 0.0052814, 0.0952407, 0.1416877))
31102    snd_display("cepstrum 16: %s?", nrl)
31103  end
31104  rl = Vct.new(16) do |i| i end
31105  nrl = snd_transform($cepstrum, rl, 0).scale(2.72)
31106  unless vequal(nrl, vct(2.720, 0.452, 0.203, 0.122, 0.082, 0.061, 0.048, 0.041,
31107                         0.039, 0.041, 0.048, 0.061, 0.082, 0.122, 0.203, 0.452))
31108    snd_display("cepstrum 16 by ones: %s?", nrl)
31109  end
31110  catch(:done) do
31111    [16, 64, 256, 512].each do |len|
31112      rl = Vct.new(len)
31113      xim = Vct.new(len)
31114      xrl = Vct.new(len)
31115      rl[0] = 1.0
31116      rl[4] = 1.0
31117      snd_transform($cepstrum, rl, 0)
31118      xrl[0] = 1.0
31119      xrl[4] = 1.0
31120      mus_fft(xrl, xim, len, 1)
31121      xrl.map_with_index! do |xval, i|
31122        if (val = xval * xval + xim[i] * xim[i]) > 0.0000001
31123          log(sqrt(val))
31124        else
31125          -10.0
31126        end
31127      end
31128      xim.scale! 0.0
31129      mus_fft(xrl, xim, len, -1)
31130      fscl = 0.0
31131      xrl.each do |val| fscl = [fscl, val.abs].max end
31132      xrl.scale! 1.0 / fscl
31133      rl.each_with_index do |val, i|
31134        if fneq(val, xrl[i])
31135          snd_display("%s at %s: %s %s?", len, i, val, xrl[i])
31136          throw(:done)
31137        end
31138      end
31139    end
31140  end
31141end
31142
31143def test_20_01
31144  #
31145  # walsh
31146  #
31147  d0 = Vct.new(8)
31148  d0[0] = 1.0
31149  snd_transform($walsh_transform, d0)
31150  unless vequal(d0, Vct.new(8, 1.0))
31151    snd_display("walsh 1: %s?", d0)
31152  end
31153  snd_transform($walsh_transform, d0)
31154  unless vequal(d0, vct(8, 0, 0, 0, 0, 0, 0, 0))
31155    snd_display("walsh -1: %s?", d0)
31156  end
31157  #
31158  d0 = Vct.new(8)
31159  d0[1] = 1.0
31160  snd_transform($walsh_transform, d0)
31161  unless vequal(d0, vct(1, -1, 1, -1, 1, -1, 1, -1))
31162    snd_display("walsh 2: %s?", d0)
31163  end
31164  snd_transform($walsh_transform, d0)
31165  unless vequal(d0, vct(0, 8, 0, 0, 0, 0, 0, 0))
31166    snd_display("walsh -2: %s?", d0)
31167  end
31168  #
31169  d0 = Vct.new(8)
31170  d0[0] = 0.5
31171  d0[1] = 1.0
31172  snd_transform($walsh_transform, d0)
31173  unless vequal(d0, vct(1.5, -0.5, 1.5, -0.5, 1.5, -0.5, 1.5, -0.5))
31174    snd_display("walsh 3: %s?", d0)
31175  end
31176  snd_transform($walsh_transform, d0)
31177  unless vequal(d0, vct(4, 8, 0, 0, 0, 0, 0, 0))
31178    snd_display("walsh -3: %s?", d0)
31179  end
31180  #
31181  d0 = Vct.new(8) do random(1.0) end
31182  d1 = d0.dup
31183  snd_transform($walsh_transform, d0)
31184  snd_transform($walsh_transform, d0)
31185  d0.scale! 1.0 / 8.0
31186  unless vequal(d0, d1)
31187    snd_display("walsh 4: %s %s?", d0, d1)
31188  end
31189  #
31190  d0 = vct(1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1)
31191  d1 = snd_transform($walsh_transform, d0)
31192  unless vequal(d1, vct(4, 4, 4, -4, 4, 4, 4, -4, 4, 4, 4, -4, -4, -4, -4, 4))
31193    snd_display("walsh 5: %s?", d1)
31194  end
31195  #
31196  d0 = vct(1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
31197  d1 = snd_transform($walsh_transform, d0)
31198  unless vequal(d1, vct(0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 0))
31199    snd_display("walsh 6: %s?", d1)
31200  end
31201  d0 = vct(0.174, -0.880, -0.555, -0.879, 0.038, 0.696, -0.612, 0.006,
31202           -0.613, 0.334, -0.111, -0.821, 0.130, 0.030, -0.229, 0.170)
31203  d1 = snd_transform($walsh_transform, d0)
31204  unless vequal(d1, vct(-3.122, -0.434, 2.940, -0.468, -3.580, 2.716, -0.178, -1.386,
31205                        -0.902, 0.638, 1.196, 1.848, -0.956, 2.592, -1.046, 2.926))
31206    snd_display("walsh 7: %s?", d1)
31207  end
31208  #
31209  # haar
31210  #
31211  d0 = Vct.new(8)
31212  d0[2] = 1.0
31213  snd_transform($haar_transform, d0)
31214  unless vequal(d0, vct(0.354, 0.354, -0.500, 0.000, 0.000, 0.707, 0.000, 0.000))
31215    snd_display("haar 1: %s?", d0)
31216  end
31217  inverse_haar(d0)
31218  unless vequal(d0, vct(0.000, 0.000, 1.000, 0.000, 0.000, 0.000, 0.000, 0.000))
31219    snd_display("inverse_haar 1: %s?", d0)
31220  end
31221  #
31222  d0 = Vct.new(8)
31223  d0[0] = 1.0
31224  snd_transform($haar_transform, d0)
31225  unless vequal(d0, vct(0.354, 0.354, 0.500, 0.000, 0.707, 0.000, 0.000, 0.000))
31226    snd_display("haar 2: %s?", d0)
31227  end
31228  inverse_haar(d0)
31229  unless vequal(d0, vct(1.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000))
31230    snd_display("inverse_haar 2: %s?", d0)
31231  end
31232  #
31233  d0 = snd_transform($haar_transform,
31234                     vct(-0.483, 0.174, -0.880, -0.555, -0.879, 0.038, 0.696, -0.612))
31235  unless vequal(d0, vct(-0.884, -0.349, 0.563, -0.462, -0.465, -0.230, -0.648, 0.925))
31236    snd_display("haar 3: %s?", d0)
31237  end
31238  #
31239  sq2 = sqrt(2.0)
31240  d0 = snd_transform($haar_transform, vct(4, 6, 10, 12, 8, 6, 5, 5))
31241  unless vequal(d0, vct(14 * sq2, 2 * sq2, -6, 2, -sq2, -sq2, sq2, 0))
31242    snd_display("haar 4: %s?", d0)
31243  end
31244  d0 = snd_transform($haar_transform, vct(2, 4, 6, 8, 10, 12, 14, 16))
31245  unless vequal(d0, x = vct(18 * sq2, -8 * sq2, -4, -4, -sq2, -sq2, -sq2, -sq2))
31246    snd_display("haar 5: %s?", d0, x)
31247  end
31248  #
31249  d0 = Vct.new(8)
31250  d1 = Vct.new(8) do |i| d0[i] = random(1.0) end
31251  snd_transform($haar_transform, d0)
31252  inverse_haar(d0)
31253  unless vequal(d0, d1)
31254    snd_display("inverse_haar 6: %s %s?", d0, d1)
31255  end
31256  #
31257  # wavelet
31258  #
31259  d0 = snd_transform($wavelet_transform, vct(1, 1, 0, 0, 0, 0, 0, 0), 0) # daub4
31260  unless vequal(d0, vct(0.625, 0.375, -0.217, 1.083, -0.354, 0.000, 0.000, 0.354))
31261    snd_display("fxt wavelet 1: %s?", d0)
31262  end
31263  [16, 64].each do |size|
31264    $wts.each do |key, val|
31265      d1 = Vct.new(size)
31266      d2 = Vct.new(size)
31267      d1[2] = 1.0
31268      d2[2] = 1.0
31269      wavelet(d1, size, 0, :pwt, val)
31270      snd_transform($wavelet_transform, d2, key.last)
31271      unless vequal(d1, d2)
31272        snd_display("wavelet (%s) %s:\n# %s\n# %s?", size, key, d1, d2)
31273      end
31274      wavelet(d2, size, -1, :pwt, val)
31275      d1.fill 0.0
31276      d1[2] = 1.0
31277      unless vequal(d1, d2)
31278        if key.last.between?(9, 10)
31279          d2[2] = 0.0
31280          if d2.peak > 0.1
31281            snd_display("inverse wavelet a (%s) %s:\n# %s\n# %s?", size, key, d1, d2)
31282          end
31283        else
31284          if key.last > 14
31285            pk = d2[2]
31286            d2[2] = 0.0
31287            if d2.peak > pk
31288              snd_display("inverse wavelet b (%s) %s:\n# %s\n# %s?", size, key, d1, d2)
31289            end
31290          else
31291            snd_display("inverse wavelet c (%s) %s:\n# %s\n# %s?", size, key, d1, d2)
31292          end
31293        end
31294      end
31295    end
31296    $wts.each do |key, val|
31297      next if key.last > 8
31298      d2 = Vct.new(size) do random(1.0) end
31299      d1 = d2.dup
31300      snd_transform($wavelet_transform, d2, key.last)
31301      wavelet(d2, size, -1, :pwt, val)
31302      unless vequal(d1, d2)
31303        snd_display("random wavelet %s:\n# %s\n# %s?", key.first, d1, d2)
31304      end
31305    end
31306  end
31307  #
31308  set_max_transform_peaks(100)
31309  ind = open_sound("oboe.snd")
31310  ftype = add_transform("low-pass", "filtered", 0.0, 1.0,
31311                        lambda { |len, fd|
31312                          flt = make_fir_filter(:order, 8, :xcoeffs, Vct.new(8, 0.0125))
31313                          Vct.new(len) do fir_filter(flt, read_sample(fd)) end
31314                        })
31315  unless transform?(ftype)
31316    snd_display("transform added: %s?", ftype)
31317  end
31318  set_transform_normalization(Dont_normalize)
31319  set_transform_type(ftype, ind, 0)
31320  set_transform_size(16, ind, 0)
31321  set_transform_graph_type(Graph_once, ind, 0)
31322  set_transform_graph?(true, ind, 0)
31323  set_cursor(12000, ind, 0)
31324  samps = transform2vct(ind, 0)
31325  delete_file("s61.rb")
31326  save_state("s61.rb")
31327  delete_file("s61.rb")
31328  close_sound(ind)
31329  #
31330  ind = open_sound("oboe.snd")
31331  ftype = add_transform("abs-it", "absit", 0.0, 1.0,
31332                        lambda { |len, fd|
31333                          Vct.new(len) do read_sample(fd) end
31334                        })
31335  set_transform_normalization(Dont_normalize)
31336  set_transform_type(ftype, ind, 0)
31337  set_transform_size(256, ind, 0)
31338  set_transform_graph_type(Graph_once, ind, 0)
31339  set_transform_graph?(true, ind, 0)
31340  set_cursor(12000, ind, 0)
31341  samps = transform2vct(ind, 0)
31342  channel2vct(left_sample(ind, 0), 256).zip(samps) do |val1, val2|
31343    if fneq(val1, val2)
31344      snd_display("add_transform same (%s): %s %s?", ftype, val1, val2)
31345    end
31346  end
31347  set_dot_size(60, ind, 0)
31348  set_graph_style(Graph_lollipops, ind, 0)
31349  set_x_bounds([2.579, 2.580])
31350  update_time_graph
31351  delete_transform(ftype)
31352  if transform?(ftype)
31353    snd_display("transform? deleted: %s?", ftype)
31354  end
31355  if transform?(-1)
31356    snd_display("transform? -1: %s?", ftype)
31357  end
31358  if transform?(integer2transform(123))
31359    snd_display("transform? 123: %s?", ftype)
31360  end
31361  if (res = transform_type(ind, 0)) != $fourier_transform
31362    snd_display("after delete_transform %s -> %s?", ftype, res)
31363  end
31364  close_sound(ind)
31365  #
31366  ind1 = open_sound("oboe.snd")
31367  set_time_graph_style(Graph_lollipops, ind1, 0)
31368  graph2ps("aaa.eps")
31369  set_transform_graph?(true, ind1, 0)
31370  set_transform_graph_type(Graph_as_sonogram, ind1, 0)
31371  set_transform_size(256)
31372  update_transform_graph
31373  size = transform_framples(ind1, 0)
31374  if number?(size) or size.length != 3
31375    snd_display("transform_framples of sonogram: %s?", size)
31376  end
31377  graph2ps("aaa.eps")
31378  old_colormap = colormap
31379  set_colormap(integer2colormap(0))
31380  update_transform_graph
31381  set_transform_graph_type(Graph_as_spectrogram, ind1, 0)
31382  update_transform_graph
31383  graph2ps("aaa.eps")
31384  set_colormap(old_colormap)
31385  close_sound(ind1)
31386  #
31387  ind = new_sound("test.snd", :header_type, Mus_next, :sample_type, Mus_bfloat)
31388  pad_channel(0, 1000)
31389  set_transform_graph_type(Graph_once, ind, 0)
31390  set_show_transform_peaks(true, ind, 0)
31391  set_fft_log_magnitude(true, ind, 0)
31392  set_fft_log_frequency(false, ind, 0)
31393  set_transform_graph?(true, ind, 0)
31394  set_x_bounds([0.0, 0.04])
31395  update_time_graph
31396  update_transform_graph
31397  close_sound(ind)
31398  #
31399  ind = open_sound("oboe.snd")
31400  size = 8192
31401  v = channel2vct(1000, size, ind, 0)
31402  set_show_listener(false)
31403  set_window_height(800)
31404  set_lisp_graph?(true, ind, 0)
31405  graph(v, "biggy", 0.0, 1.0, 0.0, 1.0, ind, 0)
31406  set_transform_graph_type(Graph_once, ind, 0)
31407  set_show_transform_peaks(true, ind, 0)
31408  set_fft_log_magnitude(true, ind, 0)
31409  set_fft_log_frequency(false, ind, 0)
31410  set_transform_graph?(true, ind, 0)
31411  graph2ps("aaa.eps")
31412  set_x_bounds([0.0, 1.0])
31413  set_max_transform_peaks(3, ind, 0)
31414  update_time_graph
31415  update_transform_graph
31416  update_lisp_graph
31417  scale_by(0.0)
31418  update_time_graph
31419  update_transform_graph
31420  undo_edit
31421  set_transform_graph_type(Graph_as_sonogram, ind, 0)
31422  set_fft_log_magnitude(false, ind, 0)
31423  update_transform_graph
31424  graph2ps("aaa.eps")
31425  set_with_gl(false)
31426  set_spectrum_end(0.2, ind, 0)
31427  set_transform_graph_type(Graph_as_spectrogram, ind, 0)
31428  update_transform_graph
31429  update_lisp_graph
31430  graph2ps("aaa.eps")
31431  set_show_listener(true)
31432  close_sound(ind)
31433end
31434
31435def test_20_02
31436  snd_test_neq(dolph(16, 2.5),
31437               vct(0.097, 0.113, 0.221, 0.366, 0.536, 0.709, 0.860, 0.963,
31438                   1.000, 0.963, 0.860, 0.709, 0.536, 0.366, 0.221, 0.113),
31439               "dolph 16 2.5 (dsp.rb)")
31440  v = Vct.new(8)
31441  v0 = Vct.new(8) do |i| v[i] = mus_random(1.0) end
31442  v = dht(dht(v)).scale(1.0 / 8.0)
31443  snd_test_any_neq(v, v0, :vvequal?, "dht twice")
31444  v.fill 0.0
31445  v[1] = 1.0
31446  snd_test_neq(dht(v), vct(1, 1.414, 1, 0, -1, -1.414, -1, 0), "dht of pulse")
31447  #
31448  ind = open_sound("oboe.snd")
31449  snd_test_neq(find_sine(553.0, 2000, 3000, ind).first, 0.03835, "find_sine")
31450  snd_test_neq(find_sine(620.0, 2000, 3000, ind).first, 0.0012, "find_sine")
31451  snd_test_neq(spot_freq(2000, ind, 0).round, 553, "spot_freq")
31452  down_oct(2)
31453  frq = spot_freq(2000, ind, 0)
31454  unless frq.ceil.between?(275, 277)
31455    snd_display("spot_freq down_oct: %s?", frq)
31456  end
31457  undo_edit
31458  zero_phase
31459  snd_test_neq(sample(0), 0.1472, "zero_phase")
31460  undo_edit
31461  rotate_phase(lambda do |x| x end)
31462  undo_edit
31463  brighten_slightly(0.5)
31464  undo_edit
31465  spike
31466  close_sound(ind)
31467  #
31468  ind = open_sound("1a.snd")
31469  frms = framples(ind)
31470  valf = find_sine(440.0, 0, frms, ind).first
31471  valg = 2 * (goertzel(440.0, 0, frms, ind) / frms)
31472  valf1 = find_sine(100.0, 0, frms, ind).first
31473  valg1 = 2 * (goertzel(100.0, 0, frms, ind) / frms)
31474  valf2 = find_sine(440.0, 0, frms, ind).first
31475  valg2 = 2 * (goertzel(440.0, 0, frms, ind) / frms)
31476  valf3 = find_sine(437.0, 0, frms, ind).first
31477  valg3 = 2 * (goertzel(437.0, 0, frms, ind) / frms)
31478  snd_test_neq(valg, valf, "goertzel 0")
31479  snd_test_neq(valg1, valf1, "goertzel 1")
31480  snd_test_neq(valg2, valf2, "goertzel 2")
31481  snd_test_neq(valg3, valf3, "goertzel 3")
31482  close_sound(ind)
31483  #
31484  snd_test_neq(vct_polynomial(vct(0, 2), vct(1, 2)),
31485               vct(1, 5),
31486               "vct_polynomial 0")
31487  snd_test_neq(vct_polynomial(vct(0, 1, 2), vct(0, 2, 1)),
31488               vct(0, 3, 8),
31489               "vct_polynomial 1")
31490  snd_test_neq(vct_polynomial(vct(0, 1, 2), vct(0, 2, 1, 0.5)),
31491               vct(0, 3.5, 12),
31492               "vct_polynomial 2")
31493  snd_test_neq(vct_polynomial(vct(0, 1, 2), vct(1)),
31494               vct(1, 1, 1),
31495               "vct_polynomial 3")
31496  #
31497  ind = open_sound("pistol.snd")
31498  mx = maxamp(ind, 0)
31499  channel_polynomial(vct(0, 2), ind, 0)
31500  snd_test_neq(maxamp(), mx * 2.0, "channel_polynomial 2")
31501  undo_edit
31502  channel_polynomial(vct(0.0, 0.5, 0.25, 0.25), ind, 0)
31503  snd_test_neq(maxamp(), 0.222, "channel_polynomial 3")
31504  undo_edit
31505  channel_polynomial(vct(0, 0, 1), ind, 0)
31506  if pos = scan_channel(lambda { |y| y < 0.0 })
31507    snd_display("channel_polynomial squares: %s?", pos)
31508  end
31509  undo_edit
31510  channel_polynomial(vct(0.5, 1), ind, 0)
31511  if pos = scan_channel(lambda { |y| y < 0.0 })
31512    snd_display("channel_polynomial offset: %s?", pos)
31513  end
31514  snd_test_neq(maxamp, 0.8575, "channel_polynomial off mx")
31515  undo_edit
31516  spectral_polynomial(vct(0, 1), ind, 0)
31517  snd_test_neq(maxamp(), 0.493, "spectral_polynomial 0 mx")
31518  snd_test_neq(framples(ind, 0), 41623, "spectral_polynomial 0 len")
31519  undo_edit
31520  spectral_polynomial(vct(0, 0.5, 0.5), ind, 0)
31521  snd_test_neq(maxamp(), 0.493, "spectral_polynomial 1 mx")
31522  snd_test_neq(framples(ind, 0), 41623 * 2, "spectral_polynomial 1 len")
31523  undo_edit
31524  spectral_polynomial(vct(0, 0, 0, 1), ind, 0)
31525  snd_test_neq(maxamp(), 0.493, "spectral_polynomial 2 mx")
31526  snd_test_neq(framples(ind, 0), 41623 * 3, "spectral_polynomial 2 len")
31527  close_sound(ind)
31528  #
31529  vals = scentroid("oboe.snd")
31530  snd_test_neq(vals[0], 1876.085, "scentroid vals[0]")
31531  snd_test_neq(vals[1], 1447.004, "scentroid vals[1]")
31532  flt = make_fir_filter(3, vct(0.5, 0.25, 0.125))
31533  data = Vct.new(10)
31534  data[0] = 1.0
31535  undata = Vct.new(10) do |i| fir_filter(flt, data[i]) end
31536  fdata = invert_filter(vct(0.5, 0.25, 0.125))
31537  flt = make_fir_filter(fdata.length, fdata)
31538  undata.map! do |val| fir_filter(flt, val) end
31539  snd_test_neq(undata, data, "invert_filter")
31540  #
31541  top = 0.9
31542  coeffs = Vct.new(6) do
31543    top -= 0.1
31544    top + random(0.2)
31545  end
31546  flt = make_fir_filter(6, coeffs)
31547  data = Vct.new(20)
31548  data[0] = 1.0
31549  undata = Vct.new(20) do |i| fir_filter(flt, data[i]) end
31550  fdata = invert_filter(coeffs)
31551  flt = make_fir_filter(fdata.length, fdata)
31552  undata.map! do |val| fir_filter(flt, val) end
31553  snd_test_neq(undata, data, "invert_filter (6)")
31554  #
31555  flt = make_volterra_filter(vct(1, 0.4), vct(0.3, 0.2, 0.1))
31556  snd_test_neq(Vct.new(10) do |i| volterra_filter(flt, (i == 1 ? 0.5 : 0.0)) end,
31557               vct(0.000, 0.575, 0.250, 0.025, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000),
31558               "volterra_filter")
31559  #
31560  flt = make_volterra_filter(vct(1.0), vct(1.0))
31561  snd_test_neq(Vct.new(10) do |i| volterra_filter(flt, (i.zero? ? 1.0 : 0.0)) end,
31562               vct(2.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000),
31563               "volterra_filter x + x^2")
31564  #
31565  flt = make_volterra_filter(vct(1.0), vct(1.0))
31566  x = 1.1
31567  snd_test_neq(Vct.new(10) do |i| volterra_filter(flt, x -= 0.1) end,
31568               vct(2.000, 1.710, 1.440, 1.190, 0.960, 0.750, 0.560, 0.390, 0.240, 0.110),
31569               "volterra_filter x + x^2 by -0.1")
31570  #
31571  flt = make_volterra_filter(vct(1.0, 0.5), vct(1.0))
31572  snd_test_neq(Vct.new(10) do |i| volterra_filter(flt, (i.zero? ? 1.0 : 0.0)) end,
31573               vct(2.000, 0.500, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000),
31574               "volterra_filter x + 0.5x(n-1) + x^2")
31575  #
31576  flt = make_volterra_filter(vct(1.0, 0.5), vct(1.0, 0.6))
31577  snd_test_neq(Vct.new(10) do |i| volterra_filter(flt, (i.zero? ? 0.9 : 0.0)) end,
31578               vct(1.710, 0.936, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000),
31579               "volterra_filter x + 0.5x(n-1) + x^2 + 0.6")
31580  #
31581  ind = new_sound("test.snd", :size, 100)
31582  gen = make_oscil(440)
31583  map_chan(lambda { |y| oscil(gen) })
31584  down_oct(2)
31585  snd_test_neq(framples(), 200, "down_oct new len")
31586  r1 = make_sampler(0, ind, 0, 1, 1)
31587  r2 = make_sampler(0, ind, 0, 1, 2)
31588  200.times do |i|
31589    val1 = r1.call
31590    val2 = r2.call
31591    val3 = r2.call
31592    if fneq(val1, val2) and fneq(val1, val3)
31593      snd_display(snd_format_neq(val1, val2, "down_oct[%d] %1.4f", i, val3))
31594    end
31595  end
31596  close_sound(ind)
31597  #
31598  d0 = Vct.new(8)
31599  d1 = Vct.new(8)
31600  d0[2] = 1.0
31601  vals = fractional_fourier_transform(d0, d1, 8, 1.0)
31602  snd_test_neq(vals[0], vct(1, 0, -1, 0, 1, 0, -1, 0), "fractional_fourier_transform vals[0]")
31603  snd_test_neq(vals[1], vct(0, 1, 0, -1, 0, 1, 0, -1), "fractional_fourier_transform vals[1]")
31604  d0 = Vct.new(8)
31605  d1 = Vct.new(8)
31606  d0[2] = 1.0
31607  vals = z_transform(d0, 8, exp(make_rectangular(0.0, 0.25 * PI)))
31608  vals.each_with_index do |val, i|
31609    d0[i] = val.real
31610    d1[i] = val.imag
31611  end
31612  snd_test_neq(d0, vct(1, 0, -1, 0, 1, 0, -1, 0), "z_transform d0")
31613  snd_test_neq(d1, vct(0, 1, 0, -1, 0, 1, 0, -1), "z_transform d1")
31614  v1 = Vct.new(16)
31615  v1[0] = 1.0
31616  snd_test_neq(z_transform(v1, 16, 0.5).to_vct, Vct.new(16, 1.0), "z_transform 0.5 0=1")
31617  snd_test_neq(z_transform(v1, 16, -1.0).to_vct, Vct.new(16, 1.0), "z_transform -1.0 0=1")
31618  v1[0] = 0.0
31619  v1[1] = 1.0
31620  snd_test_neq(z_transform(v1, 16, 0.5).to_vct,
31621               vct(1, 0.5, 0.25, 0.125, 0.062, 0.031, 0.016, 0.008,
31622                   0.004, 0.002, 0.001, 0, 0, 0, 0, 0),
31623               "z_transform 0.5 1=1")
31624  snd_test_neq(z_transform(v1, 16, 2.0).to_vct,
31625               vct(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768),
31626               "z_transform 2.0 1=1")
31627  v1[2] = 1.0
31628  snd_test_neq(z_transform(v1, 16, 0.5).to_vct,
31629               vct(2, 0.75, 0.3125, 0.14, 0.0664, 0.0322, 0.0158, 0.00787,
31630                   0.0039, 0.0019, 0, 0, 0, 0, 0, 0),
31631               "z_transform 0.5 2=1")
31632  snd_test_neq(z_transform(v1, 16, 2.0).to_vct,
31633               vct(2, 6, 20, 72, 272, 1056, 4160, 16512, 65792, 262656, 1049600,
31634                   4196352, 16781312, 67117056, 268451840, 1073774592),
31635               "z_transform 2.0 1=1 2=1")
31636  j = 1.0
31637  v1.map! do |ignored|
31638    val = j
31639    j *= 0.4
31640    val
31641  end
31642  snd_test_neq(z_transform(v1, 16, 1.0).to_vct, Vct.new(16, 1.0 / (1.0 - 0.4)), "z_transform 1 0.4g")
31643  ind = open_sound("oboe.snd")
31644  automorph(Complex(0.0, 1.0), 0, 0, 1)
31645  automorph(Complex(0.0, 1.0), 0, 0, 1)
31646  automorph(Complex(0.0, 1.0), 0, 0, 1)
31647  automorph(Complex(0.0, 1.0), 0, 0, 1)
31648  mxdiff = 0.0
31649  rd1 = make_sampler(0, ind, 0)
31650  rd2 = make_sampler(0, ind, 0, 1, 0)
31651  scan_channel(lambda do |y|
31652                 diff = (rd1.call - rd2.call).abs
31653                 if diff > mxdiff
31654                   mxdiff = diff
31655                 end
31656                 false
31657               end)
31658  snd_test_gt(mxdiff, 0.003, "automorph rotation")
31659  close_sound(ind)
31660end
31661
31662def test_20
31663  if defined? bes_j0
31664    bes_test(:bes_j0)
31665    bes_test(:bes_j1)
31666    bes_test_jn
31667    bes_test_y(:bes_y0)
31668    bes_test_y(:bes_y1)
31669    bes_test_yn
31670    bes_test_i0
31671    bes_test_i1
31672    bes_test_in
31673    bes_test_k0
31674    bes_test_k1
31675    bes_test_kn
31676    test_lgamma
31677    test_erf
31678  end
31679  test_20_00
31680  test_20_01 if $with_test_gui
31681  test_20_02
31682end
31683
31684# ---------------- test 21: new stuff ----------------
31685
31686def display_samps_in_red(snd, chn)
31687  left = left_sample(snd, chn)
31688  right = right_sample(snd, chn)
31689  old_color = foreground_color(snd, chn)
31690  red = make_color_with_catch(1, 0, 0)
31691  if left < 2000 and right > 1000
31692    case data = make_graph_data(snd, chn)
31693    when Vct
31694      samps = [right, 2000].min - [left, 1000].max
31695      offset = [0, 1000 - left].max
31696      new_data = data.subseq(offset, offset + samps)
31697      set_foreground_color(red, snd, chn)
31698      cr = channel_widgets(snd, chn)[17]
31699      graph_data(new_data, snd, chn, Copy_context,
31700                 [1000, left].max, [2000, right].min, Graph_lines, cr)
31701      set_foreground_color(old_color, snd, chn)
31702    when Array
31703      low_data = data[0]
31704      high_data = data[1]
31705      size = low_data.length
31706      samps = right - left
31707      left_offset = [0, 1000 - left].max
31708      left_bin = ((size * left_offset.to_f) / samps).round
31709      right_offset = [2000, right].min - left
31710      right_bin = ((size * right_offset.to_f) / samps).round
31711      new_low_data = low_data.subseq(left_bin, right_bin)
31712      new_high_data = high_data.subseq(left_bin, right_bin)
31713      set_foreground_color(red, snd, chn)
31714      cr = channel_widgets(snd, chn)[17]
31715      graph_data([new_low_data, new_high_data], snd, chn, Copy_context,
31716                 left_bin, right_bin, Graph_lines, cr)
31717      set_foreground_color(old_color, snd, chn)
31718    end
31719  end
31720rescue
31721  snd_display("draw error in %s", get_func_name)
31722end
31723
31724def show_greeting(snd, chn)
31725  ls = left_sample(snd, chn)
31726  rs = right_sample(snd, chn)
31727  if ls < 1000 and rs > 1000
31728    pos = x2position(1000.0 / srate(snd), snd, chn)
31729    old_color = foreground_color(snd, chn)
31730    cr = channel_widgets(snd, chn)[17]
31731    set_foreground_color(make_color_with_catch(0.75, 0.75, 0.75), snd, chn)
31732    fill_rectangle(pos, 10, 50, 20, snd, chn, Time_graph, false, cr)
31733    set_foreground_color(make_color_with_catch(1, 0, 0), snd, chn)
31734    draw_string("hi!", pos + 5, 24, snd, chn, Time_graph, cr)
31735    set_foreground_color(old_color, snd, chn)
31736  end
31737rescue
31738  snd_display("draw error in %s", get_func_name)
31739end
31740
31741def st_equal?(a, b)
31742  a == b
31743end
31744
31745def st_eql?(a, b)
31746  a.eql?(b)
31747end
31748
31749def st_vequal_2(a, b)
31750  vequal(a[0], b[0]) and vequal(a[1], b[1])
31751end
31752
31753def test_sound_func_1(func, ind_1, ind_2, new_val,
31754                      eq_func, leq_func, set_p, chan, global)
31755  old_val = snd_func(func)
31756  old_vals = snd_func(func, true)
31757  old_default = snd_func(func, false)
31758  old_1 = snd_func(func, ind_1)
31759  old_2 = snd_func(func, ind_2)
31760  sel_snd = selected_sound()
31761  unsel_snd = sel_snd == ind_1 ? ind_2 : ind_1
31762  caller = chan ? "channel" : "sound"
31763  snd_test_any_neq(old_val, old_default, eq_func,
31764                   "%s sound_func: no arg false", func)
31765  unless method(leq_func).call(old_vals, [old_1, old_2]) or
31766         method(leq_func).call(old_vals, [old_2, old_1])
31767    s = snd_format_neq(old_vals, [old_1, old_2], "%s sound_func true", func)
31768    snd_display_prev_caller(s)
31769  end
31770  if set_p
31771    set_snd_func(func, new_val)
31772    res1 = snd_func(func)
31773    res2 = snd_func(func, sel_snd)
31774    res3 = snd_func(func, unsel_snd)
31775    snd_test_any_neq(res1, new_val, eq_func, "set_%s no arg", func)
31776    snd_test_any_neq(res1, res2, eq_func, "set_%s no arg sel", func)
31777    if (global and (not method(eq_func).call(res1, res3))) or
31778       ((not global) and method(eq_func).call(res1, res3))
31779      s = snd_format_neq(res1, res3, "set_%s no arg unsel", func)
31780      snd_display_prev_caller(s)
31781    end
31782    res1 = snd_func(func, true)
31783    unless method(leq_func).call(res1, [res2, res3]) or
31784           method(leq_func).call(res1, [res3, res2])
31785      s = snd_format_neq(res1, [res2, res3],
31786                         "set_%s %s_func true", func, caller)
31787      snd_display_prev_caller(s)
31788    end
31789    set_snd_func(func, old_val)
31790    if set_p == :swap
31791      set_snd_func(func, ind_1, new_val)
31792    else
31793      set_snd_func(func, new_val, ind_1)
31794    end
31795    res0 = snd_func(func, true)
31796    res1 = snd_func(func, ind_1)
31797    res2 = snd_func(func, ind_2)
31798    unless method(eq_func).call(res1, new_val)
31799      s = snd_format_neq(res1, new_val, "set_%s arg", func)
31800      snd_display_prev_caller(s)
31801    end
31802    if method(eq_func).call(res2, new_val)
31803      s = snd_format_eq(res2, new_val, "set_%s arg (2)", func)
31804      snd_display_prev_caller(s)
31805    end
31806    unless method(leq_func).call(res0, [res1, res2]) or
31807           method(leq_func).call(res0, [res2, res1])
31808      s = snd_format_neq(res0, [res1, res2], "set_%s %s_func arg", func, caller)
31809      snd_display_prev_caller(s)
31810    end
31811    if set_p == :swap
31812      set_snd_func(func, ind_1, old_1)
31813      set_snd_func(func, true, new_val)
31814    else
31815      set_snd_func(func, old_1, ind_1)
31816      set_snd_func(func, new_val, true)
31817    end
31818    res0 = snd_func(func, true)
31819    res1 = snd_func(func, ind_1)
31820    res2 = snd_func(func, ind_2)
31821    unless method(leq_func).call(res0, [new_val, new_val])
31822      s = snd_format_neq(res0, [new_val, new_val],
31823                         "set_%s %s_func arg true", func, caller)
31824      snd_display_prev_caller(s)
31825    end
31826    unless method(eq_func).call(res1, new_val)
31827      s = snd_format_neq(res1, new_val, "set_%s %s_func arg true", func, caller)
31828      snd_display_prev_caller(s)
31829    end
31830    unless method(eq_func).call(res2, new_val)
31831      s = snd_format_neq(res2, new_val,
31832                         "set_%s %s_func arg true (2)", func, caller)
31833      snd_display_prev_caller(s)
31834    end
31835    if set_p == :swap
31836      set_snd_func(func, ind_1, old_1)
31837      set_snd_func(func, ind_2, old_2)
31838    else
31839      set_snd_func(func, old_1, ind_1)
31840      set_snd_func(func, old_2, ind_2)
31841    end
31842    res1 = snd_func(func, ind_1)
31843    res2 = snd_func(func, ind_2)
31844    unless method(eq_func).call(res1, old_1)
31845      s = snd_format_neq(res1, old_1, "set_%s arg true old", func)
31846      snd_display_prev_caller(s)
31847    end
31848    unless method(eq_func).call(res2, old_2)
31849      s = snd_format_neq(res2, old_2, "set_%s arg true old (2)", func)
31850      snd_display_prev_caller(s)
31851    end
31852  end
31853end
31854
31855def test_channel_func_1(func, ind_1, ind_2, new_val,
31856                        eq_func, leq_func, set_p, global)
31857  old_1_0 = snd_func(func, ind_1, 0)
31858  old_2_0 = snd_func(func, ind_2, 0)
31859  old_2_1 = snd_func(func, ind_2, 1)
31860  old_1_all = snd_func(func, ind_1, true)
31861  old_2_all = snd_func(func, ind_2, true)
31862  old_all_0 = snd_func(func, true, 0)
31863  old_all_all = snd_func(func, true, true)
31864  unless method(eq_func).call(old_1_0, old_1_all[0])
31865    s = snd_format_neq(old_1_0, old_1_all[0],
31866                       "%s channel_func: old 1/true", func)
31867    snd_display_prev_caller(s)
31868  end
31869  unless method(eq_func).call(old_2_0, old_2_all[0])
31870    s = snd_format_neq(old_2_0, old_2_all[0],
31871                       "%s channel_func: old 2-1/true", func)
31872    snd_display_prev_caller(s)
31873  end
31874  unless method(eq_func).call(old_2_1, old_2_all[1])
31875    s = snd_format_neq(old_2_1, old_2_all[1],
31876                       "%s channel_func: old 2-2/true", func)
31877    snd_display_prev_caller(s)
31878  end
31879  unless method(leq_func).call(old_1_all, [old_1_0])
31880    s = snd_format_neq(old_1_all, [old_1_0], "%s channel_func true", func)
31881    snd_display_prev_caller(s)
31882  end
31883  unless method(leq_func).call(old_2_all, [old_2_0, old_2_1])
31884    s = snd_format_neq(old_2_all, [old_2_0, old_2_1],
31885                       "%s channel_func true", func)
31886    snd_display_prev_caller(s)
31887  end
31888  unless ((method(leq_func).call(old_all_all[0], old_1_all) or
31889           method(leq_func).call(old_all_all[0], old_2_all)) and
31890          (method(leq_func).call(old_all_all[1], old_1_all) or
31891           (method(leq_func).call(old_all_all[1], old_2_all))))
31892    s = snd_format_neq(old_all_all[0], old_1_all,
31893                       "%s channel_func true true", func)
31894    snd_display_prev_caller(s)
31895  end
31896  if set_p
31897    set_snd_func(func, new_val, ind_1, 0)
31898    res1 = snd_func(func, ind_1, 0)
31899    res2 = snd_func(func, ind_2, 1)
31900    unless method(eq_func).call(res1, new_val)
31901      s = snd_format_neq(res1, new_val, "set_%s channel_func", func)
31902      snd_display_prev_caller(s)
31903    end
31904    if method(eq_func).call(res2, new_val)
31905      s = snd_format_eq(res2, new_val, "set_%s 2 channel_func", func)
31906      snd_display_prev_caller(s)
31907    end
31908    set_snd_func(func, old_1_0, ind_1, 0)
31909    set_snd_func(func, new_val, ind_2, 1)
31910    res1 = snd_func(func, ind_1, 0)
31911    res2 = snd_func(func, ind_2, 1)
31912    if method(eq_func).call(res1, new_val)
31913      s = snd_format_eq(res1, new_val, "set_%s (2) channel_func", func)
31914      snd_display_prev_caller(s)
31915    end
31916    unless method(eq_func).call(res2, new_val)
31917      s = snd_format_neq(res2, new_val, "set_%s (2) 2 channel_func", func)
31918      snd_display_prev_caller(s)
31919    end
31920    set_snd_func(func, new_val, ind_2, 0)
31921    set_snd_func(func, old_2_0, ind_2, true)
31922    res1 = snd_func(func, ind_2, 0)
31923    res2 = snd_func(func, ind_2, 1)
31924    unless method(eq_func).call(res1, old_2_0)
31925      s = snd_format_neq(res1, old_2_0, "set_%s (true 0) 2 channel_func", func)
31926      snd_display_prev_caller(s)
31927    end
31928    unless method(eq_func).call(res2, old_2_0)
31929      s = snd_format_neq(res2, old_2_0, "set_%s (true 1) 2 channel_func", func)
31930      snd_display_prev_caller(s)
31931    end
31932    set_snd_func(func, old_2_0, ind_2, 0)
31933    set_snd_func(func, old_2_1, ind_2, 1)
31934  end
31935end
31936
31937def test_21_00
31938  unless sound_file?("oboe.snd")
31939    snd_display("oboe.snd not a sound file?")
31940  end
31941  unless sound_file?("4.aiff")
31942    snd_display("4.aiff not a sound file?")
31943  end
31944  if sound_file?("snd.h")
31945    snd_display("snd.h is a sound file?")
31946  end
31947  ind1 = open_sound("oboe.snd")
31948  save_sound_as("test.snd", ind1)
31949  ind2 = open_sound("test.snd")
31950  unless channels_equal?(ind1, 0, ind2, 0)
31951    snd_display("channels_equal? of copy")
31952  end
31953  unless channels_eql?(ind1, 0, ind2, 0)
31954    snd_display("channels_eql? of copy")
31955  end
31956  pad_channel(framples(ind2, 0), 100)
31957  if channels_equal?(ind1, 0, ind2, 0)
31958    snd_display("channels_equal? of pad")
31959  end
31960  unless channels_eql?(ind1, 0, ind2, 0)
31961    snd_display("channels_eql? of pad")
31962  end
31963  set_sample(50900, 0.1, ind2, 0)
31964  if channels_equal?(ind1, 0, ind2, 0)
31965    snd_display("channels_equal? of pad+set")
31966  end
31967  if channels_eql?(ind1, 0, ind2, 0)
31968    snd_display("channels_eql? of pad+set")
31969  end
31970  unless channels_eql?(ind1, 0, ind2, 0, 0.2)
31971    snd_display("channels_eql? of pad+set .2err")
31972  end
31973  add_comment(1234, "sample 1234", ind1, 0)
31974  comments = show_comments(ind1, 0)
31975  update_time_graph
31976  if comments.null?
31977    snd_display("add_comment failed?")
31978  end
31979  display_db(ind1, 0)
31980  display_samps_in_red(ind1, 0)
31981  update_time_graph
31982  show_greeting(ind1, 0)
31983  update_time_graph
31984  color_samples(highlight_color, 0, 100, ind1, 0)
31985  update_time_graph
31986  power_env_channel(make_power_env([0, 0, 0.325, 1, 1, 32, 2, 0, 32], :duration, 2.0))
31987  update_time_graph
31988  $with_test_motif and show_disk_space(ind1)
31989  update_time_graph
31990  revert_sound(ind1)
31991  make_selection(10000, 20000, ind1, 0)
31992  if selection?
31993    show_selection
31994    vals = x_bounds(ind1, 0)
31995    if vals.length == 2
31996      snd_test_neq(vals[0], 10000.0 / srate(ind1), "show_selection")
31997      snd_test_neq(vals[1], 20000.0 / srate(ind1), "show_selection")
31998    end
31999  else
32000    snd_display("make_selection for show failed?")
32001  end
32002  $graph_hook.add_hook!("test-21-zoom-spectrum", &method(:zoom_spectrum).to_proc)
32003  set_transform_graph?(true, ind1, 0)
32004  ind3 = open_sound("pistol.snd")
32005  overlay_sounds(ind2, ind1, ind3)
32006  update_time_graph(ind2, 0)
32007  $after_graph_hook.reset_hook!
32008  close_sound(ind3)
32009  samples_via_colormap(ind1, 0)
32010  close_sound(ind1)
32011  $graph_hook.remove_hook!("test-21-zoom-spectrum")
32012  close_sound(ind2)
32013  #
32014  ind = new_sound("tmp.snd", 1, 22050, Mus_bfloat, Mus_next, :size, 50)
32015  set_sample(3, 1.0)
32016  filter_channel(vct(0.5, 1.0, 0.5), 3)
32017  unless vequal(res = channel2vct(0, 10), vct(0, 0, 0, 0.5, 1, 0.5, 0, 0, 0, 0))
32018    snd_display("filter_channel (sym 3): %s?", res)
32019  end
32020  undo_edit
32021  filter_channel(vct(0.5, 1.0, 0.25), 3)
32022  unless vequal(res = channel2vct(0, 10), vct(0, 0, 0, 0.5, 1, 0.25, 0, 0, 0, 0))
32023    snd_display("filter_channel (3): %s?", res)
32024  end
32025  undo_edit
32026  filter_channel(vct(0.5, 1.0, 1.0, 0.5), 4)
32027  unless vequal(res = channel2vct(0, 10), vct(0, 0, 0, 0.5, 1, 1, 0.5, 0, 0, 0))
32028    snd_display("filter_channel (sym 4): %s?", res)
32029  end
32030  undo_edit
32031  filter_channel(vct(0.5, 1.0, 1.0, 0.25), 4)
32032  unless vequal(res = channel2vct(0, 10), vct(0, 0, 0, 0.5, 1, 1, 0.25, 0, 0, 0))
32033    snd_display("filter_channel (4): %s?", res)
32034  end
32035  undo_edit
32036  close_sound(ind)
32037  #
32038  ind = new_sound("tmp.snd", 1, 22050, Mus_bfloat, Mus_next, false, 100)
32039  set_sample(10, 0.5)
32040  filter_sound(vct(1, 0, 1), 3)
32041  unless vequal(res = channel2vct(5, 10), vct(0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0))
32042    snd_display("filter_sound 1 0 1: %s?", res)
32043  end
32044  undo_edit
32045  filter_channel(vct(1, 0, 1), 3)
32046  unless vequal(res = channel2vct(5, 10), vct(0, 0, 0, 0, 0, 0.5, 0, 0.5, 0, 0))
32047    snd_display("filter_channel (v) 1 0 1: %s?", res)
32048  end
32049  undo_edit
32050  filter_sound([0, 1, 1, 1], 100)
32051  coeffs = make_fir_coeffs(100, Vct.new(100, 0.5))
32052  data = channel2vct(10, 100)
32053  data.zip(coeffs) do |val, coeff|
32054    if fneq(val, coeff)
32055      snd_display("coeffs [0, 1, 1, 1]: %s %s?", val, coeff)
32056      break
32057    end
32058  end
32059  undo_edit
32060  filter_sound([0, 1, 1, 1], 1000)
32061  unless vequal(res = channel2vct(5, 10), vct(0, 0, 0, 0, 0, 0.5, 0, 0, 0, 0))
32062    snd_display("filter_sound 1 (1000): %s?", res)
32063  end
32064  undo_edit
32065  make_selection(5, 15)
32066  filter_selection([0, 1, 1, 1], 100)
32067  if (res = edit_fragment 2) != ["filter_selection([0.000, 1.000, 1.000, 1.000], 100", "set", 5, 11]
32068    snd_display("filter_selection truncated: %s", res)
32069  end
32070  undo_edit
32071  filter_selection([0, 1, 1, 1], 100, false)
32072  if (res = edit_fragment 2) != ["filter_selection([0.000, 1.000, 1.000, 1.000], 100", "set", 5,111]
32073    snd_display("filter_selection not truncated: %s", res)
32074  end
32075  unless vequal(res = channel2vct(50, 10),
32076                vct(-0.016, 0.018, -0.021, 0.024, -0.029, 0.035, -0.045, 0.064, -0.106, 0.318))
32077    snd_display("filter_selection no trunc: %s?", res)
32078  end
32079  undo_edit
32080  filter_selection([0, 1, 1, 1], 1000, true)
32081  if (res = edit_fragment 2) != ["filter_selection([0.000, 1.000, 1.000, 1.000], 1000", "set", 5,11]
32082    snd_display("filter_selection truncated (1000): %s", res)
32083  end
32084  if fneq(maxamp, 0.0)
32085    snd_display("filter_selection 1000 untrunc: %s?", maxamp)
32086  end
32087  undo_edit
32088  filter_selection([0, 1, 1, 1], 1000, false)
32089  if (res = edit_fragment 2) != ["filter_selection([0.000, 1.000, 1.000, 1.000], 1000",
32090                                 "set", 5, 1011]
32091    snd_display("filter_selection not truncated (1000): %s", res)
32092  end
32093  if fneq(maxamp, 0.318)
32094    snd_display("filter_selection 1000 no trunc: %s?", maxamp)
32095  end
32096  unless vequal(res = channel2vct(505, 10),
32097                vct(0.035, -0.045, 0.064, -0.106, 0.318, 0.318, -0.106, 0.064, -0.045, 0.035))
32098    snd_display("filter_selection 1000 no trunc: %s?", res)
32099  end
32100  undo_edit
32101  filter_channel([0, 1, 1, 1], 10)
32102  unless vequal(res = channel2vct(10, 10),
32103                vct(0.008, -0.025, 0.050, -0.098, 0.316, 0.316, -0.098, 0.050, -0.025, 0.008))
32104    snd_display("filter_channel 10: %s?", res)
32105  end
32106  undo_edit
32107  filter_channel([0, 1, 1, 1], 1000)
32108  unless vequal(res = channel2vct(5, 10), vct(0, 0, 0, 0, 0, 0.5, 0, 0, 0, 0))
32109    snd_display("filter_channel 1 (1000): %s?", res)
32110  end
32111  undo_edit
32112  filter_channel([0, 1, 1, 0], 10)
32113  unless vequal(channel2vct(0, 30),
32114                vct(0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
32115                    0.005, 0.010, 0.006, 0.038, 0.192, 0.192, 0.038, 0.006, 0.010, 0.005,
32116                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
32117    snd_display("filter_channel lp: %s %s %s?",
32118                channel2vct(0, 10),  channel2vct(10, 10),  channel2vct(20, 10))
32119  end
32120  undo_edit
32121  filter_channel([0, 1, 1, 0], 10, 0, 20, false, false, false, false)
32122  unless vequal(channel2vct(0, 30),
32123                vct(0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
32124                    0.005, 0.010, 0.006, 0.038, 0.192, 0.192, 0.038, 0.006, 0.010, 0.005,
32125                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
32126    snd_display("filter_channel lp no trunc: %s %s %s?",
32127                channel2vct(0, 10),  channel2vct(10, 10),  channel2vct(20, 10))
32128  end
32129  undo_edit
32130  close_sound(ind)
32131  #
32132  ind = new_sound("tmp.snd", 2, 22050, Mus_bfloat, Mus_next, false, 100)
32133  set_sample(10, 0.5)
32134  set_sample(5, -0.5, ind, 1)
32135  set_sync(1, ind)
32136  filter_sound(vct(1, 0, 1), 3)
32137  unless vequal(res = channel2vct(5, 10, ind, 0), vct(0, 0, 0,0, 0, 0.5, 0, 0.5, 0, 0))
32138    snd_display("(2) filter_sound 1 0 1: %s?", res)
32139  end
32140  unless vequal(res = channel2vct(0, 10, ind, 1), vct(0, 0, 0,0, 0, -0.5, 0, -0.5, 0, 0))
32141    snd_display("(2) filter_sound 1 0 2: %s?", res)
32142  end
32143  undo_edit
32144  filter_sound([0, 1, 1, 1], 1000)
32145  unless vequal(res = channel2vct(5, 10, ind, 0), vct(0, 0, 0,0, 0, 0.5, 0, 0, 0, 0))
32146    snd_display("(2) filter_sound 1 (1000): %s?", res)
32147  end
32148  unless vequal(res = channel2vct(0, 10, ind, 1), vct(0, 0, 0,0, 0, -0.5, 0, 0, 0, 0))
32149    snd_display("(2) filter_sound 2 (1000): %s?", res)
32150  end
32151  undo_edit
32152  make_selection(0, 20)
32153  filter_selection(vct(1, 0, 1), 3)
32154  unless vequal(res = channel2vct(5, 10, ind, 0), vct(0, 0, 0,0, 0, 0.5, 0, 0.5, 0, 0))
32155    snd_display("(2) filter_selection 1 0 1: %s?", res)
32156  end
32157  unless vequal(res = channel2vct(0, 10, ind, 1), vct(0, 0, 0,0, 0, -0.5, 0, -0.5, 0, 0))
32158    snd_display("(2) filter_selection 1 0 2: %s?", res)
32159  end
32160  undo_edit
32161  set_sync(0, ind)
32162  filter_selection(vct(1, 0, 1), 3)
32163  unless vequal(res = channel2vct(5, 10, ind, 0), vct(0, 0, 0,0, 0, 0.5, 0, 0.5, 0, 0))
32164    snd_display("(2) filter_selection 1 0 1 (no sync): %s?", res)
32165  end
32166  unless vequal(res = channel2vct(0, 10, ind, 1), vct(0, 0, 0,0, 0, -0.5, 0, -0.5, 0, 0))
32167    snd_display("(2) filter_selection 1 0 2 (no sync): %s?", res)
32168  end
32169  undo_edit(1, ind, 0)
32170  undo_edit(1, ind, 1)
32171  if (res = edit_position(ind, 0)) != 1
32172    snd_display("edpos filter_selection undo 0: %s?", res)
32173  end
32174  if (res = edit_position(ind, 1)) != 1
32175    snd_display("edpos filter_selection undo 1: %s?", res)
32176  end
32177  filter_sound(vct(1, 0, 1), 3)
32178  unless vequal(res = channel2vct(5, 10, ind, 0), vct(0, 0, 0,0, 0, 0.5, 0, 0.5, 0, 0))
32179    snd_display("(2) filter_sound 1 0 1 (no sync): %s?", res)
32180  end
32181  unless vequal(res = channel2vct(0, 10, ind, 1), vct(0, 0, 0,0, 0, -0.5, 0, 0, 0, 0))
32182    snd_display("(2) filter_sound 1 0 2 (no sync): %s?", res)
32183  end
32184  undo_edit(1, ind, 0)
32185  filter_channel([0, 1, 1, 0], 10, false, false, ind, 1)
32186  unless vequal(channel2vct(0, 30, ind, 1),
32187                vct(0, 0, 0, 0, 0,
32188                    -0.005, -0.010, -0.006, -0.038, -0.192, -0.192, -0.038, -0.006, -0.010, -0.005,
32189                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
32190    snd_display("filter_channel lp:\n# %s\n# %s\n# %s",
32191                channel2vct(0, 10, ind, 1),
32192                channel2vct(10, 10, ind, 1),
32193                channel2vct(20, 10, ind, 1))
32194  end
32195  undo_edit(1, ind, 1)
32196  close_sound(ind)
32197  #
32198  ind = new_sound("tmp.snd", 1, 22050, Mus_bshort, Mus_next, :size, 100)
32199  set_sample(10, 0.5)
32200  set_sample(20, -0.5)
32201  scale_to(1.0)
32202  if fneq(sample(10), 0.999)
32203    snd_display("scale_to 1.0 Mus_bshort (10): %s?", sample(10))
32204  end
32205  if fneq(sample(20), -0.999)
32206    snd_display("scale_to 1.0 Mus_bshort (20): %s?", sample(20))
32207  end
32208  close_sound(ind)
32209  ind = new_sound("tmp.snd", 1, 22050, Mus_byte, Mus_next, :size, 100)
32210  set_sample(10, 0.5)
32211  set_sample(20, -0.5)
32212  scale_to(1.0)
32213  if fneq(sample(10), 0.992)
32214    snd_display("scale_to 1.0 Mus_byte (10): %s?", sample(10))
32215  end
32216  if fneq(sample(20), -0.992)
32217    snd_display("scale_to 1.0 Mus_byte (20): %s?", sample(20))
32218  end
32219  close_sound(ind)
32220  #
32221  set_transform_graph_type(Graph_once)
32222  set_fft_window(6)
32223  set_show_y_zero(false)
32224  set_show_transform_peaks(false)
32225  set_fft_log_frequency(false)
32226  set_fft_log_magnitude(false)
32227  set_with_verbose_cursor(false)
32228  set_show_grid(false)
32229  set_show_sonogram_cursor(false)
32230  set_with_tracking_cursor(false)
32231  set_show_controls(false)
32232  set_speed_control_tones(12)
32233  set_wavelet_type(0)
32234  set_spectrum_start(0.0)
32235  set_spectro_hop(4)
32236  set_fft_window_alpha(0.0)
32237  set_fft_window_beta(0.0)
32238  ind_1 = new_sound("test-1.snd", 1, 22050, Mus_lfloat, Mus_next,
32239                    "mono testing", 100)
32240  ind_2 = new_sound("test-2.snd", 2, 44100, Mus_bshort, Mus_aifc,
32241                    "stereo testing", 300)
32242  [[:srate,                 48000,    :st_equal?, :st_eql?,  :swap],
32243   [:sample_type,           Mus_byte, :st_equal?, :st_eql?,  :swap],
32244   [:data_location,         123,      :st_equal?, :st_eql?,  :swap],
32245   [:data_size,             12348,    :st_equal?, :st_eql?,  :swap],
32246   [:framples,              12348,    :st_equal?, :st_eql?,  true],
32247   [:sync,                  2,        :st_equal?, :st_eql?,  true],
32248   [:channels,              0,        :st_equal?, :st_eql?,  false],
32249   [:chans,                 0,        :st_equal?, :st_eql?,  false],
32250   [:header_type,           0,        :st_equal?, :st_eql?,  false],
32251   [:amp_control,           0.5,      :ffequal?,  :vfequal?, true],
32252   [:contrast_control,      0.5,      :ffequal?,  :vfequal?, true],
32253   [:expand_control,        0.5,      :ffequal?,  :vfequal?, true],
32254   [:speed_control,         0.5,      :ffequal?,  :vfequal?, true],
32255   [:reverb_control_length, 0.5,      :ffequal?,  :vfequal?, true],
32256   [:reverb_control_scale,  0.5,      :ffequal?,  :vfequal?, true],
32257   [:contrast_control?,     true,     :st_eql?,   :st_eql?,  true],
32258   [:expand_control?,       true,     :st_eql?,   :st_eql?,  true],
32259   [:filter_control?,       true,     :st_eql?,   :st_eql?,  true],
32260   [:reverb_control?,       true,     :st_eql?,   :st_eql?,  true],
32261   [:read_only,             true,     :st_eql?,   :st_eql?,  true],
32262   [:file_name,             nil,      :st_equal?, :st_eql?,  false],
32263   [:short_file_name,       nil,      :st_equal?, :st_eql?,  false],
32264   [:comment,               nil,      :st_equal?, :st_eql?,  false]
32265  ].each do |func, new_val, eq_func, leq_func, settable|
32266    test_sound_func_1(func, ind_1, ind_2, new_val,
32267                      eq_func, leq_func, settable, false, false)
32268  end
32269  save_controls(true)
32270  restore_controls(true)
32271  reset_controls(true)
32272  close_sound(true)
32273  if sounds != nil
32274    snd_display("sounds after close_sound(true): %s?", sounds)
32275  end
32276  #
32277  # snd chn cases
32278  #
32279  ind_1 = new_sound("test-1.snd", 1, 22050, Mus_bfloat, Mus_next,
32280                    "mono testing", 100)
32281  ind_2 = new_sound("test-2.snd", 2, 44100, Mus_bshort, Mus_aifc,
32282                    "stereo testing", 300)
32283  set_sample(1, 0.1, ind_1, 0)
32284  set_sample(2, 0.2, ind_2, 0)
32285  set_sample(3, 0.3, ind_2, 1)
32286  vals = [[:min_dB,                  -100.0,            :ffequal?,  :vequal?, true, true],
32287          [:x_position_slider,       0.1,               :ffequal?,  :vequal?, true, false],
32288          [:y_position_slider,       0.5,               :ffequal?,  :vequal?, true, false],
32289          [:x_zoom_slider,           0.2,               :ffequal?,  :vequal?, true, false],
32290          [:y_zoom_slider,           0.2,               :ffequal?,  :vequal?, true, false],
32291          [:fft_window_alpha,        0.5,               :ffequal?,  :vequal?, true, true],
32292          [:fft_window_beta,         0.5,               :ffequal?,  :vequal?, true, true],
32293          [:spectrum_end,            0.2,               :ffequal?,  :vequal?, true, true],
32294          [:spectrum_start,          0.1,               :ffequal?,  :vequal?, true, true],
32295          [:spectro_x_angle,         10.0,              :ffequal?,  :vequal?, true, true],
32296          [:spectro_x_scale,         0.2,               :ffequal?,  :vequal?, true, true],
32297          [:spectro_y_angle,         10.0,              :ffequal?,  :vequal?, true, true],
32298          [:spectro_y_scale,         0.1,               :ffequal?,  :vequal?, true, true],
32299          [:spectro_z_angle,         10.0,              :ffequal?,  :vequal?, true, true],
32300          [:spectro_z_scale,         0.3,               :ffequal?,  :vequal?, true, true],
32301          [:beats_per_minute,        100.0,             :ffequal?,  :vequal?, true, true],
32302          [:spectro_hop,             10,                :st_equal?, :st_eql?, true, true],
32303          [:cursor,                  50,                :st_equal?, :st_eql?, true, false],
32304          [:cursor_style,            1,                 :st_equal?, :st_eql?, true, true],
32305          [:cursor_size,             10,                :st_equal?, :st_eql?, true, true],
32306          [:framples,                  50,                :st_equal?, :st_eql?, true, false],
32307          [:zero_pad,                1,                 :st_equal?, :st_eql?, true, true],
32308          [:wavelet_type,            1,                 :st_equal?, :st_eql?, true, true],
32309          [:time_graph_type,         Graph_as_wavogram, :st_equal?, :st_eql?, true, true],
32310          [:wavo_hop,                10,                :st_equal?, :st_eql?, true, true],
32311          [:wavo_trace,              10,                :st_equal?, :st_eql?, true, true],
32312          [:transform_size,          64,                :st_equal?, :st_eql?, true, true],
32313          [:transform_graph_type,    1,                 :st_equal?, :st_eql?, true, true],
32314          [:fft_window,              1,                 :st_equal?, :st_eql?, true, true],
32315          [:transform_normalization, 2,                 :st_equal?, :st_eql?, true, true],
32316          [:max_transform_peaks,     10,                :st_equal?, :st_eql?, true, true],
32317          [:dot_size,                10,                :st_equal?, :st_eql?, true, true],
32318          [:show_axes,               2,                 :st_equal?, :st_eql?, true, true],
32319          [:transform_graph?,        true,              :st_equal?, :st_eql?, true, false],
32320          [:time_graph?,             false,             :st_equal?, :st_eql?, true, false],
32321          [:lisp_graph?,             true,              :st_equal?, :st_eql?, true, false],
32322          [:squelch_update,          true,              :st_equal?, :st_eql?, true, false],
32323          [:show_y_zero,             true,              :st_equal?, :st_eql?, true, true],
32324          [:show_grid,               true,              :st_equal?, :st_eql?, true, true],
32325          [:grid_density,            0.5,               :ffequal?,  :vequal?, true, true],
32326          [:show_sonogram_cursor,    true,              :st_equal?, :st_eql?, true, true],
32327          [:show_marks,              false,             :st_equal?, :st_eql?, true, true],
32328          [:show_transform_peaks,    true,              :st_equal?, :st_eql?, true, true],
32329          [:fft_log_frequency,       true,              :st_equal?, :st_eql?, true, true],
32330          [:fft_log_magnitude,       true,              :st_equal?, :st_eql?, true, true],
32331          [:show_mix_waveforms,      false,             :st_equal?, :st_eql?, true, true],
32332          [:with_verbose_cursor,     true,              :st_equal?, :st_eql?, true, true]]
32333  vals.each do |func, new_val, eq_func, leq_func, settable, global|
32334    test_sound_func_1(func, ind_1, ind_2, new_val,
32335                      eq_func, leq_func, settable, true, global)
32336    test_channel_func_1(func, ind_1, ind_2, new_val,
32337                        eq_func, leq_func, settable, global)
32338  end
32339  update_time_graph(true, true)
32340  update_transform_graph(true, true)
32341  update_lisp_graph(true, true)
32342  close_sound(false)
32343  close_sound(false)
32344  if sounds != nil
32345    snd_display("sounds after close_sound(false) twice: %s?", sounds)
32346  end
32347  #
32348  ind_1 = new_sound("test-1.snd", 1, 22050, Mus_bfloat, Mus_next,
32349                    "mono testing", 100)
32350  ind_2 = new_sound("test-2.snd", 2, 44100, Mus_bshort, Mus_aifc,
32351                    "stereo testing", 300)
32352  # test_sound_func_2
32353  [[:filter_control_in_dB,         true,                      :st_eql?,   :st_eql?],
32354   [:filter_control_in_hz,         true,                      :st_eql?,   :st_eql?],
32355   [:show_controls,                true,                      :st_eql?,   :st_eql?],
32356   [:speed_control_tones,          14,                        :st_equal?, :st_eql?],
32357   [:speed_control_style,          Speed_control_as_semitone, :st_equal?, :st_eql?],
32358   [:filter_control_order,         14,                        :st_equal?, :st_eql?],
32359   [:expand_control_length,        0.25,                      :ffequal?,  :vequal?],
32360   [:expand_control_ramp,          0.25,                      :ffequal?,  :vequal?],
32361   [:expand_control_hop,           0.25,                      :ffequal?,  :vequal?],
32362   [:expand_control_jitter,        0.25,                      :ffequal?,  :vequal?],
32363   [:contrast_control_amp,         0.25,                      :ffequal?,  :vequal?],
32364   [:reverb_control_feedback,      0.25,                      :ffequal?,  :vequal?],
32365   [:reverb_control_lowpass,       0.25,                      :ffequal?,  :vequal?],
32366   [:reverb_control_decay,         0.25,                      :ffequal?,  :vequal?],
32367   [:amp_control_bounds,           [0.0, 2.0],                :vequal?,   :st_vequal_2],
32368   [:contrast_control_bounds,      [0.0, 2.0],                :vequal?,   :st_vequal_2],
32369   [:expand_control_bounds,        [0.1, 2.0],                :vequal?,   :st_vequal_2],
32370   [:speed_control_bounds,         [0.1, 2.0],                :vequal?,   :st_vequal_2],
32371   [:reverb_control_length_bounds, [0.0, 2.0],                :vequal?,   :st_vequal_2],
32372   [:reverb_control_scale_bounds,  [0.0, 2.0],                :vequal?,   :st_vequal_2]
32373  ].each do |func, new_val, eq_func, leq_func|
32374    old_global_val = snd_func(func)
32375    old_vals = snd_func(func, true)
32376    old_1 = snd_func(func, ind_1)
32377    old_2 = snd_func(func, ind_2)
32378    sel_snd = selected_sound
32379    unsel_snd = sel_snd == ind_1 ? ind_2 : ind_1
32380    unless method(leq_func).call(old_vals, [old_1, old_2]) or
32381        method(leq_func).call(old_vals, [old_2, old_1])
32382      snd_display(snd_format_neq(old_vals, [old_1, old_2], "%s sound_func true", func))
32383    end
32384    #
32385    set_snd_func(func, new_val)
32386    res1 = snd_func(func)
32387    res2 = snd_func(func, sel_snd)
32388    res3 = snd_func(func, unsel_snd)
32389    snd_test_any_neq(res1, new_val, eq_func, "set_%s global no arg", func)
32390    snd_test_any_neq(res1, res2, eq_func, "set_%s global no arg sel", func)
32391    snd_test_any_neq(res1, res3, eq_func, "set_%s global no arg unsel", func)
32392    res1 = snd_func(func, true)
32393    unless method(leq_func).call(res1, [res2, res3]) or method(leq_func).call(res1, [res3, res2])
32394      snd_display(snd_format_neq(res1, [res2, res3], "set_%s true", func))
32395    end
32396    set_snd_func(func, old_global_val)
32397    set_snd_func(func, new_val, ind_1)
32398    res1 = snd_func(func, true)
32399    res2 = snd_func(func, ind_1)
32400    res3 = snd_func(func, ind_2)
32401    snd_test_any_neq(res2, new_val, eq_func, "set_%s arg", func)
32402    snd_test_any_eq(res3, new_val, eq_func, "set_%s arg (2)", func)
32403    unless method(leq_func).call(res1, [res2, res3]) or method(leq_func).call(res1, [res3, res2])
32404      snd_display(snd_format_neq(res1, [res2, res3], "set_%s arg", func))
32405    end
32406    set_snd_func(func, old_1, ind_1)
32407    set_snd_func(func, new_val, true)
32408    res1 = snd_func(func, true)
32409    res2 = snd_func(func, ind_1)
32410    res3 = snd_func(func, ind_2)
32411    snd_test_any_neq(res1, [new_val, new_val], leq_func, "set_%s arg true", func)
32412    snd_test_any_neq(res2, new_val, eq_func, "set_%s arg true", func)
32413    snd_test_any_neq(res3, new_val, eq_func, "set_%s arg true (2)", func)
32414    res1 = snd_func(func)
32415    snd_test_any_eq(res1, new_val, eq_func, "set_%s overwrote global", func)
32416    set_snd_func(func, old_1, ind_1)
32417    set_snd_func(func, old_2, ind_2)
32418    res2 = snd_func(func, ind_1)
32419    res3 = snd_func(func, ind_2)
32420    snd_test_any_neq(res2, old_1, eq_func, "set_%s arg true old", func)
32421    snd_test_any_neq(res3, old_2, eq_func, "set_%s arg true old (2)", func)
32422  end
32423  close_sound(true)
32424end
32425
32426def test_21_02
32427  set_remember_sound_state(true)
32428  ind = open_sound("oboe.snd")
32429  set_transform_graph?(true, ind, 0)
32430  set_show_transform_peaks(true, ind, 0)
32431  set_show_y_zero(true, ind, 0)
32432  close_sound(ind)
32433  ind = open_sound("oboe.snd")
32434  res1 = transform_graph?(ind, 0)
32435  res2 = show_transform_peaks(ind, 0)
32436  res3 = show_y_zero(ind, 0)
32437  if (not res1.kind_of?(TrueClass)) or
32438      (not res2.kind_of?(TrueClass)) or
32439      (not res3.kind_of?(TrueClass))
32440    snd_display("remember_sound_state: %s %s %s?", res1.inspect, res2.inspect, res3.inspect)
32441  end
32442  close_sound(ind)
32443  reset_almost_all_hooks
32444  set_remember_sound_state(false)
32445  #
32446  map_sound_files do |n|
32447    if mus_sound_duration(n) > 1000.0
32448      snd_display("%s is pretty long! %s", n, mus_sound_duration(n))
32449    end
32450    mus_sound_forget(n)
32451  end
32452  map_sound_files($sf_dir) do |n|
32453    Snd.catch do
32454      if mus_sound_duration(n) > 1000.0
32455        snd_display("%s is pretty long! %s", n, mus_sound_duration(n))
32456      end
32457      mus_sound_forget(n)
32458    end
32459  end
32460  #
32461  snd = new_sound("test.snd")
32462  pad_channel(0, 20)
32463  map_channel($init_channel)
32464  env_channel_with_base([0, 0, 1, 1], 1.0)
32465  snd_test_neq(channel2vct(0, 20),
32466               vct(0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45,
32467                   0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95),
32468               "env_chan 1.0")
32469  undo_edit
32470  env_channel_with_base([0, 0, 1, 1, 2, 1, 3, 0], 0.0)
32471  snd_test_neq(channel2vct(0, 20),
32472               vct(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0,
32473                   1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0),
32474               "env_chan 0.0")
32475  undo_edit
32476  env_channel_with_base([0, 0, 1, 1], 100.0)
32477  snd_test_neq(channel2vct(0, 20),
32478               vct(0.0, 0.003, 0.006, 0.010, 0.015, 0.022, 0.030, 0.041, 0.054, 0.070,
32479                   0.091, 0.117, 0.150, 0.191, 0.244, 0.309, 0.392, 0.496, 0.627, 0.792),
32480               "env_chan 100.0")
32481  undo_edit
32482  env_channel_with_base([0, 0, 1, 1], 0.01)
32483  snd_test_neq(channel2vct(0, 20),
32484               vct(0.0, 0.208, 0.373, 0.504, 0.608, 0.691, 0.756, 0.809, 0.850, 0.883,
32485                   0.909, 0.930, 0.946, 0.959, 0.970, 0.978, 0.985, 0.990, 0.994, 0.997),
32486               "env_chan 0.01")
32487  undo_edit
32488  env_channel_with_base([0, 0, 1, 1], 1.0, 5, 10)
32489  snd_test_neq(channel2vct(0, 20),
32490               vct(1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.111, 0.222, 0.333, 0.444,
32491                   0.556, 0.667, 0.778, 0.889, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0),
32492               "env_chan 1.0 seg")
32493  undo_edit
32494  env_channel_with_base([0, 0, 1, 1, 2, 1, 3, 0], 0.0, 5, 10)
32495  snd_test_neq(channel2vct(0, 20),
32496               vct(1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
32497                   1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0),
32498               "env_chan 0.0 seg")
32499  undo_edit
32500  env_channel_with_base([0, 0, 1, 1], 100.0, 5, 10)
32501  snd_test_neq(channel2vct(0, 20),
32502               vct(1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.007, 0.018, 0.037, 0.068,
32503                   0.120, 0.208, 0.353, 0.595, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0),
32504               "env_chan 100.0 seg")
32505  undo_edit
32506  env_channel_with_base([0, 0, 1, 1], 0.01, 5, 10)
32507  snd_test_neq(channel2vct(0, 20),
32508               vct(1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.405, 0.647, 0.792, 0.880,
32509                   0.932, 0.963, 0.982, 0.993, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0),
32510               "env_chan 0.01 seg")
32511  undo_edit
32512  close_sound(snd)
32513  #
32514  ind1 = open_sound("now.snd")
32515  ind2 = open_sound("oboe.snd")
32516  [[:channel_mean,          5.02560673308833e-5],
32517   [:channel_total_energy,  50.7153476262465],
32518   [:channel_average_power, 0.00155078578803922],
32519   [:channel_rms,           0.039380017623653],
32520   [:channel_norm,          7.12147088923675],
32521   [:channel_variance,      50.7153476237207]].each do |func_sym, req|
32522    snd_test_neq(snd_func(func_sym, ind1, 0), req, "%s", func_sym)
32523  end
32524  [[2, 7.12147088923675],
32525   [1, 775.966033935547]].each do |arg, req|
32526    snd_test_neq(channel_lp(arg, ind1, 0), req, "channel_lp %d", arg)
32527  end
32528  snd_test_neq(channel2_inner_product(ind1, 0, ind2, 0), 1.52892031334341, "channel2_inner_product")
32529  snd_test_neq(channel2_angle(ind1, 0, ind2, 0), 1.55485084385627, "channel2_angle")
32530  snd_test_neq(channel2_orthogonal?(ind1, 0, ind2, 0), false, "channel2_orthogonal?")
32531  snd_test_neq(channel2_coefficient_of_projection(ind1, 0, ind2, 0),
32532               0.0301470932351876,
32533               "channel2_coefficient_of_projection")
32534  close_sound(ind1)
32535  ind1 = open_sound("oboe.snd")
32536  scale_by(0.99, ind1, 0)
32537  snd_test_neq(channel_distance(ind1, 0, ind2, 0), 0.1346, "channel_distance")
32538  [ind1, ind2].apply(:close_sound)
32539  #
32540  file_copy("oboe.snd", "test.snd")
32541  ind = open_sound("test.snd")
32542  mx = maxamp(ind, 0)
32543  chns = channels(ind)
32544  sr = srate(ind)
32545  fr = framples(ind, 0)
32546  with_local_hook($update_hook,
32547                  lambda do |orig_ind|
32548                    lambda do |new_ind|
32549                      ind = new_ind
32550                    end
32551                  end) do
32552    10.times do |i|
32553      v = channel2vct
32554      array2file("test.snd", v, fr, sr, chns)
32555      update_sound(ind)
32556      snd_test_neq(maxamp(ind, 0), mx, "update_sound looped maxamp %d", i)
32557      snd_test_neq(chans(ind), chns, "update_sound looped chans")
32558      snd_test_neq(srate(ind), sr, "update_sound looped srate")
32559      snd_test_neq(framples(ind), fr, "update_sound looped framples")
32560    end
32561    old_ind = open_sound("oboe.snd")
32562    diff = 0.0
32563    rd = make_sampler(0, ind, 0)
32564    home = sampler_home(rd)
32565    scan_channel(lambda do |y|
32566                   if (cd = (y - rd.call).abs) > diff
32567                     diff = cd
32568                   end
32569                   false
32570                 end, 0, fr, old_ind, 0)
32571    snd_test_neq(diff, 0.0, "update_sound looped overall max diff old_ind %s rd %s", old_ind, home)
32572    close_sound(old_ind)
32573  end
32574  close_sound(ind)
32575  #
32576  delete_file("test.snd")
32577  ind = open_sound("oboe.snd")
32578  data = channel2vct
32579  5.times do |i|
32580    array2file("test.snd", data, framples(ind), 22050, 1)
32581    file2array("test.snd", 0, 0, framples, data)
32582    diff = 0.0
32583    ctr = 0
32584    scan_channel(lambda do |y|
32585                   if (cd = (y - data[ctr]).abs) > diff
32586                     diff = cd
32587                   end
32588                   ctr += 1
32589                   false
32590                 end)
32591    snd_test_neq(diff, 0.0, "array2file2array overall max diff")
32592  end
32593  #
32594  set_colormap_size(16)
32595  set_transform_size(8, ind, 0)
32596  set_transform_graph_type(Graph_as_sonogram, ind, 0)
32597  set_transform_graph?(true, ind, 0)
32598  update_transform_graph
32599  set_x_bounds([0.0, 0.04])
32600  update_time_graph
32601  update_transform_graph
32602  set_zoom_focus_style(lambda do |s, c, z, x0, x1, range| 0 end)
32603  unless proc?(res = zoom_focus_style)
32604    snd_display("zoom_focus_style as func: %s?", res)
32605  end
32606  set_zoom_focus_style(Zoom_focus_right)
32607  snd_test_neq(zoom_focus_style(), Zoom_focus_right, "unset zoom_focus_style as func")
32608  close_sound(ind)
32609  #
32610  delete_files("test.snd", "fmv.snd")
32611  rdin = false
32612  rdout = false
32613  len = mus_sound_framples("oboe.snd")
32614  types = [Mus_riff, Mus_aifc, Mus_next, Mus_nist, Mus_ircam]
32615  forms = [Mus_lshort, Mus_bshort, Mus_b24int, Mus_l24int, Mus_bint]
32616  file_copy("oboe.snd", "fmv.snd")
32617  types.zip(forms) do |tp, fm|
32618    rdin = make_readin(:file, "fmv.snd")
32619    rdout = make_sample2file("test.snd", 1, fm, tp)
32620    len.times do |k| sample2file(rdout, k, 0, readin(rdin)) end
32621    rdout.close
32622    rdin.close
32623    file_copy("test.snd", "fmv.snd")
32624    delete_file("test.snd")
32625    ["test.snd", "fmv.snd"].apply(:mus_sound_forget)
32626  end
32627  diff = 0.0
32628  ctr = 0
32629  ind1 = open_sound("oboe.snd")
32630  ind2 = make_file2sample("fmv.snd")
32631  scan_channel(lambda do |y|
32632                 if (cd = (y - file2sample(ind2, ctr, 0)).abs) > diff
32633                   diff = cd
32634                 end
32635                 ctr += 1
32636                 false
32637               end)
32638  snd_test_neq(diff, 0.0, "file2sample2file overall max diff")
32639  close_sound(ind1)
32640  #
32641  ind = open_sound("1a.snd")
32642  mx = maxamp()
32643  [["scale_by", lambda do
32644      scale_by(2.0)
32645    end],
32646   ["scale_channel", lambda do
32647      scale_channel(2.0)
32648    end],
32649   ["map_channel", lambda do
32650      map_channel(lambda do |y| y * 2.0 end)
32651    end],
32652   ["set_maxamp", lambda do
32653      set_maxamp(2 * maxamp)
32654    end],
32655   ["env_sound", lambda do
32656      env_sound([0, 2, 1, 2])
32657    end],
32658   ["env_channel", lambda do
32659      env_channel(make_env([0, 1, 1, 1], :scaler, 2.0, :length, framples))
32660    end],
32661   ["clm_channel", lambda do
32662      clm_channel(make_one_zero(:a0, 2.0, :a1, 0.0))
32663    end],
32664   ["filter_channel", lambda do
32665      filter_channel(vct(2.0), 1)
32666    end],
32667   ["vct2channel", lambda do
32668      vct2channel(channel2vct.scale(2.0), 0)
32669    end],
32670   ["mix_selection", lambda do
32671      select_all
32672      mix_selection(0)
32673    end],
32674   ["scale_selection_by", lambda do
32675      select_all
32676      scale_selection_by(2.0)
32677    end],
32678   ["mix", lambda do
32679      save_sound_as("temp.snd")
32680      mix("temp.snd", 0)
32681      delete_file("temp.snd")
32682    end],
32683   ["convolve", lambda do
32684      flt = Vct.new(8)
32685      flt[0] = 2.0
32686      cnv = make_convolve(:filter, flt)
32687      sf = make_sampler(0)
32688      map_channel(lambda do |y| convolve(cnv, lambda do |dir| read_sample(sf) end) end)
32689    end],
32690   ["fft", lambda do
32691      len = framples
32692      fsize = 2 ** (log(len) / log(2)).ceil
32693      rl = channel2vct(0, fsize)
32694      im = Vct.new(fsize)
32695      mus_fft(rl, im, fsize)
32696      mus_fft(rl, im, fsize)
32697      mus_fft(rl, im, fsize)
32698      mus_fft(rl, im, fsize)
32699      vct2channel(rl.scale(2.0 / (fsize * fsize)), 0, len)
32700    end],
32701   ["set_samples", lambda do
32702      set_squelch_update(true)
32703      100.times do |i|
32704        set_sample(i, 2.0 * sample(i))
32705      end
32706      set_squelch_update(false)
32707    end],
32708   ["coroutines", lambda do
32709      set_squelch_update(true)
32710      make_scaler = lambda do |start, dur|
32711        ctr = start
32712        us = lambda do |them|
32713          set_sample(ctr, 2.0 * sample(ctr))
32714          ctr += 2
32715          if ctr <= dur
32716            them.call(us)
32717          end
32718        end
32719        us
32720      end
32721      make_scaler.call(0, 100).call(make_scaler.call(1, 100))
32722      set_squelch_update(false)
32723    end]].each do |name, func|
32724    func.call
32725    next if name == "set_samples"
32726    next if name == "coroutines"
32727    snd_test_neq(maxamp() / mx, 2.0, "silly scalers %s", name)
32728    revert_sound
32729  end
32730  close_sound(ind)
32731end
32732
32733def test_21
32734  test_21_00 if $with_test_gui
32735  test_21_02
32736end
32737
32738# ---------------- test 23: with-sound ----------------
32739
32740require "clm-ins"
32741
32742def bigbird_2(start, dur, freq,
32743              freqskew, amp, freq_envelope, amp_envelope, partials)
32744  gls_env = make_env(:envelope, freq_envelope,
32745                     :scaler, hz2radians(freqskew),
32746                     :duration, dur)
32747  os = make_oscil(:frequency, freq)
32748  amp_env = make_env(:envelope, amp_envelope, :scaler, amp, :duration, dur)
32749  coeffs = partials2polynomial(normalize_partials(partials))
32750  run_instrument(start, dur) do
32751    env(amp_env) * polynomial(coeffs, oscil(os, env(gls_env)))
32752  end
32753end
32754
32755def bird_2(start, dur, freq, freqskew, amp, freq_envelope, amp_envelope)
32756  gls_env = make_env(:envelope, freq_envelope,
32757                     :scaler, hz2radians(freqskew),
32758                     :duration, dur)
32759  os = make_oscil(:frequency, freq)
32760  amp_env = make_env(:envelope, amp_envelope, :scaler, amp, :duration, dur)
32761  run_instrument(start, dur) do
32762    env(amp_env) * oscil(os, env(gls_env))
32763  end
32764end
32765
32766# scissor-tailed flycatcher
32767#
32768# mix a scissor-tailed flycatcher call into the current sound
32769# see bird.rb for lots more birds
32770
32771def scissor_2(start)
32772  bigbird_2(start, 0.05, 1800, 1800, 0.2,
32773            [0, 0, 40, 1, 60, 1, 100, 0], # scissor function
32774            [0, 0, 25, 1, 75, 1, 100, 0],
32775            [1, 0.5, 2, 1, 3, 0.5, 4, 0.1, 5, 0.01])
32776end
32777
32778def bobwhite_2(beg)
32779  main_amp = [0.00, 0.00, 0.25, 1.00, 0.60, 0.70, 0.75, 1.00, 1.00, 0.0]
32780  bobup1 = [0.00, 0.00, 0.40, 1.00, 1.00, 1.0]
32781  bobup2 = [0.00, 0.00, 0.65, 0.50, 1.00, 1.0]
32782  bigbird_2(0.4, 0.2, 1800, 200, 0.1, bobup1, main_amp, [1, 1, 2, 0.02])
32783  bigbird_2(1, 0.20, 1800, 1200, 0.2, bobup2, main_amp, [1, 1, 2, 0.02])
32784end
32785
32786class Sinc_train
32787  def initialize(freq, width)
32788    @range = if width
32789               width
32790             else
32791               PI * ((2 * (mus_srate() / (2.2 * freq)).floor) - 1)
32792             end
32793    @ang = -(@range * 0.5)
32794    @frq = (@range * freq) / mus_srate()
32795  end
32796
32797  def sinc_train(fm)
32798    top = @range * 0.5
32799    val = (@ang.zero? ? 1.0 : (sin(@ang) / @ang))
32800    new_ang = @ang + @frq + fm
32801    @ang = ((new_ang > top) ? (new_ang - @range) : new_ang)
32802    val
32803  end
32804end
32805
32806def make_sinc_train(freq = 440.0, width = false)
32807  Sinc_train.new(freq, width)
32808end
32809
32810def sinc_train(gen, fm = 0.0)
32811  gen.sinc_train(fm)
32812end
32813
32814def ws_sine(freq)
32815  os = make_oscil(freq)
32816  100.times do |i| outa(i, oscil(os), $output) end
32817end
32818
32819def step_src
32820  rd = make_sampler(0)
32821  os = make_oscil(2205)
32822  sr = make_src(:srate, 0.0, :input, lambda do |dir| read_sample(rd) end)
32823  incr = 2.0 + oscil(os)
32824  tempfile = with_sound(:output,  snd_tempnam(),
32825                        :srate,   srate(),
32826                        :comment, get_func_name) do
32827    samp = 0
32828    until sampler_at_end?(rd)
32829      out_any(samp, src(sr, incr), 0, $output)
32830      if (samp % 2205).zero?
32831        incr = 2.0 + oscil(os)
32832      end
32833      samp += 1
32834    end
32835  end.output
32836  len = mus_sound_framples(tempfile)
32837  set_samples(0, len - 1, tempfile, false, false, true,
32838              get_func_name, 0, false, true)
32839end
32840
32841# optkey returns an array of values or, if array length is 1, returns
32842# the single value.  All examples below could be written without local
32843# variables:
32844#
32845# def optkey_n(*args)
32846#   optkey(args, :a, ...)
32847# end
32848def optkey_1(*args)
32849  # single return value, no array returned
32850  a = optkey(args, :a)
32851  a
32852end
32853
32854def optkey_2(*args)
32855  # local variables a and b will be set by optkey, thats why function
32856  # binding as second argument
32857  a, b = nil
32858  optkey(args, binding, [:a, 3], :b)
32859  [a, b]
32860end
32861
32862def optkey_3(*args)
32863  a, b, c = nil
32864  optkey(args, binding, :a, :b, :c)
32865  [a, b, c]
32866end
32867
32868def optkey_4(*args)
32869  a, b, c, d = nil
32870  optkey(args, binding, [:a, 1], [:b, 2], [:c, 3], :d)
32871  [a, b, c, d]
32872end
32873
32874def test_23_00
32875  set_mus_srate($clm_srate = 22050)
32876  set_default_output_srate(22050)
32877  with_sound(:reverb, :nrev, :play, false) do
32878    fmt1 = [0, 1200, 100, 1000]
32879    fmt2 = [0, 2250, 100, 1800]
32880    fmt3 = [0, 4500, 100, 4500]
32881    fmt4 = [0, 6750, 100, 8100]
32882    amp1 = [0, 0.67, 100, 0.7]
32883    amp2 = [0, 0.95, 100, 0.95]
32884    amp3 = [0, 0.28, 100, 0.33]
32885    amp4 = [0, 0.14, 100, 0.15]
32886    ind1 = [0, 0.75, 100, 0.65]
32887    ind2 = [0, 0.75, 100, 0.75]
32888    ind3 = [0, 1, 100, 1]
32889    ind4 = [0, 1, 100, 1]
32890    skwf = [0, 0, 100, 0]
32891    ampf = [0, 0, 25, 1, 75, 1, 100, 0]
32892    ranf = [0, 0.5, 100, 0.5]
32893    index = [0, 1, 100, 1]
32894    solid = [0, 0, 5, 1, 95, 1, 100, 0]
32895    bassdr2 = [0.5, 0.06, 1, 0.62, 1.5, 0.07, 2, 0.6, 2.5, 0.08, 3, 0.56, 4, 0.24, 5, 0.98, 6, 0.53,
32896      7, 0.16, 8, 0.33, 9, 0.62, 10, 0.12, 12, 0.14, 14, 0.86, 16, 0.12, 23, 0.14, 24, 0.17]
32897    tenordr = [0.3, 0.04, 1, 0.81, 2, 0.27, 3, 0.2, 4, 0.21, 5, 0.18, 6, 0.35, 7, 0.03,
32898      8, 0.07, 9, 0.02, 10, 0.025, 11, 0.035]
32899    #
32900    drone(0, 4, 115, 0.125, solid, bassdr2, 0.1, 0.5, 0.03, 45, 1, 0.01, 10)
32901    drone(0, 4, 229, 0.125, solid, tenordr, 0.1, 0.5, 0.03, 45, 1, 0.01, 11)
32902    drone(0, 4, 229.5, 0.125, solid, tenordr, 0.1, 0.5, 0.03, 45, 1, 0.01, 9)
32903    canter(0.000, 0.231, 918.000, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.05, 0.01, 10, index,
32904           0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
32905    canter(2.100, 0.300, 688.500, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index,
32906           0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
32907    canter(2.400, 0.040, 826.200, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index,
32908           0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
32909    canter(2.440, 0.560, 459.000, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index,
32910           0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
32911    canter(3.000, 0.040, 408.000, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index,
32912           0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
32913    canter(3.040, 0.040, 619.650, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index,
32914           0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
32915    canter(3.080, 0.040, 408.000, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index,
32916           0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
32917    canter(3.120, 0.040, 688.500, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index,
32918           0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
32919    canter(3.160, 0.290, 459.000, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index,
32920           0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
32921    canter(3.450, 0.150, 516.375, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index,
32922           0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
32923    canter(3.600, 0.040, 826.200, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index,
32924           0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
32925    canter(3.640, 0.040, 573.750, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index,
32926           0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
32927    canter(3.680, 0.040, 619.650, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index,
32928           0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
32929    canter(3.720, 0.180, 573.750, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index,
32930           0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
32931    canter(3.900, 0.040, 688.500, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index,
32932           0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
32933    canter(3.940, 0.260, 459.000, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index,
32934           0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
32935  end
32936  if sound?(ind = find_sound("test.snd"))
32937    close_sound(ind)
32938  else
32939    snd_display("missing test.snd (%s)", get_func_name)
32940  end
32941end
32942
32943def test_23_01
32944  set_mus_srate($clm_srate = 22050)
32945  set_default_output_srate(22050)
32946  with_sound(:srate, 22050, :play, false) do
32947    fm_violin(0, 0.01, 440, 0.1, :noise_amount, 0.0)
32948    pluck(0.05, 0.01, 330, 0.1, 0.95, 0.95)
32949    maraca(0.1, 0.1)
32950    big_maraca(0.2, 0.5, 0.25, 0.95, 0.9985, 0.0312, [2300, 5600, 8100], [0.96, 0.995, 0.995], 0.01)
32951    fm_bell(0.3, 1.0, 220, 0.5,
32952            [0, 0, 0.1, 1, 10, 0.6, 25, 0.3, 50, 0.15, 90, 0.1, 100, 0],
32953            [0, 1, 2, 1.1, 25, 0.75, 75, 0.5, 100, 0.2],
32954            1.0)
32955    singer(0.4, 0.1, [[0.4, Ehh_shp, Test_glt, 523.0, 0.8, 0.0, 0.01],
32956                      [0.6, Oo_shp, Test_glt, 523.0, 0.7, 0.1, 0.01]])
32957    stereo_flute(0.6, 0.2, 440, 0.55, :flow_envelope, [0, 0, 1, 1, 2, 1, 3, 0])
32958    fofins(1, 0.3, 270, 0.4, 0.001, 730, 0.6, 1090, 0.3, 2440, 0.1)
32959    bow(1.2, 0.3, 400, 0.5, :vb, 0.15, :fb, 0.1, :inharm, 0.25)
32960    pqw_vox(1.5, 1, 300, 300, 0.1,
32961            [0, 0, 50, 1, 100, 0],
32962            [0, 0, 100, 0],
32963            0,
32964            [0, :L, 100, :L],
32965            [0.33, 0.33, 0.33],
32966            [[1, 1, 2, 0.5],
32967              [1, 0.5, 2, 0.5, 3, 1],
32968              [1, 1, 4, 0.5]])
32969    fm_noise(2, 0.5, 500, 0.25,
32970             [0, 0, 25, 1, 75, 1, 100, 0], 0.1, 0.1, 1000,
32971             [0, 0, 100, 1], 0.1, 0.1, 10, 1000,
32972             [0, 0, 100, 1], 0, 0, 100, 500,
32973             [0, 0, 100, 1], 0, 0)
32974    bes_fm(2.5, 0.5, 440, 5.0, 1.0, 8.0)
32975    chain_dsps(3, 0.5, [0, 0, 1, 0.1, 2, 0], make_oscil(440))
32976    chain_dsps(3.5, 1.0, [0, 0, 1, 1, 2, 0], make_one_zero(0.5), make_readin("oboe.snd"))
32977    vox(4, 2, 170, 0.4,
32978        [0, 0, 25, 1, 75, 1, 100, 0],
32979        [0, 0, 5, 0.5, 10, 0, 100, 1],
32980        0.1,
32981        [0, :E, 25, :AE, 35, :ER, 65, :ER, 75, :I, 100, :UH],
32982        0.05, 0.1)
32983    p(5.0, :duration, 0.5, :keyNum, 36, :strike_velocity, 0.5, :amp, 0.4,
32984      :dryPedalResonanceFactor, 0.25)
32985    bobwhite_2(5.5)
32986    scissor_2(2.0)
32987    plucky(3.25, 0.3, 440, 0.2, 1.0)
32988    bowstr(3.75, 0.3, 220, 0.2, 1.0)
32989    brass(4.2, 0.3, 440, 0.2, 1.0)
32990    clarinet(5.75, 0.3, 440, 0.2, 1.0)
32991    flute(6, 0.3, 440, 0.2, 1.0)
32992    fm_trumpet(6.5, 0.25)
32993    touch_tone(6.75, [7, 2, 3, 4, 9, 7, 1])
32994    pins(7.0, 1.0, "now.snd", 1.0, :time_scaler, 2.0)
32995    #
32996    locust = [0, 0, 40, 1, 95, 1, 100, 0.5]
32997    bug_hi = [0, 1, 25, 0.7, 75, 0.78, 100, 1]
32998    amp = [0, 0, 25, 1, 75, 0.7, 100, 0]
32999    fm_insect(7.000, 1.699, 4142.627, 0.015, amp, 60, -16.707, locust, 500.866, bug_hi, 0.346, 0.5)
33000    fm_insect(7.195, 0.233, 4126.284, 0.030, amp, 60, -12.142, locust, 649.490, bug_hi, 0.407, 0.5)
33001    fm_insect(7.217, 2.057, 3930.258, 0.045, amp, 60,  -3.011, locust, 562.087, bug_hi, 0.591, 0.5)
33002    fm_insect(9.100, 1.500,  900.627, 0.060, amp, 40, -16.707, locust, 300.866, bug_hi, 0.346, 0.5)
33003    fm_insect(10.00, 1.500,  900.627, 0.060, amp, 40, -16.707, locust, 300.866, bug_hi, 0.046, 0.5)
33004    fm_insect(10.45, 1.500,  900.627, 0.090, amp, 40, -16.707, locust, 300.866, bug_hi, 0.006, 0.5)
33005    fm_insect(10.95, 1.500,  900.627, 0.120, amp, 40, -10.707, locust, 300.866, bug_hi, 0.346, 0.5)
33006    fm_insect(11.30, 1.500,  900.627, 0.090, amp, 40, -20.707, locust, 300.866, bug_hi, 0.246, 0.5)
33007    #
33008    fm_drum(7.5, 1.5, 55, 0.3, 5, false)
33009    fm_drum(8, 1.5, 66, 0.3, 4, true)
33010    gong(9, 3, 261.61, 0.6)
33011    attract(10, 0.25, 0.5, 2.0)
33012    pqw(11, 0.5, 200, 1000, 0.2, [0, 0, 25, 1, 100, 0], [0, 1, 100, 0], [2, 0.1, 3, 0.3, 6, 0.5])
33013    #
33014    zn(10, 1, 100, 0.1, 20, 100, 0.995)
33015    zn(11.5, 1, 100, 0.1, 100, 20, 0.995)
33016    zc(11, 1, 100, 0.1, 20, 100, 0.95)
33017    zc(12.5, 1, 100, 0.1, 100, 20, 0.95)
33018    za(13, 1, 100, 0.1, 20, 100, 0.95, 0.95)
33019    za(14.5, 1, 100, 0.1, 100, 20, 0.95, 0.95)
33020    #
33021    tubebell(12, 2, 440, 0.2)
33022    wurley(12.5, 0.25, 440, 0.2)
33023    rhodey(12.75, 0.25, 440, 0.2)
33024    hammondoid(13, 0.25, 440, 0.2)
33025    metal(13.5, 0.25, 440, 0.2)
33026    reson(14.0, 1.0, 440, 0.1, 2, [0, 0, 100, 1], [0, 0, 100, 1],
33027          0.1, 0.1, 0.1, 5, 0.01, 5, 0.01, 0, 1.0, 0.01,
33028          [[[0, 0, 100, 1], 1200, 0.5, 0.1, 0.1, 0, 1.0, 0.1, 0.1],
33029            [[0, 1, 100, 0], 2400, 0.5, 0.1, 0.1, 0, 1.0, 0.1, 0.1]])
33030    cellon(14.5, 1, 220, 0.1,
33031           [0, 0, 25, 1, 75, 1, 100, 0],
33032           [0, 0, 25, 1, 75, 1, 100, 0], 0.75, 1.0, 0, 0, 0, 0, 1, 0, 0, 220,
33033           [0, 0, 25, 1, 75, 1, 100, 0], 0, 0, 0, 0,
33034           [0, 0, 100, 0], 0, 0, 0, 0, [0, 0, 100, 0])
33035    clm_expsrc(14.75, 2.5, "oboe.snd", 2.0, 1.0, 1.0)
33036    scratch(15.0, "now.snd", 1.5, [0.0, 0.5, 0.25, 1.0])
33037    two_tab(15, 1, 440, 0.1)
33038    exp_snd("fyow.snd", 15, 1.5, 1, [0, 1, 1, 3], 0.4, 0.15,
33039            [0, 2, 1, 0.5], 0.05)
33040    exp_snd("oboe.snd", 16, 1, 1, [0, 1, 1, 3], 0.4, 0.15, [0, 2, 1, 0.5], 0.2)
33041    gran_synth(15.5, 1, 300, 0.0189, 0.03, 0.4)
33042    spectra(16, 1, 440, 0.1,
33043            [1, 0.4, 2, 0.2, 3, 0.2, 4, 0.1, 6, 0.1],
33044            [0, 0, 1, 1, 5, 0.9, 12, 0.5, 25, 0.25, 100, 0])
33045    lbj_piano(16.5, 1, 440, 0.2)
33046    resflt(17, 1, 0, 0, 0, false, 0.1, 200, 230, 10,
33047           [0, 0, 50, 1, 100, 0],
33048           [0, 0, 100, 1],
33049           500, 0.995, 0.1, 1000, 0.995, 0.1, 2000, 0.995, 0.1)
33050    resflt(17.5, 1, 1, 10000, 0.01, [0, 0, 50, 1, 100, 0], 0, 0, 0, 0,
33051           false, false,
33052           500, 0.995, 0.1, 1000, 0.995, 0.1, 2000, 0.995, 0.1)
33053    bes_fm(18, 1, 440, 10.0, 1.0, 4.0)
33054    graph_eq("oboe.snd", 19, 1)
33055  end
33056  if sound?(ind = find_sound("test.snd"))
33057    close_sound(ind)
33058  else
33059    snd_display("missing test.snd (%s)", get_func_name)
33060  end
33061end
33062
33063def test_23_02
33064  set_mus_srate($clm_srate = 22050)
33065  set_default_output_srate(22050)
33066  [Mus_bshort,
33067   Mus_lshort,
33068   Mus_mulaw,
33069   Mus_alaw,
33070   Mus_byte,
33071   Mus_lfloat,
33072   Mus_bint,
33073   Mus_lint,
33074   Mus_b24int,
33075   Mus_l24int,
33076   Mus_ubshort,
33077   Mus_ulshort,
33078   Mus_ubyte,
33079   Mus_bfloat,
33080   Mus_bdouble,
33081   Mus_ldouble].each do |type|
33082    ind = find_sound(with_sound(:sample_type, type, :srate, 22050) do
33083                       fm_violin(0, 0.1, 440, 0.1)
33084                       fm_violin(10, 0.1, 440, 0.1)
33085                       fm_violin(100, 0.1, 440, 0.1)
33086                       fm_violin(250, 0.1, 440, 0.1)
33087                     end.output)
33088    snd_test_any_neq(maxamp(ind), 0.1, :ffequal?,
33089                     "format %s", mus_sample_type2string(type))
33090  end
33091  3.times do |i|
33092    with_sound(:srate, 22050) do
33093      fm_violin(0, 0.1, 110.0 * (1.0 + i), 0.1)
33094    end
33095    ind = find_sound("test.snd")
33096    unless ind
33097      snd_display("with_sound: %s?", Snd.sounds.map do |s| file_name(s) end)
33098    end
33099    if fneq(res = maxamp, 0.1)
33100      snd_display("with_sound max (%s): %s?", i, res)
33101    end
33102    if srate(ind) != 22050
33103      snd_display("with_sound srate: %s (%s %s)?",
33104                  srate(ind), mus_srate, mus_sound_srate("test.snd"))
33105    end
33106    if framples(ind) != 2205
33107      snd_display("with_sound framples (%s): %s?", i, framples(ind))
33108    end
33109  end
33110  #
33111  with_sound do
33112    fm_violin(0, 0.1, 440, 0.1)
33113  end
33114  with_sound(:continue_old_file, true) do
33115    fm_violin(0.2, 0.1, 660, 0.04)
33116  end
33117  ind = find_sound("test.snd")
33118  if fneq(res = maxamp, 0.1)
33119    snd_display("maxamp after continued sound: %s?", res)
33120  end
33121  if fneq(res = framples(ind) / srate(ind).to_f, 0.3)
33122    snd_display("duration after continued sound: %s?", res)
33123  end
33124  close_sound(ind)
33125  #
33126  with_sound(:srate,    22050,
33127             :channels, 2,
33128             :output,   "test1.snd") do
33129    fm_violin(0, 0.1, 440, 0.1, :degree, 45.0)
33130  end
33131  ind = find_sound("test1.snd")
33132  unless ind
33133    snd_display("with_sound (1): %s?", file_name(true))
33134  end
33135  if fneq(res = maxamp, 0.05)
33136    snd_display("with_sound max (1): %s?", res)
33137  end
33138  if srate(ind) != 22050 or mus_sound_srate("test1.snd") != 22050
33139    snd_display("with_sound srate (1): %s (%s %s)?",
33140                srate(ind), mus_srate, mus_sound_srate("test1.snd"))
33141  end
33142  if framples(ind) != 2205
33143    snd_display("with_sound framples (1): %s?", framples(ind))
33144  end
33145  if chans(ind) != 2 or mus_sound_chans("test1.snd") != 2
33146    snd_display("with_sound chans (1): %s?", chans(ind))
33147  end
33148  close_sound(ind)
33149  delete_file("test1.snd")
33150  #
33151  with_sound(:srate,       48000,
33152             :channels,    2,
33153             :header_type, Mus_riff,
33154             :sample_type, Mus_lshort,
33155             :output,      "test1.snd") do
33156    fm_violin(0, 0.1, 440, 0.1)
33157  end
33158  ind = find_sound("test1.snd")
33159  if srate(ind) != 48000 or mus_sound_srate("test1.snd") != 48000
33160    snd_display("with_sound srate (48000, r): %s (%s, %s)?",
33161                srate(ind),
33162                mus_srate,
33163                mus_sound_srate("test1.snd"))
33164  end
33165  if (res = header_type(ind)) != Mus_riff
33166    snd_display("with_sound type (%s, r): %s?", Mus_riff, res)
33167  end
33168  if (res = chans(ind)) != 2
33169    snd_display("with_sound chans (2, r): %s?", res)
33170  end
33171  close_sound(ind)
33172  delete_file("test1.snd")
33173  #
33174  with_sound(:srate,       48000,
33175             :channels,    2,
33176             :header_type, Mus_caff,
33177             :sample_type, Mus_lshort,
33178             :output,      "test1.snd") do
33179    fm_violin(0, 0.1, 440, 0.1)
33180  end
33181  ind = find_sound("test1.snd")
33182  if srate(ind) != 48000 or mus_sound_srate("test1.snd") != 48000
33183    snd_display("with_sound srate (48000, r): %s (%s, %s)?",
33184                srate(ind),
33185                mus_srate,
33186                mus_sound_srate("test1.snd"))
33187  end
33188  if (res = header_type(ind)) != Mus_caff
33189    snd_display("with_sound type (%s, r): %s?", Mus_caff, res)
33190  end
33191  if (res = channels(ind)) != 2
33192    snd_display("with_sound Mus_caff chans (2, r): %s?", res)
33193  end
33194  close_sound(ind)
33195  delete_file("test1.snd")
33196  #
33197  with_sound(:srate,       8000,
33198             :channels,    3,
33199             :header_type, Mus_next,
33200             :output,      "test1.snd") do
33201    fm_violin(0, 0.1, 440, 0.1)
33202  end
33203  ind = find_sound("test1.snd")
33204  if srate(ind) != 8000 or mus_sound_srate("test1.snd") != 8000
33205    snd_display("with_sound srate (8000, s): %s (%s, %s)?",
33206                srate(ind),
33207                mus_srate,
33208                mus_sound_srate("test1.snd"))
33209  end
33210  if (res = header_type(ind)) != Mus_next
33211    snd_display("with_sound type (%s, s): %s?", Mus_next, res)
33212  end
33213  if (res = channels(ind)) != 3
33214    snd_display("with_sound chans (3, s): %s?", res)
33215  end
33216  close_sound(ind)
33217  delete_file("test1.snd")
33218  #
33219  my_srate = 96000
33220  with_sound(:srate,       my_srate,
33221             :channels,    4,
33222             :header_type, Mus_aifc,
33223             :output,      "test1.snd") do
33224    fm_violin(0, 0.1, 440, 0.1)
33225  end
33226  ind = find_sound("test1.snd")
33227  if srate(ind) != my_srate or mus_sound_srate("test1.snd") != my_srate
33228    snd_display("with_sound srate (%s, t): %s (%s, %s)?",
33229                my_srate,
33230                srate(ind),
33231                mus_srate,
33232                mus_sound_srate("test1.snd"))
33233  end
33234  if (res = header_type(ind)) != Mus_aifc
33235    snd_display("with_sound type (%s, t): %s?", Mus_aifc, res)
33236  end
33237  if (res = channels(ind)) != 4
33238    snd_display("with_sound chans (4, t): %s?", res)
33239  end
33240  close_sound(ind)
33241  delete_file("test1.snd")
33242  with_sound(:srate,       22050,
33243             :channels,    1,
33244             :header_type, Mus_raw,
33245             :output,      "test1.snd") do
33246    fm_violin(0, 0.1, 440, 0.1)
33247  end
33248  ind = find_sound("test1.snd")
33249  if srate(ind) != 22050 or mus_sound_srate("test1.snd") != 22050
33250    snd_display("with_sound srate (22050, u: %s (%s, %s)?",
33251                srate(ind),
33252                mus_srate,
33253                mus_sound_srate("test1.snd"))
33254  end
33255  if (res = header_type(ind)) != Mus_raw
33256    snd_display("with_sound type (%s, u): %s?", Mus_raw, res)
33257  end
33258  if (res = channels(ind)) != 1
33259    snd_display("with_sound chans (1, u): %s?", res)
33260  end
33261  close_sound(ind)
33262  delete_file("test1.snd")
33263  #
33264  with_sound(:srate,    22050,
33265             :channels, 2,
33266             :output,   "test1.snd",
33267             :reverb,   :jc_reverb) do
33268    if (res = mus_sound_srate(mus_file_name($output))) != 22050
33269      snd_display("srate file $output: %s?", res)
33270    end
33271    if (res = mus_sound_srate(mus_file_name($reverb))) != 22050
33272      snd_display("srate file $reverb: %s?", res)
33273    end
33274    fm_violin(0, 0.1, 440, 0.1, :degree, 45.0)
33275  end
33276  if sound?(ind = find_sound("test1.snd"))
33277    if framples(ind) - (22050 + 2205) > 1
33278      snd_display("with_sound reverbed framples (2): %s?", framples(ind))
33279    end
33280    close_sound(ind)
33281  else
33282    snd_display("with_sound (2): %s?", file_name(true))
33283  end
33284  #
33285  with_sound(:srate,     22050,
33286             :comment,   "Snd+Run!",
33287             :scaled_to, 0.5) do
33288    fm_violin(0, 0.1, 440, 0.1)
33289  end
33290  ind = find_sound("test.snd")
33291  unless ind
33292    snd_display("with_sound: %s?", file_name(true))
33293  end
33294  if fneq(res = maxamp(ind), 0.5)
33295    snd_display("with_sound scaled_to: %s?", res)
33296  end
33297  if (res = comment(ind)) != "Snd+Run!"
33298    snd_display("with_sound comment: %s (%s)?", res, mus_sound_comment("test.snd"))
33299  end
33300  close_sound(ind)
33301  #
33302  with_sound(:srate,       22050,
33303             :scaled_by,   0.5,
33304             :header_type, Mus_aifc,
33305             :sample_type, Mus_bfloat) do
33306    fm_violin(0, 0.1, 440, 0.1)
33307  end
33308  ind = find_sound("test.snd")
33309  unless ind
33310    snd_display("with_sound: %s?", file_name(true))
33311  end
33312  if fneq(res = maxamp(ind), 0.05)
33313    snd_display("with_sound scaled_by: %s?", res)
33314  end
33315  if (res = header_type(ind)) != Mus_aifc
33316    snd_display("with_sound type: %s (%s)?", res, mus_header_type_name(res))
33317  end
33318  if (res = sample_type(ind)) != Mus_bfloat
33319    snd_display("with_sound format: %s (%s)?", res, mus_sample_type_name(res))
33320  end
33321  close_sound(ind)
33322  #
33323  $open_raw_sound_hook.add_hook!("with-sound") do |file, choice| [1, 22050, Mus_bshort] end
33324  with_sound(:header_type, Mus_raw) do
33325    fm_violin(0, 0.1, 440, 0.1)
33326  end
33327  $open_raw_sound_hook.remove_hook!("with-sound")
33328  unless sound?(ind = find_sound("test.snd"))
33329    snd_display("with_sound (raw out): %s?", file_name(true))
33330  end
33331  if (res = header_type(ind)) != Mus_raw
33332    snd_display("with_sound type raw: %s (%s)?", res, mus_header_type_name(res))
33333  end
33334  if (res = sample_type(ind)) != Mus_bshort and
33335    res != Mus_bfloat and
33336    res != Mus_lfloat
33337    snd_display("with_sound format raw: %s (%s)?", res, mus_sample_type_name(res))
33338  end
33339  close_sound(ind)
33340  #
33341  with_sound(:srate, 44100) do
33342    ws_sine(1000)
33343  end
33344  ind = find_sound("test.snd")
33345  i = -1
33346  scan_channel(lambda { |y|
33347                 i += 1
33348                 if fneq(y, res = sin(TWO_PI * i * (1000.0 / 44100.0)))
33349                   snd_display("with_sound sine: %s %s %s", i, y, res)
33350                   true
33351                 else
33352                   false
33353                 end
33354               })
33355  close_sound(ind)
33356  #
33357  if File.exist?("ii.rb")
33358    with_time("load(\"ii.rb\")") do load("ii.rb") end
33359    Snd.sounds.apply(:close_sound)
33360    delete_files("test.snd", "rest.reverb")
33361  end
33362  set_mus_srate($clm_srate = 22050)
33363  set_default_output_srate(22050)
33364  #
33365  outer = with_sound do
33366    sound_let(Proc.new do fm_violin(0, 0.1, 440, 0.1) end) do |tmp|
33367      clm_mix(tmp)
33368    end
33369  end.output
33370  unless string?(outer)
33371    snd_display("with_sound returns: %s?", outer)
33372  end
33373  ind = find_sound(outer)
33374  if (not sound?(ind)) or
33375     (framples(ind) - (res = (mus_srate * 0.1).floor)) > 1
33376    snd_display("sound_let: %s %s?", framples(ind), res)
33377  end
33378  close_sound(ind)
33379  delete_file("test.snd")
33380  #
33381  outer = with_sound do
33382    sound_let(Proc.new do fm_violin(0, 0.1, 440, 0.1) end,
33383              100) do |a, b|
33384      clm_mix(a, b)
33385      sound_let([:channels, 1, :output, "temp.snd",
33386                 Proc.new do fm_violin(0, 0.1, 110, 0.1) end]) do |c|
33387        clm_mix(c)
33388      end
33389    end
33390  end.output
33391  unless string?(outer)
33392    snd_display("with_sound (2) returns: %s?", outer)
33393  end
33394  ind = find_sound(outer)
33395  if (not sound?(ind)) or
33396     (framples(ind) - (res = 100 + (mus_srate * 0.1).floor)) > 1
33397    snd_display("sound_let (2): %s %s?", framples(ind), res)
33398  end
33399  if File.exist?("temp.snd")
33400    snd_display("sound_let explicit output exists?")
33401  end
33402  close_sound(ind)
33403end
33404
33405def test_23_03
33406  set_mus_srate($clm_srate = 22050)
33407  set_default_output_srate(22050)
33408  with_sound(:channels, 2) do
33409    fullmix("pistol.snd")
33410    fullmix("oboe.snd", 1, 2, 0,
33411            [[0.1, make_env([0, 0, 1, 1], :duration, 2, :scaler, 0.5)]])
33412  end
33413  if sound?(ind = find_sound("test.snd"))
33414    close_sound(ind)
33415  end
33416  with_sound(:channels, 2) do
33417    fullmix("4.aiff", 0.0, 0.1, 36.4,
33418            [[0.0, 0.0], [0.0, 0.0], [1.0, 0.0], [0.0, 1.0]])
33419  end
33420  if sound?(ind = find_sound("test.snd"))
33421    snd_test_neq(maxamp(), 0.8865, "4->2(0) fullmix")
33422    close_sound(ind)
33423  end
33424  with_sound(:channels, 1) do
33425    fullmix("4.aiff", 0.0, 0.1, 36.4,
33426            [[1.0], [0.0], [0.0], [0.0]])
33427  end
33428  if sound?(ind = find_sound("test.snd"))
33429    snd_test_neq(maxamp(), 0.221649169921875, "4->1(0) fullmix")
33430    close_sound(ind)
33431  end
33432  with_sound(:channels, 1) do
33433    fullmix("4.aiff", 0.0, 0.1, 36.4,
33434            [[0.0], [1.0], [0.0], [0.0]])
33435  end
33436  if sound?(ind = find_sound("test.snd"))
33437    snd_test_neq(maxamp(), 0.44329833984375, "4->1(1) fullmix")
33438    close_sound(ind)
33439  end
33440  with_sound(:channels, 1) do
33441    fullmix("4.aiff", 0.0, 0.1, 36.4,
33442            [[0.0], [0.0], [1.0], [0.0]])
33443  end
33444  if sound?(ind = find_sound("test.snd"))
33445    snd_test_neq(maxamp(), 0.664947509765625, "4->1(2) fullmix")
33446    close_sound(ind)
33447  end
33448  with_sound(:channels, 1) do
33449    fullmix("4.aiff", 0.0, 0.1, 36.4,
33450            [[0.0], [0.0], [0.0], [1.0]])
33451  end
33452  if sound?(ind = find_sound("test.snd"))
33453    snd_test_neq(maxamp(), 0.8865966796875, "4->1(3) fullmix")
33454    close_sound(ind)
33455  end
33456  with_sound(:channels, 2) do
33457    fullmix("4.aiff", 0.0, 0.1, 36.4,
33458            [[0.0, 0.0], [0.0, 0.0], [1.0, 0.0], [0.0, 1.0]])
33459  end
33460  if sound?(ind = find_sound("test.snd"))
33461    mxs = maxamp(ind, true)
33462    req1 = 0.664947509765625
33463    req2 = 0.8865966796875
33464    if fneq(mxs[0], req1) or fneq(mxs[1], req2)
33465      snd_test_neq(mxs[0], req1, "4->2(1a) fullmix")
33466      snd_test_neq(mxs[1], req2, "4->2(1b) fullmix")
33467    end
33468    close_sound(ind)
33469  end
33470  with_sound(:channels, 2) do
33471    fullmix("4.aiff", 0.0, 0.1, 36.4,
33472            [[0.0, 0.0], [0.0, 0.0], [0.0, 1.0], [1.0, 0.0]])
33473  end
33474  if sound?(ind = find_sound("test.snd"))
33475    mxs = maxamp(ind, true)
33476    req1 = 0.8865966796875
33477    req2 = 0.664947509765625
33478    if fneq(mxs[0], req1) or fneq(mxs[1], req2)
33479      snd_test_neq(mxs[0], req2, "4->2(2a) fullmix")
33480      snd_test_neq(mxs[1], req1, "4->2(2b) fullmix")
33481    end
33482    close_sound(ind)
33483  end
33484  with_sound(:channels, 2, :reverb, :nrev) do
33485    fullmix("pistol.snd", 0.0, 2.0, 0.25, false, 2.0, 0.1)
33486    fullmix("pistol.snd", 1.0, 2.0, 0.25, 0.2, 2.0, 0.1)
33487    fullmix("2a.snd", false, false, false, [[0.5, 0.0], [0.0, 0.75]])
33488    fullmix("oboe.snd", false, false, false, [[[0, 0, 1, 1, 2, 0], 0.5]])
33489    fullmix("oboe.snd", 3, 2, 0,
33490            [[0.1, make_env([0, 0, 1, 1], :duration, 2, :scaler, 0.5)]])
33491  end
33492  if sound?(ind = find_sound("test.snd"))
33493    close_sound(ind)
33494  end
33495end
33496
33497def test_23_04
33498  set_mus_srate($clm_srate = 22050)
33499  set_default_output_srate(22050)
33500  with_sound(:srate, 22050) do
33501    sound_let(Proc.new do
33502                fm_violin(0, 1, 440, 0.1)
33503              end,
33504              Proc.new do
33505                fm_violin(0, 2, 660, 0.1, :base, 32.0)
33506                fm_violin(0.125, 0.5, 880, 0.1)
33507              end) do |temp_1, temp_2|
33508      clm_mix(temp_1, 0)
33509      clm_mix(temp_2, 22050)
33510    end
33511  end
33512  if sound?(ind = find_sound("test.snd"))
33513    unless maxamp(ind).between?(0.15, 0.2)
33514      snd_display("with_sound+sound_lets maxamp: %s?", maxamp(ind))
33515    end
33516    if fneq(res = framples(ind) / srate(ind).to_f, 3.0)
33517      snd_display("with_sound+sound_lets dur: res %s frms %s sr %s?",
33518                  res, framples(ind), srate(ind))
33519    end
33520    close_sound(ind)
33521  else
33522    snd_display("with_sound+sound_lets init: no test.snd?")
33523  end
33524  #
33525  with_sound(:srate, 44100) do
33526    bigbird_2(0, 2.0, 60, 0, 0.5,
33527              [0, 0, 1, 1],
33528              [0, 0, 1, 1, 2, 1, 3, 0],
33529              [1, 1, 2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1, 8, 1, 9, 1, 10, 1])
33530  end
33531  ind = (find_sound("test.snd") or open_sound("oboe.snd"))
33532  mx = maxamp
33533  val = 0.0
33534  freqs = Array.new(50) do |i| val += 60.0 end
33535  notch_sound(freqs)
33536  snd_test_neq(mx, 0.5, "notch_sound 60 Hz (1a)")
33537  snd_test_any_neq(maxamp(), 0.027, :ffequal?, "notch_sound 60 Hz (1b)")
33538  undo_edit
33539  notch_sound(freqs, false, ind, 0, 10)
33540  snd_test_any_neq(maxamp(), 0.011, :ffequal?, "notch_sound 60 Hz 2")
33541  undo_edit
33542  notch_channel(freqs, false, false, false, ind, 0, false, false, 10)
33543  snd_test_neq(maxamp(), 0.004, "notch_channel 60 Hz 2")
33544  undo_edit
33545  make_selection(10000, 11000)
33546  notch_selection(freqs, false, 10)
33547  close_sound(ind)
33548  #
33549  with_sound(:srate, 44100) do
33550    bigbird_2(0, 30, 60, 0, 0.5,
33551              [0, 0, 1, 1],
33552              [0, 0, 1, 1, 2, 1, 3, 0],
33553              [1, 1, 2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1, 8, 1, 9, 1, 10, 1])
33554  end
33555  ind = find_sound("test.snd")
33556  notch_sound(freqs, false, ind, 0, 10)
33557  snd_test_neq(maxamp(), 0.011, "notch_sound 60 Hz 2 60")
33558  close_sound(ind)
33559  #
33560  # from play.rb
33561  play_sine(440, 0.1)
33562  play_sines([425, 0.05], [450, 0.01], [470, 0.01], [546, 0.02],
33563             [667, 0.01], [789, 0.034], [910, 0.032])
33564  # grani from clm-ins.rb
33565  with_sound(:channels, 2,
33566             :reverb, :jc_reverb,
33567             :reverb_channels, 1) do
33568    grani(0, 1, 0.5, "oboe.snd",
33569          :grain_envelope, [0, 0, 0.2, 0.2, 0.5, 1, 0.8, 0.2, 1, 0])
33570    grani(0, 4, 1, "oboe.snd")
33571    grani(0, 4, 1, "oboe.snd", :grains, 10)
33572    grani(0, 4, 1, "oboe.snd",
33573          :grain_start, 0.11,
33574          :amp_envelope, [0, 1, 1, 1], :grain_density, 8,
33575          :grain_envelope, [0, 0, 0.2, 0.2, 0.5, 1, 0.8, 0.2, 1, 0],
33576          :grain_envelope_end, [0, 0, 0.01, 1, 0.99, 1, 1, 0],
33577          :grain_envelope_transition, [0, 0, 0.4, 1, 0.8, 0, 1, 0])
33578    grani(0, 3, 1, "oboe.snd",
33579          :grain_start, 0.1,
33580          :amp_envelope, [0, 1, 1, 1], :grain_density, 20,
33581          :grain_duration, [0, 0.003, 0.2, 0.01, 1, 0.3])
33582    grani(0, 3, 1, "oboe.snd",
33583          :grain_start, 0.1,
33584          :amp_envelope, [0, 1, 1, 1], :grain_density, 20,
33585          :grain_duration, [0, 0.003, 0.2, 0.01, 1, 0.3],
33586          :grain_duration_limit, 0.02)
33587    grani(0, 2, 1, "oboe.snd",
33588          :amp_envelope, [0, 1, 1, 1], :grain_density, 40,
33589          :grain_start, [0, 0.1, 0.3, 0.1, 1, 0.6])
33590    grani(0, 2, 1, "oboe.snd",
33591          :amp_envelope, [0, 1, 1, 1], :grain_density, 40,
33592          :grain_start, [0, 0.1, 0.3, 0.1, 1, 0.6],
33593          :grain_start_spread, 0.01)
33594    grani(0, 2.6, 1, "oboe.snd",
33595          :grain_start, 0.1, :grain_start_spread, 0.01,
33596          :amp_envelope, [0, 1, 1, 1], :grain_density, 40,
33597          :srate, [0, 0, 0.2, 0, 0.6, 5, 1, 5])
33598    grani(0, 2.6, 1, "oboe.snd",
33599          :grain_start, 0.1, :grain_start_spread, 0.01,
33600          :amp_envelope, [0, 1, 1, 1], :grain_density, 40,
33601          :srate_base, 2,
33602          :srate, [0, 0, 0.2, 0, 0.6, -1, 1, -1])
33603    grani(0, 2.6, 1, "oboe.snd",
33604          :grain_start, 0.1, :grain_start_spread, 0.01,
33605          :amp_envelope, [0, 1, 1, 1], :grain_density, 40,
33606          :srate_linear, true,
33607          :srate, [0, 0, 0.2, 1, 0.6, 2 ** (5.0 / 12.0), 1, 2 ** (5.0 / 12.0)])
33608    grani(0, 2, 1, "oboe.snd",
33609          :grain_start, 0.1, :grain_start_spread, 0.01,
33610          :amp_envelope, [0, 1, 1, 1], :grain_density, 40,
33611          :grain_duration, [0, 0.02, 1, 0.1],
33612          :grain_duration_spread, [0, 0, 0.5, 0.1, 1, 0],
33613          :where_to, Grani_to_grain_duration,
33614          :where_bins, vct(0, 0.05, 1))
33615    grani(0, 2, 1, "oboe.snd",
33616          :grain_start, 0.1, :grain_start_spread, 0.01,
33617          :amp_envelope, [0, 1, 1, 1], :grain_density, 40,
33618          :grain_degree, [0, 0, 1, 90],
33619          :grain_degree_spread, 10)
33620  end
33621  #
33622  ind = open_sound("oboe.snd")
33623  with_sound(:output, "test1.snd") do
33624    fm_violin(0, 0.1, 440, 0.1)
33625  end
33626  set_samples(0, 2205, "test1.snd", ind, 0, false,
33627              "set_samples auto-delete test", 0, false, true)
33628  unless File.exist?("test1.snd")
33629    snd_display("oops: auto-delete test1.snd?")
33630  end
33631  undo_edit(1, ind)
33632  with_sound(:output, "test2.snd") do
33633    fm_violin(0, 0.1, 440, 0.1)
33634  end
33635  insert_sound("test2.snd", 0, 0, ind, 0, false, true)
33636  if File.exist?("test1.snd")
33637    snd_display("auto-delete set_samples?")
33638  end
33639  undo_edit(1, ind)
33640  with_sound(:output, "test3.snd") do
33641    fm_violin(0, 0.1, 440, 0.1)
33642  end
33643  insert_samples(0, 2205, "test3.snd", ind, 0, false, true)
33644  if File.exist?("test2.snd")
33645    snd_display("auto-delete insert_sound?")
33646  end
33647  undo_edit(1, ind)
33648  with_sound(:output, "test4.snd") do
33649    fm_violin(0, 0.1, 440, 0.1)
33650  end
33651  mix("test4.snd", 0, 0, ind, 0, false, true)
33652  if File.exist?("test3.snd")
33653    snd_display("auto-delete insert_samples?")
33654  end
33655  undo_edit(1, ind)
33656  delete_sample(100, ind, 0)
33657  if File.exist?("test4.snd")
33658    snd_display("auto-delete mix?")
33659  end
33660  with_sound(:output, "test5.snd") do
33661    fm_violin(0, 0.1, 440, 0.1)
33662  end
33663  mix("test5.snd", 0, 0, ind, 0, true, true)
33664  revert_sound(ind)
33665  close_sound(ind)
33666  if File.exist?("test5.snd")
33667    snd_display("auto-delete mix (with-tag)?")
33668  end
33669  Snd.sounds.apply(:close_sound)
33670  #
33671  if (res = optkey_1(1))     != 1
33672    snd_display("optkey_1: %s?", res)
33673  end
33674  if (res = optkey_1(:a, 1)) != 1
33675    snd_display("optkey_1 1: %s?", res)
33676  end
33677  if (res = optkey_1)        != nil
33678    snd_display("optkey_1 2: %s?", res)
33679  end
33680  #
33681  if (res = optkey_2(1, 2))         != [1, 2]
33682    snd_display("optkey_2: %s?", res)
33683  end
33684  if (res = optkey_2(:a, 1, :b, 2)) != [1, 2]
33685    snd_display("optkey_2 1: %s?", res)
33686  end
33687  if (res = optkey_2)               != [3, nil]
33688    snd_display("optkey_2 2: %s?", res)
33689  end
33690  if (res = optkey_2(1, :b, 2))     != [1, 2]
33691    snd_display("optkey_2 3: %s?", res)
33692  end
33693  #
33694  if (res = optkey_3(1, 2, 3))         != [1, 2, 3]
33695    snd_display("optkey_3: %s?", res)
33696  end
33697  if (res = optkey_3(1, :b, 2, :c, 3)) != [1, 2, 3]
33698    snd_display("optkey_3 1: %s?", res)
33699  end
33700  if (res = optkey_3(1, 2, :c, 3))     != [1, 2, 3]
33701    snd_display("optkey_3 2: %s?", res)
33702  end
33703  #
33704  if (res = optkey_4) != [1, 2, 3, nil]
33705    snd_display("optkey_4: %s?", res)
33706  end
33707  if (res = optkey_4(1, :b, 3, :c, 4, :d, 5)) != [1, 3, 4, 5]
33708    snd_display("optkey_4 1: %s?", res)
33709  end
33710  if (res = optkey_4(1, :d, 5, :c, 4, :b, 3)) != [1, 3, 4, 5]
33711    snd_display("optkey_4 2: %s 1?", res)
33712  end
33713  if (res = optkey_4(1, 3, 4, 5)) != [1, 3, 4, 5]
33714    snd_display("optkey_4 3: %s 2?", res)
33715  end
33716  #
33717  if defined? variable_display
33718    wid1 = make_variable_display("do-loop-1", "i*1", :text)
33719    wid2 = make_variable_display("do-loop-2", "i*2", :scale, [-1.0, 1.0])
33720    wid3 = make_variable_display("do-loop-3", "i3", :spectrum)
33721    wid4 = make_variable_display("do-loop-4", "i4", :graph)
33722    if variable_display?(wid1) and
33723       variable_display?(wid2) and
33724       variable_display?(wid3) and
33725       variable_display?(wid4)
33726      1000.times do |i|
33727        variable_display(wid4,
33728          variable_display(wid3,
33729            variable_display(wid2,
33730              sin(variable_display(wid1, 1) * 0.1)) * 0.5))
33731      end
33732      tag = Snd.catch do set_sample(0, 0.5, wid3.snd, 0) end
33733      if (res = edit_position(wid3.snd, 0)) > 0
33734        snd_display("edited variable graph: %s %s?", tag, res)
33735      end
33736      [wid1, wid2, wid3, wid4].each do |w|
33737        variable_display_close(w)
33738      end
33739    else
33740      [wid1, wid2, wid3, wid4].each_with_index do |w, i|
33741        if variable_display?(w)
33742          variable_display_close(w)
33743        else
33744          snd_display("variable_display(do-loop-%d): %s", i, w.inspect)
33745        end
33746      end
33747    end
33748    dismiss_all_dialogs
33749  end
33750  #
33751  [[:clm_srate,           default_output_srate],
33752   [:clm_channels,        default_output_chans],
33753   [:clm_header_type,     default_output_header_type],
33754   [:clm_sample_type,     default_output_sample_type],
33755   [:clm_reverb_channels, 1],
33756   [:clm_file_name,       "test.snd"],
33757   [:clm_play,            false],
33758   [:clm_verbose,         false],
33759   [:clm_statistics,      false],
33760   [:clm_reverb,          nil],
33761   [:clm_delete_reverb,   false],
33762   [:clm_reverb_data,     []]].each do |sym, req|
33763    snd_test_neq(eval("$" + sym.to_s), req, "$%s", sym.to_s)
33764  end
33765  #
33766  $clm_channels      = 2
33767  $clm_srate         = 44100
33768  $clm_file_name     = "test.wav"
33769  $clm_verbose       = false
33770  $clm_statistics    = false
33771  $clm_play          = false
33772  $clm_sample_type   = Mus_mulaw
33773  $clm_header_type   = Mus_riff
33774  $clm_delete_reverb = true
33775  $clm_reverb        = :jc_reverb
33776  $clm_reverb_data   = [:low_pass, true, :volume, 2.0, :amp_env, [0, 1, 3, 1, 4, 0]]
33777  with_sound(:comment, "fm_violin(:reverb_amount, 0.1)") do
33778    fm_violin(0, 1, 440, 0.1, :reverb_amount, 0.1)
33779  end
33780  unless sound?(ind = find_sound("test.wav"))
33781    snd_display("default output in ws: %s?", file_name(true))
33782  else
33783    if (res = srate(ind)) != 44100
33784      snd_display("default srate in ws: %s %s?", res, $clm_srate)
33785    end
33786    if (res = channels(ind)) != 2
33787      snd_display("default channels in ws: %s %s?", res, $clm_channels)
33788    end
33789    if (res = sample_type(ind)) != Mus_mulaw
33790      snd_display("default format in ws: %s %s?", res, $clm_sample_type)
33791    end
33792    if (res = header_type(ind)) != Mus_riff
33793      snd_display("default type in ws: %s %s?", res, $clm_header_type)
33794    end
33795    if (res = framples(ind)) != 88200
33796      snd_display("reverb+1 sec out in ws: %s?", res)
33797    end
33798    if File.exist?("test.reverb")
33799      snd_display("perhaps reverb not deleted in ws?")
33800    end
33801    close_sound(ind)
33802  end
33803  #
33804  val = 0
33805  old_hook = $clm_notehook
33806  $clm_notehook = lambda do |*args| val = 1 end
33807  with_sound(:comment, "$clm_notehook") do
33808    fm_violin(0, 0.1, 440, 0.1)
33809  end
33810  if val != 1
33811    snd_display("$clm_notehook (1): %s %s?", val, $clm_notehook.inspect)
33812  end
33813  with_sound(:notehook, lambda do |*args| val=2 end, :comment, ":notehook") do
33814    fm_violin(0, 0.1, 440, 0.1)
33815  end
33816  if val != 2
33817    snd_display(":notehook: %s?", val)
33818  end
33819  with_sound(:comment, "$clm_notehook (2)") do
33820    fm_violin(0, 0.1, 440, 0.1)
33821  end
33822  if val != 1
33823    snd_display("$clm_notehook (2): %s %s?", val, $clm_notehook.inspect)
33824  end
33825  $clm_notehook = old_hook
33826  #
33827  $clm_channels      = 1
33828  $clm_srate         = 22050
33829  $clm_file_name     = "test.snd"
33830  $clm_verbose       = false
33831  $clm_statistics    = false
33832  $clm_play          = false
33833  $clm_sample_type   = Mus_lfloat
33834  $clm_header_type   = Mus_next
33835  $clm_delete_reverb = false
33836  $clm_reverb        = nil
33837  $clm_reverb_data   = []
33838  #
33839  with_sound(:reverb, :jl_reverb) do
33840    attract(0, 1, 0.1, 2.0)
33841    expfil(0, 2, 0.2, 0.01, 0.1, "oboe.snd", "fyow.snd")
33842    fm_violin(0, 0.1, 660, 0.1, :reverb_amount, 0.1)
33843    anoi("oboe.snd", 1, 1)
33844    ind = open_sound("oboe.snd")
33845    ind1 = open_sound("now.snd")
33846    zp = make_zipper(make_env(:envelope, [0, 0, 1, 1], :length, 22050),
33847                     0.05,
33848                     make_env(:envelope, [0, mus_srate() * 0.05], :length, 22050))
33849    reader0 = make_sampler(0, ind, 0)
33850    reader1 = make_sampler(0, ind1, 0)
33851    22050.times do |i| outa(i, zipper(zp, reader0, reader1), $output) end
33852    [ind, ind1].apply(:close_sound)
33853  end
33854  if sound?(ind = find_sound("test.snd"))
33855    select_sound(ind)
33856    zip_sound(1, 1, "fyow.snd", "now.snd", [0, 0, 1, 1], 0.05)
33857    zip_sound(2, 3, "mb.snd", "fyow.snd", [0, 0, 1, 0, 1.5, 1, 3, 1], 0.025)
33858    close_sound(ind)
33859  else
33860    snd_display("zip_sound: no test.snd?")
33861  end
33862  #
33863  ind = open_sound("oboe.snd")
33864  pv = make_pvocoder(256, 4, 64)
33865  rd = make_sampler(0)
33866  map_channel(lambda do |y| pvocoder(pv, rd) end)
33867  close_sound(ind)
33868  #
33869  with_sound(:to_snd, :snd) do
33870    make_birds
33871  end
33872  Snd.sounds.apply(:close_sound)
33873  #
33874  # clm23.scm tests skipped
33875  #
33876  file = with_sound(:clipped,     false,
33877                    :sample_type, Mus_bfloat,
33878                    :header_type, Mus_next) do
33879    fm_violin(0, 0.1, 440, PI)
33880  end.output
33881  ind = find_sound(file)
33882  if fneq(res = maxamp(ind), PI)
33883    snd_display("clipped false: %s?", res)
33884  end
33885  close_sound(ind)
33886  file = with_sound(:clipped,     true,
33887                    :sample_type, Mus_bfloat,
33888                    :header_type, Mus_next) do
33889    fm_violin(0, 0.1, 440, PI)
33890  end.output
33891  ind = find_sound(file)
33892  if fneq(res = maxamp(ind), 1.0)
33893    snd_display("clipped true: %s?", res)
33894  end
33895  close_sound(ind)
33896  file = with_sound(:clipped,     false,
33897                    :sample_type, Mus_bfloat,
33898                    :header_type, Mus_next,
33899                    :scaled_by,   0.1) do
33900    fm_violin(0, 0.1, 440, PI)
33901  end.output
33902  ind = find_sound(file)
33903  if fneq(res = maxamp(ind), 0.314159)
33904    snd_display("scaled_by: %s?", res)
33905  end
33906  close_sound(ind)
33907  file = with_sound(:clipped,     false,
33908                    :sample_type, Mus_bfloat,
33909                    :header_type, Mus_next,
33910                    :scaled_to,   0.1) do
33911    fm_violin(0, 0.1, 440, PI)
33912  end.output
33913  ind = find_sound(file)
33914  if fneq(res = maxamp(ind), 0.1)
33915    snd_display("scaled_to: %s?", res)
33916  end
33917  close_sound(ind)
33918  #
33919  old_bufsize = $clm_file_buffer_size
33920  old_tsize = $clm_table_size
33921  old_arrp = $clm_array_print_length
33922  $clm_file_buffer_size = 1024 * 1024
33923  $clm_table_size = 256
33924  $clm_array_print_length = 123
33925  tsize = 0
33926  arrp = 0
33927  mx = 0
33928  file = with_sound(:sample_type, Mus_bfloat,
33929                    :header_type, Mus_next) do
33930    mx = mus_file_buffer_size
33931    tsize = clm_table_size
33932    arrp = mus_array_print_length
33933    fm_violin(0, 0.1, 440, 0.1)
33934  end.output
33935  ind = find_sound(file)
33936  if mx != 1024 * 1024
33937    snd_display("$clm_file_buffer_size: %s?", mx)
33938  end
33939  if tsize != 256
33940    snd_display("$clm_table_size: %s?", tsize)
33941  end
33942  if arrp != 123
33943    snd_display("$clm_array_print_length: %s?", arrp)
33944  end
33945  $clm_file_buffer_size = old_bufsize
33946  $clm_table_size = old_tsize
33947  $clm_array_print_length = old_arrp
33948  close_sound(ind)
33949  #
33950  file = with_sound() do fm_violin(0, 3.0, 440, 0.1) end.output
33951  ind = find_sound(file)
33952  set_amp_control(0.5, ind)
33953  set_x_bounds([1.0, 2.0], ind, 0)
33954  file = with_sound(:clm, false) do fm_violin(0, 4.0, 440, 0.1) end.output
33955  ind = find_sound(file)
33956  res = amp_control(ind)
33957  snd_test_neq(res, 0.5, "update ws amp")
33958  res = x_bounds(ind, 0)
33959  req = [1.0, 2.0]
33960  if fneq(res[0], req[0]) or fneq(res[1], req[1])
33961    snd_format_neq(res, req, "update ws bounds")
33962  end
33963  close_sound(ind)
33964  #
33965  file = with_sound(:reverb, :jc_reverb) do
33966    fm_violin(0, 0.1, 440, 0.1, :reverb_amount, 0.1)
33967  end.output
33968  ind = find_sound(file)
33969  mx = maxamp(ind)
33970  file = with_sound(:reverb, :jc_reverb,
33971    :reverb_data, [:volume, 12.0, :amp_env, [0, 0, 1, 1, 20, 1, 21, 0]]) do
33972    fm_violin(0, 4, 440, 0.1, :reverb_amount, 0.1)
33973  end.output
33974  ind = find_sound(file)
33975  if maxamp(ind) <= mx
33976    snd_display("reverb_data: %s %s?", mx, maxamp(ind))
33977  end
33978  close_sound(ind)
33979  #
33980  ind = open_sound("oboe.snd")
33981  step_src
33982  if (framples - 24602).abs > 100
33983    snd_display("step_src framples: %s (%s)?", framples, edits)
33984  end
33985  close_sound(ind)
33986  Snd.sounds.apply(:close_sound)
33987  #
33988  file = with_sound do
33989    gen = make_sinc_train(440.0, 9 * PI)
33990    1102.times do |i| outa(i, sinc_train(gen), $output) end
33991  end.output
33992  ind = find_sound(file)
33993  if sound?(ind)
33994    if fneq(res = maxamp(ind), 1.0)
33995      snd_display("with_sound sinc_train max: %s?", res)
33996    end
33997    close_sound(ind)
33998  else
33999    snd_display("with_sound let -> %s (%s)?", ind, file)
34000  end
34001end
34002
34003require "strad"
34004require "noise"
34005require "piano"
34006require "maraca"
34007require "play"
34008require "prc95"
34009require "singer"
34010require "zip"
34011
34012def test_23
34013  $clm_verbose    = false
34014  $clm_statistics = false
34015  $clm_play       = false
34016  $clm_info       = $DEBUG
34017  test_23_00
34018  test_23_01
34019  test_23_02
34020  test_23_03
34021  test_23_04
34022end
34023
34024# ---------------- test 28: errors ----------------
34025
34026def check_error_tag(expected_tag, &thunk)
34027  tag = Snd.catch do
34028    thunk.call
34029  end
34030  if tag.first != expected_tag
34031    snd_display_prev_caller("%s %s: %s",
34032                            get_func_name,
34033                            expected_tag.inspect,
34034                            tag.inspect)
34035  end
34036end
34037
34038Procs = [
34039  :add_mark, :add_sound_file_extension, :add_source_file_extension,
34040  :sound_file_extensions, :sound_file?, :add_to_main_menu,
34041  :add_to_menu, :add_transform, :amp_control, :ask_about_unsaved_edits,
34042  :as_one_edit, :ask_before_overwrite,
34043  :auto_resize, :auto_update, :autocorrelate,
34044  :axis_color, :axis_info, :axis_label_font, :axis_numbers_font,
34045  :basic_color, :bind_key, :apply_controls,
34046  :change_samples_with_origin, :channel_style, :channel_widgets,
34047  :channels, :chans, :peaks_font, :bold_peaks_font, :close_sound,
34048  :combined_data_color, :color_cutoff,
34049  :color_orientation_dialog, :colormap_ref, :add_colormap,
34050  :delete_colormap, :colormap_size, :colormap_name, :color_inverted,
34051  :color_scale, :color2list, :colormap, :color?, :comment,
34052  :contrast_control, :contrast_control_amp,
34053  :channel_properties, :channel_property, :controls2channel,
34054  :amp_control_bounds, :speed_control_bounds, :expand_control_bounds,
34055  :contrast_control_bounds, :sound_file_extensions,
34056  :reverb_control_length_bounds, :reverb_control_scale_bounds,
34057  :cursor_update_interval, :cursor_location_offset,
34058  :auto_update_interval,
34059  :current_font, :cursor, :cursor_color, :with_tracking_cursor,
34060  :cursor_size, :cursor_style, :tracking_cursor_style,
34061  :dac_combines_channels, :dac_size, :clipping, :data_color,
34062  :sample_type, :data_location, :data_size, :default_output_chans,
34063  :default_output_sample_type, :default_output_srate,
34064  :default_output_header_type, :insert_file_dialog, :file_write_date,
34065  :define_envelope, :delete_mark, :delete_marks, :forget_region,
34066  :delete_sample, :delete_samples, :delete_samples_and_smooth,
34067  :delete_selection, :delete_selection_and_smooth,
34068  :dialog_widgets, :display_edits, :dot_size, :draw_dot,
34069  :draw_dots, :draw_line, :draw_lines, :draw_string, :edit_header_dialog,
34070  :edit_fragment, :edit_list2function, :edit_position, :edit_tree,
34071  :edits, :env_selection, :env_sound, :enved_envelope, :enved_base,
34072  :enved_clip?, :enved_in_dB, :enved_dialog, :enved_style,
34073  :enved_power, :enved_target, :enved_waveform_color, :enved_wave?,
34074  :eps_file, :eps_left_margin, :eps_bottom_margin, :eps_size,
34075  :expand_control, :expand_control_hop, :expand_control_jitter,
34076  :expand_control_length, :expand_control_ramp, :expand_control?, :fft,
34077  :fft_window_beta, :fft_window_alpha, :fft_with_phases,
34078  :fft_log_frequency, :fft_log_magnitude, :transform_size,
34079  :disk_kspace, :transform_graph_type, :fft_window,
34080  :transform_graph?, :mix_file_dialog, :file_name, :fill_polygon,
34081  :fill_rectangle, :filter_sound, :filter_control_in_dB,
34082  :filter_control_envelope, :enved_filter_order, :enved_filter,
34083  :filter_control_in_hz, :filter_control_order, :filter_selection,
34084  :filter_channel, :filter_control_waveform_color, :filter_control?,
34085  :find_mark, :find_sound, :finish_progress_report, :foreground_color,
34086  :framples, :free_sampler, :graph, :transform?, :delete_transform,
34087  :graph_color, :graph_cursor, :graph_data, :graph2ps, :gl_graph2ps,
34088  :graph_style, :lisp_graph?, :graphs_horizontal, :header_type,
34089  :help_dialog, :info_dialog, :highlight_color, :call_in,
34090  :insert_region, :insert_sample, :insert_samples,
34091  :insert_samples_with_origin, :insert_selection, :insert_silence,
34092  :insert_sound, :just_sounds, :key, :key_binding, :left_sample,
34093  :listener_color, :listener_font, :listener_prompt,
34094  :listener_selection, :listener_text_color, :main_widgets,
34095  :make_color, :make_graph_data, :make_mix_sampler, :make_player,
34096  :make_region, :make_region_sampler, :make_sampler, :map_chan,
34097  :mark_color, :mark_name, :mark_properties, :mark_property,
34098  :mark_sample, :mark_sync, :mark_sync_max,
34099  :mark_home, :marks, :mark?, :max_transform_peaks, :max_regions,
34100  :maxamp, :maxamp_position, :menu_widgets,
34101  :min_dB, :log_freq_start, :mix, :mixes, :mix_amp,
34102  :mix_amp_env, :mix_color, :mix_length, :mix?, :view_mixes_dialog,
34103  :mix_position, :mix_dialog_mix, :mix_name, :mix_sync_max,
34104  :mix_sync, :mix_properties, :mix_property, :mix_region,
34105  :mix_sampler?, :mix_selection, :mix_home, :mix_speed,
34106  :mix_tag_height, :mix_tag_width, :mark_tag_height, :mark_tag_width,
34107  :mix_tag_y, :mix_vct, :mix_waveform_height, :time_graph_style,
34108  :lisp_graph_style, :transform_graph_style,
34109  :read_mix_sample, :next_sample, :read_region_sample,
34110  :show_full_duration, :show_full_range, :initial_beg, :initial_dur,
34111  :transform_normalization, :open_file_dialog_directory,
34112  :open_raw_sound, :open_sound, :color_orientation_dialog,
34113  :previous_sample, :peaks, :player?, :players,
34114  :play_arrow_size, :position_color,
34115  :position2x, :position2y, :print_length, :progress_report, :read_only,
34116  :redo_edit, :region_chans, :view_regions_dialog, :region_home,
34117  :region_graph_style, :region_framples, :region_position, :region_maxamp,
34118  :region_maxamp_position, :remember_sound_state, :selection_maxamp,
34119  :selection_maxamp_position, :region_sample, :region2vct,
34120  :region_srate, :regions, :region?, :remove_from_menu,
34121  :reset_controls, :restore_controls, :restore_region,
34122  :reverb_control_decay, :reverb_control_feedback,
34123  :reverb_control_length, :reverb_control_lowpass,
34124  :reverb_control_scale, :reverb_control?, :reverse_sound,
34125  :reverse_selection, :revert_sound, :right_sample, :sample,
34126  :sampler_at_end?, :sampler?, :samples, :sampler_position,
34127  :sash_color, :save_controls, :ladspa_dir, :peak_env_dir,
34128  :save_dir, :save_edit_history, :save_envelopes, :save_listener,
34129  :save_marks, :save_region, :save_selection, :save_sound,
34130  :save_sound_as, :save_state, :save_state_file,
34131  :scale_by, :scale_selection_by, :scale_selection_to, :scale_to,
34132  :search_procedure, :select_all, :select_channel,
34133  :select_sound, :selected_channel, :selected_data_color,
34134  :selected_graph_color, :selected_sound, :selection_position,
34135  :selection_color, :selection_creates_region, :selection_framples,
34136  :selection_member?, :selection?, :short_file_name,
34137  :show_axes, :show_controls, :show_transform_peaks, :show_indices,
34138  :show_listener, :show_selection, :unselect_all, :show_marks,
34139  :show_mix_waveforms, :show_selection_transform, :show_y_zero,
34140  :sinc_width, :show_grid, :show_sonogram_cursor, :grid_density,
34141  :smooth_sound, :smooth_selection, :snd_spectrum, :snd_tempnam,
34142  :snd_version, :sound_files_in_directory, :sound_loop_info,
34143  :sound_widgets, :soundfont_info, :sound?, :sounds,
34144  :spectrum_end, :spectro_hop, :spectrum_start, :spectro_x_angle,
34145  :spectro_x_scale, :spectro_y_angle, :spectro_y_scale,
34146  :spectro_z_angle, :spectro_z_scale, :speed_control,
34147  :speed_control_style, :speed_control_tones, :squelch_update,
34148  :srate, :src_sound, :src_selection, :start_progress_report,
34149  :stop_player, :stop_playing, :swap_channels, :syncd_marks,
34150  :sync, :sync_max, :sound_properties, :sound_property,
34151  :temp_dir, :text_focus_color, :tiny_font,
34152  :region_sampler?, :transform_dialog, :transform_sample, :transform2vct,
34153  :transform_framples, :transform_type, :with_file_monitor,
34154  :unbind_key, :update_transform_graph, :update_time_graph,
34155  :update_lisp_graph, :update_sound, :clm_table_size,
34156  :with_verbose_cursor, :view_sound, :wavelet_type,
34157  :with_inset_graph, :with_interrupts, :with_pointer_focus,
34158  :with_smpte_label, :with_toolbar, :with_tooltips,
34159  :with_menu_icons, :save_as_dialog_src,
34160  :save_as_dialog_auto_comment, :time_graph?, :time_graph_type,
34161  :wavo_hop, :wavo_trace, :window_height, :window_width,
34162  :window_x, :window_y, :with_mix_tags, :with_relative_panes,
34163  :with_gl, :x_axis_style, :beats_per_measure, :beats_per_minute,
34164  :x_bounds, :x_position_slider, :x2position, :x_zoom_slider,
34165  :mus_header_type2string, :mus_sample_type2string, :y_bounds,
34166  :y_position_slider, :y2position, :y_zoom_slider, :zero_pad,
34167  :zoom_color, :zoom_focus_style, :sync_style,
34168  :mus_set_formant_radius_and_frequency,
34169  :mus_sound_samples, :mus_sound_framples, :mus_sound_duration,
34170  :mus_sound_datum_size, :mus_sound_data_location, :data_size,
34171  :mus_sound_chans, :mus_sound_srate, :mus_sound_header_type,
34172  :mus_sound_sample_type, :mus_sound_length,
34173  :mus_sound_type_specifier, :mus_header_type_name,
34174  :mus_sample_type_name, :mus_sound_comment,
34175  :mus_sound_write_date, :mus_bytes_per_sample,
34176  :mus_sound_loop_info, :mus_sound_mark_info,
34177  :mus_sound_maxamp, :mus_sound_maxamp_exists?,
34178  :mus_clipping, :mus_file_clipping, :mus_header_raw_defaults,
34179  :moving_average, :moving_average?, :make_moving_average,
34180  :mus_expand_filename, :all_pass, :all_pass?,
34181  :amplitude_modulate, :array2file, :array_interp,
34182  :mus_interpolate, :asymmetric_fm, :asymmetric_fm?,
34183  :comb, :comb?, :filtered_comb, :filtered_comb?,
34184  :contrast_enhancement, :convolution, :convolve, :convolve?,
34185  :db2linear, :degrees2radians, :delay, :delay?, :dot_product,
34186  :env, :env_interp, :env?, :file2array, :file2frample,
34187  :file2frample?, :file2sample, :file2sample?,
34188  :filter, :filter?, :fir_filter, :fir_filter?, :formant,
34189  :formant_bank, :formant_bank?, :formant?,
34190  :frample2file, :frample2file?, :frample2frample,
34191  :granulate, :granulate?, :hz2radians, :iir_filter, :iir_filter?,
34192  :in_any, :ina, :inb, :linear2db, :locsig, :locsig_ref,
34193  :locsig_reverb_ref, :locsig_reverb_set!, :locsig_set!,
34194  :locsig?, :make_all_pass, :make_asymmetric_fm, :make_comb,
34195  :make_convolve, :make_delay, :make_env, :make_fft_window,
34196  :make_file2frample, :make_file2sample, :make_filter,
34197  :make_fir_filter, :make_formant, :make_frample2file,
34198  :make_granulate, :make_iir_filter, :make_locsig, :move_locsig,
34199  :make_notch, :make_one_pole, :make_one_zero,
34200  :make_oscil, :make_pulse_train, :make_rand, :make_rand_interp,
34201  :make_readin, :make_sample2file, :make_sawtooth_wave,
34202  :make_square_wave, :make_src, :make_ssb_am,
34203  :make_table_lookup, :make_triangle_wave, :make_two_pole,
34204  :make_two_zero, :make_wave_train, :move_sound,
34205  :make_move_sound, :move_sound?, :mus_float_equal_fudge_factor,
34206  :mus_array_print_length, :mus_channel, :mus_channels,
34207  :make_polyshape, :polyshape, :polyshape?, :mus_close,
34208  :mus_data, :mus_feedback, :mus_feedforward, :mus_fft,
34209  :mus_frequency, :mus_hop, :mus_increment, :mus_input?,
34210  :mus_file_name, :mus_length, :mus_location, :mus_order,
34211  :mus_output?, :mus_phase, :mus_ramp, :mus_random,
34212  :mus_scaler, :mus_srate, :mus_xcoeffs, :mus_ycoeffs,
34213  :notch, :notch?, :one_pole, :one_pole?, :one_zero, :one_zero?,
34214  :oscil, :oscil?, :out_any, :outa, :outb, :outc, :outd,
34215  :partials2polynomial, :partials2wave, :phase_partials2wave,
34216  :polynomial, :pulse_train, :pulse_train?, :radians2degrees,
34217  :radians2hz, :rand, :rand_interp, :rand_interp?, :rand?, :readin,
34218  :readin?, :rectangular2polar, :rectangular2magnitudes, :ring_modulate,
34219  :sample2file, :sample2file?, :sawtooth_wave, :sawtooth_wave?,
34220  :spectrum, :square_wave, :square_wave?, :src, :src?, :ssb_am,
34221  :ssb_am?, :table_lookup, :table_lookup?, :tap, :triangle_wave,
34222  :triangle_wave?, :two_pole, :two_pole?, :two_zero, :two_zero?,
34223  :wave_train, :wave_train?, :make_vct, :vct_add!, :vct_subtract!,
34224  :vct_copy, :vct_length, :vct_multiply!, :vct_offset!, :vct_ref,
34225  :vct_scale!, :vct_set!, :vct_peak, :vct?, :list2vct, :vct2list,
34226  :vector2vct, :vct2vector, :vct_move!, :vct_reverse!, :vct_subseq,
34227  :vct, :little_endian?, :vct2string, :clm_channel, :env_channel,
34228  :map_channel, :scan_channel, :reverse_channel, :seconds2samples,
34229  :samples2seconds, :vct2channel, :smooth_channel, :channel2vct,
34230  :src_channel, :scale_channel, :ramp_channel, :pad_channel,
34231  :normalize_channel, :cursor_position, :mus_sound_prune,
34232  :mus_sound_forget, :xramp_channel, :snd2sample, :snd2sample?,
34233  :make_snd2sample, :beats_per_minute, :beats_per_measure,
34234  :channel_amp_envs, :convolve_files, :filter_control_coeffs,
34235  :locsig_type, :make_phase_vocoder, :mus_describe,
34236  :mus_error_type2string, :mus_file_buffer_size, :mus_name,
34237  :mus_offset, :mus_reset, :mus_rand_seed, :mus_width,
34238  :phase_vocoder?, :polar2rectangular, :phase_vocoder_amp_increments,
34239  :phase_vocoder_amps, :phase_vocoder_freqs, :phase_vocoder_phase_increments,
34240  :phase_vocoder_phases, :mus_generator?, :read_sample,
34241  :reset_listener_cursor, :goto_listener_end, :sampler_home,
34242  :selection_chans, :selection_srate, :snd_gcs, :snd_font,
34243  :snd_color, :snd_warning, :channel_data, :x_axis_label,
34244  :variable_graph?, :y_axis_label, :snd_url, :snd_urls,
34245  :free_player, :delay_tick, :playing, :draw_axes,
34246  :copy_sampler, :html_dir, :html_program, :make_fir_coeffs,
34247  :mus_interp_type, :mus_run, :phase_vocoder, :player_home,
34248  :redo_edit, :undo_edit, :widget_position, :widget_size, :focus_widget]
34249
34250Set_procs = [
34251  :amp_control, :ask_before_overwrite, :auto_resize, :sound_file_extensions,
34252  :auto_update, :axis_color, :axis_label_font, :axis_numbers_font,
34253  :channel_style, :peaks_font, :bold_peaks_font, :show_full_duration,
34254  :show_full_range, :initial_beg, :initial_dur, :color_cutoff,
34255  :color_inverted, :color_scale, :contrast_control, :contrast_control_amp,
34256  :combined_data_color, :amp_control_bounds, :speed_control_bounds,
34257  :expand_control_bounds, :contrast_control_bounds,
34258  :reverb_control_length_bounds, :reverb_control_scale_bounds,
34259  :cursor_update_interval, :cursor_location_offset, :contrast_control?,
34260  :auto_update_interval, :current_font, :cursor, :cursor_color,
34261  :channel_properties, :channel_property, :with_tracking_cursor, :cursor_size,
34262  :cursor_style, :tracking_cursor_style, :dac_combines_channels, :dac_size,
34263  :clipping, :data_color, :default_output_chans, :default_output_sample_type,
34264  :default_output_srate, :default_output_header_type, :dot_size,
34265  :enved_envelope, :enved_base, :enved_clip?, :enved_in_dB, :enved_style,
34266  :enved_power, :enved_target, :enved_waveform_color, :enved_wave?, :eps_file,
34267  :eps_left_margin,
34268  :eps_bottom_margin, :eps_size, :expand_control, :expand_control_hop,
34269  :expand_control_jitter, :expand_control_length, :expand_control_ramp,
34270  :expand_control?, :fft_window_beta, :fft_window_alpha, :fft_with_phases,
34271  :fft_log_frequency, :fft_log_magnitude, :transform_size,
34272  :transform_graph_type, :fft_window, :transform_graph?,
34273  :filter_control_in_dB, :filter_control_envelope, :axis_color,
34274  :enved_filter_order, :enved_filter, :filter_control_in_hz,
34275  :filter_control_order, :filter_control_waveform_color, :filter_control?,
34276  :foreground_color, :graph_color, :graph_cursor, :graph_style, :lisp_graph?,
34277  :graphs_horizontal, :highlight_color, :just_sounds, :left_sample,
34278  :listener_color, :listener_font, :listener_prompt,
34279  :listener_text_color, :mark_color, :mark_name, :mark_properties,
34280  :mark_property, :mark_sample, :mark_sync, :max_transform_peaks,
34281  :max_regions, :min_dB, :log_freq_start, :mix_amp,
34282  :mix_amp_env, :mix_color, :mix_name, :mix_position, :mix_sync,
34283  :mix_properties, :mix_property, :mix_speed, :mix_tag_height,
34284  :mix_tag_width, :mix_tag_y, :mark_tag_width, :mark_tag_height,
34285  :mix_waveform_height, :transform_normalization,
34286  :open_file_dialog_directory, :position_color, :print_length,
34287  :play_arrow_size, :region_graph_style, :reverb_control_decay,
34288  :reverb_control_feedback, :reverb_control_length,
34289  :reverb_control_lowpass, :reverb_control_scale, :time_graph_style,
34290  :lisp_graph_style, :transform_graph_style, :reverb_control?,
34291  :sash_color, :ladspa_dir, :peak_env_dir, :save_dir, :save_state_file,
34292  :selected_data_color, :selected_graph_color, :selection_color,
34293  :selection_creates_region, :show_axes, :show_controls, :show_transform_peaks,
34294  :show_indices, :show_marks, :show_mix_waveforms, :show_selection_transform,
34295  :show_listener, :show_y_zero, :show_grid, :show_sonogram_cursor, :sinc_width,
34296  :spectrum_end, :spectro_hop, :spectrum_start, :spectro_x_angle, :grid_density,
34297  :spectro_x_scale, :spectro_y_angle, :spectro_y_scale, :spectro_z_angle,
34298  :spectro_z_scale, :speed_control, :speed_control_style, :speed_control_tones,
34299  :squelch_update, :sync, :sound_properties, :sound_property, :temp_dir,
34300  :text_focus_color, :tiny_font, :y_bounds, :transform_type,
34301  :with_file_monitor, :with_verbose_cursor, :with_inset_graph, :with_interrupts,
34302  :with_pointer_focus, :wavelet_type, :x_bounds, :with_smpte_label,
34303  :with_toolbar, :with_tooltips, :with_menu_icons, :save_as_dialog_src,
34304  :save_as_dialog_auto_comment, :time_graph?, :wavo_hop,
34305  :wavo_trace, :with_gl, :with_mix_tags, :x_axis_style,
34306  :beats_per_minute, :zero_pad, :zoom_color, :zoom_focus_style,
34307  :sync_style, :with_relative_panes, :window_x, :window_y,
34308  :window_width, :window_height, :mix_dialog_mix, :beats_per_measure,
34309  :channels, :chans, :colormap, :comment, :sample_type, :data_location,
34310  :data_size, :edit_position, :framples, :header_type, :maxamp,
34311  :read_only, :right_sample, :sample, :samples,
34312  :selected_channel, :colormap_size, :selected_sound, :selection_position,
34313  :selection_framples, :selection_member?, :sound_loop_info, :srate,
34314  :time_graph_type, :x_position_slider, :x_zoom_slider,
34315  :y_position_slider, :y_zoom_slider,
34316  :mus_array_print_length, :mus_float_equal_fudge_factor,
34317  :mus_feedback, :mus_feedforward, :mus_frequency, :mus_hop,
34318  :mus_increment, :mus_length, :mus_location, :mus_phase, :mus_ramp,
34319  :mus_scaler, :x_axis_label, :locsig_type, :mus_file_buffer_size,
34320  :mus_rand_seed, :mus_width, :clm_table_size, :mus_offset, :html_dir,
34321  :html_program, :widget_position, :widget_size,
34322  :mus_clipping, :mus_header_raw_defaults]
34323
34324Make_procs = [
34325  :make_all_pass, :make_asymmetric_fm, :make_snd2sample, :make_moving_average,
34326  :make_moving_max, :make_comb, :make_filtered_comb, :make_convolve,
34327  :make_delay, :make_env, :make_fft_window, :make_file2frample,
34328  :make_file2sample, :make_filter, :make_fir_filter, :make_formant,
34329  :make_frample2file, :make_granulate, :make_iir_filter, :make_locsig,
34330  :make_notch, :make_one_pole, :make_one_zero, :make_oscil,
34331  :make_pulse_train, :make_rand, :make_rand_interp, :make_readin,
34332  :make_sample2file, :make_sawtooth_wave, :make_square_wave, :make_src,
34333  :make_table_lookup, :make_triangle_wave, :make_two_pole, :make_two_zero,
34334  :make_wave_train, :make_phase_vocoder, :make_ssb_am, :make_polyshape,
34335  :make_color, :make_player, :make_region]
34336
34337Keyargs = [
34338  :frequency, :initial_phase, :wave, :cosines, :amplitude, :ratio, :size,
34339  :a0, :a1, :a2, :b1, :b2, :input, :srate, :file, :channel, :start,
34340  :initial_contents, :initial_element, :scaler, :feedforward, :feedback,
34341  :max_size, :radius, :gain, :partials, :r, :a, :n, :fill_time, :order,
34342  :xcoeffs, :ycoeffs, :envelope, :base, :duration, :offset, :end,
34343  :direction, :degree, :distance, :reverb, :output, :fft_size, :expansion,
34344  :length, :hop, :ramp, :jitter, :type, :format, :comment, :channels,
34345  :filter, :revout, :width, :edit, :synthesize, :analyze, :interp,
34346  :overlap, :pitch, :distribution, :sines, :dur]
34347
34348class Array
34349  # If body results in true, returns the rejected elements in a new
34350  # array and remove these elements from the original.
34351  def remove_if!
34352    ret = []
34353    self.map! do |x|
34354      if yield(x)
34355        ret.push(x)
34356        nil
34357      else
34358        x
34359      end
34360    end
34361    self.compact!
34362    ret
34363  end
34364end
34365
34366Procs00 = Procs.remove_if! do |n|
34367  function?(n) and arity_ok(n, 0)
34368end
34369Set_procs00 = Set_procs.remove_if! do |n|
34370  function?(n) and set_arity_ok(n, 1)
34371end
34372Procs01 = Procs.remove_if! do |n|
34373  function?(n) and arity_ok(n, 1)
34374end
34375Set_procs01 = Set_procs.remove_if! do |n|
34376  function?(n) and set_arity_ok(n, 2)
34377end
34378Procs02 = Procs.remove_if! do |n|
34379  function?(n) and arity_ok(n, 2)
34380end
34381Set_procs02 = Set_procs.remove_if! do |n|
34382  function?(n) and set_arity_ok(n, 3)
34383end
34384Procs03 = Procs.remove_if! do |n|
34385  function?(n) and arity_ok(n, 3)
34386end
34387Set_procs03 = Set_procs.remove_if! do |n|
34388  function?(n) and set_arity_ok(n, 4)
34389end
34390Procs04 = Procs.remove_if! do |n|
34391  function?(n) and arity_ok(n, 4)
34392end
34393Set_procs04 = Set_procs.remove_if! do |n|
34394  function?(n) and set_arity_ok(n, 5)
34395end
34396Procs05 = Procs.remove_if! do |n|
34397  function?(n) and arity_ok(n, 5)
34398end
34399Procs06 = Procs.remove_if! do |n|
34400  function?(n) and arity_ok(n, 6)
34401end
34402# Procs07 is not used
34403Procs07 = Procs.remove_if! do |n|
34404  function?(n) and arity_ok(n, 7)
34405end
34406Procs08 = Procs.remove_if! do |n|
34407  function?(n) and arity_ok(n, 8)
34408end
34409Procs10 = Procs.remove_if! do |n|
34410  function?(n) and arity_ok(n, 10)
34411end
34412
34413$delay_32 = make_oscil(440)
34414$color_95 = vector(1, 2, 3)
34415$vector_0 = make_comb(0.1, 3)
34416$vct_3    = Vct.new(3)
34417
34418def test_28_00
34419  procs1 = [
34420    :amp_control, :apply_controls, :comment, :contrast_control,
34421    :amp_control_bounds, :speed_control_bounds, :expand_control_bounds,
34422    :contrast_control_bounds, :reverb_control_length_bounds,
34423    :reverb_control_scale_bounds, :contrast_control_amp,
34424    :contrast_control?, :sample_type, :data_location, :data_size,
34425    :expand_control, :expand_control_hop, :expand_control_jitter,
34426    :expand_control_length, :expand_control_ramp, :expand_control?,
34427    :filter_control_in_dB, :filter_control_in_hz, :filter_control_envelope,
34428    :filter_control_order, :filter_control?, :finish_progress_report,
34429    :framples, :header_type, :progress_report, :read_only, :reset_controls,
34430    :restore_controls, :reverb_control_decay, :reverb_control_feedback,
34431    :reverb_control_length, :reverb_control_lowpass, :reverb_control_scale,
34432    :reverb_control?, :save_controls, :select_sound, :short_file_name,
34433    :sound_loop_info, :soundfont_info, :speed_control,
34434    :speed_control_style, :speed_control_tones, :srate, :channel_style,
34435    :start_progress_report, :sync, :sound_properties, :sound_property,
34436    :swap_channels]
34437  procs1.each do |n|
34438    tag = Snd.catch do snd_func(n, integer2sound(123)) end
34439    if tag.first != :wrong_type_arg and
34440        tag.first != :no_such_sound
34441      snd_display("snd :no_such_sound %s: %s", n, tag)
34442    end
34443  end
34444  [sqrt(-1.0), 1.5, "hiho"].each do |arg|
34445    procs1.each do |n|
34446      next if n == :progress_report
34447      tag = Snd.catch do snd_func(n, arg) end
34448      if tag.first != :wrong_type_arg and
34449          tag.first != :mus_error and
34450          tag.first != :no_such_sound
34451        snd_display("snd :wrong_type_arg %s: %s %s", n, tag, arg)
34452      end
34453    end
34454  end
34455  progs2 = [
34456    :amp_control, :channels, :chans, :comment, :contrast_control,
34457    :amp_control_bounds, :speed_control_bounds, :expand_control_bounds,
34458    :contrast_control_bounds, :reverb_control_length_bounds,
34459    :reverb_control_scale_bounds, :contrast_control_amp,
34460    :contrast_control?, :sample_type, :data_location, :data_size,
34461    :expand_control, :expand_control_hop, :expand_control_jitter,
34462    :expand_control_length, :expand_control_ramp, :expand_control?,
34463    :filter_control_in_dB, :filter_control_in_hz, :filter_control_envelope,
34464    :filter_control_order, :filter_control?, :framples, :header_type,
34465    :read_only, :reverb_control_decay, :reverb_control_feedback,
34466    :reverb_control_length, :reverb_control_lowpass,
34467    :reverb_control_scale, :reverb_control?, :sound_loop_info,
34468    :speed_control, :speed_control_style, :speed_control_tones,
34469    :srate, :channel_style, :sync]
34470  [sqrt(-1.0), 1.5, "hiho"].each do |arg|
34471    progs2.each_with_index do |n, i|
34472      if (tag = Snd.catch do
34473            case n
34474            when :channels, :chans, :sample_type, :data_location, :data_size,
34475              :header_type, :srate, :comment
34476              # g_set_channels(snd, val)
34477              set_snd_func(n, arg, 0)
34478            else
34479              # g_set_amp_control(val, snd, chn)
34480              set_snd_func(n, 0, arg)
34481            end
34482          end).first != :wrong_type_arg
34483        snd_display("snd set :wrong_type_arg %s %s: %s %s", i, n, tag, arg)
34484      end
34485    end
34486  end
34487  progs3 = [
34488    :amp_control, :contrast_control, :amp_control_bounds,
34489    :speed_control_bounds, :expand_control_bounds, :contrast_control_bounds,
34490    :reverb_control_length_bounds, :reverb_control_scale_bounds,
34491    :contrast_control_amp, :contrast_control?, :expand_control,
34492    :expand_control_hop, :expand_control_jitter,
34493    :expand_control_length, :expand_control_ramp, :expand_control?,
34494    :filter_control_in_dB, :filter_control_in_hz,
34495    :filter_control_envelope, :filter_control_order, :filter_control?,
34496    :reverb_control_decay, :reverb_control_feedback,
34497    :reverb_control_length, :reverb_control_lowpass,
34498    :reverb_control_scale, :reverb_control?, :speed_control,
34499    :speed_control_style, :speed_control_tones, :channel_style, :sync]
34500  index = open_sound("obtest.snd")
34501  [sqrt(-1.0), "hiho"].each do |arg|
34502    progs3.each_with_index do |n, i|
34503      tag = Snd.catch do set_snd_func(n, arg, index) end
34504      if tag.first != :wrong_type_arg
34505        snd_display("snd safe set :wrong_type_arg %s %s: %s %s", i, n, tag, arg)
34506      end
34507    end
34508  end
34509  close_sound(index)
34510  [Array.new(1), "hiho", sqrt(-1.0), 1.5, [1, 0], [0, 1]].each do |arg|
34511    [:make_vct, :vct_copy, :vct_length, :vct2list, :vct_peak].each do |n|
34512      if (tag = Snd.catch do snd_func(n, arg) end).first != :wrong_type_arg
34513        snd_display("vct 0 :wrong_type_arg %s: %s %s", n, tag, arg)
34514      end
34515    end
34516  end
34517  [Array.new(1), "hiho", sqrt(-1.0), 1.5, [1, 0], [0, 1]].each do |arg1|
34518    ["hiho", sqrt(-1.0), 1.5, [1, 0], [0, 1]].each do |arg2|
34519      [:vct_add!, :vct_subtract!,
34520       :vct_multiply!, :vct_ref, :vct_scale!].each do |n|
34521        case tag = (res = Snd.catch do snd_func(n, arg1, arg2) end).first
34522        when :wrong_type_arg, :wrong_number_of_args, :mus_error
34523          nil
34524        else
34525          snd_display("vct 1 :wrong_whatever %s: %s %s %s (%s)",
34526                      n, tag, arg1, arg2, res)
34527        end
34528      end
34529    end
34530  end
34531  [Array.new(1), "hiho", sqrt(-1.0), [1, 0], [0, 1]].each do |arg|
34532    [:vct_add!, :vct_subtract!,
34533     :vct_multiply!, :vct_ref, :vct_scale!].each do |n|
34534      tag = Snd.catch do snd_func(n, $vct_3, arg) end
34535      if tag.first != :wrong_type_arg
34536        snd_display("vct 2 :wrong_type_arg %s: %s %s", n, tag, arg)
34537      end
34538    end
34539  end
34540  if (tag = Snd.catch do make_vct(-23) end).first != :out_of_range
34541    snd_display("make_vct -23: %s", tag)
34542  end
34543  if (tag = Snd.catch do Vct.new(-23) end).first != :out_of_range
34544    snd_display("Vct.new -23: %s", tag)
34545  end
34546  v = $vct_3
34547  if (tag = Snd.catch do vct_ref(v, 12) end).first != :out_of_range
34548    snd_display("vct_ref 12: %s", tag)
34549  end
34550  if (tag = Snd.catch do v[12] end).first != :out_of_range
34551    snd_display("v[12]: %s", tag)
34552  end
34553  procs_p = [
34554    :all_pass?, :asymmetric_fm?, :comb?, :filtered_comb?, :convolve?,
34555    :delay?, :env?, :file2frample?, :file2sample?, :snd2sample?,
34556    :filter?, :fir_filter?, :formant?, :frample2file?, :frame?,
34557    :granulate?, :iir_filter?, :locsig?, :mixer?, :move_sound?,
34558    :mus_input?, :mus_output?, :notch?, :one_pole?, :one_zero?,
34559    :oscil?, :phase_vocoder?, :pulse_train?, :rand_interp?, :rand?,
34560    :readin?, :sample2file?, :sawtooth_wave?, :square_wave?, :src?,
34561    :table_lookup?, :triangle_wave?, :two_pole?, :two_zero?,
34562    :wave_train?, :color?, :mix_sampler?, :moving_average?,
34563    :ssb_am?, :sampler?, :region_sampler?, :vct?]
34564  [Array.new(1), "hiho", sqrt(-1.0), 1.5, [1, 0], [0, 1]].each do |arg|
34565    procs_p.each do |n|
34566      if (tag = Snd.catch do snd_func(n, arg) end).first.kind_of?(TrueClass)
34567        snd_display("?proc %s: %s %s", n, tag, arg)
34568      end
34569    end
34570  end
34571  procs_p.each do |n|
34572    next if n == :oscil?
34573    tag = Snd.catch do snd_func(n, make_oscil(440)) end
34574    if tag.first.kind_of?(TrueClass)
34575      snd_display("oscil?proc %s: %s", n, tag)
34576    end
34577  end
34578  [:reverse_selection, :selection_position, :selection_framples,
34579   :smooth_selection, :scale_selection_to, :insert_selection,
34580   :delete_selection, :delete_selection_and_smooth,
34581   :mix_selection].each do |n|
34582    if (tag = Snd.catch do snd_func(n) end).first != :no_active_selection
34583      snd_display("selection %s: %s", n, tag)
34584    end
34585  end
34586  [:src_selection, :filter_selection, :env_selection].each do |n|
34587    if (tag = Snd.catch do snd_func(n, 0.0) end).first != :no_active_selection
34588      snd_display("selection %s: %s", n, tag)
34589    end
34590  end
34591  [make_vector(1), $color_95, [1.0]].each do |arg|
34592    [:all_pass, :asymmetric_fm, :comb, :filtered_comb,
34593     :convolve, :db2linear, :moving_average, :degrees2radians, :delay,
34594     :env, :formant, :granulate, :hz2radians, :linear2db,
34595     :make_all_pass, :make_asymmetric_fm, :make_comb,
34596     :make_filtered_comb, :make_convolve, :make_delay, :make_env,
34597     :make_file2frample, :make_file2sample, :make_filter,
34598     :make_fir_filter, :make_formant, :make_granulate,
34599     :make_iir_filter, :make_locsig, :make_notch, :make_one_pole,
34600     :make_one_zero, :make_oscil, :make_pulse_train, :make_rand,
34601     :make_rand_interp, :make_readin, :make_sawtooth_wave,
34602     :make_square_wave, :make_src, :make_table_lookup,
34603     :make_triangle_wave, :make_two_pole, :make_two_zero,
34604     :make_wave_train, :make_ssb_am, :mus_channel, :mus_channels,
34605     :make_polyshape, :mus_data, :mus_feedback, :mus_feedforward,
34606     :mus_frequency, :mus_hop, :mus_increment, :mus_length,
34607     :mus_file_name, :mus_location, :mus_order, :mus_phase,
34608     :mus_ramp, :mus_random, :mus_run, :mus_scaler, :mus_xcoeffs,
34609     :mus_ycoeffs, :notch, :one_pole, :one_zero, :make_moving_average,
34610     :seconds2samples, :samples2seconds, :oscil, :partials2polynomial,
34611     :partials2wave, :phase_vocoder, :pulse_train,
34612     :radians2degrees, :radians2hz, :rand, :rand_interp, :readin,
34613     :sawtooth_wave, :square_wave, :src, :table_lookup, :tap,
34614     :triangle_wave, :two_pole, :two_zero, :wave_train, :ssb_am].each do |n|
34615      tag = Snd.catch do snd_func(n, arg) end
34616      case tag.first
34617      when :wrong_type_arg, :no_data, :no_such_method,
34618           :bad_type, :error, :arg_error
34619        next
34620      else
34621        snd_display("clm %s: tag %s, arg %s", n, tag, arg)
34622      end
34623    end
34624  end
34625  # XXX: phase_partials2wave in clm (test 28)
34626  # Original included in test above but Ruby's phase_partials2wave
34627  # takes Arrays and Vecs as lists.
34628  [make_vector(1), $color_95.to_a + [0], [1.0]].each do |arg|
34629    n = :phase_partials2wave
34630    tag = Snd.catch do snd_func(n, arg) end
34631    case tag.first
34632    when :wrong_type_arg, :no_data, :no_such_method,
34633         :bad_type, :error, :arg_error
34634      next
34635    else
34636      snd_display("clm %s: tag %s, arg %s", n, tag, arg)
34637    end
34638  end
34639  [:all_pass, :array_interp, :asymmetric_fm, :comb, :filtered_comb,
34640   :contrast_enhancement, :convolution, :convolve, :moving_average,
34641   :moving_max, :convolve_files, :delay, :dot_product, :env_interp,
34642   :file2frample, :file2sample, :snd2sample, :filter, :fir_filter,
34643   :formant, :firmant, :formant_bank,
34644   :granulate, :iir_filter, :ina, :inb, :locsig_ref,
34645   :locsig_reverb_ref, :make_all_pass, :make_asymmetric_fm,
34646   :make_comb, :make_filtered_comb, :make_delay, :make_env,
34647   :make_fft_window, :make_filter, :make_fir_filter, :make_formant,
34648   :make_firmant, :make_granulate,
34649   :make_iir_filter, :make_locsig, :make_notch, :make_one_pole, :make_one_zero,
34650   :make_oscil, :make_phase_vocoder, :make_pulse_train, :make_rand,
34651   :make_rand_interp, :make_readin, :make_sawtooth_wave, :make_moving_average,
34652   :make_nrxysin, :make_nrxycos, :make_square_wave, :make_src,
34653   :make_ncos, :make_nsin, :make_table_lookup, :make_triangle_wave,
34654   :make_two_pole, :make_two_zero, :make_wave_train,
34655   :notch, :one_pole, :one_zero, :oscil, :partials2polynomial,
34656   :partials2wave, :make_polyshape, :make_polywave,
34657   :phase_partials2wave, :phase_vocoder, :polynomial, :pulse_train,
34658   :rand, :rand_interp, :rectangular2polar, :rectangular2magnitudes,
34659   :ring_modulate, :sawtooth_wave, :nrxysin, :nrxycos,
34660   :square_wave, :src, :ncos, :nsin, :table_lookup, :tap, :triangle_wave,
34661   :two_pole, :two_zero, :wave_train, :ssb_am, :make_ssb_am].each do |n|
34662    tag = Snd.catch do snd_func(n, make_oscil, $vct_3) end
34663    case tag.first
34664    when :wrong_type_arg, :bad_arity, :error, :mus_error
34665      next
34666    else
34667      snd_display("clm-1 %s: %s", n, tag)
34668    end
34669  end
34670  [:mus_data, :mus_feedback, :mus_feedforward,
34671   :mus_frequency, :mus_hop, :mus_increment, :mus_length, :mus_location,
34672   :mus_phase, :mus_ramp, :mus_scaler].each do |n|
34673    tag = Snd.catch do set_snd_func(n, make_oscil, $vector_0) end
34674    case tag.first
34675    when :wrong_type_arg, :error
34676      next
34677    else
34678      snd_display("mus-gen %s: %s", n, tag)
34679    end
34680  end
34681  mus_procs = [
34682    :mus_sound_samples, :mus_sound_framples, :mus_sound_duration,
34683    :mus_sound_datum_size, :mus_sound_data_location, :mus_sound_chans,
34684    :mus_sound_srate, :mus_sound_header_type, :mus_sound_sample_type,
34685    :mus_sound_length, :mus_sound_type_specifier,
34686    :mus_header_type_name, :mus_sample_type_name, :mus_sound_comment,
34687    :mus_sound_write_date, :mus_bytes_per_sample, :mus_sound_loop_info,
34688    :mus_sound_mark_info, :mus_sound_maxamp, :mus_sound_maxamp_exists?,
34689    :mus_header_type2string, :mus_sample_type2string]
34690  mus_procs.each do |n|
34691    tag = Snd.catch do snd_func(n, $vct_3) end
34692    if tag.first != :wrong_type_arg
34693      snd_display("mus-sound %s: %s", n, tag)
34694    end
34695  end
34696  mus_procs.each do |n|
34697    tag = Snd.catch do snd_func(n) end
34698    case tag.first
34699    when :wrong_number_of_args, :error
34700      next
34701    else
34702      snd_display("no arg mus-sound %s: %s", n, tag)
34703    end
34704  end
34705end
34706
34707def test_28_01
34708  [:mus_sound_samples, :mus_sound_framples, :mus_sound_duration,
34709   :mus_sound_datum_size, :mus_sound_data_location, :mus_sound_chans,
34710   :mus_sound_srate, :mus_sound_header_type, :mus_sound_sample_type,
34711   :mus_sound_length, :mus_sound_type_specifier, :mus_sound_comment,
34712   :mus_sound_write_date, :mus_sound_maxamp,
34713   :mus_sound_maxamp_exists?].each do |n|
34714    tag = Snd.catch do snd_func(n, "/bad/baddy") end
34715    if tag.first != :mus_error
34716      snd_display("bad file mus-sound %s: %s", n, tag)
34717    end
34718  end
34719  mus_sound_forget("/bad/baddy")
34720  [:channel_widgets, :cursor, :channel_properties, :channel_property,
34721   :cursor_position, :cursor_size, :cursor_style, :tracking_cursor_style, :delete_sample,
34722   :display_edits, :dot_size, :draw_dots, :draw_lines, :edit_fragment, :edit_list2function,
34723   :edit_position, :edit_tree, :edits, :fft_window_alpha,
34724   :fft_window_beta, :fft_log_frequency, :fft_log_magnitude, :fft_with_phases, :transform_size,
34725   :transform_graph_type, :fft_window, :transform_graph?, :graph, :graph_style,
34726   :lisp_graph?, :insert_sound, :time_graph_style, :lisp_graph_style,
34727   :transform_graph_style, :left_sample, :make_graph_data, :map_chan, :max_transform_peaks,
34728   :maxamp_position, :min_dB, :mix_region, :transform_normalization,
34729   :peaks, :play, :position2x, :position2y, :reverse_sound,
34730   :revert_sound, :right_sample, :sample, :save_sound, :save_sound_as,
34731   :select_channel, :show_axes, :show_transform_peaks, :show_marks,
34732   :show_mix_waveforms, :show_y_zero, :show_grid, :show_sonogram_cursor, :spectrum_end,
34733   :spectro_hop, :spectrum_start, :spectro_x_angle, :spectro_x_scale, :spectro_y_angle,
34734   :grid_density, :spectro_y_scale, :spectro_z_angle, :spectro_z_scale, :squelch_update,
34735   :transform_sample, :transform2vct, :transform_framples, :transform_type,
34736   :update_transform_graph, :update_time_graph, :update_lisp_graph, :update_sound,
34737   :wavelet_type, :time_graph?, :time_graph_type, :wavo_hop, :wavo_trace, :x_bounds,
34738   :x_position_slider, :x_zoom_slider, :x_axis_label, :y_axis_label, :y_bounds,
34739   :y_position_slider, :y_zoom_slider, :zero_pad].each_with_index do |n, i|
34740    case (tag = Snd.catch do snd_func(n, $vct_3) end).first
34741    when :wrong_type_arg, :no_such_sound
34742      next
34743    else
34744      snd_display("%s: chn (no snd) procs %s: %s", i, n, tag)
34745    end
34746  end
34747  [:channel_widgets, :cursor, :channel_properties, :channel_property,
34748   :combined_data_color, :cursor_position, :cursor_size, :cursor_style, :tracking_cursor_style,
34749   :delete_sample, :display_edits, :dot_size, :draw_dots, :draw_lines, :edit_fragment,
34750   :edit_position, :edit_tree, :edits, :fft_window_beta, :fft_window_alpha, :fft_with_phases,
34751   :fft_log_frequency, :fft_log_magnitude, :transform_size, :transform_graph_type, :fft_window,
34752   :transform_graph?, :graph, :graph_style, :lisp_graph?, :insert_region,
34753   :insert_sound, :left_sample, :time_graph_style, :lisp_graph_style, :transform_graph_style,
34754   :make_graph_data, :map_chan, :max_transform_peaks, :maxamp, :maxamp_position, :min_dB,
34755   :mix_region, :transform_normalization, :peaks, :position2x, :position2y, :reverse_sound,
34756   :right_sample, :sample, :save_sound_as, :show_axes, :show_transform_peaks,
34757   :show_marks, :show_mix_waveforms, :show_y_zero, :show_grid, :show_sonogram_cursor, :spectrum_end,
34758   :spectro_hop, :spectrum_start, :spectro_x_angle, :spectro_x_scale, :spectro_y_angle,
34759   :spectro_y_scale, :spectro_z_angle, :spectro_z_scale, :squelch_update, :grid_density,
34760   :transform_sample, :transform2vct, :transform_framples, :transform_type,
34761   :update_transform_graph, :update_time_graph, :update_lisp_graph, :wavelet_type,
34762   :time_graph?, :time_graph_type, :wavo_hop, :wavo_trace, :x_bounds, :x_position_slider,
34763   :x_zoom_slider, :x_axis_label, :y_axis_label, :y_bounds, :y_position_slider,
34764   :y_zoom_slider, :zero_pad].each_with_index do |n, i|
34765    if (tag = Snd.catch do snd_func(n, 0, $vct_3) end).first != :wrong_type_arg
34766      snd_display("%s: chn (no chn) procs %s: %s", i, n, tag)
34767    end
34768  end
34769  idx = open_sound("oboe.snd")
34770  [:delete_sample, :edit_fragment, :graph_data, :position2x, :position2y, :redo_edit, :scale_by,
34771   :scale_to, :undo_edit, :x2position, :y2position].each_with_index do |n, i|
34772    tag = Snd.catch do snd_func(n, 0, idx, 1234) end
34773    if tag.first != :no_such_channel
34774      snd_display("%s: snd(1 1234) chn procs %s: %s", i, n, tag)
34775    end
34776  end
34777  close_sound(idx)
34778  idx = open_sound("oboe.snd")
34779  [:channel_widgets, :cursor, :cursor_position, :cursor_size, :cursor_style,
34780   :tracking_cursor_style, :display_edits, :dot_size, :edit_position, :edit_tree, :edits,
34781   :fft_window_alpha, :fft_window_beta, :fft_log_frequency, :fft_log_magnitude, :fft_with_phases,
34782   :transform_size, :transform_graph_type, :fft_window, :transform_graph?, :graph_style,
34783   :lisp_graph?, :left_sample, :time_graph_style, :lisp_graph_style, :transform_graph_style,
34784   :combined_data_color, :make_graph_data, :max_transform_peaks, :maxamp, :maxamp_position,
34785   :min_dB, :transform_normalization, :reverse_sound, :right_sample, :show_axes,
34786   :show_transform_peaks, :show_marks, :show_mix_waveforms, :show_y_zero, :show_grid,
34787   :show_sonogram_cursor, :grid_density, :spectrum_end, :spectro_hop, :spectrum_start,
34788   :spectro_x_angle, :spectro_x_scale, :spectro_y_angle, :spectro_y_scale, :spectro_z_angle,
34789   :spectro_z_scale, :squelch_update, :transform2vct, :transform_framples, :transform_type,
34790   :update_transform_graph, :update_time_graph, :update_lisp_graph, :wavelet_type, :time_graph?,
34791   :time_graph_type, :wavo_hop, :wavo_trace, :x_bounds, :x_position_slider, :x_axis_label,
34792   :x_zoom_slider, :y_bounds, :y_position_slider, :y_zoom_slider, :zero_pad,
34793   :channel_properties, :channel_property].each_with_index do |n, i|
34794    tag = Snd.catch do snd_func(n, idx, 1234) end
34795    if tag.first != :no_such_sound and tag.first != :no_such_channel
34796      snd_display("%s: chn procs %s: %s", i, n, tag)
34797    end
34798  end
34799  close_sound(idx)
34800  [:delete_sample, :edit_fragment, :graph_data, :graph_style,
34801   :position2x, :position2y, :redo_edit, :time_graph_style, :lisp_graph_style,
34802   :transform_graph_style, :scale_by, :scale_to, :undo_edit, :x2position, :y2position,
34803   :x_axis_label].each_with_index do |n, i|
34804    if (tag = Snd.catch do snd_func(n, 0, 1234) end).first != :no_such_sound
34805      snd_display("%s: snd(1) chn procs %s: %s", i, n, tag)
34806    end
34807  end
34808  idx = open_sound("oboe.snd")
34809  [:channel_widgets, :cursor, :cursor_position, :cursor_size, :cursor_style, :tracking_cursor_style,
34810   :display_edits, :dot_size, :edit_position, :edit_tree, :edits, :fft_window_beta,
34811   :fft_window_alpha, :fft_with_phases,
34812   :fft_log_frequency, :fft_log_magnitude, :transform_size, :transform_graph_type,
34813   :fft_window, :transform_graph?, :graph_style, :lisp_graph?, :left_sample,
34814   :time_graph_style, :lisp_graph_style, :transform_graph_style, :make_graph_data,
34815   :max_transform_peaks, :maxamp, :maxamp_position, :min_dB, :transform_normalization,
34816   :reverse_sound, :right_sample, :show_axes, :show_transform_peaks,
34817   :show_marks, :show_mix_waveforms, :show_y_zero, :show_grid, :show_sonogram_cursor,
34818   :grid_density, :spectrum_end, :spectro_hop, :spectrum_start, :spectro_x_angle,
34819   :spectro_x_scale, :spectro_y_angle, :spectro_y_scale, :spectro_z_angle,
34820   :spectro_z_scale, :squelch_update, :transform2vct, :transform_framples,
34821   :transform_type, :update_transform_graph, :update_time_graph, :update_lisp_graph,
34822   :wavelet_type, :time_graph?, :time_graph_type, :wavo_hop, :wavo_trace,
34823   :x_bounds, :x_position_slider, :x_axis_label, :x_zoom_slider, :y_bounds,
34824   :y_position_slider, :y_zoom_slider, :zero_pad,
34825   :channel_properties, :channel_property].each_with_index do |n, i|
34826    case (tag = Snd.catch do snd_func(n, idx, 1234) end).first
34827    when :no_such_sound, :no_such_channel
34828      next
34829    else
34830      snd_display("%s: chn (2) procs %s: %s", i, n, tag)
34831    end
34832  end
34833  [:channel_widgets, :cursor, :cursor_position, :display_edits, :dot_size,
34834   :edit_tree, :edits, :fft_window_beta, :fft_with_phases,
34835   :fft_window_alpha, :fft_log_frequency, :fft_log_magnitude,
34836   :transform_size, :transform_graph_type, :fft_window, :transform_graph?,
34837   :graph_style, :lisp_graph?, :left_sample, :make_graph_data,
34838   :max_transform_peaks, :maxamp, :maxamp_position, :time_graph_style,
34839   :lisp_graph_style, :transform_graph_style, :combined_data_color, :min_dB,
34840   :transform_normalization, :reverse_sound, :right_sample, :show_axes, :grid_density,
34841   :show_transform_peaks, :show_marks, :show_mix_waveforms, :show_y_zero,
34842   :show_grid, :show_sonogram_cursor, :spectrum_end, :spectro_hop, :spectrum_start,
34843   :spectro_x_angle, :spectro_x_scale, :spectro_y_angle, :spectro_y_scale,
34844   :spectro_z_angle, :spectro_z_scale, :squelch_update, :transform2vct,
34845   :transform_framples, :transform_type, :update_transform_graph, :update_time_graph,
34846   :update_lisp_graph, :wavelet_type, :time_graph?, :time_graph_type, :wavo_hop,
34847   :wavo_trace, :x_bounds, :x_position_slider, :x_zoom_slider, :y_bounds,
34848   :y_position_slider, :y_zoom_slider, :zero_pad, :x_axis_label].each_with_index do |n, i|
34849    tag = Snd.catch do set_snd_func(n, $vct_3, idx, 0) end
34850    if tag.first != :wrong_type_arg and tag.first != :no_method_error and tag.first != :name_error
34851      snd_display("%s: set chn procs %s: %s", i, n, tag)
34852    end
34853  end
34854  close_sound(idx)
34855  [:mix_amp, :mix_length, :mix_name, :mix_position, :mix_home, :mix_speed,
34856   :mix_tag_y].each_with_index do |n, i|
34857    tag = Snd.catch do snd_func(n, integer2mix(1234)) end
34858    if tag.car != :wrong_type_arg and
34859        tag.car != :syntax_error  and
34860        tag.car != :no_such_mix
34861      snd_display("%s: [2] mix procs %s: %s", i, n, tag)
34862    end
34863  end
34864  [:mix_name, :mix_position, :mix_speed, :mix_tag_y].each_with_index do |n, i|
34865    tag = Snd.catch do set_snd_func(n, integer2mix(1234), $vct_3) end
34866    if tag.car != :wrong_type_arg and tag.car != :no_such_mix
34867      snd_display("%s: set mix (3) procs %s: %s", i, n, tag)
34868    end
34869  end
34870  index = open_sound("oboe.snd")
34871  id = mix_sound("oboe.snd", 10).car
34872  [:mix_name, :mix_position, :mix_speed, :mix_tag_y].each_with_index do |n, i|
34873    if (tag = Snd.catch do set_snd_func(n, id, $vct_3) end).first != :wrong_type_arg
34874      snd_display("%s: set mix (4) procs %s: %s", i, n, tag)
34875    end
34876  end
34877  close_sound(index)
34878  [:add_mark, :mark_name, :mark_sample, :mark_sync, :mark_home, :delete_mark,
34879   :delete_marks, :find_mark].each_with_index do |n, i|
34880    if (tag = Snd.catch do snd_func(n, $vct_3) end).first != :wrong_type_arg
34881      snd_display("%s: mark procs %s: %s", i, n, tag)
34882    end
34883  end
34884  index = open_sound("oboe.snd")
34885  id = add_mark(0, index, 0)
34886  [:mark_name, :mark_sample, :mark_sync].each_with_index do |n, i|
34887    if (tag = Snd.catch do set_snd_func(n, id, $vct_3) end).first != :wrong_type_arg
34888      snd_display("%s: set mark procs %s: %s", i, n, tag)
34889    end
34890  end
34891  close_sound(index)
34892  [[0, 1], sqrt(-1.0), "hiho", [0, 1]].each do |arg|
34893    [:region_chans, :region_home, :region_framples, :region_position,
34894     :region_maxamp, :region_maxamp_position, :region_sample, :region2vct,
34895     :region_srate, :forget_region].each_with_index do |n, i|
34896      if (tag = Snd.catch do snd_func(n, arg) end).first != :wrong_type_arg
34897        snd_display("%s: region (1) procs %s: %s %s", i, n, tag, arg)
34898      end
34899    end
34900  end
34901  [:enved_filter_order, :enved_filter, :filter_control_waveform_color,
34902   :ask_before_overwrite, :auto_resize, :auto_update, :axis_label_font,
34903   :axis_numbers_font, :basic_color, :show_full_duration, :show_full_range, :initial_beg,
34904   :initial_dur, :channel_style, :color_cutoff, :color_inverted, :color_scale, :cursor_color,
34905   :dac_combines_channels, :dac_size, :clipping, :data_color,
34906   :default_output_chans, :default_output_sample_type, :default_output_srate,
34907   :default_output_header_type, :enved_envelope, :enved_base, :enved_clip?,
34908   :enved_in_dB, :enved_style, :enved_power, :enved_target,
34909   :enved_waveform_color, :enved_wave?, :eps_file, :eps_left_margin,
34910   :eps_bottom_margin, :eps_size, :foreground_color, :graph_color, :graph_cursor,
34911   :highlight_color, :just_sounds, :listener_color, :listener_font,
34912   :listener_prompt, :listener_text_color, :max_regions,
34913   :mix_waveform_height, :region_graph_style,
34914   :position_color, :time_graph_style, :lisp_graph_style, :transform_graph_style,
34915   :peaks_font, :bold_peaks_font, :print_length, :play_arrow_size,
34916   :sash_color, :ladspa_dir, :peak_env_dir, :save_dir, :save_state_file, :selected_channel,
34917   :selected_data_color, :selected_graph_color, :selected_sound,
34918   :selection_creates_region, :show_controls, :show_indices,
34919   :show_listener, :show_selection_transform, :sinc_width, :temp_dir,
34920   :text_focus_color, :tiny_font, :with_file_monitor,
34921   :with_verbose_cursor, :with_inset_graph, :with_interrupts, :with_pointer_focus,
34922   :window_height, :beats_per_measure, :with_smpte_label,
34923   :with_toolbar, :with_tooltips, :with_menu_icons, :remember_sound_state,
34924   :save_as_dialog_src, :save_as_dialog_auto_comment, :window_width, :window_x, :window_y, :with_gl,
34925   :with_mix_tags, :x_axis_style, :beats_per_minute, :zoom_color, :mix_tag_height,
34926   :mix_tag_width, :with_relative_panes, :clm_table_size,
34927   :mark_tag_width, :mark_tag_height].each do |n|
34928    tag = Snd.catch do set_snd_func(n, $vct_3) end
34929    if tag.first != :wrong_type_arg and tag.first != :mus_error
34930      snd_display("misc procs %s: %s", n, tag.inspect)
34931    end
34932  end
34933  [:after_graph_hook, :lisp_graph_hook, :before_transform_hook,
34934    :mix_release_hook, :save_hook, :before_save_as_hook, :after_save_as_hook,
34935    :save_state_hook, :new_sound_hook, :mus_error_hook, :mouse_enter_graph_hook,
34936    :mouse_leave_graph_hook, :open_raw_sound_hook, :select_channel_hook,
34937    :after_open_hook, :close_hook, :draw_mark_hook,
34938    :draw_mix_hook, :mark_click_hook, :listener_click_hook, :mix_click_hook,
34939    :after_save_state_hook, :before_save_state_hook, :mark_hook,
34940    :mark_drag_hook, :mix_drag_hook, :name_click_hook,
34941    :after_apply_controls_hook, :open_hook, :output_comment_hook,
34942    :help_hook, :play_hook, :new_widget_hook, :read_hook, :bad_header_hook,
34943    :snd_error_hook, :snd_warning_hook, :start_playing_hook,
34944    :stop_playing_hook, :mouse_enter_listener_hook, :mouse_leave_listener_hook,
34945    :select_sound_hook, :during_open_hook, :after_transform_hook,
34946    :mouse_enter_label_hook, :mouse_leave_label_hook, :initial_graph_hook,
34947    :graph_hook, :key_press_hook, :mouse_drag_hook, :mouse_press_hook,
34948    :mouse_click_hook, :enved_hook].each_with_index do |n, i|
34949    hook = eval("$#{n}")
34950    fnc = lambda do || 1 + 2 end
34951    tag = Snd.catch do hook.add_hook!("test28-1", &fnc) end
34952    if tag.first != :wrong_type_arg
34953      snd_display("%s: hooks (1) %s: %s", i, n, tag)
34954    end
34955  end
34956  [:exit_hook, :stop_playing_selection_hook, :color_hook,
34957   :orientation_hook, :start_playing_selection_hook].each_with_index do |n, i|
34958    hook = eval("$#{n}")
34959    fnc = lambda do |a, b, c| a + b + c end
34960    tag = Snd.catch do hook.add_hook!("test28-2", &fnc) end
34961    if tag.first != :wrong_type_arg
34962      snd_display("%s: hooks (2) %s: %s", i, n, tag)
34963    end
34964  end
34965end
34966
34967def test_28_02
34968  # XXX: 'not_an_env = nil' otherwise name_error: no such variable or function
34969  not_an_env = nil
34970  check_error_tag(:no_such_envelope) do set_enved_envelope("not_an_env") end
34971  check_error_tag(:cannot_save) do save_envelopes("/bad/baddy") end
34972  check_error_tag(:cannot_save) do mus_sound_report_cache("/bad/baddy") end
34973  check_error_tag(:bad_arity) do
34974    set_search_procedure(lambda do |a, b, c| a end)
34975  end
34976  check_error_tag(:no_such_channel) do make_sampler(0, "oboe.snd", 1) end
34977  check_error_tag(:no_such_channel) do make_sampler(0, "oboe.snd", -1) end
34978  check_error_tag(:bad_arity) do
34979    bind_key(key_to_int(?p), 0, lambda do |a, b| play_often([1, a].max) end)
34980  end
34981  check_error_tag(:bad_arity) do set_zoom_focus_style(lambda do |a| 0 end) end
34982  check_error_tag(:no_such_sound) do set_sound_loop_info(123, [0, 0, 1, 1]) end
34983  check_error_tag(:bad_header) do
34984    new_sound("fmv.snd", 2, 22050, Mus_bfloat, Mus_nist, "this is a comment")
34985  end
34986  check_error_tag(:wrong_type_arg) do player_home(123) end
34987  check_error_tag(:no_such_file) do set_temp_dir("/hiho") end
34988  check_error_tag(:no_such_file) do set_save_dir("/hiho") end
34989  check_error_tag(:bad_header) do
34990    mus_sound_maxamp($sf_dir + "bad_chans.snd")
34991  end
34992  check_error_tag(:bad_header) do
34993    set_mus_sound_maxamp($sf_dir + "bad_chans.snd", [0.0, 0.0])
34994  end
34995  check_error_tag(:mus_error) do
34996    make_iir_filter(:order, 32, :ycoeffs, make_vct(4))
34997  end
34998  check_error_tag(:mus_error) do
34999    make_iir_filter(:coeffs, make_vct(4), :ycoeffs, make_vct(4))
35000  end
35001  check_error_tag(:mus_error) do
35002    make_iir_filter(:coeffs, make_vct(4), :xcoeffs, make_vct(4))
35003  end
35004  check_error_tag(:out_of_range) do make_table_lookup(:size, 123456789) end
35005  check_error_tag(:out_of_range) do make_granulate(:ramp, -0.5) end
35006  check_error_tag(:out_of_range) do make_granulate(:ramp, 1.5) end
35007  check_error_tag(:mus_error) do make_granulate(:expansion, 32000.0) end
35008  check_error_tag(:out_of_range) do new_sound("test.snd", :channels, 0) end
35009  check_error_tag(:out_of_range) do new_sound("test.snd", :srate, 0) end
35010  check_error_tag(:out_of_range) do new_sound("test.snd", :size, -1) end
35011  check_error_tag(:out_of_range) do make_readin("oboe.snd", :size, 0) end
35012  check_error_tag(:out_of_range) do make_readin("oboe.snd", :size, -1) end
35013  check_error_tag(:out_of_range) do make_file2sample("oboe.snd", 0) end
35014  check_error_tag(:out_of_range) do make_file2sample("oboe.snd", -1) end
35015  check_error_tag(:out_of_range) do make_file2frample("oboe.snd", 0) end
35016  check_error_tag(:out_of_range) do make_file2frample("oboe.snd", -1) end
35017  check_error_tag(:out_of_range) do set_default_output_sample_type(-1) end
35018  check_error_tag(:out_of_range) do
35019    set_default_output_header_type(Mus_soundfont)
35020  end
35021  check_error_tag(:mus_error) do
35022    mus_sound_chans($sf_dir + "bad_location.nist")
35023  end
35024  check_error_tag(:mus_error) do mus_sound_chans($sf_dir + "bad_field.nist") end
35025  if $with_test_motif
35026    check_error_tag(:no_such_widget) do widget_position([:Widget, 0]) end
35027    check_error_tag(:no_such_widget) do widget_size([:Widget, 0]) end
35028    check_error_tag(:no_such_widget) do widget_text([:Widget, 0]) end
35029    check_error_tag(:no_such_widget) do
35030      set_widget_position([:Widget, 0], [0, 0])
35031    end
35032    check_error_tag(:no_such_widget) do
35033      set_widget_size([:Widget, 0], [10, 10])
35034    end
35035    check_error_tag(:no_such_widget) do
35036      set_widget_text([:Widget, 0], "hiho")
35037    end
35038  end
35039  check_error_tag(:no_such_menu) do main_menu(-1) end
35040  check_error_tag(:no_such_menu) do main_menu(111) end
35041  check_error_tag(:out_of_range) do
35042    new_sound("hiho", :header_type, 123)
35043  end
35044  check_error_tag(:out_of_range) do
35045    new_sound("hiho", :header_type, Mus_nist, :sample_type, 123)
35046  end
35047  check_error_tag(:bad_header) do
35048    new_sound("hiho", :header_type, Mus_nist, :sample_type, Mus_bfloat)
35049  end
35050  check_error_tag(:out_of_range) do set_mus_array_print_length(-1) end
35051  check_error_tag(:out_of_range) do set_print_length(-1) end
35052  check_error_tag(:out_of_range) do set_play_arrow_size(-1) end
35053  check_error_tag(:wrong_type_arg) do vector2vct(make_array(3, "hio")) end
35054  check_error_tag(:out_of_range) do set_enved_style(12) end
35055  check_error_tag(:out_of_range) do make_color(1.5, 0.0, 0.0) end
35056  check_error_tag(:out_of_range) do make_color(-0.5, 0.0, 0.0) end
35057  check_error_tag(:wrong_type_arg) do make_variable_graph(false) end
35058  check_error_tag(:cannot_print) do graph2ps end
35059  ind = open_sound("oboe.snd")
35060  set_selection_creates_region(true)
35061  select_all
35062  check_error_tag(:mus_error) do save_selection("sel0.snd", :not_a_key, 3) end
35063  check_error_tag(:wrong_type_arg) do read_only([ind]) end
35064  check_error_tag(:wrong_type_arg) do framples(ind, [0]) end
35065  check_error_tag(:wrong_type_arg) do smooth_sound(0, -10) end
35066  check_error_tag(:no_such_channel) do mix_selection(0, ind, 123) end
35067  check_error_tag(:no_such_channel) do insert_selection(0, ind, 123) end
35068  check_error_tag(:out_of_range) do set_channels(ind, 0) end
35069  check_error_tag(:wrong_type_arg) do set_channels(ind, -1) end
35070  check_error_tag(:out_of_range) do set_channels(ind, 12340) end
35071  check_error_tag(:out_of_range) do set_sample_type(ind, 12340) end
35072  check_error_tag(:out_of_range) do set_header_type(ind, 12340) end
35073  check_error_tag(:out_of_range) do set_srate(ind, 0) end
35074  check_error_tag(:wrong_type_arg) do set_data_location(ind, -1) end
35075  check_error_tag(:wrong_type_arg) do set_data_size(ind, -1) end
35076  check_error_tag(:no_such_sample) do set_sample(-1, -1) end
35077  check_error_tag(:no_such_sample) do sample(-1) end
35078  check_error_tag(:out_of_range) do set_framples(-10) end
35079  check_error_tag(:out_of_range) do set_min_dB(0.0) end
35080  check_error_tag(:out_of_range) do set_min_dB(0.0, ind, 0) end
35081  check_error_tag(:out_of_range) do start_playing(1, -22) end
35082  check_error_tag(:out_of_range) do start_playing(1, 0) end
35083  check_error_tag(:out_of_range) do
35084    set_filter_control_envelope([0.0, 1.0, 0.1, -0.1, 1.0, 0.0], ind)
35085  end
35086  check_error_tag(:out_of_range) do
35087    set_filter_control_envelope([0.0, 1.0, 0.1, 1.1, 1.0, 0.0], ind)
35088  end
35089  check_error_tag(:env_error) do
35090    filter_sound([0, 0, 0.1, 0.1, 0.05, 0.1, 1, 1], 32)
35091  end
35092  check_error_tag(:out_of_range) do apply_controls(ind, 123) end
35093  check_error_tag(:out_of_range) do set_speed_control_bounds([0.0, 2.0]) end
35094  check_error_tag(:out_of_range) do set_expand_control_bounds([0.0, 2.0]) end
35095  check_error_tag(:out_of_range) do set_speed_control_bounds([2.0, 0.0]) end
35096  check_error_tag(:out_of_range) do set_expand_control_bounds([2.0, 0.0]) end
35097  check_error_tag(:bad_header) do insert_sound($sf_dir + "bad_chans.snd") end
35098  check_error_tag(:io_error) do convolve_with($sf_dir + "bad_chans.snd") end
35099  check_error_tag(:cannot_save) do
35100    save_sound_as("hiho.snd", ind, -12)
35101  end
35102  check_error_tag(:cannot_save) do
35103    save_sound_as("hiho.snd", ind,
35104                  :header_type, Mus_next, :sample_type, -12)
35105  end
35106  check_error_tag(:cannot_save) do
35107    save_sound_as("test.snd", ind,
35108                  :header_type, Mus_nist, :sample_type, Mus_bdouble)
35109  end
35110  check_error_tag(:cannot_save) do
35111    save_sound_as("test.snd", ind,
35112                  :header_type, Mus_aifc, :sample_type, Mus_lfloat)
35113  end
35114  check_error_tag(:cannot_save) do
35115    save_sound_as("test.snd", ind,
35116                  :header_type, Mus_riff, :sample_type, Mus_bshort)
35117  end
35118  check_error_tag(:cannot_save) do
35119    save_sound_as("test.snd", ind,
35120                  :header_type, Mus_voc, :sample_type, Mus_bshort)
35121  end
35122  check_error_tag(:cannot_save) do
35123    save_selection("test.snd", 22050, Mus_bshort, Mus_riff)
35124  end
35125  check_error_tag(:cannot_save) do
35126    save_selection("test.snd", 22050, Mus_bshort, Mus_voc)
35127  end
35128  check_error_tag(:out_of_range) do
35129    src_channel(make_env([0, 0, 1, 1], :length, 11))
35130  end
35131  check_error_tag(:out_of_range) do
35132    src_channel(make_env([0, 1, 1, 0], :length, 11))
35133  end
35134  check_error_tag(:out_of_range) do
35135    src_channel(make_env([0, 1, 1, -1], :length, 11))
35136  end
35137  check_error_tag(:out_of_range) do
35138    src_channel(make_env([0, -1, 1, 1], :length, 11))
35139  end
35140  check_error_tag(:out_of_range) do
35141    src_sound(make_env([0, 0, 1, 1], :length, 11))
35142  end
35143  check_error_tag(:out_of_range) do
35144    src_sound(make_env([0, 1, 1, 0], :length, 11))
35145  end
35146  check_error_tag(:out_of_range) do
35147    src_sound(make_env([0, 1, 1, -1], :length, 11))
35148  end
35149  check_error_tag(:out_of_range) do
35150    src_sound(make_env([0, -1, 1, 1], :length, 11))
35151  end
35152  check_error_tag(:mus_error) do
35153    make_readin(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
35154  end
35155  check_error_tag(:out_of_range) do filter_sound($vct_3, 32) end
35156  check_error_tag(:out_of_range) do filter_sound([0, 0, 1, 1], 0) end
35157  check_error_tag(:no_such_sound) do swap_channels(ind, 0, 12345, 0) end
35158  check_error_tag(:no_such_sample) do
35159    mix_vct(vct(0.1, 0.2, 0.3), -1, ind, 0, true)
35160  end
35161  check_error_tag(:out_of_range) do snd_spectrum(Vct.new(8), 0, -123) end
35162  check_error_tag(:out_of_range) do snd_spectrum(Vct.new(8), 0, 0) end
35163  check_error_tag(:no_such_file) do play("/baddy/hiho") end
35164  check_error_tag(:bad_sample_type) do play($sf_dir + "nist-shortpack.wav") end
35165  check_error_tag(:no_such_sound) do play(123, 0) end
35166  check_error_tag(:no_such_channel) do make_player(ind, 123) end
35167  check_error_tag(:no_such_file) do mix("/baddy/hiho") end
35168  check_error_tag(:no_such_channel) do mix("oboe.snd", 0, 2) end
35169  check_error_tag(:no_such_file) do mix_sound("/baddy/hiho", 0) end
35170  check_error_tag(:no_such_file) do insert_sound("/baddy/hiho.snd") end
35171  check_error_tag(:no_such_file) do insert_samples(0, 10, "/baddy/hiho.snd") end
35172  check_error_tag(:no_data) do set_filter_control_envelope([], ind) end
35173  check_error_tag(:out_of_range) do set_sample_type(ind, 123) end
35174  check_error_tag(:out_of_range) do set_header_type(ind, 123) end
35175  check_error_tag(:no_such_channel) do set_selected_channel(ind, 123) end
35176  check_error_tag(:bad_arity) do
35177    set_search_procedure(lambda do |a, b, c| true end)
35178  end
35179  check_error_tag(:bad_arity) do map_chan(lambda do |a, b, c| 1.0 end) end
35180  check_error_tag(:bad_arity) do scan_channel(lambda do |a, b, c| 1.0 end) end
35181  check_error_tag(:bad_arity) do
35182    set_cursor_style(lambda do |a| 32 end, ind, 0)
35183  end
35184  check_error_tag(:no_such_graphics_context) do
35185    draw_line(0, 0, 1, 1, ind, 0, 1234)
35186  end
35187  check_error_tag(:no_such_graphics_context) do
35188    foreground_color(ind, 0, 1234)
35189  end
35190  check_error_tag(:no_such_graphics_context) do current_font(ind, 0, 1234) end
35191  check_error_tag(:no_such_graphics_context) do
35192    graph_data([$vct_3, $vct_3], ind, 0, 1234, 0, 1, 0)
35193  end
35194  check_error_tag(:no_such_axis) do position2x(100, ind, 0, 1234) end
35195  check_error_tag(:no_such_axis) do position2y(100, ind, 0, 1234) end
35196  check_error_tag(:no_such_axis) do x2position(100, ind, 0, 1234) end
35197  check_error_tag(:no_such_axis) do y2position(100, ind, 0, 1234) end
35198  check_error_tag(:no_such_axis) do axis_info(ind, 0, 1234) end
35199  check_error_tag(:out_of_range) do
35200    draw_axes(channel_widgets.car, snd_gcs.car, "hiho",
35201              0.0, 1.0, -1.0, 1.0, X_axis_in_seconds,1234)
35202  end
35203  check_error_tag(:out_of_range) do
35204    draw_axes(channel_widgets.car, snd_gcs.car, "hiho",
35205              0.0, 1.0, -1.0, 1.0, 1234)
35206  end
35207  check_error_tag(:no_such_channel) do axis_info(ind, 1234) end
35208  check_error_tag(:no_such_sound) do axis_info(1234) end
35209  set_time_graph_type(Graph_once)
35210  check_error_tag(:out_of_range) do set_x_bounds([0.1, -0.1]) end
35211  check_error_tag(:out_of_range) do make_region(100, 0) end
35212  check_error_tag(:no_such_sample) do delete_sample(-1) end
35213  check_error_tag(:no_such_sample) do delete_sample(2 * framples(ind)) end
35214  regions.empty? and make_region(0, 100)
35215  check_error_tag(:no_such_channel) do region_sample(regions.car, 0, 1234) end
35216  check_error_tag(:no_such_channel) do region_framples(regions.car, 1234) end
35217  check_error_tag(:no_such_channel) do region_position(regions.car, 1234) end
35218  check_error_tag(:no_such_channel) do region2vct(regions.car, 0, 1, 1234) end
35219  check_error_tag(:cannot_save) do save_sound_as("/bad/baddy.snd") end
35220  check_error_tag(:no_such_sound) do transform_sample(0, 1, 1234) end
35221  check_error_tag(:no_such_channel) do transform_sample(0, 1, ind, 1234) end
35222  check_error_tag(:no_such_sound) do
35223    graph(vct(0, 1), "hi", 0, 1, 0, 1, 1234)
35224  end
35225  check_error_tag(:no_such_channel) do
35226    graph(vct(0, 1), "hi", 0, 1, 0, 1, ind, 1234)
35227  end
35228  set_selection_member?(false, true)
35229  check_error_tag(:no_active_selection) do
35230    filter_selection(vct(0, 0, 1, 1), 4)
35231  end
35232  check_error_tag(:no_active_selection) do save_selection("/bad/baddy.snd") end
35233  check_error_tag(:no_active_selection) do env_selection([0, 0, 1, 1]) end
35234  make_region(0, 100, ind, 0)
35235  check_error_tag(:cannot_save) do save_selection("/bad/baddy.snd") end
35236  check_error_tag(:cannot_save) do
35237    save_region(regions.car, "/bad/baddy.snd")
35238  end
35239  check_error_tag(:no_such_sound) do make_region(0, 12, 1234, true) end
35240  set_read_only(true, ind)
35241  check_error_tag(:cannot_save) do set_sound_loop_info(ind, [0, 0, 1, 1]) end
35242  check_error_tag(:no_such_direction) do make_sampler(0, ind, 0, 123) end
35243  check_error_tag(:no_such_direction) do make_sampler(0, ind, 0, 0) end
35244  check_error_tag(:no_such_direction) do make_sampler(0, ind, 0, -2) end
35245  check_error_tag(:no_data) do scale_by([]) end
35246  check_error_tag(:no_data) do scale_to([]) end
35247  check_error_tag(:no_such_sample) do set_selection_position(-999, ind, 0) end
35248  check_error_tag(:wrong_type_arg) do set_selection_framples(-999, ind, 0) end
35249  check_error_tag(:wrong_type_arg) do set_selection_framples(0, ind, 0) end
35250  check_error_tag(:no_such_edit) do edit_fragment(-1) end
35251  check_error_tag(:no_such_edit) do edit_fragment(101, ind, 0) end
35252  check_error_tag(:no_such_edit) do edit_tree(ind, 0, -2) end
35253  check_error_tag(:no_such_edit) do edit_tree(ind, 0, 101) end
35254  check_error_tag(:no_such_sample) do add_mark(-1) end
35255  check_error_tag(:no_such_sample) do add_mark(framples * 2) end
35256  check_error_tag(:no_such_file) do convolve_with("/bad/baddy") end
35257  check_error_tag(:no_such_file) do mix("/bad/baddy") end
35258  check_error_tag(:no_such_sound) do swap_channels(ind, 0, 123) end
35259  check_error_tag(:out_of_range) do set_show_axes(123, ind, 0) end
35260  check_error_tag(:out_of_range) do set_show_axes(-123, ind, 0) end
35261  check_error_tag(:out_of_range) do set_x_axis_style(123, ind, 0) end
35262  check_error_tag(:out_of_range) do set_x_axis_style(-123, ind, 0) end
35263  check_error_tag(:out_of_range) do set_graph_style(123, ind, 0) end
35264  check_error_tag(:out_of_range) do set_graph_style(-123, ind, 0) end
35265  check_error_tag(:out_of_range) do env_sound([0, 0, 1, 1], 0, false, -1.5) end
35266  check_error_tag(:out_of_range) do xramp_channel(0.0, 1.0, -1.6) end
35267  check_error_tag(:wrong_type_arg) do set_samples(0, 2, -1) end
35268  check_error_tag(:wrong_type_arg) do left_sample([0]) end
35269  check_error_tag(:wrong_type_arg) do amp_control([0]) end
35270  check_error_tag(:wrong_type_arg) do sound_loop_info([0]) end
35271  check_error_tag(:wrong_type_arg) do add_mark(123, [0]) end
35272  check_error_tag(:no_such_sound) do
35273    filter_channel([0, 0, 1, 1], 100, false, false, 1234, 0)
35274  end
35275  check_error_tag(:no_such_channel) do
35276    filter_channel([0, 0, 1, 1], 100, false, false, ind, 1)
35277  end
35278  check_error_tag(:no_such_channel) do
35279    filter_channel(vct(0, 0, 1, 1), 4, false, false, ind, 1)
35280  end
35281  check_error_tag(:out_of_range) do filter_sound(vct(0, 0, 1, 1), 0) end
35282  check_error_tag(:out_of_range) do filter_sound(vct(0, 0, 1, 1), 10) end
35283  check_error_tag(:out_of_range) do
35284    set_reverb_control_length_bounds([0.1, 0.01], ind)
35285  end
35286  check_error_tag(:out_of_range) do
35287    set_reverb_control_scale_bounds([0.1, 0.01], ind)
35288  end
35289  check_error_tag(:wrong_type_arg) do scale_by(false) end
35290  check_error_tag(:wrong_type_arg) do src_sound(3.0, 1.0, true) end
35291  check_error_tag(:wrong_type_arg) do src_sound(3.0, 1.0, ind, true) end
35292  check_error_tag(:no_such_edit) do display_edits(ind, 0, 123) end
35293  check_error_tag(:no_such_edit) do marks(ind, 0, 123) end
35294  check_error_tag(:no_such_edit) do
35295    save_sound_as("test.snd", :edit_position, 123)
35296  end
35297  check_error_tag(:no_such_auto_delete_choice) do
35298    insert_sound("1a.snd", 0, 0, ind, 0, 0, 123)
35299  end
35300  close_sound(ind)
35301  check_error_tag(:bad_arity) do
35302    add_transform("hiho", "time", 0, 1, lambda do | | 1.0 end)
35303  end
35304  check_error_tag(:cannot_save) do save_state("/bad/baddy") end
35305  check_error_tag(:no_such_menu) do
35306    add_to_menu(1234, "hi", lambda do | | false end)
35307  end
35308  check_error_tag(:bad_arity) do
35309    add_to_main_menu("hi", lambda do |a, b| false end)
35310  end
35311  check_error_tag(:bad_arity) do
35312    add_to_menu(1, "hi", lambda do |a, b| false end)
35313  end
35314  check_error_tag(:wrong_type_arg) do help_dialog([0, 1], "hiho") end
35315  check_error_tag(:wrong_type_arg) do info_dialog([0, 1], "hiho") end
35316  check_error_tag(:no_such_sound) do edit_header_dialog(1234) end
35317  check_error_tag(:no_such_file) do open_sound("/bad/baddy.snd") end
35318  check_error_tag(:no_such_file) do
35319    open_raw_sound("/bad/baddy.snd", 1, 22050, Mus_lshort)
35320  end
35321  check_error_tag(:no_such_file) do view_sound("/bad/baddy.snd") end
35322  check_error_tag(:no_such_file) do make_sampler(0, "/bad/baddy.snd") end
35323  check_error_tag(:no_such_key) do bind_key(12345678, 0, false) end
35324  check_error_tag(:no_such_key) do bind_key(-1, 0, false) end
35325  check_error_tag(:no_such_key) do bind_key(12, 17, false) end
35326  check_error_tag(:no_such_key) do bind_key(12, -1, false) end
35327  check_error_tag(:no_such_key) do key_binding(12345678, 0) end
35328  check_error_tag(:no_such_key) do key_binding(-1, 0) end
35329  check_error_tag(:no_such_key) do key_binding(12, 17) end
35330  check_error_tag(:no_such_key) do key_binding(12, -1) end
35331  check_error_tag(:bad_header) do
35332    file2array($sf_dir + "bad_chans.snd", 0, 0, 123, Vct.new(123))
35333  end
35334  check_error_tag(:bad_header) do make_readin($sf_dir + "bad_chans.snd") end
35335  check_error_tag(:mus_error) do make_iir_filter(30, Vct.new(3)) end
35336  check_error_tag(:out_of_range) do make_wave_train(:size, 2 ** 30) end
35337  check_error_tag(:out_of_range) do set_mus_srate(0.0) end
35338  check_error_tag(:out_of_range) do set_mus_srate(-1000) end
35339  check_error_tag(:out_of_range) do dot_product(Vct.new(3), Vct.new(3), -1) end
35340  check_error_tag(:out_of_range) do
35341    make_delay(3, :initial_element, 0.0, :initial_contents, vct(0.1, 0.2, 0.3))
35342  end
35343  check_error_tag(:out_of_range) do
35344    make_delay(3, :max_size, 100, :initial_contents, vct(0.1, 0.2, 0.3))
35345  end
35346  check_error_tag(:out_of_range) do
35347    make_table_lookup(:size, 100, :wave, Vct.new(3))
35348  end
35349  check_error_tag(:out_of_range) do
35350    make_wave_train(:size, 100, :wave, Vct.new(3))
35351  end
35352  check_error_tag(:out_of_range) do make_ssb_am(100, 12345678) end
35353  check_error_tag(:mus_error) do
35354    make_rand(:envelope, [0, 0, 1, 1], :distribution, Vct.new(10))
35355  end
35356  check_error_tag(:mus_error) do make_rand(:envelope, [0, 0, 1]) end
35357  check_error_tag(:out_of_range) do
35358    make_rand(:envelope, [0, 0, 1, 1], :size, -2)
35359  end
35360  check_error_tag(:out_of_range) do
35361    make_rand(:envelope, [0, 0, 1, 1], :size, 1234567890)
35362  end
35363  check_error_tag(:bad_arity) do
35364    grn = make_granulate
35365    granulate(grn, false, lambda do |a, s, d| false end)
35366  end
35367  check_error_tag(:bad_arity) do
35368    pv = make_phase_vocoder
35369    phase_vocoder(pv, false, lambda do | | false end)
35370  end
35371  check_error_tag(:bad_arity) do
35372    pv = make_phase_vocoder
35373    phase_vocoder(pv, false, false, lambda do | | false end)
35374  end
35375  check_error_tag(:bad_arity) do
35376    pv = make_phase_vocoder
35377    phase_vocoder(pv, false, false, false, lambda do | | false end)
35378  end
35379  check_error_tag(:mus_error) do
35380    f = make_filter(3, :xcoeffs, $vct_3, :ycoeffs, $vct_3)
35381    mus_xcoeff(f, 4)
35382  end
35383  check_error_tag(:mus_error) do
35384    f = make_filter(3, :xcoeffs, $vct_3, :ycoeffs, $vct_3)
35385    mus_ycoeff(f, 4)
35386  end
35387  check_error_tag(:mus_error) do
35388    f = make_filter(3, :xcoeffs, $vct_3, :ycoeffs, $vct_3)
35389    set_mus_xcoeff(f, 4, 1.0)
35390  end
35391  check_error_tag(:mus_error) do
35392    f = make_filter(3, :xcoeffs, $vct_3, :ycoeffs, $vct_3)
35393    set_mus_ycoeff(f, 4, 1.0)
35394  end
35395  check_error_tag(:mus_error) do
35396    make_filter(:ycoeffs, Vct.new(4), :order, 12)
35397  end
35398  check_error_tag(:mus_error) do
35399    hi = make_oscil
35400    set_mus_offset(hi, 1)
35401  end
35402  check_error_tag(:out_of_range) do make_locsig(:channels, 2 ** 30) end
35403  check_error_tag(:out_of_range) do make_src(:width, 3000) end
35404  check_error_tag(:bad_arity) do
35405    add_colormap("baddy", lambda do | | false end)
35406  end
35407  check_error_tag(:bad_arity) do
35408    add_colormap("baddy", lambda do |a, b, c| false end)
35409  end
35410  check_error_tag(:out_of_range) do
35411    sr = make_src(:input, lambda do |dir| 1.0 end)
35412    src(sr, 2000000.0)
35413  end
35414  check_error_tag(:out_of_range) do partials2polynomial([1, 1], -1) end
35415  check_error_tag(:out_of_range) do partials2polynomial([1, 1], 3) end
35416  check_error_tag(:out_of_range) do
35417    make_polyshape(440.0, :partials, [1, 1], :kind, -1)
35418  end
35419  check_error_tag(:out_of_range) do
35420    make_polyshape(440.0, :partials, [1, 1], :kind, 3)
35421  end
35422  check_error_tag(:wrong_type_arg) do set_mus_header_raw_defaults(1234) end
35423  check_error_tag(:wrong_type_arg) do
35424    set_mus_header_raw_defaults([44100, 2.123, "hi"])
35425  end
35426  check_error_tag(:wrong_type_arg) do set_with_toolbar(123) end
35427  check_error_tag(:wrong_type_arg) do set_with_tooltips(123) end
35428  check_error_tag(:wrong_type_arg) do set_with_menu_icons(123) end
35429  check_error_tag(:wrong_type_arg) do set_save_as_dialog_src(123) end
35430  check_error_tag(:wrong_type_arg) do set_save_as_dialog_auto_comment(123) end
35431  check_error_tag(:wrong_type_arg) do set_with_smpte_label(123) end
35432  check_error_tag(:wrong_type_arg) do set_ask_about_unsaved_edits(123) end
35433  #
35434  if $with_test_motif
35435    [:widget_position, :widget_size, :widget_text,
35436      :hide_widget, :show_widget, :focus_widget].each do |n|
35437      tag = Snd.catch do snd_func(n, [:Widget, 0]) end
35438      if tag.first != :no_such_widget
35439        snd_display("%s of null widget: %s", n, tag)
35440      end
35441    end
35442  end
35443end
35444
35445def test_28_03
35446  new_wave = Vct.new(1)
35447  [[:make_table_lookup, :table_lookup]].each do |mg, g|
35448    gen = snd_func(mg, :wave, new_wave)
35449    snd_func(g, gen, 1.0)
35450  end
35451  #
35452  old_srate = mus_srate
35453  old_clm_srate = $clm_srate
35454  [100, 1].each do |n|
35455    set_mus_srate(n)
35456    $clm_srate = n
35457    [:make_oscil,
35458     :make_asymmetric_fm,
35459     :make_triangle_wave,
35460     :make_square_wave,
35461     :make_pulse_train,
35462     :make_sawtooth_wave,
35463     :make_rand,
35464     :make_rand_interp].each do |g|
35465      tag = Snd.catch do snd_func(g, :frequency, 440.0) end
35466      if tag.first != :out_of_range
35467        snd_display("srate %s: %s -> %s", n, g, tag.inspect)
35468      end
35469    end
35470  end
35471  set_mus_srate(old_srate)
35472  $clm_srate = old_clm_srate
35473  # now try everything! (all we care about here is that Snd keeps running)
35474  random_args = [1.5, [0, 1], 1234, true]
35475  main_args   = [1.5, [0, 1], 1234, $vct_3, $color_95, sqrt(-1.0), $delay_32, false]
35476  few_args    = [1.5, [0, 1], 1234, sqrt(-1.0), $delay_32, true]
35477  fewer_args  = [1.5, $vct_3, sqrt(-1.0)]
35478  less_args   = $all_args ? main_args : few_args
35479  #
35480  # key args
35481  #
35482  if $VERBOSE
35483    snd_info("keyargs-2-args")
35484  end
35485  Keyargs.each do |arg1|
35486    random_args.each do |arg2|
35487      Make_procs.each do |n|
35488        Snd.catch do snd_func(n, arg1, arg2) end
35489      end
35490    end
35491  end
35492  dismiss_all_dialogs
35493  if $all_args
35494    if $VERBOSE
35495      snd_info("keyargs-3-args")
35496    end
35497    random_args.each do |arg1|
35498      Keyargs.each do |arg2|
35499        random_args.each do |arg3|
35500          Make_procs.each do |n|
35501            Snd.catch do snd_func(n, arg1, arg2, arg3) end
35502          end
35503        end
35504      end
35505    end
35506    dismiss_all_dialogs
35507    if $VERBOSE
35508      snd_info("keyargs-4-args")
35509    end
35510    random_args.each do |arg1|
35511      Keyargs.each do |arg2|
35512        random_args.each do |arg3|
35513          Keyargs.each do |arg4|
35514            Make_procs.each do |n|
35515              Snd.catch do snd_func(n, arg1, arg2, arg3, arg4) end
35516            end
35517          end
35518        end
35519      end
35520    end
35521    dismiss_all_dialogs
35522  end
35523  #
35524  # 0 Args
35525  #
35526  unless Procs00.empty?
35527    if $VERBOSE
35528      snd_info("no-args")
35529    end
35530    Procs00.each do |n|
35531      if (tag = Snd.catch do
35532            snd_func(n)
35533          end).first == :wrong_number_of_args
35534        snd_display("procs00: %s %s\n# %s", tag, n, snd_help(n))
35535      end
35536    end
35537    dismiss_all_dialogs
35538  end
35539  #
35540  # set no Args
35541  #
35542  unless Set_procs00.empty?
35543    if $VERBOSE
35544      snd_info("set-no-args")
35545    end
35546    main_args.each do |val|
35547      Set_procs00.each do |n|
35548        if (tag = Snd.catch do
35549              set_snd_func(n, val)
35550            end).first == :wrong_number_of_args
35551          snd_display("set_procs00: %s set_%s\n# %s", tag, n, snd_help(n))
35552        end
35553      end
35554    end
35555    dismiss_all_dialogs
35556  end
35557  #
35558  # 1 Arg
35559  #
35560  unless Procs01.empty?
35561    if $VERBOSE
35562      snd_info("1-arg")
35563    end
35564    main_args.each do |arg|
35565      Procs01.each do |n|
35566        if (tag = Snd.catch do
35567              snd_func(n, arg)
35568            end).first == :wrong_number_of_args
35569          snd_display("procs01: %s %s\n# %s", tag, n, snd_help(n))
35570        end
35571      end
35572    end
35573    dismiss_all_dialogs
35574  end
35575  #
35576  # set 1 Arg
35577  #
35578  unless Set_procs01.empty?
35579    if $VERBOSE
35580      snd_info("set-1-arg")
35581    end
35582    main_args.each do |arg1|
35583      main_args.each do |arg2|
35584        Set_procs01.each do |n|
35585          if (tag = Snd.catch do
35586                set_snd_func(n, arg1, arg2)
35587              end).first == :wrong_number_of_args
35588            snd_display("set_procs01: %s set_%s\n# %s", tag, n, snd_help(n))
35589          end
35590        end
35591      end
35592    end
35593    dismiss_all_dialogs
35594  end
35595  #
35596  # 2 Args
35597  #
35598  unless Procs02.empty?
35599    if $VERBOSE
35600      snd_info("2-args")
35601    end
35602    main_args.each do |arg1|
35603      main_args.each do |arg2|
35604        Procs02.each do |n|
35605          if (tag = Snd.catch do
35606                snd_func(n, arg1, arg2)
35607              end).first == :wrong_number_of_args
35608            snd_display("procs02: %s %s\n# %s", tag, n, snd_help(n))
35609          end
35610        end
35611      end
35612    end
35613    dismiss_all_dialogs
35614  end
35615  #
35616  # set 2 Args
35617  #
35618  unless Set_procs02.empty?
35619    if $VERBOSE
35620      snd_info("set-2-args")
35621    end
35622    less_args.each do |arg1|
35623      less_args.each do |arg2|
35624        less_args.each do |arg3|
35625          Set_procs02.each do |n|
35626            if (tag = Snd.catch do
35627                  set_snd_func(n, arg1, arg2, arg3)
35628                end).first == :wrong_number_of_args
35629              snd_display("set_procs02: %s set_%s\n# %s", tag, n, snd_help(n))
35630            end
35631          end
35632        end
35633      end
35634    end
35635    dismiss_all_dialogs
35636  end
35637  #
35638  # 3 Args
35639  #
35640  unless Procs03.empty?
35641    if $VERBOSE
35642      snd_info("3-args")
35643    end
35644    less_args.each do |arg1|
35645      less_args.each do |arg2|
35646        less_args.each do |arg3|
35647          Procs03.each do |n|
35648            if (tag = Snd.catch do
35649                  snd_func(n, arg1, arg2, arg3)
35650                end).first == :wrong_number_of_args
35651              snd_display("procs03: %s %s\n# %s", tag, n, snd_help(n))
35652            end
35653          end
35654        end
35655      end
35656    end
35657    dismiss_all_dialogs
35658  end
35659  #
35660  # set 3 Args
35661  #
35662  unless Set_procs03.empty?
35663    if $VERBOSE
35664      snd_info("set-3-args")
35665    end
35666    less_args.each do |arg1|
35667      less_args.each do |arg2|
35668        less_args.each do |arg3|
35669          less_args.each do |arg4|
35670            Set_procs03.each do |n|
35671              if (tag = Snd.catch do
35672                    set_snd_func(n, arg1, arg2, arg3, arg4)
35673                  end).first == :wrong_number_of_args
35674                snd_display("set_procs03: %s set_%s\n# %s", tag, n, snd_help(n))
35675              end
35676            end
35677          end
35678        end
35679      end
35680    end
35681    dismiss_all_dialogs
35682  end
35683  #
35684  # 4 Args
35685  #
35686  unless Procs04.empty?
35687    if $VERBOSE
35688      snd_info("4-args")
35689    end
35690    few_args.each do |arg1|
35691      few_args.each do |arg2|
35692        few_args.each do |arg3|
35693          few_args.each do |arg4|
35694            Procs04.each do |n|
35695              if (tag = Snd.catch do
35696                    snd_func(n, arg1, arg2, arg3, arg4)
35697                  end).first == :wrong_number_of_args
35698                snd_display("procs04: %s %s\n# %s", tag, n, snd_help(n))
35699              end
35700            end
35701          end
35702        end
35703      end
35704    end
35705    dismiss_all_dialogs
35706  end
35707  #
35708  # set 4 Args
35709  #
35710  unless Set_procs04.empty?
35711    if $VERBOSE
35712      snd_info("set-4-args")
35713    end
35714    few_args.each do |arg1|
35715      few_args.each do |arg2|
35716        few_args.each do |arg3|
35717          few_args.each do |arg4|
35718            few_args.each do |arg5|
35719              Set_procs04.each do |n|
35720                if (tag = Snd.catch do
35721                      set_snd_func(n, arg1, arg2, arg3, arg4, arg5)
35722                    end).first == :wrong_number_of_args
35723                  snd_display("set_procs04: %s set_%s\n# %s", tag, n, snd_help(n))
35724                end
35725              end
35726            end
35727          end
35728        end
35729      end
35730    end
35731    stop_playing
35732    dismiss_all_dialogs
35733  end
35734  #
35735  # 5 Args
35736  #
35737  unless Procs05.empty?
35738    if $VERBOSE
35739      snd_info("5-args")
35740    end
35741    fewer_args.each do |arg1|
35742      fewer_args.each do |arg2|
35743        fewer_args.each do |arg3|
35744          fewer_args.each do |arg4|
35745            fewer_args.each do |arg5|
35746              Procs05.each do |n|
35747                if (tag = Snd.catch do
35748                      snd_func(n, arg1, arg2, arg3, arg4, arg5)
35749                    end).first == :wrong_number_of_args
35750                  snd_display("procs05: %s %s\n# %s", tag, n, snd_help(n))
35751                end
35752              end
35753            end
35754          end
35755        end
35756      end
35757    end
35758    dismiss_all_dialogs
35759  end
35760  #
35761  # 6 Args
35762  #
35763  unless Procs06.empty?
35764    if $VERBOSE
35765      snd_info("6-args")
35766    end
35767    fewer_args.each do |arg1|
35768      fewer_args.each do |arg2|
35769        fewer_args.each do |arg3|
35770          fewer_args.each do |arg4|
35771            fewer_args.each do |arg5|
35772              fewer_args.each do |arg6|
35773                Procs06.each do |n|
35774                  if (tag = Snd.catch do
35775                        snd_func(n, arg1, arg2, arg3, arg4, arg5, arg6)
35776                      end).first == :wrong_number_of_args
35777                    snd_display("procs06: %s %s\n# %s", tag, n, snd_help(n))
35778                  end
35779                end
35780              end
35781            end
35782          end
35783        end
35784      end
35785    end
35786    dismiss_all_dialogs
35787  end
35788  #
35789  # 8 Args
35790  #
35791  unless Procs08.empty?
35792    if $VERBOSE
35793      snd_info("8-args")
35794    end
35795    fewer_args.each do |arg1|
35796      fewer_args.each do |arg2|
35797        fewer_args.each do |arg3|
35798          fewer_args.each do |arg4|
35799            fewer_args.each do |arg5|
35800              fewer_args.each do |arg6|
35801                fewer_args.each do |arg7|
35802                  fewer_args.each do |arg8|
35803                    Procs08.each do |n|
35804                      if (tag = Snd.catch do
35805                            snd_func(n, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
35806                          end).first == :wrong_number_of_args
35807                        snd_display("procs08: %s %s\n# %s", tag, n, snd_help(n))
35808                      end
35809                    end
35810                  end
35811                end
35812              end
35813            end
35814          end
35815        end
35816      end
35817    end
35818    dismiss_all_dialogs
35819  end
35820  #
35821  # 10 Args
35822  #
35823  unless Procs10.empty?
35824    if $VERBOSE
35825      snd_info("10-args")
35826    end
35827    fewer_args.each do |arg1|
35828      fewer_args.each do |arg2|
35829        fewer_args.each do |arg3|
35830          fewer_args.each do |arg4|
35831            fewer_args.each do |arg5|
35832              fewer_args.each do |arg6|
35833                fewer_args.each do |arg7|
35834                  fewer_args.each do |arg8|
35835                    fewer_args.each do |arg9|
35836                      fewer_args.each do |arg10|
35837                        Procs10.each do |n|
35838                          if (tag = Snd.catch do
35839                                snd_func(n, arg1, arg2, arg3, arg4, arg5,
35840                                         arg6, arg7, arg8, arg9, arg10)
35841                              end).first == :wrong_number_of_args
35842                            snd_display("procs10: %s %s\n# %s", tag, n, snd_help(n))
35843                          end
35844                        end
35845                      end
35846                    end
35847                  end
35848                end
35849              end
35850            end
35851          end
35852        end
35853      end
35854    end
35855    dismiss_all_dialogs
35856  end
35857  set_ask_about_unsaved_edits(false)
35858end
35859
35860def test_28_04
35861  File.exist?("test.snd") and File.chmod(0644, "test.snd") and File.unlink("test.snd")
35862  file_copy("oboe.snd", "test.snd")
35863  ind = open_sound("test.snd")
35864  delete_file("test.snd")
35865  if (tag = Snd.catch do update_sound(ind) end).first != :cant_update_file
35866    snd_display("update_sound after deletion: %s", tag)
35867  end
35868  delete_sample(10)
35869  if (tag = Snd.catch do save_sound(ind) end).first != :cannot_save
35870    snd_display("save file deleted: %s", tag)
35871  end
35872  close_sound(ind)
35873  #
35874  file_copy("oboe.snd", "test.snd")
35875  ind = open_sound("test.snd")
35876  reg = select_all
35877  delete_file("test.snd")
35878  view_regions_dialog
35879  close_sound(ind)
35880  #
35881  file_copy("oboe.snd", "test.snd")
35882  ind = open_sound("test.snd")
35883  File.chmod(0400, "test.snd")
35884  delete_sample(10)
35885  if (tag = Snd.catch do save_sound(ind) end).first != :cannot_save
35886    snd_display("save protected sound msg: %s", tag)
35887  end
35888  close_sound(ind)
35889  File.chmod(0644, "test.snd")
35890  delete_file("test.snd")
35891  #
35892  res = Snd.catch do open_sound("test.snd") end
35893  if res.first != :no_such_file and res.first != :mus_error
35894    snd_display("open read_protected sound: %s", res)
35895    sound?(res.car) and close_sound(res.car)
35896  end
35897  #
35898  file_copy("oboe.snd", "test.snd")
35899  File.chmod(0400, "test.snd")
35900  ind = open_sound("oboe.snd")
35901  delete_sample(10)
35902  if (res = Snd.catch do save_sound_as("test.snd") end).first != :cannot_save
35903    snd_display("save_as write_protected sound: %s", res)
35904  end
35905  close_sound(ind)
35906  File.chmod(0644, "test.snd")
35907  delete_file("test.snd")
35908end
35909
35910def test_28
35911  set_with_background_processes(true)
35912  set_remember_sound_state(false)
35913  if $VERBOSE
35914    snd_info("procs  prcs/set-prcs")
35915    snd_info("====================")
35916    snd_info("proc00: %3d/%3d", Procs00.length, Set_procs00.length)
35917    snd_info("proc01: %3d/%3d", Procs01.length, Set_procs01.length)
35918    snd_info("proc02: %3d/%3d", Procs02.length, Set_procs02.length)
35919    snd_info("proc03: %3d/%3d", Procs03.length, Set_procs03.length)
35920    snd_info("proc04: %3d/%3d", Procs04.length, Set_procs04.length)
35921    snd_info("proc05: %3d", Procs05.length)
35922    snd_info("proc06: %3d", Procs06.length)
35923    snd_info("proc07: %3d", Procs07.length)
35924    snd_info("proc08: %3d", Procs08.length)
35925    snd_info("proc10: %3d", Procs10.length)
35926  end
35927  if $with_test_gui
35928    unless Procs.empty?
35929      snd_display("procs: %s?", Procs)
35930    end
35931    unless Set_procs.empty?
35932      snd_display("set_procs: %s?", Set_procs)
35933    end
35934  end
35935  reset_almost_all_hooks
35936  test_28_00
35937  if $with_test_gui
35938    test_28_01
35939    test_28_02
35940  end
35941  test_28_03
35942  test_28_04
35943end
35944
35945# ---------------- test all done
35946
35947def test_30
35948  # $bigtest_08 = true
35949  # test_08_24
35950  test_28_00
35951end
35952
35953main_test
35954
35955# snd-test.rb ends here
35956