Capturing sound input
The Microphone class lets your application connect to a microphone or other sound input device on the user's system and broadcast the input audio to that system's speakers or send the audio data to a remote server, such as Flash Media Server. You can access the raw audio data from the microphone and record or process it; you can also send the audio directly to the system's speakers or send compressed audio data to a remote server. You can use either Speex or Nellymoser codec for data sent to a remote server. (The Speex codec is supported starting with Flash Player 10 and Adobe AIR 1.5.)
Accessing a microphone
The Microphone class does not have a constructor method. Instead, you use the
static Microphone.getMicrophone()
method to obtain a new Microphone instance,
as shown below:
var mic:Microphone = Microphone.getMicrophone();
Calling the Microphone.getMicrophone()
method without a parameter returns the
first sound input device discovered on the user's system.
A system can have more than one sound input device attached to it. Your
application can use the Microphone.names
property to get an array of the names
of all available sound input devices. Then it can call the
Microphone.getMicrophone()
method with an index
parameter that matches the
index value of a device's name in the array.
A system might not have a microphone or other sound input device attached to it.
You can use the Microphone.names
property or the Microphone.getMicrophone()
method to check whether the user has a sound input device installed. If the user
doesn't have a sound input device installed, the names
array has a length of
zero, and the getMicrophone()
method returns a value of null
.
When your application calls the Microphone.getMicrophone()
method, Flash
Player displays the Flash Player Settings dialog box, which prompts the user to
either allow or deny Flash Player access to the camera and microphone on the
system. After the user clicks on either the Allow button or the Deny button in
this dialog, a StatusEvent is dispatched. The code
property of that
StatusEvent instance indicates whether microphone access was allowed or denied,
as shown in this example:
import flash.media.Microphone;
var mic:Microphone = Microphone.getMicrophone();
mic.addEventListener(StatusEvent.STATUS, this.onMicStatus);
function onMicStatus(event:StatusEvent):void
{
if (event.code == "Microphone.Unmuted")
{
trace("Microphone access was allowed.");
}
else if (event.code == "Microphone.Muted")
{
trace("Microphone access was denied.");
}
}
The StatusEvent.code
property will contain "Microphone.Unmuted" if access was
allowed, or "Microphone.Muted" if access was denied.
The Microphone.muted
property is set to true
or false
when the user allows
or denies microphone access, respectively. However, the muted
property is not
set on the Microphone instance until the StatusEvent has been dispatched, so
your application should also wait for the StatusEvent.STATUS
event to be
dispatched before checking the Microphone.muted
property.
In order for Flash Player to display the settings dialog, the application window must be large enough to display it (at least 215 by 138 pixels). Otherwise, access is denied automatically.
Content running in the AIR application sandbox does not need the permission of the user to access the microphone. Thus, status events for muting and unmuting the microphone are never dispatched. Content running in AIR outside the application sandbox does require permission from the user, so these status events can be dispatched.
Routing microphone audio to local speakers
Audio input from a microphone can be routed to the local system speakers by
calling the Microphone.setLoopback()
method with a parameter value of true
.
When sound from a local microphone is routed to local speakers, there is a risk
of creating an audio feedback loop, which can cause loud squealing sounds and
can potentially damage sound hardware. Calling the
Microphone.setUseEchoSuppression()
method with a parameter value of true
reduces, but does not completely eliminate, the risk that audio feedback will
occur. Adobe recommends you always call Microphone.setUseEchoSuppression(true)
before calling Microphone.setLoopback(true)
, unless you are certain that the
user is playing back the sound using headphones or something other than
speakers.
The following code shows how to route the audio from a local microphone to the local system speakers:
var mic:Microphone = Microphone.getMicrophone();
mic.setUseEchoSuppression(true);
mic.setLoopBack(true);
Altering microphone audio
Your application can alter the audio data that comes from a microphone in two
ways. First, it can change the gain of the input sound, which effectively
multiplies the input values by a specified amount to create a louder or quieter
sound. The Microphone.gain
property accepts numeric values between 0 and 100
inclusive. A value of 50 acts like a multiplier of one and specifies normal
volume. A value of zero acts like a multiplier of zero and effectively silences
the input audio. Values above 50 specify higher than normal volume.
Your application can also change the sample rate of the input audio. Higher
sample rates increase sound quality, but they also create denser data streams
that use more resources for transmission and storage. The Microphone.rate
property represents the audio sample rate measured in kilohertz (kHz). The
default sample rate is 8 kHz. You can set the Microphone.rate
property to a
value higher than 8 kHz if your microphone supports the higher rate. For
example, setting the Microphone.rate
property to a value of 11 sets the sample
rate to 11 kHz; setting it to 22 sets the sample rate to 22 kHz, and so on. The
sample rates available depend on the selected codec. When you use the Nellymoser
codec, you can specify 5, 8, 11, 16, 22 and 44 kHz as the sample rate. When you
use Speex codec (available starting in Flash Player 10 and Adobe AIR 1.5), you
can only use 16 kHz.
Detecting microphone activity
To conserve bandwidth and processing resources, Flash Player tries to detect when no sound is being transmitted by a microphone. When the microphone's activity level stays below the silence level threshold for a period of time, Flash Player stops transmitting the audio input and dispatches a simple ActivityEvent instead. If you use the Speex codec (available in Flash Player 10 or later and Adobe AIR 1.5 or later), set the silence level to 0, to ensure that the application continuously transmits audio data. Speex voice activity detection automatically reduces bandwidth.
Note: A Microphone object only dispatches Activity events when your application
is monitoring the microphone. Thus, if you do not call setLoopBack( true )
,
add a listener for sample data events, or attach the microphone to a NetStream
object, then no activity events are dispatched.
Three properties of the Microphone class monitor and control the detection of activity:
The read-only
activityLevel
property indicates the amount of sound the microphone is detecting, on a scale from 0 to 100.The
silenceLevel
property specifies the amount of sound needed to activate the microphone and dispatch anActivityEvent.ACTIVITY
event. ThesilenceLevel
property also uses a scale from 0 to 100, and the default value is 10.The
silenceTimeout
property describes the number of milliseconds that the activity level must stay below the silence level, until anActivityEvent.ACTIVITY
event is dispatched to indicate that the microphone is now silent. The defaultsilenceTimeout
value is 2000.
Both the Microphone.silenceLevel
property and the Microphone.silenceTimeout
property are read only, but their values can be changed by using the
Microphone.setSilenceLevel()
method.
In some cases, the process of activating the microphone when new activity is
detected can cause a short delay. Keeping the microphone active at all times can
remove such activation delays. Your application can call the
Microphone.setSilenceLevel()
method with the silenceLevel
parameter set to
zero to tell Flash Player to keep the microphone active and keep gathering audio
data, even when no sound is being detected. Conversely, setting the
silenceLevel
parameter to 100 prevents the microphone from being activated at
all.
The following example displays information about the microphone and reports on activity events and status events dispatched by a Microphone object:
import flash.events.ActivityEvent;
import flash.events.StatusEvent;
import flash.media.Microphone;
var deviceArray:Array = Microphone.names;
trace("Available sound input devices:");
for (var i:int = 0; i < deviceArray.length; i++)
{
trace(" " + deviceArray[i]);
}
var mic:Microphone = Microphone.getMicrophone();
mic.gain = 60;
mic.rate = 11;
mic.setUseEchoSuppression(true);
mic.setLoopBack(true);
mic.setSilenceLevel(5, 1000);
mic.addEventListener(ActivityEvent.ACTIVITY, this.onMicActivity);
mic.addEventListener(StatusEvent.STATUS, this.onMicStatus);
var micDetails:String = "Sound input device name: " + mic.name + '\n';
micDetails += "Gain: " + mic.gain + '\n';
micDetails += "Rate: " + mic.rate + " kHz" + '\n';
micDetails += "Muted: " + mic.muted + '\n';
micDetails += "Silence level: " + mic.silenceLevel + '\n';
micDetails += "Silence timeout: " + mic.silenceTimeout + '\n';
micDetails += "Echo suppression: " + mic.useEchoSuppression + '\n';
trace(micDetails);
function onMicActivity(event:ActivityEvent):void
{
trace("activating=" + event.activating + ", activityLevel=" +
mic.activityLevel);
}
function onMicStatus(event:StatusEvent):void
{
trace("status: level=" + event.level + ", code=" + event.code);
}
When you run the above example, speak or makes noises into your system microphone and watch the resulting trace statements appear in a console or debug window.
Sending audio to and from a media server
Additional audio capabilities are available when using ActionScript with a streaming media server such as Flash Media Server.
In particular, your application can attach a Microphone object to a NetStream object and transmit data directly from the user's microphone to the server. Audio data can also be streamed from the server to an application and played back as part of a MovieClip or by using a Video object.
The Speex codec is available starting with Flash Player 10 and Adobe AIR 1.5. To
set the codec used for compressed audio sent to the media server, set the
codec
property of the Microphone object. This property can have two values,
which are enumerated in the SoundCodec class. Setting the codec property to
SoundCodec.SPEEX
selects the Speex codec for compressing audio. Setting the
property to SoundCodec.NELLYMOSER
(the default) selects the Nellymoser codec
for compressing audio.
For more information, see the Flash Media Server documentation online at www.adobe.com/go/learn_fms_docs_en.
Capturing microphone sound data
In Flash Player 10.1 and AIR 2, or later, you can capture data from a microphone data as a byte array of floating point values. Each value represents a sample of monophonic audio data.
To get microphone data, set an event listener for the sampleData
event of the
Microphone object. The Microphone object dispatches sampleData
events
periodically as the microphone buffer is filled with sound samples. The
SampleDataEvent object has a data
property that is a byte array of sound
samples. The samples are each represented as floating point values, each
representing a monophonic sound sample.
The following code captures microphone sound data into a ByteArray object named
soundBytes
:
var mic:Microphone = Microphone.getMicrophone();
mic.setSilenceLevel(0, DELAY_LENGTH);
mic.addEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler);
function micSampleDataHandler(event:SampleDataEvent):void {
while(event.data.bytesAvailable) {
var sample:Number = event.data.readFloat();
soundBytes.writeFloat(sample);
}
}
You can reuse the sample bytes as playback audio for a Sound object. If you do,
you should set the rate
property of the Microphone object to 44, which is the
sample rate used by Sound objects. (You can also convert microphone samples
captured at a lower rate to 44 kHz rate required by the Sound object.) Also,
keep in mind that the Microphone object captures monophonic samples, whereas the
Sound object uses stereo sound; so you should write each of the bytes captured
by the Microphone object to the Sound object twice. The following example
captures 4 seconds of microphone data and plays it back using a Sound object:
const DELAY_LENGTH:int = 4000;
var mic:Microphone = Microphone.getMicrophone();
mic.setSilenceLevel(0, DELAY_LENGTH);
mic.gain = 100;
mic.rate = 44;
mic.addEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler);
var timer:Timer = new Timer(DELAY_LENGTH);
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.start();
function micSampleDataHandler(event:SampleDataEvent):void
{
while(event.data.bytesAvailable)
{
var sample:Number = event.data.readFloat();
soundBytes.writeFloat(sample);
}
}
var sound:Sound = new Sound();
var channel:SoundChannel;
function timerHandler(event:TimerEvent):void
{
mic.removeEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler);
timer.stop();
soundBytes.position = 0;
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, playbackSampleHandler);
channel.addEventListener( Event.SOUND_COMPLETE, playbackComplete );
channel = sound.play();
}
function playbackSampleHandler(event:SampleDataEvent):void
{
for (var i:int = 0; i < 8192 && soundBytes.bytesAvailable > 0; i++)
{
trace(sample);
var sample:Number = soundBytes.readFloat();
event.data.writeFloat(sample);
event.data.writeFloat(sample);
}
}
function playbackComplete( event:Event ):void
{
trace( "Playback finished.");
}
For more information on playing back sounds from sound sample data, see Working with dynamically generated audio.
More Help topics