audioop — Управление необработанными аудиоданными


Модуль audioop реализует несколько полезных операций над звуковыми фрагментами. Он работает со звуковыми фрагментами, состоящими из сэмплов целых чисел со знаком шириной 8, 16, 24 или 32 бита, хранящихся в байтоподобных объектах. Все скалярные элементы являются целыми числами, если не указано иное.

Изменено в версии 3.4: Добавлена поддержка 24-битных сэмплов. Все функции теперь принимают любой байтоподобный объект. Строковый ввод теперь приводит к немедленной ошибке.

Данный модуль предоставляет поддержку кодировок a-LAW, u-LAW и Intel/DVI ADPCM.

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

Модуль определяет следующие переменные и функции:

exception audioop.error

Вызывается исключение при всех ошибках, таких как неизвестное количество байтов на сэмпл и т. д.

audioop.add(fragment1, fragment2, width)

Возвращает фрагмент, являющийся добавлением двух сэмплов, переданных в качестве параметров. width — это ширина сэмпла в байтах: 1, 2, 3 или 4. Оба фрагмента должны быть одинаковой длины. Сэмплы усекаются в случае переполнения.

audioop.adpcm2lin(adpcmfragment, width, state)

Декодирует кодированный фрагмент Intel/DVI ADPCM в линейный фрагмент. Подробную информацию о ADPCM кодировании см. в описании lin2adpcm(). Возвращает кортеж (sample, newstate), где у сэмпла width ширину.

audioop.alaw2lin(fragment, width)

Преобразует звуковых фрагментов в кодировке a-LAW в линейно закодированные звуковые фрагменты. Кодирование a-LAW всегда использует 8-битные сэмплы, поэтому width относится только к ширине сэмпла выходного фрагмента.

audioop.avg(fragment, width)

Возвращает среднее значение по всем сэмплам во фрагменте.

audioop.avgpp(fragment, width)

Возвращает среднее пиковое значение по всем сэмплам во фрагменте. Фильтрация не выполняется, поэтому полезность этой подпрограммы сомнительна.

audioop.bias(fragment, width, bias)

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

audioop.byteswap(fragment, width)

«Bytesswap» всех сэмплов во фрагменте и возвращает изменённый фрагмент. Преобразует сэмпл с прямым порядком байтов в прямой и наоборот.

Добавлено в версии 3.4.

audioop.cross(fragment, width)

Возвращает количество пересечений нуля во фрагменте, переданном в качестве аргумента.

audioop.findfactor(fragment, reference)

Возвращает коэффициент F таким образом, чтобы rms(add(fragment, mul(reference, -F))) был минимальным, т. е. возвращает коэффициент, на который вы должны умножить reference, чтобы он максимально соответствовал fragment. Оба фрагмента должны содержать 2-байтовые сэмплы.

Затрачиваемое время подпрограммой пропорционально len(fragment).

audioop.findfit(fragment, reference)

Пытается как можно лучше сопоставить reference с частью fragment (которая должна быть более длинным фрагментом). Это (концептуально) делается путём извлечения фрагментов из fragment, использования findfactor() для вычисления наилучшего совпадения и минимизации результата. Оба фрагмента должны содержать 2-байтовые сэмплы. Возвращает кортеж (offset, factor), где offset — это (целочисленное) смещение в fragment, где началось оптимальное совпадение, а factor — это коэффициент (с плавающей запятой) в соответствии с findfactor().

audioop.findmax(fragment, length)

Найти в fragment срез длиной length сэмплов (не байтов!) с максимальной энергией, т. е. возвращает i, для которого rms(fragment[i*2:(i+length)*2]) является максимальным. Оба фрагмента должны содержать 2-байтовые сэмплы.

Подпрограмма занимает время, пропорциональное len(fragment).

audioop.getsample(fragment, width, index)

Возвращает значение сэмпла index из фрагмента.

audioop.lin2adpcm(fragment, width, state)

Преобразование сэмплов в 4-битное кодирование Intel/DVI ADPCM. Кодирование ADPCM представляет собой адаптивную схему кодирования, в которой каждое 4-битное число представляет собой разницу между одним отсчётом и следующим, делённую на (изменяющийся) шаг. Алгоритм Intel/DVI ADPCM был выбран IMA для использования, поэтому вполне может стать стандартом.

state — это кортеж, содержащий состояние кодера. Кодер возвращает кортеж (adpcmfrag, newstate), а newstate следует передать следующему вызову lin2adpcm(). В начальном вызове в качестве состояния можно передать None. adpcmfrag — это кодированный фрагмент ADPCM, упакованный по 2 4-битных значения на байт.

audioop.lin2alaw(fragment, width)

Преобразовывает сэмплы в аудиофрагменте в кодировку a-LAW и возвращает их как байтовый объект. a-LAW — это формат кодирования звука, при котором вы получаете динамический диапазон около 13 бит, используя только 8-битные сэмпл. Среди прочего, он используется аудиооборудованием Sun.

audioop.lin2lin(fragment, width, newwidth)

Преобразование семплов между 1-, 2-, 3- и 4-байтовыми форматами.

Примечание

В некоторых аудиоформатах, таких как файлы .WAV, 16-, 24- и 32-битные у сэмплов есть знак, а 8-битные сэмплы нет. Поэтому при преобразовании в 8-битные сэмплы для данных форматов вам также нужно добавить 128 к результату:

