Przechwytywanie wejścia dźwiękowego
Flash Player 9 i nowsze wersje, Adobe AIR 1.0 i nowsze wersje
Klasa Microphone umożliwia połączenie aplikacji z mikrofonem lub innym urządzeniem wejścia dźwiękowego w systemie użytkownika i nadanie dźwiękowego sygnału wejściowego do głośników tego systemu lub wysłanie danych audio na zdalny serwer, taki jak Flash Media Server. Można uzyskiwać dostęp bezpośrednio do danych audio pochodzących z mikrofonu i nagrywać je lub przetwarzać. Można również wysyłać dźwięki bezpośrednio do głośników komputera lub wysyłać skompresowane dane audio na serwer zdalny. W przypadku danych wysłanych do serwera zdalnego można korzystać z kodeka Speex lub Nellymoser. (Kodek Speex jest obsługiwany począwszy od wersji 10 programu Flash Player i wersji 1.5 środowiska Adobe AIR).
Uzyskiwanie dostępu do mikrofonu
Klasa Microphone nie dysponuje metodą konstruktora. Zamiast tego możliwe jest użycie statycznej metody
Microphone.getMicrophone()
do uzyskania nowej instancji Microphone zgodnie z informacjami poniżej:
var mic:Microphone = Microphone.getMicrophone();
Wywołanie metody
Microphone.getMicrophone()
bez parametru zwróci pierwsze dźwiękowe urządzenie wejściowe wykryte w systemie użytkownika.
System może dysponować więcej niż jednym dźwiękowym urządzeniem wejściowym podłączonym do niego. Aplikacja może używać właściwości
Microphone.names
do uzyskiwania tablicy nazw dostępnych dźwiękowych urządzeń wejściowych. Może ona następnie wywoływać metodę
Microphone.getMicrophone()
z parametrem
index
odpowiadającym wartości indeksu nazwy urządzenia w tablicy.
System może nie dysponować mikrofonem ani innym dźwiękowym urządzeniem wejściowym. Możliwe jest również użycie właściwości
Microphone.names
lub metody
Microphone.getMicrophone()
do sprawdzenia, czy użytkownik zainstalował dźwiękowe urządzenie wejściowe w systemie. Jeśli użytkownik nie zainstalował dźwiękowego urządzenia wejściowego, tablica
names
ma długość równą zeru, a metoda
getMicrophone()
zwraca wartość
null
.
Po wywołaniu przez aplikację metody
Microphone.getMicrophone()
program Flash Player wyświetla okno dialogowe Ustawienia Flash Player z monitem o zezwolenie lub odmówienie dostępu Flash Player do kamery i mikrofonu zainstalowanych w systemie. Po kliknięciu przez użytkownika przycisku Zezwalaj lub Odmów w tym oknie dialogowym dysponowane jest zdarzenie StatusEvent. Właściwość
code
tej instancji StatusEvent wskazuje, czy zezwolono, czy też odmówiono dostępu do mikrofonu, zgodnie z poniższym przykładem:
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.");
}
}
Właściwość
StatusEvent.code
będzie zawierać wartość „Microphone.Unmuted”, jeśli zezwolono na dostęp, lub „Microphone.Muted”, jeśli na dostęp nie zezwolono.
Wraz z decyzją użytkownika o dostępie do mikrofonu właściwość
Microphone.muted
jest ustawiana odpowiednio na wartość
true
lub
false
. Właściwość
muted
nie jest ustawiana w wystąpieniu klasy Microphone, dopóki nie zostanie wywołane zdarzenie StatusEvent, dlatego aplikacja powinna zaczekać na wywołanie zdarzenia
StatusEvent.STATUS
przed sprawdzeniem właściwości
Microphone.muted
.
Aby program Flash Player wyświetlił okno dialogowe ustawień, okno aplikacji musi mieć odpowiednie wymiary (co najmniej 215 x 138 pikseli). W przeciwnym razie nastąpi automatyczna odmowa dostępu.
Zawartość działająca w obszarze izolowanym aplikacji AIR nie potrzebuje uprawnień w celu uzyskania dostępu do mikrofonu. Oznacza to, że w tym przypadku nigdy nie są wywoływane zdarzenia dotyczące wyciszania i anulowania wyciszenia mikrofonu. Zawartość działająca w środowisku AIR poza obszarem izolowanym aplikacji musi mieć pozwolenie użytkownika, dlatego mogą być wywoływane te zdarzenia zmiany stanu.
Przekierowywanie dźwięku z mikrofonu do lokalnych głośników
Wejście audio z mikrofonu można przekierować do lokalnego systemu głośników, wywołując metodę
Microphone.setLoopback()
z wartością
true
parametru.
Po przekierowaniu dźwięku z lokalnego mikrofonu do lokalnych głośników istnieje ryzyko utworzenia sprzężenia zwrotnego, co może spowodować generowanie głośnych i wysokich dźwięków, i grozi uszkodzeniem sprzętu audio. Wywołanie metody
Microphone.setUseEchoSuppression()
z wartością
true
parametru redukuje, lecz nie eliminuje kompletnie, ryzyka powstania takiego sprzężenia zwrotnego. Firma Adobe zaleca wywoływanie zawsze metody
Microphone.setUseEchoSuppression(true)
przed wywołaniem metody
Microphone.setLoopback(true)
, chyba że istnieje całkowita pewność co do tego, że użytkownik odtworzy dźwięk za pomocą słuchawek lub w dowolny inny sposób, a nie przez głośniki.
Poniższy kod ilustruje sposób przekierowywana audio z lokalnego mikrofonu do lokalnego systemu głośników:
var mic:Microphone = Microphone.getMicrophone();
mic.setUseEchoSuppression(true);
mic.setLoopBack(true);
Zmienianie dźwięku mikrofonu
Aplikacja umożliwia zmianę danych dźwiękowych pochodzących z mikrofonu na dwa sposoby. Po pierwsze, może ona zmienić wzmocnienie wejścia dźwiękowego, co w praktyce powoduje przemnożenie wartości wejściowych przez określoną wielkość i wytworzenie głośniejszego lub cichszego efektu. Właściwość
Microphone.gain
przyjmuje wartości numeryczne z zakresu od 0 do 100 włącznie. Wartość 50 działa jak mnożnik wynoszący jeden i określa głośność normalną. Wartość zerowa działa jak mnożnik wynoszący zero i w praktyce wycisza całkowicie wejście audio. Wartości powyżej 50 określają głośność wyższa niż normalna.
Ponadto aplikacja może również zmieniać częstotliwość próbkowania wejścia audio. Wyższe częstotliwości próbkowania zwiększają jakość dźwięku, lecz mogą również powodować zagęszczenie strumieni danych w przypadku, jeśli korzystają one z wielu źródeł do transmisji i zapisu. Właściwość
Microphone.rate
prezentuje częstotliwość próbkowania audio mierzoną w kilohercach (kHz). Domyślna częstotliwość próbkowania wynosi 8 kHz. Możliwe jest ustawienie właściwości
Microphone.rate
na wartość wyższą niż 8 kHz, jeśli mikrofon obsługuje wyższą częstotliwość. Na przykład: ustawienie właściwości
Microphone.rate
na wartość 11 powoduje ustawienie częstotliwości próbkowania na wartość 11 kHz; ustawienie jej na wartość 22 powoduje ustawienie częstotliwości próbkowania na wartość 22 kHz itd. Częstotliwości próbkowania są uzależnione od wybranego kodeka. Jeśli używany jest kodek Nellymoser, można określić częstotliwości próbkowania: 5, 8, 11, 16, 22 oraz 44 kHz. W przypadku użycia kodeka Speex (dostępnego począwszy od wersji 10 programu Flash Player i wersji 1.5 środowiska Adobe AIR) dostępna jest tylko częstotliwość 16 kHz.
Wykrywanie aktywności mikrofonu
W celu zachowania szerokości pasma oraz zasobów przetwarzania program Flash Player próbuje wykrywać brak przesyłania dźwięku przez mikrofon. Jeśli działanie mikrofonu pozostaje przez określony czas poniżej progu poziomu ciszy, Flash Player zatrzymuje transmisję danych wejściowych audio i dysponuje zamiast tego proste zdarzenie ActivityEvent. W przypadku użycia kodeka Speex (dostępnego począwszy od wersji 10 programu Flash Player i wersji 1.5 środowiska Adobe AIR) należy poziom ciszy ustawić na 0, aby zapewnić ciągłość przesyłania danych audio przez aplikację. Wykrywanie głosu przez kodek Speex automatycznie redukuje szerokość pasma.
Uwaga:
Obiekt Microphone wywołuje zdarzenia activity (dotyczące działań) tylko w przypadku, gdy aplikacja monitoruje mikrofon. Jeśli nie zostanie wywołana metoda
setLoopBack(true)
, nie zostanie dodany detektor związany ze zdarzeniami danych próbkowania ani mikrofon nie zostanie dołączony do obiektu NetStream, nie będą wywoływane żadne zdarzenia activity.
Za monitorowanie i sterowanie wykrywaniem aktywności klasy Microphone odpowiadają trzy właściwości:
-
Właściwość tylko do odczytu
activityLevel
wskazuje wielkość dźwięku wykrytą w mikrofonie, na skali od 0 do 100.
-
Właściwość
silenceLevel
określa ilość dźwięku potrzebną do aktywacji mikrofonu i dysponuje zdarzenie
ActivityEvent.ACTIVITY
. Właściwość
silenceLevel
korzysta również ze skali od 0 do 100, gdzie wartością domyślną jest 10.
-
Właściwość
silenceTimeout
opisuje liczbę milisekund, poniżej której musi pozostać poziom aktywności, aż do chwili zadysponowania zdarzenia
ActivityEvent.ACTIVITY
w celu wskazania, że mikrofon jest wyciszony. Wartość domyślna
silenceTimeout
to 2000.
Zarówno właściwość
Microphone.silenceLevel
jak i właściwość
Microphone.silenceTimeout
mają atrybut tylko do odczytu, lecz ich wartości można zmienić za pomocą metody
Microphone.setSilenceLevel()
.
W niektórych przypadkach proces aktywacji mikrofonu po wykryciu nowej czynności może spowodować niewielkie opóźnienie. Zachowanie aktywności mikrofonu przez cały czas może pomóc wyeliminować takie opóźnienia w aktywacji. Aplikacja może wywoływać metodę
Microphone.setSilenceLevel()
z parametrem
silenceLevel
ustawionym na wartość zerową w celu przekazania do programu Flash Player informacji o konieczności zachowania aktywności mikrofonu oraz zgromadzonych danych audio, nawet jeśli przez pewien czas nie będą wykrywane żadne dźwięki. I odwrotnie, ustawienie parametru
silenceLevel
na wartość 100 całkowicie uniemożliwia aktywowanie mikrofonu.
Poniższy przykład ilustruje sposób wyświetlania informacji na temat mikrofonu, a także zdarzeń aktywności oraz statusu dysponowanych przez obiekt Microphone:
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);
}
Uruchamiając powyższy przykład, należy mówić lub wytwarzać inne dźwięki w pobliżu mikrofonu systemowego i obserwować wyniki wyświetlane w konsoli lub oknie debugowania.
Wysyłanie dźwięku na serwer oraz z serwera multimediów
Korzystanie z serwera przesyłania strumieniowego takiego jak Flash Media Server udostępnia dodatkowe możliwości audio.
W szczególności aplikacja może dołączyć obiekt Microphone do obiektu NetStream i przesyłać dane bezpośrednio z mikrofonu użytkownika na serwer. Dane audio mogą być również przesyłane strumieniowo z serwera do aplikacji lub Flex i odtwarzane jako fragment MovieClip lub za pomocą obiektu Video.
Kodek Speex jest dostępny począwszy od wersji 10 programu Flash Player i wersji 1.5 środowiska Adobe AIR. Aby wybrać kodek używany do przetwarzania dźwięku skompresowanego wysyłanego do serwera multimediów, należy przypisać wartość właściwości
codec
obiektu Microphone. Ta właściwość może mieć dwie wartości, które są wyliczane w klasie SoundCodec. Ustawienie właściwości codec na wartość
SoundCodec.SPEEX
powoduje wybranie kodeka Speex do kompresji audio. Ustawienie właściwości na
SoundCodec.NELLYMOSER
(domyślnie) powoduje wybranie kodeka Nellymoser dla kompresji audio.
Więcej informacji zawiera dokumentacja programu Flash Media Server dostępna pod adresem
www.adobe.com/go/learn_fms_docs_pl
.
Przechwytywanie danych dźwiękowych z mikrofonu
W programie Flash Player 10.1. i środowisku AIR 2 (oraz w nowszych wersjach) można przechwytywać dane z mikrofonu jako tablicę bajtów (ByteArray) wartości zmiennoprzecinkowych. Każda wartość reprezentuje próbkę dźwięku monofonicznego.
Aby pobierać dane z mikrofonu, należy skonfigurować detektor zdarzenia
sampleData
wywoływanego przez obiekt Microphone. Obiekt Microphone wywołuje zdarzenia
sampleData
okresowo, w miarę jak bufor mikrofonu zapełniany jest próbkami dźwięku. Obiekt SampleDataEvent ma właściwość
data
, która jest tablicą ByteArray zawierającą próbki dźwięku. Każda próbka jest zapisana jako wartość zmiennoprzecinkowa, reprezentująca wartość z jednego kanału (dźwięk monofoniczny).
Poniższy kod przechwytuje monofoniczne dane dźwiękowe do obiektu ByteArray o nazwie
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);
}
}
Ciąg bajtów z próbkami może zostać użyty jako dane dźwiękowe do odtwarzania przez obiekt Sound. W takim wypadku należy ustawić właściwość
rate
obiektu Microphone na 44, czyli częstotliwość próbkowania używaną przez obiekty Sound. (Można również przekonwertować próbki z mikrofonu przechwycone z niższą częstotliwością na częstotliwość 44 kHz wymaganą przez obiekt Sound). Należy także pamiętać, że obiekt Microphone przechwytuje próbki monofoniczne, a obiekt Sound operuje na dźwięku stereofonicznym; dlatego każdy bajt przechwycony przez obiekt Microphone należy zapisać do obiektu Sound dwukrotnie. W poniższym przykładzie przechwytywane są 4 sekundy danych z mikrofonu, a następnie dane te są odtwarzane za pomocą obiektu Sound:
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.");
}
Więcej informacji na temat odtwarzania dźwięku z próbek dźwiękowych zawiera sekcja
Praca z dźwiękiem generowanym dynamicznie
.
|
|
|
|
|