Правильно ли предположить, что выборки с плавающей точкой в ​​файле WAV или AIFF будут нормализованы?

Скажем, у меня есть программа, которая читает файл.WAV или.AIFF, и аудио файла кодируется как значения сэмплов с плавающей точкой. Правильно ли для моей программы предполагать, что любой правильно сформированный (с плавающей запятой) файл.WAV или.AIFF будет содержать выборочные значения только в диапазоне [-1.0f,+1.0f]? Я не смог найти ничего в спецификациях WAV или AIFF, которые бы касались этого вопроса.

И если это неверное предположение, как можно узнать, каким должен был быть полный динамический диапазон звука в файле? (Я мог бы прочитать весь файл и выяснить, каковы действительные минимальное и максимальное значения образца, но есть две проблемы с этим: (1) это будет медленная / дорогая операция, если файл очень большой, и (2) это потеряло бы информацию, так как если бы создатель файла предполагал, что файл имеет некоторый "запас", чтобы он не воспроизводился на dbFS в самом громком месте, моя программа не смогла бы обнаружить это)

3 ответа

Решение

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

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

Основная причина того, что диапазон находится в интервале [-1, 1], заключается в том, что его можно быстро и легко масштабировать / преобразовывать в целевой битовый диапазон. Вам нужно только указать целевой диапазон и умножить.

Например:

Если вы хотите воспроизвести его в 16-битном режиме, вы должны это сделать (псевдо, предполагая, что знак округлен до целочисленного результата):

sample = in < 0 ? in * 0x8000 : in * 0x7fff;

или 24-битный:

sample = in < 0 ? in * 0x800000 : in * 0x7fffff;

или 8-битный:

sample = in < 0 ? in * 0x80 : in * 0x7f;

и т. д. без необходимости каким-либо образом корректировать исходное входное значение. -1 и 1 будут представлять минимальное / максимальное значение при преобразовании в целевое значение (1x = x).

Если бы вы использовали диапазон [-0,5, 0,5], вам сначала (или в какой-то момент) пришлось бы настроить входное значение, чтобы преобразование, например, в 16-битное, потребовало бы дополнительных шагов - это требует дополнительных затрат, не только для дополнительный шаг, но также, как мы бы работали в области с плавающей запятой, которую тяжелее вычислить (последний, возможно, является немного устаревшей причиной, поскольку обработка с плавающей запятой в наше время довольно быстрая, но в любом случае).

in = in * 2;
sample = in < 0 ? in * 0x8000 : in * 0x7fff;

Сохранение его в диапазоне [-1, 1], а не в некотором предварительно масштабированном диапазоне (например, [-32768, 32767]) также позволяет использовать больше битов для точности (используя представление IEEE 754).

ОБНОВЛЕНИЕ 2017/07

тесты

Основываясь на вопросах в комментариях, я решил провести тройную проверку, выполнив тест с использованием трех файлов с синусоидальным сигналом продолжительностью 1 секунда:

А) С плавающей точкой обрезается
Б) с плавающей точкой макс 0 дБ, и
C) целое число обрезается (преобразовано из A)

Файлы, которые затем сканируются на наличие положительных значений <= -1.0 и>= 1.0, начинаются после data поле чанка и размер, чтобы минимальные / максимальные значения отражали фактические значения, найденные в аудиоданных.

Результаты подтверждают, что диапазон действительно находится в диапазоне [-1, 1] включительно, если не отсечение (не соответствует истине <= 0 дБ).

Но это также выявило еще один аспект -

Файлы WAV, сохраненные как плавающие , допускают значения, превышающие диапазон 0 дБ. Это означает, что диапазон на самом деле превышает [-1, 1] для значений, которые обычно будут обрезаться.

Это может объясняться тем, что форматы с плавающей запятой предназначены для промежуточного использования в производственных установках из-за очень небольшой потери динамического диапазона, когда будущая обработка (усиление, сжатие, ограничение и т. Д.) Может вернуть значения (без потерь). в пределах конечного и нормального диапазона -0,2 - 0 дБ; и для этого сохраняет значения как есть.

В заключение

Файлы WAV, использующие плавающую точку, сохраняют значения в [-1, 1], когда не обрезается (<= 0 дБ), но допускают значения, которые считаются обрезанными

Но при преобразовании в целочисленный формат эти значения обрезаются на эквивалентный диапазон [-1, 1], масштабированный по битовому диапазону целочисленного формата, независимо. Это естественно из-за ограниченного диапазона, который может вместить каждая ширина.

Таким образом, программное обеспечение проигрывателя /DAW/edit будет обрабатывать обрезанные значения с плавающей запятой путем нормализации данных или простого возврата к [-1, 1].

file1
Примечания: Максимальные значения для всех файлов измеряются непосредственно из данных образца.

file2
Примечания: создается как обрезанное число с плавающей запятой (+6 дБ), затем преобразуется в 16-разрядный со знаком и возвращается в число с плавающей запятой

file3
Примечания: обрезается до +6 дБ

file4
Примечания: обрезается до +12 дБ

Простой тестовый скрипт и файлы можно найти здесь.

Я знаю, что вопрос не был специфичен для данного языка программирования или фреймворка, но я не смог найти ответ ни в одной спецификации. Что я могу сказать наверняка, так это то, что библиотека NAudio, которая широко используется для обработки файлов.WAV в приложениях, написанных для.NET Framework, предполагает, что образцы с плавающей точкой находятся в диапазоне [-1.0,+1.0].

Вот соответствующий код из его исходного кода:

namespace NAudio.Wave
{
    public class WaveFileReader : WaveStream
    {
        ...
        /// <summary>
        /// Attempts to read the next sample or group of samples as floating point normalised into the range -1.0f to 1.0f
        /// </summary>
        /// <returns>An array of samples, 1 for mono, 2 for stereo etc. Null indicates end of file reached
        /// </returns>
        public float[] ReadNextSampleFrame()
        {
            ...
            var sampleFrame = new float[waveFormat.Channels];
            int bytesToRead = waveFormat.Channels*(waveFormat.BitsPerSample/8);
            ...
            for (int channel = 0; channel < waveFormat.Channels; channel++)
            {
                if (waveFormat.BitsPerSample == 16)
                ...
                else if (waveFormat.BitsPerSample == 32 && waveFormat.Encoding == WaveFormatEncoding.IeeeFloat)
                {
                    sampleFrame[channel] = BitConverter.ToSingle(raw, offset);
                    offset += 4;
                }
                ...
            }
            return sampleFrame;
        }
        ...
    }
}

Таким образом, он просто копирует float в массив без каких-либо преобразований и обещает, что он находится в заданном диапазоне.

Да.

Форматы аудиофайлов действуют как носители для одного или нескольких каналов аудиоданных. Эти аудиоданные были закодированы с использованием определенного формата аудиокодирования. Каждый формат кодирования использует алгоритм кодера. Алгоритм является важной частью. Мы можем отмахнуться от значения файла и форматов кодирования.

AIFF и WAV используют импульсную кодовую модуляцию (PCM) или ее потомков. (Если вы посмотрите этот документ Oracle, вы заметите, что в "Encoding/CompressionType" списки алгоритмов на основе PCM.) PCM работает путем выборки синусоидальной волны аудио через фиксированные интервалы времени и выбора ближайшего цифрового представления. Важным моментом здесь является "синусоида".

Синусоидальные волны модулируют от -1 до 1, поэтому все кодировки, полученные из PCM, будут работать по этому принципу. Рассмотрим реализацию мю-закона: обратите внимание, что в его определяющем уравнении диапазон должен быть от -1 до 1.

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

Другие вопросы по тегам