ある程度雑でいいから、マイコンでリズム検知できたらいいなぁ。と思いつつ。
実験。曲によってはビート取り出せる。
とりあえずsoxコマンドで10kHzサンプリングにかえてから
sox input.mp3 -t raw -B -e floating-point -b 32 -c 1 -r 10000 input.raw
以下のソフトに通す。
やってる事は以下の通り
- 10このバンドパスフィルタで各周波数帯ごとのエネルギーを取得
- 各バンドのエネルギーを掛け合わせる (打楽器系は全周波数帯域にエネルギーが出る)
- 積をとったエネルギーの変動具合を、ローパスフィルタとの差分で見る。
#!/usr/local/bin/ruby
# -*- coding: utf-8 -*-
class LPF #ローパスフィルタ
def initialize
@rate=0.99
@outValue=0.0
end
def put(v)
@outValue=(1.0-@rate)*v+@rate*@outValue;
return @outValue
end
end
class BPF #バンドパスフィルタ
def initialize
@inValue=[0.0,0.0]
@outValue=[0.0,0.0]
end
def set(p,c) #ピーク周波数と、フィルタが抽出バンド幅をを指定
@b1=2.0*c*Math::cos(Math::PI*p);
@b2=-c*c
end
def put(v)
o=v - @inValue[1];
o+=@b1*@outValue[0] + @b2*@outValue[1];
@inValue.unshift(v)
@inValue.pop
@outValue.unshift(o)
@outValue.pop
return o;
end
end
data=$stdin.read().unpack("g*")
bpf=Array.new
lpf=Array.new
llpf=LPF.new
lllpf=LPF.new
16.times do |i|
p=1.0/16*i
bpf.push(BPF.new)
bpf[-1].set(p,0.95)
lpf.push(LPF.new)
end
data.each do |d|
dd=Array.new
bpf.size.times do |i|
#各バンドのエネルギーにローパスをかけてdd配列にいれる
dd.push( lpf[i].put(bpf[i].put(d)**2))
end
sum=1.0
dd.each do |v|
sum*=v
end
sum=sum ** (1.0/dd.size())
dd.unshift(sum)
lsum = llpf.put(sum)
v= lsum-lllpf.put(lsum)
puts v
end
話の前後を知らないで書き込んですみません。
返信削除めちゃくちゃ昔ですが、普通の?アナログフィルタ、これの出力をVACだかにぶちこんでリズムを切り刻む、なんてのを読んだ事があります。
まつたけひできだったかなー。
サンレコでマドンナ?のプロデューサとかもリズムを変態的に刻むために。
ああ、フィルターの出力をコンプ制御にぶちこむとさらに面白いリズムメイクが出来たとか読んだような。
まあアナログ時代の技ですねぇ。失礼しました。