4

私の目標は、ラップトップ マイクを介して自分の声を録音し、同時に Python でエフェクトを追加することです。私が必要としているのは、ギターやマイクを接続してリバーブやエコー、ディストーションなどを追加するミュージック エフェクターに似たものです。

「pyaudio」と「wave」を使用してオーディオを録音および再生しています。「scikits.audiolab」を使用してオーディオを配列としてインポートし、この配列を反転、クリップ、タイルなどの関数で編集できるようにします。このオーディオ配列の操作により、元のオーディオにエフェクトを「追加」できます。

私は問題を抱えていますが、それは実際には問題ではなく、私が望む効果ではありません. 「こんにちは」という言葉を録音するとしましょう。録音機能を 3 秒間録音するように設定しています。次に、このオーディオ配列を取得して、1 回並べて表示します。これを再生すると、ハローが 2 回表示されます。これは遅延効果です。しかし、両方のこんにちはの間に「空のスペース」の時間間隔があります。これは、私が挨拶を終えた後も音声が録音されているために発生します。したがって、繰り返すと、単語間に空白が多すぎます。この空きスペースをなくして、再生で hello hello がより迅速に表示されるようにします。

私の先生は糸通しを勧めています。彼は、録音と同時に最初の 500 サンプルを取得する必要があると言っています。彼は、これらの 500 のサンプルを取得し、録音中に再生することをお勧めします。これを実装する方法がよくわかりません。

私の質問は、同時に録音し、最初の 500 サンプルを取得し、元の録音に「効果」を追加して新しい配列を作成する方法です。

import scikits.audiolab as audiolab
import pyaudio
import wave

def recordAudio():

    CHUNK = 1024
    FORMAT = pyaudio.paInt16
    CHANNELS = 1
    RATE = 44100
    RECORD_SECONDS = 3
    WAVE_OUTPUT_FILENAME = "audioOriginal.wav"

    p = pyaudio.PyAudio()

    stream = p.open(format=FORMAT,
                channels=CHANNELS,
                rate=RATE,
                input=True,
                frames_per_buffer=CHUNK)

    print("* recording:")

    frames = []

    for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
        data = stream.read(CHUNK)
        frames.append(data)

    print("* Finished recording.")

    stream.stop_stream()
    stream.close()
    p.terminate()

    wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
    wf.setnchannels(CHANNELS)
    wf.setsampwidth(p.get_sample_size(FORMAT))
    wf.setframerate(RATE)
    wf.writeframes(b''.join(frames))
    wf.close()

    # Duplicate audio and save as Actual
    frames, fs, encoder = audiolab.wavread('audioOriginal.wav')
    audiolab.wavwrite(frames,'audioActual.wav',fs)

def playAudio():

    import pyaudio
    import wave

    CHUNK = 1024

    wf = wave.open('audioActual.wav', 'rb')

    p = pyaudio.PyAudio()

    stream = p.open(format=p.get_format_from_width(wf.getsampwidth()), 
        channels=wf.getnchannels(), 
        rate=wf.getframerate(), 
        output=True)

    data = wf.readframes(CHUNK)

    while data != '':  
        stream.write(data)  
        data = wf.readframes(CHUNK)

    stream.stop_stream()
    stream.close()
    p.terminate()

def reverseAudio():

    frames, fs, encoder = audiolab.wavread('audioActual.wav')

    audiolab.wavwrite(frames[::-1],'audioActual.wav',44100)

def revert():
    frames, fs, encoder = audiolab.wavread('audioOriginal.wav')
    audiolab.wavwrite(frames,'audioActual.wav',fs)

def errorSelection():
    print("\nERROR.") # no option in menu
def showMenu():
    print("""
    1. Record audio
    2. Play audio
    3. Reverse audio
    4. Add delay
    5. Revert to original audio

    T to end program.
    """)

# Menu
def main():
    selecciones = {"1": recordAudio, "2": playAudio, "3": reverseAudio, "5": revert}
    while True:
        showMenu()
        seleccion = raw_input(u'What do you want to do? ')
        if "t" == seleccion:
            return
        elif "T" == seleccion:
            return
        toDo = selecciones.get(seleccion, errorSelection)
        toDo()

if __name__ == "__main__":
    main()
4

2 に答える 2

4

まず、あなたが提起した問題 (オーディオ サンプル間の静かなスペースを自動的に削除しながら、オーディオ サンプルを並べて表示できること) は、スレッド化で解決できるものではありません。録音されたサウンドを分析して、無音がある場所とない場所を判断するか、ユーザーがいつ録音を終了するかを指定できるようにする必要があります。後者は単純なループで実現できます。

  1. オーディオ ハードウェアを開き、録音を開始します。
  2. 空のリストを作成してオーディオのチャンクを保存します
  3. 音声データの小さなチャンクをリクエストし、リストに追加します
  4. ユーザーが記録の終了を要求したことを確認します。そうでない場合は、3 に戻ります。
  5. 終了したら、再生のためにチャンクを 1 つの配列に組み立てます。

この単純な例では、スレッド化を使用する利点はありません。

提案された、記録と同時に再生する方法は、はるかに複雑な別の問題に対する解決策のように思えます。この場合、次の 2 つの大きな問題があります。

  1. すべてのコンシューマ サウンド カードが録音と再生を同時に行えるわけではありません。「半二重」ではなく「全二重」と表記されているカードを探してください。
  2. マイクに向かって話すと、少し遅れて自分の声が聞こえると、非常に気が散ります。これを適切に機能させるには、録音されたオーディオを処理し、約 20 ミリ秒以内にサウンド カードに送り返す必要があります。44.1 kHz では、ループ サイクルごとに 880 フレーム未満を読み取る必要があり、処理が追いつかない場合、出力にギャップが生じることを意味します。これは、専門のソフトウェアを使用しない限り、驚くほど難しい問題です。本当にこの方法を使いたい場合は、Jack ( http://jackaudio.org/ ) を参照してください。これは、ほとんどのプラットフォームで低遅延のオーディオ アクセスを提供し、簡単な Python ライブラリ( http://sourceforge.org/) も備えています。 net/projects/py-jack/ )。この種のプログラムでは、おそらくスレッド化は役に立ちません。
于 2013-07-20T19:12:50.547 に答える