22.1. audioop – Управление необработанными аудиоданными¶audioop – Manipulate raw audio data
Модуль audioop содержит несколько полезных операций над звуковыми фрагментами. Он работает со звуковыми фрагментами, состоящими из целочисленных отсчётов со знаком разрядностью 8, 16, 24 или 32 бита, хранящихся в байтоподобных объектах. Все скалярные значения являются целыми числами, если не указано иное.
Changed in version 3.4: Support for 24-bit samples was added. All functions now accept any bytes-like object. String input now results in an immediate error.
Этот модуль предоставляет поддержку кодировок a-LAW, u-LAW и Intel/DVI ADPCM.
Некоторые более сложные операции работают только с 16-битными отсчётами, в остальных случаях размер отсчёта (в байтах) всегда является параметром операции.
Модуль определяет следующие переменные и функции:
- exception audioop.error¶
Это исключение возникает при любых ошибках, например при неизвестном числе байт на отсчёт и т.п.
- audioop.add(fragment1, fragment2, width)¶
Return a fragment which is the addition of the two samples passed as parameters. width is the sample width in bytes, either 1, 2, 3 or 4. Both fragments should have the same length. Samples are truncated in case of overflow.
- 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.byteswap(fragment, width)¶
«Переворачивает байты» (byteswap) всех отсчётов во фрагменте и возвращает изменённый фрагмент. Преобразует отсчёты из порядка big-endian в little-endian и наоборот.
Новое в версии 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 и возвращает результат как объект bytes. 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 и возвращает результат как объект bytes. 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)