Вход

Просмотр полной версии : Конвертация аудио беззнаковое в знаковое. Как?



Saar
21.04.2017, 12:30
Пре-амбула:
Делаю новую FPGA платформу для эмуляции разных ретро систем. Свой ZX эмулятор, по традиции, использую в качестве пробного шара. Дошел до аудио где требуется представление ввиде знаковых сэмплов (signed samples) - I2S.

Амбула:
Вроде, согласно общему представлению о конвертации достаточно проинвертировать старший бит чтобы 0..65535 сместить в диапазон -32767..+32767... Но я тут поразмыслил - нельзя так делать, как мне кажется..
Ведь в беззнаковом представлении амплитуда это полный диапазон 0-65536, когда как в знаковом амплитуда вроде как 0-32767.. Можно возразить, что амплитуда всё же -32767..+32767 и вроде равна той что в беззнаковом представлении, однако мне кажется что они не равны..
В добавок при инвертировании старшего бита у меня явный перегруз слышен на I2S, когда как в беззнаковом виде при использовании Delta-Sigma ЦАП перегруза нет.
В добавок к этому, уровень "тишины" после такой конвертации -32768, что не есть хорошо.

Есть ли проверенный метод перевода беззнаковых сэмплов в знаковые?

- - - Updated - - -

Чисто "проигав" знаковй сэмпл в уме, прихожу к выводу что нужна более продвинутая конвертация по типу конденсатора, где спокойствие стремится к нулю а любое возмущение с последующим обратным возмущением рождает отрицательную полуволну...

Titus
21.04.2017, 12:42
Конвертация из беззнакового формата в знаковый - это чисто инверсия старшего бита. Только так и никак более)

Saar
21.04.2017, 13:35
Звук искаженный идет если просто инвертировать старший бит.
И остается нерешенным вопрос по поводу уровня тишины. При инверсии старшего бита он на -32767 что находится на максимуме амплитуды. Отсюда сильные щелчки при инициализации и перезагрузке FPGA.

NEO SPECTRUMAN
21.04.2017, 17:33
Конвертация из беззнакового формата в знаковый - это чисто инверсия старшего бита. Только так и никак более)
о чем это вы ? о_О

2 - 0000 0000 0000 0010
-2 - 1111 1111 1111 1110

чтоб сконвертировать в знаковое нужно сделать -32768±1


чтоб из знакового обратно нужно +32768±1


чтобы сменить знак на противоположный нужно инверсировать биты числа (заменить 0 на 1 и 1 на 0) и +1 (если мы кудато спешим можно и не плюсовать)


простая инверсия бита знака даст страшные искажения
да и инверсия бита знака не даст никакого перевода даже если мы будем хранить числа в формате в котором будет бит знака и смещение от 0 в обыкновенном виде...
и для чисел с плавающей запятой это тоже не прокатит...

NEO SPECTRUMAN
21.04.2017, 20:34
Проверил
16 бит WAV хранит значение со знаком в таком же виде




-32767..+32767
-32768
+32767
как бы

$7FFF маскимум + по версии audacity
$8000 максимум -

самое интересное что audacity
проэкспортировал звук с подмешиванием высокочастотного писка килогерца 22
в итоге в файле уровень 0 колебался в диапазоне ±4
хотя до экспорта была тишина

то же и с максимальным и минимальным уровнем...

Titus
21.04.2017, 23:33
о чем это вы ? о_О

2 - 0000 0000 0000 0010
-2 - 1111 1111 1111 1110

При чем здесь СМЕНА знака и конвертация из беззнакового диапазона в знаковый? Это совершенно разные вещи)
Конвертация из беззнакового формата - это всего лишь смещение на половину диапазона. Т.е. инверсия старшего бита. Или говоря математичнее прибавление или уменьшение числа на 0x8000.
Таким образом самое малое число 0x0000 станет -0x8000, средне 0x8000 станет 0x0000, а самое большое 0xFFFF станет 0x7FFF.

NEO SPECTRUMAN
21.04.2017, 23:52
При чем здесь
Интересно... :v2_conf2:
...картина мира перевернулась... :v2_dizzy_vodka: :v2_dizzy_vodka4:

я делал подобное и получал тот же эффекта с искажением...
из чего сделал вывод что...

а если взять калькулятор то все правильно получается... о_О

интересно где же была ошибко...

Afavyt
20.09.2017, 07:15
В знаковом представлении, уровень тишины - это ноль. В принципе, если вычесть 0х8000, то все работает, но есть нюанс: к примеру, в ZXSpin при отсутствии звука, раздаются потрескивания - это он -0х8000 постоянно в звуковушку кидает, что не есть правильно и хорошо.

А Аудасити, скорее всего, просто добавил дизеринга при конверсии (не проверял, предположение).

Barmaley_m
23.07.2018, 03:00
В добавок к этому, уровень "тишины" после такой конвертации -32768, что не есть хорошо.
А кто вам сказал, что в беззнаковом представлении уровень "тишины" должен быть 0? Нет, он должен быть 32768, что при переводе в беззнаковое представление превращается в нуль.

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

Есть ли проверенный метод перевода беззнаковых сэмплов в знаковые?
Описанная инверсия старшего бита, как правильно заметил выше Titus, и есть такой проверенный метод, единственно верный.

Чисто "проигав" знаковй сэмпл в уме, прихожу к выводу что нужна более продвинутая конвертация по типу конденсатора, где спокойствие стремится к нулю а любое возмущение с последующим обратным возмущением рождает отрицательную полуволну...
"По типу конденсатора" - это фильтр высоких частот. Можно сделать такой фильтр простейшей формулой вида:
y[n] = -a*y[n-1] + x[n] - x[n-1]
где x[n] - входной сигнал, y[n] - выходной сигнал (текущий отсчет), y[n-1] - предыдущий отсчет выходного сигнала, x[n-1] - предыдущий отсчет входного сигнала; a - константа, 0<a<1. От этой константы зависит частота среза по низким частотам. Формула АФЧХ: H = (1-z^-1)/(1+a*z^-1), для АЧХ надо взять модуль от H и перевести его в децибелы; z=exp(-j*w*T), где j^2=-1, w=2*pi*f, f - частота, T - период дискретизации, в секундах; pi=3.14...

Однако хочу предостеречь от использования фильтров без необходимости. Для перевода из беззнакового в знаковый формат никакие фильтры не нужны. Фильтр же приводит к фазовым искажениям и (в некоторой степени) искажениям АЧХ, а также потребляет вычислительные ресурсы. В случае целочисленной реализации фильтр добавляет шум.

ZXMAK
23.07.2018, 08:08
Отсюда сильные щелчки при инициализации и перезагрузке FPGA.

это можно решить, добавив ВЧ FIR фильтр. Для FPGA в квартусе вроде есть визард для создания FIR фильтров.
Частоту среза можно выбрать с небольшим запасом от минимально воспроизводимой.
Т.е. если принять за минимальную частоту 20 Гц, то можно расчитать HPF FIR фильтр на 10 Гц.