Search Unity

Multiple objects that use Microphone.start()???

Discussion in 'Audio & Video' started by EnsurdFrndship, May 22, 2015.

  1. EnsurdFrndship

    EnsurdFrndship

    Joined:
    Apr 17, 2010
    Posts:
    786
    Hello,
    I noticed something when I use the code...

    GetComponent<AudioSource>().clip = Microphone.Start ("", true, 1, 44100);

    If I use this on multiple instantiated objects, only 1 out of the objects play the microphone's input. If I disable or mute the last object that gets Instantiated and uses this line of code, I don't hear anything. I was hoping that the microphone's input could be played on multiple audio sources so I can add random effects to them. That way, when I speak into the microphone, it would sound like a crowd of people repeating after me. Is there any way to play the microphone's audio on multiple audio sources? Thank you.
     
  2. Ostwind

    Ostwind

    Joined:
    Mar 22, 2011
    Posts:
    2,804
    Try creating the clip first as its own variable and then assign it to all audio sources.
     
  3. EnsurdFrndship

    EnsurdFrndship

    Joined:
    Apr 17, 2010
    Posts:
    786
    That didn't work.
     
  4. EnsurdFrndship

    EnsurdFrndship

    Joined:
    Apr 17, 2010
    Posts:
    786
    I figured out a different solution. I used GetOutputData() and SetData() to 'copy' the data from one AudioSource to another. I wish I could make multiple audio clips with the microphone data on each one, and then assign each clip to each audio source. Maybe having multiple 'channels' from the microphone stored on each separate audio clip would be a great idea for the next version of Unity, or an add-on for this version.

    What about audio mixers? If I am making multiple instantiations of objects that use the same audio mixers. Is there a way where I can change an exposed variable of the audio mixer, without having the change effect all of the audio mixers that use the same name (due to the instantiation of that object)? I tried researching for an AudioMixer class (to see if I could create a new AudioMixer by a script, to assign to each object), but couldn't find anything.
     
  5. manlymooning

    manlymooning

    Joined:
    Apr 11, 2020
    Posts:
    3
    I know this thread is 5 years old, but there was no ready-to-use solution for that problem so I wrote a class to be used instead of `Microphone` that would properly handle cases when one input needs to be recorded from more than one place.

    Replace all usages of
    Microphone.Start
    /
    Microphone.End
    in your project with MicrophoneUtils.

    I highly advise using the same recording parameters when using this though (so that loop flag, length and frequency would match)!

    Code (CSharp):
    1.  
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. /// <summary>
    6. /// by foma
    7. /// https://github.com/fomalsd
    8. /// </summary>
    9. public class MicrophoneUtils
    10. {
    11.     private static Dictionary<string, RecordingParameters> ongoingRecordings = new Dictionary<string, RecordingParameters>();
    12.    
    13.     public static AudioClip Start(
    14.         string deviceName,
    15.         bool loop,
    16.         int lengthSec,
    17.         int frequency)
    18.     {
    19.        
    20.         if (IsRecording(deviceName))
    21.         {
    22.             if (!ongoingRecordings.ContainsKey(deviceName))
    23.             {
    24.                 Debug.LogError("Something is using Microphone class directly to record, please change it to use MicrophoneUtils instead!");
    25.                 End(deviceName);
    26.                 return StartNewRecording();
    27.             }
    28.  
    29.             var ongoingRecording = ongoingRecordings[deviceName];
    30.             if (loop != ongoingRecording.loop
    31.                 || lengthSec != ongoingRecording.lengthSec
    32.                 || frequency != ongoingRecording.frequency)
    33.             {
    34.                 Debug.LogWarningFormat("MicUtils: attempting to record same device from another place " +
    35.                                        "but recording params don't quite match:\ncurrent: {0}\nrequested: {1}",
    36.                     ongoingRecording, new RecordingParameters{loop = loop, lengthSec = lengthSec, frequency = frequency });
    37.                 //todo: possibly somehow convert audioclip data to suit desired parameters if that becomes a problem,
    38.                 //      for now just return the clip with first specified parameters
    39.             }
    40.  
    41.             ongoingRecording.users++;
    42.             Debug.LogFormat("Microphone {0} now has {1} users", deviceName, ongoingRecording.users);
    43.            
    44.             return ongoingRecording.audioClip;
    45.         }
    46.  
    47.         return StartNewRecording();
    48.  
    49.  
    50.         AudioClip StartNewRecording()
    51.         {
    52.             var audioClip = Microphone.Start(deviceName, loop, lengthSec, frequency);
    53.             var parameters = new RecordingParameters
    54.             {
    55.                 loop = loop,
    56.                 lengthSec = lengthSec,
    57.                 frequency = frequency,
    58.                 audioClip = audioClip,
    59.                 users = 1
    60.             };
    61.             ongoingRecordings.Add(deviceName, parameters);
    62.             Debug.LogFormat("Started the '{0}' input device: {1}", deviceName, parameters);
    63.             return audioClip;
    64.         }
    65.     }
    66.  
    67.     public static bool IsRecording(string deviceName)
    68.     {
    69.         return Microphone.IsRecording(deviceName);
    70.     }
    71.  
    72.     /// How many places are using this input source right now
    73.     public static int GetUsersRecording(string deviceName)
    74.     {
    75.         if (!IsRecording(deviceName))
    76.         {
    77.             return 0;
    78.         }
    79.  
    80.         if (!ongoingRecordings.ContainsKey(deviceName))
    81.         {
    82.             Debug.LogErrorFormat("Someone's recording '{0}' without MicUtils knowing!",deviceName);
    83.             return -1;
    84.         }
    85.  
    86.         return ongoingRecordings[deviceName].users;
    87.     }
    88.  
    89.     public static void End(string deviceName)
    90.     {
    91.         if (!IsRecording(deviceName))
    92.         {
    93.             return;
    94.         }
    95.         if (!ongoingRecordings.ContainsKey(deviceName))
    96.         {
    97.             JustStop();
    98.             return;
    99.         }
    100.  
    101.         var ongoingRecording = ongoingRecordings[deviceName];
    102.         if (ongoingRecording.users <= 1)
    103.         {
    104.             ongoingRecordings.Remove(deviceName);
    105.             JustStop();
    106.         }
    107.         else
    108.         {
    109.             ongoingRecording.users--;
    110.             Debug.LogFormat("Microphone {0} now has {1} users", deviceName, ongoingRecording.users);
    111.         }
    112.  
    113.        
    114.         void JustStop()
    115.         {
    116.             Debug.LogFormat("Stopping the '{0}' input device", deviceName);
    117.             Microphone.End(deviceName);
    118.         }
    119.     }
    120.  
    121. }
    122.  
    123. public class RecordingParameters
    124. {
    125.     public bool loop;
    126.     public int lengthSec;
    127.     public int frequency;
    128.     public int users;
    129.     public AudioClip audioClip;
    130.  
    131.     public override string ToString()
    132.     {
    133.       return $"{nameof(loop)}: {loop}, {nameof(lengthSec)}: {lengthSec}, {nameof(frequency)}: {frequency}, {nameof(users)}: {users}";
    134.     }
    135. }
    136.  
     
    Claytonious, noridon and laurajhchen like this.