"Fossies" - the Fresh Open Source Software Archive

Member "snd-20.9/rubber.rb" (11 Apr 2018, 11406 Bytes) of package /linux/misc/snd-20.9.tar.gz:


As a special service "Fossies" has tried to format the requested text file into HTML format (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 # rubber.rb -- Translation of rubber.scm
    2 
    3 # Translator/Author: Michael Scholz <mi-scholz@users.sourceforge.net>
    4 # Created: 03/02/28 03:04:03
    5 # Changed: 14/11/23 06:14:52
    6 
    7 # module Rubber (see rubber.scm)
    8 #  add_named_mark(samp, name, snd, chn)
    9 #  derumble_sound(snd, chn)
   10 #  sample_sound(snd, chn)
   11 #  unsample_sound(snd, chn)
   12 #  crossings()
   13 #  env_add(s0, s1, samps)
   14 #  rubber_sound(stretch, snd, chn)
   15 
   16 require "clm"
   17 
   18 module Rubber
   19   doc "#{self.class} #{self.name} is the translation of rubber.scm.\n"
   20   
   21   $zeros_checked = 8
   22   $extension = 10.0
   23   $show_details = false
   24   
   25   def add_named_mark(samp, name, snd = false, chn = false)
   26     m = add_mark(samp.round, snd, chn)
   27     set_mark_name(m, name)
   28     m
   29   end
   30 
   31   def derumble_sound(snd = false, chn = false)
   32     old_length = framples(snd, chn)
   33     pow2 = (log([old_length, srate(snd)].min) / log(2)).ceil
   34     fftlen = (2 ** pow2).round
   35     flt_env = [0.0, 0.0, 32.0 / srate(snd), 0.0,
   36                40.0 / srate(snd), 1.0, 1.0, 1.0]
   37     filter_sound(flt_env, fftlen, snd, chn)
   38     set_framples(old_length, snd, chn)
   39   end
   40 
   41   def sample_sound(snd = false, chn = false)
   42     if $extension != 1.0
   43       src_sound(1.0 / $extension, 1.0, snd, chn)
   44     end
   45   end
   46 
   47   def unsample_sound(snd = false, chn = false)
   48     if $extension != 1.0
   49       src_sound($extension, 1.0, snd, chn)
   50     end
   51   end
   52 
   53   def crossings
   54     crosses = 0
   55     sr0 = make_sampler(0)
   56     samp0 = next_sample(sr0)
   57     len = framples()
   58     sum = 0.0
   59     last_cross = 0
   60     silence = $extension * 0.001
   61     (0...len).each do |i|
   62       samp1 = next_sample(sr0)
   63       if samp0 <= 0.0 and
   64           samp1 > 0.0 and
   65           (i - last_cross) > 4 and
   66           sum > silence
   67         crosses += 1
   68         last_cross = i
   69         sum = 0.0
   70       end
   71       sum += samp0.abs
   72       samp0 = samp1
   73     end
   74     crosses
   75   end
   76 
   77   def env_add(s0, s1, samps)
   78     data = make_vct(samps.round)
   79     x = 1.0
   80     xinc = 1.0 / samps
   81     sr0 = make_sampler(s0.round)
   82     sr1 = make_sampler(s1.round)
   83     (0...samps).each do |i|
   84       data[i] = x * next_sample(sr0) + (1.0 - x) * next_sample(sr1)
   85       x += xinc
   86     end
   87     data
   88   end
   89 
   90   def rubber_sound(stretch, snd = false, chn = false)
   91     as_one_edit(lambda do | |
   92                   derumble_sound(snd, chn)
   93                   sample_sound(snd, chn)
   94                   crosses = crossings()
   95                   cross_samples = make_vct(crosses)
   96                   cross_weights = make_vct(crosses)
   97                   cross_marks = make_vct(crosses)
   98                   cross_periods = make_vct(crosses)
   99                   sr0 = make_sampler(0, snd, chn)
  100                   samp0 = next_sample(sr0)
  101                   len = framples()
  102                   sum = 0.0
  103                   last_cross = 0
  104                   cross = 0
  105                   silence = $extension * 0.001
  106                   (0...len).each do |i|
  107                     samp1 = next_sample(sr0)
  108                     if samp0 <= 0.0 and
  109                         samp1 > 0.0 and
  110                         (i - last_cross) > 4 and
  111                         sum > silence
  112                       last_cross = i
  113                       sum = 0.0
  114                       cross_samples[cross] = i
  115                       cross += 1
  116                     end
  117                     sum += samp0.abs
  118                     samp0 = samp1
  119                   end
  120                   (0...(crosses - 1)).each do |i|
  121                     start = cross_samples[i]
  122                     autolen = 0
  123                     s0 = start
  124                     pow2 = (log($extension * (srate() / 40.0)) / log(2)).ceil
  125                     fftlen = (2 ** pow2).round
  126                     len4 = fftlen / 4
  127                     data = make_vct(fftlen)
  128                     reader = make_sampler(s0.round)
  129                     (0...fftlen).each do |j|
  130                       data[j] = next_sample(reader)
  131                     end
  132                     autocorrelate(data)
  133                     autolen = 0
  134                     (1...len4).detect do |j|
  135                       if data[j] < data[j + 1] and data[j + 1] > data[j + 2]
  136                         autolen = j * 2
  137                         true
  138                       end
  139                     end
  140                     next_start = start + autolen
  141                     min_i = i + 1
  142                     min_samps = (cross_samples[min_i] - next_start).abs
  143                     ((i + 2)...[crosses, i + $zeros_checked].min).each do |k|
  144                       dist = (cross_samples[k] - next_start).abs
  145                       if dist < min_samps
  146                         min_samps = dist
  147                         min_i = k
  148                       end
  149                     end
  150                     current_mark = min_i
  151                     current_min = 0.0
  152                     s0 = start
  153                     s1 = cross_samples[current_mark]
  154                     len = autolen
  155                     sr0 = make_sampler(s0.round)
  156                     sr1 = make_sampler(s1.round)
  157                     ampsum = 0.0
  158                     diffsum = 0.0
  159                     (0...len).each do |dummy|
  160                       samp0 = next_sample(sr0)
  161                       samp1 = next_sample(sr1)
  162                       ampsum += samp0.abs
  163                       diffsum += (samp1 - samp0).abs
  164                     end
  165                     if diffsum == 0.0
  166                       current_min = 0.0
  167                     else
  168                       current_min = diffsum / ampsum
  169                     end
  170                     min_samps = 0.5 * current_min
  171                     top = [crosses - 1, current_mark, i + $zeros_checked].min
  172                     ((i + 1)...top).each do |k|
  173                       wgt = 0.0
  174                       s0 = start
  175                       s1 = cross_samples[k]
  176                       len = autolen
  177                       sr0 = make_sampler(s0.round)
  178                       sr1 = make_sampler(s1.round)
  179                       ampsum = 0.0
  180                       diffsum = 0.0
  181                       (0...len).each do |dummy|
  182                         samp0 = next_sample(sr0)
  183                         samp1 = next_sample(sr1)
  184                         ampsum += samp0.abs
  185                         diffsum += (samp1 - samp0).abs
  186                       end
  187                       if diffsum == 0.0
  188                         wgt = 0.0
  189                       else
  190                         wgt = diffsum / ampsum
  191                       end
  192                       if wgt < min_samps
  193                         min_samps = wgt
  194                         min_i = k
  195                       end
  196                     end
  197                     unless current_mark == min_i
  198                       cross_weights[i] = 1000.0
  199                     else
  200                       cross_weights[i] = current_min
  201                       cross_marks[i] = current_mark
  202                       cross_periods[i] = cross_samples[current_mark] -
  203                                          cross_samples[i]
  204                     end
  205                   end
  206                   len = framples(snd, chn)
  207                   adding = (stretch > 1.0)
  208                   samps = ((stretch - 1.0).abs * len).round
  209                   needed_samps = (adding ? samps : [len, samps * 2].min)
  210                   handled = 0
  211                   mult = 1
  212                   curs = 0
  213                   weigths = cross_weights.length
  214                   edits = make_vct(weigths)
  215                   until curs == weigths or handled >= needed_samps
  216                     best_mark = -1
  217                     old_handled = handled
  218                     cur = 0
  219                     curmin = cross_weights[0]
  220                     cross_weights.each_with_index do |cross_w, i|
  221                       if cross_w < curmin
  222                         cur = i
  223                         curmin = cross_w
  224                       end
  225                     end
  226                     best_mark = cur
  227                     handled += cross_periods[best_mark].round
  228                     if (handled < needed_samps) or
  229                        ((handled - needed_samps) < (needed_samps - old_handled))
  230                       edits[curs] = best_mark
  231                       curs += 1
  232                     end
  233                     cross_weights[best_mark] = 1000.0
  234                   end
  235                   mult = (needed_samps / handled).ceil if curs >= weigths
  236                   changed_len = 0
  237                   weights = cross_weights.length
  238                   (0...curs).detect do |i|
  239                     best_mark = edits[i].round
  240                     beg = cross_samples[best_mark].to_i
  241                     next_beg = cross_samples[cross_marks[best_mark].round]
  242                     len = cross_periods[best_mark].to_i
  243                     if len > 0
  244                       if adding
  245                         new_samps = env_add(beg, next_beg, len)
  246                         if $show_details
  247                           add_named_mark(beg,
  248                                          format("%d:%d",
  249                                                 i, (len / $extension).round))
  250                         end
  251                         insert_samples(beg, len, new_samps)
  252                         if mult > 1
  253                           (1...mult).each do |k|
  254                             insert_samples(beg + k * len, len, new_samps)
  255                           end
  256                         end
  257                         changed_len = changed_len + mult * len
  258                         (0...weights).each do |j|
  259                           curbeg = cross_samples[j]
  260                           if curbeg > beg
  261                             cross_samples[j] = curbeg + len
  262                           end
  263                         end
  264                       else
  265                         frms = framples()
  266                         if beg >= frms
  267                           Snd.display("trouble at %d: %d of %d", i, beg, frms)
  268                         end
  269                         if $show_details
  270                           add_named_mark(beg - 1,
  271                                          format("%d:%d",
  272                                                 i, (len / $extension).round))
  273                         end
  274                         delete_samples(beg, len)
  275                         changed_len += len
  276                         fin = beg + len
  277                         (0...weights).each do |j|
  278                           curbeg = cross_samples[j]
  279                           if curbeg > beg
  280                             if curbeg < fin
  281                               cross_periods[j] = 0
  282                             else
  283                               cross_samples[j] = curbeg - len
  284                             end
  285                           end
  286                         end
  287                       end
  288                     end
  289                     changed_len > samps
  290                   end
  291                   if $show_details
  292                     Snd.display("wanted: %d, got %d",
  293                                 samps.round, changed_len.round)
  294                   end
  295                   unsample_sound(snd, chn)
  296                   if $show_details
  297                     frms0 = framples(snd, chn, 0)
  298                     Snd.display("%f -> %f (%f)",
  299                                 frms0,
  300                                 framples(snd,chn),
  301                                 (stretch * frms0).round)
  302                   end
  303                 end,
  304                 format("rubber_sound(%f, %p, %p,", stretch, snd, chn))
  305   end
  306 end
  307 
  308 include Rubber
  309 
  310 # rubber.rb ends here