동적으로 생성되는 오디오를 사용한 작업

Flash Player 10 이상, Adobe AIR 1.5 이상

참고: 오디오를 동적으로 생성하는 기능은 Flash Player 10 및 Adobe AIR 1.5부터 사용할 수 있습니다.

기존 사운드를 로드하거나 스트리밍하는 대신 동적으로 오디오 데이터를 생성할 수 있습니다. Sound 객체의 sampleData 이벤트에 대한 이벤트 리스너를 지정할 때 오디오 데이터를 생성할 수 있습니다. sampleData 이벤트는 flash.events 패키지의 SampleDataEvent 클래스에 정의되어 있습니다. 이 환경에서 Sound 객체는 파일에서 사운드 데이터를 로드하지 않습니다. 대신 이 객체는 이 이벤트에 할당하는 함수를 통해 스트리밍되어 들어오는 사운드 데이터에 대한 소켓 역할을 합니다.

Sound 객체에 sampleData 이벤트 리스너를 추가하면 이 객체는 데이터를 주기적으로 요청하여 사운드 버퍼에 추가합니다. 이 버퍼에는 Sound 객체가 재생할 데이터가 포함됩니다. Sound 객체의 play() 메서드를 호출하면 새 사운드 데이터를 요청할 때 sampleData 이벤트가 전달됩니다. 이는 Sound 객체가 mp3 데이터를 파일에서 로드하지 않은 경우에만 해당합니다.

SampleDataEvent 객체에는 data 속성이 포함됩니다. 이벤트 리스너에서는 이 data 객체에 ByteArray 객체를 씁니다. 이 객체에 쓰는 바이트 배열은 Sound 객체가 재생하는 버퍼링된 사운드 데이터에 추가됩니다. 버퍼의 바이트 배열은 -1부터 1까지의 부동 소수점 값에 대한 스트림입니다. 각 부동 소수점 값은 사운드 샘플의 한 쪽(왼쪽 또는 오른쪽) 채널 진폭을 나타냅니다. 사운드는 44,100SPS(초당 샘플 수)의 속도로 샘플링됩니다. 각 샘플에는 바이트 배열에 부동 소수점 데이터로 인터리브된 왼쪽 및 오른쪽 채널이 들어 있습니다.

핸들러 함수에서는 ByteArray.writeFloat() 메서드를 사용하여 sampleData 이벤트의 data 속성에 값을 씁니다. 예를 들어 다음 코드에서는 사인파를 생성합니다.

var mySound:Sound = new Sound(); 
mySound.addEventListener(SampleDataEvent.SAMPLE_DATA, sineWaveGenerator); 
mySound.play(); 
function sineWaveGenerator(event:SampleDataEvent):void 
{ 
    for (var i:int = 0; i < 8192; i++) 
    { 
        var n:Number = Math.sin((i + event.position) / Math.PI / 4); 
        event.data.writeFloat(n); 
        event.data.writeFloat(n); 
    } 
}

Sound.play() 를 호출하면 응용 프로그램에서는 사운드 샘플 데이터를 요청하는 이벤트 핸들러 호출을 시작합니다. 응용 프로그램에서는 사운드가 재생될 때 이벤트를 전송하며 이는 사용자가 데이터 제공을 중단하거나 SoundChannel.stop() 을 호출할 때까지 계속됩니다.

이벤트의 지연 시간은 플랫폼마다 다르며 Flash Player 및 AIR의 이후 버전에서 변경될 수 있습니다. 따라서 특정 지연 시간을 사용하는 대신 직접 계산해야 합니다. 지연 시간을 계산하려면 다음 공식을 사용합니다.

(SampleDataEvent.position / 44.1) - SoundChannelObject.position

이벤트 리스너에 대한 각 호출에서 SampleDataEvent 객체의 data 속성에 2048~8192개의 샘플을 제공합니다. 최상의 성능을 위해 샘플을 최대한 많이(최대 8192개) 제공하는 것이 좋습니다. 제공하는 샘플이 적을수록 재생 중 잡음이 발생하거나 고르지 않게 재생될 가능성이 높습니다. 이러한 비헤이비어는 플랫폼마다 다를 수 있으며 여러 가지 상황(예: 브라우저 크기 조절 시)에서 발생할 수 있습니다. 2048개의 샘플만 제공할 경우 한 플랫폼에서 작동하는 코드가 다른 플랫폼에서 실행될 때는 작동하지 않을 수도 있습니다. 지연 시간을 최대한 낮추려면 사용자가 데이터 양을 선택할 수 있게 하는 것이 좋습니다.

sampleData 이벤트 리스너에 대한 각 호출에서 2048개 미만의 샘플을 제공하면 응용 프로그램은 나머지 샘플을 재생한 후 중단됩니다. 그런 다음 SoundChannel 객체에서 SoundComplete 이벤트를 전달합니다.

mp3 데이터에서 사운드 수정

Sound.extract() 메서드를 사용하여 Sound 객체에서 데이터를 추출할 수 있습니다. 이 데이터를 사용하고 수정하여 재생용으로 다른 Sound 객체의 동적 스트림에 쓸 수 있습니다. 예를 들어 다음 코드에서는 로드된 MP3 파일의 바이트를 사용하고 이를 필터 함수 upOctave() 를 통해 전달합니다.

var mySound:Sound = new Sound(); 
var sourceSnd:Sound = new Sound(); 
var urlReq:URLRequest = new URLRequest("test.mp3"); 
sourceSnd.load(urlReq); 
sourceSnd.addEventListener(Event.COMPLETE, loaded); 
function loaded(event:Event):void 
{ 
    mySound.addEventListener(SampleDataEvent.SAMPLE_DATA, processSound); 
    mySound.play(); 
} 
function processSound(event:SampleDataEvent):void 
{ 
        var bytes:ByteArray = new ByteArray(); 
        sourceSnd.extract(bytes, 8192); 
        event.data.writeBytes(upOctave(bytes)); 
} 
function upOctave(bytes:ByteArray):ByteArray 
{ 
    var returnBytes:ByteArray = new ByteArray(); 
    bytes.position = 0; 
    while(bytes.bytesAvailable > 0) 
    { 
        returnBytes.writeFloat(bytes.readFloat()); 
        returnBytes.writeFloat(bytes.readFloat()); 
        if (bytes.bytesAvailable > 0) 
        { 
            bytes.position += 8; 
        } 
    } 
    return returnBytes; 
}

생성되는 사운드에 대한 제한

sampleData 이벤트 리스너를 Sound 객체와 함께 사용할 때 활성화되는 다른 Sound 메서드는 Sound.extract() Sound.play() 뿐입니다. 다른 메서드나 속성을 호출하면 예외가 발생합니다. SoundChannel 객체의 모든 메서드와 속성은 계속 사용할 수 있습니다.