基本的に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);
}
}
}
}