Как уменьшить громкость потока wav?

У меня есть flac-файл. Я хочу раскодировать его через команду "flac -dc", прочитать поток wav, который выводит команда, уменьшить громкость вдвое и вывести сигнал обратно. Вот мой фактический код:

#include <stdio.h>
#include <stdlib.h>

int main( int argc, char *argv[] ) {

   FILE *stream;
   int16_t normal, decreased;

   stream = popen( "/usr/bin/flac -dc 1.flac", "r" );

   while( feof( stream ) == 0 ) {

       normal = fgetc( stream );
       decreased = (int16_t) (normal * 0.5f);

       printf( "%c", decreased );
   }

   pclose( stream );

   return 0;
}

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

./myprogram | aplay -f dc

звук сильно искажен. Ситуация не изменится, если я попытаюсь декодировать mp3-файл с помощью команды «mpg123 -s». Что случилось?


person giuliom_95    schedule 27.10.2015    source источник


Ответы (1)


Вполне вероятно, что flac декодирует на разрядность выше 8 бит. В этом случае вам нужно будет собрать два байта в короткий, а затем умножить на усиление. Представьте себе 16-битный образец 0x7fff. При делении на два вы ожидаете, что результат будет 0x3fff. Но поскольку вы делите каждый байт отдельно, вы получите результат 0x3f7f. Еще одна проблема, на которую нужно обратить внимание, — это знак.

Непроверено, но что-то вроде этого должно работать для 16-битной подписи:

while( feof( stream ) == 0 ) {
    normal = (int16_t)((fgetc(stream) << 8) | (fgetc(stream));
    decreased = (int16_t) (normal * 0.5f);
}
person jaket    schedule 27.10.2015
comment
Спасибо за ответ, но я решил по-другому. Проблема заключалась в том, что функция fgetc возвращает беззнаковое целое число, даже если поток wav фактически подписан, поэтому, например (игнорируя дополнение до двух), если я разделил наполовину беззнаковый символ 178, то есть -50 в подписанном символе, я получил 89, а не -25, как и ожидалось. Решений на тот момент было два: либо заставить aplay принимать 8-битные данные без знака, либо заставить fgetc возвращать значение в переменной со знаком. Я выбрал второй путь. Теперь работает ровно. Однако спасибо за помощь. - person giuliom_95; 29.10.2015
comment
@giuliom_95. Вы должны убедиться, что данные имеют 8-битную подпись, а не 16-битную. Было бы необычно иметь 8-битные данные из flac или mp3. - person jaket; 29.10.2015