CSCore: воспроизведение массива с плавающей точкой из чистых данных
Я пишу программу на 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 в документации, и я думаю, что он подходит для этой задачи. Я попытался что-то вроде этого в методе чтения моей реализации интерфейса:
...
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, но где я могу это настроить? Функция Process в LibPd работает следующим образом:
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, используя информацию выше:
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 (это float-массив размером 128 каждый раз).
Теперь я слышу синусоидальную волну, но с сильным потрескивающим звуком - кажется, что сэмплы не обрабатываются непрерывно. Есть идеи как решить это?
1 ответ
Но это не сработало - у меня только хрустящие звуки (угадайте, что). Я знаю, что это как-то связано с размером буфера метода Read, но где я могу это настроить?
Вы не можете "настроить" это. Если WasapiOut
запрашивает определенный объем данных, это в ваших руках, сколько данных вы хотите вернуть. Заполните buffer
начиная с указанного offset
, с данными, которые вы хотите. Вернуть количество предоставленных образцов. Вот как вы "настраиваете" это.