【问题标题】:Synthesise variable length multi tonal audio with SoX while avoiding clipping使用 SoX 合成可变长度的多音调音频,同时避免削波
【发布时间】:2016-07-09 10:15:25
【问题描述】:

我先说我在音频处理和合成方面完全是新手,如果我做出一些愚蠢的假设或误解了核心概念,请纠正我。

我正在尝试使用 SoX 将数字数据数组转换为单个音频文件。到目前为止,我有两种“有效”的方法,它们产生了一些非常可怕的结果,并且都有严重的局限性。

我在 64 位 WIN 8.1 机器上通过 PHP 使用 SoX。

方法一输出单个音调然后连接

$toneLinks=array();
for($i=0;$i<count($sourceData);$i++){
  $filename='tones\\'.$dataTitle.'_'.$i.'.au';
  $soxCommand=$soxFolder.'sox -n '.$filename.' synth .5 sin '.($sourceData[$i]).' vol 0.5 ';
  shell_exec($soxCommand);
  $toneLinks[]=$filename;
}
$chunks=array_chunk($toneLinks,100);
$chunkFiles=array();
for($ch=0;$ch<count($chunks);$ch++){
  $name='tones\\'.$dataTitle.'_chunk_'.$ch.'.au';
  $soxCommand=$soxFolder.'sox ';
  for($i=0;$i<count($chunks[$ch]);$i++){
      $soxCommand.=' '.$chunks[$ch][$i]; 
  }
  $soxCommand.=' '.$name;
  $result=shell_exec($soxCommand);
  $chunkFiles[]=$name;
}
$soxCommand=$soxFolder.'sox ';
for($i=0;$i<count($chunkFiles);$i++){
  $soxCommand.=' '.$chunkFiles[$i]; 
}
$soxCommand.=' '.$dataTitle.'.au';
shell_exec($soxCommand);

限制:

  • 缓慢,需要多次单独执行
  • 混合似乎受到限制,即尝试加入 100 或 200 个文件将产生一个包含部分但不是全部音调的文件。尝试加入 1000 个文件将失败且没有输出。大概可以连接几个文件,然后连接那些连接的文件,但这会加剧第一个限制。在创建多个
  • 放弃了“混音”,并且能够使用更新的方法 1 成功连接任意数量的音调,因为这种方法显示出最大的希望,随着最终限制的进展,我将继续试验和更新。
  • 虽然不重要,但最终输出没有“流”,听起来就是这样,许多单独的音调粘在一起。

方法2在单个命令中生成“和弦”

$soxCommand=$soxFolder.'sox -n '.$dataTitle.'.au synth ';
for($i=1;$i<count($sourceData);$i++){
    $soxCommand.='.25 sin '.($sourceData[$i]).' ';  
}
$soxCommand.='delay ';
for($i=1;$i<count($sourceData);$i++){
    $soxCommand.=($i*.2).' ';   
}
$soxCommand.='remix - fade 0 '.(count($sourceData)*.2+.5).' .1 norm -1';
shell_exec($soxCommand);

限制:

  • 尝试创建具有 300 多个音调的“和弦”时会遇到 与最后一种方法类似的问题,但连接更小 使用这种方法的文件听起来很奇怪,因为 连接处有声音中断的组件。可以重叠文件,但这仍然不理想。
  • 虽然使用此方法的音符重叠会产生“流动”的音频 它还引入了裁剪,大概是由于两个分层 音量为 1 的音调。我无法按照方法 1 确定如何指定音量

理想的答案将解决以下问题:

  • 合成多个音调并将它们组合成一个单一的内聚 一段“音乐”
  • 使用不确定长度的源数据集
  • 避免在最终输出中剪裁

【问题讨论】:

    标签: php audio sox


    【解决方案1】:

    经过更多的实验,我确定了一种满足我要求的方法。我确信可以使用管道来提高流程效率,但是这种方法已经在不到一分钟的时间内对大约所需大小 (~2,000) 的数据集产生了所需的结果。

    //Generate individual tones
    $tones=array();
    for($i=0;$i<count($sourceData)-1;$i++){
        $name='tones\\'.$dataTitle.'_'.$i.'.au';
        $soxCommand=$soxFolder.'sox -n '.$name.' synth 0.2 sin '.($sourceData[$i]).' fade q 0.05 0 ';
        shell_exec($soxCommand);
        $tones[]=$name;
    }
    //Break into manageable chunks to avoid exec character limit
    $chunks=array_chunk($tones,100);
    $chunkFiles=array();
    for($ch=0;$ch<count($chunks);$ch++){
        $name='tones\\'.$dataTitle.'_chunk_'.$ch.'.au';
        $soxCommand=$soxFolder.'sox ';
        for($i=0;$i<count($chunks[$ch]);$i++){
            $soxCommand.=' '.$chunks[$ch][$i]; 
        }
        $soxCommand.=' '.$name.' splice 0.2';
        shell_exec($soxCommand);
        $chunkFiles[]=$name;
    }
    //Render chunks into final track
    $soxCommand=$soxFolder.'sox ';
    for($i=0;$i<count($chunkFiles);$i++){
        $soxCommand.=' '.$chunkFiles[$i]; 
    }
    $soxCommand.=' '.$dataTitle.'.au splice 20';
    shell_exec($soxCommand);
    //Clean component files
    for($i=0;$i<count($tones);$i++){
        unlink($tones[$i]); 
    }
    for($i=0;$i<count($chunkFiles);$i++){
        unlink($chunkFiles[$i]); 
    }
    

    SoX 命令消歧

    生成音调: "sox -n [outfile] synth 0.2 [frequency] fade q 0.05 0"

    此命令在曲目自然结束前生成一个 0.2 秒的音调,四分之一正弦淡入为 0.05 秒,四分之一正弦淡出为 0.05 秒。

    组合音调/块:“sox [tone1] [tone2] [tone...] [outfile] splice 0.2”

    其中的秘诀是拼接会自动尝试消除由哑连接引起的点击。最后的命令只是简单地将tone infiles替换为chunk infiles,并将拼接点从0.2sec增加到20sec。

    【讨论】:

    • 您也许还可以使用混音管道效果来混合和淡入淡出而无需剪辑。我在命令末尾使用了… remix - fade 0 4 .1 norm -1 来(粗略地)合成简单的guitar chords
    猜你喜欢
    • 2012-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多