Actionscript 3 生成的音频没有循环存储在ByteArray中并加载到声音对象中?
编辑2:这个问题仍然存在,但似乎是一个bug。AdobeActionscript 3 生成的音频没有循环存储在ByteArray中并加载到声音对象中?,actionscript-3,audio,Actionscript 3,Audio,编辑2:这个问题仍然存在,但似乎是一个bug。AdobeSound类在加载ByteArray后不发送Sound.length值。这是我提交的bug报告(请投赞成票!) ===== 下面的代码只产生一次声音——它播放正确的声音,但不循环。我认为应该这样。我似乎无法调试它 它似乎也不会给整个事件带来好的结果。我是不是遗漏了什么 编辑:仍然是坏的,但我更新了下面的代码,所以你可以测试它。只需复制到类并调用testSound(): private var NUM_SAMPLES:int=16384*2
Sound
类在加载ByteArray
后不发送Sound.length
值。这是我提交的bug报告(请投赞成票!)
=====
下面的代码只产生一次声音——它播放正确的声音,但不循环。我认为应该这样。我似乎无法调试它
它似乎也不会给整个事件带来好的结果。我是不是遗漏了什么
编辑:仍然是坏的,但我更新了下面的代码,所以你可以测试它。只需复制到类并调用testSound()
:
private var NUM_SAMPLES:int=16384*2;
私人银行:ByteArray;
私有var卷:数量=1;
私有变量通道:SoundChannel=新的SoundChannel();
私人风险值率:int=44100;
公共函数testSound():void
{
var baseSound:Sound=新声音();
storeAudio();
var trans:SoundTransform=新的SoundTransform(音量,0);
SoundMixer.soundTransform=trans;
soundByteArray.position=0;
baseSound.loadPCMFromByteArray(soundByteArray,NUM_样本,“float”,true,RATE);
soundByteArray.position=0;
baseSound.addEventListener(flash.events.Event.SOUND_COMPLETE,onPlaybackComplete);
记录道(“加载1:+baseSound.长度);
跟踪(“加载2:+基音。字节加载”);
跟踪(“加载3:+baseSound.ByTestTotal”);
通道=基音。播放(0,20,trans);
channel.addEventListener(flash.events.Event.SOUND_COMPLETE,onPlaybackComplete);
}
播放完成时受保护的函数(事件:flash.events.event):无效
{
跟踪(“onPlaybackComplete”+通道位置);
}
私有函数storeAudio():void
{
soundByteArray=新的ByteArray();
对于(变量i:Number=0;i
好的,我很感谢您将此问题视为一个bug并可能继续。然而,我使用了一个小黑客来重播loadPCMFromByteArray。不要依赖声音。完成
只需编写知道何时完全达到PCM音频字节长度的代码
通过将字节长度转换为毫秒
并使用channel.position
您将获得与.Complete功能基本相同的结果(如果我在这里出错,任何人都可以纠正我)。如果您确实需要触发事件,即为了某些依赖于该反馈的功能,那么您只需发送您自己的自定义事件并监听该事件,而不是声音。完成
从测试中,我认为持续的小故障/咔哒声实际上是Flash试图向前播放声音,但不会移动到PCM数据的最后字节。
可以将其视为ByteArray中发现的E-O-F错误的一个非常听得见的版本,但也可以从内部运行(永不结束?而循环
只是为了愉悦您的耳朵
代码前的一些注意事项:
- 在测量音结束时,我试着<代码>soundByteArray.position=0代码>不好!channel.position跟踪显示为卡在结束pos金额上。也试过
channel=baseSound.play(0)代码>不好<代码>频道。位置
轨迹显示为卡在零位置。两者都发出了口吃声
- 此外,虽然我这次没有尝试,但我以前循环过sampleData,没有出现故障,因此我确信值得考虑将PCM复制到sampleData设置中,并查看循环和触发声音是否更有效。完成等
如果只是简单的音调生成和循环,您甚至不需要使用PCMdata,只需使用sampleData作为第一选择就可以进行动态声音生成。然而,如果你涉及到人声或乐队音乐的PCM样本,那么你将需要下面的技巧在声音结束时重播
不管怎样,现在这里有一些代码演示来说明循环黑客
package
{
import flash.display.MovieClip;
import flash.events.*;
import flash.utils.*;
import flash.media.*;
import flash.text.*;
public class testSound extends MovieClip
{
private var BIT_TYPE:int = 16; //16bit audio
private var RATE:int = 44100;
private var NUM_SAMPLES:int = 8192; //16384 * 2;
private var NUM_CHANNEL:int = 2; //if stereo
private var NUM_TEMP:int =0; //adjustable number for test without changing others
public var NUM_TONE_FREQ:int = 440;
private var soundByteArray:ByteArray;
private var volume:Number = 1;
private var channel:SoundChannel = new SoundChannel();
public var final_samples:int = 0;
public var time_total:Number; //dont use Integers here - wont always be correct
public var time_kbps:Number; //"bytes per second" count
public var loop_count:int = 0;
public var timerCount:Number = 0;
public var timerSecs:Number = 0;
public var timer:Timer;
public var trans:SoundTransform;
public var baseSound:Sound = new Sound();
public var timeText:TextField;
public var txtFormat:TextFormat;
public function testSound():void
{
//correct NUM_SAMPLES helps with end-time check
NUM_SAMPLES *= NUM_CHANNEL * BIT_TYPE;
trans = new SoundTransform(volume, 0);
channel.soundTransform = trans; //SoundMixer.soundTransform = trans;
soundByteArray = new ByteArray();
soundByteArray.position = 0;
//setup textField for debug feedback
setupTextFBack();
//generate PCM
storeAudio();
}
protected function onPlaybackComplete(event:flash.events.Event):void
{
//only works if you are passing your PCM to sampleData events,
trace("onPlaybackComplete" + channel.position);
}
private function storeAudio():void
{
for (var i:Number = 0; i < NUM_SAMPLES; i++)
{
soundByteArray.writeFloat
( Math.sin((i / RATE) * Math.PI * 2 * NUM_TONE_FREQ) );
soundByteArray.writeFloat
( Math.sin((i / RATE) * Math.PI * 2 * NUM_TONE_FREQ) );
}
trace("storeAudio samples (i) = " + i + ", ByteArray length: " + soundByteArray.length);
final_samples = i;
playAudio();
}
public function playAudio():void
{
soundByteArray.position = 0;
baseSound.loadPCMFromByteArray(soundByteArray, final_samples, "float", true, RATE);
channel = baseSound.play(); //channel = baseSound.play(0, 0, trans);
setupTimeCount(); //count when play starts
time_kbps = (RATE * NUM_CHANNEL * BIT_TYPE) / 4; //not /8 because time is never doubled on stereo
time_total = (soundByteArray.length / time_kbps);
time_total = Math.round(time_total * 100) / 100;
trace ("=== DEBUG INFO : (loop: "+loop_count+ ") =========================================");
trace ("*** Playing beyond Total Time (PCM end) creates sound glitch issues ");
trace ("*** Re-Play on a continous Tone will creates short click when it stops to replay ");
trace ("*** If PCM was music/vocals this click might not be perceived by ear if looped right");
trace ("====================================================================");
trace ("Total Kb/sec : " + time_kbps + " bytes per sec");
trace ("Total time : " + time_total + " secs" );
//trim Total millisecs just to avoid any glitches/clicks. Test & fine-tune
time_total -= 0.314; //PI divided by 10. Need fine-tune? Hell Yes!
trace ("Total (trim) : " + time_total + " secs" );
}
public function setupTimeCount():void
{
timer = new Timer(100);
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timerCount = 0;
timer.start();
}
function timerHandler(Event:TimerEvent):void
{
timerCount += 100;
checkTime(timerCount);
//trace("channel.pos = " + channel.position); //for debug only
}
function checkTime(miliseconds:int) : void
{
timerSecs = miliseconds/1000;
timeText.text = ("elapsed : " + timerSecs);
//if (timerSecs >= time_total)
if ( channel.position >= (time_total * 1000) )
{
reloopAudio();
}
}
function reloopAudio():void
{
channel.stop(); //else you get stutter from going forward
timer.stop();
trace("attempting replay / loop..");
loop_count += 1;
playAudio(); //redo playing function
}
public function setupTextFBack():void
{
txtFormat = new TextFormat();
txtFormat.size = 20;
txtFormat.font = "Arial";
timeText = new TextField();
timeText.defaultTextFormat = txtFormat;
timeText.antiAliasType = AntiAliasType.ADVANCED;
timeText.x = stage.stageWidth / 2 ;
timeText.y = stage.stageHeight / 2 ;
timeText.textColor = 0xFF0000;
timeText.text = " ";
timeText.width = 200;
addChild(timeText);
}
}
}
包
{
导入flash.display.MovieClip;
导入flash.events.*;
导入flash.utils。*;
导入flash.media.*;
导入flash.text.*;
公共类testSound扩展了MovieClip
{
私有变量位类型:int=16;//16位音频
私人风险值率:int=44100;
私有变量NUM_SAMPLES:int=8192;//16384*2;
专用var NUM_通道:int=2;//如果立体声
private var NUM_TEMP:int=0;//在不更改其他值的情况下,测试的可调整值
公共变量NUM\u TONE\u FREQ:int=440;
私人银行:ByteArray;
私有var卷:数量=1;
私有变量通道:SoundChannel=新的SoundChannel();
公共var最终样本:int=0;
public var time\u total:Number;//此处不要使用整数-不会总是正确的
公共变量时间\u kbps:Number;/“每秒字节数”计数
公共变量循环计数:int=0;
公共变量timerCount:Number=0;
公共变量timerSecs:Number=0;
公共变量计时器:计时器;
公共变量转换:声音转换;
public var baseSound:Sound=新声音();
公共变量timeText:TextField;
公共变量txtFormat:TextFormat;
公共函数testSound():void
{
//正确的NUM_示例有助于结束时间检查
NUM_SAMPLES*=NUM_信道*位类型;
trans=新的声音转换(音量,0);
channel.soundTransform=trans;//SoundMixer.soundTransform=trans;
soundByteArray=新的ByteArray();
soundByteArray.position=0;
//调试反馈的设置文本字段
setupTextFBack();
//生成PCM
storeAudio();
}
package
{
import flash.display.MovieClip;
import flash.events.*;
import flash.utils.*;
import flash.media.*;
import flash.text.*;
public class testSound extends MovieClip
{
private var BIT_TYPE:int = 16; //16bit audio
private var RATE:int = 44100;
private var NUM_SAMPLES:int = 8192; //16384 * 2;
private var NUM_CHANNEL:int = 2; //if stereo
private var NUM_TEMP:int =0; //adjustable number for test without changing others
public var NUM_TONE_FREQ:int = 440;
private var soundByteArray:ByteArray;
private var volume:Number = 1;
private var channel:SoundChannel = new SoundChannel();
public var final_samples:int = 0;
public var time_total:Number; //dont use Integers here - wont always be correct
public var time_kbps:Number; //"bytes per second" count
public var loop_count:int = 0;
public var timerCount:Number = 0;
public var timerSecs:Number = 0;
public var timer:Timer;
public var trans:SoundTransform;
public var baseSound:Sound = new Sound();
public var timeText:TextField;
public var txtFormat:TextFormat;
public function testSound():void
{
//correct NUM_SAMPLES helps with end-time check
NUM_SAMPLES *= NUM_CHANNEL * BIT_TYPE;
trans = new SoundTransform(volume, 0);
channel.soundTransform = trans; //SoundMixer.soundTransform = trans;
soundByteArray = new ByteArray();
soundByteArray.position = 0;
//setup textField for debug feedback
setupTextFBack();
//generate PCM
storeAudio();
}
protected function onPlaybackComplete(event:flash.events.Event):void
{
//only works if you are passing your PCM to sampleData events,
trace("onPlaybackComplete" + channel.position);
}
private function storeAudio():void
{
for (var i:Number = 0; i < NUM_SAMPLES; i++)
{
soundByteArray.writeFloat
( Math.sin((i / RATE) * Math.PI * 2 * NUM_TONE_FREQ) );
soundByteArray.writeFloat
( Math.sin((i / RATE) * Math.PI * 2 * NUM_TONE_FREQ) );
}
trace("storeAudio samples (i) = " + i + ", ByteArray length: " + soundByteArray.length);
final_samples = i;
playAudio();
}
public function playAudio():void
{
soundByteArray.position = 0;
baseSound.loadPCMFromByteArray(soundByteArray, final_samples, "float", true, RATE);
channel = baseSound.play(); //channel = baseSound.play(0, 0, trans);
setupTimeCount(); //count when play starts
time_kbps = (RATE * NUM_CHANNEL * BIT_TYPE) / 4; //not /8 because time is never doubled on stereo
time_total = (soundByteArray.length / time_kbps);
time_total = Math.round(time_total * 100) / 100;
trace ("=== DEBUG INFO : (loop: "+loop_count+ ") =========================================");
trace ("*** Playing beyond Total Time (PCM end) creates sound glitch issues ");
trace ("*** Re-Play on a continous Tone will creates short click when it stops to replay ");
trace ("*** If PCM was music/vocals this click might not be perceived by ear if looped right");
trace ("====================================================================");
trace ("Total Kb/sec : " + time_kbps + " bytes per sec");
trace ("Total time : " + time_total + " secs" );
//trim Total millisecs just to avoid any glitches/clicks. Test & fine-tune
time_total -= 0.314; //PI divided by 10. Need fine-tune? Hell Yes!
trace ("Total (trim) : " + time_total + " secs" );
}
public function setupTimeCount():void
{
timer = new Timer(100);
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timerCount = 0;
timer.start();
}
function timerHandler(Event:TimerEvent):void
{
timerCount += 100;
checkTime(timerCount);
//trace("channel.pos = " + channel.position); //for debug only
}
function checkTime(miliseconds:int) : void
{
timerSecs = miliseconds/1000;
timeText.text = ("elapsed : " + timerSecs);
//if (timerSecs >= time_total)
if ( channel.position >= (time_total * 1000) )
{
reloopAudio();
}
}
function reloopAudio():void
{
channel.stop(); //else you get stutter from going forward
timer.stop();
trace("attempting replay / loop..");
loop_count += 1;
playAudio(); //redo playing function
}
public function setupTextFBack():void
{
txtFormat = new TextFormat();
txtFormat.size = 20;
txtFormat.font = "Arial";
timeText = new TextField();
timeText.defaultTextFormat = txtFormat;
timeText.antiAliasType = AntiAliasType.ADVANCED;
timeText.x = stage.stageWidth / 2 ;
timeText.y = stage.stageHeight / 2 ;
timeText.textColor = 0xFF0000;
timeText.text = " ";
timeText.width = 200;
addChild(timeText);
}
}
}