アーカイブ
wavファイルをRubyで編集する
Rubyでwavファイルのフォーマットを読んだり、データチャンクを編集するためのgemを作った。
ベースは以前作ったやつで、ついでにwavファイル操作のサンプルをたくさん追加してrubygems.orgに登録しておいた。
あくまでサーバーで音を合成して返すようなwebサービスで使う事を想定している物で、マイクからの入力をリアルタイムに音声処理するための物ではない。
■インストール
gem install wav-file
■使う
フォーマットとデータチャンクを読む
require 'rubygems'
require 'wav-file'
f = open("input.wav")
format = WavFile::readFormat(f)
dataChunk = WavFile::readDataChunk(f)
f.close
puts format
するとこんな感じにフォーマットが取れる。
Format ID: 1
Channels: 2
Sampling Ratio: 48000 (Hz)
Byte per Sec: 192000
Bit per Sample: 16
Block Size: 4
バイナリからwavの波形を配列として取り出す
bit = 's*' if format.bitPerSample == 16 # int16_t
bit = 'c*' if format.bitPerSample == 8 # signed char
wavs = dataChunk.data.unpack(bit) # read binary
音量を半分にしてみる
wavs = wavs.map{|w| w/2}
逆再生にして、バイナリに戻す
dataChunk.data = wavs.reverse.pack(bit) # reverse
wavファイルに保存する
open("output.wav", "w"){|out|
WavFile::write(out, format, [dataChunk])
}
samplesディレクトリの中に色々と例を入れておいた。githubからも見れる。
- 音量が小さいのを大きくする
- 左右チャンネルを分けて保存する
- wavファイル同士を連結する
- wavファイル同士を重ねて同時に鳴らす
- 再生速度を上げる
- 波形をグラフにする
■tips
使う前にwavファイルのフォーマットについて理解しておいた方が良いかもしれない。
wav ファイルフォーマットが参考になる。
あと、複数のwavファイルを合成して新しいファイルを作る場合、操作する前にffmpegでformatを揃えた方が良い。その方が楽だし高速。
adjust_wav_format.rbにやり方を書いておいた。
サンプルを実行するのに必要なwavも、ffmpegでmp3とかから変換して作れる。
ffmpeg -i input.mp3 -ac 2 -ar 44100 output.wav
wavファイルの音量を調整する
音量の小さいwavファイルのボリュームを上げる。上げすぎて音割れしないようにする。
前に作ったWavFile.rbを使ったら簡単にできた
16ビットwavは+-32768、8ビットwavは+-128の範囲の配列で波形が表現されている。
ソースのwavの波形を配列に取り出して、その中で最大の値を取りだし、全体を何倍すれば+-32768の間になるかの倍率を計算して全部かけ算すれば音量を調整できる。
maximizeVolume.rb
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
# wavの音量を最大に調節する
require File.dirname(__FILE__) + '/WavFile'
if ARGV.size < 2
puts 'ruby maximizeVolume.rb input.wav output.wav'
exit 1
end
in_file = ARGV.shift
out_file = ARGV.shift
format, data = WavFile::read open(in_file)
puts format.to_s
bit = 's*' if format.bitPerSample == 16 # int16_t
bit = 'c*' if format.bitPerSample == 8 # signed char
wavs = data.data.unpack(bit)
puts "このwav中の最大音量: #{wavs.max}"
volume_ratio = 32768/wavs.max.to_f if format.bitPerSample == 16
volume_ratio = 128/wavs.max.to_f if format.bitPerSample == 8
puts "補正倍率: #{volume_ratio}"
wavs_fixed = wavs.map{|w|
(w*volume_ratio).to_i
}
puts "補正されたwav中の最大音量: #{wavs_fixed.max}"
data.data = wavs_fixed.pack(bit)
open(out_file, "w"){|out|
WavFile::write(out, format, [data])
}
使う
ruby maximizeVolume.rb input.wav out.wav
約24倍されてout.wavに保存された
フォーマットID: 1
チャンネル数: 1
サンプリングレート: 44100 (Hz)
byte per sec: 88200
bit per sample: 16
ブロックサイズ: 2
このwav中の最大音量: 1335
補正倍率: 24.5453183520599
補正されたwav中の最大音量: 32768
Rubyでwavファイルをいじる WavFile.rbを作った
gemにしました → 橋本商会 wavファイルをRubyで編集する
*****
Rubyでwavファイルを操作するためにWavFile.rbを作った。スピーカから音を鳴らすのではなくて、wavファイルそのものをいじって合成したりつなげたり、逆再生や左右反転させたりした後ファイルに書き出す為に作った。
packやunpackを使ってRubyでバイナリを読み書きする部分でかなり苦戦したけど、WAVファイル – MoonRock@MoonRock/A mere diary (2002-2)(7年も前に同じような事やってる!)がすごく参考になった。attr_accessorとかも知らなかったから勉強になった。
http://shokai.org/projects/ruby-wavfile/にサンプルを色々置いておく。
例えば、逆再生のwavファイルを作るコードはこう書ける
reverseWav.rb
#!/usr/bin/env ruby波形部分をRubyの配列として取り出して処理する。ファイルに戻す部分はWavFile.rbがやってくれるようにした。
# -*- coding: utf-8 -*-
# wavファイルを逆再生にして保存する
# ステレオの場合、左右チャンネルが入れ替わってしまうがまあいい
require File.dirname(__FILE__) + '/WavFile'
if ARGV.size < 2
puts 'ruby reverseWav.rb input.rb output.wav'
exit 1
end
f = open(ARGV.shift)
format, chunks = WavFile::readAll(f)
f.close
puts format.to_s
dataChunk = nil
chunks.each{|c|
puts "#{c.name} #{c.size}"
dataChunk = c if c.name == 'data' # 波形の入っているchunkを探す
}
if dataChunk == nil
puts 'no data chunk'
exit 1
end
# 波形をいじる
bit = 's*' if format.bitPerSample == 16 # int16_t
bit = 'c*' if format.bitPerSample == 8 # signed char
wavs = dataChunk.data.unpack(bit) # 16bit or 8bitずつbinaryから読み出し
dataChunk.data = wavs.reverse.pack(bit) # 逆再生、binaryに戻す
open(ARGV.shift, "w"){|out|
WavFile::write(out, format, [dataChunk])
}
実行
ruby reverseWav.rb test.wav reverse.wav結果
フォーマットID: 1
チャンネル数: 1
サンプリングレート: 8000 (Hz)
byte per sec: 16000
bit per sample: 16
ブロックサイズ: 2
data 4077172
主にできる事と、処理の手順はこんな感じ
- wavファイルのファイルヘッダ、フォーマットチャンク、データチャンクをメモリに読み込む。WavFile.rbではファイルヘッダとフォーマットチャンクをまとめて管理するためにWavFile::Formatクラスを作ってある。
- データチャンクを波形として扱う処理は時前でやってください。ステレオ・モノラルやbpsなどのフォーマットが全て読み込まれているのでそんなに大変ではないはず。format.bitPerSampleやunpackを使う。ただしCPUのエンディアンが違うとおかしくなるかも。
- 最後にいじったデータチャンクをpackでバイト列に戻して、ファイルヘッダと合わせてwavファイルに戻す。
上の例ではWavFile::readAllを使ってフォーマットと全チャンクを読み込んでいるけど、wavファイルにはデータチャンク(波形)以外のチャンクもある。でもデータチャンクとフォーマットさえあれば後は必要ない場合が多いので、フォーマットとデータチャンクのみを取り出す関数も用意してある。
require 'WavFile'
File.open("test.wav"){|file|
format = WavFile::readFormat(file)
dataChunk = WavFile::readDataChunk(file)
}
タプルを使ってこう受け取る事もできる
format, dataChunk = WavFile::read(file)
wavファイルへ保存
open("out.wav"){|out|
WavFile.write(out, format, [dataChunk])
}
他にも色々やった。下にいくほど新しい。
上の方はWavFile.rbのバージョンが古い頃の物なので読み書きまわりが少し違うかもしれないが、解説が書いてあるので列挙しておく。最新のWavFile.rbで動くコードはリポジトリに置いておく
- wavファイルのヘッダを読み込む
- wavファイルのフォーマットを読み込む
- wavファイルのフォーマットを書き換えて倍速再生にする
- wavファイルを複数つなげる
- 逆再生するwavを作る
- wavファイルを左チャンネルのみ、右チャンネルのみにする
- wavファイルの波形を見てみる
- wavファイル同士を重ねて合成する
- wavファイルのdata chunkを取り出す
wavファイルの扱いについては、C言語で書かれたこの本を参考にした。この本ではファイルを先頭からseekして逐次処理して結果をwavファイルとして書き込んでいる。
でもwavファイルなんて数百MB程度だから、WavFile.rbではメモリ上で処理した方が後々便利そうだから今回は富豪的に全部メモリに読み込むようにした。
カットシステム
売り上げランキング: 160207

