사운드 입력 캡처

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 속성을 사용하여 사용 가능한 모든 사운드 입력 장치의 이름 배열을 가져옵니다. 그런 다음 배열에 있는 장치 이름의 인덱스 값과 일치하는 index 매개 변수를 사용하여 Microphone.getMicrophone() 메서드를 호출할 수 있습니다.

시스템에 마이크 또는 기타 사운드 입력 장치가 연결되어 있지 않을 수도 있습니다. Microphone.names 속성 또는 Microphone.getMicrophone() 메서드를 사용하여 사용자의 시스템에 사운드 입력 장치가 설치되어 있는지 여부를 확인합니다. 사용자의 시스템에 사운드 입력 장치가 설치되어 있지 않으면 names 배열 길이는 0이고 getMicrophone() 메서드가 null 값을 반환합니다.

응용 프로그램이 Microphone.getMicrophone() 메서드를 호출하면 Flash Player는 [Flash Player 설정] 대화 상자를 표시합니다. 이 대화 상자에서 사용자는 시스템의 카메라 및 마이크에 대한 Flash Player의 액세스를 허용 또는 거부할 수 있습니다. 이 대화 상자에서 [허용] 또는 [거부] 버튼을 클릭하면 StatusEvent가 전달됩니다. 다음 예제에서와 같이, 해당 StatusEvent 인스턴스의 code 속성은 마이크 액세스의 허용 또는 거부를 나타냅니다.

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 속성은 StatusEvent가 전달되기 전에는 Microphone 인스턴스에 설정되지 않으므로 응용 프로그램에서 Microphone.muted 속성을 확인하려면 또한 StatusEvent.STATUS 이벤트가 전달될 때까지 대기해야 합니다.

Flash Player에서 설정 대화 상자를 표시하려면 응용 프로그램 창의 크기는 최소한 215×138 픽셀 이상이 되어야 합니다. 그렇지 않으면 액세스는 자동으로 거부됩니다.

AIR 응용 프로그램 샌드박스에서 실행되는 내용은 마이크에 액세스하는 데 사용자의 권한을 얻을 필요가 없습니다. 따라서 마이크의 음소거 및 음소거 해제에 대한 status 이벤트는 전달되지 않습니다. 응용 프로그램 샌드박스 외부의 AIR에서 실행되는 내용은 사용자의 권한을 필요로 하므로 이러한 status 이벤트가 전달될 수 있습니다.

마이크 오디오를 로컬 스피커로 라우팅

매개 변수 값을 true로 하여 Microphone.setLoopback() 메서드를 호출하면 마이크의 오디오 입력을 로컬 시스템 스피커로 라우팅할 수 있습니다.

로컬 마이크의 사운드가 로컬 스피커로 라우팅되면 오디오 피드백 루프를 만들어 커다란 빽 소리를 일으키고 잠재적으로 사운드 하드웨어의 손상을 초래할 위험이 있습니다. 매개 변수 값을 true로 하여 Microphone.setUseEchoSuppression() 메서드를 호출하면 오디오 피드백이 발생할 위험이 완전히 배제되지는 않지만 낮아집니다. 사용자가 헤드폰을 사용하거나 스피커 이외의 다른 장치를 사용하여 사운드를 재생하고 있음을 확신할 수 없는 경우라면 Microphone.setLoopback(true)을 호출하기 전에 항상 Microphone.setUseEchoSuppression(true)을 호출하는 것이 좋습니다.

다음 코드는 로컬 마이크의 오디오를 로컬 시스템 스피커로 라우팅하는 방법을 보여 줍니다.

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

마이크 오디오 변경

응용 프로그램은 마이크로부터 전달되는 오디오 데이터를 두 가지 방법으로 변경할 수 있습니다. 먼저 입력 사운드의 게인을 변경할 수 있습니다. 게인은 입력 값을 지정된 양만큼 곱하여 더 크거나 작은 사운드를 생성합니다. Microphone.gain 속성은 0부터 100까지의 숫자 값을 받습니다. 값을 50으로 지정하면 1을 곱한 것과 같게 되어 보통 볼륨을 생성합니다. 값을 0으로 지정하면 0을 곱한 것과 같게 되어 입력 오디오를 제거합니다. 값을 50 이상으로 지정하면 보통 볼륨보다 높은 볼륨을 생성합니다.

응용 프로그램에서 입력 오디오의 샘플링 속도를 변경할 수도 있습니다. 샘플링 속도가 높을수록 사운드 품질은 향상되지만, 전송과 저장에 더 많은 리소스를 사용하는 좀 더 밀집된 데이터 스트림이 생성됩니다. Microphone.rate 속성은 kHz로 측정되는 오디오 샘플링 속도를 나타냅니다. 기본 샘플링 속도는 8kHz입니다. 마이크가 더 높은 속도를 지원하는 경우 Microphone.rate 속성 값을 8kHz 이상으로 설정할 수 있습니다. 예를 들어 Microphone.rate 속성의 값을 11로 설정하면 샘플링 속도가 11kHz로 지정되고, 22로 설정하면 샘플링 속도가 22kHz로 지정됩니다. 사용할 수 있는 샘플링 속도는 선택하는 코덱에 따라 달라집니다. Nellymoser 코덱을 사용할 경우에는 샘플링 속도로 5, 8, 11, 16, 22 및 44kHz를 지정할 수 있고, Speex 코덱을 사용할 경우(Flash Player 10 및 Adobe AIR 1.5부터 지원) 16kHz만 사용할 수 있습니다.

