在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/