C言語初心者向けでわかりやすいが本格的な音響処理はいまいち
分かりやすいが…
あまり見かけないジャンルの本ですね作ってる時に大変だったのは音を出さないとデバッグできないので電車の中で作業するためにイヤホンは必須。
バイナリとRubyのオブジェクトとのやりとりの部分は音で聞いてもなんだかわからない時もあるので、putsで波形を数字としてdumpしてエクセルで描画すると原因がすぐわかる。
ML115 + Ubuntu9.10 64bit環境で音を出す
元サーバーマシンを、開発用のデスクトップマシンにした。
Windowsをインストールするとすんなりいくらしいんだけど、64bit版Ubuntuで音を出そうとすると大変だった。
PCIスロットが3.3V用で、5V用のサウンドカードだと切り欠きが合わなくて刺さらない。そして刺さっても64bitでのまともなサウンドドライバが無くて音がホワイトノイズだらけになる。
このUSBスピーカーを刺して他のサウンドデバイスを刺さないようにすれば音が出る。音質はたぶんそんなに良くないけど。
売り上げランキング: 798

ちょっと不便。
安いし簡単
値段以上の価値はあります
音は及第点(値段の割には)
価格以上の音質他にも、Creative Sound Blaster 5.1 VXを使うと音が全部ホワイトノイズになってしまうが、
alsamixer -Dpulseで音量をギリギリまで絞ると一応聞こえなくもなかった。
alsamixer -Dhw
参考:[ubuntu-jp:1749] Jaunty において Creative Sound Blaster 5.1 VX 上で再生する音声が全てホワイトノイズに
あとはAppleのMac用の小さいキーボードと、Microsoftの光学式マウスの安い奴を使ってる。
PCなしで、moxaで音を出す
xtel technical information > learning> Sound Writeより
moxaとスピーカを直結させて、soundWrite(ピン番号, 周波数)関数を使うと音が出せる
センサと組み合わせるとインタラクティブに音階を変えられる。CdSという明度センサを使っている




最近のコメント