Конвейерная обработка звука
 
Автор: (C) Адриан Чанг [Adrian J. Chung]
Перевод: (C) С. Скороходов


С помощью программ обработки текста опытные пользователи Unix десятилетиями значительно облегчали себе редактирование документов. Такие консольные утилиты, как sed, awk, cut, paste и join, хотя и полезны каждая в отдельности, реализуют свой полный потенциал только при объединении в конвейеры с помощью программных каналов [pipelines] .

Linux теперь используется не только для работы с простым текстом в формате ASCII. Растущая популярность различных мультимедиа-форматов, содержащих изображения и аудиоданные, подстегнула разработку инструментария для работы с ними. Многие программы имеют графический интерфейс и не работают без взаимодействия с пользователем. Вместе с тем, все возрастающее число программных инструментов могут использоваться в пакетном режиме с отключенным пользовательским интерфейсом. Некоторые программы создаются специально для вызова из командной строки или скриптов.

Именно этот класс програмных утилит и будет рассмотрен в данной статье. Задачи сложного, комплексного преобразования медийных данных часто может быть осуществлена комбинацией простых инструментов с использованием техники, обычно применяемой в текстовых фильтрах. Мы сосредоточимся на потоковой аудио-обработке, поскольку изменно в обработке этих форматов парадигма программных каналов Unix показала себя особенно успешной.

Преобразователь аудиосэмплов

Существует множество звуковых форматов и преобразование файлов из одного формата в другой -- частая операция. Утилита sox может выполнять эту роль и вызывается из комнадной строки:


sox sample.wav sample.aiff

Приведенная выше комнада преобразует WAV-файл в формат AIFF. При этом можно изменить частоту дискретизации, число битов на отсчет (8 или 16), а также число каналов:


sox sample.aiff -r 8000 -b -c 1 low.aiff

Файл low.aiff содержать один канал с 8-битным сигналом, оцифрованном на частоте 8000 в секунду.


sox sample.aiff -r 44100 -w -c 2 high.aiff

А файл high.aiff -- стерео-звучание с частотой дискретизации 44100 Гц, 16-бит на отсчет.

Когда sox не может угадать выходной формат по расширению файла, его необходимо указать явно:


sox sample.wav -t aiff sample.000 

Опция "-t raw" указывает на специальный "беззаголовочный" формат, содержащий только "сырые" байты данных:


sox sample.wav -t raw -r 11025 -sw -c 2 sample.000 

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


sox -t raw -r 11025 -sw -c 2 sample.000 sample.aiff 

Нет нужды указывать опцию "-t raw", если у файла есть расширение .raw. Однако это требуется делать, если поток данных поступает со стандартного ввода или посылается в стандартный вывод. Для того, чтобы сделать это, воспользуйтесь ключом "-" на том месте в строке параметров , где должно находиться имя файла:


sox -t raw -r 11025 -sw -c 2 - sample.aiff < sample.raw

sox sample.aiff -t raw -r 11025 -sw -c 2 - > sample.raw

Зачем нам все это? Так мы сможем использовать sox как фильтр в програмном канале.

Ускоренное/замедленное воспроизведение

Обычно, благодаря использованию интерполяции sox изменяет частоту дискретизации без изменения высоты тона или темпа воспроизведения. Перенаправляя выход одного "sox'а" на вход другого и указав неравные частоты дискретизации, мы можем "обойти" интерполяцию, в результате замедляя звучание отрывка:


sox sample.aiff -t raw -r 44100 -sw -c 2 - |
sox -t raw -r 32000 -sw -c 2 - slow.aiff

или ускоряя его:


sox sample.aiff -t raw -r 32000 -sw -c 2 - |
sox -t raw -r 44100 -sw -c 2 - fast.aiff

Простейшее редактирование

Предположим, что требуется звуковой отрывок, содержащий первые две секунды другого файла. Этого можно достичь, запуская sox в "командной трубе":


sox sample.aiff -t raw -r 44100 -sw -c 2 - | head -c 352800 |
sox -t raw -r 44100 -sw -c 2 - twosecs.aiff

