Работа с динамически создаваемым звуком

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

Примечание. Возможность динамического создания аудио доступна для использования, начиная с Flash Player версии 10 и Adobe AIR версии 1.5.

Вместо загрузки или потоковой передачи существующего звука можно использовать аудиоданные, создаваемые в динамическом режиме. Можно создавать аудиоданные, когда регистрируется прослушиватель события sampleData объекта Sound. (Событие sampleData определено в классе SampleDataEvent в пакете flash.events.) В такой среде объект Sound не загружает аудиоданные из файла. Вместо этого он выполняет функцию сокета для потока звуковых данных, направляемых ему при помощи функции, назначенной для этого события.

Когда для объекта Sound добавляется прослушиватель события sampleData , объект периодически запрашивает данные для добавления в аудиобуфер. Этот буфер содержит данные, которые должен воспроизводить объект Sound. Когда вызывается метод play() объекта Sound, он отправляет событие sampleData , запрашивая новые аудиоданные. (Это происходит, только если объект Sound еще не загрузил данных mp3 из файла.)

Объект SampleDataEvent включает свойство data . В прослушивателе событий в этот объект data записываются объекты ByteArray. Записываемые для этого объекта массивы байтов добавляются в буфер к аудиоданным, которые воспроизводит объект Sound. Массив байтов в буфере является потоком, содержащим значения с плавающей запятой от -1 до 1. Каждое значение с плавающей запятой представляет амплитуду одного канала (левого или правого) звукового сэмпла. Частота дискретизации (сэмплирования) звука составляет 44100 сэмплов в секунду. Каждый сэмпл включает левый и правый канал, которые чередуются как данные с плавающей запятой в массиве байтов.

В функции обработчика используется метод ByteArray.writeFloat() для записи свойства data события sampleData . Например, следующий код создает синусоидальную волну.

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

Передайте от 2048 до 8192 сэмплов свойству data объекта SampleDataEvent (для каждого вызова прослушивателя событий). Для лучшей производительности укажите как можно больше сэмплов (до 8192). Чем меньше сэмплов вы укажете, тем больше вероятность возникновения звуковых помех во время воспроизведения. Однако этот принцип действует по-разному на разных платформах, и помехи могут возникнуть в различных ситуациях, например при изменении размера обозревателя. Код, который на одной платформе работает всего при 2048 сэмплах, может плохо работать на другой платформе. Если вам требуется как можно меньший период ожидания, предоставьте пользователям возможность выбирать объем данных.

Если передавать меньше 2048 сэмплов (для одного вызова прослушивателя события sampleData ), приложение останавливается после воспроизведения оставшихся сэмплов Затем объект SoundChannel отправляет событие SoundComplete.

Изменение звука, полученного из данных mp3

Для извлечение данных из объекта Sound служит метод Sound.extract() . Полученные данные можно использовать (или изменять) для записи в динамический поток другого объекта 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 остаются доступными.