You need to enable JavaScript to run this app. C语言中如何将存储PCM数据的int*数组转换为short*数组
优惠活动
大模型
产品
解决方案
定价
更多

C语言中如何将存储PCM数据的int*数组转换为short*数组

C语言下16位PCM数据 int数组转short实现

先修正现有代码的易踩坑点

  • 你当前malloc的尺寸逻辑存在冗余:data_size一般指代WAV文件中PCM段的实际字节长度,16位位深下单采样占2字节,你直接将data_size * sizeof(int)作为分配长度,会多分配2倍内存。虽然只要readPCM按实际数据长度写入不会直接崩溃,但后续转换时必须严格以data_size作为有效数据的长度依据,不能用分配的总内存长度计算采样数。
分场景实现方案

因为int*存储PCM的常见逻辑有两种,对应不同的转换写法:

场景1:readPCM接口将每个16位采样值直接存入int数组元素

这是音频读取接口最常用的封装逻辑:接口传入int*缓冲区时,会把对应位深的采样值(16位下范围是-32768 ~ 32767)存在每个int元素的低16位,高16位为符号扩展或无效填充。
这种场景下的转换代码:

#include <stdlib.h>

// 计算有效采样数:16位每采样占2字节
const long n_samples = data_size / 2;
short *pcm_short = (short*)malloc(n_samples * sizeof(short));
if (pcm_short == NULL) {
    // 内存分配失败,释放原有缓冲区后退出
    free(data);
    exit(EXIT_FAILURE);
}

// 逐元素转换
for (long i = 0; i < n_samples; i++) {
    int sample_val = data[i];
    // 边界钳位,避免值超出short的有效范围(和Java中short的范围一致)
    sample_val = sample_val > 32767 ? 32767 : sample_val;
    sample_val = sample_val < -32768 ? -32768 : sample_val;
    pcm_short[i] = (short)sample_val;
}

说明:如果确认readPCM写入的int值本身就没有超出16位范围,边界钳位的代码可以省略,直接强转赋值即可。

场景2:readPCM接口将原始PCM字节流直接写入int*内存

这种场景和你参考的Java逻辑完全对应:int*指向的内存本质是连续的PCM原始字节,没有按采样拆分,需要从连续字节中拼接出16位short值。
这种场景下的转换代码:

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

// 计算有效采样数
const long n_samples = data_size / 2;
short *pcm_short = (short*)malloc(n_samples * sizeof(short));
if (pcm_short == NULL) {
    free(data);
    exit(EXIT_FAILURE);
}

// 将int*指针转为字节指针,和Java中byte[]输入的逻辑对齐
unsigned char *raw_pcm_bytes = (unsigned char*)data;
for (long i = 0; i < n_samples; i++) {
    // 按WAV文件默认的小端序拼接采样:低字节在前,高字节在后
    unsigned char byte_low = raw_pcm_bytes[2 * i];
    unsigned char byte_high = raw_pcm_bytes[2 * i + 1];
    // 拼接为有符号short值
    pcm_short[i] = (short)(byte_low | (byte_high << 8));

    // 如果处理的是大端序PCM,替换为下面的拼接逻辑即可,和你Java参考的实现逻辑完全一致
    // pcm_short[i] = (short)(byte_high | (byte_low << 8));
}
通用注意事项
  • 转换完成后及时释放原int数组的内存,避免泄漏:free(data); data = NULL;
  • 不要直接将int指针强行强转为short使用,除非完全确认内存布局是连续的16位采样,否则会出现字节错位、采样值完全错乱的问题。
  • 所有循环的计数长度严格按data_size计算,不要用之前malloc的总内存长度作为依据,避免读取到未初始化的野值。

内容的提问来源于stack exchange,提问作者Subbir Rahman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.07 15:27:04