Ответ 1
Вы задаете два вопроса:
-
Как сжать от 22 кГц до 8 кГц?
-
Как преобразовать из float [-1,1] в 16-битный int и обратно?
Обратите внимание, что вопрос обновлен, чтобы указать, что № 1 позаботится о другом, но я оставлю эту часть своего ответа, если это поможет кому-то другому.
1. Как сжать от 22 кГц до 8 кГц?
Комментирующий намекнул, что это можно решить с помощью FFT. Это неверно (один шаг в передискретизации - фильтрация. Я упоминаю, почему бы не использовать FFT для фильтрации здесь, если вы заинтересованы: http://blog.bjornroche.com/2012/08/when-to-not-use-fft.html).
Один очень хороший способ перепрограммировать сигнал - это многофазный фильтр. Однако это довольно сложно, даже для тех, кто имеет опыт обработки сигналов. У вас есть несколько других вариантов:
- используйте библиотеку, которая реализует повторную выборку высокого качества, например libsamplerate
- сделать что-то быстрое и грязное
Похоже, что вы уже пошли с первым подходом, что здорово.
Быстрое и грязное решение не будет звучать так же хорошо, но, поскольку вы снижаетесь до 8 кГц, я предполагаю, что качество звука - не ваш первый приоритет. Один быстрый и грязный вариант:
- Применить фильтр нижних частот к сигналу. Постарайтесь избавиться от звука, превышающего 4 кГц, как вы можете. Вы можете использовать фильтры, описанные здесь (хотя в идеале вы хотите что-то гораздо круче, чем эти фильтры, они, по крайней мере, лучше, чем ничего).
- выберите каждый 2.75-й образец из исходного сигнала, чтобы создать новый, повторно выбранный сигнал. Когда вам нужен нецелый образец, используйте линейную интерполяцию. Если вам нужна помощь в линейной интерполяции, попробуйте здесь.
Этот метод должен быть более чем достаточно для голосовых приложений. Тем не менее, я не пробовал, поэтому я не знаю точно, поэтому настоятельно рекомендую использовать другую библиотеку.
Если вы действительно хотите реализовать собственное преобразование частоты дискретизации высокого качества, такое как многофазный фильтр, вам следует изучить его, а затем задать любые вопросы, которые у вас есть, https://dsp.stackexchange.com/, а не здесь.
2. Как конвертировать из float [-1,1] в 16-бит int и обратно?
Это началось c.fogelklou уже, но позвольте мне украсить.
Для начала, диапазон 16-битных целых чисел составляет от -32768 до 32767 (обычно 16-битный звук подписывается). Для преобразования из int в float вы делаете это:
float f;
int16 i = ...;
f = ((float) i) / (float) 32768
if( f > 1 ) f = 1;
if( f < -1 ) f = -1;
Обычно вам не нужно делать лишние "ограничивающие" (на самом деле это не так, если вы действительно используете 16-битное целое число), но это там, если у вас есть некоторые > 16-битные целые числа по какой-либо причине.
Чтобы преобразовать назад, вы делаете это:
float f = ...;
int16 i;
f = f * 32768 ;
if( f > 32767 ) f = 32767;
if( f < -32768 ) f = -32768;
i = (int16) f;
В этом случае обычно необходимо следить за значениями вне диапазона, особенно значениями больше 32767. Вы можете пожаловаться, что это приводит к некоторым искажениям для f = 1. Этот вопрос горячо обсуждается. Для некоторого (неполного) обсуждения этого, см. это сообщение в блоге.
Это больше, чем "достаточно хорошо для работы правительства". Другими словами, он будет работать нормально, за исключением случаев, когда вы обеспокоены качеством звука. Поскольку вы собираетесь на 8 кГц, я думаю, мы установили, что это не так, поэтому этот ответ в порядке.
Однако, для полноты, я должен добавить это: если вы пытаетесь сохранить вещи абсолютно нетронутыми, имейте в виду, что это преобразование вводит искажения. Зачем? Поскольку ошибка при преобразовании из float в int коррелирует с сигналом. Оказывается, корреляция этой ошибки ужасна, и вы действительно можете ее услышать, хотя она очень маленькая. (к счастью, он достаточно мал, что для таких вещей, как речь и низкодинамичная музыка диапазона, это не имеет большого значения). Чтобы устранить эту ошибку, вы должны использовать что-то, называемое dither в преобразовании из float в int. Опять же, если вам что-то нужно, исследуйте его и задайте соответствующие конкретные вопросы https://dsp.stackexchange.com/, а не здесь.
Вы также можете быть заинтересованы в слайдах из моего рассказа об основах цифрового аудиопрограммирования, в котором есть слайд на эту тему, хотя в основном он говорит то же самое (может быть, даже меньше, чем я только что сказал): http://blog.bjornroche.com/2011/11/slides-from-fundamentals-of-audio.html