audioop – Работа с необработанными аудиоданными¶audioop – Manipulate raw audio data
Модуль audioop содержит несколько полезных операций для работы со звуковыми фрагментами. Он работает со звуковыми фрагментами, состоящими из знаковых целочисленных отсчётов с разрядностью 8, 16 или 32 бита, хранящихся в строках Python. Все скалярные значения являются целыми числами, если не указано иное.
Этот модуль предоставляет поддержку кодировок a-LAW, u-LAW и Intel/DVI ADPCM.
Некоторые более сложные операции работают только с 16-битными отсчётами, в остальных случаях размер отсчёта (в байтах) всегда является параметром операции.
Модуль определяет следующие переменные и функции:
- exception audioop.error¶
- Это исключение возникает при любых ошибках, например при неизвестном числе байт на отсчёт и т.п.
- audioop.add(fragment1, fragment2, width)¶
- Возвращает фрагмент, представляющий собой сумму двух сэмплов, переданных в качестве параметров. width – это ширина сэмпла в байтах: 1, 2 или 4. Оба фрагмента должны быть одинаковой длины.
- audioop.adpcm2lin(adpcmfragment, width, state)¶
- Декодирует фрагмент, закодированный в формате Intel/DVI ADPCM, в линейный фрагмент. Описание кодирования ADPCM см. в lin2adpcm(). Возвращает кортеж (sample, newstate), где sample имеет ширину, указанную в width.
- audioop.alaw2lin(fragment, width)¶
- Convert sound fragments in a-LAW encoding to linearly encoded sound fragments. a-LAW encoding always uses 8 bits samples, so width refers only to the sample width of the output fragment here.
- audioop.avg(fragment, width)¶
- Возвращает среднее арифметическое всех отсчётов во фрагменте.
- audioop.avgpp(fragment, width)¶
- Возвращает среднее размаха (пик-пик) по всем отсчётам во фрагменте. Фильтрация не производится, поэтому полезность этой функции сомнительна.
- audioop.bias(fragment, width, bias)¶
- Возвращает фрагмент, полученный из исходного фрагмента путём добавления смещения (bias) к каждому сэмплу.
- 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 и возвращает результат в виде строки Python. a-LAW – это формат аудиокодирования, при котором можно получить динамический диапазон около 13 бит, используя только 8-битные сэмплы. Он применяется, в частности, в звуковом оборудовании Sun.
- audioop.lin2lin(fragment, width, newwidth)¶
Преобразует сэмплы между одно-, двух- и четырёхбайтовыми форматами.
Примечание
В некоторых аудиоформатах, таких как .WAV, 16- и 32-битные сэмплы являются знаковыми, а 8-битные – беззнаковыми. Поэтому при преобразовании в 8-битные сэмплы для этих форматов к результату необходимо также прибавить 128:
new_frames = audioop.lin2lin(frames, old_width, 1) new_frames = audioop.bias(new_frames, 1, 128)
То же самое в обратном порядке следует применять при преобразовании из 8-битных сэмплов в 16- или 32-битные.
- audioop.lin2ulaw(fragment, width)¶
- Преобразует сэмплы звукового фрагмента в кодировку u-LAW и возвращает результат в виде строки Python. u-LAW – это формат аудиокодирования, при котором можно получить динамический диапазон около 14 бит, используя только 8-битные сэмплы. Он применяется, в частности, в звуковом оборудовании Sun.
- audioop.minmax(fragment, width)¶
- Возвращает кортеж, состоящий из минимального и максимального значений всех сэмплов в звуковом фрагменте.
- audioop.max(fragment, width)¶
- Возвращает максимум абсолютных значений всех сэмплов во фрагменте.
- audioop.maxpp(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(sample, width, lfactor)
rsample = audioop.mul(sample, 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)