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
Hi Denis,
ReplyDeleteThanks so much for the awesome tutorial and code.
I have the file browser working, and the MP3s loading, but my game I'm making depends on an audio source playing the MP3 through it's audio clip. I feel like I'm so close to getting this to work.
I tried different variations of audio.clip = www.audioClip; and audio.clip = www.GetAudioClip(); in void LoadAudio(), but to no avail. The script is attached to an audiosource.
Can you help?
Sincerely,
Jonathan
Hi Jonathan,
DeleteAs far as i remember, Unity3d WWW.audioClip supports only Ogg files. MP3 files are not supported via WWW class.
You can read about this here:
http://docs.unity3d.com/Documentation/ScriptReference/WWW-audioClip.html
http://docs.unity3d.com/Documentation/Manual/AudioFiles.html
So, for loading MP3 files i created such tutorial. But this tutorial uses external *.dll file (from NAudio library), and its works on PC and standalone, but Unity3d WebPlayer doesn't supports external *.dll plugins.
But i think there is a solution for you - it is use not NAudio *.dll file, but embed the source code of NAudio to you project. Since NAudio is a free and open source library, you can download the source code and embed it to your project.
So, the solution for you:
- Download the source code of NAudio from here: http://naudio.codeplex.com/releases/view/96875;
- Embed it to your project;
- Compile it, and create Unity3d WebPlayer build;
- Thats all :)
If you have any questions, please ask me. Also, please tell me about your results. If this solution is not working for some reason, also please tell me.
Best regards,
Denis
First, thanks for the detailed and quick response, I really appreciate it!
ReplyDeleteI should have been a bit more clear though, my bad. I actually don't need anything to work in the unity web player, my game will be standalone. What I need is, using your AppRoot code from the tutorial, to take the Mp3 file the user selects, and have an Audio Source in Unity play that mp3.
Right now, I'm using your source code to load an mp3 through the file browser, and that works great, but unfortunately like I said I need the audio source specifically to play it.
Theoretically it sounds easy. But I've tried to get the audio.clip to load the mp3 the user selects in multiple ways, but I can't figure it out.
I tried looking around in the NAudio source code like you said, and embedding it in my project, but that just produced errors. I may not have been doing it right.
I'm not much of a programmer, and I've never really worked in unity before this, so you might have to dumb it down a bit for me. Sorry for the inconvenience, and thanks again for the help.
Sincerely,
Jonathan
Jonathan,
DeletePlease tell me, why do you need AudioSource object?
Best regards,
Denis
I'm using this program - http://u3d.as/content/altered-reality-entertainment/visualizer-studio/2dq
DeleteIt manipulates object properties according to music, and it takes the music data from an audio source. I don't know if it's capable of getting data from another source, but right now it only lets me select audio sources. Screenshot - http://i.imgur.com/3zjJUBV.png
Jonathan,
DeleteI see. Unfortunately, the way presented in this article is custom solution for playing audio Unity3d. But, if you already bought this asset, you may just to inform developers of the asset, that you want to play music from custom audio source. I think they know the solution, because AudioSource for developers is only the way the get the audio data. And i think this is not the single way to do it :)
Best regards,
Denis
Ok, thanks for the advice, I contacted the developers! Once again thanks for your help.
DeleteSincerely,
Jonathan
doesnt work mp3 files in unity 3d
ReplyDeleteYes, so please use my example to resolve this issue :)
DeleteHi Denis !
ReplyDeleteFirst of all, thank you a lot for your tutorials ! Unfortunately, the way i want to select the mp3 files is a bit different than yours and i can't success to adapt your code. What i want is the files loading during the launching time of the application without any selection in a Browser . After loading, stock them all in an array ( or list , etc .. ) in order to assign them to different AudioSources ..
Can you help me ?
Thank youuu
Nathan
Hello Nathan,
DeleteYou cannot create AudioSource and set the loaded audio file for it in real time in Unity3d. That is why I showed how to play audio, without actually creating audio source. That is what Unity3d supports now. Perhaps in future, this feature will be implemented.
Regards,
Denis
This comment has been removed by the author.
ReplyDeleteHi Denis,
ReplyDeleteCould you try running this same code using an .m4a file and reporting your results? Naudio is supposed to support m4a files through MediaFoundation - this works fine in their demo apps but crashes within unity.
Thanks!
Hello Martin,
DeleteI am sorry, but now, I have not time for this :(
Hello and thanks for the tutorial!
ReplyDeleteWhat I have done is, converting the mp3 file to wav in real time before playing, extract the mp3 tag and use the audioclip/audiosource with the wav file. This way I can use the best of both methods.
Greetings!
Hello Robert,
DeleteI will try to help but always have not a lot of time for this. Also we used another .NET library to process the mp3 files. So this plugin can be embedded to the WebBuild!
Regards,
Denis
Hello, could you please share code, how you convert mp3 to wav at runtime?
Deletei'm look close to goal
ReplyDeleteany way to add loading mp3 in list please ?
Hello Kilik,
Deletedo you mean to load a lot of mp3 files? Or something else?
i have buy little asset for do this job
Deletebut i need help for my projet it's simple mix audio and save
is you can help i can share it
Just use the similar code to create several streams.
DeleteHello thanks for the tutorial, LoadAudioFromData(byte[] data) method throws exception: Error! Msacm32.dll.
ReplyDeleteHello Jakhongir,
DeletePlease share your project with me, and I will help you!
This comment has been removed by the author.
ReplyDeleteAlso I get this:
ReplyDeleteDllNotFoundException: Msacm32.dll
NAudio.Wave.Compression.AcmStream.SuggestPcmFormat (NAudio.Wave.WaveFormat compressedFormat)
NAudio.Wave.AcmMp3FrameDecompressor..ctor (NAudio.Wave.WaveFormat sourceFormat)
NAudio.Wave.Mp3FileReader.CreateAcmFrameDecompressor (NAudio.Wave.WaveFormat mp3Format)
NAudio.Wave.Mp3FileReader..ctor (System.IO.Stream inputStream, NAudio.Wave.FrameDecompressorBuilder frameDecompressorBuilder)
Hello Jakhongir,
DeletePlease share your project with me, and I will help you! Thank you in advance
wow. awesome! thank you!
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteSorry if there was already an answer for this but skimming through I did not see if anyone had asked but will this work on a Mac in Unity 5 & up?
ReplyDeleteHello Michael,
DeleteIts ok :) I just checked in Unity3d 5.2.0f3 - everything works fine!
This comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteIm getting
ReplyDelete`MemoryStream' could not be found. Are you missing a using directive or an assembly reference? error
Please use sources to build the project and proper Unity3d version
DeleteHave you found, how to decide error DllNotFoundException: Msacm32.dll on Mac?
ReplyDeleteNope. This code is only for windows
Deleteit ALWAYS says
ReplyDeleteError! Invalid MP3 file - no MP3 Frames Detected
UnityEngine.Debug:LogWarning(Object)
Testmp3:LoadAudioFromData(Byte[]) (at Assets/Testmp3.cs:37)
Testmp3:LoadAudio() (at Assets/Testmp3.cs:72)
Testmp3:prova() (at Assets/Testmp3.cs:43)
UnityEngine.EventSystems.EventSystem:Update()
NOT WORK......
and the variable cLocalPath is NEVER declared -.-
DeletePlease download sources. In article presented only part of them
DeleteI cannot wait to dig deep and kickoff utilizing resources that I received from you. Your exuberance is refreshing. BTS Boy With Luv Dance Practice RM mp3 download
ReplyDeletePretty good post. I have just stumbled upon your blog and enjoyed reading your blog posts very much. I am looking for new posts to get more precious info. Big thanks for the useful info. sbunoah ewe getsemane live mp3 download
ReplyDeleteLatest Music Download 2020
ReplyDeleteI will provide white hat contextual seo dofollow high quality backlinks
ReplyDelete5.0(9)
African News Today
USA News Today
entertainment
sports
Download Movies
Relationship