Music player - (load sound files at runtime from directory, and play them)

Hi guys, i’ve made this music player, the songs are added from unity editor, how can i do for create a directory folder, so that the songs that must be reproduced are taken from there?

#pragma strict


var CurrentSong : AudioClip = null;
var SongList : AudioClip[];
var gSkin : GUISkin;
var SongName : String;
var Music : AudioSource;
//per usare lo stex input!
var on : boolean; 
 
var SongNumber : int = 10;

var showGUI : boolean = false;


//Volume Audio 
 var hSliderValue : float = 0.0;
 
 
function Start(){

    
    CurrentSong = SongList[SongNumber];
    Music = gameObject.GetComponent(AudioSource);
    Music.loop = false;
    Music.playOnAwake = false;
    Music.clip = CurrentSong;
    Music.volume = 2;
 
audio.Play();
 
NextSong();

}

function Update () {


//Volume Audio 
audio.volume = hSliderValue; 
 
SongName = CurrentSong.name;
 
Music = gameObject.GetComponent(AudioSource);
Music.clip = CurrentSong;
 


if (SongNumber > SongList.length - 1)
{
    SongNumber = 0;
}
if (SongNumber < 0)
{
    SongNumber = SongList.length - 1;
}

}





function OnMouseDown () {
    if (Input.GetMouseButton){
    
    //Per usare lo stex Input!
    on= !on;
    
    if (!on) {
    showGUI = true;
    }
    if (on) {
    showGUI = false;
       
}
}
}



 
function OnGUI(){

if(showGUI){



GUI.skin = gSkin;
 
GUI.Box(Rect(10, Screen.height-125, 420, 130), SongName);


//Volume Audio
hSliderValue = GUI.HorizontalSlider (Rect (180, Screen.height-28, 180, 100), hSliderValue, 0.0, 1.0);

 
if(GUI.Button(Rect(30, Screen.height-41, 40, 40), "<<")){
    SongNumber -= 1;
    CurrentSong = SongList[SongNumber];
    Wait();
}
 
if(audio.isPlaying){
    if(GUI.Button(Rect(75, Screen.height-41, 40, 40), "||")){
       audio.Pause();
    }
}
 
if(!audio.isPlaying){
    if(GUI.Button(Rect(75, Screen.height-41, 40, 40), ">")){
       audio.Play();
    }
}
 
if(GUI.Button(Rect(120, Screen.height-41, 40, 40), ">>")){
    SongNumber += 1;
    CurrentSong = SongList[SongNumber];
    Wait();
}
 
}
}
 
function Wait(){
yield WaitForSeconds(0.05);
audio.Play();
 
}
 
function NextSong(){
yield WaitForSeconds (audio.clip.length);
    SongNumber += 1;
    CurrentSong = SongList[SongNumber];
    Wait();
}

Apologies for the delay, I hit a brick wall dealing with WWW - as this is my first time I use this class, I didn’t know that I had to provide the FULL path to a file for it to load it successfully.

The code is taken from here, with some modifications.

Just attach this to some gameObject, and have your music files in your Asset folder (at edit-time) or the game folder (when you build).

It’s in C#, if you have trouble translating to JS let me know.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;

public class MusicPlayer : MonoBehaviour
{
    public enum SeekDirection { Forward, Backward }

    public AudioSource source;
    public List<AudioClip> clips = new List<AudioClip>();

    [SerializeField] [HideInInspector] private int currentIndex = 0;

    private FileInfo[] soundFiles;
    private List<string> validExtensions = new List<string> { ".ogg", ".wav" }; // Don't forget the "." i.e. "ogg" won't work - cause Path.GetExtension(filePath) will return .ext, not just ext.
    private string absolutePath = "./"; // relative path to where the app is running - change this to "./music" in your case

    void Start()
    {
        //being able to test in unity
        if (Application.isEditor) absolutePath = "Assets/";

        if (source == null) source = gameObject.AddComponent<AudioSource>();

        ReloadSounds();
    }

