dtas-all
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 2/3] player: support playing splitfx YAML files


From: Eric Wong
Subject: [PATCH 2/3] player: support playing splitfx YAML files
Date: Sat, 27 Dec 2014 12:02:57 +0000

This allows splitfx users to test CUE breakpoints and run
file-specific effects without interrupting their normal flow.
---
 examples/splitfx.sample.yml     |  8 ++++
 lib/dtas/player.rb              |  4 +-
 lib/dtas/source/splitfx.rb      | 92 +++++++++++++++++++++++++++++++++++++++++
 lib/dtas/splitfx.rb             |  8 ++++
 test/test_player_integration.rb |  6 +--
 5 files changed, 114 insertions(+), 4 deletions(-)
 create mode 100644 lib/dtas/source/splitfx.rb

diff --git a/examples/splitfx.sample.yml b/examples/splitfx.sample.yml
index 297e50b..3826012 100644
--- a/examples/splitfx.sample.yml
+++ b/examples/splitfx.sample.yml
@@ -11,6 +11,14 @@ comments:
   ARTIST: John Smith
   ALBUM: Hello World
   YEAR: 2013
+# override the normal sox command for dtas-player playback:
+command: exec sox "$INFILE" $SOXFMT - $TRIMFX $RGFX $FX
+env:
+  # these effects may be used in any command in this file, including targets
+  FX:
+    highpass -1 120 highpass 40 highpass 40
+    ladspa -lr tap_limiter -10 9.5
+    stats
 track_start: 1 # 0 for pregap/intro tracks
 cdda_align: true
 tracks:
diff --git a/lib/dtas/player.rb b/lib/dtas/player.rb
index 39e5abf..0ae8cef 100644
--- a/lib/dtas/player.rb
+++ b/lib/dtas/player.rb
@@ -8,6 +8,7 @@ require_relative 'source'
 require_relative 'source/sox'
 require_relative 'source/av'
 require_relative 'source/ff'
+require_relative 'source/splitfx'
 require_relative 'source/cmd'
 require_relative 'sink'
 require_relative 'unix_server'
@@ -44,9 +45,10 @@ class DTAS::Player # :nodoc:
     @current = nil
     @watchers = {}
     @source_map = {
-      "sox" => DTAS::Source::Sox.new,
+      "sox" => (sox = DTAS::Source::Sox.new),
       "av" => DTAS::Source::Av.new,
       "ff" => DTAS::Source::Ff.new,
+      "splitfx" => DTAS::Source::SplitFX.new(sox),
     }
     source_map_reload
   end
