Skip to content

Commit

Permalink
com.utilities.encoder.ogg 4.1.0
Browse files Browse the repository at this point in the history
- com.utilities.audio -> 2.1.0
- better support for output sample rate when recording
  • Loading branch information
StephenHodgson committed Nov 30, 2024
1 parent 54d88a6 commit ee79a6e
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -139,19 +139,23 @@ public async Task<Tuple<string, AudioClip>> StreamSaveToDiskAsync(ClipData clipD
}

var totalSampleCount = 0;
var finalSamples = new float[clipData.MaxSamples ?? clipData.SampleRate * RecordingManager.MaxRecordingLength];
var maxSampleLength = clipData.MaxSamples ?? clipData.InputSampleRate * RecordingManager.MaxRecordingLength;
var finalSamples = new float[maxSampleLength];

try
{
WriteOggHeader(clipData.SampleRate, clipData.Channels, 0.5f, out OggStream oggStream, out ProcessingState processingState);
WriteOggHeader(clipData.OutputSampleRate, clipData.Channels, 0.5f, out OggStream oggStream, out ProcessingState processingState);

try
{
var sampleCount = 0;
var shouldStop = false;
var lastMicrophonePosition = 0;
var needsResample = clipData.InputSampleRate != clipData.OutputSampleRate;
var channelBuffer = new float[clipData.Channels][];
var sampleBuffer = new float[clipData.BufferSize];
var ratio = needsResample ? (double)clipData.InputSampleRate / clipData.OutputSampleRate : 1d;
var inputBufferSize = clipData.InputBufferSize;
var sampleBuffer = new float[inputBufferSize];

for (var i = 0; i < clipData.Channels; i++)
{
Expand All @@ -176,7 +180,7 @@ public async Task<Tuple<string, AudioClip>> StreamSaveToDiskAsync(ClipData clipD
if (isLooping)
{
// Microphone loopback detected.
samplesToWrite = clipData.BufferSize - lastMicrophonePosition;
samplesToWrite = clipData.InputSampleRate - lastMicrophonePosition;

if (RecordingManager.EnableDebug)
{
Expand All @@ -194,22 +198,41 @@ public async Task<Tuple<string, AudioClip>> StreamSaveToDiskAsync(ClipData clipD
cancellationToken.ThrowIfCancellationRequested();
clipData.Clip.GetData(sampleBuffer, 0);

for (var i = 0; i < samplesToWrite; i++)
var outputSamplesToWrite = needsResample
? (int)(samplesToWrite * ratio)
: samplesToWrite;

for (var i = 0; i < outputSamplesToWrite; i++)
{
var bufferIndex = (lastMicrophonePosition + i) % clipData.BufferSize; // Wrap around index.
var sample = sampleBuffer[bufferIndex];
float value;

if (needsResample)
{
var resampleIndex = Math.Round(lastMicrophonePosition + i / ratio, MidpointRounding.ToEven);
var leftIndex = (int)Math.Floor(resampleIndex) % inputBufferSize; // Wrap around index.
var rightIndex = (leftIndex + 1) % inputBufferSize; // Wrap around index.
var fraction = resampleIndex - leftIndex;

// Simple Linear Interpolation
value = (float)((1 - fraction) * sampleBuffer[leftIndex] + fraction * sampleBuffer[rightIndex]);
}
else
{
var bufferIndex = (lastMicrophonePosition + i) % inputBufferSize; // Wrap around index.
value = sampleBuffer[bufferIndex];
}

for (var channel = 0; channel < clipData.Channels; channel++)
{
channelBuffer[channel][i] = sample;
channelBuffer[channel][i] = value;
}

// Store the sample in the final samples array.
finalSamples[sampleCount * clipData.Channels + i] = sampleBuffer[bufferIndex];
finalSamples[sampleCount * clipData.Channels + i] = value;
}

lastMicrophonePosition = microphonePosition;
sampleCount += samplesToWrite;
sampleCount += outputSamplesToWrite;

if (RecordingManager.EnableDebug)
{
Expand All @@ -221,7 +244,7 @@ public async Task<Tuple<string, AudioClip>> StreamSaveToDiskAsync(ClipData clipD
}

// Check if we have recorded enough samples or if cancellation has been requested
if (oggStream.Finished || sampleCount >= clipData.MaxSamples || cancellationToken.IsCancellationRequested)
if (oggStream.Finished || sampleCount >= maxSampleLength || cancellationToken.IsCancellationRequested)
{
shouldStop = true;
}
Expand Down Expand Up @@ -299,7 +322,7 @@ public async Task<Tuple<string, AudioClip>> StreamSaveToDiskAsync(ClipData clipD
await Awaiters.UnityMainThread;

// Create a new copy of the final recorded clip.
var newClip = AudioClip.Create(clipData.Name, microphoneData.Length, clipData.Channels, clipData.SampleRate, false);
var newClip = AudioClip.Create(clipData.Name, microphoneData.Length, clipData.Channels, clipData.OutputSampleRate, false);
newClip.SetData(microphoneData, 0);
result = new Tuple<string, AudioClip>(outputPath, newClip);
callback?.Invoke(result);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"displayName": "Utilities.Encoder.Ogg",
"description": "Simple library for Ogg encoding support.",
"keywords": [],
"version": "4.0.1",
"version": "4.1.0",
"unity": "2021.3",
"documentationUrl": "https://github.com/RageAgainstThePixel/com.utilities.encoder.ogg#documentation",
"changelogUrl": "https://github.com/RageAgainstThePixel/com.utilities.encoder.ogg/releases",
Expand All @@ -15,7 +15,7 @@
"author": "Stephen Hodgson",
"url": "https://github.com/StephenHodgson",
"dependencies": {
"com.utilities.audio": "2.0.2"
"com.utilities.audio": "2.1.0"
},
"samples": [
{
Expand Down

0 comments on commit ee79a6e

Please sign in to comment.