gpt4 book ai didi

actionscript-3 - 存储在 ByteArray 中并加载到 Sound 对象中的生成音频没有循环?

转载 作者:行者123 更新时间:2023-12-04 04:32:26 36 4
gpt4 key购买 nike

编辑2:这个问题仍然存在,但似乎是一个错误。土坯 Sound类不发送Sound.length加载后的值 ByteArray .这是我提交的错误报告(请投赞成票!):

https://bugbase.adobe.com/index.cfm?event=bug&id=3749649

= = = = =

下面的代码可以产生一次声音——它播放正确的声音,但不循环。我相信应该。我似乎无法调试它

它似乎也没有抛出 SOUND_COMPLETE 事件。我在这里错过了什么吗?

编辑:仍然损坏,但我更新了下面的代码,以便您可以对其进行测试。只需复制到类(class)并调用 testSound() :

private var NUM_SAMPLES:int = 16384 * 2;
private var soundByteArray:ByteArray;
private var volume:Number = 1;
private var channel:SoundChannel = new SoundChannel();
private var RATE:int = 44100;


public function testSound():void
{
var baseSound:Sound = new Sound();
storeAudio();
var trans:SoundTransform = new SoundTransform(volume, 0);
SoundMixer.soundTransform = trans;

soundByteArray.position = 0;
baseSound.loadPCMFromByteArray(soundByteArray, NUM_SAMPLES, "float", true, RATE);
soundByteArray.position = 0;

baseSound.addEventListener(flash.events.Event.SOUND_COMPLETE, onPlaybackComplete);

trace("loaded 1: " + baseSound.length);
trace("loaded 2: " + baseSound.bytesLoaded);
trace("loaded 3: " + baseSound.bytesTotal);

channel = baseSound.play(0, 20, trans);
channel.addEventListener(flash.events.Event.SOUND_COMPLETE, onPlaybackComplete);
}

protected function onPlaybackComplete(event:flash.events.Event):void
{
trace("onPlaybackComplete" + channel.position);
}

private function storeAudio():void
{
soundByteArray = new ByteArray();
for (var i:Number = 0; i < NUM_SAMPLES; i++)
{
soundByteArray.writeFloat(
Math.sin(
((i / RATE))
* Math.PI * 2 * 440
)
);
soundByteArray.writeFloat(
Math.sin(
((i / RATE))
* Math.PI * 2 * 440
)
);
}

trace("storeAudio i = " + i + ", " + soundByteArray.length);
}

最佳答案

好的,我很感激你接受了这个问题作为一个错误,并可能继续前进。但是我使用了一个小技巧来重放 loadPCMFromByteArray。而不是依赖 Sound.Complete只需编写知道何时完全达到 PCM 音频字节长度的代码。

来自 converting bytes length to milliseconds并使用 channel.position您将获得与 基本相同的结果.完成功能(如果我在这里错了,任何人都可以纠正我)。如果您确实需要触发事件,即为了某些依赖该反馈的函数,那么您可以简单地发送自己的自定义事件并监听该事件而不是 Sound.Complete
从测试中我推断连续的故障/咔嗒声实际上是 Flash 试图向前播放声音但没有移动到 PCM 数据的最后字节太远。
将其视为在 ByteArrays 中发现的 E-O-F 错误的一个非常可听的版本,但随后也从内部运行(永无止境?)while loop只是为了取悦你的耳朵。

代码前的一些注意事项:

  • 在测量的声音结尾我试过.. soundByteArray.position = 0;不好! channel.position 跟踪显示为卡在 上结束位置 数量。也试过channel = baseSound.play(0);不好! channel.position跟踪显示卡在 零位两者都发出了结结巴巴的声音
  • 此外,虽然这次我没有尝试过,但我之前已经循环过 sampleData,没有出现任何故障,所以我确定考虑将 PCM 复制到 sampleData 设置也是值得的,看看它是否更适合循环和触发 Sound.Complete 等.

  • 如果它只是您正在生成和循环的简单音调,您甚至不需要使用 PCMdata,只需使用 sampleData 作为首选进行动态声音生成。但是,如果您涉及人声或乐队音乐的 PCM 样本,那么您将需要下面的 hack 来重播声音结尾

    所以无论如何,现在这里有一些代码演示来说明循环黑客
     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);

    }

    }
    }

    关于actionscript-3 - 存储在 ByteArray 中并加载到 Sound 对象中的生成音频没有循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23258515/

    36 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com