4

私は音楽を再生するPythonプログラムに取り組んでいます。1つの機能は、ユーザーが音楽の再生中に音楽のピッチを変更するために上下にドラッグできるスライダーです。

たとえば、ピッチが2に設定されている場合、音楽は1オクターブ高く聞こえ、2倍の速さで再生され、半分の長さで持続します。私が本当に変えているのは再生速度だけですが、リアルタイムでインタラクティブに行う必要があります。

フラッシュに実装されたこの機能の良い例は、ここにあります。(ロードには少し時間がかかります。しばらくお待ちください。)

多くのPythonオーディオパッケージを調べましたが、現在再生中のサウンドのピッチを変更できるパッケージは見つかりませんでした。Pythonには複数のバージョンがあるので、パッケージがサポートするバージョンの要件はありません。私はこれをWindows7で開発しています。

助言がありますか?

4

4 に答える 4

2

Craig McQueenの助けを借りて、概念実証プログラムを作成しました。

このプログラムは、「music.wav」(プログラムと同じフォルダにあります)と呼ばれるモノラルwavファイルを再生し、短くて広いウィンドウを表示します。ウィンドウをクリックしてドラッグすると、音楽のピッチが変化します。ウィンドウの左側は2オクターブ低く、右側は2オクターブ高くなっています。

ここには、修正方法がわからない奇妙な動作がいくつかあります。ピッチが現在低い場合、ピッチが変わるまでに約2秒の遅延があります。ただし、高音域ではピッチがリアルタイムで変化します。(ピッチが低くなると、遅延はスムーズに増加します)。の場合にのみ、バッファにサウンドを追加しますsoundOutput.getLeft() < 0.2。つまり、バッファに残っている音の量が0.2秒未満の場合です。したがって、遅延はありません。トラブルシューティングのためsoundOutput.getLeft()に、ファイルに書き込むコードを含めました。常に0またはその近くにとどまる傾向があります。

読み取ったフレームをwaveRead.readframes(100)減らすと遅延が減りますが、音が途切れます。読み取られるフレームを増やすと、遅延が大幅に増加します。

import os, sys, wave, pygame, numpy, pymedia.audio.sound, scikits.samplerate

class Window:
    def __init__(self, width, height, minOctave, maxOctave):
        """
        width, height: the width and height of the screen.
        minOctave, maxOctave: the highest and lowest pitch changes. 0 is no change.
        """
        self.minOctave = minOctave
        self.maxOctave = maxOctave
        self.width = width
        self.mouseDown = False
        self.ratio = 1.0 # The resampling ratio
        waveRead = wave.open(os.path.join(sys.path[0], "music.wav"), 'rb')
        sampleRate = waveRead.getframerate()
        channels = waveRead.getnchannels()
        soundFormat = pymedia.audio.sound.AFMT_S16_LE
        soundOutput = pymedia.audio.sound.Output(sampleRate, channels, soundFormat)
        pygame.init()
        screen = pygame.display.set_mode((width, height), 0)
        screen.fill((255, 255, 255))
        pygame.display.flip()
        fout = open(os.path.join(sys.path[0], "musicdata.txt"), 'w') # For troubleshooting
        byteString = waveRead.readframes(1000) # Read at most 1000 samples from the file.
        while len(byteString) != 0:
            self.handleEvent(pygame.event.poll()) # This does not wait for an event.
            fout.write(str(soundOutput.getLeft()) + "\n") # For troubleshooting
            if soundOutput.getLeft() < 0.2: # If there is less than 0.2 seconds left in the sound buffer.
                array = numpy.fromstring(byteString, dtype=numpy.int16)
                byteString = scikits.samplerate.resample(array, self.ratio, "sinc_fastest").astype(numpy.int16).tostring()
                soundOutput.play(byteString)
                byteString = waveRead.readframes(500) # Read at most 500 samples from the file.
        waveRead.close()
        return

    def handleEvent(self, event):
        if event.type == pygame.QUIT or (event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE):
            sys.exit()
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            self.mouseDown = True
            self.setRatio(event.pos)
        if event.type == pygame.MOUSEBUTTONUP and event.button == 1:
            self.mouseDown = False
        if event.type == pygame.MOUSEMOTION and self.mouseDown:
            self.setRatio(event.pos)
        return None

    def setRatio(self, point):
        self.ratio = 2 ** -(self.minOctave + point[0] * (self.maxOctave - self.minOctave) / float(self.width))
        print(self.ratio)

def main():
    Window(768, 100, -2.0, 2.0)

if __name__ == '__main__':
    main()

私が使用するすべてのパッケージを一緒にうまく機能させることを試みるのは苦痛です。私はPython2.6.6 、Python2.6にはPyGame1.9.1 、 Python2.6にはNumPy1.3.0、 Python2.6にはPyMedia1.3.7.3Python2.6にはscikits.samplerate0.3.1を使用しています。scikits.samplerateはNumPy1.4以降と競合し、パッケージの1つ(どれを忘れたか)にはsetuptoolsが必要であることに注意してください。

于 2010-10-22T17:44:09.307 に答える
1

オンザフライでオーディオをリサンプリングしたいように聞こえます。

おそらく、 scikits.samplerateモジュールを使用してみることができます。シークレットラビットコードライブラリを使用します。

于 2010-10-20T23:26:02.747 に答える
0

wxPython使用してメディアプレーヤーを作成し、関数を調査することをお勧めしますSetPlaybackRate()wxWidgetのドキュメントはこちら

そのSetPlaybackRate()機能はすべてのプラットフォームでサポートされているわけではなく、私はそれがあなたが望むものを正確に実行するかどうか、そしてそれがどれだけうまく機能するかを確認するために自分で試したわけではありません。

于 2010-10-22T02:08:56.880 に答える
0

scikits.samplerate0.3.1にはセットアップツールが必要です

そうしないと、エラーが発生し続けますImportError:pkg_resourcesという名前のモジュールがありません

于 2013-03-12T07:18:12.233 に答える