音関連
こんな感じに定期的に音を採れるようにしてみた。parameter 部分は最初は不定値にして、上位から値を設定してみたもののなぜかちゃんと動かないので値をいれることにした。それの関係で桁の設定がかなりバラバラ。
ちょっと考えないと。あまりよく見てないが parameter は整数、小数、文字列(!)も入るってのが、ちょっと不思議。
module sound_recorder #( parameter kHz = 20, parameter CH = 1, parameter RECORD_NS = 1000_000, parameter FILENAME = "stream.memh" )( input signed [15:0] sound_r_or_mono, sound_l ); parameter ns = 1000000 / kHz; parameter SAMPLENUM = RECORD_NS / ns; reg [15:0] data [0:(SAMPLENUM * CH) - 1 + 2]; integer i; initial begin data[0] = kHz * 1000; data[1] = CH; for(i = 0; i < (SAMPLENUM * CH); i = i + CH) begin #ns data[i+2+0] = sound_r_or_mono; if(CH == 2) begin data[i+2+1] = sound_l; end end $writememh(FILENAME, data); $display("%t: %s dumped", $time, FILENAME); $stop; end endmodule
writememh で出力されたファイルを wav ファイルに変換する。簡単ね。
require 'wave.rb' begin f = File.open(ARGV.shift, 'r') sample = [] hz = nil ch = nil while t = f.gets t = t.chomp if(t =~ /\A[0-9a-fA-F]+\z/) v = t.to_i(0x10) & 0xffff if(hz == nil) hz = v elsif(ch == nil) ch = v p hz, ch else sample << v end elsif(t == 'xxxx') sample << 0 end end f.close wave_write(ARGV.shift, hz, ch, 2, sample) end
なんでこういうことをやってるかというと、テストベンチ毎に似たようなものを作ったり、周波数を 1 から割って、 10 の -何乗かを関数電卓で計算して、という不毛なことを割と繰り返してた verilog ソースと、似たようなものをコピペして書き捨てる ruby ソースも多かったので、さすがに汎用性があるものは require とか include とかしましょうよ、という基本的な話。
それをやってる自分が言うのもなんだが、他人の使い捨てではないソースでこういうのがあると、やはり完成度が低くやっつけで不親切で不安定というがよくあるので、戒め。