diff --git a/lib/dtas/source/splitfx.rb b/lib/dtas/source/splitfx.rb
new file mode 100644
index 0000000..ad9e7c1
--- /dev/null
+++ b/lib/dtas/source/splitfx.rb
@@ -0,0 +1,92 @@
+# Copyright (C) 2014, all contributors <address@hidden>
+# License: GPLv3 or later <https://www.gnu.org/licenses/gpl-3.0.txt>
+require 'yaml'
+require_relative 'sox'
+require_relative '../splitfx'
+
+class DTAS::Source::SplitFX < DTAS::Source::Sox # :nodoc:
+  MAX_YAML_SIZE = 512 * 1024
+  attr_writer :sox
+
+  SPLITFX_DEFAULTS = SOX_DEFAULTS.merge("tryorder" => 3)
+
+  def initialize(sox = DTAS::Source::Sox.new)
+    command_init(SPLITFX_DEFAULTS)
+    @sox = sox
+  end
+
+  def try(ymlfile, offset = nil)
+    @splitfx = @ymlhash = nil
+    st = File.stat(ymlfile)
+    return false if !st.file? || st.size > MAX_YAML_SIZE
+
+    # read 4 bytes first to ensure we have a YAML file with a hash:
+    buf = ""
+    File.open(ymlfile, "rb") do |fp|
+      return false if fp.read(4, buf) != "---\n"
+      buf << fp.read
+    end
+
+    sfx = DTAS::SplitFX.new
+    begin
+      Dir.chdir(File.dirname(ymlfile)) do # ugh
+        sfx.import(@ymlhash = YAML.load(buf))
+        sfx.infile.replace(File.expand_path(sfx.infile))
+      end
+      @splitfx = sfx
+    rescue
+      return false
+    end
+    @infile = ymlfile
+    sox = @sox.try(sfx.infile, offset) or return false
+    rv = source_file_dup(ymlfile, offset)
+    rv.sox = sox
+    rv.env = sfx.env
+    rv
+  end
+
+  def __load_comments
+    @ymlhash["comments"] || @sox.__load_comments
+  end
+
+  def command_string
+    @ymlhash["command"] || @sox.command_string
+  end
+
+  def spawn(player_format, rg_state, opts)
+    raise "BUG: #{self.inspect}#spawn called twice" if @to_io
+    e = @env.merge!(player_format.to_env)
+    e["INFILE"] = @sox.infile
+
+    # make sure these are visible to the "current" command...
+    e["TRIMFX"] = @offset ? "trim address@hidden" : nil
+    e["RGFX"] = rg_state.effect(self) || nil
+    e.merge!(@rg.to_env) if @rg
+
+    @pid = dtas_spawn(e, command_string, opts)
+  end
+
+  def to_hsh
+    to_hash.delete_if { |k,v| v == SPLITFX_DEFAULTS[k] }
+  end
+
+  def format
+    @sox.format
+  end
+
+  def samples!
+    @sox.samples!
+  end
+
+  def samples
+    @sox.samples
+  end
+
+  def source_defaults
+    SPLITFX_DEFAULTS
+  end
+
+  def cuebreakpoints
+    @splitfx.cuebreakpoints
+  end
+end
diff --git a/lib/dtas/splitfx.rb b/lib/dtas/splitfx.rb
index ac39233..9af3faf 100644
--- a/lib/dtas/splitfx.rb
+++ b/lib/dtas/splitfx.rb
@@ -12,6 +12,7 @@ class DTAS::SplitFX # :nodoc:
         '$TRIMFX $RATEFX $DITHERFX'
   include DTAS::Process
   include DTAS::XS
+  attr_reader :infile, :env
 
   class Skip < Struct.new(:tstart) # :nodoc:
     def commit(_)
@@ -76,6 +77,7 @@ class DTAS::SplitFX # :nodoc:
     }
     @tracks = []
     @infmt = nil # wait until input is assigned
+    @cuebp = nil # for playback
   end
 
   def _bool(hash, key)
@@ -334,4 +336,10 @@ class DTAS::SplitFX # :nodoc:
     end
     false
   end
+
+  def cuebreakpoints
+    rv = @cuebp and return rv
+    require_relative 'cue_index'
+    @cuebp = @tracks.map { |t| DTAS::CueIndex.new(1, "#{t.tstart}s") }
+  end
 end
diff --git a/test/test_player_integration.rb b/test/test_player_integration.rb
index 66f599e..2525ac5 100644
--- a/test/test_player_integration.rb
+++ b/test/test_player_integration.rb
@@ -208,11 +208,11 @@ class TestPlayerIntegration < Testcase
 
   def test_source_ed
     s = client_socket
-    assert_equal "sox av ff", s.req("source ls")
+    assert_equal "sox av ff splitfx", s.req("source ls")
     s.req_ok("source ed av tryorder=-1")
-    assert_equal "av sox ff", s.req("source ls")
+    assert_equal "av sox ff splitfx", s.req("source ls")
     s.req_ok("source ed av tryorder=")
-    assert_equal "sox av ff", s.req("source ls")
+    assert_equal "sox av ff splitfx", s.req("source ls")
 
     s.req_ok("source ed sox command=true")
     sox = YAML.load(s.req("source cat sox"))
-- 
EW




reply via email to

[Prev in Thread] Current Thread [Next in Thread]