我正在用C#编写一个程序,该程序使用libpd库与纯数据进行通信(更多信息:http://libpd.cc/)
我的纯数据补丁只是创建一个正弦波。
我编写了一些测试代码,以查看是否可以从纯数据补丁中获取任何数据。 LibPD.Process方法将样本写入到外缓冲区数组中,并且内容是介于-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接口(interface),我认为这是执行此任务的正确方法。我在接口(interface)实现的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。
编辑:
我编写了一个PureDataSource类,该类使用上面的信息实现ISampleSource接口(interface):
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)。我现在可以听到正弦波,但是发出很多crack啪声-似乎样品没有被连续处理。任何想法如何解决这个问题?
最佳答案
您不能“配置”它。如果WasapiOut
请求一定数量的数据,那么您要返回多少数据就在您手中。从指定的buffer
开始,用所需的数据填充offset
。返回提供的样本数。这就是您“配置”它的方式。
关于c# - CSCore:从纯数据回放浮点数组,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34465033/