Входной файл sample.aiff преобразовывается к частоте 44,1 кГц, каждые два байта в два канала. Две секунды звучания, таким образом, представлены в 44100х2х2х2 = 352800 первых байтах, которые обрезаются фильтром "head -c 352800". Затем они преобразуются обратно в формат AIFF и сохраняются в twosecs.aiff.

Точно также можно извлечь последнюю секунду "сэмпла":


sox sample.aiff -t raw -r 44100 -sw -c 2 - | tail -c 176400 |
sox -t raw -r 44100 -sw -c 2 - lastsec.aiff

или его третью секунду:


sox sample.aiff -t raw -r 44100 -sw -c 2 - | tail -c +352801 |
head -c 176400 | sox -t raw -r 44100 -sw -c 2 - lastsec.aiff

Обратите внимание на то, что при работе с 16-битным звуком параметр, передаваемый "tail -c +N" должен быть нечетным, иначе "сырые" отсчеты окажутся неверно выровненными.

Можно извлечь фрагменты разных звуковых отрывков и объединить их в один файл с помощью вложенных шелл-команд:


(sox sample-1.aiff -t raw -r 44100 -sw -c 2 - | head -c 176400 
sox sample-2.aiff -t raw -r 44100 -sw -c 2 - | head -c 176400 ) | 
sox -t raw -r 44100 -sw -c 2 - newsample.aiff

В этом примере мы вызываем дочерний шелл, который "выдает сырые байты" из двух различных файлов в стандартный поток вывода, который в свою очередь перенаправляется процессу sox, выполняющемуся в родительском шелле и создающему результирующий файл.

Настольная система звуковоспроизведения

Опция командной строки "-t ossdsp" позволяет посылать звуки на OSS (open sound system) устройство /dev/dsp:


sox sample.aiff -t ossdsp /dev/dsp

В состав пакета sox обычно входит платформо-независимый скрипт play, который вызывает sox с подобающими случаю опциями. Предыдущую команду можно проще выполнить так:


play sample.aiff

Проигрываемые таким способом аудиофрагменты "монополизируют" воспроизводящую аппаратуру. Прежде, чем проиграть что-либо еще, другим "звучащим" приложениям приходится ждать, пока аудиоустройство освободится. "Рабочие столы" GNOME и KDE предоставляют возможности одновременного проигрывания более чем одного аудиофрагмента. Звуки могут "издаваться" различными программами в любой момент времени без необходимости ожидать своей очереди, однако не каждое аудио-приложение знает, как это делается в каждом из различных "рабочих столов". sox такой способностью не обладает. Но, если дать себе труд хотя бы поверхностно изучить мультимедийные звуковый службы, предоставляемые GNOME и KDE, то можно легко придумать, как обойти это ограничение.

Существует много пакетов, позволяющих совместно использовать звуковые устройства. Одна часто используемая стратегия -- запуск фонового сервера, которому приложения-клиенты посылают для проигрывания звуковые фрагменты. Сервер, в свою очередь, получает в свое распоряжение звуковое устройство и направляет на него аудиоданные. В случае, когда звуки поступают от двух и более программ сразу, сервер микширует их и направляет на устройство объединенный поток.

Такой подход используется в Enlightened Sound Daemon (ESD). Пользователи GNOME часто могут обнаружить запущенный в фоновом режиме сервер esd. Пакет ESD под именем esound входит в большинство дистрибутивов и включает несколько простых клиентских приложений:

  • esdplay -- проигрыватель звуковых фрагментов, хранимых в наиболее популярныъ файловых форматах: WAV, AU или AIFF.
  • esdcat -- посылает серверу звуковые данные в "сыром" формате raw. Эта утилита -- естественный "оконечкик" объединяемых в конвейер звуковых фильтров.

Вот команда, проигрывающая через ESD первую секунду звукового фрагмента:


sox sample.aiff -t raw -r 44100 -sw -c 2 - | head -c 176400 | esdcat

Тот же прием используется для воспроизведения фрагментов в формате, который не понимает ESD, но "читает" sox:



sox sample.cdr -t raw -r 44100 -sw -c 2 - | esdcat

