サイン波を発振しよう
今日みたいな、こんな日はお洒落にサイン波を
発信したくなりませんか?
以下、URLのC言語をRubyでトレースしてみました。
(少々変更してます)
まずは音を出してみよう
http://homepage3.nifty.com/rio_i/lab/oss/002sound.htm
実行結果としては、
Hello, worldよろしく、440Hzのサイン波を再生するんですが
コードの内容は簡単で以下の事をしています。
ここまでできたら、サイン波をノコギリ波や矩形波にしてみたりして遊べますな。
そうそう、サイン波っていうのはポーという音です。ポー。
require 'soundcard.rb' include SoundCard sec = 1 #1sec freq = 440 #440Hz fs = 44100 #44100 gain = 32767 #16bit class Array def playable self.collect { |d| raise if d > 32767 || d < -32768 d = 65536 + d if d < 0 [ d & 0xff , d >> 8 ] }.flatten!.collect { |d| [d].pack('c') }.join end end class IO def w_ctl(arg,data) self.ioctl( arg,[data].pack('V') ) end def r_ctl(arg) ret = '' self.ioctl(arg,ret) ret.unpack('V') end end buf = Array.new(fs*sec) { |t| (gain * Math.sin(Math::PI* 2 * freq / fs * t) + 0.5).to_i } # plot buf[0..100] # if you want open('/dev/dsp','w') { |fd| fd.w_ctl( Param[:SOUND_PCM_SETFMT] , Param[:AFMT_S16_LE] ) puts "fmts = #{ fd.r_ctl( Param[:SOUND_PCM_GETFMTS] ) } " fd.w_ctl( Param[:SOUND_PCM_WRITE_CHANNELS],1) puts "channels = #{ fd.r_ctl( Param[:SOUND_PCM_READ_CHANNELS]) } " fd.w_ctl( Param[:SOUND_PCM_WRITE_RATE],fs) puts "rate = #{ fd.r_ctl( Param[:SOUND_PCM_READ_RATE]) } " fd.write( buf.playable ) }
上記ファイルでのSoundCard.rbは以前、生成したファイルです。
以下のようになっています。
module SoundCard Param = { :SOUND_PCM_READ_RATE => 0x80045002, :SOUND_PCM_READ_CHANNELS => 0x80045006, :SOUND_PCM_READ_BITS => 0x80045005, :SNDCTL_DSP_GETBLKSIZE => 0xc0045004, :SNDCTL_DSP_SETFRAGMENT => 0xc004500a, :SOUND_PCM_GETFMTS => 0x8004500b, :AFMT_MU_LAW => 0x1, :AFMT_A_LAW => 0x2, :AFMT_U8 => 0x8, :AFMT_S8 => 0x40, :AFMT_S16_LE => 0x10, :AFMT_S16_BE => 0x20, :AFMT_U16_LE => 0x80, :AFMT_U16_BE => 0x100, :SOUND_PCM_SETFMT => 0xc0045005, :SOUND_PCM_WRITE_CHANNELS => 0xc0045006, :SOUND_PCM_WRITE_RATE => 0xc0045002, } end