마이크 활동 감지

대역폭과 처리 리소스를 보존하기 위해 Flash Player는 마이크가 사운드를 전송하지 않는 때를 감지하려고 합니다. 마이크의 활동 레벨이 일정 시간 동안 묵음 레벨 임계값 미만을 유지하면 Flash Player는 오디오 입력 전송을 중지하고 대신 단순 ActivityEvent를 전달합니다. Speex 코덱을 사용할 경우(Flash Player 10 이상 및 Adobe AIR 1.5 이상에서 지원) 묵음 레벨을 0으로 설정해야 응용 프로그램에서 오디오 데이터가 연속적으로 전송됩니다. 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() 메서드를 사용하여 이 값을 변경할 수 있습니다.

새로운 활동이 감지되었을 때 마이크를 활성화하는 프로세스에서 약간의 지연이 발생하는 경우도 있습니다. 마이크를 항상 활성화시켜 두면 이러한 활성화 지연을 방지할 수 있습니다. 응용 프로그램이 silenceLevel 매개 변수를 0으로 설정하여 Microphone.setSilenceLevel() 메서드를 호출하면 Flash Player는 사운드가 감지되지 않더라도 마이크의 활성 상태를 유지하고 오디오 데이터를 계속 수집합니다. 반대로, silenceLevel 매개 변수를 100으로 설정하면 마이크가 전혀 활성화되지 않습니다.

다음 예제는 마이크에 대한 정보를 표시하고 Microphone 객체가 전달한 activity 이벤트 및 status 이벤트를 보고합니다.

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 문을 확인합니다.

미디어 서버에서의 오디오 송수신

Flash Media Server와 같은 스트리밍 미디어 서버와 함께 ActionScript를 사용할 때 추가 오디오 기능을 사용할 수 있습니다.

특히 응용 프로그램은 Microphone 객체를 NetStream 객체에 연결하여 마이크에서 서버로 직접 데이터를 전송할 수 있습니다. 또한 오디오 데이터는 서버에서 응용 프로그램으로 스트리밍되어 MovieClip의 일부로 재생되거나 Video 객체를 사용하여 재생될 수 있습니다.

Flash Player 10 및 Adobe AIR 1.5부터는 Speex 코덱을 사용할 수 있습니다. 미디어 서버로 전송되는 압축 오디오에 코덱을 설정하려면 Microphone 객체의 codec 속성을 설정합니다. 이 속성은 SoundCodec 클래스에 열거되는 두 개의 값을 가질 수 있습니다. 코덱 속성을 SoundCodec.SPEEX로 설정하면 오디오를 압축하는 데 Speex 코덱이 선택됩니다. 이 속성을 SoundCodec.NELLYMOSER(기본값)로 설정하면 오디오를 압축하는 데 Nellymoser 코덱이 선택됩니다.

자세한 내용은 www.adobe.com/go/learn_fms_docs_kr에서 온라인으로 제공되는 Flash Media Server 설명서를 참조하십시오.

마이크 사운드 데이터 캡처

Flash Player 10.1 및 AIR 2 이상 버전에서는 마이크의 데이터를 부동 소수점 값의 바이트 배열로 캡처할 수 있습니다. 각 값은 모노 오디오 데이터의 샘플을 나타냅니다.

마이크 데이터를 가져오려면 Microphone 객체의 sampleData 이벤트에 대한 이벤트 리스너를 설정합니다. Microphone 객체는 마이크 버퍼에 사운드 샘플이 채워지는 경우 정기적으로 sampleData 이벤트를 전달합니다. SampleDataEvent 객체에는 사운드 샘플의 바이트 배열인 data 속성이 포함됩니다. 샘플은 각각 부동 소수점 값으로 표시되며, 각각 모노 사운드 샘플을 나타냅니다.

다음 코드에서는 마이크 사운드 데이터를 soundBytes라는 이름의 ByteArray 객체로 캡처합니다.

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 객체의 재생 오디오로 다시 사용할 수 있습니다. 이렇게 할 경우 Microphone 객체의 rate 속성을 Sound 객체에서 사용되는 샘플링 속도인 44로 설정해야 합니다. 보다 낮은 속도로 캡처된 마이크 샘플을 Sound 객체에 필요한 44kHz 속도로 변환할 수도 있습니다. 또한 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."); 
}

사운드 샘플 데이터의 사운드를 재생하는 방법에 대한 자세한 내용은 동적으로 생성되는 오디오를 사용한 작업을 참조하십시오.