Иногда звучание лучше, если использовать этот способ. Некоторые версии ESD вносят в записанные на низкой частоте дискретизации звуки значительные искажения и шум.

ARtS -- Analog RealTime Synthsizer -- схож с ESD, но чаще используется в KDE. Фоновый сервер называется artsd, а "клиентские программы сопровождения" -- artsplay и artscat.

Для проигрывания звукового отрывка выполните команду:


sox sample.cdr -t raw -r 44100 -sw -c 2 - | tail -c 352800 |artscat

Ни ESD, ни ARtS не зависят от собственно окружения какого-либо "рабочего стола". В теории, приложив некоторые усилия, можно использовать ESD с KDE, а ARtS -- в GNOME. Любой из серверов можно использовать и в консольной сессии. Таким образом можно микшировать все изобилие форматов как в графической среде, так и без нее.

Музыка, как источник аудиофрагментов

Рассказав про один из "конецов" звукового конвейера, следует рассмотреть то, с чего он начинается. Иногда требуется поработать над фрагментами, извлеченными из музыкальных файлов MP3, MIDE или "модульных" форматов -- MOD, XM, S3M и т.д. Для любого из них существуют утилиты командной строки, позволяющие направлять в стандартный вывод поток "сырого звука", получаемого из соответствующих файлов.

Для MP3-музыки используется "maplay -s"


maplay -s music.mp3 | artscat

Для того, чтобы "проиграться" с нормальным качеством, файл music.mp3 должен быть в формате стерео 44,1 кГц. Иное нужно явно указать artscat или esdcat:


maplay -s mono22khz.mp3 | esdcat -r 22050 -m
maplay -s mono22khz.mp3 | artscat -r 22050 -c 1

В качестве альтернативы можно воспользоваться "mpg123 -s". Дополнительные параметры гарантируют, что на выход будет подаваться сигнал, отцифрованный на нужной частоте и с нужным числом каналов:


mpg123 -s -r 44100 --stereo lowfi.mp3 | artscat

Пользователи Ogg Vorbis могут поступать так:


ogg123 -d raw -f - music.ogg | artscat

Явное создание канала не является необходимостью, т.к. в ogg123 есть встроенные драйверы для ESD и ARtS. Тем не менее, не вредно иметь прямой доступ к потоку "сырых" данных, которыми можно "запитать" конвейер.

К нам попдают и файлы с музыкой в формате MIDI. Если у вас (как и у меня) страрая звуковая карточка с плохим аппаратным секвенсером, вы можете найти, что timidity может творить чудеса. Обычно с помощью этого пакета конвертируют MIDI-файлы в обычный звуковой поток для вывода напрямую через устройство звуковоспроизведения. С аккуратно подобранные опции командной строки этот поток можно перенаправить:


timidity -Or1sl -o - -s 44100 music.mid | artscat

Опция "-o -" посылает данные в стандартный вывод, "-Or1sl" гарантирует 16-битное представление, а "-s 44100" устанавливает подходящую частоту дискретизации.

Фанатикам demo scene может захотеться проиграть на своем настольном компьтере несколько музыкальных модулей. К их счастью, mikmod умеет работать с большинством распространенных модульных форматов. Программа может выводить звук как напрямую через устройство, так и через ESD. Похоже, что последняя стабильная версия libmikmod (3.1.9) еще не умеет работать с ARtS. Это можно вылечить, создав конвейер в командной строке:


mikmod -d stdout -q -f 44100 music.mod | artscat

Параметр -q нужен для отключения интерфейса curses, который тоже использует стандартный вывод. Если он вам, тем не менее, нужен, то попробуйте вот так:


mikmod -d pipe,pipe=artscat -f 44100 music.mod

Учтите, что создание собственных командных каналов по силам только последней версии mikmod.

Фильтры-эффекты

