Захват вводимого звука

Flash Player 9 и более поздних версий, Adobe AIR 1.0 и более поздних версий

Класс Microphone позволяет приложению подключаться к микрофону или другому устройству ввода звука, установленному в пользовательской системе, и затем транслировать вводимый звук на системные динамики или отправлять его на удаленный сервер, такой как Flash Media Server. Можно получить доступ к необработанной звуковой информации с микрофона для выполнения записи или обработки. Звук также можно направлять напрямую на системные динамики или передавать сжатую звуковую информацию на удаленный сервер. Для данных, отправленных на удаленный сервер, можно использовать кодек Speex или Nellymoser. (Кодек Speex доступен для использования, начиная с Flash Player версии 10 и Adobe AIR версии 1.5.)

Получение доступа к микрофону

Класс Microphone не имеет собственного конструктора. Вместо него используется статический метод Microphone.getMicrophone() , который позволяет получить новый экземпляр Microphone, как показано ниже.

var mic:Microphone = Microphone.getMicrophone();

Вызов метода Microphone.getMicrophone() без параметра возвращает первое устройство ввода звука, обнаруженное в системе пользователя.

В системе может быть установлено несколько устройств ввода звука. Приложение может использовать свойство Microphone.names , чтобы получить массив имен всех доступных устройств ввода звука. Затем оно может вызвать метод Microphone.getMicrophone() с параметром index , значение которого соответствует позиции индекса нужного устройства в массиве.

К системе может быть не подключен ни микрофон, ни другое устройство ввода звука. С помощью свойства Microphone.names или метода Microphone.getMicrophone() можно проверить, установлено ли устройство ввода звука в системе пользователя. Если пользователь не установил устройство ввода звука, массив names будет иметь нулевую длину, а метод getMicrophone() возвращает значение null .

Когда приложение вызывает метод Microphone.getMicrophone() , проигрыватель Flash Player выводит окно «Параметры Flash Player», в котором пользователь может разрешить или запретить проигрывателю Flash Player доступ к камере или микрофону в системе. После того, как пользователь нажмет кнопку «Разрешить» или «Запретить» в этом окне, отправляется событие StatusEvent. Свойство code этого экземпляра StatusEvent указывает, разрешен или запрещен доступ к микрофону, как показано в следующем примере.

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."); 
    } 
}

Свойство StatusEvent.code будет содержать значение «Microphone.Unmuted», если доступ разрешен, или «Microphone.Muted», если доступ запрещен.

Свойство Microphone.muted получает значение true или false , когда пользователь соответственно разрешает или запрещает доступ к микрофону. Однако свойство muted задается для экземпляра Microphone только после отправки события StatusEvent, поэтому приложение также должно дождаться отправки события StatusEvent.STATUS , прежде чем проверять свойство Microphone.muted .

Для того чтобы в проигрывателе Flash Player было показано диалоговое окно настройки, окно приложения должно быть достаточно большим для его отображения (не менее 215 x 138 пикселов). В противном случае доступ автоматически запрещается.

Содержимому, выполняемому в изолированной программной среде приложения AIR, не требуется разрешение пользователя для получения доступа к микрофону. Таким образом, события status при отключении и включении звука микрофона никогда не отправляются. Содержимому, которое выполняется в AIR за пределами изолированной программной среды приложения, требуется разрешение пользователя, поэтому отправка событий status возможна.

Трансляция звука с микрофона на локальные динамики

Звук, вводимый с микрофона, можно транслировать на динамики локальной системы с помощью метода Microphone.setLoopback() , параметр которого имеет значение true .

Когда звук с локального микрофона транслируется на локальные динамики, существует риск создания эффекта обратной связи, который может вызвать громкие свистящие звуки и даже повредить звуковое оборудование. Вызов метода Microphone.setUseEchoSuppression() со значением параметра true уменьшает, но не устраняет полностью риск возникновения эффекта обратной связи. Компания Adobe рекомендует всегда вызывать метод Microphone.setUseEchoSuppression(true) перед вызовом Microphone.setLoopback(true) , если нет уверенности в том, что пользователь воспроизводит звук не через динамики, а с помощью наушников или другого устройства.

Следующий код демонстрирует трансляцию звука с локального микрофона на динамики локальной системы.

var mic:Microphone = Microphone.getMicrophone(); 
mic.setUseEchoSuppression(true); 
mic.setLoopBack(true);

Изменение звука, захватываемого с микрофона

Приложение может изменять аудиоданные, поступающие с микрофона, двумя способами. Во-первых, оно может изменять уровень усиления вводимого звука, умножая вводимые значения на заданный коэффициент, чтобы сделать звук громче или тише. Свойство Microphone.gain принимает числовые значения от 0 до 100 включительно. Значение 50 соответствует множителю 1 и обозначает нормальную громкость. Значение 0 соответствует множителю 0 и заглушает вводимый звук. Значения выше 50 делают звук громче.

Приложение также может изменять частоту дискретизации вводимого звука. Чем выше частота дискретизации, тем выше качество звука, но при этом также уплотняются потоки данных, которые требуют больше ресурсов для передачи и хранения. Свойство Microphone.rate представляет частоту дискретизации звука в килогерцах (кГц). Частота дискретизации по умолчанию составляет 8 кГц. Если микрофон поддерживает более высокую частоту, можно задать для свойства Microphone.rate значение больше 8 кГц. Например, если задать свойству Microphone.rate значение 11, то частота дискретизации будет составлять 11 кГц, а при значении 22 частота будет равна 22 кГц. Доступная частота дискретизации зависит от выбранного кодека. При использовании кодека Nellymoser можно выбрать частоту дискретизации, равную 5, 8, 11, 16, 22 или 44 кГц. При использовании кодека Speex (доступен, начиная с Flash Player версии 10 и Adobe AIR версии 1.5) вы можете выбрать только частоту 16 кГц.

