2009-05-17 76 views
4

wavファイルの各単語の間に完全な無音があります(私はHexワークショップでチェックし、無音は0で表しています)。Pythonを使ってwavファイルを編集する

ノンサイレンスサウンドをカットするにはどうしたらいいですか?

私はPythonを使用してプログラミングしています。

ありがとうございます!

+0

質問を少し明確にすることを検討する必要があります。私はあなたが沈黙を取り除こうとしているのか、実際にはオーディオを別々のチャンクに分割しようとしているのかを知りたいですか? – Soviut

答えて

1

私はこの経験はありませんが、標準ライブラリにあるwaveモジュールを見てください。それはあなたが望むことをするかもしれない。それ以外の場合は、0バイトのシーケンスを切り取ってバイトストリームとしてファイルを読み取る必要があります(ファイルを無効にするので、0バイトをすべて切り捨てることはできません)...

1

コマンドラインのサウンド処理ツールであるsoxを試してみてください。それは多くのモードがあり、そのうちの1つはsilence

です。silence:サウンドファイルの先頭、途中、または終わりから無音を削除します。無音は指定されたしきい値以下です。

これは複数のサウンドフォーマットをサポートしていますが、非常に高速です。したがって、大きなファイルを解析することは問題ではありません。

ファイルの途中から無音を削除するには、陰性のbelow_periodsを指定します。この値は正の値として扱われ、above_periodsで指定された処理を再開する必要があることを示すためにも使用され、サウンドファイルの途中で無音期間を削除するのに適しています。

でも、私はlibsoxのための任意のPythonの建物を発見していない、しかし、あなたはPythonで、すべてのコマンドラインプログラムを使用するとあなたはそれを使用することができます(またはあなたがそれを書き換えることができます - その後、指導のためのSOXのソースを使用)。

+0

http://pypi.python.org/pypi/pysox – endolith

15

