Я предвосхищу это, сказав, что я новичок в том, что касается обработки и синтеза аудио, если я делаю какие-то глупые предположения или неправильно понимаю основные концепции, пожалуйста, поправьте меня.
Я экспериментирую с SoX для преобразования массивов числовых данных в один аудиофайл. Пока у меня есть два «работающих» метода, которые дают довольно ужасные результаты, и оба имеют критические ограничения.
Я использую SoX через PHP на 64-битной коробке WIN 8.1.
Способ 1 Выведите отдельные тоны, затем объедините
$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);
Ограничения:
Способ 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);
Ограничения:
Идеальный ответ будет касаться следующего:
После еще нескольких экспериментов я остановился на методе, который отвечает моим требованиям. Я уверен, что можно было бы использовать каналы, чтобы сделать процесс более эффективным, однако этот метод дает требуемые результаты для наборов данных приблизительного требуемого размера (~ 2000) менее чем за минуту.
//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 [частота] fade q 0.05 0»
Эта команда генерирует 0,2-секундный тон с четвертью синусоидального усиления 0,05 секунды и четверть синусоидального сигнала за 0,05 секунды до естественного конца дорожки.
Объединить тоны / куски: «sox [tone1] [tone2] [tone …] [outfile] splice 0.2»
Секретным соусом в этом является соединение, которое будет автоматически пытаться удалить щелчки, вызванные тупой конкатенацией. Последняя команда просто заменяет инфильские тоны на инфильские фрагменты и увеличивает точку сращивания до 0,2 с с 20 с.
Других решений пока нет …