    void OnGUI()
    {
        if (GUILayout.Button("Previous")) {
            Seek(SeekDirection.Backward);
            PlayCurrent();
        }
        if (GUILayout.Button("Play current")) {
            PlayCurrent();
        }
        if (GUILayout.Button("Next")) {
            Seek(SeekDirection.Forward);
            PlayCurrent();
        }
        if (GUILayout.Button("Reload")) {
            ReloadSounds();
        }
    }

    void Seek(SeekDirection d)
    {
        if (d == SeekDirection.Forward)
            currentIndex = (currentIndex + 1) % clips.Count;
        else {
            currentIndex--;
            if (currentIndex < 0) currentIndex = clips.Count - 1;
        }
    }

    void PlayCurrent()
    {
        source.clip = clips[currentIndex];
        source.Play();
    }

    void ReloadSounds()
    {
        clips.Clear();

        // get all valid files
        var info = new DirectoryInfo(absolutePath);
        soundFiles = info.GetFiles()
            .Where(f => IsValidFileType(f.Name))
            .ToArray();

        // and load them
        foreach (var s in soundFiles)
            StartCoroutine(LoadFile(s.FullName));
    }

    bool IsValidFileType(string fileName)
    {
        return validExtensions.Contains(Path.GetExtension(fileName));
        // Alternatively, you could go fileName.SubString(fileName.LastIndexOf('.') + 1); that way you don't need the '.' when you add your extensions
    }

    IEnumerator LoadFile(string path)
    {
        WWW www = new WWW("file://" + path);
        print("loading " + path);

        AudioClip clip = www.GetAudioClip(false);
        while(!clip.isReadyToPlay)
            yield return www;

        print("done loading");
        clip.name = Path.GetFileName(path);
        clips.Add(clip);
    }
}

Couple of notes:

  1. You might ask, why use create a
    DirectoryInfo and then call
    GetFiles on that, instead of just
    directly go
    Directory.GetFiles(path)? Well,
    the latter one will return the paths
    of the files in path, relative
    to
    path and NOT the full path
    (which is what you’ll need to pass
    into WWW). i.e. if you do
    Directory.GetFiles("Assets"); it
    will return, (for example) a string
    array of { “Assets/soundFile1.wav”,
    “Assets/soundFile2.ogg”, etc } -
    these paths are relative to “Assets”
    while the full path would be “E:\Dropbox\UnityStuff\MyProject.…\soundFile.wav”
  2. MP3s won’t work in a PC build (haven’t tried wav, but it should work) see this for more info. If you want MP3s, you have to go for something more complex, like MP3Sharp, NAudio and others.
  3. If you want to search recursively, change your GetFiles() call to GetFiles("*.*", SearchOption.AllDirectories)

EDIT:

JS, as per your request

import UnityEngine;
import System.Collections.Generic;
import System.IO;
import System.Linq;

public enum SeekDirection { Forward, Backward }

public var source : AudioSource;
public var clips : List.<AudioClip> = new List.<AudioClip>();

@HideInInspector @SerializeField private var currentIndex : int = 0;

private var soundFiles : FileInfo[];
private var validExtensions : List.<String> = new List.<String> ([ ".ogg", ".wav" ]);
private var absolutePath : String = "./"; // relative path to where the app is running

function Start()
{
	//being able to test in unity
	if (Application.isEditor)
		absolutePath = "Assets/";

	if (source == null)
		source = gameObject.AddComponent.<AudioSource>();

	ReloadSounds();
}

function OnGUI()
{
	if (GUILayout.Button("Previous")) {
		Seek(SeekDirection.Backward);
		PlayCurrent();
	}
	if (GUILayout.Button("Play current")) {
		PlayCurrent();
	}
	if (GUILayout.Button("Next")) {
		Seek(SeekDirection.Forward);
		PlayCurrent();
	}
	if (GUILayout.Button("Reload")) {
		ReloadSounds();
	}
}

