简体   繁体   中英

Copying buffer data in real time

I am trying to send incoming microphone audio from Unity to Wwise in real time. I have a "producer thread" and a "consumer thread". I am trying to copy my incoming buffer from the producer to the consumer.

// 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;
}

This works but the audio I get from Wwise is glitchy. Any inputs on the best method to do this/improve this? Are circular buffers the way to go?

I think use multiple buffers instead of a large one to reduce synchronous time will be helpful.

// 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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM