agosty.ru13. ОХРАНА ОКРУЖАЮЩЕЙ СРЕДЫ, ЗАЩИТА ЧЕЛОВЕКА ОТ ВОЗДЕЙСТВИЯ ОКРУЖАЮЩЕЙ СРЕДЫ. БЕЗОПАСНОСТЬ13.320. Системы аварийной сигнализации и оповещения

ГОСТ Р 56047-2014 Системы охранные телевизионные. Компрессия оцифрованных аудиоданных. Классификация. Общие требования и методы оценки алгоритмов

Обозначение:
ГОСТ Р 56047-2014
Наименование:
Системы охранные телевизионные. Компрессия оцифрованных аудиоданных. Классификация. Общие требования и методы оценки алгоритмов
Статус:
Действует
Дата введения:
09.01.2015
Дата отмены:
-
Заменен на:
-
Код ОКС:
13.320

Текст ГОСТ Р 56047-2014 Системы охранные телевизионные. Компрессия оцифрованных аудиоданных. Классификация. Общие требования и методы оценки алгоритмов


ГОСТ Р 56047-2014

Группа П77

НАЦИОНАЛЬНЫЙ СТАНДАРТ РОССИЙСКОЙ ФЕДЕРАЦИИ

Системы охранные телевизионные

КОМПРЕССИЯ ОЦИФРОВАННЫХ АУДИОДАННЫХ

Классификация. Общие требования и методы оценки алгоритмов

Video surveillance systems. Digital audio data compression. Classification. General requirements and evaluation algorithm methods

ОКС 13.320

ОКП 43 7200

Дата введения 2015-09-01

Предисловие

1 РАЗРАБОТАН Закрытым акционерным обществом "Нордавинд" и Всероссийским научно-исследовательским институтом стандартизации и сертификации в машиностроении (ВНИИНМАШ)

2 ВНЕСЕН Техническим комитетом по стандартизации ТК 234 "Системы тревожной сигнализации и противокриминальной защиты"

3 УТВЕРЖДЕН И ВВЕДЕН В ДЕЙСТВИЕ Приказом Федерального агентства по техническому регулированию и метрологии от 30 июня 2014 г. N 677-ст

4 ВВЕДЕН ВПЕРВЫЕ

Правила применения настоящего стандарта установлены в ГОСТ Р 1.0-2012 (раздел 8). Информация об изменениях к настоящему стандарту публикуется в годовом (по состоянию на 1 января текущего года) информационном указателе "Национальные стандарты", а официальный текст изменений и поправок - в ежемесячно издаваемом информационном указателе "Национальные стандарты". В случае пересмотра (замены) или отмены настоящего стандарта соответствующее уведомление будет опубликовано в ближайшем выпуске ежемесячного информационного указателя "Национальные стандарты". Соответствующая информация, уведомление и тексты размещаются также в информационной системе общего пользования - на официальном сайте Федерального агентства по техническому регулированию и метрологии (gost.ru)

Введение

Активное применение в системах охранных телевизионных (СОТ) методов компрессии оцифрованных аудиоданных, заимствованных из мультимедийных применений телевидения, из-за низкого качества восстановленных после компрессии оцифрованных аудиоданных привело к невозможности осуществления следственных мероприятий, а также оперативных функций, с использованием отдельных СОТ.

Важной отличительной особенностью методов компрессии оцифрованных аудиоданных для СОТ является необходимость обеспечения высокого качества звука в восстановленных аудиоданных. Настоящий стандарт позволяет упорядочить существующие и разрабатываемые методы компрессии оцифрованных аудиоданных, предназначенные для применения в составе систем противокриминальной защиты.

В качестве критерия для классификации алгоритмов компрессии оцифрованных аудиоданных в настоящем стандарте установлены значения метрик качества, характеризующих степень отклонения восстановленных оцифрованных данных от соответствующих им исходных аудиоданных.

Методика классификации алгоритмов компрессии оцифрованных аудиоданных, приведенная в настоящем стандарте, основана на оценке качества восстановленных аудиоданных, с учетом психоакустических особенностей человеческого слуха. Этот подход к оценке качества восстановленных аудиоданных рекомендован Сектором радиосвязи Международного союза электросвязи (МСЭ-Р), членом которого является Российская Федерация.

1 Область применения

Настоящий стандарт распространяется на цифровые системы охранные телевизионные (далее - ЦСОТ) и устанавливает классификацию, общие требования и методы оценки алгоритмов компрессии оцифрованных аудиоданных.

Настоящий стандарт устанавливает методику сравнения различных алгоритмов компрессии и декомпрессии оцифрованных аудиоданных.

Настоящий стандарт применяют к алгоритмам компрессии и декомпрессии аудиоданных независимо от их реализации на аппаратном уровне.

Настоящий стандарт применяют совместно с ГОСТ Р 51558.

2 Нормативные ссылки

В настоящем стандарте использованы нормативные ссылки на следующие стандарты:

ГОСТ 15971 Системы обработки информации. Термины и определения

ГОСТ Р 51558 Средства и системы охранные телевизионные. Классификация. Общие технические требования. Методы испытаний

Примечание - При пользовании настоящим стандартом целесообразно проверить действие ссылочных стандартов в информационной системе общего пользования - на официальном сайте Федерального агентства по техническому регулированию и метрологии в сети Интернет или по ежегодному информационному указателю "Национальные стандарты", который опубликован по состоянию на 1 января текущего года, и по выпускам ежемесячного информационного указателя "Национальные стандарты" за текущий год. Если заменен ссылочный стандарт, на который дана недатированная ссылка, то рекомендуется использовать действующую версию этого стандарта с учетом всех внесенных в данную версию изменений. Если ссылочный стандарт отменен без замены, то положение, в котором дана ссылка на него, рекомендуется применять в части, не затрагивающей эту ссылку.

3 Термины и определения

В настоящем стандарте применены термины по ГОСТ 15971 и следующие термины с соответствующими определениями:

3.1 алгоритм быстрого преобразования Фурье (БПФ) (fast Fourier transform, FFT): Набор алгоритмов, реализация которых приводит к существенному уменьшению вычислительной сложности дискретного преобразования Фурье (ДПФ).

Примечание - Смысл быстрого преобразования Фурье состоит в том, чтобы разбить исходный N-отсчетный сигнал x(n) на два более коротких сигнала, дискретные преобразования Фурье которых могут быть скомбинированы таким образом, чтобы получить дискретное преобразования Фурье исходного N-отсчетного сигнала.

3.2 алгоритм декомпрессии (decompression algorithm): Точный набор инструкций и правил, описывающий последовательность действий, согласно которым сжатые аудиоданные преобразуются в восстановленные, реализуемый при помощи аудиодекодера.

3.3 алгоритм компрессии (compression algorithm): Точный набор инструкций и правил, описывающий последовательность действий, согласно которым исходные аудиоданные преобразуются в сжатые, реализуемый при помощи аудиокодера.

3.4 амплитудно-временная метрика (time-amplitude metric): Метрика качества, основанная на сравнении оцифрованных и восстановленных аудиоданных по форме волны.

3.5 аналого-цифровой преобразователь, АЦП (analog-to-digital converter, ADC): Устройство, преобразующее входной аналоговый аудиосигнал в оцифрованные аудиоданные.

3.6 аудиодекодер (audio decoder): Программные, аппаратные или аппаратно-программные средства, с помощью которых осуществляется декомпрессия сжатых аудиоданных.

3.7 аудиокодер (audio encoder): Программные, аппаратные или аппаратно-программные средства, с помощью которых осуществляется компрессия оцифрованных аудиоданных.

3.8 аудиоданные (audio data), аудиосигнал (audio signal), моноканальный аудиосигнал (mono channel audio): Аналоговый сигнал, несущий информацию об изменении во времени амплитуды звука.

3.9 битрейт (bitrate): Выраженная в битах оценка количества сжатых аудиоданных, определенная для некоторого временного интервала и отнесенная к длительности выбранного временного интервала в секундах.

3.10 восстановленные аудиоданные (recovered audio data): Данные, полученные из сжатых аудиоданных после их декомпрессии.

3.11 декомпрессия сжатых аудиоданных (decompression of compressed digitized audio data): Восстановление оцифрованных данных из сжатых аудиоданных.

3.12 дискретное преобразование Фурье, ДПФ (discrete Fourier transform, DFT): Преобразование, ставящее в соответствие N отсчетам дискретного сигнала N отсчетов дискретного спектра сигнала.

3.13 дифференциация (differentia): Выделение частного из общей совокупности по некоторым признакам.

3.14 искаженный фрейм (distorted frame): Фрейм, для которого максимальное отношение шума к порогу маскирования превышает 1,5 дБ.

3.15 искусственная нейронная сеть (artificial neural network, ANN): Модель биологической нейронной сети, которая представляет собой сеть элементов - искусственных нейронов - связанных между собой синаптическими соединениями.

Примечание - Нейронная сеть предназначена для обработки входной информации и в процессе изменения своего состояния во времени формирует совокупность выходных сигналов.

3.16 качество восстановленных аудиоданных (decoded audio data quality): Объективная оценка соответствия восстановленных аудиоданных исходным оцифрованным аудиоданным на основе рассчитанных метрик качества.

3.17 кодек аудиоданных (audio codec): Программный, аппаратный или аппаратно-программный модуль, способный выполнять как компрессию, так и декомпрессию аудиоданных.

3.18 компрессия (сжатие) оцифрованных аудиоданных (digitzed audio data compression): Обработка оцифрованных аудиоданных с целью уменьшения их объема.

3.19 компрессия оцифрованных аудиоданных без потерь (lossless digitized audio compression): Обработка оцифрованных аудиоданных, при которой не происходит потери информации, вследствие чего восстановленные (в результате выполнения декомпрессии) оцифрованные аудиоданные не отличаются от исходных оцифрованных аудиоданных.

3.20 компрессия оцифрованных аудиоданных с потерями (lossy compression of digitized audio data): Обработка оцифрованных аудиоданных, при которой происходит потеря информации, и вследствие этого восстановленные (в результате выполнения декомпрессии) оцифрованные аудиоданные отличаются от исходных оцифрованных аудиоданных.

3.21 метод оценки алгоритма компрессии (evaluation method of compression algorithm): Метод аналитического определения значений метрик качества на соответствие требованиям, предъявляемым к алгоритмам компрессии аудиоданных.

3.22 метрика качества (quality metric): Аналитически определяемые параметры, характеризующие степень отклонения восстановленных аудиоданных от исходных оцифрованных аудиоданных.

3.23 многоканальный аудиосигнал (multi-channel audio): Аудиосигнал, состоящий из объединения определенного количества аудиосигналов (каналов), которые несут информацию об одном и том же звуке.

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

3.24 окно (window): Весовая функция, которая используется для управления эффектами, обусловленными наличием боковых лепестков в спектральных оценках (растеканием спектра).

Примечание - Имеющуюся конечную запись данных или имеющуюся конечную корреляционную последовательность удобно рассматривать как некоторую часть соответствующей бесконечной последовательности, видимую через применяемое окно.

3.25 оконное преобразование Ханна (short-time Fourier transform with Hann window): Дискретное преобразование Фурье с весовой функцией - окном Ханна.

3.26 оцифрованные аудиоданные (digitized audio data): Данные, полученные путем аналого-цифрового преобразования аудиоданных, представляющие собой последовательность байтов в некотором формате (WAV или др.).

3.27 передискретизация аудиосигнала (resampling): Изменение частоты дискретизации аудиосигнала.

3.28 пиковое отношение сигнал/шум (peak-to-peak signal-to-noise ratio): Соотношение между максимумом возможного значения сигнала и мощностью шума.

3.29 порог маскирования (masking threshold): Пороговый уровень сигнала, не различаемого человеком из-за эффекта психоакустического маскирования.

3.30 психоакустическая модель (psychoacoustics model): Модель для сжатия аудиоданных с потерями, использующая особенности восприятия звука человеческим ухом.

3.31 психоакустическое маскирование (psychoacoustics masking): Подавление (сокрытие) при определенных условиях одного звука другим звуком из-за особенностей восприятия звука человеческим ухом.

3.32 разрядность АЦП (resolution of ADC): Количество бит, которым кодируется каждый отсчет сигнала в процессе АЦП.

3.33 сжатые аудиоданные (compressed audio data): Данные, полученные путем компрессии оцифрованных аудиоданных.

3.34 спектр сигнала (frequency spectrum): Результат разложения сигнала на простые синусоидальные функции (гармоники).

3.35 спектрограмма (spectrogram): Характеристика плотности мощности сигнала в частотно-временном пространстве.

3.36 степень сжатия (compressionratio): Коэффициент сокращения объема оцифрованных аудиоданных в результате компрессии.

3.37 стереофонический двухканальный аудиосигнал (stereophonic audiosignal), стерео аудиосигнал (stereo audio signal), двухканальный аудиосигнал (two-channel audio signal): Многоканальный аудиосигнал, состоящий из двух моноканальных аудиосигналов.

3.38 формат оцифрованных аудиоданных (digitized audio data format): Представление оцифрованных аудиоданных, обеспечивающее их обработку цифровыми вычислительными средствами.

3.39 фрейм (frame): Фрагмент звукового сигнала с заданным количеством значений (длиной фрейма).

3.40 частота дискретизации (sample rate): Частота взятия последовательных значений непрерывного во времени сигнала при его аналого-цифровом преобразовании в оцифрованные аудиоданные.

3.41 частотно-временная метрика (time-frequency metric): Метрика качества, основанная на сравнении спектрограмм оцифрованных и восстановленных аудиоданных.

3.42 шум (noise): Совокупность апериодических звуков различной интенсивности и частоты, не несущая полезную информацию.

4 Общие требования

4.1 Оценку качества восстановленных после сжатия аудиоданных определяют по качеству каждого отдельного звукового фрагмента восстановленных аудиоданных.

4.2 Размер звукового фрагмента определяется в секундах или количеством оцифрованных значений внутри фрагмента.

4.3 Качество звукового фрагмента восстановленных аудиоданных определяют по значениям метрик качества алгоритмов компрессии оцифрованных аудиоданных (далее - метрики качества), характеризующих степень искажения восстановленных после сжатия аудиоданных в сравнении с исходными оцифрованными аудиоданными. Описание метрик приведено в разделе 6 настоящего стандарта, а порядок их расчета приведен в приложении А.

4.4 Алгоритмы компрессии оцифрованных аудиоданных относят к одному из трех классов, установленных в разделе 5 настоящего стандарта.

5 Классификация

5.1 Класс алгоритма компрессии оцифрованных данных определяют по рассчитанным для него значениям метрик качества. Для оценки качества восстановленных аудиоданных и классификации алгоритмов компрессии используют метрики качества, указанные в таблице 1.

Таблица 1 - Диапазоны значений метрик качества по классам алгоритмов компрессии оцифрованных аудиоданных

Метрика качества

Диапазон значений метрик качества по классам алгоритмов компрессии оцифрованных аудиоданных

Класс III

Класс II

Класс I

Пиковое отношение сигнал/шум (PSNR), дБ

Менее 30

[30; 40]

Свыше 40

Коэффициент различия форм сигналов

Более 10

[10; 10]

Менее 10

Объективная оценка аудиоданных с точки зрения восприятия (PEAQ)

[-3,98; -2,3)*

[-2,3; -0,62]

(-0,62; 0,22]*

Примечание - Метрики качества отражают изменения оцифрованных аудиоданных (после их обработки алгоритмами компрессии и декомпрессии), которые могут оказать критическое влияние на возможность использования восстановленных аудиоданных для установления наличия звуковых сигналов, дифференциации звуков и речи.

________________

* Текст документа соответствует оригиналу. - .

5.2 В зависимости от значений метрик качества, вычисленных в ходе проведения их оценки, алгоритм компрессии оцифрованных аудиоданных относят к одному из классов:

- класс III - алгоритмы компрессии, обеспечивающие качество восстановленных аудиоданных, достаточное для установления наличия звуковых сигналов и не уступающее в этом качеству исходных аудиоданных, но создающее помехи при дифференциации звуков, понимании речи.

- класс II - алгоритмы компрессии, обеспечивающие качество восстановленных аудиоданных, достаточное для установления наличия звуковых сигналов, дифференциации звуков, речи и не уступающее в этом качеству исходных аудиоданных, но отличимое от качества исходных аудиоданных;

- класс I - полнофункциональные алгоритмы компрессии, обеспечивающие качество восстановленных аудиоданных, неотличимое от качества исходных аудиоданных.

5.3 Значения метрик качества определяют для каждого звукового фрагмента (длиной 5 с) оцифрованных аудиоданных, а в качестве результирующей оценки восстановленных аудиоданных выбирают наименьшее значение для метрик PSNR и PEAQ и наибольшее значение для коэффициента различия форм сигналов.

Для расчета метрик PSNR и коэффициента различия форм сигналов исходные и восстановленные цифровые аудиоданные должны быть представлены с частотой дискретизации 44100 Гц, 16 битами памяти на одно дискретное значение выборки и с одним звуковым каналом. Длина звукового фрагмента 5 с должна включать в себя 220500 оцифрованных значений.

Для расчета метрики PEAQ исходные и восстановленные цифровые аудиоданные должны быть представлены с частотой дискретизации 48000 Гц, 16 битами памяти на одно дискретное значение выборки и с одним или с двумя звуковыми каналами. Длина звукового фрагмента 5 с должна включать в себя 240000 оцифрованных значений для каждого канала.

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

5.4 Алгоритмы компрессии следует различать по степени сжатия, выражаемой через коэффициент сжатия. Коэффициент сжатия определяют как отношение объема исходных несжатых данных к объему сжатых данных [порядок расчета данной метрики выполняют в соответствии с А.4 (приложение А)].

В зависимости от значения коэффициента сжатия алгоритмы компрессии аудиоданных подразделяют на:

- алгоритмы с высокой степенью сжатия - коэффициент сжатия более 42;

- алгоритмы со средней степенью сжатия - коэффициент сжатия от 15 до 42 включительно;

- алгоритмы с низкой степенью сжатия - коэффициент сжатия менее 15.

6 Методы оценки алгоритмов компрессии

6.1 Общее описание методов оценки

Общая схема работы ЦСОТ при использовании алгоритмов компрессии и декомпрессии представлена на рисунке 1.


Рисунок 1 - Общая схема работы ЦСОТ

Аналоговые аудиоданные подвергают аналогово-цифровому преобразованию, в результате которого получают оцифрованные аудиоданные с определенной частотой дискретизации и количеством битов на одно дискретное оцифрованное значение. На компьютере оцифрованные аудиоданные следует хранить в одном из форматов хранения оцифрованных аудиоданных.

Оцифрованные аудиоданные подвергают компрессии, в результате которой формируют сжатые аудиоданные.

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

В соответствии с представленной общей схемой работы ЦСОТ классификацию алгоритмов компрессии оцифрованных аудиоданных осуществляют путем оценки метрик качества восстановленных аудиоданных от исходных оцифрованных аудиоданных. В зависимости от особенностей технической реализации конкретной ЦСОТ существует два метода оценки: с разделением оцифрованных аудиоданных и с разделением аудиоданных.

Перед оценкой значений метрик качества оба аудиосигнала (исходный и восстановленный) должны быть преобразованы в сигналы с частотой дискретизации 44100 и 48000 Гц. Для указанных частот количество бит, приходящееся на одно дискретное оцифрованное значение, должно быть равным 16.

6.1.1 Метод оценки алгоритма компрессии на основе разделения оцифрованных аудиоданных

Для применения данного метода техническая реализация ЦСОТ должна позволять получить оцифрованные аудиоданные до их обработки алгоритмами компрессии и декомпрессии.


Рисунок 2 - Общая схема реализации метода оценки на основе разделения оцифрованных аудиоданных

Общая схема реализации метода оценки алгоритма на основе разделения оцифрованных аудиоданных представлена на рисунке 2.

Оценку алгоритма выполняют в последовательности:

- на вход испытуемой ЦСОТ подают последовательные аудиоданные;

- оцифрованные и восстановленные аудиоданные сохраняют на устройствах хранения;

- выполняют расчет значений метрик качества и осуществляют классификацию алгоритма компрессии по таблице 1. Описания метрик приведены в 6.2-6.5. Метрики должны быть рассчитаны в соответствии с приложением А.

6.1.2 Метод оценки алгоритма компрессии на основе разделения аудиоданных

Метод оценки алгоритма компрессии на основе разделения аудиоданных следует применять в случае, если техническая реализация ЦСОТ не позволяет применять метод оценки на основе разделения оцифрованных аудиоданных. Применение данного метода требует наличия дополнительной ЦСОТ в составе испытательного стенда, которая предназначена для сохранения оцифрованных аудиоданных.

Общая схема реализации метода оценки на основе разделения аудиоданных представлена на рисунке 3.

Оценку алгоритма компрессии выполняют в последовательности:

- на вход испытуемой ЦСОТ подают последовательные аудиоданные, которые автоматически дублируются на другую ЦСОТ посредством делителя аудиосигнала, являющегося элементом испытательного стенда;

- восстановленные аудиоданные сохраняют на устройствах хранения ЦСОТ;

- оцифрованные аудиоданные сохраняют на устройствах хранения с использованием возможностей второй ЦСОТ (из состава испытательного стенда);

- выполняют расчет значений метрик качества и осуществляют классификацию алгоритма компрессии по таблице 1. Описания метрик приведены в 6.2-6.5. Метрики должны быть рассчитаны в соответствии с приложением А.


Рисунок 3 - Общая схема реализации метода оценки алгоритма компрессии на основе разделения аудиоданных

6.2 Метрика PEAQ

6.2.1 Метрика PEAQ предназначена для оценки качества обработанного сигнала относительно исходного с учетом слуховых особенностей человека (психоакустической модели). Метрика должна быть рассчитана в соответствии с А.1 (приложение А).

6.2.2 Для расчета метрики PEAQ к аудиосигналам предъявляют следующие требования:

- исходный и восстановленный аудиосигналы должны иметь частоту дискретизации равную 48000 Гц. Для сигналов с частотой отличной от указанной необходимо предварительно выполнить передискретизацию аудиосигнала;

- исходный и восстановленный аудиосигналы должны иметь одинаковую длину, т.е. состоять из одного и того же количества оцифрованных значений.

6.3 Метрика PSNR

6.3.1 Метрика PSNR выражает количественную характеристику отношения энергии шума (искажений), вносимого процессом кодирования, к максимально возможной энергии исходного сигнала. Значения метрики PSNR измеряют в децибелах. Метрика должна быть рассчитана в соответствии с А.2 (приложение А).

