Arbeta med dynamiskt skapat ljud

Flash Player 10 och senare, Adobe AIR 1.5 och senare

Obs! Från och med Flash Player 10 och Adobe AIR 1.5 kan du generera ljud dynamiskt.

I stället för att läsa in eller direktuppspela ett befintligt ljud, kan du skapa ljuddata dynamiskt. Du kan skapa ljuddata när du tilldelar en händelseavlyssnare för händelsen sampleData för ett Sound-objekt. (Händelsen sampleData definieras i klassen SampleDataEvent i flash.events-paketet.) I den här miljön läser Sound-objektet inte in ljuddata från någon fil. I stället fungerar det som en socket för ljuddata som börjar flöda med den funktion som du har tilldelat den här händelsen.

När du lägger till en sampleData-händelseavlyssnare till ett Sound-objekt begär objektet regelbundet data som ska läggas till i ljudbufferten. Den här bufferten innehåller data som Sound-objektet ska spela upp. När du anropar play()-metoden för Sound-objektet skickas händelsen sampleData när nya ljuddata begärs. (Detta gäller bara om Sound-objektet inte har läst in MP3-data från en fil.)

SampleDataEvent-objektet omfattar en data-egenskap. I händelseavlyssnaren ska du skriva ByteArray-objekt till det här data-objektet. De bytearrayer som du skriver till det här objektet lägger till buffertlagrade ljuddata som Sound-objektet spelar upp. Bytearrayen i bufferten är en ström med flyttalsvärden från -1 till 1. Varje flyttalsvärde representerar amplituden för en kanal (vänster eller höger) för en ljudsampling. Ljud samplas med 44 100 samplingar per sekund. Varje sampling innehåller en höger- och vänsterkanal, sammanflätade som flyttalsdata i bytearrayen.

I hanterarfunktionen använder du metoden ByteArray.writeFloat() för att skriva till data-egenskapen för händelsen sampleData. Följande kod genererar till exempel en sinusvåg:

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

När du anropar Sound.play() börjar programmet att anropa händelsehanteraren, och begär ljudsamplingsdata. Programmet fortsätter att skicka händelser när ljudet spelas upp fram till dess att du inte anger mer data eller tills SoundChannel.stop() anropas.

Händelsens tidsfördröjning kan variera från plattform till plattform och kan ändras i framtida versioner av Flash Player och AIR. Var inte beroende av en specifik tidsfördröjning, beräkna den i stället. Tidsfördröjningen beräknas med följande formel:

(SampleDataEvent.position / 44.1) - SoundChannelObject.position

Ange 2 048 till och med 8 192 samplingar för egenskapen data för SampleDataEvent-objektet (för varje anrop till händelseavlyssnaren). Ju fler samplingar (upp till 8 192), desto bättre prestanda. Ju färre samplingar, desto mer troligt är det att störningar inträffar under uppspelning. Det här beteendet är olika på olika plattformar och inträffar i olika situationer, till exempel när webbläsare ändrar storlek. Kod som fungerar på en plattform när du bara anger 2 048 samplingar kanske inte fungerar när den körs på en annan plattform. Om du kräver lägsta möjliga tidsfördröjning bör du överväga att göra mängden data valbar för användaren.

Om du anger färre än 2 048 samplingar (per anrop till händelseavlyssnaren sampleData) stannar programmet när resten av samplingarna har spelats upp. SoundChannel-objektet skickar sedan en SoundComplete-händelse.

Ändra ljud från MP3-data

Använd metoden Sound.extract() när du vill hämta data från ett Sound-objekt. Du kan använda (och ändra) dessa data om du vill skriva till den dynamiska strömmen för ett annat Sound-objekt för uppspelning. Följande kod använder byte för en inläst MP3-fil och skickar dem via en filterfunktion, 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; 
}

Begränsningar för genererade ljud

När du använder en sampleData-händelseavlyssnare med ett Sound-objekt är de enda övriga Sound-metoder som aktiveras Sound.extract() och Sound.play(). Anrop av andra metoder eller egenskaper resulterar i ett undantag. Alla metoder och egenskaper för SoundChannel-objektet är fortfarande aktiverade.