Fixed loaded audio not looping bug

This commit is contained in:
Nick J. Connors 2022-02-05 14:15:31 -05:00
parent bf0fc6f465
commit 4d744d0cc1
2 changed files with 33 additions and 64 deletions

View File

@ -121,7 +121,8 @@ namespace NewHorizons.Builder.Props
{ {
try try
{ {
clip = mod.Assets.GetAudio(info.AudioFilePath); clip = AudioUtility.LoadAudio(mod.Manifest.ModFolderPath + "/" + info.AudioFilePath);
//clip = mod.Assets.GetAudio(info.AudioFilePath);
} }
catch(Exception e) catch(Exception e)
{ {

View File

@ -5,87 +5,55 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using UnityEngine; using UnityEngine;
using UnityEngine.Networking;
namespace NewHorizons.Utility namespace NewHorizons.Utility
{ {
public static class AudioUtility public static class AudioUtility
{ {
// Thank you https://answers.unity.com/questions/737002/wav-byte-to-audioclip.html?_ga=2.94866780.194866897.1641426110-1837936344.1635819725 public static AudioClip LoadAudio(string filePath)
// convert two bytes to one float in the range -1 to 1
static float bytesToFloat(byte firstByte, byte secondByte)
{ {
// convert two bytes to one short (little endian) var task = Task.Run(async () => await GetAudioClip(filePath));
short s = (short)((secondByte << 8) | firstByte); task.Wait();
// convert to range from -1 to (just below) 1 return task.Result;
return s / 32768.0F;
} }
static int bytesToInt(byte[] bytes, int offset = 0) private static async Task<AudioClip> GetAudioClip(string filePath)
{ {
int value = 0;
for (int i = 0; i < 4; i++) var extension = filePath.Split(new char[] { '.' }).Last();
UnityEngine.AudioType audioType;
switch (extension)
{ {
value |= ((int)bytes[offset + i]) << (i * 8); case ("wav"):
} audioType = UnityEngine.AudioType.WAV;
return value; break;
case ("ogg"):
audioType = UnityEngine.AudioType.OGGVORBIS;
break;
default:
Logger.LogError($"Invalid audio file extension ({extension}) must be .wav or .ogg");
return null;
} }
private static byte[] GetBytes(string filename) using (UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip(filePath, audioType))
{ {
return File.ReadAllBytes(filename); var result = www.SendWebRequest();
while (!result.isDone) { await Task.Delay(100); }
if (www.isNetworkError)
{
Debug.Log(www.error);
return null;
} }
else
// Returns left and right double arrays. 'right' will be null if sound is mono.
public static AudioClip LoadWAV(string filename)
{ {
var wav = GetBytes(filename); return DownloadHandlerAudioClip.GetContent(www);
// Determine if mono or stereo
var ChannelCount = wav[22]; // Forget byte 23 as 99.999% of WAVs are 1 or 2 channels
// Get the frequency
var Frequency = bytesToInt(wav, 24);
// Get past all the other sub chunks to get to the data subchunk:
int pos = 12; // First Subchunk ID from 12 to 16
// Keep iterating until we find the data chunk (i.e. 64 61 74 61 ...... (i.e. 100 97 116 97 in decimal))
while (!(wav[pos] == 100 && wav[pos + 1] == 97 && wav[pos + 2] == 116 && wav[pos + 3] == 97))
{
pos += 4;
int chunkSize = wav[pos] + wav[pos + 1] * 256 + wav[pos + 2] * 65536 + wav[pos + 3] * 16777216;
pos += 4 + chunkSize;
} }
pos += 8;
// Pos is now positioned to start of actual sound data.
var SampleCount = (wav.Length - pos) / 2; // 2 bytes per sample (16 bit sound mono)
if (ChannelCount == 2) SampleCount /= 2; // 4 bytes per sample (16 bit stereo)
// Allocate memory (right will be null if only mono sound)
var LeftChannel = new float[SampleCount];
float[] RightChannel;
if (ChannelCount == 2) RightChannel = new float[SampleCount];
else RightChannel = null;
// Write to double array/s:
int i = 0;
while (pos < wav.Length)
{
LeftChannel[i] = bytesToFloat(wav[pos], wav[pos + 1]);
pos += 2;
if (ChannelCount == 2)
{
RightChannel[i] = bytesToFloat(wav[pos], wav[pos + 1]);
pos += 2;
} }
i++;
}
AudioClip audioClip = AudioClip.Create("testSound", SampleCount, 1, Frequency, false);
audioClip.SetData(LeftChannel, 0);
return audioClip;
} }
} }
} }