【问题标题】:How to reduce volume of wav stream?如何减少wav流的音量?
【发布时间】:2015-10-27 12:45:38
【问题描述】:

我有一个 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

声音严重失真。如果我尝试通过“mpg123 -s”命令解码 mp3 文件,情况不会改变。怎么了?

【问题讨论】:

    标签: audio wav flac


    【解决方案1】:

    flac 可能正在解码到高于 8 位的位深度。在这种情况下,您需要将两个字节组合成一个短字节,然后乘以增益。想象一下 0x7fff 的 16 位样本。除以 2 时,您会期望结果为 0x3fff。但是由于您分别划分每个字节,因此结果将是 0x3f7f。您需要注意的另一个问题是标志。

    未经测试,但类似这样的东西应该适用于 16 位签名:

    while( feof( stream ) == 0 ) {
        normal = (int16_t)((fgetc(stream) << 8) | (fgetc(stream));
        decreased = (int16_t) (normal * 0.5f);
    }
    

    【讨论】:

    • 感谢您的回答,但我已经以另一种方式解决了。问题是即使 wav 流实际上是有符号的,“fgetc”函数也会返回一个无符号整数,因此例如(忽略二进制补码)如果我将无符号字符 178 减半,即有符号字符中的 -50,我得到 89而不是预期的-25。此时的解决方案有两个:或者让 aplay 接受无符号的 8 位数据,或者将 fgetc 返回值强制到有符号变量中。我选择了第二条路。现在它工作顺利。不过感谢您的帮助。
    • @giuliom_95。您应该确定数据是 8 位签名的,而不是 16 位签名的。来自 flac 或 mp3 的 8 位数据是不寻常的。
    猜你喜欢
    • 1970-01-01
    • 2017-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-22
    • 1970-01-01
    • 2013-04-15
    相关资源
    最近更新 更多