что такое оцифровка звука
Оцифровка звука: как это работает
Как переводят голос в бездушную цифру.
Начинаем рассказывать, как работают привычные технологии: компьютерный звук, видео, MP3, вещание и стриминги, всевозможные алгоритмы и всё подобное.
👍 У этой статьи нет никакой практической ценности, она просто для удовольствия. Иногда можно себя побаловать 🙂
Немного школьной физики
Звук — это колебания воздуха. Как волны на воде, только в воздухе. Воздух давит нам на уши, а в ушах есть чувствительные части, которые тонко чувствуют колебания воздуха. Эти колебания люди воспринимают как звук. В открытом космосе звуков нет, потому что там нет воздуха. И людей.
Частота. Чем быстрее колебания, тем тоньше воспринимаемый нами звук. Человек воспринимает колебания от 20 раз в секунду до примерно 20 тысяч раз в секунду. По-другому это называется частотой колебаний: герцами. То есть диапазон, который мы слышим — от 20 герц до 20 килогерц.
Для сравнения, собаки слышат от 40 герц до 60 килогерц, поэтому собачий свисток не воспринимается людьми, но очень хорошо слышен собакам. Собачий свисток как раз звучит в диапазоне 23–54 КГц.
Амплитуда. Чем сильнее колебания — тем громче, и наоборот. Можно представить, что это высота волн на поверхности пруда: может быть мелкая рябь (тихий звук), а могут быть большие мощные волны.
График. Если мы произнесём фразу «Привет, это журнал „Код“», то с точки зрения волн он будет выглядеть как-то так (очень примерно):
Делим звук на отрезки
Давайте увеличим наш график и посмотрим, что происходит, например, за одну секунду (опять же, очень примерно и упрощённо!):
Упрощённо!
А теперь сделаем вот что: разделим секунду на 4 части, и для каждой найдём значение амплитуды:
Мы за секунду четыре раза измерили состояние волны. Это называется дискретизацией
Мы измерили значение амплитуды в каждой из четырёх точек, получили, условно говоря, четыре числа: +30, −50, −50 и −60. Теоретически, если взять ток и подать эти четыре напряжения на динамик, у нас получится воспроизвести тот же звук. Но есть несколько проблем:
Дискретизация с частотой 4 (сколько значений мы измеряем в секунду) — это слишком мало для звука. Чтобы получить более или менее разборчивую речь, нужно секунду делить на 8 тысяч отрезков, а для музыки обычно хватает 41 тысячи.
Увеличим частоту дискретизации: нарежем звук на более мелкие кусочки за ту же единицу времени:
Теперь измерения будут намного точнее, а получившийся звук — естественнее
Переводим в цифру
После того как мы разбили звук на мелкие отрезки и измерили значение амплитуды для каждого из них, мы можем записать это в виде таблички:
Время | Амплитуда |
0.01 сек. | 5 |
0.02 сек. | 7 |
0,03 сек | 10 |
. | . |
1 сек | −21 |
Если мы весь звук разбиваем на одинаковые отрезки, то время можно не писать, потому что мы знаем, как оно меняется, достаточно записать в строчку только значения амплитуды:
Чтобы компьютер понимал эти числа, переведём эти числа в двоичную систему счисления. Для простоты будем считать, что одно число занимает ровно один байт памяти, но на самом деле чем больше байт выделяется на число, тем точнее будет измерение и качество звука. После перевода получим такое:
Последнее большое число получилось оттого, что нам нужно хранить и отрицательные значения, поэтому первая единица в байте означает, что это отрицательное число и его нужно считать немного иначе.
Вот эту последовательность компьютер уже может понять и воспроизвести в виде звука.
Как теперь воспроизвести звук
Чтобы что-то зазвучало, нужно сделать следующие шаги:
Что дальше
У такого способа есть одна проблема: файл получается слишком большим, чтобы им было удобно пользоваться. Представьте: 44 тысячи чисел за одну секунду!
Чтобы уменьшить размер файла, придумали два решения: сжатие с потерями и без них. Каждое разберём отдельно, несмотря на то, что у них много общего.
Цифровое представление аналогового аудиосигнала. Краткий ликбез
Дорогие читатели, меня зовут Феликс Арутюнян. Я студент, профессиональный скрипач. В этой статье хочу поделиться с Вами отрывком из моей презентации, которую я представил в университете музыки и театра Граца по предмету прикладная акустика.
Рассмотрим теоретические аспекты преобразования аналогового (аудио) сигнала в цифровой.
Статья не будет всеохватывающей, но в тексте будут гиперссылки для дальнейшего изучения темы.
Чем отличается цифровой аудиосигнал от аналогового?
Аналоговый (или континуальный) сигнал описывается непрерывной функцией времени, т.е. имеет непрерывную линию с непрерывным множеством возможных значений (рис. 1).
Цифровой сигнал — это сигнал, который можно представить как последовательность определенных цифровых значений. В любой момент времени он может принимать только одно определенное конечное значение (рис. 2).
Аналоговый сигнал в динамическом диапазоне может принимать любые значения. Аналоговый сигнал преобразуется в цифровой с помощью двух процессов — дискретизация и квантование. Очередь процессов не важна.
Дискретизацией называется процесс регистрации (измерения) значения сигнала через определенные промежутки (обычно равные) времени (рис. 3).
Квантование — это процесс разбиения диапазона амплитуды сигнала на определенное количество уровней и округление значений, измеренных во время дискретизации, до ближайшего уровня (рис. 4).
Дискретизация разбивает сигнал по временной составляющей (по вертикали, рис. 5, слева).
Квантование приводит сигнал к заданным значениям, то есть округляет сигнал до ближайших к нему уровней (по горизонтали, рис. 5, справа).
Эти два процесса создают как бы координатную систему, которая позволяет описывать аудиосигнал определенным значением в любой момент времени.
Цифровым называется сигнал, к которому применены дискретизация и квантование. Оцифровка происходит в аналого-цифровом преобразователе (АЦП). Чем больше число уровней квантования и чем выше частота дискретизации, тем точнее цифровой сигнал соответствует аналоговому (рис. 6).
Уровни квантования нумеруются и каждому уровню присваивается двоичный код. (рис. 7)
Количество битов, которые присваиваются каждому уровню квантования называют разрядностью или глубиной квантования (eng. bit depth). Чем выше разрядность, тем больше уровней можно представить двоичным кодом (рис. 8).
Данная формула позволяет вычислить количество уровней квантования:
Если N — количество уровней квантования,
n — разрядность, то
Обычно используют разрядности в 8, 12, 16 и 24 бит. Несложно вычислить, что при n=24 количество уровней N = 16,777,216.
При n = 1 аудиосигнал превратится в азбуку Морзе: либо есть «стук», либо нету. Существует также разрядность 32 бит с плавающей запятой. Обычный компактный Аудио-CD имеет разрядность 16 бит. Чем ниже разрядность, тем больше округляются значения и тем больше ошибка квантования.
Ошибкой квантований называют отклонение квантованного сигнала от аналогового, т.е. разница между входным значением и квантованным значением
(
)
Большие ошибки квантования приводят к сильным искажениям аудиосигнала (шум квантования).
Чем выше разрядность, тем незначительнее ошибки квантования и тем лучше отношение сигнал/шум (Signal-to-noise ratio, SNR), и наоборот: при низкой разрядности вырастает шум (рис. 9).
Разрядность также определяет динамический диапазон сигнала, то есть соотношение максимального и минимального значений. С каждым битом динамический диапазон вырастает примерно на 6dB (Децибел) (6dB это в 2 раза; то есть координатная сетка становиться плотнее, возрастает градация).
Ошибки квантования (округления) из-за недостаточного количество уровней не могут быть исправлены.
50dB SNR
примечание: если аудиофайлы не воспроизводятся онлайн, пожалуйста, скачивайте их.
Теперь о дискретизации.
Как уже говорили ранее, это разбиение сигнала по вертикали и измерение величины значения через определенный промежуток времени. Этот промежуток называется периодом дискретизации или интервалом выборок. Частотой выборок, или частотой дискретизации (всеми известный sample rate) называется величина, обратная периоду дискретизации и измеряется в герцах. Если
T — период дискретизации,
F — частота дискретизации, то
Чтобы аналоговый сигнал можно было преобразовать обратно из цифрового сигнала (точно реконструировать непрерывную и плавную функцию из дискретных, «точечных» значении), нужно следовать теореме Котельникова (теорема Найквиста — Шеннона).
Теорема Котельникова гласит:
Если аналоговый сигнал имеет финитный (ограниченной по ширине) спектр, то он может быть восстановлен однозначно и без потерь по своим дискретным отсчетам, взятым с частотой, строго большей удвоенной верхней частоты.
Вам знакомо число 44.1kHz? Это один из стандартов частоты дискретизации, и это число выбрали именно потому, что человеческое ухо слышит только сигналы до 20kHz. Число 44.1 более чем в два раза больше чем 20, поэтому все частоты в цифровом сигнале, доступные человеческому уху, могут быть преобразованы в аналоговом виде без искажении.
Но ведь 20*2=40, почему 44.1? Все дело в совместимости с стандартами PAL и NTSC. Но сегодня не будем рассматривать этот момент. Что будет, если не следовать теореме Котельникова?
Когда в аудиосигнале встречается частота, которая выше чем 1/2 частоты дискретизации, тогда возникает алиасинг — эффект, приводящий к наложению, неразличимости различных непрерывных сигналов при их дискретизации.
Как видно из предыдущей картинки, точки дискретизации расположены так далеко друг от друга, что при интерполировании (т.е. преобразовании дискретных точек обратно в аналоговый сигнал) по ошибке восстанавливается совершенно другая частота.
Аудиопример 4: Линейно возрастающая частота от
100 до 8000Hz. Частота дискретизации — 16000Hz. Нет алиасинга.
Аудиопример 5: Тот же файл. Частота дискретизации — 8000Hz. Присутствует алиасинг
Пример:
Имеется аудиоматериал, где пиковая частота — 2500Hz. Значит, частоту дискретизации нужно выбрать как минимум 5000Hz.
Следующая характеристика цифрового аудио это битрейт. Битрейт (bitrate) — это объем данных, передаваемых в единицу времени. Битрейт обычно измеряют в битах в секунду (Bit/s или bps). Битрейт может быть переменным, постоянным или усреднённым.
Следующая формула позволяет вычислить битрейт (действительна только для несжатых потоков данных):
Битрейт = Частота дискретизации * Разрядность * Количество каналов
Например, битрейт Audio-CD можно рассчитать так:
44100 (частота дискретизации) * 16 (разрядность) * 2 (количество каналов, stereo)= 1411200 bps = 1411.2 kbit/s
При постоянном битрейте (constant bitrate, CBR) передача объема потока данных в единицу времени не изменяется на протяжении всей передачи. Главное преимущество — возможность довольно точно предсказать размер конечного файла. Из минусов — не оптимальное соотношение размер/качество, так как «плотность» аудиоматериала в течении музыкального произведения динамично изменяется.
При кодировании переменным битрейтом (VBR), кодек выбирает битрейт исходя из задаваемого желаемого качества. Как видно из названия, битрейт варьируется в течение кодируемого аудиофайла. Данный метод даёт наилучшее соотношение качество/размер выходного файла. Из минусов: точный размер конечного файла очень плохо предсказуем.
Усреднённый битрейт (ABR) является частным случаем VBR и занимает промежуточное место между постоянным и переменным битрейтом. Конкретный битрейт задаётся пользователем. Программа все же варьирует его в определенном диапазоне, но не выходит за заданную среднюю величину.
При заданном битрейте качество VBR обычно выше чем ABR. Качество ABR в свою очередь выше чем CBR: VBR > ABR > CBR.
ABR подходит для пользователей, которым нужны преимущества кодирования VBR, но с относительно предсказуемым размером файла. Для ABR обычно требуется кодирование в 2 прохода, так как на первом проходе кодек не знает какие части аудиоматериала должны кодироваться с максимальным битрейтом.
Существуют 3 метода хранения цифрового аудиоматериала:
Несжатый (RAW) формат данных
Другой формат хранения несжатого аудиопотока это WAV. В отличие от RAW, WAV содержит заголовок файла.
Аудиоформаты с сжатием без потерь
Принцип сжатия схож с архиваторами (Winrar, Winzip и т.д.). Данные могут быть сжаты и снова распакованы любое количество раз без потери информации.
Как доказать, что при сжатии без потерь, информация действительно остаётся не тронутой? Это можно доказать методом деструктивной интерференции. Берем две аудиодорожки. В первой дорожке импортируем оригинальный, несжатый wav файл. Во второй дорожке импортируем тот же аудиофайл, сжатый без потерь. Инвертируем фазу одного из дорожек (зеркальное отображение). При проигрывании одновременно обеих дорожек выходной сигнал будет тишиной.
Это доказывает, что оба файла содержат абсолютно идентичные информации (рис. 11).
Кодеки сжатия без потерь: flac, WavPack, Monkey’s Audio…
При сжатии с потерями
акцент делается не на избежание потерь информации, а на спекуляцию с субъективными восприятиями (Психоакустика). Например, ухо взрослого человек обычно не воспринимает частоты выше 16kHz. Используя этот факт, кодек сжатия с потерями может просто жестко срезать все частоты выше 16kHz, так как «все равно никто не услышит разницу».
Другой пример — эффект маскировки. Слабые амплитуды, которые перекрываются сильными амплитудами, могут быть воспроизведены с меньшим качеством. При громких низких частотах тихие средние частоты не улавливаются ухом. Например, если присутствует звук в 1kHz с уровнем громкости в 80dB, то 2kHz-звук с громкостью 40dB больше не слышим.
Этим и пользуется кодек: 2kHz-звук можно убрать.
Кодеки сжатия с потерям: mp3, aac, ogg, wma, Musepack…
Как происходит оцифровка звука.
Звуковой сигнал в аналоговой аппаратуре — это непрерывный электрический сигнал. А компьютер это машина, которая оперирует данными в цифровом виде. Значит и звуковой сигнал в ней представляется тоже в «цифре». Но как же происходит процесс преобразования аналогового в цифровой звук?
Оцифровка звука
При оцифровке звука условно можно выделить два этапа:
Кстати аналоговый (analog) означает «непрерывный».
Таким образом, оцифровка звука — это фиксация в определённые временные промежутки амплитуды сигнала и регистрация этих величин амплитуды в виде округлённых цифровых значений. А округлённых потому, что амплитуда это непрерывная величина и точным числом записать её нет возможности. В принципе звуковые колебания представить в виде математической формулы практически невозможно. Вот и остаётся хранить сигнал в виде дискретных значений, записанных в определённых временных точках.
Пример оцифровки звука
Рассмотрим рисунок, чтобы стало немного понятнее:
На первом рисунке: в АЦП поступает аналоговый электрический сигнал.
На втором рисунке : АЦП приближает полученный сигнал (его напряжение) дискретной числовой последовательностью. При этом шкала времени (ось Х — горизонталь) разбивается на равноотстоящие интервалы. Именно по этим интервалам и происходит выборка АЦП мгновенного напряжения аналогового аудиосигнала. Эти записанные значения называют отсчётами. Логично предположить, что чем больше и чаще эти замеры произвести, тем выше будет частота дискретизации и придётся намного меньше округлять полученные значения (квантование). В итоге получится более точное представление аналогового сигнала в цифровой форме. Вы наверно видели на всех дисках или звуковых файлах числа 44100 — это и есть частота дискретизации (подробнее почему именно эти цифры рассмотрим в другой статье).
Что касается оси Y (вертикаль), то она также разбита и имеет определённый шаг. По этой оси отсчитывается дискретное значение, то есть ближайшее к измеренному мгновенному значению.
На третьем рисунке : АЦП округляет все измерения.
На четвёртом рисунке : Аналоговый сигнал превращается в цифровой. Но как вы уже поняли это не совсем исходный сигнал, так как преобразуется он с некоторой погрешностью, зависящей от уровня квантования сигнала.
Sample
Если взять любой аудиофайл и очень сильно увеличить масштаб, то получите следующую картину (файл открыт в программе Adobe Audition):
На рисунке вы видите зелёные квадратики, это и есть отдельные отсчёты сигнала, называемые sample. Линии между квадратиками добавлены только чтобы облегчить наше визуальное восприятие. А на самом деле сигнал дискретен (разделен).
Понравился пост? Поделись с друзьями!
А чтобы подписаться на рассылку нажимай здесь.
Похожие записи
Музыка в игорных заведениях: как ее выбирают и какое влияние оказывает на посетителей
5/5 — (11 голосов) Почему в наземных казино чаще играет спокойная музыка… Узнаем, некоторые нюансы о том, что такое музыка…
Русские синтезаторы
4.9/5 — (19 голосов) В России ведется значительное количество разработок и производство синтезаторов, и вот те, русские синтезаторы за которыми…
Аддитивный синтез звука (Additive)
5/5 — (18 голосов) В этой статье поговорим о таком виде, как аддитивный синтез звука (Additive). Facebook Tweet Подписаться Share…
Субтрактивный синтез звука (Subtractive)
5/5 — (20 голосов) В этой и следующих статьях познакомимся с различными видами синтеза звука. Сегодня поговорим о таком виде,…
Dante, AES 50, AVB и все такое: какой формат аудио сети вам подходит?
5/5 — (30 голосов) Аудиосеть становится все более важной частью концертных и студийных мероприятий. Но в чем разница между всеми сетевыми…
Оцифровка звука на STM32 (АЦП+DMA) и кодирование в Speex для передачи
В продолжение своей вчерашней статьи на Geektimes хочу рассказать подробнее про реализацию оцифровки и кодирования звука на микроконтроллере STM32.
В статье покажу как настроить проект в STM32CubeMX, собирать данные с АЦП в два кольцевых буфера посредствам DMA, подключить библиотеку Speex и кодировать данные. Возможно многим материал покажется весьма очевидным, но надеюсь хоть кому-то он будет полезен.
Прошу под кат.
Что такое Speex?
Speex — это свободный кодек для сжатия речевого сигнала, который может использоваться в приложениях «голос-через-интернет» (VoIP). Сжатые кодеком Speex данные можно хранить либо в формате хранения звуковых данных Ogg, либо передавать напрямую с помощью пакетов UDP/RTP. © Wiki
Про Speex я узнал из статьи Распознавание речи на STM32F4-Discovery, советую почитать, большая часть кода взята оттуда.
В статье я буду использовать самую дешевую и распространенную отладочную плату на базе микроконтроллера STM32F103C8T6. К ней должен быть отдельно приобретен программатор. Подход не изменится и для любой платы Discovery. К отладке я подключал микрофонный модуль с усилителем Max9812.
Схему можно посмотреть в статье, указанной в самом начале. Там я завожу на АЦП сигнал прям с выхода Max9812. Для этого на покупном модуле нужно закоротить конденсатор на ноге OUT (Пятой точкой чувствую, что так делать нельзя, но не знаю как правильно). По входу получается сигнал с постоянной составляющей
1,6V. Его мы отснимаем и в программе приводим к знаковому типу для выполнения кодирования.
Настройка проекта в STM32CubeMX
Создадим новый проект с микроконтроллером STM32F103C8T6. Первым делом указываем, что у нас подключен внешний кварцевый резонатор. Часовой кварц нам сейчас не нужен, хотя на отладочной плате он тоже есть. Не забываем включить интерфейс отладки Serial Wire. Потом включаем необходимый вход АЦП, у меня это IN8 (см. схему в предыдущей статье). Ну и удобный таймер, по которому DMA будет забирать данные из буфера.
После этого заходим во вкладку Clock Configuration и настраиваем схему тактирования. У меня получилось так:
Я задал частоту для основной периферии микроконтроллера по максимуму в 72 МГц. На Таймеры тоже заведено 72 МГц, запомним это значение. Вы можете сделать по-другому, но тогда и таймер надо будет пересчитать по-своему.
Переходим во вкладку Configuration. Тут нам надо настроить АЦП, DMA и Таймер.
АЦП настраиваем по триггеру таймера 3. Тут же во вкладке DMA выделяем под это первый канал DMA Peripheral To Memory (из переферии в память). Приоритет не важен, если в программе больше ничего нет. Режим — Circular (циклический), размер данных Half Word (полслова, 2 байта) и адрес памяти будет инкрементироваться.
Далее настроим таймер. Speex поддерживает кодирование данные в узкой полосе частот (Narrowband, 8 кГц), широкой (wideband, 16 кГц) и ультраширокой (ultra-wideband, 32 кГц). Не будем нагружать контроллер, возьмем по минимуму. Получается контроллер должен отснимать данные с АЦП на частоте 8 кГц. На таймер нам приходит 72 МГц. Считаем:
Настраиваем таймер на значение 8999 (считать ведь он начинает с нуля) и событие по таймеру Update Event. Ставим галочку глобального прерывания.
Можно переходить к генерации проекта. Заходим в Project → Serrings. Укажем путь сохранения проекта и размеры стэка и кучи. Для кодирования Speex нам примерно понадобится 0x600 и 0x1600. После этого генерируем для своей среды и открываем, у меня это IAR.
Подключим библиотеку Speex
Первое, что нужно сделать, скопировать папку STM32F10x_Speex_Lib с библиотекой Speex в папку Drivers проекта. Потом добавим в проект группу libspeex, а в нее следующие файлы (см. скриншот).
В свойствах проекта на вкладке Preprocessor добавим дефайн HAVE_CONFIG_H и следующие дирректории:
$PROJ_DIR$/../Drivers/STM32F10x_Speex_Lib/include
$PROJ_DIR$/../Drivers/STM32F10x_Speex_Lib/libspeex
$PROJ_DIR$/../Drivers/STM32F10x_Speex_Lib/STM32
$PROJ_DIR$/../Drivers/STM32F10x_Speex_Lib/STM32/include
$PROJ_DIR$/../Drivers/STM32F10x_Speex_Lib/STM32/libspeex
$PROJ_DIR$/../Drivers/STM32F10x_Speex_Lib/STM32/libspeex/iar
Попробуем скомпилировать, должно быть все хорошо без варнингов и ошибок.
Тут главное писать код в специально отведенных USER CODE BEGIN-END блоках, тогда, в случае необходимости внесения изменений в проект Куба и повторной его генерации, весь ваш код сохранится. Работу с библиотекой я вынесу в отдельный файл speexx.c. Приведу его код и код заголовочного файла speexx.h сразу:
Также необходимо найти обработчики прерываний таймера и DMA в файле stm32f1xx_it.c и дополнить их переключением флага кодируемых данных Start_Encoding и сбросом флага таймера TIM3_IRQn:
Таким образом вся основная программа сводится к запуску таймера и DMA, инициализации Speex и его кодирования (помимо стандартных инициализаций HAL конечно):
А теперь немного пробегусь по коду. В функции Speex_Init инициализируется только кодировщик Speex, декодер нужно инициализировать отдельно.
Итак, мы настроили АЦП на срабатывание по триггеру таймера. Триггер таймера мы сбрасываем в прерывании каждые 0.125мс (8 кГц).
По прерыванию DMA у нас происходит следующее:
Флаг DMA_FLAG_HT1 (half transfer complete) поднимается когда DMA выполнило работу на половину (читай первая половина буфера заполнена), а флаг DMA_FLAG_TC1 (transfer complete flag) соответственно, когда DMA закончило передачу (вторая половина заполнена).
Вот тут я наткнулся на интересную особенность, которую не знал и потерял на этом время. На отладчике, во время останова, DMA продолжает работать. Таким образом буфер всегда выглядит заполненным полностью и оба флага в поднятом состоянии. Нельзя так отлаживать работу DMA, оно не останавливается.
Семплирование АЦП идет в двойной буфер IN_Buffer[2][FRAME_SIZE], каждая половина размером 160 сэмплов. На выходе уже получаем ENCODED_FRAME_SIZE байт данных, которые отправляются в массив REC_DATA[2][MAX_REC_FRAMES*ENCODED_FRAME_SIZE] по адресу Rec_Data_ptr. Адрес инкрементируется на ENCODED_FRAME_SIZE.
После каждого кодирования счетчик Encoded_Frames инкрементируется и в момент, когда он станет равен MAX_REC_FRAMES, первая половина выходного буфера становится полностью заполнена и можно забирать данные. На это у нас есть время, пока заполняется вторая половина, и так по кругу. Данные забираем из REC_DATA[0] и REC_DATA[1] соответственно.
Можно попробовать поиграться с рамерами фрейма, настройками качества и прочее, но я не стал.
Пример переданного звукового файла есть в репозитории первой статьи.