CSCore:从纯数据回放浮点数组

时间:2015-12-25 17:41:44

标签: c# audio signal-processing cscore libpd

我在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播放这个float数组。我在文档中找到了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 - &gt; 128。

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

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的float数组)。

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

1 个答案:

答案 0 :(得分:1)

  

但它没有成功 - 我只能听到噼里啪啦的声音(猜猜是什么)。我知道它与Read方法的缓冲区大小有关,但我在哪里可以配置它?

你不能&#34;配置&#34;它。如果WasapiOut请求了一定数量的数据,那么您需要返回多少数据。从指定的buffer开始,使用您想要的数据填充offset。返回提供的样本数量。这就是你如何配置&#34;它