我正在使用一个名为Visualizer Studio(http://www.alteredr.com/visualizer-studio/)的软件包来制作一个对象对音乐作出反应的游戏。我的目标是让用户能够在游戏过程中随时加载歌曲。它将是独立的/ PC,而不是WebPlayer。
我的问题是Visualizer Studio从场景中的音频源获取音频数据。因此,当我使用NAudio加载和流式传输MP3时,visualizer工作室不会听到它们,我的对象也不会对音乐作出反应。
我现在正在我的代码中使用IWavePlayer。我已经尝试添加audio.clip = www.GetAudioClip和类似功能,让音频片段加载正在播放的音乐,但无济于事。
我从这篇博客文章中获取了用于选择和流式传输.mp3s的代码(源代码位于底部):( http://denis-potapenko.blogspot.com/2013/04/task-6-loading-mp3-audio-via-www-class.html)。目前它没有改变,因为我没有尝试过任何工作。
要清楚,当我从文件浏览器中选择.mp3s时,它会播放。我只需要它们通过我的场景中的音频源播放。请,有一种方法可以做到这一点。我联系了visualizer studio支持并在团结论坛上询问过,但到目前为止还没有人可以提供帮助。
请记住,我不是一个优秀的程序员,所以你可能不得不为我愚蠢的回答。感谢您提前耐心等待。无论如何,
这是我用来打开文件浏览器和流音频的代码:
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 :(得分:1)
使用WaveOut
实例时,您(相对)直接在声卡上播放,在外部。您需要一种方法将该数据引入Unity。
我没有使用Unity,所以这可能不是最佳答案,但是...
您可以使用OnAudioFilterRead
将波浪数据引入场景。您可以使用它来创建程序性声音,并且通过一些编码,它可以被连接到NAudio波源。这将直接将音频数据引入游戏中,以便您处理游戏中的代码。
以下是我发现的可能有用的文章:Procedural Audio with Unity
答案 1 :(得分:1)
mWaveOutDevice = new WaveOut();
可能导致问题,最好使用支持在所有非GUI线程中运行的WaveOutEvent()。
mWaveOutDevice = new WaveOutEvent();
答案 2 :(得分:1)
http://answers.unity3d.com/answers/1128204/view.html
使用"最新的"插入到您的Resources文件夹中的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;
}
}
我引用
&#34; songToPlay&#34;传递给函数的变量是从CheckMusic函数下创建的数组中获取的简单int。我搜索从GUI输入字段输入的选定目录中的特定文件类型(MP3),可以将其更改为WAV或OGG,然后将这些文件输入到数组中。其他代码选择要播放的阵列上的歌曲编号,您可以将其更改为您喜欢的任何内容。重要的是NAudio,dll完成所有繁重的工作。您需要做的就是使用aud.Read(float []发送数据,歌曲起始点(通常为0),歌曲数据长度(aud.length)。这里的Float []长度与aud相同。 length所以创建相同长度的浮点数,读取文件,填充浮点数,创建剪辑,然后使用AudioClip.SetData()
转储浮点数据现在这段代码可以正常运行。缺点是它需要 用这种方式填充浮子需要2-3秒,这是一个明显的阻力。它 也倾向于快速咀嚼内存,但它完成了工作。 希望它有助于作为那些希望做的人的起点 这个。我知道我需要它。