• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
3
Question by Leos924 · Aug 02, 2015 at 08:51 PM · soundaudioclipencodingbytearrayexternal-libraries

Audioclip error using NAudio to open MP3 file on Windows

I'm using the NAudio libraries to open an MP3 file from the HardDrive, convert the byte array returned to a float array and then create an audioclip to set it to an AudioSource because i created a visualizer and i need the audio coming from inside Unity not from the SoundCard, well the problem is that i only hear strange sounds maybe because of the structure of the final audioclip but i doesn't find where the problem is or even how to identify it because i don't know too much how the sound files work, so please someone help me to fix this issue. Also, sorry if i comitted too much language errors but my mother language is spanish

 using UnityEngine;
 using System.Collections;
 using NAudio;
 using NAudio.Wave;
 using System.IO;
 using NAudio.MediaFoundation;
 
 public class AbrirMP3 : MonoBehaviour {
     
     private IWavePlayer mWaveOutDevice;
     private WaveStream mMainOutputStream;
     private WaveChannel32 mVolumeStream;
     public GameObject Spectrum;
     public int position = 0;
     public int samplerate = 44100;
     public float frequency = 440;
     public AudioSource source1;
     public int SamplesArrayFloat;
     // Use this for initialization
     void Start () {
     }
 
     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;
     }
 
     public static float[] ConvertByteToFloat(byte[] array) {
         float[] floatArr = new float[array.Length / 4];
         for (int i = 0; i < floatArr.Length; i++) {
             if (System.BitConverter.IsLittleEndian) {
                 System.Array.Reverse(array, i * 4, 4);
             }
             floatArr[i] = System.BitConverter.ToSingle(array, i * 4);
         }
         return floatArr;
     }
     
     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("file://" + ofd.FileName);
             Debug.Log("path = " + 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;
             }
             source1.Stop();
             float[] f = ConvertByteToFloat(imageData);
             SamplesArrayFloat = f.Length;
             AudioClip audioClip = AudioClip.Create("testSound", f.Length, 1, 44100, false, OnAudioRead, OnAudioSetPosition);
             audioClip.SetData(f, 0);
             source1.clip = audioClip;
             source1.Play();
 
             Resources.UnloadUnusedAssets();
         }
     }
 
     void OnAudioRead(float[] data) {
         int count = 0;
         while (count < data.Length) {
             data[count] = Mathf.Sign(Mathf.Sin(2 * Mathf.PI * frequency * position / samplerate));
             position++;
             count++;
         }
     }
     void OnAudioSetPosition(int newPosition) {
         position = newPosition;
     }
 
     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;
         }
     }
 
 
     // Update is called once per frame
     void Update () {
     
         }
     }

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
5
Best Answer

Answer by C.IV · Jan 18, 2016 at 05:43 PM

Old question, but as it took me two days to hammer out the answer I figure it deserves one. With the "latest" version of NAudio.dll and NAudio.WindowsMediaFormat.dll inserted into your Resources folder utilize this code to do what you described:

 var musicInput : GameObject;
 private var aud : AudioFileReader;
 private var craftClip : AudioClip;
 private var AudioData : float[];
 private var readBuffer : float[];
 private var soundSystem : AudioSource;
 private var musicPath : String[];

 //Check if there's a pref set for the music path. Use it AND add all the files from it
 function CheckMusic()
 {
     var pathname = musicInput.GetComponent.<InputField>();
         if(PlayerPrefs.HasKey("musicpath") == false)
             {
                 PlayerPrefs.SetString("musicpath", "Enter Music Directory");
             }
             else
                 {
                     pathname.text = PlayerPrefs.GetString("musicpath");
                     musicPath = Directory.GetFiles(PlayerPrefs.GetString("musicpath"),"*.mp3");
                 }
     
 }
 
 function LoadSong(songToPlay : int)
 {
     //Download the song via WWW
     var currentSong : WWW = new WWW(musicPath[songToPlay]);
     
     //Wait for the song to download
     if(currentSong.error == null)
         {
             //Set the title of the song
             playingSong.text = Path.GetFileNameWithoutExtension(musicPath[songToPlay]);
             //Parse the file with NAudio
             aud = new AudioFileReader(musicPath[songToPlay]);
             
             //Create an empty float to fill with song data
             AudioData = new float[aud.Length];
             //Read the file and fill the float
             aud.Read(AudioData, 0, aud.Length);
             
             //Create a clip file the size needed to collect the sound data
             craftClip = AudioClip.Create(Path.GetFileNameWithoutExtension(musicPath[songToPlay]),aud.Length,aud.WaveFormat.Channels,aud.WaveFormat.SampleRate, false);
             //Fill the file with the sound data
             craftClip.SetData(AudioData,0);
             //Set the file as the current active sound clip
             soundSystem.clip = craftClip;
         }
 }

The "songToPlay" variable that is passed to the function is a simple int that is acquired from the array created under the CheckMusic function. I search a chosen directory entered from a GUI Inputfield for a specific file type (MP3) which can be changed to WAV or OGG and then input those files to an array. Other code chooses the number of the song on the array to play and you can change that to anything you like. The important part is that the NAudio,dll does all the heavy lifting. All you need to do is use the aud.Read(float[] to send data to, song starting point(usually 0),length of song data (aud.length). The Float[] here is the same length as aud.length so create the float of the same length, read the file, fill the float, create the clip, then dump the float data in with AudioClip.SetData()

Right now this code works and it does the job. Downside is it takes 2-3 seconds to fill the float in this way and is a noticeable drag. It also tends to chew up memory pretty fast, but it gets the job done. Hope it helps as a starting point for those who are looking to do this. I know I needed it.

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image jister · Apr 22, 2016 at 12:10 PM 0
Share

Using your code i keep getting this error... DllNotFoundException: $$anonymous$$sacm32.dll NAudio.Wave.Compression.AcmStream.SuggestPcmFormat (NAudio.Wave.WaveFormat compressedFormat) NAudio.Wave.Acm$$anonymous$$p3FrameDecompressor..ctor (NAudio.Wave.WaveFormat sourceFormat) NAudio.Wave.$$anonymous$$p3FileReader.CreateAcmFrameDecompressor (NAudio.Wave.WaveFormat mp3Format) NAudio.Wave.$$anonymous$$p3FileReader..ctor (System.IO.Stream inputStream, NAudio.Wave.FrameDecompressorBuilder frameDecompressorBuilder)

avatar image jister jister · Apr 22, 2016 at 01:59 PM 0
Share

ok i'm osx, seems NAudio is windows only :-(

avatar image twobob · Mar 13, 2017 at 01:08 AM 0
Share

mirrored on http://stackoverflow.com to help another

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.



Follow this Question

Answers Answers and Comments

25 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Is OnAudioFilterRead Still the Preferred Method for Procedural Audio? 0 Answers

About Array to AudioClip 0 Answers

A method for streaming custom audio from the hard drive 0 Answers

how to make multiple sound augmented reality in 1 scene UNITY? 0 Answers

AudioClip.GetData returns only 0s 3 Answers

  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges