913102 ランダム
 HOME | DIARY | PROFILE 【フォローする】 【ログイン】

緑のボタンを押せ! Press the green button

PR

Category

Keyword Search

▼キーワード検索

Archives

2019.07
2019.06
2019.05
2019.04
2019.03

Comments

 Jun@ Re:「いっちゅう」さんのiEPG用ソフト入れてみた(09/15) TVdeIEPG Ver.1.2.1.0がリンク切れしてい…
 スター@ Re:hauppauge HD PVR 速報(08/25) スタービーチ <small> <a href="http://c…
 ASOBO@ Re:hauppauge HD PVR 速報 ASOBO攻略 <small> <a href="http:/…
 ハッピーメール@ Re:hauppauge HD PVR 速報 ハッピーメール <small> <a href="http:/…
 恋も遊びもイクヨクルヨ@ Re:hauppauge HD PVR 速報 イクヨクルヨ <small> <a href="http://f…

Freepage List

Favorite Blog

まだ登録されていません
2009.07.08
XML
テーマ:私のPC生活(6672)
カテゴリ:Digital Audio

すっかり「Ruby猿」になっている私です(笑)が、今度はデジタルオーディオを扱ってみることにします。とりあえず、WAVファイルを扱うところを書いてみました。WAVファイル(というかRIFFフォーマット)は、ここ
http://www.kk.iij4u.or.jp/~kondo/wave/
の記述が参考になります。思ったより、時間がかかりましたが、WAVファイルの読み書きはできました。pack(),unpack()の使い方のいい勉強になりました。 書き込みはとりあえず44.1k、16ビットで決めうちです。

 早速動かしてみます。WAVファイルをコピーしているだけですが、遅いっすね~。 orz
ちゃんとThread化すれば少しはましになるかしら?RubyのTheradって、Native Threadではないからダメかな・・・

----
require "thread"
module DigitalAudio 
  def bytes2value( ar )
      bytePerSample = ar.length
      bitPerSample = bytePerSample * 8
      sum = 0
      (bytePerSample -1).to_i.downto( 0 ) { |i|
        sum = (sum << 8 ) + ar[i]
      }
      if bytePerSample == 1
         return sum - 128
      end
      if sum > ( 0x1 << ( bitPerSample -1 ))
          sum -= ( 0x1 <<  bitPerSample )
      end
      sum
  end #def bytes2value( ar )
end #module DigitalAudio

class DigitalAudioElement
  include Math
  include DigitalAudio
  @@S48k = 48000
end #class DigitalAudioElement

class ToFile < DigitalAudioElement
  def initialize( fspec , inQArray , pHash=nil )
    f = open(fspec , "wb" )
    totalDataChunkByte = 0
    totalByte = totalDataChunkByte +36
    fomatId = 1 # must be 1 (=LPCM)
    noOfChannel = inQArray.length
    samplingRate = 44100 # tentative
    bitPerSample = 16 # tentative
    blockSize = noOfChannel *( bitPerSample /8 )
    bytePerSec = samplingRate * blockSize
    x = ["RIFF", totalByte, "WAVE" ]
    f.write( x.pack( "Z4VZ4"))
    x = [ "fmt ", 16, fomatId, noOfChannel, samplingRate, bytePerSec, blockSize, bitPerSample ]
    p x
    f.write( x.pack( "Z4VvvVVvv"))
    x = [ "data", totalDataChunkByte ]
    f.write( x.pack( "Z4V"))
    d = true
    while d
      for i in 0..(noOfChannel-1)
        lsbArray = Array.new
        d =  inQArray[i].pop
        #p __FILE__, __LINE__, d
        break if !d
        #p __FILE__, __LINE__, d
        d = d.to_i
        for j in 1..( bitPerSample /8 )
          lsbArray << (d & 0xff)
          d >>= 8
        end
        f.write( lsbArray.pack( "C*" ))
        #f.write( "XXXX" )
      end
      break if !d
      totalDataChunkByte += blockSize
    end
    f.seek( 0) # rewind to begin    
    totalByte = totalDataChunkByte +36
    x = ["RIFF", totalByte, "WAVE" ]
    f.write( x.pack( "Z4VZ4"))
    x = [ "fmt ", 16, fomatId, noOfChannel, samplingRate, bytePerSec, blockSize, bitPerSample ]
    p x
    f.write( x.pack( "Z4VvvVVvv"))
    x = [ "data", totalDataChunkByte ]
    f.write( x.pack( "Z4V"))
    f.close
  end #def initialize( fspec , outQ, pHash=nil )
end #class ToFile < DigitalAudioElement

class FromFile < DigitalAudioElement
  include DigitalAudio
  def initialize( fspec , outQ, pHash=nil )
    File::open( fspec ) { |f|
      f.binmode
      p "-----------------"
      if( !(buf = f.read(12 )))
        raise "File read error : #{fspec}"
      end
      riffHeader = buf.unpack("Z4VZ4")
      p riffHeader
      if !((riffHeader[0] == "RIFF") && (riffHeader[2] == "WAVE"))
        raise "File format error error : #{fspec}"
      end
     
      # parse 'chunk'
      while( buf = f.read(8) )
        chunkHeader = buf.unpack("Z4V")
        if chunkHeader[0] == "fmt "
          buf = f.read( chunkHeader[1])
          fmtChunk = buf.unpack("vvVVvvvc*")
        elsif chunkHeader[0] == "fact"
          buf = f.read( chunkHeader[1])
          factChunk = buf.unpack("c*")
        elsif chunkHeader[0] == "data"
          break
        else
          raise "unknown chunk type : #{chunkHeader[0]}"
        end
      end

      p fmtChunk, factChunk
      fomatId, noOfChannel, samplingRate, bytePerSec, blockSize, bitPerSample= fmtChunk[0..6]
      p fomatId, noOfChannel, samplingRate, bytePerSec, blockSize, bitPerSample
      if fomatId != 1
        raise "unknown data format. Only LPCM is supported"
      end
      bytePerSample = bitPerSample / 8
      count = chunkHeader[1] # total bytes in data chunk
      p "--datachunk--" ,count
      while( buf = f.read( blockSize ) )
        d = buf.unpack( "C*" )
        for ch in 0..(noOfChannel -1)
          val = bytes2value( d[0..(bytePerSample-1)])
          outQ[ch].push( val )
          d = d[bytePerSample..-1]
        end
        for ch in noOfChannel..( outQ.length() -1)
          outQ[ch].push( 0 )
        end
        count -= blockSize
        break if count <= 0
      end
      for ch in 0..( outQ.length() -1)
          outQ[ch].push( nil )
      end
    }
    p "----Done"
  end #def initialize( fspec , outQ, pHash=nil )
end # class FromFile < DigitalAudioElement

#-------- test
 w1 = Queue.new
 w2 = Queue.new
 w3 = Queue.new
 w4 = Queue.new
 fm = FromFile.new( "WAVE.WAV", [w1, w2 ] )
 fm1 = ToFile.new( "aaa.WAV", [w1, w2] )
# fm2 = FromFile.new( "aaa.WAV", [w3, w4] )
 exit







Last updated  2009.07.08 06:02:57
コメント(0) | コメントを書く
[Digital Audio] カテゴリの最新記事

Copyright (c) 1997-2019 Rakuten, Inc. All Rights Reserved.