Синтезируйте мультитональный звук переменной длины с SoX, избегая при этом отсечения

Я предвосхищу это, сказав, что я новичок в том, что касается обработки и синтеза аудио, если я делаю какие-то глупые предположения или неправильно понимаю основные концепции, пожалуйста, поправьте меня.

Я экспериментирую с 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);

Ограничения:

  • Медленно, требует много отдельных казней
  • Микширование кажется ограниченным, т.е. попытка соединить 100 или 200 файлов приведет к созданию файла, содержащего некоторые, но не все тоны. Попытка объединить 1000 файлов не даст результатов. Можно предположительно объединить несколько файлов, а затем объединить эти объединенные файлы, но это усугубит первое ограничение. При создании окончательной смеси нескольких <= 100 тональных промежуточных файлов, по-видимому, микс обрабатывается до того, как компоненты завершат рендеринг, и получается пустой финальный микс.
  • Отказался от «микширования» и смог успешно объединить любое количество тонов, используя обновленный метод 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

Идеальный ответ будет касаться следующего:

  • Синтез нескольких тонов и объединение их в единый
    музыкальная пьеса»
  • Работа с исходными наборами данных неопределенной длины
  • Избегайте отсечения в конечном результате

1

Решение

После еще нескольких экспериментов я остановился на методе, который отвечает моим требованиям. Я уверен, что можно было бы использовать каналы, чтобы сделать процесс более эффективным, однако этот метод дает требуемые результаты для наборов данных приблизительного требуемого размера (~ 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 с.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]