0

我有一个连接到 ATmega 微控制器的 MP3 板,该微控制器还连接到一个电位器。MP3 板直接通过其板载扬声器播放 MP3 数据,因此我还可以设置输出音量。

所以,正如你可能猜到的,我从 poti 读取值并将其转发给微控制器。不幸的是,微控制器不会以线性方式增加音量。因此,从值 0 到 128,您几乎听不到任何声音,而从 128 到 255(最大),音量会迅速增加。

我发现,下面的函数可以解决这个问题:

vol = 1 - (1 - x)^4

但 x 必须介于 0 和 1 之间,结果也介于 0 和 1 之间。

由于我在微控制器上,我想

  1. 转换这个公式,以便我可以将它与无符号整数一起使用
  2. 优化它(也许使用一些便宜的二进制函数),因为我每秒多次读取poti值。所以这个函数必须每秒计算多次,我也想用微控制器做其他事情;-)

也许你们中的一些人有一个想法?会很好!

 uint8_t linearize_volume(uint8_t value) {
     // ideas?
     // please don't use bigger data types than uint16_t
 }
4

3 回答 3

3

您可以用内存“支付” CPU 周期。如果你有 256 字节的 ROM 可用,那么计算这种功能的最便宜的方法就是建立一个查找表。

编写一个程序,用非线性函数的值打印 256 个 8 位数字的列表。程序有多快并不重要,因为您只会运行一次。将程序打印的数字作为数组初始值设定项复制到 C 程序中,然后执行查找而不是计算函数。

于 2013-06-23T19:11:01.160 回答
1

您可以通过将这些值视为 8.8 定点并通过二次平方提高到四次方来获得一个不错的估计值。

uint8_t linearize_volume(uint8_t value) {
    // Approximate 255 * (1 - (1 - x/255)^4)
    uint16_t x = 0xff - value;
    x = (x * x) >> 8;
    x = (x * x) >> 8;
    return 0xff - x;
}
于 2013-06-24T16:24:30.503 回答
0

首先,确保您使用的是线性电位器,而不是音频锥形电位器。

这是典型的音频输出。数据是正弦波,因此需要负值。您当然可以将负片转换为正片以获取其功率水平的唯一目的,但您无法在不听到完全不同的声音的情况下更改样本。

根据输出设备的不同,较低的值可能根本无法为扬声器提供足够的能量。

“MP3 板”应该包括无需更改样本即可控制音量的能力。

你说你读过底池并将其转发给微。你不是在用微型的 ADC 看底池吗?

于 2013-06-23T19:12:19.973 回答