Skip to content

Instantly share code, notes, and snippets.

@larryfox
Last active August 29, 2015 14:22
Show Gist options
  • Save larryfox/51fc6a7df1c3de4de9b1 to your computer and use it in GitHub Desktop.
Save larryfox/51fc6a7df1c3de4de9b1 to your computer and use it in GitHub Desktop.
Generate sample chains for use with the Elektron Octatrack
#!/usr/bin/env ruby
require 'pathname'
def run_cmd(*cmd)
io = IO.popen cmd.map(&:to_s)
io.read.chomp
end
class Sample
include Comparable
attr_reader :filename, :duration, :sample_rate
def initialize(filename)
@filename = filename
@sample_rate = (run_cmd 'soxi', '-r', filename).to_i
@duration = (run_cmd 'soxi', '-s', filename).to_i
end
def pad(max_duration)
diff = (max_duration - duration) / sample_rate.to_f
run_cmd 'sox', filename, padded_filename, 'pad', 0, diff
end
def padded_filename
@padded_filename ||= filename.sub(/.wav$/, '.padded.wav')
end
def <=>(rhs)
duration <=> rhs.duration
end
end
class SampleChain
attr_reader :samples
def initialize(input)
@samples = begin
input.map { |x| Pathname.new(x) }
.select(&:exist?)
.map { |x| Sample.new(x.to_s) }
end
end
def save_to(output)
# Pad samples
samples.each { |x| x.pad(longest_sample.duration) }
# Concatenate padded files
run_cmd 'sox', *padded_samples, output
# Clean up padded files
run_cmd 'rm', '-f', *padded_samples
end
private
def longest_sample
@longest_sample ||= samples.max
end
def padded_samples
@padded_samples ||= samples.map(&:padded_filename)
end
end
# Get input from arguments or read from stdin
input = (ARGV.empty? ? $stdin.read.split : ARGV)
SampleChain.new(input).save_to('out.wav')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment