如何改变PCM数据流的音量(实验失败)
已解决
我的代码以前从未用于处理有符号值,因此字节 ->短转换错误地处理了符号位。这样做正确地解决了问题。
问题是...
我正在尝试更改 PCM 数据流的音量。我可以从立体声文件中提取单通道数据,通过跳过/复制它们/插入零/等方式对样本进行各种愚蠢的实验效果,但我似乎找不到一种方法以任何方式修改实际样本值并获得合理的输出。
我的尝试非常简单: https://i.sstatic.net/CDJzi.png
- 源音频数据
- 值 - 10000 个
- 值 + 10000 个
- 值 * 0.9
- 个值 * 1.1
(值 = -value 工作正常 - 反转波,听起来是一样的)
执行此操作的代码同样简单(I/O 使用 0-65535 范围内的无符号值) <-- 这就是问题所在,正确读取有符号值解决了问题:
// NOTE: INVALID CODE
int sample = ...read unsigned 16 bit value from a stream...
sample -= 32768;
sample = (int)(sample * 0.9f);
sample += 32768;
...write unsigned 16 bit value to a stream...
// NOTE: VALID CODE
int sample = ...read *signed* 16 bit value from a stream...
sample = (int)(sample * 0.9f);
...write 16 bit value to a stream...
我正在努力使示例更安静。我想象减小振幅(样本 * 0.9)会产生更安静的文件,但上面的 4. 和 5. 显然都是无效的。有关于SO的类似问题< /a> 其中 MusiGenesis 说他使用“sample *= 0.75”类型的代码得到了正确的结果(是的,我确实尝试了除了 0.9 和 1.1 之外的其他值)。
问题是:我是在做一些愚蠢的事情还是乘以常数的整个想法是错误的?我希望最终结果是这样的: https://i.sstatic.net/Wspe9.png
Solved
My code was never before used for processing signed values and as such bytes -> short conversion was incorrectly handling the sign bit. Doing that properly solved the issue.
The question was...
I'm trying to change the volume of a PCM data stream. I can extract single channel data from a stereo file, do various silly experimental effects with the samples by skipping/duplicating them/inserting zeros/etc but I can't seem to find a way to modify actual sample values in any way and get a sensible output.
My attempts are really simple: https://i.sstatic.net/CDJzi.png
- source audio data
- values - 10000
- values + 10000
- values * 0.9
- values * 1.1
(value = -value works fine -- reverses the wave and it sounds the same)
The code to do this is equally simple (I/O uses unsigned values in range 0-65535) <-- that was the problem, reading properly signed values solved the issue:
// NOTE: INVALID CODE
int sample = ...read unsigned 16 bit value from a stream...
sample -= 32768;
sample = (int)(sample * 0.9f);
sample += 32768;
...write unsigned 16 bit value to a stream...
// NOTE: VALID CODE
int sample = ...read *signed* 16 bit value from a stream...
sample = (int)(sample * 0.9f);
...write 16 bit value to a stream...
I'm trying to make the sample quieter. I'd imagine making the amplitude smaller (sample * 0.9) would result in a quieter file but both 4. and 5. above are clearly invalid. There is a similar question on SO where MusiGenesis saying he got correct results with 'sample *= 0.75' type of code (yes, I did experiment with other values besides 0.9 and 1.1).
The question is: am I doing something stupid or is the whole idea of multiplying by a constant wrong? I'd like the end result to be something like this: https://i.sstatic.net/Wspe9.png
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的第四次尝试绝对是正确的方法。假设您的样本范围以 0 为中心,则可以将每个样本乘以另一个值来更改信号的音量或增益。
但在这种情况下,我猜当你将 int 乘以 float 并转换回 int 时,幕后会发生一些有趣的事情。在不知道您使用的语言的情况下很难说,但这可能就是导致问题的原因。
Your 4th attempt is definitely the the correct approach. Assuming your sample range is centered around 0, multiplying each sample by another value is how you can change the volume or gain of a signal.
In this case though, I'd guess something funny happening behind the scenes when you're multiplying an int by a float and casting back to int. Hard to say without knowing what language you're using, but that might be what's causing the problem.