Как добавить кучу WAV-файлов, сохранив (не добавляя ноль) числовой порядок?

У меня есть много (7500) WAV-файлов (названных по их номерам), которые я хотел бы объединить в один. Я думаю, что это должно быть сделано с помощью цикла bash, потому что при использовании глобирования некоторые файлы были бы в неправильном порядке (например, 1111 до 2).

Какой лучший способ сделать это под Linux?

2 ответа

Решение

Если все файлы имеют одинаковые параметры, такие как частота дискретизации и количество каналов, вы все равно не можете просто их объединить. Вы должны удалить заголовок WAV.

Это может быть проще всего использовать утилиту манипулирования звуковыми файлами, как sox, который содержит метод для объединения файлов. На самом деле, он делает это по умолчанию. Например, чтобы объединить три WAV-файла в один длинный:

$ sox short1.wav short2.wav short3.wav long.wav

Цикл не будет располагать файлы в нужном вам порядке. Вам нужно отсортировать имена, но обработать их численно. sort -n сделаю это.

Таким образом:

$ sox $(ls *.wav | sort -n) out.wav

Если sox не можем обработать столько файлов, мы можем разбить работу следующим образом:

$ ls *.wav | sort -n > script

Тогда у нас есть файл сценария, который выглядит так:

1.wav
2.wav
...
3999.wav
4000.wav
...
file7500.wav

Мы редактируем это, чтобы сделать несколько командных строк:

# catenate about half the files to temp1.wav   
sox \
1.wav \
2.wav \
... \
3999.wav \
temp1.wav

# catenate the remainder to temp2.wav  
sox \
4000.wav \
... \
7500.wav \
temp2.wav

# catenate the two halves
sox temp1.wav temp2.wav out.wav ; rm temp1.wav temp2.wav

В качестве первого шага редактирования в списке файлов вы можете использовать vi команда :%s/.*/& \\/ добавить обратную косую черту после каждой строки.

Это беспокоило меня сегодня, так как мне нужно было объединить гораздо больше файлов, чем мог загрузить sox. В итоге я использовал этот сценарий оболочки внутри папки с wav-файлами (пожалуйста, убедитесь, что вам не нужны in.wav и out.wav, поскольку они будут перезаписаны):

      rm in.wav out.wav                                                                                                                            
ls *.wav | sort -n | while read l;
do                                                                                                                                                            
   if [ ! -f in.wav ]                                                                                                                                         
   then                                                                                                                                                       
      cp $l in.wav                                                                                                                                            
   else                                                                                                                                                       
      sox in.wav $l out.wav                                                                                                                                   
      cp out.wav in.wav                                                                                                                                       
   fi                                                                                                                                                         
   echo "$l"                                                                                                                                                  
done        
``
Другие вопросы по тегам