audioop
— Манипулирование необработанными аудиоданными¶
Утратил актуальность с версии 3.11, будет удален в версии 3.13: Модуль audioop
устарел (подробнее см. PEP 594).
Модуль audioop
содержит несколько полезных операций над звуковыми фрагментами. Он работает со звуковыми фрагментами, состоящими из целых чисел со знаком шириной 8, 16, 24 или 32 бита, хранящихся в bytes-like objects. Все скалярные элементы являются целыми числами, если не указано иное.
Изменено в версии 3.4: Добавлена поддержка 24-разрядных выборок. Все функции теперь принимают любые bytes-like object. Ввод строки теперь немедленно приводит к ошибке.
Этот модуль обеспечивает поддержку кодировок 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, в линейный фрагмент. Смотрите описание
lin2adpcm()
для получения подробной информации о кодировании в ADPCM. Возвращает кортеж(sample, newstate)
, где образец имеет ширину, указанную в width.
- audioop.alaw2lin(fragment, width)¶
Преобразуйте звуковые фрагменты в кодировке a-LAW в линейно закодированные звуковые фрагменты. в кодировке a-LAW всегда используются 8-битные выборки, поэтому ширина здесь относится только к ширине выборки выходного фрагмента.
- audioop.avg(fragment, width)¶
Возвращает среднее значение по всем выборкам во фрагменте.
- audioop.avgpp(fragment, width)¶
Возвращает среднее пиковое значение по всем выборкам во фрагменте. Фильтрация не выполняется, поэтому полезность этой процедуры сомнительна.
- audioop.bias(fragment, width, bias)¶
Возвращает фрагмент, который является исходным фрагментом, с добавлением смещения к каждой выборке. Выборки обтекаются в случае переполнения.
- audioop.byteswap(fragment, width)¶
«Byteswap» преобразует все выборки во фрагменте и возвращает измененный фрагмент. Преобразует выборки с большими порядковыми номерами в выборки с малыми порядковыми номерами и наоборот.
Добавлено в версии 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)¶
Постарайтесь как можно лучше сопоставить ссылку с частью фрагмента (который должен быть более длинным фрагментом). Это (концептуально) делается путем извлечения фрагментов из фрагмента, использования
findfactor()
для вычисления наилучшего соответствия и минимизации результата. Оба фрагмента должны содержать 2-байтовые выборки. Возвращает кортеж(offset, factor)
, где offset - это (целочисленное) смещение в фрагмент, где началось оптимальное сопоставление, а factor - коэффициент (с плавающей запятой) в соответствии сfindfactor()
.
- audioop.findmax(fragment, length)¶
Найдите в фрагменте фрагмент длины length samples (не в байтах!) с максимальной энергией, т.е. верните i, для которого
rms(fragment[i*2:(i+length)*2])
является максимальным. Оба фрагмента должны содержать 2-байтовые выборки.Выполнение процедуры занимает время, пропорциональное
len(fragment)
.
- audioop.getsample(fragment, width, index)¶
Возвращает значение sample 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 и верните их в виде объекта bytes. a-LAW - это формат кодирования звука, при котором вы получаете динамический диапазон около 13 бит, используя только 8-битные сэмплы. Он используется, в частности, в оборудовании Sun audio.
- 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 и верните их в виде объекта bytes. u-LAW - это формат кодирования звука, при котором вы получаете динамический диапазон около 14 бит, используя только 8-битные сэмплы. Он используется, в частности, в оборудовании Sun audio.
- audioop.max(fragment, width)¶
Возвращает максимальное значение absolute value для всех выборок во фрагменте.
- 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-образной кодировке в линейно закодированные звуковые фрагменты. в u-образной кодировке всегда используются 8-битные выборки, поэтому ширина здесь относится только к ширине выборки выходного фрагмента.
Обратите внимание, что такие операции, как 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) # one tenth second
out_test = outputdata[pos*2:]
in_test = inputdata[pos*2:]
ipos, factor = audioop.findfit(in_test, out_test)
# Optional (for better cancellation):
# 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)