about summary refs log tree commit homepage
diff options
context:
space:
mode:
-rw-r--r--lib/dtas/fadefx.rb56
-rw-r--r--lib/dtas/format.rb1
-rw-r--r--test/test_fadefx.rb17
3 files changed, 74 insertions, 0 deletions
diff --git a/lib/dtas/fadefx.rb b/lib/dtas/fadefx.rb
index d67f896..899505b 100644
--- a/lib/dtas/fadefx.rb
+++ b/lib/dtas/fadefx.rb
@@ -2,7 +2,9 @@
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require_relative '../dtas'
 require_relative 'parse_time'
+require_relative 'xs'
 
+# note: This is sox-specific
 # --------- time --------->
 # _____   _______   ______
 #      \ /       \ /
@@ -15,6 +17,7 @@ require_relative 'parse_time'
 # in_next  - controls the upward slope into next
 class DTAS::FadeFX # :nodoc:
   include DTAS::ParseTime
+  include DTAS::XS
 
   attr_reader :out_prev, :in_cur, :out_cur, :in_next
   F = Struct.new(:type, :flen)
@@ -28,6 +31,59 @@ class DTAS::FadeFX # :nodoc:
     end
   end
 
+  def fade_cur_fx(format, tbeg, tlen, args = [])
+    fx = %W(trim #{tbeg}s #{tlen}s)
+    fx.concat(args)
+    if @in_cur && @out_cur && @in_cur.type == @out_cur.type
+      f = %W(fade #{@in_cur.type} #{@in_cur.flen} #{tlen}s #{@out_cur.flen})
+      fx.concat(f)
+    else # differing fade types for in/out, chain them:
+      fpart = @in_cur and
+        fx.concat(%W(fade #{fpart.type} #{fpart.flen} 0 0))
+      fpart = @out_cur and
+        fx.concat(%W(fade #{fpart.type} 0 #{tlen}s #{fpart.flen}))
+    end
+    fx
+  end
+
+  def fade_out_prev_fx(format, tbeg, tlen)
+    fx = %W(trim #{tbeg}s)
+
+    if fpart = @out_prev
+      out_len = format.hhmmss_to_samples(fpart.flen)
+      fx.concat(%W(fade #{fpart.type} 0 #{out_len}s #{out_len}s))
+      remain = tlen - out_len
+
+      # fade-out is longer than tlen, so truncate again:
+      remain < 0 and fx.concat(%W(trim 0 #{tlen}s))
+
+      # pad with silence, this is where fade_cur_fx goes
+      remain > 0 and fx.concat(%W(pad #{remain}s@#{out_len}s))
+    end
+    fx
+  end
+
+  def fade_in_next_fx(format, tbeg, tlen)
+    fpart = @in_next
+    flen = fpart ? fpart.flen : 0
+    nlen = format.hhmmss_to_samples(flen)
+    nbeg = tbeg + tlen - nlen
+    npad = nbeg - tbeg
+    if npad < 0
+      warn("in_next should not exceed range: #{inspect} @trim " \
+           "#{tbeg}s #{tlen}s\nclamping to #{tbeg}")
+      nbeg = tbeg
+    end
+
+    fx = %W(trim #{nbeg}s #{nlen}s)
+    nlen != 0 and
+      fx.concat(%W(fade #{fpart.type} #{nlen}s 0 0))
+
+    # likely, the pad section is where fade_cur_fx goes
+    npad > 0 and fx.concat(%W(pad #{npad}s@0s))
+    fx
+  end
+
   # q - quarter of a sine wave
   # h - half a sine wave
   # t - linear (`triangular') slope
diff --git a/lib/dtas/format.rb b/lib/dtas/format.rb
index a76b893..a6314bd 100644
--- a/lib/dtas/format.rb
+++ b/lib/dtas/format.rb
@@ -165,6 +165,7 @@ class DTAS::Format # :nodoc:
   # HH:MM:SS.frac (don't bother with more complex times, too much code)
   # part of me wants to drop this feature from playq, feels like bloat...
   def hhmmss_to_samples(hhmmss)
+    Numeric === hhmmss and return hhmmss * @rate
     time = hhmmss.dup
     rv = 0
     if time.sub!(/\.(\d+)\z/, "")
diff --git a/test/test_fadefx.rb b/test/test_fadefx.rb
index 942a4b6..5c84578 100644
--- a/test/test_fadefx.rb
+++ b/test/test_fadefx.rb
@@ -2,6 +2,7 @@
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require_relative 'helper'
 require 'dtas/fadefx'
+require 'dtas/format'
 
 class TestFadeFX < Testcase
   def test_fadefx
@@ -14,6 +15,22 @@ class TestFadeFX < Testcase
     assert_equal 4, ffx.out_cur.flen
     assert_equal 't', ffx.in_next.type
     assert_equal 1, ffx.in_next.flen
+
+    fmt = DTAS::Format.new
+    fmt.rate = 48000
+    tbeg = 0
+    tlen = 48000 * 9
+
+    # XXX: this isn't testing much...
+    cur = ffx.fade_cur_fx(fmt, tbeg, tlen, %w(vol +3dB))
+    assert_equal(%w(trim 0s 432000s vol +3dB
+                    fade t 3.1 0 0 fade l 0 432000s 4), cur)
+    out = ffx.fade_out_prev_fx(fmt, tbeg, tlen)
+    assert_equal(%w(trim 0s
+                    fade t 0 48000s 48000s pad 384000s@48000s), out)
+    inn = ffx.fade_in_next_fx(fmt, tbeg, tlen)
+    assert_equal(%w(trim 384000s 48000s
+                    fade t 48000s 0 0 pad 384000s@0s), inn)
   end
 
   def test_fadefx_no_cur