wavファイル同士を重ねて合成する

音の合成は、波なので足すだけでいい。ただし16bitを越えてしまうので2で割るなりして音量を下げる必要がある。


base.wavを元として、sound.wavを1、3.3、8秒目に置いてresult.wavとして書き出す例。

ruby compositeWav.rb base.wav sound.wav 1 3.3 8 result.wav


compositeWav.rb
http://shokai.org/projects/ruby-wavfile/index.cgi/file/0971a11a4fd6/compositeWav.rb

#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
# wavを重ねる。重ねる場所は時間で指定できる
require 'WavFile'

if ARGV.size < 4
  puts 'ruby compositeWav.rb base.wav input1.wav 1 3 10 out.wav'
  puts 'put "input1.wav" on 1,3,10(sec)'
  exit 1
end

out_file = ARGV.pop
base_file = ARGV.shift
input_file =ARGV.shift
times = ARGV.map{|i|i.to_f}.uniq.sort

format1, chunks1 = WavFile::readAll open(base_file)
format2, chunks2 = WavFile::readAll open(input_file)

puts format1.to_s
if format1 != format2
  puts '!!formatが違うファイルが混ざっています!!'
  puts format2.to_s
  exit 1
end


bit = 's*' if format1.bitPerSample == 16 # int16_t
bit = 'c*' if format1.bitPerSample == 8 # signed char
wavs1 = chunks1[0].data.unpack(bit)
wavs2 = chunks2[0].data.unpack(bit)

times.each{|t|
  offset = format1.hz * t * format1.channel
  next if offset+wavs2.size > wavs1.size # 音がはみでる時
  print "#{t}(sec)..."
  for i in 0..wavs2.size-1 do
    wav1 = wavs1[i+offset]
    wav2 = wavs2[i] * 0.3 # 音量を下げる
    wavs1[i+offset] = ((wav1+wav2)/2).to_i
  end
  puts ''
}

chunks1[0].data = wavs1.pack(bit)

out = open(out_file, "w")
WavFile::write(out, format1, chunks1)
out.close