Capturing sound input
Flash Player 9 and later, Adobe AIR 1.0 and
later
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 an
ActivityEvent.ACTIVITY
event.
The
silenceLevel
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 an
ActivityEvent.ACTIVITY
event
is dispatched to indicate that the microphone is now silent. The
default
silenceTimeout
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
.
|
|
|
|
|