2016-04-05 7 views
2

サウンドトーンサウンドクリップを連結して作成されたオーディオの "ポップ"と "クリック"サウンドを削除するにはどうすればよいですか?PyAudioの連結されたサウンドデータからポップを削除するには

私は一連のトーンを生成するため、このPyAudioコードがあります。

import time 
import math 
import pyaudio 

class Beeper(object): 

    def __init__(self, **kwargs): 
     self.bitrate = kwargs.pop('bitrate', 16000) 
     self.channels = kwargs.pop('channels', 1) 
     self._p = pyaudio.PyAudio() 
     self.stream = self._p.open(
      format = self._p.get_format_from_width(1), 
      channels = self.channels, 
      rate = self.bitrate, 
      output = True, 
     ) 
     self._queue = [] 

    def __enter__(self): 
     return self 

    def __exit__(self, exc_type, exc_val, exc_tb): 
     self.stream.stop_stream() 
     self.stream.close() 

    def tone(self, frequency, length=1000, play=False, **kwargs): 

     number_of_frames = int(self.bitrate * length/1000.) 

     ##TODO:fix pops? 
     g = get_generator() 
     for x in xrange(number_of_frames): 
      self._queue.append(chr(int(math.sin(x/((self.bitrate/float(frequency))/math.pi))*127+128))) 

    def play(self): 
     sound = ''.join(self._queue) 
     self.stream.write(sound) 
     time.sleep(0.1) 

with Beeper(bitrate=88000, channels=2) as beeper: 
    i = 0 
    for f in xrange(1000, 800-1, int(round(-25/2.))): 
     i += 1 
     length = log(i+1) * 250/2./2. 
     beeper.tone(frequency=f, length=length) 
    beeper.play() 

が、色調の変化は、独特の「ポップ」は、オーディオであります、と私はそれを削除するかどうかはわかりません。

最初は、各クリップをただちに再生していたためにポップが発生していると思っていました。クリップを生成したときの各再生の時間は、オーディオをフラットラインにするのに十分な遅延でした。しかし、すべてのクリップを1つのストリングに連結して再生したところ、ポップはまだそこに残っていました。

次に、正弦波が各クリップの境界で一致しないと思ったので、現在のオーディオクリップの最初のNフレームを前のクリップの最後のNフレームで平均化しようとしましたが、何の効果もありませんでした。

私は間違っていますか?これをどうやって解決するのですか?

+0

は、あなたがまだ波形を見たことがありますか? –

+0

ここに推測..おそらくシンプルで単一のビープ音を分離してください。サウンドのようなアンプがオン/オフしています。また、88000はビープ音のビットレートが高いように見えました。これはチャープですか?ビットレートで符号化された電圧振幅で、周波数帯域幅は忠実度のためのものです。 – wbg

答えて

0

さまざまな属性のクリップを連結している場合、連結点の2つのクリップのピークが揃っていないと、クリック音が聞こえることがあります。

これを回避する1つの方法は、最初の信号の最後にFade-outを実行し、次に2番目の信号の最初にfade-inを実行することです。残りの連結プロセスを通じてこのパターンを継続します。 Fadingの詳細はCheck hereをご覧ください。

私は、Audacityのようなビジュアルツールで連結したものを試して、あなたが参加し、タイミングと望ましい結果を得るために設定をいじっするクリップにFade-outfade-inをしようとするだろう。

次に、pyAudioには簡単な実装方法があります。fadingですが、できる場合はpyDubを試してみるとよいでしょう。オーディオを操作する簡単な方法を提供します。 Fade-inFade-outの両方の方法とcross-fadeの方法があり、基本的に1つのステップでフェードインとフェードアウトの両方を実行します。あなたが本当にプロ級でクリアノイズ/ポップを取得したい場合

from pydub import AudioSegment 
from pydub.playback import play 

#Load first audio segment 
audio1 = AudioSegment.from_wav("SineWave_440Hz.wav") 

#Load second audio segment 
audio2 = AudioSegment.from_wav("SineWave_150Hz.wav") 

# 1.5 second crossfade 
combinedAudio= audio1.append(audio2, crossfade=1500) 

#Play combined Audio 
play(combinedAudio) 

最後に、あなたがしたいことがあります。pyDubのためのサンプルコードがあるpydubここ

pip install pydubとして

あなたはインストールすることができますPSOLAPitch Synchronous Overlap and Add)をご覧ください。 ここでは、オーディオ信号をfrequency domainに変換し、可能な限り最小限のノイズでオーディオをマージするようにチャンクでPSOLAを実行します。

これは長かったですが、助けてくれることを願っています。

1

個々の波形が整列していないという私の最初の疑念は正しいです。私はAudacityで検査して確認しました。私の解決策は、正弦波のピークで各波形を開始および停止するようにコードを修正することでした。

def tone(self, frequency, length=1000, play=False, **kwargs): 

    number_of_frames = int(self.bitrate * length/1000.) 

    record = False 
    x = 0 
    y = 0 
    while 1: 
     x += 1 
     v = math.sin(x/((self.bitrate/float(frequency))/math.pi)) 

     # Find where the sin tip starts. 
     if round(v, 3) == +1: 
      record = True 

     if record: 
      self._queue.append(chr(int(v*127+128))) 
      y += 1 
      if y > number_of_frames and round(v, 3) == +1: 
       # Always end on the high tip of the sin wave to clips align. 
       break 
2

あなた自身で書いた答えはこのトリックを行いますが、このタイプのことを行う正しい方法ではありません。

問題の1つは、正弦波の「先端」またはピークを1と比較して調べることです。すべての正弦周波数がその値に達するわけではありません。また、多数のサイクルが必要な場合もあります。

言えば数学的には、正弦波のピークは*あなたは、式Y = SIN(2PIを使用し、所与の周波数に対して正弦を計算するためにK.

のすべての整数値に対してSIN(PI/2 + 2piK)でありますx * f0/fs)ここで、xはサンプル番号、f0はサイン周波数、fsはサンプルレートです。 X = 12次に、48kHzのサンプルレートで1kHzのような素敵な数について

:ただし

sin(2pi * 12 * 1000/48000) = sin(2pi * 12/48) = sin(pi/2) = 1 

997Hzのような周波数では、その後、真のピークは、サンプル後の試料の割合を低下12.

sin(2pi * 12 * 997/48000) = 0.99087178042 
sin(2pi * 12 * 997/48000) = 0.99998889671 
sin(2pi * 12 * 997/48000) = 0.99209828673 

波形を一緒に縫い合わせるより良い方法は、1つのトーンから位相を追跡し、それを次のトーンの開始フェーズとして使用することです。

まず、所定の周波数のためにあなたが位相増分を把握する必要があり、それはあなたがサンプルでやっていることは因数分解と同じであることに注意してください:

phInc = 2*pi*f0/fs 

次に、正弦を計算し、更新します現在の位相を表す変数。

for x in xrange(number_of_frames): 
    y = math.sin(self._phase); 
    self._phase += phaseInc; 

すべて一緒にそれを置く:

def tone(self, frequency, length=1000, play=False, **kwargs): 

    number_of_frames = int(self.bitrate * length/1000.) 
    phInc = 2*math.pi*frequency/self.bitrate 

    for x in xrange(number_of_frames): 
     y = math.sin(self._phase) 
     _phase += phaseInc; 
     self._queue.append(chr(int(y)))