6.3.2 Для расчета метрики PSNR к аудиосигналам предъявляют следующие требования:

- исходный и восстановленный аудиосигналы должны иметь частоту дискретизации равную 44100 Гц. Для сигналов с частотой, отличной от указанной, необходимо предварительно выполнить передискретизацию аудиосигнала;

- если исходный и восстановленный аудиосигналы многоканальные, то используют только один канал исходного аудиосигнала и соответствующий ему один канал восстановленного аудиосигнала.

6.4 Метрика "коэффициент различия форм сигналов"

6.4.1 Разница соседних последовательных значений амплитуд исходного аудиосигнала, полученных в результате импульсно-кодовой модуляции, и разница соседних последовательных значений амплитуд восстановленного аудиосигнала определяют соответственно форму исходного аудиосигнала и форму восстановленного аудиосигнала в последовательные моменты времени. Конечное значение метрики "коэффициента различия форм сигналов" подсчитывают как суммарную среднеквадратичную ошибку между формой исходного аудиосигнала и формой восстановленного аудиосигнала. Метрика должна быть рассчитана в соответствии с А.3 (приложение А).

6.4.2 Для расчета метрики "коэффициент различия форм сигналов" к аудиосигналам предъявляют следующие требования:

- исходный и восстановленный аудиосигналы должны иметь частоту дискретизации равную 44100 Гц. Для сигналов с частотой, отличной от указанной, необходимо предварительно выполнить передискретизацию аудиосигнала;

- если исходный и восстановленный аудиосигналы многоканальные, то для расчета метрики используют только один канал исходного аудиосигнала и соответствующий ему один канал восстановленного аудиосигнала.

6.5 Метрика "коэффициент сжатия"

6.5.1 Метрика "коэффициент сжатия" предназначена для характеристики качества алгоритма компрессии с точки зрения уменьшения объема занимаемой исходными аудиоданными памяти после их обработки алгоритмом сжатия. Метрика должна быть рассчитана в соответствии с А.4 (приложение А).

7 Методы сравнения алгоритмов компрессии оцифрованных аудиоданных

7.1 Два и более алгоритмов компрессии сравнимы друг с другом, если они принадлежат одному и тому же классу в соответствии с таблицей 1.

7.2 Из двух и более сравниваемых алгоритмов компрессии лучшим признают алгоритм, обеспечивающий лучшие значения хотя бы двух из трех метрик, приведенных в таблице 1. Лучшим значением метрики признают большее значение - для метрик PSNR и PEAQ и меньшее значение - для метрики "коэффициент различия форм сигналов". Если сравниваемые алгоритмы имеют одинаковые значения метрик качества, приведенных в таблице 1, то лучшим считают алгоритм с наибольшей степенью сжатия, определяемой коэффициентом сжатия по 6.5.

Приложение А
(обязательное)

Математическое описание алгоритмов расчета метрик оценки качества алгоритмов компрессии аудиоданных

А.1 Алгоритм расчета метрики PEAQ

А.1.1 Обозначения, используемые в алгоритме:

=48000 Гц - частота дискретизации сигналов;

=2048 - количество оцифрованных значений сигнала, определяющих длину звукового фрагмента (размер фрейма);

x[n] - оцифрованные данные фрейма, где n - целое число, представляющее собой индекс конкретного значения амплитуды сигнала внутри звукового фрагмента (фрейма), n[0, -1].

покадровый шаг вперед: /2=1024, таким образом перекрытие фреймов составляет 50%;

/1024 - частота выборки кадров с учетом покадрового шага;

=109 - количество частотных полос фильтрации.

А.1.2 Расчет метрики должен состоять из пяти этапов:

I - предварительная обработка сигналов;

II - обработка образов;

III - расчет выходных значений психоакустической модели;

IV - нормирование значений выходных переменных психоакустической модели;

V - оценка качества восстановленного сигнала с помощью искусственной нейронной сети.

А.1.2.1 Предварительная обработка сигналов

А.1.2.1.1 Применение оконного преобразования

Исходные оцифрованные данные разбивают на фреймы. Оцифрованные данные каждого фрейма подвергают масштабированному оконному преобразованию Ханна, , по формуле

, (А.1)

где h [n, ] - функция, рассчитываемая по формуле

(А.2)

Переход в частотную область осуществляют путем применения дискретного преобразования Фурье (ДПФ) по формуле

, (А.3)

где 0-1;

j - мнимая единица.

А.1.2.1.2 Модель наружного и среднего уха

Частотную характеристику наружного и среднего уха вычисляют по формуле

, (А.4)*

где - частота, заданная в кГц, а * вычисляют по формуле

. (А.5)*

________________

* Формулы и экспликации к ним соответствуют оригиналу. - .

По формуле (А.4) вектор весовых коэффициентов W[k] вычисляют следующим образом:

, (А.6)

где 0.

Используя веса, рассчитанные по формуле (А.6), вычисляют взвешенную энергию ДПФ по формуле:

, (А.7)

где 0;

=2,794·10.

А.1.2.1.3 Разложение критической полосы слуха

Для преобразования частоты сигнала в высоту звука используют шкалу Барка. Расчет следует производить по формуле (А.8), для обратного преобразования - по формуле (А.9)

, (А.8)

где z - высота звука, измеряемая в Барках.

. (А.9)

Полосы частот определяют заданием нижней, центральной и верхней частот каждой полосы и их значение по шкале Барка определяют по формулам

, (А.10)


(А.11)


, (А.12)

где =1/4;

;

;

=80 Гц;

=18 кГц.

Обратное преобразование выполняют по формулам

, (А.13)


, (А.14)


, (А.15)

где i=1, 2, ..., =109.

Вклад энергии от k-ой основной частоты ДПФ U[i, k] для i-й полосы частот вычисляют по формуле

. (А.16)

Энергию i-й полосы частот вычисляют по формуле

, (А.17)

где ;

.

Конечную формулу энергии i-й полосы частот [i] вычисляют по формуле

, (А.18)

где =1·10.

А.1.2.1.4 Внутренний шум уха

Для компенсации внутренних шумов в самом ухе, следует ввести надбавочное значение [i] для энергии каждой полосы частот, E[i]:

, (А.19)

где внутренний шум [i] моделируют следующим образом:

(А.20)

Энергии E[i] - образы высоты.

А.1.2.1.5 Энергия распространения в пределах одного фрейма

Характеристику энергии распространения в шкале Барка [i] рассчитывают по формуле

, (А.21)

где [i] - характеристика, рассчитываемая по формуле

, (А.22)

где E[i] - надбавочные значения энергий из (А.19);

E[0] устанавливают равным 1;

S(i, , E) - характеристика, рассчитываемая по формуле

(А.23)

где (для упрощения записи выражения) ;

;

;

.

Тогда (, E) преобразуется по формуле

(А.24)

Слагаемые [i] и [i] из формулы (А.21) вычисляют по формулам

, (А.25)

где -2, ..., 0.

, (А.26)


. (А.27)

Энергии [i] в дальнейшем в тексте стандарта - образы нераспространенных возбуждений.

А.1.2.1.6 Фильтрация энергии

Фильтрацию энергии вычисляют по формулам

, (А.28)


, (А.29)

где n - индекс фрейма (фреймы проиндексированы, начиная с n=0);

[i, n] - энергия n-го фрейма, соответствующая формуле (А.21);

[i] - постоянная времени для угасающей энергии. Начальное условие для фильтрации: [i, -1]=0.

[i, n] - конечные значения (образы возбуждений в дальнейшем).

А.1.2.1.7 Постоянные времени

Постоянную времени для фильтрации i-й полосы вычисляют по формуле

, (А.30)

где =0,03 c;

=0,008 c.

Постоянную времени для угасающей энергии [i] следует вычислять по формуле

. (А.31)

На рисунке А.1 приведена схема предварительных вычислений.


Рисунок А.1 - Схема предварительных вычислений

Индексами R и T обозначают исходный и восстановленный аудиосигналы соответственно. Индексом k обозначают индекс полосы частот (всего 109 полос частот), а индексом n - номер фрейма. Для рекуррентных формул на этом этапе и этапе III всегда выбирают нулевые начальные условия.

А.1.2.2 Обработка образов

А.1.2.2.1 Обработка образов возбуждений

Входными данными для этой стадии вычислений являются образы возбуждений [k, n] и [k, n], рассчитываемые по формулам (А.28) и (А.29) для исходного и восстановленного аудиосигналов соответственно.

Коррекция образов возбуждений

Сначала осуществляют фильтрацию для обоих аудиосигналов по формулам

, (А.32)


, (А.33)

где [i] - постоянная времени, рассчитываемая по формулам (А.30) и (А.31), но при =0,05c, =0,008c.

Начальное условие для фильтрации выбирают равным 0.

Далее вычисляют коэффициент коррекции, [n]:

. (А.34)

Образы возбуждений, [k, n] и [k, n], корректируют по формулам

(А.35)

(А.36)

Адаптация образов возбуждений

Используя те же постоянные времени и начальные условия, что и при коррекции образов возбуждений, выходные сигналы, рассчитанные по формулам (А.35) и (А.36), сглаживают в соответствии с формулами

, (А.37)


. (А.38)

На основе соотношения между рассчитанными в формулах (А.37) и (А.38) значениями вычисляют пару вспомогательных сигналов:

(А.39)


(А.40)

Если в формулах (А.39) и (А.40) числитель и знаменатель равны нулю, то необходимо выполнить действия:

и . (А.41)


Если k=0, то [k, n]=[k, n]=1. (А.42)

С целью формирования множителей для коррекции образов вспомогательные сигналы подвергают фильтрации с использованием тех же постоянных времени и начального условия, что и в формулах (А.32) и (А.33):

*, (А.43)

________________

* Формула соответствует оригиналу. - .

, (А.44)

где

, (А.45)


, (А.46)


, . (А.47)

Конечным результатом этой стадии обработки, на основе формул (А.43) и (А.44) получают спектрально адаптированные образы, [k, n] и [k, n], по формулам

, (А.48)


, (А.49)

А.1.2.2.2 Обработка образов модуляции

Входными данными для этой стадии вычислений являются образы нераспространенных возбуждений [k, n] и [k, n], которые рассчитывают по формуле (А.21) для исходного и восстановленного аудиосигналов соответственно. Вычисляют меры модуляций огибающих спектра.

Предварительно вычисляют среднюю громкость, [k, n] и [k, n] по формулам

, (А.50)


. (А.51)

Далее необходимо вычислить разности [k, n] и [k, n]:

, (А.52)


. (А.53)

Постоянные времени и начальные условия используют те же самые, что и в А.1.2.2.1.

Меры модуляции огибающих спектра вычисляют по формулам

, (А.54)


. (А.55)

А.1.2.2.3 Вычисление громкости

Образы громкости вычисляют в соответствии с формулами

, (А.56)


, (А.57)

где с=1,07664.

, (А.58)


, (А.59)


, (А.60)


. (А.61)

Общие громкости для обоих сигналов вычисляют по формулам

, (А.62)


. (А.63)

А.1.2.3 Расчет выходных значений психоакустической модели

А.1.2.3.1 Общее описание процесса расчета параметров

Выходные характеристики из А.1.2.1 используют для вычисления выходных характеристик А.1.2.2 в соответствии со схемой, приведенной на рисунке А.2.


Рисунок А.2 - Схема обработки образов

Значения из А.1.2.2 используют для вычисления выходных значений переменных психоакустической модели (см. таблицу А.1 и рисунок А.3).

Рассчитывают значения 11 переменных психоакустической модели. Наименование и краткое описание переменных психоакустической модели приведены в таблице А.1.

Таблица А.1 - Выходные переменные психоакустической модели

Наименования выходной переменной модели

Описание

BandwidthRefB

Ширина полосы исходного аудиосигнала

BandwidthTestB

Ширина полосы восстановленного аудиосигнала

Total NMRB

Отношение уровня шума к порогу маскирования

WinModDiff1B

Оконная разница модуляций

ADBB

Среднее поблочное искажение

EHSB

Гармоническая структура ошибки

AvgModDiff1B

Средняя разница модуляции 1

AvgModDiff2B

Средняя разница модуляции 2

RmsNoiseLoudB

Громкость шума

MFPDB

Максимальная вероятность обнаружения искажения

RelDistFramesB

Относительное искажение фреймов


Рисунок А.3 - Схема вычисления значений выходных переменных психоакустической модели

Для двухканальных аудиосигналов значения переменных для каждого канала следует рассчитывать отдельно, а затем усреднять. Значения всех переменных (кроме значений переменных ADBB и MFPDB) для каждого канала сигнала рассчитывают независимо от второго канала.

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

Значения, которые будут усреднены, должны лежать в границах, определяемых следующим условием: начало или конец данных, которые будут подвержены усреднению, определяют как первую позицию с начала или с конца последовательности значений амплитуд аудиосигнала, для которой сумма пяти последовательных абсолютных значений амплитуд превышает 200 в любом из аудиоканалов. Фреймы, которые лежат вне этих границ, следует игнорировать при усреднении. Значение порога 200 используют в случае, если амплитуды входных аудиосигналов нормализованы в диапазоне от минус 32768 до плюс 32767. В противном случае значение порога вычисляют следующим образом:

, (А.64)

где - максимальное значение амплитуды аудиосигнала.

В дальнейшем индекс фрейма n начинается с нуля для первого фрейма, удовлетворяющего условиям проверки границ с порогом , и отсчитывает число фреймов N вплоть до последнего фрейма, удовлетворяющего вышеприведенному условию.

А.1.2.3.2 Оконная разница модуляций 1 (WinModDiff1B)

Вычисляют мгновенную разницу модуляций, [k, n], по формуле

. (А.65)

Значение мгновенной разницы модуляций усредняют по всем полосам частот в соответствии со следующей формулой

. (А.66)

Конечное значение выходной переменной получают усреднением формулы (А.66) со скользящим окном L=4 (85 мс, так как каждый шаг равен 1024 оцифрованных значений):

. (А.67)

При этом применяют усреднение с задержкой - первые 0,5 с сигнала не участвуют в вычислениях. Количество пропускаемых фреймов составляет:

. (А.68)

В формуле (А.68) операция означает отбрасывание дробной части.

В формуле (А.67) индекс фреймов включает только фреймы, которые идут после задержки величиной 0,5 с.

А.1.2.3.3 Средняя разница модуляций 1 (WinModDiff1B)

Значение данной выходной переменной психоакустической модели, , вычисляют по формуле

, (А.69)

где

. (А.70)

Для вычисления этого значения также применяют усреднение с задержкой.

А.1.2.3.4 Средняя разница модуляций 2 (WinModDiff2B)

Сначала вычисляют значение мгновенной разницы модуляций по формуле

(А.71)

Затем вычисляют усредненное по полосам частот значение разности модуляций:

. (А.72)

Конечное значение переменной психоакустической модели вычисляют по формулам (А.73) и (А.74)

, (А.73)

где

. (А.74)

При вычислении этого значения также применяют усреднение с задержкой.

А.1.2.3.5 Громкость шума (RmsNoiseLoudB)

Значение мгновенной громкости шума рассчитывают по формуле

, (А.75)


где , (А.76)

где =1.

; (А.77)


; (А.78)


, (А.79)

где =1,5;

=0,15;

=0,5.

Если мгновенная громкость менее 0, ее устанавливают равной 0:

(А.80)

Значение конечной выходной переменной психоакустической модели находят усреднением мгновенной громкости по формуле (А.81):

. (А.81)

Для вычисления этого значения применяют усреднение с задержкой. Совместно с усреднением с задержкой используют порог громкости для нахождения значения мгновенной громкости шума, начиная с которого выполняют процесс усреднения. Таким образом, усреднение начинают с первого значения, определяемого условием превышения порога громкости, но не позднее 0,5 с от начала сигнала (в соответствии с усреднением с задержкой).

Условие превышения порога громкости

Значения мгновенной громкости шума в начале обоих сигналов (исходного и восстановленного) игнорируют до тех пор, пока не пройдет 50 мс после того, как значение общей громкости превысит в обоих каналах одного из сигналов значение порога, равное 0,1.

Условие превышения порога имеет вид:

, для моносигнала

(А.82)

, стереосигнала,

где =0,1.

Количество пропускаемых после превышения порога фреймов рассчитывают по формуле (А.83)

. (А.83)

А.1.2.3.6 Ширина полос исходного и восстановленного аудиосигналов (BandwidthRefB и BandwidthTestB)

Операции вычислений ширины полос исходного и восстановленного аудиосигналов описывают в терминах операций на выходных значениях ДПФ, выраженных в децибелах. Прежде всего для каждого фрейма выполняют следующие операции:

- для восстановленного сигнала: находят самую большую компоненту после частоты 21600 Гц. Это значение называют уровнем порога;

- для исходного сигнала: выполняя поиск вниз, начиная с частоты 21600 Гц, находят первое значение, которое превышает значение уровня порога на 10 дБ. Соответствующую этому значению частоту называют шириной полосы для исходного сигнала;

- для восстановленного сигнала: выполняя поиск вниз, начиная со значения ширины полосы исходного сигнала, находят первое значение, которое превышает значение уровня порога на 5 дБ. Обозначают соответствующую этому значению частоту как ширину полосы для восстановленного сигнала.

Если найденные частоты для исходного сигнала не превышают 8100 Гц, то ширину полосы для этого фрейма игнорируют.

Значения ширин полос для всех фреймов называют основными частотами ДПФ.

Основную частоту ДПФ для n-го фрейма обозначают как [n] для исходного сигнала и как [n] - для восстановленного сигнала. Вычисление конечных значений переменных психоакустической модели, значений ширин полос исходного и восстановленного сигналов необходимо выполнять по следующим формулам соответственно:

. (А.84)


, (А.85)

где суммирование осуществляют только для тех фреймов, в которых основная частота ДПФ превышает 8100 Гц.

А.1.2.3.7 Отношение уровня шума к порогу маскирования (TotalNMRB)

Порог маскирования M[k, n] вычисляют по формуле (А.86)

, (А.86)

где

(А.87)

Уровень шума, [k], вычисляют по формуле (А.88)

, (А.88)

где k - индекс основной частоты ДПФ.

Отношение уровня шума к порогу маскирования в k-й полосе частот выражают формулой (А.89)

. (А.89)

Конечное отношение уровня шума к порогу маскирования , дБ, вычисляют по формуле (А.90)

. (А.90)

А.1.2.3.8 Относительное искажение фреймов (RelDistFramesB)

Максимальное отношение шума к порогу маскирования фрейма [n] вычисляют по формуле (А.91):

. (А.91)

Искаженным считают тот фрейм, в котором максимальное отношение шума к порогу маскирования более 1,5 дБ.

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

А.1.2.3.9 Максимальная вероятность обнаружения искажения (MFPDB)

Сначала вычисляют асимметричное возбуждение:

, (А.92)

где (А.93)

Далее вычисляют шаг для обнаружения искажения, s [k, n], по формуле

(А.94)

где =-0,198719;

=0,0550197;

=-0,00102438;

(А.95)

=5,05622·10;

=9,01033·10;

=5,95072.

=6,39468;

=1,71332;

Вероятность обнаружения вычисляют по формуле

, (А.96)

где показатель степени b вычисляют по формуле

(А.97)

Затем вычисляют количество шагов сверх порога вероятности обнаружения, [k, n], по формуле

. (А.98)

Характеристики по формулам (А.96) и (А.98) вычисляют для каждого канала сигнала. Для каждой частоты и времени полную вероятность обнаружения и полное число шагов сверх порога выбирают как большее значение из всех каналов:

, (А.99)


, (А.100)

где индексы 1 и 2 - номера каналов.

Для одноканальных сигналов характеристики вычисляют по формулам (А.101) и (А.102):

. (А.101)


. (А.102)

Выполняют следующие вычисления:

, (А.103)

где =0,9 и начальное условие - нулевое.

Максимальную вероятность обнаружения искажения [n] вычисляют по рекуррентной формуле

. (А.104)

Конечное значение выходной переменной психоакустической модели MFPD рассчитывают по формуле (А.105)

. (А.105)

А.1.2.3.10 Среднее поблочное искажение (ADBB)

Сначала вычисляют сумму общего числа шагов сверх порога обнаружения по формуле

. (А.106)

Причем суммирование ведут для всех значений, для которых [n]>0,5.

Конечная характеристика ADB имеет вид:

. (А.107)

А.1.2.3.11 Гармоническая структура ошибки (EHSB)

Выходы ДПФ для исходного и восстановленного сигналов обозначают как [k] и [k] соответственно.

Вычисляют характеристику D[k]:

, . (А.108)

Формируют вектор длины M из значений D[k]:

, (A.109)

где .

Нормализованную автокорреляцию вычисляют по формуле (А.110)

, (А.110)

где .

При необходимо вычислить:

(А.111)

При вычислении по формуле (А.110) в случае, если сигналы равны, необходимо установить нормализованную автокорреляцию равной единице, чтобы избежать деления на ноль.

Вводят оконную функцию:

(А.112)

К нормализованной автокорреляции применяют оконное преобразование по формуле (А.113)

, , (А.113)


где . (А.114)

Спектр мощности S[k] вычисляют по формуле (А.115)

. (А.115)

Поиск максимального пика спектра мощности начинают с k=1 и заканчивают при S[k]>S[k-1] или k>/2. Найденное значение максимального пика обозначают как [n]. Тогда конечное значение выходной переменной психоакустической модели рассчитывают по формуле (А.116)

. (А.116)

При вычислении этого значения исключают фреймы с низкой энергией. Для определения фреймов с низкой энергией вводят пороговое значение

, (А.117)

где =32768 для амплитуд, хранимых в виде 16 битного целого числа.

Энергию фрейма оценивают по формуле (А.118):

. (А.118)

При вычислении гармонической структуры ошибки фрейм игнорируют, если:

, для моносигнала,

(А.119)


, для стереосигнала.

А.1.2.4 Нормирование значений выходных переменных психоакустической модели

Нормирование полученных на предыдущем шаге значений выходных переменных психоакустической модели выполняют по формуле (А.120)

, (А.120)

где [i] - значение i-й выходной переменной психоакустической модели, а значения [i] и [i] приведены в таблице А.2.

Таблица А.2 - Константы для нормирования значений выходных переменных психоакустической модели

Индекс переменой, i

Наименование переменной

Минимальное значение [i]

Максимальное значение [i]

0

BandwidthRefB

393,916656

921,0

1

BandwidthTestB

361,965332

881,131226

2

TotalNMRB

-24,045116

16,212030

3

WinModDiff1B

1,110661

107,137772

4

ADBB

-0,206623

2,886017

5

EHSB

0,074318

13,933351

6

AvgModDiff1B

