From: Bill Kelly Date: 2003-11-09T01:07:13+09:00 Subject: Re: process .wav file? Hi, From: "mike re-v" > > Sorry I should have specified linux platform > I've looked at the RAA several keywd searches > like 1.) sound i/o > 2)i/o sound linux > 3).wav > I don't see anything relative. Not sure if this will be of any help, but I wrote some code awhile back to parse WAV files and read/write the format chunk (sample rate, etc.) and extract the audio samples from the WAV... (Doesn't play the sound, tho!) For what it's worth I'll attach the code below... Regards, Bill ~~ wavtweak.rb ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # WAV format info at: http://www.borg.com/~jglatt/tech/wave.htm # class NotRIFFFormat < StandardError; end class NotWAVEFormat < StandardError; end def read_chunk_header(file) hdr = file.read(8) chunkName, chunkLen = hdr.unpack("A4V") end def parse_wav(file) riff, riffLen = read_chunk_header(file) raise NotRIFFFormat unless riff == 'RIFF' riffEnd = file.tell + riffLen wave = file.read(4) raise NotWAVEFormat unless wave == 'WAVE' while file.tell < riffEnd chunkName, chunkLen = read_chunk_header(file) fpos = file.tell yield file, chunkName, chunkLen if block_given? file.seek(fpos + chunkLen) end end class WaveFmtChunk # short AudioFormat; PCM = 1 (i.e. Linear quantization) # Values other than 1 indicate some # form of compression. # unsigned short NumChannels; Mono = 1, Stereo = 2, etc. # unsigned long SampleRate; 8000, 44100, etc. # unsigned long ByteRate; == SampleRate * NumChannels * BitsPerSample/8 # unsigned short BlockAlign; == NumChannels * BitsPerSample/8 # The number of bytes for one sample including # all channels. # unsigned short BitsPerSample; 8 bits = 8, 16 bits = 16, etc. attr_reader :audioFormat, :numChannels, :sampleRate, :byteRate, :blockAlign, :bitsPerSample PACK_FMT = "vvVVvv" def initialize(binRepr) @audioFormat, @numChannels, @sampleRate, @byteRate, @blockAlign, @bitsPerSample = binRepr.unpack(PACK_FMT) end def to_s [ @audioFormat, @numChannels, @sampleRate, @byteRate, @blockAlign, @bitsPerSample ].pack(PACK_FMT) end def set_sample_rate(rate) @byteRate = calc_byte_rate(rate) @sampleRate = rate end def calc_byte_rate(srate, numch = @numChannels, bitss = @bitsPerSample) srate * numch * (bitss / 8) end end def handle_fmt_chunk(file, chunkLen) fmtDatPos = file.tell fmt = WaveFmtChunk.new(file.read(chunkLen)) print "srate is #{fmt.sampleRate} brate is #{fmt.byteRate}\n" # Tweak the sample rate (without resampling the data) # # fmt.set_sample_rate(45750) # (52245) # print "srate now #{fmt.sampleRate} brate now #{fmt.byteRate}\n" # fs = fmt.to_s # print "writing new fmt data, len #{fs.length} bytes " # fs.each_byte {|c| printf("%02x", c) } # print "\n" # file.seek(fmtDatPos) # print "cur file ofst #{file.tell}\n" # file.write(fmt) # print "post write file ofst #{file.tell}\n" end def handle_data_chunk(file, chunkLen) data = file.read(chunkLen) end ARGV.each do |fname| puts "#{fname}" File.open(fname, File::RDWR) do |f| f.binmode f.seek(0) parse_wav(f) do |file, chunkName, chunkLen| puts "'#{chunkName}' size #{chunkLen}" case chunkName when 'fmt' then handle_fmt_chunk(file, chunkLen) when 'data' then handle_data_chunk(file, chunkLen) end end end end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~