Hey all!
I’m working on an awesome editor for my rhythm-based dungeon crawler!
One of the main features is the ability to import and trim custom music then save the level with that music in the save file. So far you can import and trim the music and it plays and loops properly, but I can’t seem to find an easy way to export an mp3 file from an AudioClip.
The closest I came was a script that converts an audioclip from a wav to and mp3 then saves it, but when I try that with an mp3 the end gets cut off.
EncodeMp3.cs
/* GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
*/
/*---------------------- BeatUp (C) 2016-------------------- */
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System;
using NAudio.Wave;
using NAudio.Lame;
public static class EncodeMP3
{
public static void convert (AudioClip clip, string path, int bitRate)
{
if (!path.EndsWith (".mp3"))
path = path + ".mp3";
ConvertAndWrite (clip, path, bitRate);
}
// derived from Gregorio Zanon's script
private static void ConvertAndWrite (AudioClip clip, string path, int bitRate)
{
float[] samples = new float[clip.samples * clip.channels];
clip.GetData (samples, 0);
Debug.Log(samples.Length);
Int16[] intData = new Int16[samples.Length];
//converting in 2 float[] steps to Int16[], //then Int16[] to Byte[]
Byte[] bytesData = new Byte[samples.Length * 2];
//bytesData array is twice the size of
//dataSource array because a float converted in Int16 is 2 bytes.
float rescaleFactor = 32767; //to convert float to Int16
for (int i = 0; i < samples.Length; i++) {
intData[i] = (short)(samples[i] * rescaleFactor);
Byte[] byteArr = new Byte[2];
byteArr = BitConverter.GetBytes(intData[i]);
byteArr.CopyTo(bytesData, i * 2);
}
File.WriteAllBytes (path, ConvertWavToMp3 (bytesData, bitRate));
}
public static byte[] GetClipData(AudioClip _clip)
{
//Get data
float[] floatData = new float[_clip.samples * _clip.channels];
_clip.GetData(floatData, 0);
//convert to byte array
byte[] byteData = new byte[floatData.Length * 4];
Buffer.BlockCopy(floatData, 0, byteData, 0, byteData.Length);
return (byteData);
}
private static byte[] ConvertWavToMp3 (byte[] bytes, int bitRate)
{
var retMs = new MemoryStream ();
var ms = new MemoryStream (bytes);
var rdr = new RawSourceWaveStream (ms, new WaveFormat ());
var wtr = new LameMP3FileWriter (retMs, rdr.WaveFormat, bitRate);
rdr.CopyTo (wtr);
return retMs.ToArray ();
}
}
It doesn’t cut off the end if I just save the rawdata…
File.WriteAllBytes (path, GetClipData(clip));
But then it’s not compressed which defeats the purpose of an mp3 file.
If I convert it instead…
File.WriteAllBytes (path, ConvertWavToMp3 (bytesData, bitRate));
it ends up missing the very end.
I would very much like to be able to just import an mp3, edit it, and then save it as an mp3.
Any ideas?