1,113683

63,257874

7

AvgModDiff2B

0,950345

1145,018555

8

RmsNoiseLoudB

0,029985

14,819740

9

MFPDB

0,000101

1,0

10

RelDistFramesB

0,0

1,0

А.1.2.5 Оценка качества восстановленного сигнала с помощью искусственной нейронной сети

На вход нейронной сети подают значения 11 выходных переменных психоакустической модели, рассчитанных в А.1.2.1-А.1.2.4. Нейронная сеть имеет 11 нейронов во входном слое, один скрытый слой с тремя нейронами и один нейрон в выходном слое. Выход нейронной сети - конечное значение метрики PEAQ рассчитывают по формуле (А.121)

, (А.121)

где =-3,98 и =0,22, а функция sig (x) - асимметричная сигмоида:

. (А.122)

Значение вычисляют следующим образом:

, (А.123)

где [i] - нормализованное значение i-й выходной переменной, - количество выходных переменных (равное 11), J - количество нейронов в скрытом слое (равное трем), , , , - значения весов и смещений нейронной сети, приведенные в таблицах А.3-А.5.

Таблица А.3 - Веса нейронной сети

Индекс i

Вес [i, 0]

Вес [i, 1]

Вес [i, 2]

0

-0,502657

0,436333

1,219602

1

4,307481

3,246017

1,123743

2

4,984241

2,211189

-0,192096

3

0,0511056

-1,762424

4,331315

4

2,321580

1,789971

-0,754560

5

-5,303901

-3,452257

-10,814982

6

2,730991

-6,111805

1,519223

7

0,624950

-1,331523

-5,955151

8

3,10288

0,871260

-5,922878

9

-1,051468

-0,939882

-0,142913

10

-1,804679

-0,503610

0,620456

Таблица А.4 - Смещения нейронной сети

Bias

Bias [0]

Bias [1]

Bias [2]

-0,307594

-2,518254

0,654841

-2,207228

Таблица А.5 - Веса и смещения нейронной сети

Индекс j

Вес [j]

0

-3,817048

1

4,017138

2

4,629582

Это значение метрики (PEAQ) представляет собой вещественное число, принадлежащее отрезку [-3,98; 0,22].

А.2 Алгоритм расчета метрики PSNR

Пиковое отношение сигнал/шум между исходным аудиосигналом и восстановленным рассчитывают по формулам:

, (А.124)


, (А.125)

где разности значений сигналов и их математическое ожидание рассчитывают по формулам:

, , (А.126)

где и - i-e оцифрованные значения исходного и восстановленного аудиосигналов соответственно, i=1, 2, ..., n;

- максимальное значение среди оцифрованных значений исходного аудиосигнала.

А.3 Алгоритм расчета метрики "коэффициент различия форм сигналов"

Пусть - исходный моноканальный аудиосигнал (либо один канал исходного многоканального аудиосигнала), а - восстановленный моноканальный аудиосигнал (либо один канал восстановленного многоканального аудиосигнала). Оба сигнала состоят из одинакового количества значений N.

Массивы значений амплитуд сигналов и представляют в виде относительного изменения значений амплитуд сигнала:

, (А.127)


. (А.128)

Значение метрики "коэффициент различия форм сигналов" вычисляют как среднеквадратическое отклонение массивов значений амплитуд и

. (А.129)

А.4 Алгоритм расчета коэффициента сжатия

Пусть - объем памяти, который занимают исходные аудиоданные, а - объем памяти, который занимают сжатые данные, тогда коэффициент сжатия k рассчитывают по формуле

. (А.130)



Приложение Б
(рекомендуемое)

Листинги программ расчета метрик качества аудиоданных

Б.1 Листинг программы расчета метрики PEAQ на языке Matlab

function ODG = PQevalAudio (Fref, Ftest, StartS, EndS)

% Оценка качества аудиоданных с точки зрения восприятия (Perceptual evaluation of audio quality)

% - StartS - индекс значения, соответствующего началу сигнала.

% - EndS - индекс значения, соответствующего концу сигнала.

% глобальные переменные

global MOVC PQopt

% параметры

NF = 2048;

Nadv = NF/2;

Version ='Basic';

% настройки

PQopt.ClipMOV = 0;

PQopt.PCinit = 0;

PQopt.PDfactor = 1;

PQopt.Ni = 1;

PQopt.DelayOverlap = 1;

PQopt.DataBounds = 1;

PQopt.EndMin = NF/2;

