Created
December 6, 2010 23:12
-
-
Save loganrosen/731179 to your computer and use it in GitHub Desktop.
Filter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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