В основном я использую AS3 для создания тона. Мне нужно иметь возможность передать моей функции массив, который будет выглядеть примерно так {0,50,100,0,20,500,200,100}
, каждый из которых представляет миллисекунды. Это было бы просто «выкл, вкл, выкл, вкл, выкл» и т. Д., И мне нужно, чтобы тон проигрывался с точностью до миллисекунды, без задержек или икоты.
Я попытался сделать функцию с таймерами, чтобы выполнить это... но это действительно не так точно, как мне нужно. Есть небольшие задержки, и заметно, что действительно короткие проигрываются не так коротко, как нужно.
Я думал, что просто воспроизведу свой тон, а затем использую SoundTransform для включения и выключения громкости, и это может помочь сделать его быстрее, поскольку я не запускаю и не останавливаю звук, я просто манипулирую громкостью в реальном времени. время.
Но, может быть, его замедляет не громкость, а может быть, просто таймеры не так надежны. Вот мой код, функция просто зацикливается, пока я не остановлю ее с помощью другой имеющейся у меня функции. Любые предложения о том, как сделать это более точным?
Моя функция, которая обрабатывает массив со всеми таймерами
private function soundPattern(patternArr:Array):void
{
//setup vars
var pTotal:Number = patternArr.length;
var pCount:Number = 0;
if(pTotal >=1)
{
//setup listenrs
patTimer = new Timer(patternArr[pCount],1);
patTimer.addEventListener(TimerEvent.TIMER_COMPLETE, comp);
function comp(e:TimerEvent=null):void
{
pCount++;
if(pCount != pTotal)
{
patTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, comp);
toneGen.soundTrans.volume=1;
toneGen.toneChannel.soundTransform = toneGen.soundTrans;
patTimer = new Timer(patternArr[pCount],1);
patTimer.addEventListener(TimerEvent.TIMER_COMPLETE, compTwo);
if(patternArr[pCount]>0)
{
patTimer.reset();
patTimer.start();
}
else
{
compTwo();
}
}
else if(repeat)
{
trace("1resetting...");
patTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, comp);
pCount = 0;
patTimer = new Timer(patternArr[pCount],1);
patTimer.addEventListener(TimerEvent.TIMER_COMPLETE, compTwo);
toneGen.soundTrans.volume=0;
toneGen.toneChannel.soundTransform = toneGen.soundTrans;
if(patternArr[pCount]>0)
{
patTimer.reset();
patTimer.start();
}
else
{
compTwo();
}
}
}
//in-between
function compTwo(e:TimerEvent=null):void
{
pCount++;
if(pCount != pTotal)
{
patTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, compTwo);
patTimer = new Timer(patternArr[pCount],1);
patTimer.addEventListener(TimerEvent.TIMER_COMPLETE, comp);
toneGen.soundTrans.volume=0;
toneGen.toneChannel.soundTransform = toneGen.soundTrans;
if(patternArr[pCount]>0)
{
patTimer.reset();
patTimer.start();
}
else
{
comp();
}
}
else if(repeat)
{
trace("2resetting...");
patTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, compTwo);
pCount = 0;
patTimer = new Timer(patternArr[pCount],1);
patTimer.addEventListener(TimerEvent.TIMER_COMPLETE, comp);
toneGen.soundTrans.volume=0;
toneGen.toneChannel.soundTransform = toneGen.soundTrans;
if(patternArr[pCount]>0)
{
patTimer.reset();
patTimer.start();
}
else
{
comp();
}
}
}
//get the tone started, but remember the first is a pause
toneGen.startTone();
//start things
if(patternArr[pCount]>0)
{
patTimer.reset();
patTimer.start();
}
else
{
comp();
}
}
}
и вот класс toneGen, который я использую
package
{
import flash.events.SampleDataEvent;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundTransform;
public class ToneGenerator {
[Bindable]
public var amp_multiplier_right:Number = 0.5;
[Bindable]
public var amp_multiplier_left:Number = 0.5;
[Bindable]
public var freq_right:Number = 580;
[Bindable]
public var freq_left:Number = 580;
public static const SAMPLING_RATE:int = 44100;
public static const TWO_PI:Number = 2*Math.PI;
public static const TWO_PI_OVER_SR:Number = TWO_PI/SAMPLING_RATE;
public var tone:Sound;
public var toneChannel:SoundChannel;
public var soundTrans:SoundTransform;
public function ToneGenerator() {
}
public function stopTone():void {
if(tone)
{
toneChannel.stop();
tone.removeEventListener(SampleDataEvent.SAMPLE_DATA, generateSineTone);
}
}
public function startTone():void {
tone = new Sound();
tone.addEventListener(SampleDataEvent.SAMPLE_DATA, generateSineTone);
soundTrans = new SoundTransform(0);
toneChannel = tone.play();
toneChannel.soundTransform = soundTrans;
}
public function generateSineTone(e:SampleDataEvent):void {
var sample:Number;
for(var i:int=0;i<8192;i++) {
sample = Math.sin((i+e.position) * TWO_PI_OVER_SR * freq_left);
e.data.writeFloat(sample * amp_multiplier_left);
sample = Math.sin((i+e.position) * TWO_PI_OVER_SR * freq_right);
e.data.writeFloat(sample * amp_multiplier_right);
}
}
}
}