1

我正在用 C# 编写一个程序,它使用 libpd 库与纯数据进行通信(更多信息:http ://libpd.cc/ )

我的纯数据补丁只是创建一个正弦波。

我写了一些测试代码来看看我是否从我的纯数据补丁中得到任何数据。LibPD.Process 方法将样本写入 outbuffer 数组,内容为 -1 和 1 之间的连续值:

// Initialise Pd with 0 input and 2 output channels and a samplerate of 44100. Project dependent.
int pdOpen = -1;
pdOpen = LibPD.OpenAudio(0, 2, 44100);

if (pdOpen != 0)
{
    Console.WriteLine("Error opening audio... exiting");
    return;
}

string patchFile = @"..\..\..\test.pd";
int patch = LibPD.OpenPatch(patchFile);
LibPD.ComputeAudio(true);

//Read from Process Function...
// The size of each buffer must be the product of the number of channels, the number of ticks, 
// and the number of samples per tick. (The number of samples per tick is the value 
// returned by libpd_blocksize(), i.e., 64.)

int ret;
float[] outbuffer = new float[2 * 1 * LibPD.BlockSize]; // Size = 128

for (int i = 0; i < 10; i++)
{
    ret = LibPD.Process(1, new float[0], outbuffer);
    Thread.Sleep(1000);
}

LibPD.ClosePatch(patch);
LibPD.Release();

所以我确信我正在从我的补丁中获取处理过的数据。

现在我想使用 CSCore 回放这个浮点数组。我在文档中找到了 ISampleSource 接口,我认为它是完成这项任务的正确选择。我在接口实现的 Read 方法中尝试了类似的方法:

...

public PureDataSource()
{
    _WaveFormat = new WaveFormat(44100, 16, 2);

    int pdOpen = -1;
    pdOpen = LibPD.OpenAudio(0, 2, 44100);

    if (pdOpen != 0)
    {
        Console.WriteLine("Error opening audio... exiting");
        return;
    }

    string patch = @"..\..\..\test.pd";
    _Patch = LibPD.OpenPatch(patch);
    LibPD.ComputeAudio(true);
}

...

public int Read(float[] buffer, int offset, int count)
{
    LibPD.Process(1, new float[0], buffer);

    return count;
}

但它不起作用 - 我只听到噼啪声(你猜怎么着)。我知道这与 Read 方法的缓冲区大小有关,但我在哪里可以配置呢?LibPd 的 Process 函数是这样工作的:

The size of each buffer must be the product of the number of channels, the      number of ticks, 
and the number of samples per tick. (The number of samples per tick is the value 
returned by libpd_blocksize(), i.e., 64.)

在我的情况下是:2 个通道(输出通道),1 个滴答声,每个滴答声的样本数是 64 --> 128。

编辑:我使用上面的信息编写了一个实现 ISampleSource 接口的 PureDataSource 类:

class Program
{
    static void Main(string[] args)
    {
        PureDataSource pdSource = new PureDataSource();
        WasapiOut soundOut = new WasapiOut();

        soundOut.Initialize(pdSource.ToWaveSource());

        soundOut.Play();
        Thread.Sleep(5000);
        soundOut.Stop();
    }
}

class PureDataSource : ISampleSource
{
    public long Length
    {
        get
        {
            return 0;
        }
    }

    public long Position
    {
        get
        {
            return 0;
        }

        set
        {
            throw new NotImplementedException();
        }
    }
    private WaveFormat _WaveFormat;
    public WaveFormat WaveFormat
    {
        get
        {
            return _WaveFormat;
        }
    }

    private int _Patch;
    public int Patch
    {
        get { return _Patch; }
        //set { _Patch = value; }
    }

    public PureDataSource()
    {
        _WaveFormat = new WaveFormat(44100, 16, 2);

        // Initialise Pd with 2 ins and outs and a samplerate of 44100. Project dependent.
        int pdOpen = -1;
        pdOpen = LibPD.OpenAudio(0, 2, 44100);

        if (pdOpen != 0)
        {
            Console.WriteLine("Error opening audio... exiting");
            return;
        }

        string patch = @"..\..\..\test.pd";
        _Patch = LibPD.OpenPatch(patch);
        LibPD.ComputeAudio(true);
    }

    public void Dispose()
    {
        LibPD.ClosePatch(_Patch);
        LibPD.Release();
    }

    public int Read(float[] buffer, int offset, int count)
    {
        int ticks = 1;

        int pdBufferPos = 0;
        float[] pdBuffer = new float[2 * ticks * LibPD.BlockSize];
        LibPD.Process(ticks, new float[0], pdBuffer);

        for (int i = offset; i < count; i++)
        { 
            if (pdBufferPos >= pdBuffer.Length)
            {
                pdBufferPos = 0;
                LibPD.Process(ticks, new float[0], pdBuffer);
            }

            buffer[i] = pdBuffer[pdBufferPos];
            pdBufferPos++;
        }            

        return count;
    }
}

Read方法使用 LibPD.Process 提供的输出填充整个缓冲区(这是一个浮点数组,每次大小为 128)。

我现在可以听到正弦波,但有很多噼啪声 - 似乎样本没有连续处理。任何想法如何解决这个问题?

4

1 回答 1

2

但它不起作用 - 我只听到噼啪声(你猜怎么着)。我知道这与 Read 方法的缓冲区大小有关,但我在哪里可以配置呢?

你不能“配置”它。如果WasapiOut请求一定量的数据,就在你手中,你要返回多少数据。buffer从指定的 开始offset,用您想要的数据填充。返回提供的样本数。这就是你“配置”它的方式。

于 2016-01-03T22:28:03.270 回答