Давайте вернемся к sox, который хорошо работает в составе конвейера. В дополнению к функциям конвератации из одного формата в другой к нему прилагается небольшая библиотка эффектов. Вот несколько примеров:

  • Эхо
    play sample.aiff echo 1 0.6 150 0.6

  • Вибрато
    play sample.aiff vibro 20 0.9

  • Добавление грубых искажений
    play sample.aiff flanger 0.7 0.7 4 0.8 2
    play sample.aiff phaser 0.6 0.6 4 0.6 2


  • Полосовой фильтр -- звучит, как плохая телефонная линия:
    play sample.aiff band 3000 700

    или будто слущаешь через толстое одеяло:
    play sample.aiff band 0 700

  • Создание хора из одного голоса:
    play sample.aiff chorus 0.7 0.7 20 1 5 2 -s

  • Тайные сообщения? Воспроизведите задом на перед:
    play sample.aiff reverse

Предупреждаем: наложение этих эффектов могут потребовать большого объема оперативной памяти и дискового пространства (зависит от размера фрагмента)

Собирая все вместе

Итак, основные компоненты конвейера звукообработки освещены. Давайте посмотрим, как их можно комбинировать для выполнения не столь тривиальных задач:

  • KDE: проигрывание музыкального модуля с эффектом хора:

    mikmod -d stdout -q -f 44100 music.xm |
    sox -t raw -r 44100 -sw -c 2 - -t raw - chorus 0.7 0.7 80 0.5 2 1 -s |
    artscat


  • Воспроизведение песни в формате Ogg Vorbis с удалением первых 4 секунд звучания:

    ogg123 -d raw -f - music.ogg | tail -c +705601 |artscat

  • Преобразование из MIDE в файл Ogg Vorbis с добавлением слабого эффекта "эхо":

    timidity -Or1sl -o - -s 44100 music.mid |
    sox -t raw -r 44100 -sw -c 2 - -t raw - echo 1 0.6 80 0.6 |
    oggenc -o music.ogg --raw -


    Конвейер был остановлен кодером Ogg Vorbis (oggenc), сконфигурированного на получение "сырых" отсчетов из стандартного входного потока.
  • Конвертация MP3 файла (32 кГц, моно) в файл Ogg Vorbis (44,1 кГц, стерео) с параллельным снижением громкости:

    maplay -s mono32.mp3 |
    sox -v 0.5 -t raw -r 32000 -sw -c 1 - -t raw -r 44100 -c 2 - split |
    oggenc -o music.ogg --raw -


  • Объединение всех находящихся в текущей директории файлов AIFF в один (но большой:) WAV-файл:

    for x in *.aiff
    do sox $x -v 0.5 -t raw -r 8000 -bu -c 1 -
    done | sox -t raw -r 8000 -bu -c 1 - all.wav


Надеюсь, эти примеры показывают, что можно сделать с исползованием "пайпов". Глупо возражать против создания интерактивных приложений с развитым графическим интерфейсом. В них часто можно решать сложные задачи, при этом не заставляя пользователя вызубривать несколько страниц опций коммандной строки. Однако, всегда остануться ситуации, в которых программные конвейеры оказываются удобнее: конвертация большого числа звуковых фрагментов требует использование скриптов, интерактивные программы нельзя вызвать в составе задания at или cron.

Пакетная обработка звуковых данных может уменьшать потребность в дисковом пространстве. Нет необходимости хранить десятки копий в сущности одного и того же сэмпла, отличающихся лишь незначительными изменениями. Вместо этого создайте нужное количество скриптов, каждый создающий свой конвейер и использующие разные фильтры. И вызывайте их когда вам потребуется та или иная версия фрагмента. Требуемое звучание будет сделано на лету тогда, когда в нем возникнет необходимость.

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


Адриан Дж. Чанг [Adrian J Chung]

Время, свободное от преподавания информационных технологий студентам Вест-Индийского Университета в Тринидаде [University of the West Indies, Trinidad], Адриан посвещает написанию системных скриптов для управления сетью Linux-машин. Или проводит эксперименты по взаимодействию различных интерпретируемых языков [scripting environments] с "самопальными" [home-brew] библиотеками визуализации и построения изображений [computer graphics renderers and data visualization].


Copyright (C) 2001, Adrian J. Chung.
Copying license http://www.linuxgazette.com/copying.html
Published in Issue 73 of Linux Gazette, December 2001

Вернуться на главную страницу