Skip to main content

Прячем секретное сообщение в аудио файле

Этот пост будет лишним доказательством того, что файлы типа 96kHz/24bps не несут в себе никакой дополнительной информации по сравнению с обычными (44.1kHz/16bps).

Мы возьмём файл с частотой дискретизации 96kHz и на фоне шума запишем в него секретное сообщение (которое, правда, сможет прослушать любой с соответствующей программой, так что никакого "реального" шифрования тут не происходит).

Работать это будет по принципу амплитудной модуляции, AM. Судя по википедии, видов амплитудной модуляции три — "обычная", double-sideband suppressed-carrier и single-sideband suppressed-carrier. О том, что это такое, подробно ниже.

Предположим, у нас есть входной сигнал — синусоида с частотой колебания $\omega_{s}$. Мы хотим замодулировать её с частотой $\omega_{c} > \omega_{s}$. Делаем это так:
$f(t) = (1 + \sin \omega_{s}t) \sin \omega_{c}t$

Вот график нашего замодулированного сигнала:
Синусоида $\sin t$, смодулированная с несущим сигналом $\sin 10 t$.

Перемножим синусы в смодулированном сигнале:
$f(t) = \sin (\omega_{c} t) + 1/2 (\cos (\omega_{c} - \omega_{s})t - \cos (\omega_{c} + \omega_{s})t)$

Видим, что тут есть колебания на трех частотах — одно на несущей и два на несущей плюс-минус частота сигнала. Это "классическая" амплитудная модуляция, такой сигнал легко демодулировать обратно с помощью так называемого детектора огибающей (envelope detector). Смысл работы этого детектора — нахождение огибающей сигнала, т.е. зеленой линии на картинке снизу. Эта огибающая — и есть наш сигнал плюс некое постоянное значение.


 Этот детектор можно построить на обычном диоде и конденсаторе. В каком-то номере журнала "Радио" даже была статья, как сделать радио из куска проволоки, диода, конденсатора и высокоомного наушника. Такому радио не нужно дополнительное питание, он использует как раз мощность волны-носителя.

Более сложная схема для реализации в железе, но простая для нас — DSB-SC (double-sideband suppressed-carrier). В ней колебания на частоте волны-носителя приглушены или убраны из смодулированного сигнала, т.е. модулируется он так:
$f(t) = \sin \omega_{s}t \sin \omega_{c}t = 1/2 (\cos (\omega_{c} - \omega_{s})t - \cos (\omega_{c} + \omega_{s})t)$

Для демодуляции этого сигнала воссоздаются колебания с несущей частотой и умножаются на смодулированный сигнал:
$f(t) = 1/2 (\cos (\omega_{c} - \omega_{s})t - \cos (\omega_{c} + \omega_{s})t) \sin \omega_{c} t = -1/2 \sin \omega_{s} t + 1/4 (\sin (2\omega_{c} - \omega_{s})t - \sin (2\omega_{c} + \omega_{s})t)$

Мы видим, что таким образом у нас есть наш исходный сигнал (с множителем $-1/2$) и сигналы с высокими частотами (около $2\omega_{c}$), которые мы можем просто отфильтровать.

Теперь к изначальной теме встраивания сообщения в аудио файл. Допустим, что самый высокий тон человеческой речи не превышает 5 кГц, и смодулируем сообщение с частотой 30 кГц по схеме DSB-SC. Тогда замодулированный сигнал будет лежать в диапазоне частот 25-35 кГц. Нижний предел находится выше предела восприятия человека, а верхний предел меньше половинного значения частота дискретизации (48 кГц). Таким образом, файл с частотой дискретизации 96 кГц может хранить одновременно и аудио, и некий секретный голосовой сигнал.

Вот реализация идеи на SuperCollider:
// Подготовка записи
s.recChannels = 2
s.recHeaderFormat = "WAV"
s.recSampleFormat = "int16"

// Модуляция. Записываем 10 секунд секретного сообщения на фоне обычного шума
(
{
 var noise = LPF.ar (WhiteNoise.ar (0.8)),
     // Модулируем сигнал с микрофона с частотой 30 кГц
     signal = SinOsc.ar (30000, mul: 0.2) * SoundIn.ar ([0,1]);
 noise + signal; // Складываем полезный сигнал и шум
}.play;
s.record ("~/test2/hiddenmessage.wav".standardizePath);
SystemClock.sched (10.0, {s.stopRecording; s.freeAll; nil}) // Запишем 10 секунд сообщения
)

