about summary refs log tree commit homepage
path: root/lib/dtas/source
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2015-01-28 07:44:05 +0000
committerEric Wong <e@80x24.org>2015-01-28 07:47:57 +0000
commit37eae22446feb5a805d9cd59f6ad54362829189f (patch)
tree50172ce0b549fb9a0eae1e2e0b4d6bc47bc3a8d6 /lib/dtas/source
parentead7725fa693c7dd832b22f77b32847c81a70d72 (diff)
downloaddtas-37eae22446feb5a805d9cd59f6ad54362829189f.tar.gz
This feature is intended to allow users to "zoom-in" on a
particular portion of a track to tweak parameters (either
with dtas-sourceedit(1) or via playback of splitfx YAML files).
This may be combined with looping the tracklist
(via "tl repeat").
Diffstat (limited to 'lib/dtas/source')
-rw-r--r--lib/dtas/source/av.rb2
-rw-r--r--lib/dtas/source/av_ff_common.rb25
-rw-r--r--lib/dtas/source/ff.rb2
-rw-r--r--lib/dtas/source/file.rb24
-rw-r--r--lib/dtas/source/sox.rb6
-rw-r--r--lib/dtas/source/splitfx.rb8
6 files changed, 48 insertions, 19 deletions
diff --git a/lib/dtas/source/av.rb b/lib/dtas/source/av.rb
index 722c798..c86b5d2 100644
--- a/lib/dtas/source/av.rb
+++ b/lib/dtas/source/av.rb
@@ -10,7 +10,7 @@ class DTAS::Source::Av # :nodoc:
   AV_DEFAULTS = COMMAND_DEFAULTS.merge(
     "command" =>
       'avconv -v error $SSPOS $PROBE -i "$INFILE" $AMAP -f sox - |' \
-      'sox -p $SOXFMT - $RGFX',
+      'sox -p $SOXFMT - $TRIMFX $RGFX',
 
     # this is above ffmpeg because this av is the Debian default and
     # it's easier for me to test av than ff
diff --git a/lib/dtas/source/av_ff_common.rb b/lib/dtas/source/av_ff_common.rb
index 03526d2..189e135 100644
--- a/lib/dtas/source/av_ff_common.rb
+++ b/lib/dtas/source/av_ff_common.rb
@@ -19,8 +19,8 @@ module DTAS::Source::AvFfCommon # :nodoc:
   attr_reader :precision # always 32
   attr_reader :format
 
-  def try(infile, offset = nil)
-    rv = source_file_dup(infile, offset)
+  def try(infile, offset = nil, trim = nil)
+    rv = source_file_dup(infile, offset, trim)
     rv.av_ff_ok? or return
     rv
   end
@@ -101,10 +101,20 @@ module DTAS::Source::AvFfCommon # :nodoc:
     ! @astreams.compact.empty?
   end
 
-  def sspos(offset)
-    offset =~ /\A(\d+)s\z/ or return "-ss #{offset}"
-    samples = $1.to_f
-    sprintf("-ss %0.9g", samples / @format.rate)
+  def sspos
+    return unless @offset || @trim
+    off = offset_samples / @format.rate.to_f
+    sprintf('-ss %0.9g', off)
+  end
+
+  def av_ff_trimfx # for sox
+    return unless @trim
+    tbeg, tlen = @trim # Floats
+    tend = tbeg + tlen
+    off = offset_samples / @format.rate.to_f
+    tlen = tend - off
+    tlen = 0 if tlen < 0
+    sprintf('trim 0 %0.9g', tlen)
   end
 
   def select_astream(as)
@@ -150,8 +160,9 @@ module DTAS::Source::AvFfCommon # :nodoc:
     # make sure these are visible to the source command...
     e["INFILE"] = @infile
     e["AMAP"] = amap
-    e["SSPOS"] = @offset ? sspos(@offset) : nil
+    e["SSPOS"] = sspos
     e["RGFX"] = rg_state.effect(self) || nil
+    e["TRIMFX"] = av_ff_trimfx
     e.merge!(@rg.to_env) if @rg
 
     @pid = dtas_spawn(e, command_string, opts)
diff --git a/lib/dtas/source/ff.rb b/lib/dtas/source/ff.rb
index c59de40..d5e744c 100644
--- a/lib/dtas/source/ff.rb
+++ b/lib/dtas/source/ff.rb
@@ -12,7 +12,7 @@ class DTAS::Source::Ff  # :nodoc:
   FF_DEFAULTS = COMMAND_DEFAULTS.merge(
     "command" =>
       'ffmpeg -v error $SSPOS $PROBE -i "$INFILE" $AMAP -f sox - |' \
-      'sox -p $SOXFMT - $RGFX',
+      'sox -p $SOXFMT - $TRIMFX $RGFX',
 
     # I haven't tested this much since av is in Debian stable and ff is not
     "tryorder" => 2,
diff --git a/lib/dtas/source/file.rb b/lib/dtas/source/file.rb
index 8a9fa34..75b4a43 100644
--- a/lib/dtas/source/file.rb
+++ b/lib/dtas/source/file.rb
@@ -21,17 +21,18 @@ module DTAS::Source::File # :nodoc:
   FILE_SIVS = %w(infile comments command env) # for the "current" command
   SRC_SIVS = %w(command env tryorder)
 
-  def source_file_dup(infile, offset)
+  def source_file_dup(infile, offset, trim)
     rv = dup
-    rv.__file_init(infile, offset)
+    rv.__file_init(infile, offset, trim)
     rv
   end
 
-  def __file_init(infile, offset)
+  def __file_init(infile, offset, trim)
     @env = @env.dup
     @format = nil
     @infile = infile
     @offset = offset
+    @trim = trim
     @comments = nil
     @samples = nil
     @cuebp = nil
@@ -47,6 +48,13 @@ module DTAS::Source::File # :nodoc:
   # returns any offset in samples (relative to the original source file),
   # likely zero unless seek was used
   def offset_samples
+    off = __offset_samples
+    return off unless @trim
+    tbeg = @trim[0] * format.rate
+    tbeg < off ? off : tbeg
+  end
+
+  def __offset_samples
     return 0 unless @offset
     case @offset
     when /\A\d+s\z/
@@ -56,6 +64,16 @@ module DTAS::Source::File # :nodoc:
     end
   end
 
+  # creates the effect to fill the TRIMFX env
+  def trimfx
+    return unless @offset || @trim
+    fx = "trim #{offset_samples}s"
+    if @trim && @trim[1]
+      fx << sprintf(' =%0.9gs', (@trim[0] + @trim[1]) * format.rate)
+    end
+    fx
+  end
+
   # A user may be downloading the file and start playing
   # it before the download completes, this refreshes
   def samples!
diff --git a/lib/dtas/source/sox.rb b/lib/dtas/source/sox.rb
index 99dfe35..91a3c40 100644
--- a/lib/dtas/source/sox.rb
+++ b/lib/dtas/source/sox.rb
@@ -38,13 +38,13 @@ class DTAS::Source::Sox # :nodoc:
     command_init(SOX_DEFAULTS)
   end
 
-  def try(infile, offset = nil)
+  def try(infile, offset = nil, trim = nil)
     err = ""
     cmd = %W(soxi -s #{infile})
     s = qx(@env.dup, cmd, err_str: err, no_raise: true)
     return if err =~ /soxi FAIL formats:/
     self.class.try_to_fail_harder(infile, s, cmd) or return
-    source_file_dup(infile, offset)
+    source_file_dup(infile, offset, trim)
   end
 
   def format
@@ -81,7 +81,7 @@ class DTAS::Source::Sox # :nodoc:
     e["INFILE"] = @infile
 
     # make sure these are visible to the "current" command...
-    e["TRIMFX"] = @offset ? "trim #@offset" : nil
+    e["TRIMFX"] = trimfx
     e["RGFX"] = rg_state.effect(self) || nil
     e.merge!(@rg.to_env) if @rg
 
diff --git a/lib/dtas/source/splitfx.rb b/lib/dtas/source/splitfx.rb
index 680ad8b..b7b9b86 100644
--- a/lib/dtas/source/splitfx.rb
+++ b/lib/dtas/source/splitfx.rb
@@ -20,7 +20,7 @@ class DTAS::Source::SplitFX < DTAS::Source::Sox # :nodoc:
     @sox = sox
   end
 
-  def try(ymlfile, offset = nil)
+  def try(ymlfile, offset = nil, trim = nil)
     @splitfx = @ymlhash = nil
     st = File.stat(ymlfile)
     return false if !st.file? || st.size > MAX_YAML_SIZE
@@ -41,8 +41,8 @@ class DTAS::Source::SplitFX < DTAS::Source::Sox # :nodoc:
     end
     @splitfx = sfx
     @infile = ymlfile
-    sox = @sox.try(sfx.infile, offset) or return false
-    rv = source_file_dup(ymlfile, offset)
+    sox = @sox.try(sfx.infile, offset, trim) or return false
+    rv = source_file_dup(ymlfile, offset, trim)
     rv.sox = sox
     rv.env = sfx.env
     rv.sfx = sfx
@@ -66,7 +66,7 @@ class DTAS::Source::SplitFX < DTAS::Source::Sox # :nodoc:
     @sfx.infile_env(e, @sox.infile)
 
     # make sure these are visible to the "current" command...
-    e["TRIMFX"] = @offset ? "trim #@offset" : nil
+    e["TRIMFX"] = trimfx
     e["RGFX"] = rg_state.effect(self) || nil
     e.merge!(@rg.to_env) if @rg