#flash #actionscript-3 #audio #mp3 #flashdevelop
#вспышка #actionscript-3 #Аудио #mp3 #разработка flash
Вопрос:
Доброе утро!
Я пытаюсь создать визуальную форму сигнала для MP3. Код, который я включил, вызывается при успешной загрузке MP3. Я намерен извлечь всего несколько важных сэмплов из звука для создания формы сигнала, а не извлекать весь звук в bytearray. Даже на хорошей машине извлечение всей песни может привести к зависанию flash на 3-5 секунд (или дольше!). Для моих целей это невозможно.
К сожалению, приведенный ниже код не выдает никаких чисел. Если я извлекаю всю песню, она работает, но извлечение только ключевых моментов мне ничего не дает. Делает ли выполнение извлечения оставшуюся часть звукового объекта недопустимой для будущих извлечений? Если да, есть ли какой-нибудь способ обойти это, который не приведет к зависанию flash на длительный период времени во время извлечения?
Некоторые важные переменные из остальной части кода:
waveFormWidth: статическая ширина спрайта формы волны.
waveFormHeight: статическая высота спрайта формы волны.
песня: звуковой объект, который я буду использовать для создания формы волны.
public function mapWaveForm(e:Event = null):void
{
// Clear the wave form sprite
waveForm.graphics.clear();
waveForm.graphics.lineStyle(0, 0x000000, 1);
// Storage for the wave form bit data
var byteOutput:ByteArray;
var leftPeakSize:Number;
var rightPeakSize:Number;
var songTotalSamples:int;
var thisSample:int;
byteOutput = new ByteArray();
// How many samples?
songTotalSamples = (song.length * 44.1);
// Loop for the wave form width
for (var peakCount:int = 0; (peakCount < waveFormWidth); peakCount )
{
// Get info at each peak.
thisSample = Math.floor(songTotalSamples * (peakCount / waveFormWidth));
song.extract(byteOutput, 1, thisSample);
byteOutput.position = 0;
trace(thisSample, byteOutput.readFloat());
leftPeakSize = byteOutput.readFloat() / 1.27;
rightPeakSize = byteOutput.readFloat() / 1.27;
// Turn those peaks into something usable.
leftPeakSize = leftPeakSize * (waveFormHeight * .5);
rightPeakSize = rightPeakSize * (waveFormHeight * .5);
// Make the left channel line
waveForm.graphics.moveTo(peakCount, (waveFormHeight * .5));
waveForm.graphics.lineTo(peakCount, (waveFormHeight * .5) - leftPeakSize);
// Make the right channel line
waveForm.graphics.moveTo(peakCount, (waveFormHeight * .5));
waveForm.graphics.lineTo(peakCount, (waveFormHeight * .5) rightPeakSize);
}
}
Спасибо за вашу помощь, ребята!
Ответ №1:
Как бы то ни было, я просто работал над ТОЧНО такой же вещью, и я только что получил ее после некоторых исследований. Кажется, я не могу заставить его работать с файлами WAV, но это совместимо с файлами MP3 всех типов. Вот что у меня получилось:
var IMAGE_SIZE:int = new int(600); // Final width of image
var IMAGE_DEPTH:int = new int(5); // How many passes per pixel of image
var RESOLUTION:int = new int(IMAGE_SIZE * IMAGE_DEPTH);
var DRAW_AMPLITUDE:int = new int(150); // pixel height of max volume line
var waveForm:Shape = new Shape();
var mp3File:Sound = new Sound();
mp3File.load(new URLRequest("audio.mp3"));
mp3File.addEventListener(Event.COMPLETE, parseSound);
function parseSound(e:Event):void {
var soundBytes:ByteArray = new ByteArray();
for (var i:int=0; i<RESOLUTION; i ) {
mp3File.extract(soundBytes, 1, Math.floor((mp3File.length*44.1)*(i/RESOLUTION)));
soundBytes.position = 0;
while (soundBytes.bytesAvailable > 0) {
var tmpNum:Number = new Number();
tmpNum = soundBytes.readFloat();
}
drawWave(i, tmpNum);
soundBytes.clear();
}
this.addChild(waveForm);
trace("--DONE--");
}
function drawWave(i:Number, amp:Number):void {
var pixX:Number = new Number(Math.floor(i/IMAGE_DEPTH));
var pixY:Number = new Number((amp*DRAW_AMPLITUDE)/2);
waveForm.graphics.lineStyle(1, 0x0, (1.2/IMAGE_DEPTH));
waveForm.graphics.moveTo(pixX, ((DRAW_AMPLITUDE/2)-pixY));
waveForm.graphics.lineTo(pixX, ((DRAW_AMPLITUDE/2) pixY));
}
Ответ №2:
Это старый пост, и, возможно, я не правильно понял ваш вопрос, но метод extract позволяет вам указать длину сэмплов и где в начале.
"public function extract(target:ByteArray, length:Number, startPosition:Number = -1):Number"
длина — это количество выборок для извлечения, а StartPosition — это то, с какой позиции в ByteArray начинать.
Смотрите http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/Sound.html#extract()
Ответ №3:
Используйте этот класс:
http://www.bytearray.org/?p=329
Я также включил это в действительно дерьмовый, непродуманный эксперимент, который я начал некоторое время назад при создании звукового микшера. Вы также можете получить исходный код для этого здесь:
Комментарии:
1. Привет, спасибо за ответ, но в вашем примере вы извлекаете весь звук. Это приводит к зависанию примерно на 4 секунды песни, которую я использую в качестве примера, и не является полезным для того, что я делаю. На самом деле я нашел ваш пример до того, как опубликовал здесь.
2. Вы извлекаете большой аудиофайл?
3. Это обычная песня. 10-15 минут? Мне нужно разместить MP3-файлы длиной до подкаста (более 120 минут), поэтому я пытаюсь извлечь отдельные сэмплы, а не все целиком.
4. Да, это будет проблемой, у вас задержка из-за огромного размера данных. Единственный другой способ, которым вы могли бы это сделать, — это динамически генерировать форму волны постепенно по мере воспроизведения песни с использованием SampleDataEvent.
5. Значит, нет способа стратегически получать отдельные сэмплы, а не извлекать все целиком? Объект sound уже полностью загружен, кажется немного странным, что нет способа обойти полное извлечение из bytearray.