Pythonにはwav moduleがあります。これを使って読み込み用のwavファイルを開き、 `getframes(1) 'コマンドを使ってフレームごとにファイルを調べることができます。

import wave 
w = wave.open('beeps.wav', 'r') 
for i in range(): 
frame = w.readframes(1) 

戻されるフレームは、16進値の入ったバイト文字列になります。ファイルがステレオである場合、結果はこのような何か(4バイト)になります。そのモノ場合

'\xe2\xff\xe2\xff' 

を、それが半分のデータ(2バイト)を持つことになります。

'\xe2\xff' 

各チャネルは2でありますオーディオは16ビットなのでバイト長です。 Ifが8ビットの場合、各チャネルは1バイトのみになります。これを確認するにはgetsampwidth()メソッドを使用できます。また、getchannels()は、モノラルかステレオかを判断します。

これらのバイトをループして、すべてがゼロに等しいかどうかを調べることができます。つまり、両方のチャネルがサイレントであることを意味します。次の例では、ord()関数を使用して、16進数の値を整数に変換します('\xe2')。

import wave 
w = wave.open('beeps.wav', 'r') 
for i in range(w.getnframes()): 
    ### read 1 frame and the position will updated ### 
    frame = w.readframes(1) 

    all_zero = True 
    for j in range(len(frame)): 
     # check if amplitude is greater than 0 
     if ord(frame[j]) > 0: 
      all_zero = False 
      break 

    if all_zero: 
     # perform your cut here 
     print 'silence found at frame %s' % w.tell() 
     print 'silence found at second %s' % (w.tell()/w..getframerate()) 

これは振幅が0のマーク通常の周波数を横切ることができるので、無音の単一フレームは、必ずしも空の空間を意味しないことは注目に値します。したがって、領域が実際には無音であるかどうかを判断する前に、0で特定の数のフレームを観察することをお勧めします。

+1

0を超えると純粋な正弦波で\ 0バイトが発生する可能性があります。私が何を意味するかを見るために、11025Hzの正弦波上に44100Hzのサンプリングされたファイルを想像してみてください。答えの残りがとても良いので、私は-1ではありません。 –

+1

readframes(i)は、位置iの1フレームではなく、iフレームを順番に返します。したがって、ループは1フレーム、2フレーム、3フレームなどを返します。これはreadframes(1)でなくreadframes(i)でなければなりません。 – gravitron

+1

固定しましたが、私はあなたの言葉をこれに服用しています。 – Soviut

1

あなたがそれらをカットする前に、連続するゼロの最小数のいくつかのしきい値を考え出す必要があります。それ以外の場合は、通常のオーディオデータの真中から完全に有効なゼロを削除します。ウェーブファイルを反復し、ゼロ以外の値をコピーし、ゼロ値をバッファリングすることができます。ゼロをバッファリングしていて、次のゼロ以外の値を見つけると、バッファにしきい値よりも少ないサンプルがある場合はそれらをコピーし、それ以外の場合は破棄します。

しかし、Pythonはこの種のタスクにとって素晴らしいツールではありません。 :(

4

も参照して、沈黙を決定するための、すなわち方法が正しくありません。 "より正確" な実装は次のようになります。

import struct 
import wave 

wave_file = wave.open("sound_file.wav", "r") 

for i in range(wave_file.getnframes()): 
    # read a single frame and advance to next frame 
    current_frame = wave_file.readframes(1) 

    # check for silence 
    silent = True 
    # wave frame samples are stored in little endian** 
    # this example works for a single channel 16-bit per sample encoding 
    unpacked_signed_value = struct.unpack("<h", current_frame) # * 
    if abs(unpacked_signed_value[0]) > 500: 
     silent = False 

    if silent: 
     print "Frame %s is silent." % wave_file.tell() 
    else 
     print "Frame %s is not silent." % wave_file.tell() 

参考文献とリンク集

* Struct Unpackingはここに有用であろう:https://docs.python.org/2/library/struct.html

**私は異なるサイズのビット符号化し、複数のチャネルを扱うためウェーブファイルのフォーマットを説明見出さ良い基準である:最初にPythonで内蔵ORD()関数を使用してhttp://www.piclist.com/techref/io/serial/midi/wave.html

readframes(x)メソッドによって返された文字列オブジェクトの要素は正しく動作しません。

もう1つの重要な点は、複数チャネルのオーディオがインターリーブされているため、チャネルを処理するために少し余分なロジックが必要であることです。繰り返しになりますが、上記のリンクはこれについて詳しく説明しています。

これは今後のお役に立てば幸いです。

ここでは、リンクからの重要な点のいくつかと、私が助けてくれたことを紹介します。

データ構成


すべてのデータは、インテル80X86(すなわち、リトルエンディアン)形式で配置され、8ビット・バイトに格納されます。複数バイト値のバイトは、下位(すなわち、最下位バイト)のバイトが最初に格納されます。次のようにデータ・ビット(すなわち、上部のビット数で示す)である:それぞれの(例えば、ステレオ波形)マルチチャンネルサウンド、単一のサンプル点について

  7 6 5 4 3 2 1 0 
     +-----------------------+ 
char: | lsb    msb | 
     +-----------------------+ 

     7 6 5 4 3 2 1 0 15 14 13 12 11 10 9 8 
     +-----------------------+-----------------------+ 
short: | lsb  byte 0  |  byte 1  msb | 
     +-----------------------+-----------------------+ 

     7 6 5 4 3 2 1 0 15 14 13 12 11 10 9 8 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24 
     +-----------------------+-----------------------+-----------------------+-----------------------+ 
long: | lsb  byte 0  |  byte 1   |   byte 2  |  byte 3  msb | 
     +-----------------------+-----------------------+-----------------------+-----------------------+ 

インタリーブ


チャネルがインターリーブされます。例えば、ステレオ(すなわち、2チャンネル)の波形を仮定する。最初に左チャンネルのサンプルポイントをすべて保存し、次に右チャンネルのサンプルポイントをすべて保存する代わりに、2つのチャンネルのサンプルポイントを一緒にミックスします。左チャンネルの最初のサンプルポイントを保存します。次に、右チャンネルの最初のサンプルポイントを保存します。次に、左チャンネルの2番目のサンプルポイントを保存します。次に、右側のチャンネルの2番目のサンプルポイントを保存し、その後、各チャンネルの次のサンプルポイントを交互に保存します。これはインターリーブされたデータの意味です。各チャンネルの次のサンプルポイントを順番に保存し、同時に再生する(つまり、DACに送信する)サンプルポイントを連続して保存します。

関連する問題