everything related to duct tape audio suite (dtas)
 help / color / mirror / code / Atom feed
From: Eric Wong <e@80x24.org>
To: <dtas-all@nongnu.org>
Cc: Eric Wong <e@80x24.org>
Subject: [PATCH 2/3] player: support playing splitfx YAML files
Date: Sat, 27 Dec 2014 12:02:57 +0000	[thread overview]
Message-ID: <1419681778-6183-3-git-send-email-e@80x24.org> (raw)
In-Reply-To: <1419681778-6183-1-git-send-email-e@80x24.org>

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 <dtas-all@nongnu.org>
+# 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 #@offset" : 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



  parent reply	other threads:[~2014-12-27 12:03 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-12-27 12:02 [PATCH 0/3] more functionality for editing audio Eric Wong
2014-12-27 12:02 ` [PATCH 1/3] dtas-console: keys for "cue next/prev" Eric Wong
2014-12-27 12:02 ` Eric Wong [this message]
2014-12-27 12:02 ` [PATCH 3/3] player: support "source restart" command Eric Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://80x24.org/dtas/README

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1419681778-6183-3-git-send-email-e@80x24.org \
    --to=e@80x24.org \
    --cc=dtas-all@nongnu.org \
    --subject='Re: [PATCH 2/3] player: support playing splitfx YAML files' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Code repositories for project(s) associated with this inbox:

	../../dtas.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).