Practical use of Unity3d engine.
Task #6: Loading MP3 audio via WWW class in Unity3d
Let’s solve the task: Application should implement mp3 audio loading from file system via WWW class in Unity3d.
Since Unity3d doesn’t support mp3 audio loading via WWW class for windows, we will load mp3 binary data via class WWW and pass binary data to NAudio library. NAudio library is free, and able to play mp3 audio from binary data (read more here: http://naudio.codeplex.com/).
At first, download NAudio library, and copy NAudio.dll and NAudio.WindowsMediaFormat.dll files to Assets folder.
Then, enable full .NET Framework version in Unity3d. To do this choose menu item «File/Build Settings/Player Settings/Other Settings/Optimization/Api Compatibility Level», and set «.NET 2.0» parameter.
On fig.1 you can see process of choosing full .NET Framework.
Figure 1. – Choose full .NET Framework implementation
Let’s start to write scripts. At first, check that NAudio library is already attached to project. To do this, expand «References» section in project and check existing of NAudio libraries. If they are not attached, attach them. «References» section is shown on fig. 2.
Figure 2. – «References» section
Now, add using statements.
using NAudio; using NAudio.Wave;
Create class variables.
private IWavePlayer mWaveOutDevice; private WaveStream mMainOutputStream; private WaveChannel32 mVolumeStream;
Create function that wills load audio from bytes array.
private bool LoadAudioFromData(byte[] data)
{
try
{
MemoryStream tmpStr = new MemoryStream(data);
mMainOutputStream = new Mp3FileReader(tmpStr);
mVolumeStream = new WaveChannel32(mMainOutputStream);
mWaveOutDevice = new WaveOut();
mWaveOutDevice.Init(mVolumeStream);
return true;
}
catch (System.Exception ex)
{
Debug.LogWarning("Error! " + ex.Message);
}
return false;
}
The algorithm of the function is:
- Create instance of the «MemoryStream» class;
- Since we will load audio in mp3 format, create instance of the «Mp3FileReader» class;
- Create instance of the «WaveChannel32» class;
- At last, create instance of the «WaveOut» class to play audio;
Create «LoadAudio» function.
private void LoadAudio()
{
System.Windows.Forms.OpenFileDialog ofd = new System.Windows.Forms.OpenFileDialog();
ofd.Title = "Open audio file";
ofd.Filter = "MP3 audio (*.mp3) | *.mp3";
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
WWW www = new WWW(cLocalPath + ofd.FileName);
Debug.Log("path = " + cLocalPath + ofd.FileName);
while (!www.isDone) { };
if (!string.IsNullOrEmpty(www.error))
{
System.Windows.Forms.MessageBox.Show("Error! Cannot open file: " + ofd.FileName + "; " + www.error);
return;
}
byte[] imageData = www.bytes;
if (!LoadAudioFromData(imageData))
{
System.Windows.Forms.MessageBox.Show("Cannot open mp3 file!");
return;
}
mWaveOutDevice.Play();
Resources.UnloadUnusedAssets();
}
}
The algorithm of the function is:
- Show «OpenFileDialog» to user. Set filters to mp3 files;
- Load mp3 binary data via WWW class;
- Pass loaded data to «LoadAudioFromData» function. If function returns true – play audio;
To unload audio from memory, create «UnloadAudio» function.
private void UnloadAudio()
{
if (mWaveOutDevice != null)
{
mWaveOutDevice.Stop();
}
if (mMainOutputStream != null)
{
// this one really closes the file and ACM conversion
mVolumeStream.Close();
mVolumeStream = null;
// this one does the metering stream
mMainOutputStream.Close();
mMainOutputStream = null;
}
if (mWaveOutDevice != null)
{
mWaveOutDevice.Dispose();
mWaveOutDevice = null;
}
}
The algorithm of the function is: - Stop playing audio;
- Close «WaveChannel32» and «WaveStream»;
- Free memory for instance of the «IWavePlayer» class;
That's all. Also, there is a good example of loading mp3 audio by means of NAudio library, you can see here: http://naudio.codeplex.com/wikipage?title=MP3. If you need more detailed article description, please write it in comments.
Demo of the application you can download here: https://dl.dropboxusercontent.com/u/20023505/Articles/Unity3d/Lesson6/Builds/Builds.zip
Free source codes you can download here:
https://dl.dropboxusercontent.com/u/20023505/Articles/Unity3d/Lesson6/Sources/Source.zip
https://github.com/den-potapenko/Unity3dArticles/tree/master/Lesson6