我正在尝试将传入的麦克风音频从Unity实时发送到Wwise。 我有一个“生产者线程”和一个“消费者线程”。我正在尝试将传入缓冲区从生产者复制到消费者。
// Unity callback on microphone input (“producer thread“)
void OnAudioFilterRead(float[] data, int channels)
{
// acquire ownership of mutex and buffer
mutex.WaitOne();
// copy samples to buffer (de–interleave channels)
for (int i = 0; i < data.Length / channels; i++)
{
buffer.Add(data[i * channels]);
}
// release ownership of mutex and buffer
mutex.ReleaseMutex();
}
// Wwise callback that sends buffered samples to Wwise (“consumer thread“)
bool AudioSamplesDelegate(uint playingID, uint channelIndex, float[] samples)
{
// acquire ownership of mutex and buffer
mutex.WaitOne();
// copy samples from buffer to temporary block
int blockSize = Math.Min(buffer.Count, samples.Length);
List<float> block = buffer.GetRange(0, blockSize);
buffer.RemoveRange(0, blockSize);
// release ownership of mutex and buffer (release mutex as quickly as possible)
mutex.ReleaseMutex();
// copy samples from temporary block to output array
block.CopyTo(samples);
// Return false to indicate that there is no more data to provide. This will also stop the associated event.
return IsPlaying;
}
这可以工作,但是我从Wwise那里获得的音频出现了毛刺。是否有关于最佳方法做到这一点/改善这一点的意见?循环缓冲区是否可行?
答案 0 :(得分:1)
我认为使用多个缓冲区而不是大缓冲区来减少同步时间将很有帮助。
// Create a thread-safed queue
Queue bufferQueue = Queue.Synchronized(new Queue());
List<float> remains;
// Unity callback on microphone input (“producer thread“)
void OnAudioFilterRead(float[] data, int channels)
{
var buffer = new List<folat>(data.Length);
// copy samples to buffer (de–interleave channels)
for (int i = 0; i < data.Length / channels; i++)
{
buffer.Add(data[i * channels]);
}
// Add buffer to the queue
bufferQueue.Enqueue(buffer);
}
// Wwise callback that sends buffered samples to Wwise (“consumer thread“)
bool AudioSamplesDelegate(uint playingID, uint channelIndex, float[] samples)
{
// Fill samples
var requiredLength = samples.Length;
while (requiredLength > 0)
{
if (remains == null)
if (bufferQueue.Count > 0)
remains = bufferQueue.Dequeue();
else
break;
if (remains.Length > requiredLength)
{
remains.CopyTo(0, samples, samples.Length - requiredLength, requiredLength);
remains.RemoveRange(0, requiredLength);
break;
}
remains.CopyTo(0, samples, samples.Length - requiredLength, remains.Length);
requiredLength -= remains.Length;
remains = null;
}
// Return false to indicate that there is no more data to provide. This will also stop the associated event.
return IsPlaying;
}