2013-10-13 72 views
2

我正在使用名爲Visualizer Studio的軟件包(http://www.alteredr.com/visualizer-studio/)製作一個遊戲,讓對象對音樂做出反應。我的目標是讓用戶能夠在遊戲過程中隨時加載歌曲。這將是獨立/ PC,而不是WebPlayer。在Unity中通過音頻源播放NAudio.mp3

我的問題是Visualizer Studio從場景中的音頻源獲取音頻數據。因此,當我使用NAudio加載和流式傳輸MP3時,可視化工作室聽不到它們,而我的物體對音樂沒有反應。

我現在在我的代碼中使用IWavePlayer。我嘗試添加audio.clip = www.GetAudioClip和類似的功能,讓音頻剪輯加載正在播放的音樂,但無濟於事。

我從我的博客文章(源代碼在底部)中選擇和傳輸.mp3s的代碼:(http://denis-potapenko.blogspot.com/2013/04/task-6-loading-mp3-audio-via-www-class.html)。目前它沒有變化,因爲我沒有嘗試過。

要清楚,當我從文件瀏覽器中選擇它們時,.mp3s DO會播放。我只需要他們通過我的場景中的音頻源播放。請,必須有辦法做到這一點。我已經聯繫了可視化工作室支持,並在統一論壇上提出要求,但目前還沒有人能夠提供幫助。

請記住,我不是一個偉大的程序員,所以你可能不得不爲我愚蠢的回答。感謝您提前的耐心。直接當您使用WaveOut比如,你正在玩的(相對)

using UnityEngine; 
using System.Collections; 
using System.IO; 

using System.Runtime; 
using System.Runtime.InteropServices; 

using System.Runtime.Serialization.Formatters.Binary; 
using System.Runtime.Serialization; 

using NAudio; 
using NAudio.Wave; 

public class AppRoot : MonoBehaviour 
{ 
    /////////////////////////////////////////////////////////////////////////// 
    #region Variables 

    private static AppRoot mInstance = null; 

    private const string cLocalPath = "file://localhost/"; 

    private IWavePlayer mWaveOutDevice; 
    private WaveStream mMainOutputStream; 
    private WaveChannel32 mVolumeStream; 

    #endregion 
    /////////////////////////////////////////////////////////////////////////// 

    /////////////////////////////////////////////////////////////////////////// 
    #region Interface 

    public AppRoot() 
    { 
     mInstance = this; 
    } 

    public void Start() 
    { 

    } 

    public void Update() 
    { 
     if(Input.GetKeyDown(KeyCode.F)) 
     { 
      UnloadAudio(); 
      LoadAudio(); 
     } 



    } 

    public void OnGUI() 
    { 
     if (GUI.Button(new Rect(100, Screen.height - 200 + 100, Screen.width - 200, 35), "Load audio")) 
     { 
      UnloadAudio(); 
      LoadAudio(); 
     } 
    } 

    public void OnApplicationQuit() 
    { 
     UnloadAudio(); 
    } 

    #endregion 
    /////////////////////////////////////////////////////////////////////////// 

    /////////////////////////////////////////////////////////////////////////// 
    #region Implementation 

    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(); 
     } 

    } 

    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; 
    } 

    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; 
     } 

    } 

    #endregion 
    /////////////////////////////////////////////////////////////////////////// 

    /////////////////////////////////////////////////////////////////////////// 
    #region Properties 

    private static AppRoot Instance 
    { 
     get 
     { 
      return mInstance; 
     } 
    } 

    #endregion 
    /////////////////////////////////////////////////////////////////////////// 
} 

真誠, 喬納森

+0

@Steven這當然是一個Unity相關的問題。你爲什麼刪除標籤? – Corey

+1

@Corey:不,它不是。 [Unity](http://stackoverflow.com/tags/unity/info)是一個「.NET的依賴注入容器」,但你正在談論[Unity3d](http://stackoverflow.com/tags/unity3d/info)是「創造遊戲的商業開發平臺」。 – Steven

+1

@Steve感謝您的更正,並將正確的標記添加回:) – Corey

回答

1

:反正

這裏是我的代碼,我使用的是打開一個文件瀏覽器和流音頻在聲卡上,以外的Unity環境的。您需要一種將數據引入Unity的方法。

與統一使用OnAudioFilterRead ...

您可以引入波數據到現場我沒有工作所以這可能不是最好的答案,但。您可以使用它來創建程序聲音,並且只需稍加編碼就可以將其連接到NAudio波源。這會將音頻數據直接引入遊戲中以供遊戲中的代碼處理。

這裏有一個文章,我發現可能會幫助:Procedural Audio with Unity

1
mWaveOutDevice = new WaveOut(); 

可能導致問題,這是它支持所有非GUI線程上運行更好的做法是使用WaveOutEvent()。

mWaveOutDevice = new WaveOutEvent(); 

Related StackOverFlow Question

0

http://answers.unity3d.com/answers/1128204/view.html

隨着NAudio.dll和NAudio.WindowsMediaFormat的 「最新」 版本。DLL插入到你的資源文件夾使用此代碼做你所描述的:

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; 
    } 
} 

我引用

傳遞給函數的「songToPlay」變量是從獲得一個簡單的INT在CheckMusic函數下創建的數組。我搜索從GUI輸入字段輸入的特定文件類型(MP3)所選的目錄,可以將其更改爲WAV或OGG,然後將這些文件輸入到數組中。其他代碼選擇陣列上的歌曲數量進行播放,您可以將其更改爲任何您喜歡的內容。重要的部分是NAudio,dll會完成所有繁重的工作。所有你需要做的就是使用aud.Read(float []發送數據,歌曲的起始點(通常爲0),歌曲數據的長度(aud.length),這裏的Float []與aud的長度相同。創建相同長度的浮點數,讀取文件,填充浮點數,創建剪輯,然後使用AudioClip.SetData()轉儲浮點數據。

此時此代碼可以工作,它可以完成這項工作。是否需要花費 2-3秒來填充浮球,這是一個明顯的阻礙,它也傾向於快速咀嚼記憶,但它完成了工作 希望它有助於成爲那些誰的起點我想知道我需要它