基本上我使用 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);
}
}
}
}