Created
July 18, 2022 16:38
-
-
Save Vanlalhriata/c73273ead6afd6cb7a89c2c0addfd2c5 to your computer and use it in GitHub Desktop.
Generate a timmed and fading audio wav file from an AudioClip in Unity3D
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.IO; | |
using System.Linq; | |
using UnityEngine; | |
// Generate a preview audio file (.wav) from an AudioClip. | |
// This uses SavWav forked and modified from darktable: | |
// https://gist.github.com/Vanlalhriata/dc5b703cca6f2e885557e1c2f54c376a | |
public static class PreviewAudioUtil | |
{ | |
private const string PREVIEW_AUDIO_FILENAME = "Preview"; | |
private const string PREVIEW_AUDIO_EXTENSION = ".wav"; | |
private const float PREVIEW_DURATION_SECONDS = 20f; | |
private const float FADE_SECONDS = 2f; | |
public static void GeneratePreviewAudioFile(AudioClip sourceClip, string folderPath) | |
{ | |
if (null == sourceClip) | |
{ | |
Debug.LogError($"PreviewAudioUtil: sourceClip is null."); | |
return; | |
} | |
// NOTE: Using random part of the clip for now. may want to let user choose the preview window | |
var startTime = getRandomPreviewStartTime(sourceClip.length); | |
var previewAudioClip = trimAndFade(sourceClip, startTime, PREVIEW_DURATION_SECONDS); | |
if (null == previewAudioClip) return; | |
var filePath = Path.Combine(folderPath, PREVIEW_AUDIO_FILENAME + PREVIEW_AUDIO_EXTENSION); | |
var isSucess = SavWav.Save(filePath, previewAudioClip); | |
if (!isSucess) | |
{ | |
Debug.LogError("PreviewAudioUtil: Error writing preview audio to file."); | |
} | |
} | |
private static float getRandomPreviewStartTime(float clipLengthSeconds) | |
{ | |
if (clipLengthSeconds <= PREVIEW_DURATION_SECONDS) | |
{ | |
return clipLengthSeconds; | |
} | |
// Start from anywhere between 0 and preview-length seconds before the end | |
return Random.Range(0, clipLengthSeconds - PREVIEW_DURATION_SECONDS); | |
} | |
// Trim an audioClip into the specified duration starting from startTime. Also fades in and out | |
private static AudioClip trimAndFade(AudioClip sourceClip, float startTime, float durationSeconds) | |
{ | |
// Get samples starting from startTime | |
int sampleOffset = Mathf.RoundToInt(startTime * sourceClip.frequency); // No need to multiply by channel count | |
var samples = new float[sourceClip.samples * sourceClip.channels]; | |
bool isGetSuccessful = sourceClip.GetData(samples, sampleOffset); | |
if (!isGetSuccessful) | |
{ | |
Debug.LogError("PreviewAudioUtil: Could not get samples from main AudioClip."); | |
return null; | |
} | |
// Get the samples making up the required duration | |
var samplesCount = Mathf.CeilToInt(durationSeconds * sourceClip.frequency * sourceClip.channels); | |
samples = samples.Take(samplesCount).ToArray(); | |
samples = fadeSamples(samples, sourceClip.frequency, sourceClip.channels); | |
var previewAudioClip = AudioClip.Create(PREVIEW_AUDIO_FILENAME, samples.Length / 2, sourceClip.channels, sourceClip.frequency, false); | |
previewAudioClip.SetData(samples, 0); | |
return previewAudioClip; | |
} | |
// Apply fade-in and fade-out | |
private static float[] fadeSamples(float[] samples, int frequency, int channelCount) | |
{ | |
// Just fade, without caring for uniform fade for each channel | |
var fadeInToSample = Mathf.RoundToInt(FADE_SECONDS * frequency * channelCount); | |
var fadeOutFromSample = samples.Length - fadeInToSample; | |
var fadeStep = 1f / fadeInToSample; | |
int i; | |
for (i = 0; i < fadeInToSample; i++) | |
{ | |
samples[i] *= i * fadeStep; // Linear fade | |
} | |
for (i = fadeOutFromSample; i < samples.Length; i++) | |
{ | |
samples[i] *= (samples.Length - i) * fadeStep; // Linear fade | |
} | |
return samples; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment