Skip to content

Instantly share code, notes, and snippets.

@loganrosen
Created December 6, 2010 23:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save loganrosen/731179 to your computer and use it in GitHub Desktop.
Save loganrosen/731179 to your computer and use it in GitHub Desktop.
Filter
require 'fileutils'
class String
def to_hex_i
hex_string = ''
self.each_byte do |b|
hex_string << ("%02x" % b.ord)
end
hex_string.hex
end
def self.fill(character, length)
fill_string = ''
length.times do
fill_string << character
end
fill_string
end
end
class Integer
def to_byte_s(bytes=2)
hex_string = "%0#{ bytes*2 }x" % self
byte_string = ''
(hex_string.length / 2).times do |i|
byte_string << hex_string[i*2, 2].hex.chr
end
byte_string
end
def to_unsigned(bits)
max_unsigned = 2**bits
if self < 0
return max_unsigned - self.abs
else
return self
end
end
def to_signed(bits)
mid = 2**(bits-1)
max_unsigned = 2**bits
if self >= mid
return self - max_unsigned
else
return self
end
end
def shift_to_mid(bits)
mid = 2**(bits-1)
return self - mid
end
def shift_to_zero(bits)
mid = 2**(bits-1)
return self + mid
end
end
class AudioFile < File
def initialize(file_path, permissions)
super(file_path, permissions)
end
protected
def get_bytes_big_endian(pos, len)
self.pos = pos
self.read(len)
end
def get_bytes_little_endian(pos, len)
self.pos = pos
self.read(len).reverse
end
def set_bytes_big_endian(pos, byte_string)
self.pos = pos
self.write(byte_string)
end
def set_bytes_little_endian(pos, byte_string)
self.pos = pos
self.write(byte_string.reverse)
end
end
class WavFile < AudioFile
attr_reader :format
attr_reader :numchannels
attr_reader :samplerate
attr_reader :duration
attr_reader :bitspersample
def initialize(file_path, permissions)
super(file_path, permissions)
@chunkid = get_bytes_big_endian(0, 4)
throw "Unrecognized chunkid '#{ @chunkid }', expected 'RIFF'" if @chunkid != "RIFF"
@chunksize = get_bytes_little_endian(4, 4).to_hex_i
@format = get_bytes_big_endian(8, 4)
throw "Unrecognized format '#{ @format }', expected 'WAVE'" if @format != "WAVE"
@subchunk1id = get_bytes_big_endian(12, 4)
throw "Unrecognized subchunk1id '#{ @subchunk1id }', expected 'fmt '" if @subchunk1id != "fmt "
@subchunk1size = get_bytes_little_endian(16, 4).to_hex_i
@compressioncode = get_bytes_little_endian(20, 2).to_hex_i
throw "Compressed Audio" if @compressioncode != 1
@numchannels = get_bytes_little_endian(22, 2).to_hex_i
@samplerate = get_bytes_little_endian(24, 4).to_hex_i
@byterate = get_bytes_little_endian(28, 4).to_hex_i
@bitspersample = get_bytes_little_endian(34, 2).to_hex_i
@subchunk2_offset = 20 + @subchunk1size
@subchunk2id = get_bytes_big_endian(@subchunk2_offset + 0, 4)
throw "Unrecognized subchunk2id '#{ @subchunk2id }', expected 'data'" if @subchunk2id != "data"
@subchunk2size = get_bytes_little_endian(@subchunk2_offset + 4, 4).to_hex_i
@data_offset = @subchunk2_offset + 8
@bytespersample = @bitspersample / 8
@sample_size = @bytespersample * @numchannels
@total_samples = (@subchunk2size.to_f / @sample_size.to_f).to_i
@duration = @totalsamples.to_f / @samplerate.to_f
@subchunkextra_offset = @data_offset + @subchunk2size
@subchunkextrasize = @chunksize - @subchunkextra_offset
end
def total_samples
@total_samples
end
def total_samples= (new_total_samples)
new_subchunk2size = new_total_samples*@sample_size
new_chunksize = 20 + @subchunk1size + 8 + new_subchunk2size + @subchunkextrasize
new_subchunkextra_offset = @data_offset + new_subchunk2size
subchunkextra = get_bytes_little_endian(@subchunkextra_offset, @subchunkextrasize)
if new_total_samples > @total_samples
number_of_silent_bytes = new_subchunkextra_offset - @subchunkextra_offset
silence_byte_character = (@bitspersample == 8 ? 0.shift_to_zero(@bitspersample) : 0).to_byte_s(@bytespersample)
set_bytes_little_endian(@subchunkextra_offset, String.fill(silence_byte_character, number_of_silent_bytes))
elsif new_total_samples < @total_samples
self.truncate(8 + new_chunksize)
else
return @total_samples
end
set_bytes_little_endian(new_subchunkextra_offset, subchunkextra)
set_bytes_little_endian(4, new_chunksize.to_byte_s(4))
set_bytes_little_endian(@subchunk2_offset + 4, new_subchunk2size.to_byte_s(4))
@subchunk2size = new_subchunk2size
@chunksize = new_chunksize
@subchunkextra_offset = @data_offset + @subchunk2size
@total_samples = (new_subchunk2size.to_f / @sample_size.to_f).to_i
end
def [](sample_number)
throw "Out of bounds" if sample_number >= @total_samples
channels = []
@numchannels.times do |channel_num|
offset = @data_offset + (sample_number*@sample_size) + @bytespersample*channel_num
data = get_bytes_little_endian(offset, @bytespersample).to_hex_i
channels << if @bitspersample == 8
data.shift_to_mid(@bitspersample)
else
data.to_signed(@bitspersample)
end
end
return channels
end
def []=(sample_number, channel_array)
throw "Out of bounds" if sample_number >= @total_samples
throw "Invalid channel array" if channel_array.class.to_s != 'Array' || channel_array.size != @numchannels
channel_array.each_with_index do |channel_data, channel_num|
offset = @data_offset + (sample_number*@sample_size) + @bytespersample*channel_num
data = if @bitspersample == 8
channel_data.shift_to_zero(@bitspersample).to_byte_s(@bytespersample)
else
channel_data.to_unsigned(@bitspersample).to_byte_s(@bytespersample)
end
set_bytes_little_endian(offset, data)
end
end
def each
@total_samples.times do |i|
yield self[i], i
end
end
def collect
@total_samples.times do |i|
self[i] = yield self[i], i
end
end
def clone(file_path, permissions)
FileUtils.cp self.path, file_path
WavFile.open(file_path, permissions)
end
end
require './audio_lib.rb'
#reverse an audio clip
rev = [].to_a
#WavFile.open('./bugs_mail.wav', "r+b") do |f|
# f.each do |element,i|
# rev << element
# end
#
# rev.reverse!
#
# f.collect do |element,i|
# rev[i]
# end
#end
#
#array = [].to_a
##halve the speed of an audio clip
#WavFile.open('./bugs_mail.wav', "r+b") do |f|
# f.each do |element,i|
# array << element
# n = 0
# while n<=i
# array.insert((2*n+1), array.at(2*n))
# n+1
# end
# end
#
# f.collect do |element,i|
# array[i]
# end
#end
#
###Set the pitch for an audio file
##x = gets.chomp
##WavFile.open('./bugs_mail.wav', "r+b") do |f|
## f.collect do |element, i|
## element = x
## end
##end
#"You're a bit pitchy..." -Randy
newarray = [].to_a
WavFile.open('./Censor Beep 1 Second.wav', "r+b") do |f|
f.each do |element, i|
newarray << element
end
max = 0
f.each do |element, i|
# blah = newarray.join
# puts blah[i]
if newarray.to_s[i].to_i>max
max = newarray.to_s[i].to_i
end
# end
end
end
if max>1
puts "That audio has a generally high pitch."
else
puts "That audio doesn't have a generally high pitch."
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment