What is the proper way to copy an audio clip?

I've got my audio clips being dynamically loaded by WWW, and I have pre-set an audio source on an invisible gameobject that sits right by the main camera. As I load new audio clips, I simply make a copy of the invisible gameobject, and then assign the clip to the new source.

That works great, but of course I can only have each clip playing once at a time. So, if I have clip A, for instance, I can't have clip A playing over top of itself if two things trigger clip A semi-simultaneously.

The code I am using for copying the gameobject of the audio source is simply this:

(GameObject)GameObject.Instantiate( Game.Instance.audioObj )

And that works great for the audio sources. However, if I assign the same clip to multiple audio sources, it seems that the same issue as noted above is there: it can't play on top of itself, it simply resets to the start when it is triggered the second time.

So, I am therefore trying to do something similar for the Audio Clip, copying that once for each Audio Source, but when I do that it winds up with no sound playing at all:

(AudioClip)AudioClip.Instantiate( this.Clip );

That code doesn't throw any errors, but it also doesn't play any sound. It doesn't matter if I wait until after the initial audio clip has isReadyToPlay as true or not.

Any thoughts? Surely this must be a pretty common need, with multiple guns of the same sort on a battlefield, etc. In DirectX in the past I've had to just make multiple copies of a SecondarySoundBuffer to play them independently, but that's so wasteful of memory -- my hope is to find a better approach here...

Holy moly, here’s what I had to do:

    public AudioClip CloneAudioClip(AudioClip audioClip, string newName)
        AudioClip newAudioClip = AudioClip.Create(newName, audioClip.samples, audioClip.channels, audioClip.frequency, false);
        float[] copyData = new float[audioClip.samples * audioClip.channels];
        audioClip.GetData(copyData, 0);
        newAudioClip.SetData(copyData, 0);
        return newAudioClip;

Why? Because if you just Instantiate an AudioClip it leaves the sample data as 0 as in UNALLOCATED! Then you think, okay, just create float and GetData and then SetData with new float… nope, crash! You can only allocate data with AudioClip.Create(…) so you do that, the GetData then SetData and all is perfect (and fast, no loading!)


the problem is that each AudioSource is referencing the same AudioClip instance. Each time you create a new AudioSource you should also create a new AudioClip for that source (if you want multiple instances of the same sound playing). Id suggest using WWW.GetAudioClip() or WWW.audioClip since they by default return a copy (not a reference). Otherwise you can use Instantiate to create a copy of your AudioClips.

Probably the easiest way is to use AudioSource.PlayClipAtPoint(), which handles the housekeeping for you.

to clarify, the instantiate would look like this:

AudioClip clip = www.audioClip;
AudioClip clip2 = (AudioClip)Instantiate(clip);

if loading with Resources, you dont need to copy the clip. If loading with www, just get the clip from the www class and it will be a copy.

How do you slove this question finally?

I’m in a puzzle as to slove this problem too!!!

Could you teach me ?