Общий режим WASAPI: какую амплитуду ожидает звуковой движок?

Ранее я запутался с этим вопросом. Я сделал это так, как будто я спрашиваю о своей конкретной реализации, но на самом деле мой вопрос касается общей темы. Я вполне уверен, что моя реализация в порядке. Поэтому я переписываю этот вопрос:

WASAPI предоставляет мне информацию об аудиоформате, который звуковой движок принимает в общем режиме. Я знаю ожидаемую разрядность сэмплов, которые я передаю в буфер. Чего я не знаю, так это ожидаемого представления амплитуды сигнала в сэмплах. Например, если звуковой движок ожидает 32-битные сэмплы, означает ли это, что я должен представлять амплитуду синусоидальной волны? так как:

  • long в диапазоне [min, max]
  • unsigned long в диапазоне [0, max]
  • float в диапазоне [min, max]
  • или даже что-то вроде float в диапазоне [-1, 1]?

(max = std::numeric_limits<type>::max() и min = ...::min() в C++)

До сих пор я экспериментировал с этим с разными значениями методом проб и ошибок. Кажется, что только когда мои семплы содержат числа max/2 или -min/2 (как long) чередующиеся (вместе с другими числами), получается звук. Даже числа, близкие к этим (+- несколько целых чисел), дают одинаковые результаты. Когда этих двух чисел (или близких к ним чисел) нет в семплах, то получается тишина, что бы я ни делал.

Это может быть неважно, но я заметил, что битовое представление этих чисел (max/2 и min/2) (как longs) идентично IEEE float битному представлению 2.0 и -2.0. Мне до сих пор непонятно, почему это так работает.


person egst    schedule 25.08.2018    source источник


Ответы (2)


Типичное представление — это число с плавающей запятой от -1 до 1, масштабированное к представлению с фиксированной точкой. Для 32-битной подписи в идеале нужно, чтобы 1 отображалось на 0x7ffffffff, а -1 — на 0x8000000. Однако вы должны иметь в виду, что существует асимметрия вокруг 0, так что отрицательное значение на одно больше, чем положительное. Другими словами, вы не должны использовать 0x80000000, иначе вы рискуете переполниться с положительной стороны.

int xfixed = (int)(xfloat * 0x7fffffff);

Более явно:

int xfixed = (int)(xfloat * ((1<<(32-1)) - 1));
person jaket    schedule 27.08.2018
comment
Спасибо за ваше предложение и за объяснение проблемы переполнения. Я этого не понимал. Однако это не помогло. Я решил проблему и опубликую ее как ответ. - person egst; 28.08.2018

После более глубокого изучения структуры WAVEFORMATEXTENSIBLE я обнаружил, что нужная мне информация может храниться в свойстве SubFormat. В моем случае это было KSDATAFORMAT_SUBTYPE_IEEE_FLOAT. Таким образом, звуковой движок ожидал 32-битных floats в диапазоне [-1, +1]. По какой-то причине мой предыдущий тест со значениями с плавающей запятой не увенчался успехом, поэтому я продолжил попытки с целыми числами. Теперь простая синусоидальная функция в диапазоне [-1, +1] дает правильный результат. Есть некоторые сбои в звуке, но это может быть связано с некоторыми проблемами синхронизации при ожидании буфера.

person egst    schedule 28.08.2018