addpath ('CB', 'MOV, 'Misc', 'Patt');

if (nargin < 3)

StartS = [0, 0];

end

if (nargin < 4)

EndS = [];

end

% вычислить количество значений и каналов для каждого входного файла

WAV(1) = PQwavFilePar (Fref);

WAV(2) = PQwavFilePar (Ftest);

% согласовать размеры файлов

PQ_CheckWAV (WAV);

if (WAV(1).Nframe ~= WAV(2).Nframe)

disp ('>>>Number of samples differ: using the minimum');

end

% границы данных

Nchan = WAV(1).Nchan;

[Starts, Fstart, Fend] = PQ_Bounds (WAV, Nchan, StartS, EndS, PQopt);

% фреймов PEAQ

Np = Fend - Fstart + 1;

if (PQopt.Ni < 0)

PQopt.Ni=ceil (Np/abs(PQopt.Ni));

end

% инициализация структуры MOV

MOVC = PQ_InitMOVC (Nchan, Np);

Nc = PQCB (Version);

for (j = 0:Nchan-1)

Fmem(j+1) = PQinitFMem (Nc, PQopt.PCinit);

end

is = 0;

for (i = -Fstart:Np-1)

% считать фрейм данных

xR = PQgetData (WAV(1), StartS(1) + is, NF); % Reference file

xT = PQgetData (WAV(2), StartS(2) + is, NF); % Test file

is = is + Nadv;

% обработка фрейма

for (j = 0:Nchan-1)

[MOVI(j+1), Fmem(j+1)] = PQeval (xR(j+1,:), xT(j+1,:), Fmem(j+1));

end

if (i >= 0)

% вывести MOV в новую структуру

PQframeMOV (i, MOVI); % выходные значения теперь в глобальной переменной MOVC

% вывод значений

if (PQopt.Ni ~= 0 & mod (i, PQopt.Ni) == 0)

%

PQprtMOVCi (Nchan, i, MOVC);

end

end

end

% усреднение по времени значений MOV

if (PQopt.DelayOverlap)

Nwup = Fstart;

else

Nwup = 0;

end

MOVB = PQavgMOVB (MOVC, Nchan, Nwup);

% запуск нейронной сети

ODG = PQnNet (MOVB);

% совокупный вывод значений

% PQprtMOV (MOVB, ODG);

%----------

function PQ_CheckWAV (WAV)

% проверка файлов

Fs = 48000;

if (WAV(1).Nchan ~= WAV(2).Nchan)

error ('>>> Number of channels differ');

end

if (WAV(1).Nchan > 2)

error ('>>> Too many input channels');

end

if (WAV(1).Nframe ~= WAV(2).Nframe)

disp ('>>> Number of samples differ');

end

if (WAV(1).Fs ~= WAV(2).Fs)

error ('>>> Sampling frequencies differ');

end

if (WAV(1).Fs ~= Fs)

error ('>>> Invalid Sampling frequency: only 48 kHz supported');

end

%----------

function [StartS, Fstart, Fend] = PQ_Bounds (WAV, Nchan, StartS, EndS, PQopt)

PQ_NF = 2048;

PQ_NADV = (PQ_NF/2);

if (isempty (StartS))

StartS(1) = 0;

StartS(2) = 0;

elseif (length (StartS) ==1)

StartS(2) = StartS(1);

end

Ns = WAV(1).Nframe;

% границы данных

if (PQopt.DataBounds)

Lim = PQdataBoundary (WAV(1), Nchan, StartS(1), Ns);

fprintf ('PEAQ Data Boundaries: %ld (%.3f s) - %ld (%.3f s)\n', ...

Lim(1), Lim(1)/WAV(1).Fs, Lim(2), Lim(2)/WAV(1).Fs);

else

Lim = [Starts(1), StartS(1) + Ns -1];

end

% номер первого фрейма

Fstart = floor ((Lim(1) - StartS(1)) / PQ_NADV);

% номер последнего фрейма

Fend = floor ((Lim(2) - StartS(1) + 1 - PQopt.EndMin) / PQ_NADV);

%----------

function MOVC = PQ_lnitMOVC (Nchan, Np)

MOVC.MDiff.Mt1 В = zeros (Nchan, Np);

MOVC.MDiff.Mt2B = zeros (Nchan, Np);

MOVC.MDiff.Wt = zeros (Nchan, Np);

MOVC.NLoud.NL = zeros (Nchan, Np);

MOVC.Loud.NRef = zeros (Nchan, Np);

MOVC.Loud.NTest = zeros (Nchan, Np);

MOVC.BW.BWRef = zeros (Nchan, Np);

MOVC.BW.BWTest = zeros (Nchan, Np);

MOVC.NMR.NMRavg = zeros (Nchan, Np);

MOVC.NMR.NMRmax = zeros (Nchan, Np);

MOVC.PD.Pc = zeros (1, Np);

MOVC.PD.Qc = zeros (1, Np);

MOVC.EHS.EHS = zeros (Nchan, Np);

function ODG = PQnNetB (MOV) '

% нейронная сеть для получения конечного значения метрики

persistent amin amax wx wxb wy wyb bmin bmax I J CLIPMOV

global PQopt

if (isempty (amin))

I = length (MOV);

if (l == 11)

[amin, amax, wx, wxb, wy, wyb, bmin, bmax] = NNetPar ('Basic');

else

[amin, amax, wx, wxb, wy, wyb, bmin, bmax] = NNetPar ('Advanced');

end

[I, J] = size (wx);

end

sigmoid = inline ('1 / (1 + exp(-x))');

% Scale the MOV's

Nclip = 0;

MOVx = zeros (1, I);

for (i = 0:I-1)

MOVx(i+1) = (MOV(i+1) - amin(i+1)) / (amax(i+1) - amin(i+1));

if (~ isempty (PQopt) & PQopt.ClipMOV ~= 0)

if (MOVx(i+1) < 0)

MOVx(i+1) = 0;

Nclip = Nclip + 1;

elseif (MOVx(i+1) > 1)

MOVx(i+1)= 1;

Nclip = Nclip + 1;

end

end

end

if (Nclip > 0)

fprintf ('>>> %d MOVs clipped/n', Nclip);

end

% нейтронная сеть

DI = wyb;

for (j = 0:J-1)

arg = wxb(j+1);

for (i = 0:I-1)

arg = arg + wx(i+1,j+1) * MOVx(i+1);

end

Dl = Dl + wy(j+1) * sigmoid (arg);

end

ODG = bmin + (bmax - bmin) * sigmoid (Dl);

function [amin, amax, wx, wxb, wy, wyb, bmin, bmax] = NNetPar (Version)

if (strcmp (Version, 'Basic'))

amin = ...

[393.916656, 361.965332, -24.045116, 1.110661, -0.206623, ...

0.074318, 1.113683, 0.950345, 0.029985, 0.000101, ...

0];

amax = ...

[921, 881.131226, 16.212030, 107.137772, 2.886017, ...

13.933351, 63.257874, 1145.018555, 14.819740, 1, …

1];

wx = ...

[ [ -0.502657, 0.436333, 1.219602 ];

[ 4.307481, 3.246017, 1.123743 ];

[ 4.984241, -2.211189, -0.192096 ];

[ 0.051056, -1.762424, 4.331315 ];

[ 2.321580, 1.789971, -0.754560 ];

[ -5.303901, -3.452257, -10.814982 ];

[ 2.730991, -6.111805, 1.519223 ];

[ 0.624950, -1.331523, -5.955151 ];

[ 3.102889, 0.871260, -5.922878 ];

[ -1.051468, -0.939882, -0.142913 ];

[ -1.804679, -0.503610, -0.620456 ] ];

wxb = ...

[ -2.518254, 0.654841, -2.207228 ];

wy = ...

[ -3.817048, 4.107138, 4.629582 ];

wyb = -0.307594;

bmin = -3.98;

bmax = 0.22;

else

amin = ...

[ 13.298751, 0.041073, -25.018791, 0.061560, 0.024523 ];

amax = ...

[ 2.166.5, 13.24326 13.46708, 10.226771, 14.224874 ];

wx = ...

[ [ 21.211773, -39.913052, -1.382553, -14.545348, -0.320899 ];

[ -8.981803, 19.956049, 0.935389, -1.686586, -3.238586 ];

[ 1.633830, -2.877505, -7.442935, 5.606502, -1.783120 ];

[ 6.103821, 19.587435, -0.240284, 1.088213, -0.511314 ];

[ 11.556344, 3.892028, 9.720441, -3.287205, -11.031250 ] ];

wxb = ...

[ 1.330890, 2.686103, 2.096598, -1.327851, 3.087055];

wy = ...

[ -4.696996, -3.289959, 7.004782, 6.651897, 4.009144 ];

wyb = -1.360308;

bmin = -3.98;

bmax = 0.22;

end

function [Nc, fc, fl, fu, dz] = PQCB (Version)

% параметры критической полосы пропускания

B = inline (7 * asinh (f / 650)');

Bl = inline ('650 * sinh (z / 7)');

fL = 80;

fU = 18000;

if (strcmp (Version, 'Basic'))

dz = 1/4;

elseif (strcmp (Version, 'Advanced'))

dz = 1/2;

else

error ('PQCB: Invalid version');

end

zL= B(fL);

zU = B(fU);

Nc = ceil((zU - zL) / dz);

zl = zL + (0:Nc-1) * dz;

zu = min (zL + (1:Nc) * dz, zU);

zc = 0.5 * (zl + zu);

fl = Bl (zl);

fc = Bl (zc);

fu = Bl (zu);

if (strcmp (Version, 'Basic'))

fl = [ 80.000,

103.445,

127.023,

150.762,

174.694, …

198.849,

223.257,

247.950,

272.959.

298.317, …

324.055,

350.207,

376.805,

403.884,

431.478, …

459.622,

488.353,

517.707,

547.721,

578.434, …

609.885,

642.114,

675.161,

709.071,

743.884, …

779.647,

816.404,

854.203,

893.091,

933.119, …

974.336,

1016.797,

1060.555,

1105.666,

1152.187, …

1200.178,

1249.700,

1300.816,

1353.592,

1408.094, …

1464.392,

1522.559,

1582.668,

1644.795,

1709.021, …

1775.427,

1844.098,

1915.121,

1988.587,

2064.590, …

2143.227,

2224.597,

2308.806,

2395.959.

2486.169, …

2579.551,

2676.223,

2776.309,

2879.937,

2987.238, …

3098.350,

3213.415,

3332.579,

3455.993,

3583.817, …

3716.212,

3853.817,

3995.399,

4142.547,

4294.979, …

4452.890,

4616.482,

4785.962,

4961.548,

5143.463, …

5331.939,

5527.217,

5729.545,

5939.183,

6156.396, …

6381.463,

6614.671,

6856.316,

7106.708,

7366 166, …

7635.020,

7913.614,

8202.302,

8501.454,

8811.450, …

9132.688,

9465.574,

9810.536,

10168.013,

10538.460, …

10922.351,

11320.175,

11732.438,

12159.670,

12602.412, …

13061.229,

13536.710,

14029.458,

14540.103,

15069.295, …

15617.710,

16186.049,

16775.035,

17385.420 ];

fc = [ 91.708,

115.216,

138.870,

162.702,

186.742, …

211.019,

235.566,

260.413,

285.593,

311.136, …

337.077,

363.448,

390.282,

417.614,

445.479, …

473.912,

502.950,

532.629,

562.988,

594.065, …

625.899,

658.533,

692.006,

726.362,

761.644, …

797.898,

835.170,

873.508,

912.959,

953.576, …

995.408,

1038.511,

1082.938,

1128.746,

1175.995, …

1224.744,

1275.055,

1326.992,

1380.623,

1436.014, …

1493.237,

1552.366,

1613.474,

1676.641,

1741.946, …

1809.474,

1879.310,

1951.543,

2026.266,

2103.573, …

2183.564,

2266.340,

2352.008,

2440.675,

2532.456, …

2627.468,

2725.832,

2827.672,

2933.120,

3042.309, …

3155.379,

3272.475,

3393.745,

3519.344,

3649.432, …

3784.176,

3923.748,

4068.324,

4218.090,

4373.237, …

4533.963,

4700.473,

4872.978,

5051.700,

5236.866, …

5428.712,

5627.484,

5833.434,

6046.825,

6267.931, …

6497.031,

6734.420,

6980.399,

7235.284,

7499.397, …

7773.077,

8056.673,

8350.547,

8655.072,

8970.639, …

9297.648,

9636.520,

9987.683,

10351.586,

10728.695, …

11119.490,

11524.470,

11944.149,

12379.066,

12829.775, …

13294.850,

13780.887,

14282.503,

14802.338

15341,057, …

15899.345,

16477.914,

17077.504,

17690.045 ];

fu = [ 103.445.

127.023,

150.762,

174.694

198,849, …

223.257,

247.950,

272.959,

298.317,

324.055, …

350.207,

376.805,

403.884,

431.478,

459.622, …

488.353,

517.707,

547.721,

578434

609.885, ...

642.114,

675.161,

709.071,

743.884,

779.647, …

816.404,

854.203,

893.091,

933.113,

974 336, …

1016.797,

1060.555,

1105.666,

1152.187,

1200.178, …

1249.700,

1300.816,

1353.592,

1408.094,

1464.392, …

1522.559,

1582.668,

1644.795,

1709.021,

1775.427, …

1844.098,

1915.121,

1988,587.

2064.590,

2143.227, …

2224.597,

2308.806,

2395.959,

2486.169,

2579.551, …

2676.223,

2776.309,

2879.937,

2987.238,

3098.350, …

3213.415,

3332.579,

3455.993,

3583.817,

3716.212, …

3853.348,

3995.399,

4142.547,

4294.979,

4452.890, …

4643.482,

4785.962,

4961.548,

5143.463,

5331.939, …

5527.217,

5729.545,

5939.183,

6156.396,

6381.463, …

6614.671,

6856.316,

7106.708,

7366.166,

7635.020, …

7913.614,

8202.302,

8501.454,

8811.450,

9132.688, …

9465.574,

9810.536,

10168.013,

10538.460,

10922.351, …

11320.175,

11732.438,

12159.670,

12602.412,

13061.229, …

13536.710,

14029.458,

14540,103,

15069.295,

15617.710, …

16186.049,

16775.035,

17385.420,

18000.000 ];

end

function Es = PQspreadCB (E. Ver)

% распространение возбуждений

% E и Es - энергии

persistent Bs Version

if (~ strcmp (Ver, Version))

Version = Ver;

Nc = length (E);

Bs = PQ_SpreadCB (ones(1,Nc), ones(1,Nc), Version);

end

Es = PQ_SpreadCB (E, Bs, Version);

%----------------------

function Es = PQ_SpreadCB (E, Bs, Ver);

persistent Nc dz fc aL aUC Version

e = 0.4;

if (~ strcmp (Ver, Version))

Version = Ver;

[Nc, fc, fl, fu, dz] = PQCB (Version);

end

% вычисление памяти

aUCEe = zeros (1, Nc);

Ene = zeros (1, Nc);

Es = zeros (1, Nc);

% вычисление термов, зависящих от энергии

aL = 10^(-2.7 *dz);

for (m = 0:Nc-1)

aUC = 10^((-2.4 - 23 / fc(m+1)) * dz);

aUCE = aUC * E(m+1)^(0.2 * dz);

glL = (1 -aL^ (m+1))/(1 - aL);

glU = (1 - aUCE^ (Nc-m)) / (1 - aUCE);

En = E(m+1) / (glL + glU - 1);

aUCEe(m+1) = aUCE^e;

Ene(m+1) = En^e;

end

% распространение вниз

Es(Nc-1+1) = Ene(Nc-1+1);

aLe = aL^e;

for (m = Nc-2:-1:0)

Es(m+1) = aLe * Es(m+1+1) + Ene(m+1);

end

% распространение вверх i > m

for (m = 0:Nc-2)

r = Ene(m+1);

a = aUCEe(m+1);

for (i = m+1:Nc-1)

r = r * a;

Es(i+1) = Es(i+1) + r;

end

end

for (i = 0:Nc-1)

Es(i+1) = (Es(i+1 ))^(1/е) / Bs(i+1);

end

function Eb = PQgroupCB (X2, Ver)

% группировка вектора энергии ДПФ и критической полосы пропускания

% Х2 - вектор значений, возведенных в степень 2

% Eb - вектор возбуждений

persistent Nc kl ku Ul Uu Version

Emin = 1e-12;

if (~ strcmp (Ver, Version))

Version = Ver;

NF = 2048;

Fs = 48000;

[Nc, kl, ku, Ul, Uu] = PQ_CBMapping (NF, Fs, Version);

end

% выделение памяти

Eb = zeros (1, Nc);

% вычисление возбуждений в каждой полосе

for (i = 0:Nc-1)

Ea = UI(i+1) * X2(kl(i+1)+1);

for (k = (kl(i+1)+1):(ku(i+1)-1))

Ea = Ea + X2(k+1);

end

Ea = Ea + Uu(i+1) * X2(ku(i+1)+1);

Eb(i+1) = max(Ea, Emin);

end

%---------------------------------------

function [Nc, kl, ku, Ul, Uu] = PQ_CBMapping (NF, Fs, Version)

[Nc, fc, fl, fu] = PQCB (Version);

df=Fs/NF;

for (i = 0:Nc-1)

fli = fl(i+1);

fui = fu(i+1);

for (k = 0:NF/2)

if ((k+0.5)*df > fli)

kl(i+1) = k;

Ul(i+1) = (min(fui, (k+0.5)*df)...

- max(fli, (k-0.5)*df)) / df;

break;

end

end

for (k=NF/2:-1:0)

if ((k-0.5)*df < fui)

ku(i+1) = k;

if(kl(i+1) == ku(i+1))

Uu(i+1) = 0;

else

Uu(i+1) = (min(fui, (k+0.5)*df)...

- max(fli, (k-0.5)*df)) / df;

end

break;

end

end

end

function [MOVI, Fmem] = PQeval (xR, xT, Fmem)

% PEAQ - обработка единичного фрейма

NF = 2048;

Version ='Basic';

% оконное ДПФ

X2(1,:) = PQDFTFrame (xR);

X2(2,:) = PQDFTFrame (xT);

[EbN, Es] = PQ_excitCB (X2);

[Ehs(1,:), Fmem.TDS.Ef(1,:)] = PQ_timeSpread (Es(1,:), Fmem.TDS.Ef(1,:));

[Ehs(2,:), Fmem.TDS.Ef(2,:)] = PQ_timeSpread (Es(2,:), Fmem.TDS.Ef(2,:));

% адаптация паттернов возбуждения

[ЕР, Fmem.Adap] = PQadapt (Ehs, Fmem.Adap, Version, 'FFT');

% паттерны модуляции

[M, ERavg, Fmem.Env] = PQmodPatt (Es, Fmem.Env);

% громкость

MOVI.Loud.NRef = PQIoud (Ehs(1,:), Version, 'FFT');

MOVI.Loud.NTest = PQIoud (Ehs(2,:), Version, 'FFT');

% разница модуляций

MOVI.MDiff = PQmovModDiffB (M, ERavg);

% громкость шума

MOVI.NLoud.NL = PQmovNLoudB (M, EP);

% полоса пропускания

MOVI.BW = PQmovBW (X2);

% отношений шума к маскированию

MOVI.NMR = PQmovNMRB (EbN, Ehs(1,:));

% вероятность обнаружения

MOVI.PD = PQmovPD (Ehs);

% ошибка гармонической структуры

MOVI.EHS.EHS = PQmovEHS (xR, xT, X2);

%--------------------

function [EbN, Es] = PQ_excitCB (X2)

persistent W2 EIN

NF = 2048;

Version ='Basic';

if (isempty (W2))

Fs = 48000;

f = linspace (0, Fs/2, NF/2+1);

W2 = PQWOME (f);

[Nc, fc] = PQCB (Version);

EIN = PQIntNoise (fc);

end

% выделение памяти

XwN2 = zeros (1, NF/2+1);

% фильтрация на основе модели внешнего и среднего уха

Xw2(1,:) = W2.* X2(1,1:NF/2+1);

Xw2(2,:) = W2.* X2(2,1:NF/2+1);

for (k = 0:NF/2)

XwN2(k+1) = (Xw2(1,k+1) - 2 * sqrt (Xw2(1,k+1) * Xw2(2,k+1))...

+ Xw2(2,k+1));

end

Eb(1,:) = PQgroupCB (Xw2(1,:), Version);

Eb(2,:) = PQgroupCB (Xw2(2,:), Version);

EbN = PQgroupCB (XwN2, Version);

E(1,:) = Eb(1,:) + EIN;

E(2,:) = Eb(2,:) + EIN;

Es(1,:) = PQspreadCB (E(1,:), Version);

Es(2,:) = PQspreadCB (E(2,:), Version);

%--------------------

function [Ehs, Ef] = PQ_timeSpread (Es, Ef)

persistent Nc a b

if (isempty (Nc))

[Nc, fc] = PQCB ('Basic');

Fs = 48000;

NF = 2048;

Nadv = NF / 2;

Fss = Fs / Nadv;

t100 = 0.030;

tmin = 0.008;

[a, b] = PQtConst (t100, tmin, fc, Fss);

end

Ehs = zeros (1, Nc);

for (m = 0:Nc-1)

Ef(m+1) = a(m+1) * Ef(m+1) + b(m+1) * Es(m+1);

Ehs(m+1) = max(Ef(m+1), Es(m+1));

end

function X2 = PQDFTFrame (x)

persistent hw

NF = 2048;

if (isempty (hw))

Amax = 32768;

fc= 1019.5;

Fs = 48000;

Lp = 92;

GL = PQ_GL (NF, Amax, fc/Fs, Lp);

hw = GL * PQHannWin (NF);

end

xw = hw.* x;

X = PQRFFT (xw, NF, 1);

X2 = PQRFFTMSq (X, NF);

%----------------------------------------

function GL = PQ_GL (NF, Amax, fcN, Lp)

W = NF - 1;

gp = PQ_gp (fcN, NF, W);

GL = 10^ (Lp / 20) / (gp * Amax/4 * W);

%----------

function gp = PQ_gp (fcN, NF, W)

df = 1 / NF;

k = floor (fcN / df);

dfN = min ((k+1) * df - fcN, fcN - k * df);

dfW = dfN * W;

gp = sin(pi * dfW) / (pi * dfW * (1 - dfW^2));

function Lim = PQdataBoundary (WAV, Nchan, StartS, Ns)

PQ_L = 5;

Amax = 32768;

NBUFF = 2048;

PQ_ATHR = 200 * (Amax / 32768);

Lim(1) = -1;

is = StartS;

EndS = StartS + Ns -1;

while (is <= EndS)

Nf = min (EndS - is + 1, NBUFF);

x = PQgetData (WAV, is, Nf);

for (k = 0:Nchan-1)

Lim(1) = max (Lim(1), PQ_DataStart (x(k+1,:), Nf, PQ_L, PQ_ATHR));

end

if (Lim(1) >= 0)

Lim(1) = Lim(1) + is;

break

end

is = is + NBUFF - (PQ_L-1);

end

Lim(2) = -1;

is = StartS;

while (is <= EndS)

Nf = min (EndS - is + 1, NBUFF);

ie = is + Nf - 1;

js = EndS - (ie - StartS + 1) + 1;

x = PQgetData (WAV, js, Nf);

for (k = 0:Nchan-1)

Lim(2) = max (Lim(2), PQ_DataEnd (x(k+1,:), Nf, PQ_L, PQ_ATHR));

end

if (Lim(2) >= 0)

Lim(2) = Lim(2) + js;

break

end

is = is + NBUFF-(PQ_L-1);

end

if (~ ((Lim(1) >= 0 & Lim(2) >= 0) | (Lim(1) < 0 & Lim(2) < 0)))

error ('>>> PQdataBoundary: limits have difference signs');

end

if(~(Lim(1) <= Lim(2)))

error ('>>> PQdataBoundary: Lim(1) > Lim(2)');

end

if (Lim(1) < 0)

Lim(1) = 0;

Lim(2) = 0;

end

%----------

function ib = PQ_DataStart (x, N, L, Thr)

ib = -1;

s = 0;

M = min (N, L);

for (i = 0:M-1)

s = s + abs (x(i+1));

end

if (s > Thr)

ib = 0;

return

end

for (i = 1:N-L)

s = s + (abs (x(i+L-1 + 1)) - abs (x(i-1 + 1)));

if (s > Thr)

ib = i;

return

end

end

%----------

function ie = PQ_DataEnd (x, N, L, Thr)

ie = -1;

s = 0;

M = min (N, L);

for (i = N-M:N-1)

s = s + abs (x(i+1));

end

if (s > Thr)

ie = N-1;

return

end

for (i = N-2:-1:L-1)

s = s + (abs (x(i-L+1+1)) - abs (x(i+1+1)));

if (s > Thr)

ie = i;

return

end

end

function x = PQgetData (WAV, i, N)

persistent Buff

iB = WAV.iB + 1;

if (N == 0)

Buff(iB).N = 20 * 1024; % Fixed size

Buff(iB).x = PQ_ReadWAV (WAV, i, Buff(iB).N);

Buff(iB).i = i;

end

if (N > Buff(iB).N)

error ('>>> PQgetData: Request exceeds buffer size');

end

is = i-Buff(iB).i;

if (is < 0 | is + N-1 > Buff(iB).N - 1)

Buff(iB).x = PQ_ReadWAV (WAV, i, Buff(iB).N);

Buff(iB).i = i;

end

Nchan = WAV.Nchan;

is = i - Buff(iB).i;

x = Buff(iB).x(1:Nchan,is+1:is+N-1 + 1);

% ------

function x = PQ_ReadWAV (WAV, i, N)

Amax = 32768;

Nchan = WAV.Nchan;

х = zeros (Nchan, N);

Nz = 0;

if (i < 0)

Nz = min (-i, N);

i = i + Nz;

end

Ns = min (N - Nz, WAV.Nframe - i);

if (i >= 0 & Ns > 0)

x(1:Nchan,Nz+1:Nz+Ns-1 + 1) = Amax * (wavread (WAV.Fname, [i+1 i+Ns-1+1]))';

end

function hw = PQHannWin (NF)

hw = zeros (1, NF);

for(n = 0:NF-1)

hw(n+1) = 0.5 * (1 - cos(2 * pi * n / (NF-1)));

end

function Fmem = PQinitFMem (Nc, PCinit)

Fmem.TDS.Ef(1:2,1:Nc) = 0;

Fmem.Adap.P(1:2,1:Nc) = 0;

Fmem.Adap.Rn(1:Nc) = 0;

Fmem.Adap.Rd(1:Nc) = 0;

Fmem.Adap.PC(1:2,1:Nc) = PCinit;

Fmem.Env.Ese(1:2,1:Nc) = 0;

Fmem.Env.DE(1:2,1:Nc) = 0;

Fmem.Env.Eavg(1:2,1:Nc) = 0;

function EIN = PQIntNoise (f)

N = length (f);

for (m = 0:N-1)

INdB = 1.456 * (f(m+1)/ 1000)^(-0.8);

EIN(m+1) = 10^(INdB/10);

End

function X = PQRFFT (x, N, ifn)

if (ifn > 0)

X = fft (x, N);

XR = real(X(0+1 : N/2+1));

XI = imag(X(1+1:N/2-1+1));

X = [XR XI];

else

xR = [x(0+1 : N/2+1)];

xl = [0x(N/2+1+1:N-1+1) 0];

x = complex ([xR xR(N/2-1+1:-1:1+1)], [xl - xl(N/2-1+1:-1:1+1)]);

X = real (ifft (x, N));

end

function X2 = PQRFFTMSq (X, N)

X2 = zeros (1, N/2+1);

Х2(0+1) = Х(0+1)^2;

for (k = 1 : N/2-1)

X2(k+1) = X(k+1)^2 + X(N/2+k+1)^2;

end

X2(N/2+1) = X(N/2+1)^2;

function [a, b] = PQtConst (t100, tmin, f, Fs)

N = length (f);

for (m = 0:N-1)

t = tmin + (100 / f(m+1)) * (t100 - tmin);

a(m+1) = exp(-1 / (Fs * t));

b(m+1) = (1 - a(m+1));

end

function W2 = PQWOME (f)

N = length (f);

for (k = 0:N-1)

fkHz = f(k+1) / 1000;

AdB = -2.184 * fkHz^(-0.8) + 6.5 * exp(-0.6 * (fkHz - 3.3)^2)...

-0.001 * fkHz^(3.6);

W2(k+1) = 10^(AdB / 10);

end

function WAV = PQwavFilePar (File)

persistent iB

if (isempty (iB))

iB = 0;

else

iB = mod (iB + 1, 2);

end

[size WAV.Fs Nbit] = wavread (File, 'size');

WAV.Fname = File;

WAV.Nframe = size(1);

WAV.Nchan = size(2);

WAV.iB = iB;

PQgetData (WAV, 0, 0);

function MOV = PQavgMOVB (MOVC, Nchan, Nwup)

Fs = 48000;

NF = 2048;

Nadv=NF / 2;

Fss = Fs / Nadv;

tdel = 0.5;

tex = 0.050;

[MOV(0+1), MOV(1+1)] = PQ_avgBW(MOVC.BW);

% Total NMRB, RelDistFramesB

[MOV(2+1), MOV(10+1)] = PQ_avgNMRB (MOVC.NMR);

% WinModDiff1B, AvgModDiff1B, AvgModDiff2B

N500ms = ceil (tdel * Fss);

Ndel = max (0, N500ms - Nwup);

[MOV(3+1), MOV(6+1), MOV(7+1)] = PQ_avgModDiffB (Ndel, MOVC.MDiff);

% RmsNoiseLoudB

N50ms = ceil (tex * Fss);

Nloud = PQIoudTest (MOVC.Loud);

Ndel = max (Nloud + N50ms, Ndel);

MOV(8+1) = PQ_avgNLoudB (Ndel, MOVC.NLoud);

%ADBB, MFPDB

[MOV(4+1), MOV(9+1)] = PQ_avgPD (MOVC.PD);

% EHSB

MOV(5+1) = PQ_avgEHS (MOVC.EHS);

%----------------------------------------

function EHSB = PQ_avgEHS (EHS)

[Nchan, Np] = size (EHS.EHS);

s = 0;

for (j = 0:Nchan-1)

s = s + PQ_LinPosAvg (EHS.EHS(j+1,:));

end

EHSB = 1000 * s / Nchan;

%----------------------------------------

function [ADBB, MFPDB] = PQ_avgPD (PD)

global PQopt

c0 = 0.9;

if (isempty (PQopt))

c1 = 1;

else

c1 = PQopt. PDfactor;

end

N = length (PD.Pc);

Phc = 0;

Pcmax = 0;

Qsum = 0;

nd = 0;

for(i = 0:N-1)

Phc = c0 * Phc + (1 - c0) * PD.Pc(i+1);

Pcmax = max (Pcmax * c1, Phc);

if (PD.Pc(i+1) > 0.5)

nd = nd + 1;

Qsum = Qsum + PD.Qc(i+1);

end

end

if (nd == 0)

ADBB = 0;

elseif (Qsum > 0)

ADBB = Iog10 (Qsum / nd);

else

ADBB = -0.5;

end

MFPDB = Pcmax;

%----------------------------------------

function [TotalNMRB, RelDistFramesB] = PQ_avgNMRB (NMR)

[Nchan, Np] = size (NMR.NMRavg);

Thr= 10^(1.5 / 10);

s = 0;

for (j = 0:Nchan-1)

s = s + 10 * Iog10 (PQ_LinAvg (NMR.NMRavg(j+1,:)));

end

TotalNMRB = s / Nchan;

s = 0;

for (j = 0:Nchan-1)

s = s + PQ_FractThr (Thr, NMR.NMRmax(j+1,:));

end

RelDistFramesB = s / Nchan;

%----------------------------------------

function [BandwidthRefB, BandwidthTestB] = PQ_avgBW (BW)

[Nchan, Np] = size (BW.BWRef);

sR = 0;

sT = 0;

for (j = 0:Nchan-1)

sR = sR + PQ_LinPosAvg (BW.BWRef(j+1,:));

sT = sT + PQ_LinPosAvg (BW.BWTest(j+1,:));

end

BandwidthRefB = sR / Nchan;

BandwidthTestB = sT / Nchan;

%----------------------------------------

function [WinModDiff1B, AvgModDiff1B, AvgModDiff2B] = PQ_avgModDiffB (Ndel, MDiff)

NF = 2048;

Nadv=NF / 2;

Fs = 48000;

Fss = Fs / Nadv;

tavg = 0.1;

[Nchan, Np] = size (MDiff.Mt1B);

L = floor (tavg * Fss);

s = 0;

for (j = 0:Nchan-1)

s = s + PQ_WinAvg (L, MDiff.Mt1B(j+1,Ndel+1:Np-1+1));

end

WinModDiff1B = s / Nchan;

s = 0;

for (j = 0:Nchan-1)

s = s + PQ_WtAvg (MDiff.Mt1B(j+1,Ndel+1:Np-1+1), MDiff.Wt(j+1,Ndel+1:Np-1+1));

end

AvgModDiff1В = s / Nchan;

s = 0;

for (j = 0:Nchan-1)

s = s + PQ_WtAvg (MDiff.Mt2B(j+1,Ndel+1:Np-1+1), MDiff.Wt(j+1,Ndel+1:Np-1+1));

end

AvgModDiff2B = s / Nchan;

%-----------------------------------

function RmsNoiseLoudB = PQ_avgNLoudB (Ndel, NLoud)

[Nchan, Np] = size (NLoud.NL);

s = 0;

for (j = 0:Nchan-1)

s = s + PQ_RMSAvg (NLoud.NL(j+1,Ndel+1:Np-1+1));

end

RmsNoiseLoudB = s / Nchan;

%-----------------------------------

function s = PQ_LinPosAvg (x)

N = length(x);

Nv = 0;

s = 0;

for (i = 0:N-1)

if (x(i+1) >= 0)

s = s + x(i+1);

Nv= Nv + 1;

end

end

if (Nv > 0)

s = s / Nv;

end

%----------

function Fd = PQ_FractThr (Thr, x)

N = length (x);

Nv = 0;

for (i = 0:N-1)

if (x(i+1) > Thr)

Nv = Nv + 1;

end

end

if (N > 0)

Fd = Nv / N;

else

Fd = 0;

end

%----------

function s = PQ_WinAvg (L, x)

N = length (x);

s = 0;

for (i = L-1:N-1)

t = 0;

for (m = 0:L-1)

t = t + sqrt (x(i-m+1));

end

s = s + (t / L)^4;

end

if (N >= L)

s = sqrt (s / (N - L + 1));

end

%----------

function s = PQ_WtAvg (x, W)

N = length (x);

s = 0;

sW = 0;

for (i = 0:N-1)

s = s + W(i+1) * x(i+1);

sW=sW + W(i+1);

end

if (N > 0)

s = s / sW;

end

%----------

function LinAvg = PQ_LinAvg (x)

N = length (x);

s = 0;

for (i = 0:N-1)

s = s + x(i+1);

end

LinAvg = s / N;

%----------

function RMSAvg = PQ_RMSAvg (x)

N = length (x);

s = 0;

for (i = 0:N-1)

s = s + x(i+1)^2;

end

if (N > 0)

RMSAvg = sqrt(s / N);

else

RMSAvg = 0;

end

function PQframeMOV (i, MOVI)

global MOVC

[Nchan,Nc] = size (MOVC.MDiff.Mt1B);

for(j = 1:Nchan)

% Modulation differences

MOVC.MDiff.Mt1B(j,i+1) = MOVI(j).MDiff.Mt1B;

MOVC.MDiff.Mt2B(j,i+1) = MOVI(j).MDiff.Mt2B;

MOVC.MDiff.Wt(j,i+1) = MOVI(j).MDiff.Wt;

% Noise loudness

MOVC.NLoud.NL(j,i+1) = MOVI(j).NLoud.NL;

% Total loudness

MOVC.Loud.NRef(j,i+1) = MOVI(j).Loud.NRef;

MOVC.Loud.NTest(j,i+1) = MOVI(j).Loud.NTest;

% Bandwidth

MOVC.BW.BWRef(j,i+1) = MOVI(j).BW.BWRef;

MOVC.BW.BWTest(j,i+1) = MOVI(j).BW.BWTest;

% Noise-to-mask ratio

MOVC.NMR.NMRavg(j,i+1) = MOVI(j).NMR.NMRavg;

MOVC.NMR.NMRmax(j,i+1) = MOVI(j).NMR.NMRmax;

% Error harmonic structure

MOVC.EHS.EHS(j,i+1) = MOVI(j).EHS.EHS;

end

% Probability of detection (collapse frequency bands)

[MOVC.PD.Pc(i+1), MOVC.PD.Qc(i+1)] = PQ_ChanPD (MOVI);

%----------------------------------------

function [Pc, Qc] = PQ_ChanPD (MOVI)

Nc = length (MOVI(1).PD.p);

Nchan = length (MOVI);

Pr = 1;

Qc = 0;

if (Nchan > 1)

for (m = 0:Nc-1)

pbin = max (MOVI(1).PD.p(m+1), MOVI(2).PD.p(m+1));

qbin = max (MOVI(1).PD.q(m+1), MOVI(2).PD.q(m+1));

Pr = Pr * (1 - pbin);

Qc = Qc + qbin;

end

else

for (m = 0:Nc-1)

Pr = Pr * (1 - MOVI.PD.p(m+1));

Qc = Qc + MOVI.PD.q(m+1);

end

end

Pc = 1 - Pr;

function Ndel = PQIoudTest (Loud)

[Nchan, Np] = size (Loud.NRef);

Thr = 0.1;

Ndel = Np;

for (j = 0:Nchan-1)

Ndel = min (Ndel, PQ_LThresh (Thr, Loud.NRef(j+1,:), Loud.NTest(j+1,:)));

end

%----------

function it = PQ_LThresh (Thr, NRef, NTest)

Np = length (NRef);

it = Np;

for (i = 0:Np-1)

if (NRef(i+1) > Thr & NTest(i+1) > Thr)

it = i;

break;

end

end

function BW = PQmovBW (X2)

persistent kx kl FR FT N

if (isempty (kx))

NF = 2048;

Fs = 48000;

fx = 21586;

kx = round (fx / Fs * NF); % 921

fl = 8109;

kl = round (fl / Fs * NF); % 346

FRdB = 10;

FR = 10^(FRdB / 10);

FTdB = 5;

FT=10^(FTdB / 10);

N = NF / 2; % Limit from pseudo-code

end

Xth = X2(2,kx+1);

for (k = kx+1:N-1)

Xth = max(Xth, X2(2,k+1));

end

BW.BWRef = -1;

XthR = FR * Xth;

for (k = kx-1:-1:kl+1)

if (X2(1,k+1) >= XthR)

BW.BWRef = k + 1;

break;

end

end

BW.BWTest = -1;

XthT = FT * Xth;

for (k = BW.BWRef-1:-1:0)

if(X2(2,k+1) >= XthT)

BW.BWTest = k + 1;

break;

end

end

function MDiff - PQmovModDiffB (M, ERavg)

persistent Nc Ete

if (isempty (Nc))

e = 0,3;

[Nc, fc] = PQCB ('Basic');

Et = PQIntNoise (fc);

for (m = 0:Nc-1)

Ete(m+1) = E(m+1)^e;

end

end

negWt2B = 0.1;

offset1B = 1.0;

offset2B = 0.01;

levWt = 100;

s1B = 0;

s2B = 0;

Wt = 0;

for (m = 0:Nc-1)

if (M(1,m+1) > M(2,m+1))

num1B = M(1,m+1) - M(2,m+1);

num2B = negWt2B * num1B;

else

num1B = M(2,m+1) - M(1,m+1);

num2B = num1B;

end

MD1В = num1В / (offset1В + M(1,m+1));

MD2B = num2B / (offset2B + M(1,m+1));

s1B = s1B + MD1B;

s2B = s2B + MD2B;

Wt = Wt + ERavg(m+1) / (ERavg(m+1) + levWt * Ete(m+1));

end

MDiff.Mt1B = (100/Nc) * s1B;

MDiff.Mt2B = (100/Nc) * s2B;

MDiff.Wt = Wt;

function NL = PQmovNLoudB (M, EP)

persistent Nc Et

if (isempty (Nc))

[Nc, fc] = PQCB ('Basic');

Et = PQIntNoise (fc);

end

alpha = 1.5;

TF0 = 0.15;

S0 = 0.5;

NLmin = 0;

e = 0.23;

s = 0;

for (m = 0:Nc-1)

sref =TF0 * M(1,m+1) + S0;

stest = TF0 * M(2,m+1) + S0;

beta = exp (-alpha * (EP(2,m+1) - EP(1,m+1)) / EP(1,m+1));

a = max (stest * EP(2,m+1) - serf * EP(1,m+1), 0);

b = Et(m+1) + sref * EP(1,m+1) * beta;

s = s + (Et(m+1) / stest)e * ((1 + a / b)е - 1);

end

NL = (24 / Nc) * s;

if (NL < NLmin)

NL = 0;

end

function NMR = PQmovNMRB (EbN, Ehs)

persistent Nc gm

if (isempty (Nc))

[Nc, fc, fl, fu, dz] = PQCB ('Basic');

gm = PQ_MaskOffset (dz, Nc);

end

NMR.NMRmax = 0;

s = 0;

for (m = 0:Nc-1)

NMRm = EbN(m+1) / (gm(m+1) * Ehs(m+1));

s = s + NMRm;

if (NMRm > NMR.NMRmax)

NMR.NMRmax = NMRm;

end

end

NMR.NMRavg = s/Nc;

%----------------------------------------

function gm = PQ_MaskOffset (dz, Nc)

for (m = 0:Nc-1)

if (m <= 12/dz)

mdB = 3;

else

mdB = 0.25 * m *dz;

end

gm(m+1) = 10^(-mdB / 10);

end

function PD = PQmovPD (Ehs)

Nc = length (Ehs);

PD.p = zeros (1, Nc);

PD.q = zeros (1, Nc);

persistent с g d1 d2 bP bM

if (isempty (c))

с = [-0.198719 0.0550197 -0.00102438 5.05622e-6 9.01033e-11];

d1 = 5.95072;

d2 = 6.39468;

g = 1.71332;

bP = 4;

bM=6;

end

for(m = 0:Nc-1)

EdBR = 10 * Iog10 (Ehs(1,m+1));

EdBT = 10 * Iog10 (Ehs(2,m+1));

edB = EdBR - EdBT;

if (edB > 0)

L = 0.3 * EdBR + 0.7 * EdBT;

b = bP;

else

L = EdBT;

b = bM;

end

if (L > 0)

s = d1 * (d2 / L)^g...

+ c(1) + L * (c(2) + L * (c(3) + L * (c(4) + L * c(5))));

else

s = 1e30;

end

PD.p(m+1) = 1 - 0.5^((edB / s)^b);

PD.q(m+1) = abs (fix(edB)) / s;

end

function PQprtMOV (MOV, ODG)

N = length (MOV);

PQ_NMOV_B = 11;

PQ_NMOV_A = 5;

fprintf ('Model Output Variables:\n');

if (N == PQ_NMOV_B)

fprintf (' BandwidthRefB: %g\n', MOV(1));

fprintf (' BandwidthTestB: %g\n', MOV(2));

fprintf ('

Total NMRB: %g\n', MOV(3));

fprintf ('

WinModDiff1B: %g\n', MOV(4));

fprintf ('

ADBB: %g\n', MOV(5));

fprintf ('

EHSB: %g\n', MOV(6));

fprintf ('

AvgModDiff1B: %g\n', MOV(7));

fprintf ('

AvgModDiff2B: %g\n', MOV(8));

fprintf ('

RmsNoiseLoudB: %g\n', MOV(9));

fprintf ('

MFPDB: %g\n', MOV(10));

fprintf ('

RelDistFramesB: %g\n', MOV(11));

elseif (N == NMOV_A)

fprintf ('

RmsModDiffA: %g\n', MOV(1));

fprintf ('

RmsNoiseLoudAsymA: %g\n', MOV(2));

fprintf ('

Segmental NMRB: %g\n', MOV(3));

fprintf ('

EHSB: %g\n', MOV(4));

fprintf ('

AvgLinDistA: %g\n', MOV(5));

else

error ('Invalid number of MOVs');

end

fprintf ('Objective Difference Grade: %.3f\n', ODG);

return;

function PQprtMOVCi (Nchan, i, MOVC)

fprintf ('Frame: %d\n', i);

if (Nchan == 1)

fprintf ('

Ntot : %g%g\n', ...

MOVC.Loud.NRef(1,i+1), MOVC.Loud.NTest(1,i+1));

fprintf ('

ModDiff: %g %g %g\n', ...

MOVC.MDiff.Mt1 B(1,i+1), MOVC.MDiff.Mt2B(1,i+1), MOVC.MDiff.Wt(1,i+1));

fprintf ('

NL : %g\n', MOVC.NLoud.NL(1,i+1));

fprintf ('

BW : %g %g\n', ...

MOVC.BW.BWRef(1,i+1), MOVC.BW.BWTest(1,i+1));

fprintf ('

NMR : %g %g\n', ...

MOVC.NMR.NMRavg(1,i+1), MOVC.NMR.NMRmax(1,i+1));

fprintf ('

PD : %g %g\n', MOVC.PD.Pc(i+1), MOVC.PD.Qc(i+1));

fprintf ('

EHS : %g\n', 1000 * MOVC.EHS.EHS(1,i+1));

else

fprintf ('

Ntot : %g %g // %g %g\n', ...

MOVC.Loud.NRef(1,i+1), MOVC.Loud.NTest(1,i+1), ...

MOVC.Loud.NRef(2,i+1), MOVC.Loud.NTest(2,i+1));

fprintf ('

ModDiff: %g %g %g // %g %g %g\n', ...

MOVC.MDiff.Mt1B(1,i+1), MOVC.MDiff.Mt2B(1,i+1), MOVC.MDiff.Wt(1,i+1), ...

MOVC.MDiff.Mt1B(2,i+1), MOVC.MDiff.Mt2B(2,i+1), MOVC.MDiff.Wt(2,i+1));

fprintf ('

NL : %g//%g\n', ...

MOVC.NLoud.NL(1,i+1), ...

MOVC.NLoud.NL(2,i+1));

fprintf ('

BW : %g %g // %g %g\n', ...

MOVC.BW.BWRef(1,i+1), MOVC.BW.BWTest(1,i+1), ...

MOVC.BW.BWRef(2,i+1), MOVC.BW.BWTest(2,i+1));

fprintf ('

NMR : %g %g // %g %g\n', ...

MOVC.NMR.NMRavg(1,i+1), MOVC.NMR.NMRmax(1,i+1), ...

MOVC.NMR.NMRavg(2,i+1), MOVC.NMR.NMRmax(2,i+1));

fprintf ('

PD : %g%g\n', MOVC.PD.Pc(i+1), MOVC.PD.Qc(i+1));

fprintf ('

EHS : %g//%g\n', ...

1000 * MOVC.EHS.EHS(1,i+1), ...

1000 * MOVC.EHS.EHS(2,i+1));

end

function EHS = PQmovEHS (xR, xT, X2)

persistent NF Nadv NL M Hw

if (isempty (NL))

NF = 2048;

Nadv = NF/2;

Fs = 48000;

Fmax = 9000;

NL = 2^(PQ_log2(NF * Fmax / Fs));

M = NL;

Hw = (1 / M) * sqrt(8 / 3) * PQHannWin (M);

end

EnThr = 8000;

kmax = NL+ M -1;

EnRef = xR(Nadv+1:NF-1 + 1) * xR(Nadv+1 :NF-1+1)';

EnTest = xT(Nadv+1:NF-1+1) * xT(Nadv+1:NF-1+1)';

if (EnRef < EnThr & EnTest < EnThr)

EHS = -1;

return;

end

D = zeros (1, kmax);

for (k = 0:kmax-1)

D(k+1) = log (X2(2,k+1) / X2(1,k+1));

end

C = PQ_Corr(D, NL, M);

Cn = PQ_NCorr (C, D, NL, M);

Cnm = (1 / NL) * sum (Cn(1:NL));

Cw = Hw. * (Cn - Cnm);

% DFT

cp = PQRFFT (Cw, NL, 1);

c2 = PQRFFTMSq (cp, NL);

EHS = PQ_FindPeak (c2, NL/2+1);

%----------------------------------------

function log2 = PQ_log2 (a)

log2 = 0;

m = 1;

while (m < a)

log2 = log2 + 1;

m = 2 * m;

end

log2 = log2 - 1;

%----------

function С = PQ_Corr (D, NL, M)

NFFT = 2 * NL;

D0 = [D(1:M)zeros(1,NFFT-M)];

D1 = [D(1:M+NL-1) zeros(1 ,NFFT-(M+NL-1))];

d0 = PQRFFT (DO, NFFT, 1);

d1 = PQRFFT (D1, NFFT, 1);

dx(0+1) = d0(0+1) * d1(0+1);

for (n = 1:NFFT/2-1)

m = NFFT/2 + n;

dx(n+1) = d0(n+1) * d1(n+1) + d0(m+1) * d1(m+1);

dx(m+1) = d0(n+1) * d1(m+1) - d0(m+1) * d1(n+1);

end

dx(NFFT/2+1) = d0(NFFT/2+1) * d1(NFFT/2+1);

% Inverse DFT

Cx = PQRFFT (dx, NFFT, -1);

C = Cx(1:NL);

%----------

function Cn = PQ_NCorr (C, D, NL, M)

Cn = zeros (1, NL);

s0 = C(0+1);

sj = s0;

Cn(0+1) = 1;

for (i = 1:NL-1)

sj = sj + (D(i+M-1+1)^2 - D(i-1+1)^2);

d = s0 * sj;

if (d <= 0)

Cn(i+1) = 1;

else

Cn(i+1) = C(i+1) / sqrt (d);

end

end

%----------

function EHS = PQ_FindPeak (c2, N)

cprev = c2(0+1);

cmax = 0;

for (n = 1:N-1)

if (c2(n+1) > cprev) % Rising from a valley

if (c2(n+1) > cmax)

cmax = c2(n+1);

end

end

end

EHS = cmax;

function [EP, Fmem] = PQadapt (Ehs, Fmem, Ver, Mod)

persistent a b Nc M1 M2 Version Model

if (~strcmp (Ver, Version) | ~strcmp (Mod, Model))

Version = Ver;

Model = Mod;

if (strcmp (Model, 'FFT'))

[Nc, fc] = PQCB (Version);

NF = 2048;

Nadv = NF / 2;

else

[Nc, fc] = PQFB;

Nadv = 192;

end

Version = Ver;

Model = Mod;

Fs = 48000;

Fss = Fs / Nadv;

t100 = 0.050;

tmin = 0.008;

[a b] = PQtConst (t100, tmin, fc, Fss);

[M1, M2]= PQ_M1M2 (Version, Model);

end

EP = zeros (2, Nc);

R = zeros (2, Nc);

sn = 0;

sd = 0;

for (m = 0:Nc-1)

Fmem.P(1,m+1) = a(m+1) * Fmem.P(1,m+1) + b(m+1) * Ehs(1,m+1);

Fmem.P(2,m+1) = a(m+1) * Fmem.P(2,m+1) + b(m+1) * Ehs(2,m+1);

sn = sn + sqrt (Fmem.P(2,m+1) * Fmem.P(1,m+1));

sd = sd + Fmem.P(2,m+1);

end

CL = (sn/sd)^2;

for (m = 0:Nc-1)

if (CL > 1)

EP(1,m+1) = Ehs(1,m+1) / CL;

EP(2,m+1) = Ehs(2,m+1);

else

EP(1,m+1) = Ehs(1,m+1);

EP(2,m+1) = Ehs(2,m+1) * CL;

end

Fmem.Rn(m+1) = a(m+1) * Fmem.Rn(m+1) + EP(2,m+1) * EP(1,m+1);

Fmem.Rd(m+1) = a(m+1) * Fmem.Rd(m+1) + EP(1,m+1) * EP(1,m+1);

if (Fmem.Rd(m+1) <= 0 | Fmem.Rn(m+1) <= 0)

error ('>>> PQadap: Rd or Rn is zero');

end

if (Fmem.Rn(m+1) >= Fmem.Rd(m+1))

R(1,m+1) = 1;

R(2,m+1) = Fmem.Rd(m+1) / Fmem.Rn(m+1);

else

R(1,m+1) = Fmem.Rn(m+1) / Fmem.Rd(m+1);

R(2,m+1) = 1;

end

end

for (m = 0:Nc-1)

iL= max(m - M1, 0);

iU = min (m + M2, Nc-1);

s1 = 0;

s2 = 0;

for (i = iL:iU)

s1 =s1 + R(1,i+1);

s2 = s2+ R(2,i+1);

end

Fmem.PC(1,m+1) = a(m+1) * Fmem.PC(1,m+1) + b(m+1) * s1 / (iU-iL+1);

Fmem.PC(2,m+1) = a(m+1) * Fmem.PC(2,m+1) + b(m+1) * s2 / (iU-iL+1);

EP(1,m+1) = EP(1,m+1) * Fmem.PC(1,m+1);

EP(2,m+1) = EP(2,m+1) * Fmem.PC(2,m+1);

end

%------------------------------

function [M1, M2] = PQ_M1M2 (Version, Model)

if (strcmp (Version, 'Basic'))

M1 = 3;

M2 = 4;

elseif (strcmp (Version, 'Advanced'))

if (strcmp (Model, 'FFT'))

M1 = 1;

M2 = 2;

else

M1 = 1;

M2= 1;

end

end

function Ntot = PQIoud (Ehs, Ver, Mod)

e = 0.23;

persistent Nc s Et Ets Version Model

if (~strcmp (Ver, Version) | ~strcmp (Mod, Model))

Version = Ver;

Model = Mod;

if (strcmp (Model, 'FFT'))

[Nc, fc] = PQCB (Version);

с =1.07664;

else

[Nc, fc] = PQFB;

с =1.26539;

end

E0 = 1e4;

Et = PQ_enThresh (fc);

s = PQ_exlndex (fc);

for (m = 0:Nc-1)

Ets(m+1) = с * (Et(m+1) / (s(m+1) * Е0))^е;

end

end

sN = 0;

for (m = 0:Nc-1)

Nm = Ets(m+1) * ((1 - s(m+1) + s(m+1) * Ehs(m+1) / Et(m+1))^е -1);

sN = sN + max(Nm, 0);

end

Ntot = (24 / Nc) * sN;

%====================

function s = PQ_exlndex (f)

N = length (f);

for (m = 0:N-1)

sdB = -2 - 2.05 * atan(f(m+1) / 4000) - 0.75 * atan((f(m+1) / 1600)^2);

s(m+1) = 10^(sdB / 10);

end

%--------------------

function Et = PQ_enThresh (f)

N = length (f);

for (m = 0:N-1)

EtdB = 3.64 * (f(m+1) / 1000)^(-0.8);

Et(m+1) = 10^(EtdB/10);

end

function [M, ERavg, Fmem] = PQmodPatt (Es, Fmem)

persistent Nc a b Fss

if (isempty (Nc))

Fs = 48000;

NF = 2048;

Fss = Fs / (NF/2);

[Nc, fc] = PQCB ('Basic');

t100 = 0.050;

t0 = 0.008;

[a, b] = PQtConst (t100, t0, fc, Fss);

end

M = zeros (2, Nc);

е = 0.3;

for (i = 1:2)

for(m = 0:Nc-1)

Ee = Es(i,m+1)^e;

Fmem.DE(i,m+1) = a(m+1) * Fmem.DE(i,m+1)...

+ b(m+1) * Fss * abs (Ее - Fmem.Ese(i,m+1));

Fmem.Eavg(i,m+1) = a(m+1) * Fmem.Eavg(i,m+1) + b(m+1) * Ee;

Fmem.Ese(i,m+1) = Ee;

M(i,m+1) = Fmem.DE(i,m+1) / (1 + Fmem.Eavg(i,m+1) / 0.3);

end

end

ERavg = Fmem.Eavg(1,:);


Б.2 Листинг программы расчета метрики PEAQ на языке С

Файл: common.h

#define DEBUG

#define HANN 2048

#define BARK 109

#define DOUBLE

#if defined(DOUBLE)

#define module(x) fabs((double) x)

#define p(x,y) pow((double)x, (double)y)

#elif defined(LDOUBLE)

#define module(x) fabsl((long double) x)

#define p(x,y) powl((long double)x, (long double)y)

#endif

/************************ detprob ***********************/

#defineC1 1.0

/************************** end **************************/

/*********************** harmstruct **********************/

#defineAVGHANN

#define SKIPFRAME

#define GETMAX

#define Fup 18000.0

#define Flow 80.0

#define PATCH 1

/***************************** end **************************/

/**************************** peaqb ************************/

#define LOGVARIABLE

#ifdef LOGVARIABLE

#define LOGALLFRAMES

#endif

/****************************** end **************************/

struct processing {

double fftref[HANN/2];

double ffttest[HANN/2];

double ffteref[HANN/2];

double ffletest[HANN/2];

double fnoise[HANN/2];

double pptest[BARK];

double ppref[BARK];

double ppnoise[BARK];

double E2test[BARK];

double E2ref[BARK];

double Etest[BARK];

double Eref[BARK];

double Mref[BARK];

double Modtest[BARK];

double Modref[BARK];

};

Файл: peaqb.h

#define LOGRESULT "analized"

#ifdef DEBUG

#define LOGFILE "debugged.txt"

#endif

#define OPT_REF

0x01

#define OPT_TEST

0x02

#define THRESHOLDDELAY 0.050

#define AVERAGINGDEALAY 0.5

#define B(f) 7 * asinh((double)f /650)

#define Bl(z) 650 * sinh((double)z /7)

/* Function prototypes */

void fatalerr(char *,...);

void usage(char*);

void logvariable(const char*, double*, int);

void ProcessFrame(signed int*, signed int*, int, signed int *,

signed int*, int, int, int, int);

/* Prototypes end */

Файл: peaqb.c

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <stdarg.h>

#include <getopt.h>

#include <assert.h>

#include <math.h>

#include <fftw.h>

#include <common.h>

#include <wavedump.h>

#include <getframe.h>

#include <bandwidth.h>

#include <levpatadapt.h>

#include <moddiff.h>

#include <modulation.h>

#include <loudness.h>

#include <neural.h>

#include <nmr.h>

#include <detprob.h>

#include <energyth.h>

#include <harmstruct.h>

#include <boundary.h>

#include <critbandgroup.h>

#include <earmodelfft.h>

#include <noiseloudness.h>

#include <reldistframes.h>

#include <spreading.h>

#include <timespreading.h>

#include threshold.h>

#include <peaqb.h>

extern int errno;

char *fileref, *filetest;

double hannwindow[HANN];

double Etesttmpch1[BARK], Etesttmpch2[BARK], Ereftmpch1[BARK],

Ereftmpch2[BARK], Cffttmpch1[HANN/2], Cffttmpch2[HANN/2];

int delaytime1, delaytime2;

int count = 0;

int harmsamples = 1;

fftw_plan plan, plan2;

/* Bark Tables */

double *fL, *fC, *fU;

int bark;

struct levpatadaptin levinch1, Ievinch2;

struct modulationin modintestch1, modintestch2, modinrefch1, modinrefch2;

struct moddiffin moddiffinch1, moddiffinch2;

struct bandwidthout bandwidthch1, bandwidthch2;

struct outframes processed;

int

main(int argc, char *argv[])

{

signed int ch1ref[HANN];

signed int ch2ref[HANN];

signed int ch1test[HANN];

signed int ch2test[HANN];

int opt_line = 0;

int rateref, numchref, bitsampleref, Ipref;

int ratetest, numchtest, bitsampletest, Iptest;

int boundflag, totalframes = 0;

FILE *fpref, *fptest;

struct boundaryflag boundbe = {0, 0};

struct out oveRet;

/* Parse command line */

if (argc < 3)

usage(argv[0]);

{

int с = 0;

while ((c = getopt(argc, argv, "r:t:h")) != EOF)

switch (c) {

case 'h':

usage(argv[0]);

break;

case 'r':

opt_line |= OPT_REF;

fileref = optarg;

break;

case 't':

opt_line |= OPT_TEST;

filetest = optarg;

break;

}

}

/* Input control */

if (!(opt_line & OPT_REF) || !*fileref)

fatalerr ("err: -r/--reference <arg> required");

if (!(opt_line & OPT_TEST) || !*filetest)

fatalerr ("err: -t/--test <arg> required");

Ipref = LevelPression(fileref);

Iptest = LevelPression(filetest);

/* Init routines */

// make Hann Window (2.1.3)

{

int k;

for(k=0;k<HANN;k++)

hannwindow[k] = 0.5*sqrt((double)8/3)*

(1 - cos((double)2*M_PI*k/(HANN -1)));

}

// make Bark tables (2.1.5)

{

int k;

double zL, zU;

double *zl, *zc, *zu;

zL = B(Flow);

zU = B(Fup);

bark = ceil((zU-zL)/dz);

fL = (double *)malloc(bark * sizeof(double));

fC = (double *)malloc(bark * sizeof(double));

fU = (double *)malloc(bark * sizeof(double));

zl = (double *)malloc(bark * sizeof(double));

zc = (double *)malloc(bark * sizeof(double));

zu = (double *)malloc(bark * sizeof(double));

assert(fL != NULL && fC != NULL && fU != NULL && zl != NULL

&& zc != NULL && zu != NULL);

for(k=0;k<bark;k++) {

zl[k] = zL + k*dz;

zu[k] = zL + (k+1)*dz;

zc[k] = 0.5*(zl[k] + zu[k]);

}

zu[bark-1] = zU;

zc[bark - 1] = 0.5 * (zl[bark-1] + zu[bark-1]);

for(k=0;k<bark;k++) {

fL[k] = Bl(zl[k]);

fU[k] = Bl(zu[k]);

fC[k] = Bl(zc[k]);

}

free(zl);

free(zu);

free(zc);

}

// Initialize temp var

memset(&levinch1, 0x00, sizeof(struct levpatadaptin));

memset(&levinch2, 0x00, sizeof(struct levpatadaptin));

memset(&modintestch1, 0x00, sizeof(struct modulationin));

memset(&modintestch2, 0x00, sizeof(struct modulationin));

memset(&modinrefch1, 0x00, sizeof(struct modulationin));

memset(&modinrefch2, 0x00, sizeof(struct modulationin));

memset(Etesttmpch1, 0x00, BARK * sizeof(double));

memset(Etesttmpch2, 0x00, BARK * sizeof(double));

memset(Ereftmpch1, 0x00, BARK * sizeof(double));

memset(Ereftmpch2, 0x00, BARK * sizeof(double));

memset(Cffttmpch1, 0x00, (HANN/2) * sizeof(double));

memset(Cffttmpch2, 0x00, (HANN/2) * sizeof(double));

memset(&moddiffinch1, 0x00, sizeof(struct moddiffin));

memset(&moddiffinch2, 0x00, sizeof(struct moddiffin));

memset(&bandwidthch1, 0x00, sizeof(struct bandwidthout));

memset(&bandwidthch2, 0x00, sizeof(struct bandwidthout));

// ref file

if ((fpref = fopen(fileref,"r")) == NULL)

fatalerr("err: %s", strerror(errno));

if ((rateref = SampleRate(fpref)) == -1)

fatalerr("err: error in WaveHeader");

if ((numchref = NumOfChan(fpref)) == -1)

fatalerr("err: error in WaveHeader");

if ((bitsampleref = BitForSample(fpref)) == -1)

fatalerr("err: error in WaveHeader");

if (FindData(fpref) == -1)

fatalerr("err: can't find Data Field");

// test file

if ((fptest = fopen(filetest,"r")) == NULL)

fatalerr("err: %s", strerror(errno));

if ((ratetest = SampleRate(fptest)) == -1)

fatalerr("err: error in WaveHeader");

if ((numchtest = NumOfChan(fptest)) == -1)

fatalerr("err: error in WaveHeader");

if ((bitsampletest = BitForSample(fptest)) == -1)

fatalerr("err: error in WaveHeader");

if(FindData(fptest) == -1)

fatalerr("err: can't find Data Field");

fprintf(stdout,"\n PEAQb Algorithm. Author Giuseppe Gottardi 'oveRet'"

" <gottardi@ailinux.org>\n");

fprintf(stdout,"\nRef File %s"

"\n - Sample Rate: %d"

"\n - Number Of Channel: %d"

"\n - Bits for Sample: %d"

"\n - Level Playback: %d\n\n", fileref, rateref,

numchref, bitsampleref, Ipref);

fprintf(stdout,"\nTest File %s"

"\n - Sample Rate: %d"

"\n - Number Of Channel: %d"

"\n - Bits for Sample: %d"

"\n - Level Playback: %d\n\n", filetest, ratetest,

numchtest, bitsampletest, Iptest);

// Processing

if(ratetest != rateref)

fatalerr("err: Can't process Wave Files with different Sample Rate");

if(numchref != numchtest)

fatalerr("err: Can't process Mono Wave with Stereo Wave");

// Find delaytimel for Loudness Threshold

delaytime1 = ceilf((float)THRESHOLDDELAY*ratetest*2/HANN);

// Find delaytime2 for Delayed Averaging

delaytime2 = ceilf((float)AVERAGINGDEALAY*ratetest*2/HANN);

// make fft plan

plan = fftw_create_plan(HANN, FFTW_FORWARD, FFTW_MEASURE);

while(harmsamples < (Fup/ratetest)*(HANN/2.0)/2.0)

harmsamples *= 2;

plan2 = fftw_create_plan(harmsamples, FFTW_FORWARD, FFTW_MEASURE);

if(numchref == 1) {

if (fseek(fpref, (HANN/2)*bitsampleref/8, SEEK_CUR) == -1)

fatalerr("err: %s", strerror(errno));

if (fseek(fptest, (HANN/2)*bitsampletest/8, SEEK_CUR) == -1)

fatalerr("err: %s", strerror(errno));

#ifdef DATABOUND_BE

#undef DATABOUND_ONE

{

int i = 0, flag = 0, f1, f2;

long dataref, datatest, br1, br2;

dataref = ftell(fpref);

datatest = ftell(fptest);

while(1) {

br1 = ftell(fpref);

br2 = ftell(fptest);

f1 = GetMonoFrame(fpref, (signed int *)ch1ref,

bitsampleref/8, HANN);

f2 = GetMonoFrame(fptest, (signed int*)ch1test,

bitsampletest/8, HANN);

if(f1 && f2) {

totalframes++;

if(boundary(ch1ref, ch1test, NULL, NULL, HANN) && !flag) {

boundbe. begin = totalframes;

flag = 1;

}

}

else {

fseek(fptest, br1, SEEK_SET);

fseek(fpref, br2, SEEK_SET);

break;

}

}

fseek(fptest, -(HANN/2)*bitsampletest/8, SEEK_CUR);

fseek(fpref, -(HANN/2)*bitsampleref/8, SEEK_CUR);

while(i<totalframes) {

GetMonoFrame(fpref, (signed int *)ch1ref, bitsampleref/8, HANN);

GetMonoFrame(fptest, (signed int *)ch1 test, bitsampletest/8, HANN);

fseek(fptest, -2*(HANN/2)*bitsampletest/8, SEEK_CUR);

fseek(fpref, -2*(HANN/2)*bitsampleref/8, SEEK_CUR);

i++;

if(boundary(ch1ref, ch1test, NULL, NULL, HANN)) {

boundbe.end = totalframes-i;

break;

}

}

fseek(fptest, datatest, SEEK_SET);

fseek(fpref, dataref, SEEK_SET);

}

#endif

while (GetMonoFrame(fpref, (signed int *)ch1ref,

bitsampleref/8, HANN)

&& GetMonoFrame(fptest, (signed int *)ch1test,

bitsampletest/8, HANN)) {

count++;

#ifdefDATABOUND_BE

if(count >= boundbe.begin && count <= boundbe.end)

boundflag = 1;

else

boundflag = 0;

#else

boundflag = boundary(ch1ref, ch1test, NULL, NULL, HANN);

#ifdef DATABOUND_ONE

{

static int flag 1 =0, flag2 = 0;

if(boundflag && !flag1)

flag1 = 1;

if(!boundflag && flag1)

flag2 = 1;

if(flag2)

boundflag = 0;

}

#endif

#endif

ProcessFrame((signed int *)ch1ref,

(signed int*)NULL, Ipref,

(signed int *)ch1test,

(signed int *)NULL,

Iptest, rateref, boundflag, HANN);

oveRet = neural(processed);

fprintf(stdout,"\nframe: %d"

#ifdef DATABOUND_BE

"/%d"

"\ndata boundary: %d -> %d"

#endif

"\nBandwidthRefb: %g"

"\nBandwidthTestb: %g"

"\nTotalNMRb %g"

"\nWinModDiff1b: %g"

"\nADBb: %g"

"\nEHSb: %g"

"\nAvgModDiff1b: %g"

"\nAvgModDiff2b %g"

"\nRmsNoiseLoudb: %g"

"\nMFPDb: %g"

"\nRelDistFramesb: %g"

"\nDI: %g"

"\nODG: %g\n",

count,

#ifdef DATABOUND_BE

totalframes, boundbe.begin, boundbe.end,

#endif

processed. BandwidthRefb,

processed.BandwidthTestb, processed.TotalNMRb,

processed.WinModDiff1b, processed.ADBb,

processed.EHSb, processed.AvgModDiff1b,

processed.AvgModDiff2b,

processed.RmsNoiseLoudb, processed.MFPDb,

processed.RelDistFramesb,

oveRet.Dl, oveRet.ODG);

}

{

FILE *res;

res = fopen(LOGRESULT,"a+");

fprintf(res,"\nFile: %s\n"

"\nframe: %d"

"\nBandwidthRefb: %g"

"\nBandwidthTestb: %g"

"\nTotalNMRb %g"

"\nWinModDiff1b: %g"

"\nADBb: %g"

"\nEHSb: %g"

"\nAvgModDiff1b: %g"

"\nAvgModDiff2b %g"

"\nRmsNoiseLoudb: %g"

"\nMFPDb: %g"

"\nRelDistFramesb: %g"

"\nDI: %g"

"\nODG: %g\n",

filetest, count, processed.BandwidthRefb,

processed.BandwidthTestb, processed.TotalNMRb,

processed.WinModDiff1b, processed.ADBb,

processed.EHSb, processed.AvgModDiff1b,

processed.AvgModDiff2b,

processed.RmsNoiseLoudb, processed.MFPDb,

processed.RelDistFramesb,

oveRet.DI, oveRet.ODG);

fclose(res);

}

}

if(numchref == 2) {

if (fseek(fpref, HANN*bitsampleref/8, SEEK_CUR) == -1)

fatalerr("err: %s", strerror(errno));

if (fseek(fptest, HANN*bitsampletest/8, SEEK_CUR) == -1)

fatalerr("err: %s", strerror(errno));

#ifdefDATABOUND_BE

#undef DATABOUND_ONE

{

int i = 0, flag = 0, f1, f2;

long dataref, datatest, br1, br2;

dataref = ftell(fpref);

datatest = ftell(fptest);

while(1) {

br1 = ftell(fpref);

br2 = ftell(fptest);

f1 = GetStereoFrame(fpref, (signed int *)ch1ref,

(signed int *)ch2ref, bitsampleref/8, HANN);

f2 = GetStereoFrame(fptest, (signed int *)ch1test,

(signed int *)ch2test, bitsampletest/8, HANN);

if(f1 && f2) {

totalframes++;

if(boundary(ch1ref, ch1test, ch2ref, ch2test, HANN) && Iflag) {

boundbe.begin = totalframes;

flag = 1;

}

}

else {

fseek(fptest, br1, SEEK_SET);

fseek(fpref, br2, SEEK_SET);

break;

}

}

fseek(fptest, -HANN*bitsampletest/8, SEEK_CUR);

fseek(fpref, -HANN*bitsampleref/8, SEEK_CUR);

while(i<totalframes) {

GetStereoFrame(fpref, (signed int *)ch1ref,

(signed int *)ch2ref, bitsampleref/8, HANN);

GetStereoFrame(fptest, (signed int *)ch1test,

(signed int *)ch2test, bitsampletest/8, HANN);

fseek(fptest, -2*HANN*bitsampletest/8, SEEK_CUR);

fseek(fpref, -2*HANN*bitsampleref/8, SEEK_CUR);

i++;

if(boundary(ch1ref, ch1test, ch2ref, ch2test, HANN)) {

boundbe.end = totalframes-i+1;

break;

}

}

fseek(fptest, datatest, SEEK_SET);

fseek(fpref, dataref, SEEK_SET);

}

#endif

while (GetStereoFrame(fpref, (signed int *)ch1ref,

(signed int *)ch2ref, bitsampleref/8, HANN)

&& GetStereoFrame(fptest, (signed int *)ch1test,

(signed int *)ch2test, bitsampletest/8, HANN)) {

count++;

#ifdef DATABOUND_BE

if(count >= boundbe.begin && count <= boundbe.end)

boundflag = 1;

else

boundflag = 0;

#else

boundflag = boundary(ch1ref, ch1test, ch2ref, ch2test, HANN);

#ifdef DATABOUND_ONE

{

static int flag1 =0, flag2 = 0;

if(boundflag && !flag1)

flag1 = 1;

if(!boundflag && flag1)

flag2 = 1;

if(flag2)

boundflag = 0;

}

#endif

#endif

ProcessFrame((signed int *)ch1ref,

(signed int*)ch2ref, Ipref,

(signed int *)ch1test,

(signed int *)ch2test,

Iptest, rateref, boundflag, HANN);

oveRet = neural(processed);

fprintf(stdout,"\nframe: %d"

#ifdef DATABOUND_BE

"/%d"

"\ndata boundary: %d -> %d"

#endif

"\nBandwidthRefb: %g"

"\nBandwidthTestb: %g"

"\nTotalNMRb %g"

"\nWinModDiff1b: %g"

"\nADBb: %g"

"\nEHSb: %g"

"\nAvgModDiff1b: %g"

"\nAvgModDiff2b %g"

"\nRmsNoiseLoudb: %g"

"\nMFPDb: %g"

"\nRelDistFramesb: %g"

"\nDI: %g"

"\nODG: %g\n",

count,

#ifdefDATABOUND_BE

totalframes, boundbe.begin, boundbe.end,

#endif

processed. BandwidthRefb,

processed.BandwidthTestb, processed.TotalNMRb,

processed.WinModDiff1b, processed.ADBb,

processed.EHSb, processed.AvgModDiff1b,

processed. AvgModDiff2b,

processed.RmsNoiseLoudb, processed.MFPDb,

processed. RelDistFramesb,

oveRet.DI, oveRet.ODG);

}

{

FILE *res;

res = fopen(LOGRESULT,"a+");

fprintf(res,"\nFile: %s\n"

"\nframe: %d"

"\nBandwidthRefb: %g"

"\nBandwidthTestb: %g"

"\nTotalNMRb %g"

"\nWinModDiff1b: %g"

"\nADBb: %g"

"\nEHSb: %g"

"\nAvgModDiff1b: %g"

"\nAvgModDiff2b %g"

"\nRmsNoiseLoudb: %g"

"\nMFPDb: %g"

"\nRelDistFramesb: %g"

"\nDI: %g"

"\nODG: %g\n",

filetest, count, processed.BandwidthRefb,

processed.BandwidthTestb, processed.TotalNMRb,

processed.WinModDiff1b, processed.ADBb,

processed.EHSb, processed.AvgModDiff1b,

processed. AvgModDiff2b,

processed.RmsNoiseLoudb, processed.MFPDb,

processed. RelDistFramesb,

oveRet.DI, oveRet.ODG);

fclose(res);

}

}

fftw_destroy_plan(plan);

fclose(fpref);

fclose(fptest);

return 0;

}

void

ProcessFrame(signed int *ch1ref, signed int*ch2ref, int Ipref,

signed int *ch1test, signed int*ch2test, int Iptest,

int rate, int boundflag, int hann)

{

int k;

static int ch = 1;

double Ntotaltest, Ntotalref;

struct levpatadaptout lev;

struct moddiffout mod;

struct processing processch1, processch2;

earmodelfft(ch1ref, Ipref, hann, processch1.ffteref,

processch1.fftref);

earmodelfft(ch1test, Iptest, hann, processch1.fltetest,

processch1.ffttest);

critbandgroup(processch1.ffteref, rate, hann, processch1. ppref);

AddlntNoise(processch1.ppref);

critbandgroup(processch1.fltetest, rate, hann, processch1.pptest);

AddlntNoise(processch1.pptest);

for(k=0;k<hann/2;k++)

processch1.fnoise[k] = module(processch1.flteref[k])

- module(processch1.fftetest[k]);

critbandgroup(processch1.fnoise, rate, hann, processch1.ppnoise);

spreading(processch1.pptest, processch1.E2test);

spreading(processch1.ppref, processch1.E2ref);

timespreading(processch1.E2test, Etesttmpch1, rate, processch1.Etest);

timespreading(processch1.E2ref, Ereftmpch1, rate, processch1.Eref);

threshold(processch1.Eref, processch1.Mref);

modulation(processch1.E2test, rate, &modintestch1, processch1.Modtest);

modulation(processch1.E2ref, rate, &modinrefch1, processch1.Modref);

// Data boundary

if(boundflag) {

static int countboundary = 1;

static double RelDistFramesb = 0, nmrtmp = 0;

bandwidth(processch1.ffttest, processch1.fftref, hann,

&bandwidthch1);

processed.BandwidthRefb = bandwidthch1.BandwidthRefb;

processed.BandwidthTestb = bandwidthch1.BandwidthTestb;

processed.TotalNMRb = nmr(processch1.ppnoise, processch1.Mref,

&nmrtmp, countboundary);

processed.RelDistFramesb = reldistframes(processch1.ppnoise,

processch1.Mref,

&RelDistFramesb,

countboundary);

countboundary++;

// Data boundary + Energy threshold

if(energyth(ch1test, ch1ref, hann)) {

static int countenergy = 1;

static double EHStmp = 0;

processed.EHSb = harmstruct(processch1. ffttest,

processch1.fftref,

&EHStmp, rate, Cffttmpch1,

harmsamples, &countenergy);

countenergy++;

}

}

// Delayed Averaging

if(count > delaytime2) {

static double nltmp = 0;

static int noise = 0, internal_count = 0, loudcounter = 0;

mod = moddiff(processch1.Modtest, processch1.Modref,

(double *)&(modinrefch1.Etildetmp));

processed.WinModDiff1b = ModDiff1(mod, &moddiffinch1,

count - delaytime2);

processed.AvgModDiff1b = ModDiff2(mod, &moddiffinch1);

processed.AvgModDiff2b = ModDiff3(mod, &moddiffinch1);

Ntotaltest = loudness(processch1.Etest);

Ntotalref = loudness(processch1.Eref);

if(Ntotaltest > 0.1 || Ntotalref > 0.1) {

noise = 1;

#ifdefined(LOUDMODO2)

internal_count = 0;

#endif

}

// Delayed Averaging + loudness threshold

if(noise && internal_count <= delaytime1) {

// skip 0.05 sec (about 3 frames)

internal_count++;

loudcounter++;

}

else {

lev= levpatadapt(processch1.Etest, processch1.Eref, rate,

&levinch1, hann);

processed.RmsNoiseLoudb = noiseloudness(processch1.Modtest,

processch1.Modref,

lev, &nltmp,

count - delaytime2

- loudcounter);

}

}

/*{

extern double Cfft[];

extern int maxk;

FILE *fp;

logvariable("Cfftsx.txt", Cfft, 128);

fp = fopen("Cfftsxmaxpos.txt", "a+");

fprintf(fp,"%d\n", maxk);

fclose(fp);

}*/

if(*ch2ref && *ch2test) {

ch=2;

earmodelfft(ch2ref, Ipref, hann, processch2.ffteref,

processch2.fftref);

earmodelfft(ch2test, Iptest, hann, processch2.fftetest,

processch2.ffttest);

critbandgroup(processch2.ffteref, rate, hann, processch2.ppref);

AddlntNoise(processch2.ppref);

critbandgroup(processch2.fftetest, rate, hann, processch2.pptest);

AddlntNoise(processch2.pptest);

for(k=0;k<hann/2;k++)

processch2.fnoise[k] = module(processch2.ffteref[k])

- module(processch2.fftetest[k]);

critbandgroup(processch2.fnoise, rate, hann, processch2.ppnoise);

spreading(processch2.pptest, processch2.E2test);

spreading(processch2.ppref, processch2.E2ref);

timespreading(processch2.E2test, Etesttmpch2, rate,

processch2.Etest);

timespreading(processch2.E2ref, Ereftmpch2, rate,

processch2.Eref);

threshold(processch2.Eref, processch2.Mref);

modulation(processch2.E2test, rate, &modintestch2,

processch2.Modtest);

modulation(processch2.E2ref, rate, &modinrefch2,

processch2.Modref);

// Data boundary

if(boundflag) {

static int countboundary = 1;

static double RelDistFramesb = 0, nmrtmp = 0;

bandwidth(processch2.ffttest, processch2.fftref, hann,

&bandwidthch2);

processed.BandwidthRefb += bandwidthch2.BandwidthRefb;

processed.BandwidthTestb += bandwidthch2.BandwidthTestb;

processed.BandwidthRefb /= 2.0;

processed.BandwidthTestb /= 2.0;

processed.TotalNMRb += nmr(processch2.ppnoise,

processch2.Mref, &nmrtmp,

countboundary);

processed. RelDistFramesb += reldistframes(processch2.ppnoise,

processch2.Mref,

&RelDistFramesb,

countboundary);

processed.TotalNMRb /= 2.0;

processed.RelDistFramesb /= 2.0;

countboundary++;

// Data boundary + Energy threshold

if(energyth(ch2test, ch2ref, hann)) {

static int countenergy = 1;

static double EHStmp = 0;

processed.EHSb += harmstruct(processch2.ffttest,

processch2.fftref,

&EHStmp, rate, Cffttmpch2,

harmsamples, &countenergy);

processed.EHSb/=2.0;

countenergy++;

}

}

// Delayed Averaging

if(count > delaytime2) {

static double nltmp = 0;

static int noise = 0, internal_count = 0, loudcounter = 0;

mod = moddiff(processch2.Modtest, processch2.Modref,

(double *)&(modinrefch2.Etildetmp));

processed.WinModDiff1b += ModDiff1(mod, &moddiffinch2,

count - delaytime2);

processed.AvgModDiff1b += ModDiff2(mod, &moddiffinch2);

processed.AvgModDiff2b += ModDiff3(mod, &moddiffinch2);

processed.WinModDiff1b /= 2.0;

processed.AvgModDiff1b /= 2.0;

processed.AvgModDiff2b /= 2.0;

Ntotaltest = loudness(processch2.Etest);

Ntotalref = loudness(processch2.Eref);

if(Ntotaltest> 0.1 || Ntotalref > 0.1) {

noise = 1;

#ifdefined(LOUDMODO2)

internal_count = 0;

#endif

}

// Delayed Averaging + loudness threshold

if(noise && internal_count <= delaytime1) {

// skip 0.05 sec (about 3 frames)

internal_count++;

loudcounter++;

}

else {

lev= levpatadapt(processch2.Etest, processch2.Eref, rate,

&levinch2, hann);

processed.RmsNoiseLoudb += noiseloudness(processch2.Modtest,

processch2.Modref,

lev, &nltmp,

count - delaytime2

- loudcounter);

processed.RmsNoiseLoudb /= 2.0;

}

}

}

{

static int ndistorcedtmp = 0;

static double Ptildetmp = 0, PMtmp = 0, Qsum = 0;

if(ch == 2)

processed.ADBb = detprob(processch1.Etest, processch2.Etest,

processch1.Eref, processch2.Eref,

&Ptildetmp, &PMtmp, &Qsum,

&ndistorcedtmp, hann);

else

processed.ADBb = detprob(processch1.Etest, NULL,

Processch1.Eref, NULL,

&Ptildetmp, &PMtmp, &Qsum,

&ndistorcedtmp, hann);

processed. MFPDb = PMtmp;

}

/*

#ifdef LOGVARIABLE

logvariable("fftetestsx.txt", processch1.fftetest, hann/2);

logvariable("ffterefsx.txt", processch1.ffteref, hann/2);

logvariable("ffttestsx.txt", processch1.ffttest, hann/2);

logvariable("fftrefsx.txt", processch1.fftref, hann/2);

logvariable("Etestsx.txt", processch1.Etest, bark);

logvariable("Erefsx.txt", processch1.Eref, bark);

logvariable("E2testsx.txt", processch1.E2test, bark);

logvariable("E2refsx.txt", processch1.E2ref, bark);

logvariable("pptestsx.txt", processch1.pptest, bark);

logvariable("pprefsx.txt", processch1.ppref, bark);

logvariable("ppnoisesx.txt", processch1.ppnoise, bark);

logvariable("Mrefsx.txt", processch1.Mref, bark);

logvariable("Modtestsx.txt", processch1.Modtest, bark);

logvariable("Modrefsx.txt", processch1.Modref, bark);

logvariable("fftetestdx.txt", processch2.fftetest, hann/2);

logvariable("ffterefdx.txt", processch2.ffteref, hann/2);

logvariable("ffttestdx.txt", processch2.ffttest, hann/2);

logvariable("fftrefdx.txt", processch2.fftref, hann/2);

logvariable("Etestdx.txt", processch2.Etest, bark);

logvariable("Erefdx.txt", processch2.Eref, bark);

logvariable("E2testdx.txt", processch2.E2test, bark);

logvariable("E2refdx.txt", processch2.E2ref, bark);

logvariable("pptestdx.txt", processch2.pptest, bark);

logvariable("pprefdx.txt", processch2.ppref, bark);

logvariable("ppnoisedx.txt", processch2.ppnoise, bark);

logvariable("Mrefdx.txt", processch2.Mref, bark);

logvariable("Modtestdx.txt", processch2.Modtest, bark);

logvariable("Modrefdx.txt", processch2.Modref, bark);

#endif

*/

/*{

extern double Cfft[];

extern int maxk;

FILE *fp;

logvariable("Cfftdx.txt", Cfft, 128);

fp = fopen("Cfftdxmaxpos.txt", "a+");

fprintf(fp,"%d\n", maxk);

fclose(fp);

}*/

return;

}

void

fatalerr(char * pattern,...)/* Error handling routine */

{

va_list ap;

va_start(ap, pattern);

fprintf(stderr,"PEAQ-");

vfprintf(stderr, pattern, ap);

fprintf(stderr," (exit forced).\n");

va_end(ap);

exit(-1);

}

#ifdef DEBUG

void

debug(char * pattern,...) /* Debug handling routine */

{

FILE log;

va_list ap;

va_start(ap, pattern);

log=fopen(LOGFILE,"a+");

vfprintf(log, pattern, ap);

va_end(ap);

fclose(log);

return;

}

#endif

#ifdef LOGVARIABLE

void

logvariable(const char *filename, double *var, int len)

{

FILE *fp;

int k;

#ifdef LOGALLFRAMES

fp = fopen(filename,"a+");

#else

fp = fopen(filename,"w");

#endif

for(k=0;k<len;k++)

fprintf(fp,"%g\n",var[k]);

fclose(fp);

return;

}

#endif

void

usage(char * name) /* Print usage */

{

fprintf(stderr, "PEAQ Algorithm. Giuseppe Gottardi 'oveRet'"

"<gottardi@ailinux.org>\n\n");

fprintf(stderr, "usage: %s <option>\n", name);

fprintf(stderr,"

-r reffile[:lp] (Ip default = 92)\n"

" -t testfile[:lp] (Ip default = 92)\n"

"-h print this help\n");

exit (0);

}

Файл: bandwidth.h

#define ZEROTHRESHOLD 921

#define BwMAX 346

struct bandwidthout {

double sumBandwidthRefb;

int countref;

double sumBandwidthTestb;

int counttest;

double BandwidthRefb;

double BandwidthTestb;

};

/* Function prototypes */

int bandwidth(double *, double *, int, struct bandwidthout *);

/* Prototypes end */

Файл: bandwidth.c

#include <stdlib.h>

#include <math.h>

#include <common.h>

#include <bandwidth.h>

int

bandwidth(double *ffttest, double *fftref, int hann,

struct bandwidthout *out)

{

int k, BwRef = 0, BwTest = 0;

double Flevtest, Flevref;

double ZeroThreshold;

ZeroThreshold = 20.0 * log10((double)ffttest[ZEROTHRESHOLD]);

for(k=ZEROTHRESHOLD;k<hann/2;k++) {

Flevtest = 20.0 * Iog10((double)ffttest[k]);

if(Flevtest > ZeroThreshold)

ZeroThreshold = Flevtest;

}

for(k=ZEROTHRESHOLD-1; k>=0;k--) {

Flevref = 20.0 * Iog10((double)fftref[k]);

if(Flevref >= 10.0+ZeroThreshold) {

BwRef = k + 1;

break;

}

}

for(k=BwRef-1;k>=0;k--) {

Flevtest = 20.0 * Iog10((double)ffttest[k]);

if(Flevtest >= 5.0+ZeroThreshold) {

BwTest = к + 1;

break;

}

}

if( BwRef >BwMAX) {

out->sumBandwidthRefb += (double)BwRef;

out->countref++;

}

if(BwTest > BwMAX) {

out->sumBandwidthTestb += (double)BwTest;

out->counttest++;

}

if(out->countref == 0)

out->BandwidthRefb = 0;

else

out->BandwidthRefb = out->sumBandwidthRefb/(double)out->countref;

if(out->counttest == 0)

out->BandwidthTestb = 0;

else

out->BandwidthTestb = out->sumBandwidthTestb/(double)out->counttest;

return 0;

}

Файл: boundary.h

#define BOUNDWIN 5

#defineBOUNDLIMIT 200

struct boundaryflag {

int begin;

int end;

};

/* Function prototypes */

int boundary(signed int *, signed int *, signed int *, signed int *, int);

/* Prototypes end */

Файл: boundary.c

#include <stdlib.h>

#include <math.h>

#include <common.h>

#include <boundary.h>

int

boundary(signed int *ch1ref, signed int *ch1test, signed int *ch2ref,

signed int *ch2test, int hann)

{

int k, i, sum;

int ch1t = 0, ch1r = 0, ch2t = 0, ch2r = 0;

for(k=0;k<hann-BOUNDWIN+1;k++) {

if(!ch1t) {

sum = 0;

for(i=0;i<BOUNDWIN;i++)

sum += abs(ch1test[k+i]);

if(sum > BOUNDLIMIT)

ch1t=1;

}

if(!ch1r) {

sum = 0;

for(i=0;i<BOUNDWIN;i++)

sum += abs(ch1ref[k+i]);

if(sum > BOUNDLIMIT)

ch1r = 1;

}

if(ch1t || ch1r) // || or &&

return 1;

if(ch2test == NULL && ch2ref == NULL)

return 0;

for(k=0;k<hann-BOUNDWIN+1;k++) {

if(!ch2t) {

sum = 0;

for(i=0;i<BOUNDWIN;i++)

sum += abs(ch2test[k+i]);

if(sum > BOUNDLIMIT)

ch2t = 1;

}

if(!ch2r) {

sum = 0;

for(i=0;i<BOUNDWIN;i++)

sum += abs(ch2ref[k+i]);

if(sum> BOUNDLIMIT)

ch2r=1;

}

if((ch1t || ch2t) || (ch1r || ch2r)) // || or &&

return 1;

}

return 0;

}

Файл: critbandgroup.h

/* Function prototypes */

int critbandgroup(double *, int, int, double *);

intAddlntNoise(double*);

/* Prototypes end */

Файл: critbandgroup.c

#include <stdlib.h>

#include <math.h>

#include <common.h>

#include <critbandgroup.h>

extern double *fL, *fC, *fU;

extern int bark;

int

critbandgroup(double *ffte, int rate, int hann, double *pe)

{

double fres;

int i, k;

fres = (double)rate/hann;

for(i=0;i<bark;i++) {

pe[i] = 0;

for(k=0;k<hann/2;k++) {

if(((double)(k-0.5)*fres) >= fL[i]

&& ((double)(k+0.5)*fres <= fU[i]))

pe[i] += p(ffte[k], 2.0);

else

if(((double)(k-0.5)*fres) < fL[i]

&& ((double)(k+0.5)*fres > fU[i]))

pe[i] += p(ffte[k], 2.0)*(fU[i]-fL[i])/fres;

else

if(((double)(k-0.5)*fres) < fL[i]

&& ((double)(k+0.5)*fres > fL[i]))

pe[i] += p(ffte[k], 2.0)*(double)((k+0.5)

*fres-fL[i])/fres;

else

if(((double)(k-0.5)*fres) < fU[i]

&& ((double)(k+0.5)*fres > fU[i]))

pe[i] += p(ffte[k], 2.0)*(fU[i]-(double)(k-0.5)

*fres)/fres;

}

if(pe[i] < p(10.0, -12.0))

pe[i] = p(10.0, -12.0);

}

return 0;

}

int

AddlntNoise(double *pe)

{

int k;

double Pthres;

for(k=0;k<bark;k++) {

Pthres = p(10.0, 0.4*0.364*p(fC[k]/1000.0, -0.8));

pe[k] += Pthres;

}

return 0;

}

Файл: detprob.h

/* Function prototypes */

double detprob(double *, double *, double *, double *, double *,

double *, double *, int *, int);

/* Prototypes end */

Файл: detprob.c

#include <stdlib.h>

#include <math.h>

#include <common.h>

#include <detprob.h>

extern int bark;

double

detprob(double *Etestch1, double *Etestch2, double *Erefch1,

double *Erefch2, double *Ptildetmp, double *PMtmp,

double *Qsum, int *ndistorcedtmp, int hann)

{

int k;

double Etilderefch1, Etilderefch2, Etildetestch1, Etildetestch2;

double L, s, e, b, a, pch1, pch2, pbin,

qch1, qch2, qbin, P, c0, c1, ADBb;

double prod = 1.0, Q = 0.0;

for(k=0;k<bark;k++) {

Etildetestch1 = 10.0*log10((double)Etestch1[k]);

Etilderefch1 = 10.0*log10((double)Erefch1[k]);

if(Etilderefch1 > Etildetestch1)

L = 0.3*Etilderefch1;

else

L = 0.3*Etildetestch1;

L += 0.7*Etildetestch1;

if(L > 0)

s = 5.95072*p(6.39468/L, 1.71332)+9.01033*p(10.0, -11.0)

*p(L, 4.0)+5.05622*p(10.0, -6.0)*p(L, 3.0)-0.00102438

*p(L, 2.0)+0.0550197*L-0.198719;

else

s = p(10.0, 30.0);

e = Etilderefch1 - Etildetestch1;

if(Etilderefch1 > Etildetestch1)

b = 4.0;

else

b = 6.0;

a = (double)p(10.0, Iog10((double)log10((double)2.0))/b)/s;

pch1 = 1.0 - p(10.0, -p(a*e, b));

qch1 = abs((int)e)/s; //don't touch this

pbin = pch1;

qbin = qch1;

if(Etestch2 != NULL && Erefch2 != NULL) {

Etildetestch2 = 10.0*log10((double)Etestch2[k]);

Etilderefch2 = 10.0*log10((double)Erefch2[k]);

if(Etilderefch2 > Etildetestch2)

L = 0.3*Etilderefch2;

else

L = 0.3*Etildetestch2;

L += 0.7*Etildetestch2;

if(L > 0)

s = 5.95072*p(6.39468/L, 1.71332)+9.01033*p(10.0, -11.0)

*p(L, 4.0)+5.05622*p(10.0, -6.0)*p(L, 3.0)

-0.00102438*p(L, 2.0)+0.0550197*L-0.198719;

else

s = 1.0*p(10.0, 30.0);

e = Etilderefch2 - Etildetestch2;

if(e > 0)

b = 4.0;

else

b = 6.0;

a = (double)p(10.0, Iog10((double)log10((double)2.0))/b)/s;

pch2 = 1.0 - p(10.0, -p(a*e, b));

qch2 = abs((int)e)/s; // don't touch this

if(pch2 > pch1)

pbin = pch2;

if(qch2 > qch1)

qbin = qch2;

}

prod *= (1.0 - pbin);

Q += qbin;

}

P = 1.0 - prod;

if(P > 0.5) {

*Qsum += Q;

(*ndistorcedtmp)++;

}

if(*ndistorcedtmp == 0)

ADBb = 0;

else

if(*Qsum > 0)

ADBb = log10((double)*Qsum / (*ndistorcedtmp));

else

ADBb = -0.5;

c0 = p(0.9, hann/(2.0*1024.0));

#if !defined(C1)

c1 = p(0.99, hann/(2.0*1024.0));

#else

c1 =C1;

#endif

*Ptildetmp = (1.0 - c0)*P + (*Ptildetmp)*c0;

if(*Ptildetmp > (*PMtmp)*c1)

*PMtmp = *Ptildetmp;

else

*PMtmp = (*PMtmp)*c1;

return ADBb;

}

Файл: earmodelfft.h

#define NORM 11361.301063573899

#define FREQADAP 23.4375 // for 48 kHz

/* Function prototypes */

int earmodelfft(signed int *, int, int, double *, double *);

/* Prototypes end */

Файл: earmodelfft.c

#include <stdlib.h>

#include <math.h>

#include <fftw.h>

#include <common.h>

#include <earmodelfft.h>

extern double hannwindow[ ];

extern fftw_plan plan;

int

earmodelfft(signed int *ch, int Ip, int hann, double *ffte, double *absfft)

{

int k;

double w, fac;

fftw_complex in[HANN], out[HANN];

fac = p(10.0, lp/20.0)/NORM;

for(k=0;k<hann;k++) {

in[k].re = hannwindow[k] * (double)ch[k];

in[k].im = 0;

}

fftw_one(plan, in, out);

for(k=0;k<hann/2;k++) {

out[k].re *= (double)(fac/hann);

out[k].im *= (double)(fac/hann);

absfft[k] = sqrt((double)(p(out[k].re, 2.0) + p(out[k].im, 2.0)));

w = -0.6*3.64*p(k * FREQADAP/1000.0, -0.8) +

6.5*exp((double)-0.6*p(k * FREQADAP/1000.0 - 3.3, 2.0)) -

0.001*p(k * FREQADAP/1000.0, 3.6);

ffte[k] = absfft[k]*p(10.0, w/20.0);

}

return 0;

}

Файл: energyth.h

#define ENERGYLIMIT 8000

/* Function prototypes */

int energyth(signed int *, signed int *, int);

/* Prototypes end */

Файл: energyth.c

#include <stdlib.h>

#include <math.h>

#include <common.h>

#include <energyth.h>

int

energyth(signed int *test, signed int *ref, int hann)

{

int k;

double sum;

sum = 0;

for(k=0;k<hann/2;k++) {

sum += p(test[hann/2 + k], 2.0);

if(sum > ENERGYLIMIT)

return 1;

}

sum = 0;

for(k=0;k<hann/2;k++) {

sum += p(ref[hann/2 + k], 2.0);

if(sum > ENERGYLIMIT)

return 1;

}

return 0;

}

Файл: getframe.h

#define LP 92

/* Function prototypes */

signed int GetFrameValue(FILE *, int);

int GetMonoFrame(FILE *, signed int *, int, int);

int GetStereoFrame(FILE *, signed int *, signed int *, int, int);

int LevelPression(char *);

int Readlnt(FILE*, int);

void fatalerr(char *,...);

/* Prototypes end */

Файл: getframe.c

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <getframe.h>

extern int errno;

signed int

GetFrameValue(FILE *fp, int bytes)

{

int intvalue;

if (bytes <= 0)

return 0;

intvalue = Readlnt(fp, bytes);

switch(bytes) {

case 3:

if (intvalue & 0x00800000)

intvalue |= 0xff000000;

break;

case 2:

if (intvalue & 0x00008000)

intvalue |= 0xffff0000;

break;

case 1:

if (intvalue & 0x00000080)

intvalue |= 0xffffff00;

break;

}

return (signed int) intvalue;

}

int

GetMonoFrame(FILE *fp, signed int *vect, int bytes, int hann)

{

int i = 0;

if (fp == NULL)

return 0;

if (fseek(fp, (-hann/2)*bytes, SEEK_CUR) == -1)

fatalerr("err: %s", strerror(errno));

while(!feof(fp) && i < hann) {

vect[i] = GetFrameValue(fp, bytes);

i++;

}

if(i < hann) {

bzero(vect, hann*4);

fseek(fp, -i*bytes, SEEK_END);

return 0;

}

/* Number of samples wrote */

return i ;

}

int

GetStereoFrame(FILE *fp, signed int *sx, signed int *dx, int bytes,

int hann)

{

int i = 0, k = 0, count = 0;

if (fp == NULL)

return 0;

if (fseek(fp, -hann*bytes, SEEK_CUR) == -1)

fatalerr("err: %s", strerror(errno));

while(!feof(fp) && count < hann*2) {

if(!k) {

sx[i] = GetFrameValue(fp, bytes);

k=1;

i--;

count++;

}

else {

dx[i] = GetFrameValue(fp, bytes);

k = 0;

count++;

}

i++;

}

if (count < hann*2) {

bzero(sx, hann*4);

bzero(dx, hann*4);

fseek(fp, -count*bytes, SEEK_END);

return 0;

}

/* Number of samples wrote */

return count;

}

int

LevelPression(char *f)

{

int Ip;

while(*f !=':' && *f)

f++;

if(*f ==':') {

lp = atoi(f + 1);

*f ='\0';

return Ip;

}

else

return LP;

}

Файл: harmstruct.h

/* Function prototypes */

double harmstruct(double *, double *, double *, int, double *, int, int *);

void debug(char *,...);

/* Prototypes end */

Файл: harmstruct.c

#include <stdlib.h>

#include <math.h>

#include <string.h>

#include <fftw.h>

#include <common.h>

#include <harmstruct.h>

extern char*filetest;

extern int count;

extern fftw_plan plan2;

double Cfft[HANN/2];

int maxk;

double

harmstruct(double *ffttest, double *fftref, double *EHStmp, int rate,

double *Cffttmp, int p, int *n)

{

int k, i;

double F0[HANN/2], C[HANN/2], hannwin[HANN/2];

double num, denoma, denomb, Csum = 0;

fftw_complex in[HANN/2], out[HANN/2];

double max;

bzero(Cfft, 8 * HANN/2);

for(k=0;k<p*2-1;k++) {

if(!fftref[k] || !ffttest[k]) { // skip log(0)

#if defined(SKIPFRAME) && !defined(ZERO)

(*n)--;

return 0;

#elif defined(ZERO)

if(!fftref[k]) {

fftref[k] = ZERO;

#ifdef DEBUG

debug("Warning [%s:%d] in Harmstruct.c: "

"fftref[%d] is set around zero\n",

filetest, count, k, fftref[k]);

#endif

}

if(!ffttest[k]) {

ffttest[k] = ZERO;

#ifdef DEBUG

debug("Warning [%s:%d] in Harmstruct.c: "

"ffttest[%d] is set around zero\n",

filetest, count, k, ffttest[k]);

#endif

}

F0[k] = Iog10(p(fftref[k], 2.0)) - Iog10(p(ffttest[k], 2.0));

#else

if(!fftref[k] && !ffttest[k])

F0[k] = 0;

else {

#ifdef DEBUG

debug("Error [%s:%d] in Harmstruct.c: "

"log(fftref[%d] = %g log(ffttest[%d] = %g\n",

filetest, count, k, fftref[k], k, ffttest[k]);

#endif

F0[k] = 0;

}

#endif

}

else

F0[k] = Iog10(p(fftref[k], 2.0)) - Iog10(p(ffttest[k], 2.0));

}

for(i=0;i<p;i++) {

num = 0;

denoma = 0;

denomb = 0;

for(k=0;k<p;k++) {

num += F0[k] * F0[i+k];

denoma += p(F0[k], 2.0);

denomb += p(F0[i+k], 2.0);

}

hannwin[i] = 0.5*sqrt((double)8.0/3.0)*(1.0 - cos((double)2.0

*M_PI*i/(p-1.0)));

C[i] = num / (sqrt((double)denoma) * sqrt((double)denomb));

#if !defined(AVGHANN)

C[i] *= hannwin[i];

#endif

Csum += C[i];

}

for(i=0;i<p;i++) {

C[i] -= (double)Csum/p;

#if defined(AVGHANN)

C[i] *= hannwin[i];

#endif

in[i].im = 0;

in[i].re = C[i];

}

fftw_one(plan2, in, out);

for(k=0;k<p/2;k++) {

out[k].re *= (double)(1.0/p);

out[k].im *= (double)(1.0/p);

Cfft[k] = p(out[k].re, 2.0) + p(out[k].im, 2.0);

}

#ifdef EHSMODO2

for(k=0;k<p/2;k++) {

Cffttmp[k] += Cfft[k];

Cfft[k] = Cffttmp[k]/(*n);

}

#endif

#if !defined(GETMAX)

i = 0+PATCH;

while(1) {

if(Cfft[i] >= Cfft[i+1]) {

while(i < p/2-1 && Cfft[i] >= Cfft[i+1])

i++;

if(i < p/2-1)

break;

else {

(*n)--;

return 0;

}

}

else {

while(i < p/2-1 && Cfft[i] <= Cfft[i+1])

i++;

while(i < p/2-1 && Cfft[i] >= Cfft[i+1])

i++;

if(i < p/2-1)

break;

else {

(*n)--;

return 0;

}

}

}

#else

i = 0;

#endif

max = 0;

for(k=i+1;k<p/2;k++)

if(Cfft[k] > max) {

max = Cfft[k];

maxk = k;

}

#ifdef EHSMODO2

return max*1000.0;

#endif

(*EHStmp) += max;

return ((*EHStmp)*1000.0/(*n));

}

Файл: levpatadapt.h

#define T100 0.05

#define Tmin 0.008

#define M 8

// if M is odd

/*

#define M1 (M-1)/2

#define M2 M1

*/

// if M is even

#define M1 M/2 - 1

#define M2 M/2

struct levpatadaptout {

double Epref[BARK];

double Eptest[BARK];

};

struct levpatadaptin {

double Ptest[BARK];

double Pref[BARK];

double PattCorrTest[BARK];

double PattCorrRef[BARK];

double Rnum[BARK];

double Rdenom[BARK];

};

/* Function prototypes */

struct levpatadaptout levpatadapt(double *, double *, int,

struct levpatadaptin *, int);

/* Prototypes end */

Файл: levpatadapt.c

#include <stdlib.h>

#include <math.h>

#include <common.h>

#include <levpatadapt.h>

extern int bark;

extern double *fC;

struct levpatadaptout

levpatadapt(double *Etest, double *Eref, int rate,

struct levpatadaptin *tmp, int hann)

{

int k, i, m1, m2;

double T, levcorr, numlevcorr = 0, denomlevcorr = 0, R;

double pattcoeffref, pattcoefftest;

double Elref[BARK], Eltest[BARK], Rtest[BARK], Rref[BARK], a[BARK];

struct levpatadaptout out;

for(k=0;k<bark;k++) {

T = (double)Tmin + (100.0/fC[k])*(T100 - Tmin);

a[k] = exp((double)-hann/(2.0*rate * T));

tmp->Ptest[k] = tmp->Ptest[k]*a[k] + (1.0-a[k])*Etest[k];

tmp->Pref[k] = tmp->Pref[k]*a[k] + (1.0-a[k])*Eref[k];

numlevcorr += sqrt(tmp->Ptest[k]*tmp->Pref[k]);

denomlevcorr += tmp->Ptest[k];

}

levcorr = p(numlevcorr/denomlevcorr, 2.0);

for(k=0;k<bark;k++) {

if(levcorr> 1.0) {

Elref[k] = (double)Eref[k]/levcorr;

Eltest[k] = Etest[k];

}

else {

Eltest[k] = (double)Etest[k]*levcorr;

Elref[k] = Eref[k];

}

// Autocorrelation

tmp->Rnum[k] *= a[k];

tmp->Rdenom[k] *= a[k];

tmp->Rnum[k] += Elref[k]*Eltest[k];

tmp->Rdenom[k] += Elref[k]*Elref[k];

if(tmp->Rdenom[k] == 0 && tmp->Rnum[k] != 0) {

Rtest[k] = 0;

Rref[k] = 1.0;

}

else

if(tmp->Rdenom[k] == 0 && tmp->Rnum[k] == 0) {

//copy from frequency band below

if(k) {

Rtest[k] = Rtest[k-1];

Rref[k] = Rref[k-1];

}

//if don't exist

else {

Rtest[k] = 1.0;

Rref[k] = 1.0;

}

}

else {

R = tmp->Rnum[k] / tmp->Rdenom[k];

if(R >= 1.0) {

Rtest[k] = 1.0/R;

Rref[k] = 1.0;

}

else {

Rtest[k] = 1.0;

Rref[k] = R;

}

}

}

for(k=0;k<bark;k++) {

m1 = M1;

m2 = M2;

pattcoefftest = 0;

pattcoeffref = 0;

if(m1 > k)

m1 = k;

if(m2 > bark -k -1)

m2 = bark -k -1;

for(i = -m1;i <= m2;i++) {

pattcoefftest += Rtest[k+i];

pattcoeffref += Rref[k+i];

}

tmp->PattCorrTest[k] = a[k]*tmp->PattCorrTest[k] +

pattcoeffiest*(1.0-a[k])/(m1+m2+1);

tmp->PattCorrRef[k] = a[k]*tmp->PattCorrRef[k] +

pattcoeffref*(1.0-a[k])/(m1+m2+1);

out.Epref[k] = Elref[k] * tmp->PattCorrRef[k];

out.Eptest[k] = Eltest[k] * tmp->PattCorrTest[k];

}

return out;

}

Файл: loudness.h

#define CONST 1.07664

/* Function prototypes */

double loudness(double *);

/* Prototypes end */

Файл: loudness.c

#include <stdlib.h>

#include <math.h>

#include <common.h>

#include <loudness.h>

extern double *fC;

extern int bark;

double

loudness(double *E)

{

int k;

double Ntot = 0;

double s, N, Ethres;

for(k=0;k<bark;k++) {

s = p(10.0, (-2.0-2.05*atan((double)fC[k]/4000.0) - 0.75

*atan((double)p(fC[k]/1600.0, 2.0)))/10.0);

Ethres = p(10.0, 0.364*p(fC[k]/1000.0, -0.8));

N = (double)CONST*p(Ethres/(s*10000.0), 0.23)

*(p(1.0-s+s*E[k]/Ethres, 0.23) - 1.0);

if(N > 0)

Ntot += N;

}

Ntot*=(double)24.0/bark;

return Ntot;

}

Файл: moddiff.h

#define L 4

struct moddiffin {

double win;

int Lcount;

double modtmp;

double mod[L];

double num2;

double denom2;

double num3;

double denom3;

};

struct moddiffout {

double ModDiff1;

double ModDiff2;

double TempWt;

};

/* Function prototypes */

struct moddiffout moddiff(double *, double *, double *);

double ModDiff1(struct moddiffout, struct moddiffin *, int);

double ModDiff2(struct moddiffout, struct moddiffin *);

double ModDiff3(struct moddiffout, struct moddiffin *);

/* Prototypes end */

Файл: moddiff.c

#include <stdlib.h>

#include <assert.h>

#include <math.h>

#include <common.h>

#include <moddiff.h>

extern double *fC;

extern int bark;

struct moddiffout

moddiff(double *Modtest, double *Modref, double *Etilderef)

{

int k;

struct moddiffout out;

double Pthres;

out.ModDiff1 = 0;

out.ModDiff2 = 0;

out.TempWt = 0;

for(k=0;k<bark;k++) {

// WinModDiff1B && AvgModDiff1B

out.ModDiff1 += module(Modtest[k] - Modref[k])/(1.0 + Modref[k]);

// AvgModDiff2B

if(Modtest[k] > Modref[k])

out.ModDiff2 += module(Modtest[k] - Modref[k])

/(0.01 + Modref[k]);

else

out.ModDiff2 += 0.1*module(Modtest[k] - Modref[k])

/(0.01 + Modref[k]);

Pthres = p(10.0, 0.4*0.364*p(fC[k]/1000.0, -0.8));

out.TempWt += Etilderef[k]/(Etilderef[k] + p(Pthres, 0.3)*100.0);

}

out.ModDiff1 *= (double)100.0/bark;

out.ModDiff2 *= (double)100.0/bark;

return out;

}

double

ModDiff1 (struct moddiffout in, struct moddiffin *intmp, int n)

{

int i;

intmp->mod[intmp->Lcount] = in.ModDiff1;

intmp->Lcount++;

if(intmp->Lcount == L)

intmp->Lcount = 0;

if(n < L)

return 0;

intmp->modtmp = 0;

for(i=0;i<L;i++)

intmp->modtmp += sqrt((double)intmp->mod[i]);

intmp->modtmp /= (double)L;

intmp->win += p(intmp->modtmp, 4.0);

return sqrt((double)intmp->win/(double)(n-L+1.0));

}

double

ModDiff2(struct moddiffout in, struct moddiffin *intmp)

{

intmp->num2 += in.ModDiff1 * in.TempWt;

intmp->denom2 += in.TempWt;

return (intmp->num2/intmp->denom2);

}

double

ModDiff3(struct moddiffout in, struct moddiffin *intmp)

{

intmp->num3 += in.ModDiff2 * in.TempWt;

intmp->denom3 += in.TempWt;

return (intmp->num3/intmp->denom3);

}

Файл: modulation.h

#defineT100 0.05

#defineTmin 0.008

struct modulationin {

double Edertmp[BARK];

double E2tmp[BARK];

double Etildetmp[BARK];

};

/* Function prototypes */

int modulation(double *, int, struct modulationin *, double *);

/* Prototypes end */

Файл: modulation.с

#include <stdlib.h>

#include <assert.h>

#include <math.h>

#include <common.h>

#include <modulation.h>

extern int bark;

extern double *fC;

int

modulation(double *E2, int rate, struct modulationin *in, double *Mod)

{

int k;

double T, a;

for(k=0;k<bark;k++) {

T = (double)Tmin + (double)(100/fC[k])*(double)(T100- Tmin);

a = exp((double)-HANN/(2*rate * T));

in->Edertmp[k] = in->Edertmp[k]*a+(1-a)*(double)(rate/(HANN/2))

*module(p(E2[k], 0.3) - p(in->E2tmp[k], 0.3));

in->E2tmp[k] = E2[k];

in->Etildetmp[k] = a*in->Etildetmp[k]+(1-a)*p(E2[k], 0.3);

Mod[k] = in->Edertmp[k]/(1 + (in->Etildetmp[k]/0.3));

}

return 0;

}

Файл: neural.h

#define sig(x) (double)(1.0/(1.0 + exp((double)-(x))))

#define I 11

#define J 3

struct outframes {

double WinModDiff1b;

double AvgModDiff1b;

double AvgModDiff2b;

double RmsNoiseLoudb;

double BandwidthRefb;

double BandwidthTestb;

double TotalNMRb;

double RelDistFramesb;

double ADBb;

double MFPDb;

double EHSb;

};

struct out {

double ODG;

double Dl;

};

/* Function prototypes */

struct out neural(struct outframes processed);

/* Prototypes end */

Файл: neural.c

#include <stdlib.h>

#include <math.h>

#include <common.h>

#include <neural.h>

double amin[11] = {393.916656, 361.965332, -24.045116, 1.110661, -0.206623,

0.074318, 1.113683, 0.950345, 0.029985, 0.000101, 0.0};

double amax[11] = {921.0, 881.131226, 16.212030, 107.137772,2.886017,

13.933351, 63.257874, 1145.018555, 14.819740, 1.0, 1.0};

double wx[12][3] = {{-0.502657, 0.436333, 1.219602},

{4.307481, 3.246017, 1.123743},

{4.984241, -2.211189, -0.192096},

{0.051056, -1.762424, 4.331315},

{2.321580, 1.789971, -0.754560},

{-5.303901, -3.452257, -10.814982},

{2.730991, -6.111805, 1.519223},

{0.624950, -1.331523, -5.955151},

{3.102889, 0.871260, -5.922878},

{-1.051468, -0.939882, -0.142913},

{-1.804679, -0.503610, -0.620456},

{-2.518254, 0.654841, -2.207228}};

double wy[4] = {-3.817048, 4.107138, 4.629582, -0.307594};

double bmin = -3.98;

double bmax = 0.22;

struct out

neural(struct outframes processed)

{

int j, i;

struct out oveRet;

double suml, sum2;

double x[11];

x[0] = processed. BandwidthRefb;

x[1] = processed. BandwidthTestb;

x[2] = processed.TotalNMRb;

x[3] = processed.WinModDiff1b;

x[4] = processed.ADBb;

x[5] = processed. EHSb;

x[6] = processed.AvgModDiff1b;

x[7] = processed.AvgModDiff2b;

x[8] = processed. RmsNoiseLoudb;

x[9] = processed. MFPDb;

x[10] = processed. RelDistFramesb;

// gcodcla.wav

/*x[0] = 834.117;

x[1] = 647.095;

x[2] = -14.6048;

x[3] = 6.89483;

x[4] = 0.432969;

x[5] = 0.503605;

x[6] = 7.14863;

x[7] = 24.9353;

x[8] = 0.124738;

x[9] = 0.968876;

x[10] = 0.0485208; // cosми tutto ok*/

// ccodsax.wav

/*x[0] = 853.375;

x[1] = 645.444;

x[2] = -7.94882;

x[3] = 11.4108;

x[4] = 1.41971;

x[5] = 0.491164;

x[6] = 12.6383;

x[7] = 44.7187;

x[8] = 0.21807;

x[9] = 1.15;//0.675505;

x[10] = 0.556215;*/

sum2 = 0;

for(j=0;j<J;j++) {

sum1 = 0;

for(i=0;i<l;i++)

sum1 += wx[i][j]*((x[i] - amin[i])/(amax[i] - amin[i]));

sum2 += wy[j]*sig(wx[l][j] + sum1);

}

oveRet.DI = wy[J] + sum2;

oveRet.ODG = bmin + (bmax - bmin)*sig(oveRet.DI);

return oveRet;

}

Файл: nmr.h

/* Function prototypes */

double nmr(double *, double *, double *, int);

/* Prototypes end */

Файл: nmr.c

#include <stdlib.h>

#include <math.h>

#include <common.h>

#include <nmr.h>

extern int bark;

double

nmr(double *Pnoise, double *M, double *nmrtmp, int n)

{

int k;

double sum = 0;

for(k=0;k<bark;k++)

sum += Pnoise[k]/M[k];

sum *= (double)1.0/bark;

*nmrtmp += sum;

return (10.0*log10((*nmrtmp)/n));

}

Файл: noiseloudness.h

#define THRESFAC0 0.15

#define S0 0.5

#define E0 1.0

#define ALPHA 1.5

/* Function prototypes */

double noiseloudness(double *, double *, struct levpatadaptout,

double *, int);

/* Prototypes end */

Файл: noiseloudness.c

#include <stdlib.h>

#include <math.h>

#include <common.h>

#include <levpatadapt.h>

#include <noiseloudness.h>

extern int bark;

extern double *fC;

double

noiseloudness(double *Modtest, double *Modref, struct levpatadaptout lev,

double *nltmp, int n)

{

int k;

double Pthres, stest, sref, beta, num, denom;

double nl = 0;

for(k=0;k<bark;k++) {

Pthres = p(10.0, 0.4*0.364*p(fC[k]/1000.0, -0.8));

stest = (double)THRESFAC0*Modtest[k] + S0;

sref = (double)THRESFAC0*Modref[k] + S0;

if(lev.Eptest[k] == 0 && lev.Epref[k] == 0)

beta = 1.0;

else

if(lev.Epref[k] == 0)

beta = 0;

else

beta = exp((double)-ALPHA*(lev.Eptest[k] - lev.Epref[k])

/lev.Epref[k]);

num = stest*lev.Eptest[k] - sref*lev.Epref[k];

denom = Pthres + sref*lev.Epref[k]*beta;

if(num < 0)

num = 0;

nl += p(Pthres/(E0*stest), 0.23)*(p(1.0 + num/denom, 0.23) - 1.0);

}

nl *= (double)24.0/bark;

if(nl < 0)

nl = 0;

*nltmp += p(nl, 2.0);

return sqrt((double)*nltmp/n);

}

Файл: reldistframes.h

/* Function prototypes */

double reldistframes(double *, double *, double *, int);

/* Prototypes end */

Файл: reldistframes.c

#include <stdlib.h>

#include <math.h>

#include <common.h>

#include <reldistframes.h>

extern int bark;

double

reldistframes(double *Pnoise, double *M, double *reldisttmp, int n)

{

int k;

for(k=0;k<bark;k++) {

if(10.0*log10((double)Pnoise[k]/M[k]) >= 1.5) {

*reldisttmp = *reldisttmp + 1;

break;

}

}

return ((double)*reldisttmp/n);

}

Файл: spreading.h

#ifdef ADVANCED

#define dz 0.5

#else

#define dz 0.25

#endif

/* Function prototypes */

int spreading(double *, double *);

/* Prototypes end */

Файл: spreading.с

#include <stdlib.h>

#include <math.h>

#include <common.h>

#include <spreading.h>

extern double *fC;

extern int bark;

int

spreading(double *pp, double *e2)

{

int k, j, u;

double L;

double denom, sum1, sum2, Eline, Su, SI = 27.0;

for(k=0;k<bark;k++) {

sum1 = 0;

sum2 = 0;

// Eline

for(j=0;j<bark;j++) {

L = 10.0*log10((double)pp[j]);

Su = -24.0-230.0/fC[j]+0.2*L;

Eline = p(10.0, L/10.0);

if(k < j)

Eline *= p(10.0, -dz*(j-k)*SI/10.0);

else

Eline *= p(10.0, dz*(k-j)*Su/10.0);

denom = 0;

for(u=0;u<j;u++)

denom += p(10.0, -dz*(j-u)*SI/10.0);

for(u=j;u<bark;u++)

denom += p(10.0, dz*(u-j)*Su/10.0);

Eline /= denom;

sum1 += p(Eline, 0.4);

}

// Eline (tilde)

for(j=0;j<bark;j++) {

Su=-24.0-230.0/fC[j]; //L = 0

if(k < j)

Eline = p(10.0, -dz*(j-k)*SI/10.0);

else

Eline = p(10.0, dz*(k-j)*Su/10.0);

denom = 0;

for(u=0;u<j;u++)

denom += p(10.0, -dz*(j-u)*SI/10.0);

for(u=j;u<bark;u++)

denom += p(10.0, dz*(u-j)*(-24.0-230.0/fC[j])/10.0);

Eline /= denom;

sum2 += p(Eline, 0.4);

}

sum2 = p(sum2, 1.0/0.4);

sum1 = p(sum1, 1.0/0.4);

e2[k] = sum1/sum2;

}

return 0;

}

Файл: threshold.h

#ifdef ADVANCED

#define dz 0.5

#else

#define dz 0.25

#endif

/* Function prototypes */

int threshold(double *, double *);

/* Prototypes end */

Файл: threshold.c

#include <stdlib.h>

#include <math.h>

#include <common.h>

#include <threshold.h>

extern int bark;

int

threshold(double *E, double *M)

{

int k;

double m;

for(k=0;k<bark;k++) {

if((m = k*dz) <= 12)

m = 3.0;

else

m *= 0.25;

M[k] = E[k]/p(10, m/10);

}

return 0;

}

Файл: timespreading.h

/* Function prototypes */

int timespreading(double *, double *, int, double *);

/* Prototypes end */

Файл: timespreading.c

#include <stdlib.h>

#include <math.h>

#include <common.h>

#include <timespreading.h>

#define T100 0.03

#defineTmin 0.008

extern int bark;

extern double *fC;

int

timespreading(double *E2, double *Etmp, int rate, double *E)

{

int k;

double a, T;

for(k=0;k<bark;k++) {

T = (double)Tmin + (double)(100.0/fC[k])*(double)(T100- Tmin);

a = exp((double)-HANN/(double)(T*2.0*rate));

Etmp[k] = Etmp[k]*a + (1.0-a)*E2[k];

if(Etmp[k] >= E2[k])

E[k] = Etmp[k];

else

E[k] = E2[k];

}

return 0;

}

Файл: wavedump.h

/* Function prototypes */

int HeaderDump(FILE *, const char *);

int Readlnt(FILE *, int);

int SampleRate(FILE *);

int BitForSample(FILE *);

int NumOfChan(FILE *);

int FindData(FILE *);

void fatalerr(char *,...);

/* Prototypes end */

Файл: wavedump.c

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <wavedump.h>

extern int errno;

int

HeaderDump(FILE *fp, const char*string)

{

char buff[7];

int k, offset = 0;

while (!feof(fp)) {

if(!fread(buff, 7, 1,fp))

fatalerr("err: error in WaveHeader");

offset += 7;

for(k=0;k<4;k++)

if (!strncmp((char *)(buff + k), string, 4)) {

fseek(fp, k-3, SEEK_CUR);

offset += k-3;

return offset;

}

fseek(fp, -3, SEEK_CUR);

offset += -3;

}

return -1;

}

int SampleRate(FILE *fp)

{

int rate, offset;

if ((offset = HeaderDump(fp,"fmt")) == -1)

return -1;

if (fseek(fp, 8, SEEK_CUR) == -1)

fatalerr("err: %s", strerror(errno));

rate = Readlnt(fp,4);

fseek(fp, -8 - offset, SEEK_CUR);

return rate;

}

int

BitForSample(FILE *fp)

{

int bit, offset;

if ((offset = HeaderDump(fp,"fmt")) == -1)

return -1;

if (fseek(fp, 18, SEEK_CUR) == -1)

fatalerr("err: %s", strerror(errno));

bit=Readlnt(fp,2);

fseek(fp, -18 - offset, SEEK_CUR);

return bit;

}

int

NumOfChan(FILE*fp)

{

int chan, offset;

if ((offset = HeaderDump(fp,"fmt")) == -1)

return -1;

if (fseek(fp, 6, SEEK_CUR) == -1)

fatalerr("err: %s", strerror(errno));

chan = Readlnt(fp,2);

fseek(fp, -6 - offset, SEEK_CUR);

return chan;

}

int

FindData(FILE *fp)

{

int offset;

if(fp == NULL)

return -1;

if ((offset = HeaderDump(fp,"data")) == -1)

return -1;

if (fseek(fp, 4 + offset, SEEK_CUR) == -1)

fatalerr("err: %s", strerror(errno));

return 1;

}

#if defined(LITTLE) && !defined(BIG)

int

Readlnt(FILE*fp, int size)

{

int I;

unsigned char c;

if (size <= 0)

return 0;

с = fgetc(fp);

I = ((int) c) & 255;

I | = (Readlnt(fp, size-1) << 8);

return I;

}

#elif defined(BIG) && !defined(LITTLE)

int

Readlnt(FILE*fp, int size)

{

int I;

if (size <= 0)

return 0;

I = (Readlnt(fp, size-1) << 8);

I | = ((int) fgetc(fp)) & 255;

return I;

}

#endif


Б.3 Листинг программы расчета метрики PSNR на языке Matlab

function PSNR = calcPSNR(X,Y)

% чем больше значение PNSR, тем более похожи сигналы

m = max(X);

d = var(X-Y);

R = m/sqrt(d);

PSNR = 20* log10(R);

end


Б.4 Листинг программы расчета метрики PSNR на языке C

#include <math.h>

double var(double* arr, int size)

{

if(!arr || !size)

return 0.0;

double v= 0.0;

double avg = 0.0;

for(int i = 0; i < size; ++i)

avg+= arr[i];

avg/= size;

for(int i = 0; i < size; ++i)

{

v+= (arr[i] - avg) * (arr[i] - avg);

}

return v/(size - 1);

}

double calcPSNR(double* X, int sizeX, double* Y, int sizeY )

{

if(!X || !sizeX || !Y || !sizeY || (sizeX != sizeY))

return 0.0;

double D[sizeX];

double maxX = X[0];

for(int i = 0; i < sizeX; ++i)

{

if(X[i] > maxX)

maxX = X[i];

D[i] = X[i] - Y[i];

}

double v = var(D, sizeX);

if(v == 0)

return 0.0;

return 20 * log10(maxX/sqrt(v));

}


Б.5 Листинг программы расчета метрики "Коэффициент различия форм сигналов" на языке Matlab

function val = calcMeasureBasedOnSingalsForms(X, Y)

% чем меньше результирующее значение, тем более похожи сигналы

X=X(:,1);

Y=Y(:,1);

dX=X(2:end) - X(1:end-1);

dY=Y(2:end) - Y(1:end-1);

val = var(dX-dY);

end


Б.6 Листинг программы расчета метрики "Коэффициент различия форм сигналов" на языке C

#include <math.h>

double var(double* arr, int size)

{

if(!arr || !size)

return 0.0;

double v= 0.0;

double avg = 0.0;

for(int i = 0; i < size; ++i)

avg+= arr[i];

avg/= size;

for(int i = 0; i < size; ++i)

{

v+= (arr[i] - avg) * (arr[i] - avg);

}

return v / (size - 1);

}

double calcMeasureBasedOnSingalsForms(double*X, int sizeX, double* Y, int sizeY )

{

if(!X || !sizeX || !Y || !sizeY || (sizeX != sizeY))

return 0.0;

double dX[sizeX - 1];

double dY[sizeX - 1];

double D[sizeX - 1];

for(int i = 1; i < sizeX; ++i)

{

dX[i -1] = X[i] - X[i - 1];

dY[i -1] = Y[i] - Y[i - 1];

D[i -1] =dX[i - 1] - dY[i - 1];

}

return var(D, sizeX - 1);

}

УДК 621.398:006.354

ОКС 13.320

П77

ОКП 43 7200

Ключевые слова: системы охранные телевизионные, аудиоданные, аудиокомпрессия, аудиокодер, аудиодекодер, кодек аудиоданных

Электронный текст документа

и сверен по:

, 2015

Превью ГОСТ Р 56047-2014 Системы охранные телевизионные. Компрессия оцифрованных аудиоданных. Классификация. Общие требования и методы оценки алгоритмов