7

我用 Python 创建了一个简单的基于文本的密室逃脱游戏,目的是嵌入一个纯数据补丁(通过 libPd)以播放不同的声音文件(稍后将用生成音乐的算法替换)我每个不同的房间。

我目前正在使用的 python 代码取自 libPD github 中的一个示例。如下——

import pyaudio
import wave
import sys
from pylibpd import *

p = pyaudio.PyAudio()

ch = 2
sr = 48000
tpb = 16
bs = 64

stream = p.open(format = pyaudio.paInt16,
                channels = ch,
                rate = sr,
                input = True,
                output = True,
                frames_per_buffer = bs * tpb)

m = PdManager(ch, ch, sr, 1)
libpd_open_patch('wavfile.pd')

while 1:
    data = stream.read(bs)
    outp = m.process(data)
    stream.write(outp)

stream.close()
p.terminate()
libpd_release()

纯数据补丁只是播放预渲染的 wav 文件,但生成的输出听起来几乎就像是被比特粉碎了一样。我猜问题与块大小有关,但不确定。

如果有人有在 Python 中嵌入 lidPD 的经验,我将不胜感激,因为我确信我想要实现的目标非常简单。

在此先感谢, 帽

4

4 回答 4

3

我最终使用了一种解决方法并导入了 pygame(而不是 pyaudio)来处理音频并初始化补丁。它工作顺利。

谢谢你的帮助。

*对于遇到类似问题的任何人,请查看 libPd github for python 中的“pygame_test.py”。

于 2013-07-12T15:07:11.410 回答
2

I had similar problems. Using a callback fixed it for me.

Here is the python to play a sine wave.

    import pyaudio
    from pylibpd import *
    import time

    def callback(in_data,frame_count,time_info,status):
        outp = m.process(data)
        return (outp,pyaudio.paContinue)

    p  = pyaudio.PyAudio()
    bs = libpd_blocksize()

    stream = p.open(format = pyaudio.paInt16,
                    channels = 1,
                    rate = 44100,
                    input = False,
                    output = True,
                    frames_per_buffer = bs,
                    stream_callback=callback)

    m = PdManager(1, 1 , 44100, 1)

    libpd_open_patch('sine.pd')

    data=array.array('B',[0]*bs)

    while stream.is_active():
        time.sleep(.1)

    stream.close()
    p.terminate()
    libpd_release()

and the patch "sine.pd"

    #N canvas 647 301 450 300 10;
    #X obj 67 211 dac~;
    #X obj 24 126 osc~ 1000;
    #X obj 16 181 *~ 0.2;
    #X connect 1 0 2 0;
    #X connect 2 0 0 0;

于 2015-04-12T12:11:48.650 回答
0

这有几个部分。

  1. 音频文件的块大小是错误的,因为您设置 tpb = 16 而不是 1。通过将其设置为 16,您将块大小设为 16 * 64 而不是 64。

  2. 采样率可能存在问题。您确定您的声音文件是 48000hz 而不是 44100hz?

于 2013-07-12T04:53:20.160 回答
0

我对上面的示例进行了一些重构:

import pyaudio
from pylibpd import *

class PdAudio:
    def __init__(self):
        self.sample_rate = 44100
        self.num_channel = 2
        self.pd = self.__InitPd(self.num_channel, self.sample_rate)
        self.py_audio = pyaudio.PyAudio()
        self.block_size = libpd_blocksize()
        self.stream = self.__InitAudio(self.num_channel, self.sample_rate,self.block_size)
        self.inbuf = array.array('h', range(self.block_size))
        print("Blocksize: %d" % self.block_size)

    def StartPatchInBackground(self, filename):
        self.patch = libpd_open_patch(filename, '.')

    def IsPlaying(self):
        return self.stream.is_active()

    def __InitAudio(self, num_channels, sample_rate, block_size):
        return self.py_audio.open(format = pyaudio.paInt16,
                                  channels = num_channels,
                                  rate = sample_rate,
                                  input = False,
                                  output = True,
                                  frames_per_buffer = block_size,
                                  stream_callback=self.__AudioCallback)

    def __InitPd(self, num_channels, sample_rate):
        return PdManager(1, num_channels, sample_rate, 1)

    def __AudioCallback(self, in_data,frame_count,time_info,status):
        outp = self.pd.process(self.inbuf)
        return (outp.tobytes(),pyaudio.paContinue)

    def __del__(self):
        self.stream.close()
        self.pd.terminate()
        libpd_release()

pd_audio = PdAudio()
pd_audio.StartPatchInBackground('bloopy.pd')

https://github.com/jkammerl/pylibpd_pyaudio/blob/main/pd_callback_example.py

于 2021-08-12T21:54:23.227 回答