function Seek(d : SeekDirection)
{
	if (d == SeekDirection.Forward)
		currentIndex = (currentIndex + 1) % clips.Count;
	else {
		currentIndex--;
		if (currentIndex < 0) currentIndex = clips.Count - 1;
	}
}

function PlayCurrent()
{
	source.clip = clips[currentIndex];
	source.Play();
}

function ReloadSounds()
{
	clips.Clear();

	// get all valid files
	var info = new DirectoryInfo(absolutePath);
	soundFiles = info.GetFiles()
		.Where(function (f) { return IsValidFileType(f.Name); } )
		.ToArray();

	// and load them
	for(var s in soundFiles)
		StartCoroutine(LoadFile(s.FullName));
}

function IsValidFileType(fileName : String) : boolean
{
	return validExtensions.Contains(Path.GetExtension(fileName));
}

function LoadFile(path : String)
{
	var www = new WWW("file://" + path);
	print("loading " + path);

	var clip = www.GetAudioClip(false);
	while(!clip.isReadyToPlay)
		yield www;

	print("done loading");
	clip.name = Path.GetFileName(path);
	clips.Add(clip);
}

@ vexe could you please update the script i cant script and i need something like this for my music player i am making

Download this .dll: NAudio.dll : Free .DLL download. - DLLme.com and import in folder Plugins

Download this c# script: Dropbox - NAudioPlayer.cs - Simplify your life

Download and import this Unity Asset Store: Runtime File Browser | GUI Tools | Unity Asset Store

Create a c# Script, add to a gameObject, and write this lines:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using UnityEngine.UI;
using System.Runtime;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using NAudio;
using NAudio.Wave;
using UnityEngine.Networking;
using SimpleFileBrowser;

public class ReadMp3 : MonoBehaviour{
private AudioSource audioSource;
public Text pathText;

private void Start()
{
    audioSource = GetComponent<AudioSource>();
} public void ReadMp3Sounds()
{
    FileBrowser.SetFilters(false, new FileBrowser.Filter("Sounds", ".mp3"));
    FileBrowser.SetDefaultFilter(".mp3");
    StartCoroutine(ShowLoadDialogCoroutine());
}

IEnumerator ShowLoadDialogCoroutine () 
{
yield return FileBrowser.WaitForLoadDialog(false, null, "Select Sound", "Select");

pathText.text = FileBrowser.Result;

if (FileBrowser.Success)
{
    byte[] SoundFile = FileBrowserHelpers.ReadBytesFromFile(FileBrowser.Result);
    yield return SoundFile;

    audioSource.clip = NAudioPlayer.FromMp3Data(SoundFile);
    audioSource.Play();   
}

}

i think this is the best way to import all of your audio files from one folder

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using System.IO;

public class PlayList : MonoBehaviour {

    string path;
    public List<AudioClip> Cliplist;
    AudioClip[] clips;

    public List<string> audioname;

    void Start ()
    {
        path = Application.persistentDataPath; 

        
        if (Directory.Exists(path))
        {
            DirectoryInfo info = new DirectoryInfo(path);
            
            foreach (FileInfo item in info.GetFiles("*.wav"))
            {
                
                audioname.Add(item.Name);
            }
            
        }
        StartCoroutine(LoadAudioFile());
	}
	
	IEnumerator LoadAudioFile()
    {
        for (int i = 0; i <audioname.Count; i++)
        {
            UnityWebRequest AudioFiles = UnityWebRequestMultimedia.GetAudioClip(path + string.Format("{0}", audioname*),AudioType.WAV);*

yield return AudioFiles.SendWebRequest();
if(AudioFiles.isNetworkError)
{
Debug.Log(AudioFiles.error);
Debug.Log(path + string.Format(“{0}”, audioname*));*
}
else
{
AudioClip clip = DownloadHandlerAudioClip.GetContent(AudioFiles);
clip.name = audioname*;*
Cliplist.Add(clip);
Debug.Log(path + string.Format(“{0}”, audioname*));*
}
}

}
}