Skip to content

Commit

Permalink
Added audio info functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
Mark committed Oct 24, 2012
1 parent b2fe6ed commit a77eb33
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 22 deletions.
11 changes: 8 additions & 3 deletions app/controllers/media_controller.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
class MediaController < ApplicationController
include Spectrogram
def index
def info
@input_path = './test/fixtures/'
@audio = 'TorresianCrow.wav'
# not-an-audio-file.wav
# TorresianCrow.wav
# TestAudio1.wv
# sites.yml
# this file does not exist.nope
@audio = 'TestAudio1.wv'
@input_audio = @input_path + @audio
@result = Audio::info(@input_audio)
end
Expand All @@ -16,7 +21,7 @@ def audio
@input_audio = @input_path + @audio
@output_audio = @output_path + @modified_audio

@result = Audio::segment(@input_audio, @output_audio)
@result = Audio::modify(@input_audio, @output_audio, [])
end
def spectrogram
@input_path = './test/fixtures/'
Expand Down
Empty file added app/views/media/audio.html.erb
Empty file.
1 change: 1 addition & 0 deletions app/views/media/info.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<%= @result %>
File renamed without changes.
17 changes: 17 additions & 0 deletions lib/modules/OS.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module OS
def OS.windows?
(/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil
end

def OS.mac?
(/darwin/ =~ RUBY_PLATFORM) != nil
end

def OS.unix?
!OS.windows?
end

def OS.linux?
OS.unix? and not OS.mac?
end
end
110 changes: 96 additions & 14 deletions lib/modules/audio.rb
Original file line number Diff line number Diff line change
@@ -1,33 +1,115 @@
module Audio

@ffmpeg_path = "./vendor/bin/ffmpeg/windows/ffmpeg.exe"
@ffprobe_path = "./vendor/bin/ffmpeg/windows/ffprobe.exe"
@sox_path = "./vendor/bin/sox/windows/sox.exe"
@wvunpack_path = "./vendor/bin/wavpack/windows/wvunpack.exe"
@mp3splt_path = "./vendor/bin/mp3splt/windows/mp3splt.exe"

@sox_arguments_info = "--info"
@@my_logger ||= Logger.new("#{Rails.root}/log/my.log")

# public methods
public

# Provides information about an audio file.
def self.info(source)
# sox command to create a spectrogram from an audio file
command = "#{@sox_path} #{@sox_arguments_info} \"#{source}\""

# run the command and wait for the result
stdout_str, stderr_str, status = Open3.capture3(command)

info = []
error = []

# get the audio file information from the stdout_str
something = stdout_str.each_line { |substr| p substr.index(':') }

# package up all the available information and return it
result = [ stdout_str, stderr_str, status, File.exist?(source), something ]
sox_info source, info, error
ffprobe_info source, info, error
wvunpack_info source, info, error

# return the packaged info array
[ info, error ]
end
def self.segment(source, destination)

# Creates a new audio file from source path in target path, modified according to the
# parameters in modify_parameters
def self.modify(source, target, modify_parameters)
# sox command to create a spectrogram from an audio file
command = "#{@sox_path} #{@sox_arguments_verbose} \"#{source}\" #{@sox_arguments_output_audio} #{@sox_arguments_sample_rate} #{@sox_arguments_spectrogram} #{@sox_arguments_output} \"#{destination}\""
command = "#{@sox_path} #{@sox_arguments_verbose} \"#{source}\" #{@sox_arguments_output_audio} #{@sox_arguments_sample_rate} #{@sox_arguments_spectrogram} #{@sox_arguments_output} \"#{target}\""

# run the command and wait for the result
stdout_str, stderr_str, status = Open3.capture3(command)

# package up all the available information and return it
result = [ stdout_str, stderr_str, status, File.exist?(source), File.exist?(destination) ]
result = [ stdout_str, stderr_str, status, File.exist?(source), File.exist?(target) ]
end

# private methods
private

def self.sox_info(source, info, error)
sox_arguments_info = "--info"
sox_command = "#{@sox_path} #{sox_arguments_info} \"#{source}\"" # commands to get info from audio file
sox_stdout_str, sox_stderr_str, sox_status = Open3.capture3(sox_command) # run the commands and wait for the result

if sox_status.exitstatus == 0
# sox std out contains info (separate on first colon(:))
sox_stdout_str.strip.split(/\r?\n|\r/).each { |line| info.push [ 'SOX ' + line[0,line.index(':')].strip, line[line.index(':')+1,line.length].strip ] }
# sox_stderr_str is empty
else
error.push ['SOX ERROR',sox_stderr_str]
end
end

def self.ffprobe_info(source, info, error)
ffprobe_arguments_info = "-sexagesimal -print_format default -show_error -show_streams -show_format"
ffprobe_command = "#{@ffprobe_path} #{ffprobe_arguments_info} \"#{source}\""
ffprobe_stdout_str, ffprobe_stderr_str, ffprobe_status = Open3.capture3(ffprobe_command)

if ffprobe_status.exitstatus == 0
# ffprobe std out contains info (separate on first equals(=))
# ffprobe_stderr_str contains progress info and human-formatted info
ffprobe_current_block_name = ''
ffprobe_stdout_str.strip.split(/\r?\n|\r/).each do |line|
line.strip!
if line[0] == '['
# this chomp reverse stuff is due to the lack of a proper 'trim'
ffprobe_current_block_name = line.chomp(']').reverse.chomp('[').reverse
else
current_key = line[0,line.index('=')].strip
current_value = line[line.index('=')+1,line.length].strip
info.push [ 'FFPROBE ' + ffprobe_current_block_name + ' ' + current_key, current_value ]
end
end
else
# ffprobe std err contains info (separate on first equals(=))
ffprobe_current_block_name = ''
ffprobe_stdout_str.strip.split(/\r?\n|\r/).each do |line|
line.strip!
if line[0] == '['
# this chomp reverse stuff is due to the lack of a proper 'trim'
ffprobe_current_block_name = line.chomp(']').reverse.chomp('[').reverse
else
current_key = line[0,line.index('=')].strip
current_value = line[line.index('=')+1,line.length].strip
error.push [ 'FFPROBE ' + ffprobe_current_block_name + ' ' + current_key, current_value ]
end
end
end
end

def self.wvunpack_info(source, info, error)
wvunpack_arguments_info = "-s"
wvunpack_command = "#{@wvunpack_path} #{wvunpack_arguments_info} \"#{source}\"" # commands to get info from audio file
wvunpack_stdout_str, wvunpack_stderr_str, wvunpack_status = Open3.capture3(wvunpack_command) # run the commands and wait for the result

if wvunpack_status.exitstatus == 0
# wvunpack std out contains info (separate on first colon(:))
wvunpack_stdout_str.strip.split(/\r?\n|\r/).each do |line|
line.strip!
current_key = line[0,line.index(':')].strip
current_value = line[line.index(':')+1,line.length].strip
info.push [ 'WVUNPACK ' + current_key, current_value ]
end

# wvunpack_stderr_str contains human-formatted info and errors
else
info.push [ 'WVUNPACK ERROR', wvunpack_stderr_str.strip!.split(/\r?\n|\r/).last ]
end
end

end
Empty file added lib/modules/cache.rb
Empty file.
22 changes: 17 additions & 5 deletions lib/modules/spectrogram.rb
Original file line number Diff line number Diff line change
@@ -1,24 +1,36 @@
require 'OS'

module Spectrogram
@sox_path = "./vendor/bin/sox/windows/sox.exe"
@sox_path = if OS.windows? then "./vendor/bin/sox/windows/sox.exe" else "sox" end
@sox_arguments_verbose = "-V"
@sox_arguments_output_audio = "-n"
@sox_arguments_sample_rate = "rate 22050"
@sox_arguments_spectrogram = "spectrogram -m -r -l -a -q 249 -w hann -y 257 -X 43.06640625 -z 100"
@sox_arguments_output = "-o"
@my_logger ||= Logger.new("#{Rails.root}/log/my.log")
def self.generate(source, destination)

# Generate a spectrogram image from an audio file.
# The spectrogram will be 257 pixels high, but the length is not known exactly beforehand.
# The spectrogram will be created for the entire file. Durations longer than 2 minutes are not recommended.
# Source is the audio file, target is the image file that will be created.
# An existing image file will not be overwritten.
def self.generate(source, target)

# check for existing image, and do not overwrite
if File.exist?(target)
return [ "", "", "", source, File.exist?(source), target, File.exist?(target) ]
end

# sox command to create a spectrogram from an audio file
command = "#{@sox_path} #{@sox_arguments_verbose} \"#{source}\" #{@sox_arguments_output_audio} #{@sox_arguments_sample_rate} #{@sox_arguments_spectrogram} #{@sox_arguments_output} \"#{destination}\""
command = "#{@sox_path} #{@sox_arguments_verbose} \"#{source}\" #{@sox_arguments_output_audio} #{@sox_arguments_sample_rate} #{@sox_arguments_spectrogram} #{@sox_arguments_output} \"#{target}\""

# run the command and wait for the result
stdout_str, stderr_str, status = Open3.capture3(command)

# log the command
@my_logger.debug(command)


# package up all the available information and return it
result = [ stdout_str, stderr_str, status, File.exist?(source), File.exist?(destination) ]
result = [ stdout_str, stderr_str, status, source, File.exist?(source), target, File.exist?(target) ]
end
end
File renamed without changes.

0 comments on commit a77eb33

Please sign in to comment.