actionscript-3 - 消除AS3中产生的声音中不必要的咔嗒声

标签 actionscript-3 flash audio

在Flash中生成声波时出现以下问题。
这是生成器部分:

const SAMPLING_RATE:int = 44100;
const TWO_PI:Number = 2 * Math.PI;
const TWO_PI_OVER_SR:Number = TWO_PI / SAMPLING_RATE;
const SAMPLE_SIZE:int = 8192 / 4;


function generateSine(fq:Number):ByteArray
{
var bytes:ByteArray = new ByteArray();
var sample:Number;
var amp:Number = 1;


for (var i:int=0; i<SAMPLE_SIZE; i++)
{
    sample = amp* Math.sin(i  * TWO_PI_OVER_SR *   fq  );
    bytes.writeFloat(sample);
}


bytes.position = 0;
return bytes;
 }

这是回放部分:
function playbackSampleHandler(event:SampleDataEvent):void
{
var sample:Number;

for (var i:int = 0; i <  SAMPLE_SIZE && soundData.bytesAvailable; i++)
{
    sample = soundData.readFloat();
    event.data.writeFloat(sample);
    event.data.writeFloat(sample);
}
 }



 function onClickPlay(e:MouseEvent)
 {
soundData= new ByteArray();
    var sound:ByteArray= new ByteArray();
    sound=generateSine(440);
soundData.writeBytes(sound,0,sound.length);
soundData.position = 0;
morphedSound.addEventListener(SampleDataEvent.SAMPLE_DATA, playbackSampleHandler);
soundChannel = morphedSound.play();             
 }

快速说明:
我基本上将正弦函数的值写入ByteArray中,然后播放处理程序读取该数组并播放声音。我只写了一个8192/4样本缓冲区。

问题:
我的问题是,当您执行此操作时,声音的末端会产生令人讨厌的咔嗒声,这是正弦波的伪像被切成非0的值。所以我的问题是如何避免这种情况?

奖金:
我还想知道,当Flash中的缓冲区非常严格(即从2048到8192)时,如何才能准确地生成100毫秒的正弦波?

链接:
如果有帮助,我的代码基于本教程
http://www.bit-101.com/blog/?p=2669
和我自己的探索。

最佳答案

您需要保留在样本数据处理结束时出现的正弦波相位。否则,您的正弦波将无法平稳持续,并且您会听到咔嗒声。

var totalSamples:int=0;
function generateSine(fq:Number):ByteArray
{
var bytes:ByteArray = new ByteArray();
var sample:Number;
var amp:Number = 1;


for (var i:int=0; i<SAMPLE_SIZE; i++)
{
    sample = amp* Math.sin((i+totalSamples)  * TWO_PI_OVER_SR *   fq  );
    // this uses stored phase ^^^
    bytes.writeFloat(sample);
}
totalSamples+=SAMPLE_SIZE; // this preserves phase between subsequent samples

bytes.position = 0;
return bytes;

}

更新:我注意到您连续两次调用了Generator-这太糟糕了。如果只需要一个函数的工作结果,就决不能两次调用该函数。

函数onClickPlay(e:MouseEvent)
{
soundData = generateSine(440); //如果我们只能使用赋值,为什么还要使用writeBytes?
soundData.position = 0;
morphedSound.addEventListener(SampleDataEvent.SAMPLE_DATA,playingSampleHandler);
soundChannel = morphedSound.play();
}

另外,要使声音以完整的(半)声波结束并消除需要的最后单击,请使用以下技术:
function generateSine(fq:Number,cleanFinish:Boolean=false):ByteArray
{
var bytes:ByteArray = new ByteArray();
var sample:Number;
var amp:Number = 1;


for (var i:int=0; i<SAMPLE_SIZE; i++)
{
    sample = amp* Math.sin((i+totalSamples)  * TWO_PI_OVER_SR *   fq  );
    // this uses stored phase ^^^
    bytes.writeFloat(sample);
    if (cleanFinish) 
      if ((Math.abs(sample)<(SAMPLING_RATE/fq/3))&&(i>SAMPLE_SIZE-SAMPLING_RATE/fq)) break; 
    // this triggers a drop if we are sampling the last wave already
}
totalSamples+=i; // this preserves phase between subsequent samples

bytes.position = 0;
return bytes;

}

使用可选的 bool(boolean) 参数设置为true来调用此函数,以接收正确终止的wave。

关于actionscript-3 - 消除AS3中产生的声音中不必要的咔嗒声,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18440872/

相关文章:

actionscript-3 - 反编译、修改和编译 Flash 对象

jquery - 单击时重新加载/重置嵌入的 swf

actionscript-3 - 动态 xml 文本和图像不会在 Flash 中刷新

使动画对声音文件使用react的 JavaScript 代码在 Edge 中有效,但在 Chrome 中无效

java - 使用Java提取音频增益

javascript - 如果我给你一个函数的引用,你能得到函数的名称吗?

php - 如何使用 actionscript 和 javascript 在客户端获取文件大小?

javascript - 使用 jQuery 访问 Flash 函数

javascript - 音频节点实时输入-找不到声音不断更新的麻烦

actionscript-3 - 如何停止 Flex/AIR 异或填充?