Определение активности микрофона

С целью экономии пропускной способности и ресурсов обработки проигрыватель Flash Player пытается определить, когда микрофон не передает звука. Если уровень активности микрофона остается ниже порога тишины в течение определенного времени, проигрыватель Flash Player перестает передавать вводимый звук и отправляет простое событие ActivityEvent. При использовании кодека Speex (доступен, начиная с Flash Player версии 10 и Adobe AIR версии 1.5) установите уровень тишины на нулевое значение, чтобы приложение осуществляло непрерывную передачу звука. Система обнаружения речевой активности Speex автоматически снижает потребление пропускной способности.

Примечание. Объект Microphone отправляет события activity, только когда приложение отслеживает микрофон. Таким образом, если функция setLoopBack( true ) не вызывается, добавьте прослушиватель для событий звуковых данных сэмплов или подключите микрофон к объекту NetStream. В этом случае события activity не отправляются.

Для отслеживания и контроля активности в классе Microphone предусмотрено три свойства.

  • Свойство activityLevel , предназначенное только для чтения, указывает количество звука, определяемое микрофоном, по шкале от 0 до 100.

  • Свойство silenceLevel указывает количество звука, необходимое для активации микрофона и отправки события ActivityEvent.ACTIVITY . Свойство silenceLevel также использует шкалу от 0 до 100, по умолчанию используется значение 10.

  • Свойство silenceTimeout указывает количество миллисекунд, в течение которых уровень активности должен находиться ниже порога тишины, прежде чем будет отправлено событие ActivityEvent.ACTIVITY , сообщающее о том, что микрофон заглушен. По умолчанию свойство silenceTimeout имеет значение 2000.

И свойство Microphone.silenceLevel , и свойство Microphone.silenceTimeout предназначены только для чтения, но их значения можно изменить с помощью метода Microphone.setSilenceLevel() .

В некоторых случаях процесс активации микрофона при обнаружении новой активности может вызывать небольшую задержку. Постоянное поддержание микрофона в активном состоянии предотвращает такие задержки при активации. Приложение может вызвать метод Microphone.setSilenceLevel() с параметром silenceLevel в значении 0, чтобы проигрыватель Flash Player поддерживал микрофон в активном состоянии и продолжал собирать аудиоданные, даже когда звук не определяется. И наоборот, если задать параметру silenceLevel значение 100, микрофон вообще не будет активироваться.

В следующем примере показана информация о микрофоне, а также сообщения о событиях activity и status, отправленных объектом 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); 
}

При тестировании этого примера говорите в микрофон или создавайте шумы, чтобы понаблюдать за значениями инструкции trace на консоли или в окне отладки.

Отправка звука на сервер мультимедийного содержимого и с сервера

Когда ActionScript используется с потоковым сервером мультимедийного содержимого, таким как Flash Media Server, становятся доступны дополнительные возможности.

В частности, приложение может присоединить объект Microphone к объекту NetStream и передавать данные непосредственно с микрофона пользователя на сервер. Аудиоданные также можно передавать потоком с сервера приложению и воспроизводить в составе объекта MovieClip или с помощью объекта Video.

Кодек Speex доступен, начиная с Flash Player версии 10 и Adobe AIR версии 1.5. Для выбора кодека, используемого для сжатия отправляемых на медиа-сервер аудиоданных, настройте свойство codec объекта Microphone. Это свойство может иметь два значения, которые перечислены в классе SoundCodec. Если свойству codec задано значение SoundCodec.SPEEX , для сжатия аудио выбирается кодек Speex. Если свойству задано значение SoundCodec.NELLYMOSER (по умолчанию), для сжатия аудио выбирается кодек Nellymoser.

Дополнительные сведения см. в интерактивной документации по Flash Media Server на странице www.adobe.com/go/learn_fms_docs_ru .

Захват аудиоданных с микрофона

В программах Flash Player 10.1 и AIR 2 и более поздних версиях информацию можно захватывать из данных микрофона в качестве байтового массива значений с плавающей запятой. Каждое значение представляет сэмпл монофонических аудиоданных.

Чтобы получить микрофонные данные, задайте прослушиватель событий для события sampleData объекта Microphone. Объект Microphone периодически отправляет события sampleData по мере того, как буфер микрофона заполняется звуковыми сэмплами. Объект SampleDataEvent обладает свойством data , которое представляет собой байтовый массив звуковых сэмплов. Каждый сэмпл представлен значениями с плавающей запятой, которые относятся к монофоническому звуковому сэмплу.

Следующий код захватывает звуковые данные с микрофона в объект ByteArray под названием 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); 
    } 
}

Байты сэмпла можно повторно использовать в качестве аудио для воспроизведения в объекте Sound. При этом необходимо присвоить свойству rate объекта Microphone значение 44, которое соответствует частоте дискретизации, используемой объектами Sound. Можно также преобразовать микрофонные сэмплы, захваченные при низкой частоте, в частоту 44 кГц, которая требуется объекту Sound. Учтите также, что объект Microphone захватывает монофонические сэмплы, тогда как объект Sound использует стереозвук. Поэтому каждый из байтов, захваченных объектом Microphone, нужно записывать в объект Sound дважды. В следующем примере 4 секунды микрофонных данных захватываются и воспроизводятся с помощью объекта 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."); 
}

Дополнительные сведения о воспроизведении звуков из данных звукового сэмпла см. в разделе « Работа с динамически создаваемым звуком ».