wav converter for mp3

This commit is contained in:
minenice55 2023-12-04 15:12:14 -05:00
parent 88b21877ca
commit 961a2152b3
7 changed files with 258 additions and 14 deletions

View file

@ -73,6 +73,9 @@ namespace HeavenStudio
public event Action<double> onBeatChanged;
public event Action<RiqEntity, RiqEntity> onSectionChange;
public event Action<double> onBeatPulse;
public event Action<double> onPlay;
public event Action<double> onPause;
public event Action<double> onUnPause;
public int BeatmapEntities()
{
@ -143,9 +146,6 @@ namespace HeavenStudio
eventCaller = this.gameObject.AddComponent<EventCaller>();
eventCaller.GamesHolder = GamesHolder.transform;
eventCaller.Init();
Conductor.instance.SetBpm(120f);
Conductor.instance.SetVolume(100f);
Conductor.instance.firstBeatOffset = Beatmap.data.offset;
// note: serialize this shit in the inspector //
GameObject textbox = Instantiate(Resources.Load<GameObject>("Prefabs/Common/Textbox"));
@ -177,6 +177,9 @@ namespace HeavenStudio
}
SortEventsList();
Conductor.instance.SetBpm(Beatmap.TempoChanges[0]["tempo"]);
Conductor.instance.SetVolume(Beatmap.VolumeChanges[0]["volume"]);
Conductor.instance.firstBeatOffset = Beatmap.data.offset;
if (Beatmap.Entities.Count >= 1)
{
@ -231,6 +234,7 @@ namespace HeavenStudio
public void NewRemix()
{
Debug.Log("Creating new remix");
AudioLoadDone = false;
Beatmap = new("1", "HeavenStudio");
Beatmap.data.properties = Minigames.propertiesModel;
@ -238,7 +242,6 @@ namespace HeavenStudio
Beatmap.AddNewVolumeChange(0, 100f);
Beatmap.data.offset = 0f;
Conductor.instance.musicSource.clip = null;
RiqFileHandler.UnlockCache();
RiqFileHandler.WriteRiq(Beatmap);
AudioLoadDone = true;
}
@ -680,6 +683,11 @@ namespace HeavenStudio
Minigame miniGame = currentGameO?.GetComponent<Minigame>();
if (miniGame != null)
miniGame.OnPlay(beat);
onPlay?.Invoke(beat);
}
else
{
onUnPause?.Invoke(beat);
}
if (playMode)
@ -693,17 +701,21 @@ namespace HeavenStudio
public void Pause()
{
Conductor.instance.Pause();
// Util.SoundByte.PauseOneShots();
Util.SoundByte.PauseOneShots();
onPause?.Invoke(Conductor.instance.songPositionInBeatsAsDouble);
canInput = false;
}
public void Stop(double beat, bool restart = false, float restartDelay = 0f)
{
// I feel like I should standardize the names
SkillStarManager.instance.KillStar();
TimingAccuracyDisplay.instance.StopStarFlash();
GoForAPerfect.instance.Disable();
SectionMedalsManager.instance.OnRemixEnd(endBeat, currentSection);
if (Conductor.instance.isPlaying)
{
SkillStarManager.instance.KillStar();
TimingAccuracyDisplay.instance.StopStarFlash();
GoForAPerfect.instance.Disable();
SectionMedalsManager.instance.OnRemixEnd(endBeat, currentSection);
}
Minigame miniGame = currentGameO.GetComponent<Minigame>();
if (miniGame != null)
@ -739,22 +751,27 @@ namespace HeavenStudio
private IEnumerator WaitReadyAndPlayCo(double beat, float delay = 1f, bool discord = true)
{
WaitUntil yieldOverlays = new WaitUntil(() => OverlaysManager.OverlaysReady);
WaitUntil yieldBeatmap = new WaitUntil(() => Beatmap != null && Beatmap.Entities.Count > 0);
WaitUntil yieldBeatmap = new WaitUntil(() => Beatmap != null && BeatmapEntities() > 0);
WaitUntil yieldAudio = new WaitUntil(() => AudioLoadDone || (ChartLoadError && !GlobalGameManager.IsShowingDialog));
WaitUntil yieldGame = null;
List<Minigames.Minigame> gamesToPreload = SeekAheadAndPreload(beat, 4f);
Debug.Log($"Preloading {gamesToPreload.Count} games");
if (gamesToPreload.Count > 0)
{
yieldGame = new WaitUntil(() => gamesToPreload.All(x => x.AssetsLoaded));
}
// wait for overlays to be ready
Debug.Log("waiting for overlays");
yield return yieldOverlays;
// wait for beatmap to be loaded
Debug.Log("waiting for beatmap");
yield return yieldBeatmap;
//wait for audio clip to be loaded
Debug.Log("waiting for audio");
yield return yieldAudio;
//wait for games to be loaded
Debug.Log("waiting for minigames");
if (yieldGame != null)
yield return yieldGame;

View file

@ -414,7 +414,6 @@ namespace HeavenStudio.Editor
{
try
{
RiqFileHandler.UnlockCache();
RiqFileHandler.WriteRiq(GameManager.instance.Beatmap);
RiqFileHandler.PackRiq(path, true);
Debug.Log("Packed RIQ successfully!");
@ -465,7 +464,6 @@ namespace HeavenStudio.Editor
try
{
RiqFileHandler.UnlockCache();
string tmpDir = RiqFileHandler.ExtractRiq(path);
Debug.Log("Imported RIQ successfully!");
LoadRemix();

View file

@ -4,6 +4,7 @@ using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;
using DG.Tweening;
using HeavenStudio.Util;
@ -32,6 +33,7 @@ namespace HeavenStudio
public static void InitPreprocessor()
{
RiqBeatmap.OnUpdateBeatmap += PreProcessBeatmap;
RiqFileHandler.AudioConverter = JukeboxAudioConverter;
}
public static Dictionary<string, object> propertiesModel = new()
@ -142,6 +144,35 @@ namespace HeavenStudio
}
}
public static string JukeboxAudioConverter(string filePath, AudioType audioType, string specificType)
{
if (audioType == AudioType.MPEG)
{
Debug.Log($"mp3 loaded, Converting {filePath} to wav...");
// convert mp3 to wav
// import the mp3 as an audioclip
string url = "file://" + filePath;
using (var www = UnityWebRequestMultimedia.GetAudioClip(url, audioType))
{
www.SendWebRequest();
while (!www.isDone) { }
if (www.result == UnityWebRequest.Result.ConnectionError)
{
Debug.LogError($"Could not load audio file {filePath}! Error: {www.error}");
return filePath;
}
AudioClip clip = DownloadHandlerAudioClip.GetContent(www);
string fileName = Path.GetFileNameWithoutExtension(filePath);
Debug.Log(fileName);
SavWav.Save("/RIQCache/" + fileName, clip, true);
filePath = Path.Combine(Application.temporaryCachePath, "/RIQCache/" + fileName + ".wav");
clip = null;
}
}
return filePath;
}
/// <summary>
/// processes an riq beatmap after it is loaded
/// </summary>

View file

@ -82,7 +82,7 @@ namespace HeavenStudio.Common
public void OnRemixEnd(double beat, RiqEntity lastSection)
{
if (!PersistentDataManager.gameSettings.isMedalOn) return;
if (PersistentDataManager.gameSettings.isMedalOn && isMedalsStarted)
if (PersistentDataManager.gameSettings.isMedalOn && isMedalsStarted && lastSection != null)
{
GameManager.instance.DoSectionCompletion(beat, isMedalsEligible, lastSection["sectionName"], 1);
GameObject medal = Instantiate(isMedalsEligible ? MedalOkPrefab : MedalMissPrefab, MedalsHolder.transform);

View file

@ -0,0 +1,187 @@
// Copyright (c) 2012 Calvin Rien
// http://the.darktable.com
//
// This software is provided 'as-is', without any express or implied warranty. In
// no event will the authors be held liable for any damages arising from the use
// of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not claim
// that you wrote the original software. If you use this software in a product,
// an acknowledgment in the product documentation would be appreciated but is not
// required.
//
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
// =============================================================================
//
// derived from Gregorio Zanon's script
// http://forum.unity3d.com/threads/119295-Writing-AudioListener.GetOutputData-to-wav-problem?p=806734&viewfull=1#post806734
//
// Fork by R-WebsterNoble
// Optimized! Now 20 times quicker
// Easy to get byte[] instead of saving file
// Note: GetWav() with trimming returns the full buffer with a load of zeros on the end.
// Use the length out parameter to know where the data stops.
//
// RHeavenStudio
// modified to use temporary cache path instead of persistent data path
using System;
using System.IO;
using System.Text;
using UnityEngine;
public static class SavWav
{
private const uint HeaderSize = 44;
private const float RescaleFactor = 32767; //to convert float to Int16
public static void Save(string filename, AudioClip clip, bool trim = false)
{
if (!filename.ToLower().EndsWith(".wav"))
{
filename += ".wav";
}
var filepath = Path.Combine(Application.temporaryCachePath, filename);
// Make sure directory exists if user is saving to sub dir.
if (!Directory.Exists(Path.GetDirectoryName(filepath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(filepath));
}
using (var fileStream = new FileStream(filepath, FileMode.Create))
using (var writer = new BinaryWriter(fileStream))
{
var wav = GetWav(clip, out var length, trim);
writer.Write(wav, 0, (int)length);
}
}
public static byte[] GetWav(AudioClip clip, out uint length, bool trim = false)
{
var data = ConvertAndWrite(clip, out length, out var samples, trim);
WriteHeader(data, clip, length, samples);
return data;
}
private static byte[] ConvertAndWrite(AudioClip clip, out uint length, out uint samplesAfterTrimming, bool trim)
{
var samples = new float[clip.samples * clip.channels];
clip.GetData(samples, 0);
var sampleCount = samples.Length;
var start = 0;
var end = sampleCount - 1;
if (trim)
{
for (var i = 0; i < sampleCount; i++)
{
if ((short)(samples[i] * RescaleFactor) == 0)
continue;
start = i;
break;
}
for (var i = sampleCount -1; i >= 0; i--)
{
if ((short)(samples[i] * RescaleFactor) == 0)
continue;
end = i;
break;
}
}
var buffer = new byte[(sampleCount * 2) + HeaderSize];
var p = HeaderSize;
for (var i = start; i <= end; i++)
{
var value = (short) (samples[i] * RescaleFactor);
buffer[p++] = (byte) (value >> 0);
buffer[p++] = (byte) (value >> 8);
}
length = p;
samplesAfterTrimming = (uint) (end - start + 1);
return buffer;
}
private static void AddDataToBuffer(byte[] buffer, ref uint offset, byte[] addBytes)
{
foreach (var b in addBytes)
{
buffer[offset++] = b;
}
}
private static void WriteHeader(byte[] stream, AudioClip clip, uint length, uint samples)
{
var hz = (uint)clip.frequency;
var channels = (ushort)clip.channels;
var offset = 0u;
var riff = Encoding.UTF8.GetBytes("RIFF");
AddDataToBuffer(stream, ref offset, riff);
var chunkSize = BitConverter.GetBytes(length - 8);
AddDataToBuffer(stream, ref offset, chunkSize);
var wave = Encoding.UTF8.GetBytes("WAVE");
AddDataToBuffer(stream, ref offset, wave);
var fmt = Encoding.UTF8.GetBytes("fmt ");
AddDataToBuffer(stream, ref offset, fmt);
var subChunk1 = BitConverter.GetBytes(16u);
AddDataToBuffer(stream, ref offset, subChunk1);
const ushort two = 2;
const ushort one = 1;
var audioFormat = BitConverter.GetBytes(one);
AddDataToBuffer(stream, ref offset, audioFormat);
var numChannels = BitConverter.GetBytes(channels);
AddDataToBuffer(stream, ref offset, numChannels);
var sampleRate = BitConverter.GetBytes(hz);
AddDataToBuffer(stream, ref offset, sampleRate);
var byteRate = BitConverter.GetBytes(hz * channels * 2); // sampleRate * bytesPerSample*number of channels, here 44100*2*2
AddDataToBuffer(stream, ref offset, byteRate);
var blockAlign = (ushort)(channels * 2);
AddDataToBuffer(stream, ref offset, BitConverter.GetBytes(blockAlign));
ushort bps = 16;
var bitsPerSample = BitConverter.GetBytes(bps);
AddDataToBuffer(stream, ref offset, bitsPerSample);
var dataString = Encoding.UTF8.GetBytes("data");
AddDataToBuffer(stream, ref offset, dataString);
var subChunk2 = BitConverter.GetBytes(samples * 2);
AddDataToBuffer(stream, ref offset, subChunk2);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5a24cd489c15c51408c78bb5c145360e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -22,7 +22,7 @@
"com.unity.nuget.newtonsoft-json": "3.2.1",
"jillejr.newtonsoft.json-for-unity.converters": "1.5.1"
},
"hash": "33fa051b5a6954a365df23038085caca9a844cab"
"hash": "4628637dd95ff16553a55e0cdb08f6c4fbce2906"
},
"com.sr4dev.unity-spriteassist": {
"version": "https://github.com/sr4dev/Unity-SpriteAssist.git?path=Assets/SpriteAssist",