// Демодуляция
(
var buf = Buffer.read (s, "~/test2/hiddenmessage.wav".standardizePath);
{
 10 * BLowPass4.ar (SinOsc.ar (30000) *
 BHiPass4.ar (PlayBuf.ar (2, buf, doneAction: 2), 25000), 5000)
}.play
) 

Вот пример файла, закодированного таким образом:
Секретное сообщение

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

Да, разумеется, сообщение можно прятать в чем угодно, а не только в шуме. Просто ради демонстрации я выбрал шум.

Comments

Popular posts from this blog

Гладкая сшивка кусочно-постоянной функции.

Накануне мне понадобилось найти гладкую функцию, определенную на $\textbf{R}[a,c]$, равную единице на одном отрезке числовой оси, скажем, $[a, b-\epsilon]$ и нулю на другом, скажем $[b+\epsilon, c]$. Для того, чтобы гладко склеить эти два кусочка, я решил найти монотонно убывающий многочлен $f(x)$, равный $f(0) = 1$ и $f(1) = 0$, а потом "вставить" его в отрезок $[b-\epsilon, b+\epsilon]$. Для гладкости сшивки должны выполняться условия $f'(0) = f'(1) = 0$. Я решил пойти далее и положить $f^{(n)}(0) = f^{(n)}(1) = 0$ для всех $n = 1,2,\cdots,N$. То есть первые N производных должны быть равны нулю в т. $x = 0$ и $x = 1$. Понятно, что это легко сделать при наперед известном N, но как найти общую формулу? Я некоторое время промучился над этой задачей, пока не решил её следующим способом. Пусть искомая функция $f(x) = 1 + x^{N+1}L_{1}(x)$, где $L_{1}(x)$ — некий многочлен. Тогда у нас выполняется условие $f(0) = 1$ и $f^{(n)}(0) = 0$ (так как первая производная будет

Ресемплинг аудио.

В этом посте расскажу о ресемплинге аудио (в частности, о даунсемплинге), под чем я подразумеваю понижение частоты дискретизации, с которой был записан звук. Известно, что в компьютере непрерывный аудио сигнал представлен в виде семплов (по-русски, измерений), сделанных в равно отстоящие друг от друга промежутки времени. Например, если звук записан с частотой дискретизации 44.1 кГц, то за одну секунду было сделано 44100 семплов. Здесь я расскажу о том, как восстановить исходный непрерывный сигнал по взятым семплам и как выбирать и менять частоту семплирования (или, что то же самое, частоту дискретизации). Преобразование Фурье. Преобразованим Фурье $F(\xi)$ функции $f(x)$ называется следующая функция: $F(\xi) = \int_{-\infty}^{\infty} f(x) e^{-ix\xi}dx$ обратное преобразование определено как $f(x) = \frac{1}{2\pi}\int_{-\infty}^{\infty} F(\xi) e^{ix\xi}d\xi$ Вопрос о том, когда существует преобразование Фурье и обратимо ли оно (т.е. работает ли вторая формула), очень сложе

На что влияет размер (глубина) семпла?

В этом посте я разберу ещё одну характеристику представления аудио на компьютере — размер или глубину семпла. В теореме Шеннона, с которой мы ознакомились в первом посте, сказано, что семплы нужно брать с определенной частотой, чтобы восстановить исходный сигнал. Однако, в ней ничего не сказано о том, сколько памяти компьютера нужно выделить на один семпл. По сути  ней семплы — это обычные вещественные числа. В компьютере же семплы чаще всего представляются целыми числами в диапазоне от $-2^{n-1}$ до $2^{n-1}-1$ (целые числа со знаком), где $n$ — количество бит на один семпл (bps, bits per sample). С количеством бит на семпл связана другая величина — динамический диапазон (или отношение сигнал-шум, что в данном случае то же самое). Он измеряется в децибелах определяется так: $DR = 20 \lg (2^{n}) \approx 6 n$ Динамический диапазон показывает логарифм отношения самого сильного сигнала к самому слабому. Теперь, что будет, если мы выберем $n$ маленьким? Если взять синусоидальную волн