73 lines
3.6 KiB
C#
73 lines
3.6 KiB
C#
|
using UnityEngine;
|
|||
|
|
|||
|
namespace Normal.Realtime {
|
|||
|
public class AudioDeviceDataReader {
|
|||
|
// TODO: Support switching?
|
|||
|
// I think we just need to reset the variables set in the contructor
|
|||
|
public MicrophoneDevice microphone { get; private set; }
|
|||
|
|
|||
|
private int _previousLocalWriteHeadPosition;
|
|||
|
private int _writeHeadLoopCount;
|
|||
|
private int _readHeadPosition;
|
|||
|
|
|||
|
public AudioDeviceDataReader(MicrophoneDevice microphone) {
|
|||
|
this.microphone = microphone;
|
|||
|
|
|||
|
// Initialize read and write head positions to the current position of the microphone write head.
|
|||
|
_previousLocalWriteHeadPosition = microphone.deviceWriteHeadPosition;
|
|||
|
_writeHeadLoopCount = 0;
|
|||
|
_readHeadPosition = microphone.deviceWriteHeadPosition;
|
|||
|
}
|
|||
|
|
|||
|
public bool GetData(float[] buffer) {
|
|||
|
// Get the current write head position
|
|||
|
int localWriteHeadPosition = microphone.deviceWriteHeadPosition;
|
|||
|
if (localWriteHeadPosition < _previousLocalWriteHeadPosition)
|
|||
|
_writeHeadLoopCount++;
|
|||
|
_previousLocalWriteHeadPosition = localWriteHeadPosition;
|
|||
|
|
|||
|
// Calculate the global write head position
|
|||
|
int writeHeadPosition = _writeHeadLoopCount * microphone.deviceBufferSampleCount + localWriteHeadPosition;
|
|||
|
|
|||
|
// Number of samples to read into the supplied buffer.
|
|||
|
int numberOfSamplesToRead = buffer.Length / microphone.numberOfChannels;
|
|||
|
|
|||
|
// Figure out where the read head will be after filling this buffer.
|
|||
|
int nextReadHeadPosition = _readHeadPosition + numberOfSamplesToRead;
|
|||
|
|
|||
|
if (numberOfSamplesToRead > microphone.deviceBufferSampleCount) {
|
|||
|
Debug.LogError("Reading microphone audio data. Supplied buffer is larger than the microphone buffer. (" + buffer.Length + ", " + microphone.deviceBufferSampleCount * microphone.numberOfChannels + ")");
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
// If the next read head will be past the write head position, bail.
|
|||
|
if (nextReadHeadPosition >= writeHeadPosition)
|
|||
|
return false;
|
|||
|
|
|||
|
// TODO: Will this barf if buffer.Length is > _microphone.samples or will GetData automatically loop back to the beginning for us?
|
|||
|
bool success = microphone.GetBufferData(buffer, _readHeadPosition % microphone.deviceBufferSampleCount);
|
|||
|
_readHeadPosition = nextReadHeadPosition;
|
|||
|
|
|||
|
return success;
|
|||
|
}
|
|||
|
|
|||
|
public bool GetMostRecentData(float[] buffer) {
|
|||
|
// Number of samples to read into the supplied buffer.
|
|||
|
int numberOfSamplesToRead = buffer.Length / microphone.numberOfChannels;
|
|||
|
if (numberOfSamplesToRead > microphone.deviceBufferSampleCount) {
|
|||
|
Debug.LogError("Reading microphone audio data. Supplied buffer is larger than the microphone buffer. (" + buffer.Length + ", " + microphone.deviceBufferSampleCount * microphone.numberOfChannels + ")");
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
int localWriteHeadPosition = microphone.deviceWriteHeadPosition;
|
|||
|
int localReadHeadPosition = localWriteHeadPosition - numberOfSamplesToRead;
|
|||
|
while (localReadHeadPosition >= microphone.deviceBufferSampleCount)
|
|||
|
localReadHeadPosition -= microphone.deviceBufferSampleCount;
|
|||
|
while (localReadHeadPosition < 0)
|
|||
|
localReadHeadPosition += microphone.deviceBufferSampleCount;
|
|||
|
|
|||
|
return microphone.GetBufferData(buffer, localReadHeadPosition);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|