new_frames = audioop.lin2lin(frames, old_width, 1)
new_frames = audioop.bias(new_frames, 1, 128)

То же самое, в обратном порядке, должно быть применено при преобразовании семплов с разрядностью 8 в 16, 24 или 32 бита.

audioop.lin2ulaw(fragment, width)

Преобразовывает сэмплы в аудиофрагменте в кодировку u-LAW и возвращает их как байтовый объект. u-LAW — это формат кодирования звука, при котором вы получаете динамический диапазон около 14 бит, используя только 8-битные сэмплы. Среди прочего, он используется аудиооборудованием Sun.

audioop.max(fragment, width)

Возвращает максимальное абсолютное значение всех сэмплов во фрагменте.

audioop.maxpp(fragment, width)

Возвращает максимальное пиковое значение в звуковом фрагменте.

audioop.minmax(fragment, width)

Возвращает кортеж, состоящий из минимального и максимального значений всех семплов в звуковом фрагменте.

audioop.mul(fragment, width, factor)

Возвращает фрагмент, в котором все сэмплы в исходном фрагменте умножены на значение с плавающей запятой factor. Сэмплы усекаются в случае переполнения.

audioop.ratecv(fragment, width, nchannels, inrate, outrate, state[, weightA[, weightB]])

Преобразует частоты фреймов входного фрагмента.

state — это кортеж, содержащий состояние преобразователя. Преобразователь возвращает кортеж (newfragment, newstate), а newstate следует передать при следующем вызове ratecv(). Первоначальный вызов должен передавать None в качестве состояния.

Аргументы weightA и weightB являются параметрами простого цифрового фильтра и по умолчанию равны 1 и 0 соответственно.

audioop.reverse(fragment, width)

Переворачивает сэмплы во фрагменте и возвращает изменённый фрагмент.

audioop.rms(fragment, width)

Возвращает среднеквадратичное значение фрагмента, т. е. sqrt(sum(S_i^2)/n).

Это мера мощности звукового сигнала.

audioop.tomono(fragment, width, lfactor, rfactor)

Преобразование стереофрагмента в монофрагмент. Левый канал умножается на lfactor, а правый канал — на rfactor перед добавлением двух каналов для получения монофонического сигнала.

audioop.tostereo(fragment, width, lfactor, rfactor)

Создаёт стереофрагмент из монофрагмента. Каждая пара сэмплов в стереофрагменте вычисляется из моно сэмпла, при этом сэмпла левого канала умножаются на lfactor, а сэмпл правого канала — на rfactor.

audioop.ulaw2lin(fragment, width)

Преобразует звуковые фрагменты в кодировке u-LAW в линейно закодированные звуковые фрагменты. Кодирование u-LAW всегда использует 8-битные сэмплы, поэтому width здесь относится только к ширине сэмпла выходного фрагмента.

Обратите внимание, что такие операции, как mul() или max(), не делают различия между монофоническими и стереофрагментами, т. е. все сэмплы обрабатываются одинаково. Если это проблема, то стереофонический фрагмент следует сначала разделить на два монофонических фрагмента, а затем снова объединить. Вот пример того, как это сделать:

def mul_stereo(sample, width, lfactor, rfactor):
    lsample = audioop.tomono(sample, width, 1, 0)
    rsample = audioop.tomono(sample, width, 0, 1)
    lsample = audioop.mul(lsample, width, lfactor)
    rsample = audioop.mul(rsample, width, rfactor)
    lsample = audioop.tostereo(lsample, width, 1, 0)
    rsample = audioop.tostereo(rsample, width, 0, 1)
    return audioop.add(lsample, rsample, width)

Если вы используете ADPCM кодер для создания сетевых пакетов и хотите, чтобы ваш протокол не сохранял состояния (т. е. чтобы он мог выдерживать потерю пакетов), вы должны передавать не только данные, но и состояние. Обратите внимание, что вы должны отправить декодеру первоначальное состояние (которое вы передали в lin2adpcm()), а не конечное состояние (которое возвращает кодер). Если вы хотите использовать struct.Struct для хранения состояния в двоичном формате, вы можете закодировать первый элемент (прогнозируемое значение) в 16 бит, а второй (дельта-индекс) в 8.

ADPCM кодеры никогда не сравнивали с другими ADPCM кодерами. Вполне может быть, что я неверно истолковал стандарты, и в этом случае они не будут совместимы с соответствующими стандартами.

Подпрограммы find*() могут показаться немного забавными на первый взгляд. Они в первую очередь предназначены для подавления эха. Достаточно быстрый способ сделать это — выбрать наиболее энергичную часть выходного сэмпла, найти его во входном сэмпле и вычесть весь выходной сэмпл из входного сэмпла:

def echocancel(outputdata, inputdata):
    pos = audioop.findmax(outputdata, 800)    # одна десятая секунды
    out_test = outputdata[pos*2:]
    in_test = inputdata[pos*2:]
    ipos, factor = audioop.findfit(in_test, out_test)
    # Необязательно (для лучшей отмены):
    # factor = audioop.findfactor(in_test[ipos*2:ipos*2+len(out_test)],
    #              out_test)
    prefill = '\0'*(pos+ipos)*2
    postfill = '\0'*(len(inputdata)-len(prefill)-len(outputdata))
    outputdata = prefill + audioop.mul(outputdata, 2, -factor) + postfill
    return audioop.add(inputdata, outputdata, 2)