C++ 如何从无符号字符(8位)缓冲区读取短(16位)整数

C++ 如何从无符号字符(8位)缓冲区读取短(16位)整数,c++,casting,ffmpeg,short,portaudio,C++,Casting,Ffmpeg,Short,Portaudio,在标题中,我需要从字符缓冲区读取短整数 缓冲区 uint8_t *data[AV_NUM_DATA_POINTERS] 它是AVFrame结构的一个字段,由对ffmpeg函数的调用填充 avcodec_decode_audio4(avctx,frame,got_frame_ptr,avpkt) 但是,我需要将此缓冲区作为有符号16位整数的缓冲区读取,因为这是编解码器上下文指示的样本格式 avctx->sample\u fmt==AV\u sample\u fmt\u S16 我尝试使用mem

在标题中,我需要从字符缓冲区读取短整数

缓冲区

uint8_t *data[AV_NUM_DATA_POINTERS]
它是
AVFrame
结构的一个字段,由对ffmpeg函数的调用填充

avcodec_decode_audio4(avctx,frame,got_frame_ptr,avpkt)
但是,我需要将此缓冲区作为有符号16位整数的缓冲区读取,因为这是编解码器上下文指示的样本格式 avctx->sample\u fmt==AV\u sample\u fmt\u S16

我尝试使用memcpy来实现这一点,但我没有成功地获得合理的值,因此我尝试使用union结构,正如在StackOverflow中对一些相关问题所建议的那样。我的代码如下: 联合宪章组织{ uint8_t myCharArray[2]; 短期价值; }当前声音

 audioRet=avcodec_decode_audio4(avctx,frame,got_frame_ptr,avpkt);
 if(got_frame_ptr){
     audioRet=audioRet/2;
     int b=0;
     for(int i=0;i<audioRet;i++){
         presentSound.myCharArray[0]=frame->data[0][2*i+1];
         presentSound.myCharArray[1]=frame->data[0][2*i]
         dbuf[((i-b)/2)*8+info->mLeft+b]=info->presentSound.value;//the reason of the offset by 8 here is because I will be writing the result to a multichannel device
 }
audioRet=avcodec\u decode\u audio4(avctx,frame,got\u frame\u ptr,avpkt);
如果(得到帧){
audioRet=audioRet/2;
int b=0;
(int i=0;idata[0][2*i+1];
presentSound.myCharArray[1]=帧->数据[0][2*i]
dbuf[((i-b)/2)*8+info->mLeft+b]=info->presentSound.value;//这里偏移8的原因是我将把结果写入多通道设备
}
这样,值是合理的,但当我使用portaudio将其写入设备时,只会听到咔嗒声。我是否以错误的方式进行转换?你能帮我找到更好的方法来读取吗

非常感谢你的帮助


阿尔巴

在我看来,这似乎是错误的:

     presentSound.myCharArray[0]=frame->data[0][2*i+1];
     presentSound.myCharArray[1]=frame->data[0][2*i]
我希望看到:

     presentSound.myCharArray[0]=frame->data[0][2*i]
     presentSound.myCharArray[1]=frame->data[0][2*i+1];

将数据写入一个文件,并附加一个WAV头(从一个正确格式的现有文件中取前40个字节[每采样位,每秒采样数],然后是输出中的采样数,以及之后的采样数)。

只要把uint8\u t数组看作一个原始字节数组就行了。在C/C++无符号字符(uint8\t)中尽可能接近“无类型”数组。任何类型的数据都可以作为原始字节写入任何类型数组,但最容易与无符号字符数组交互,因为每个元素都是从0x00到0xFF(一个字节)的值,用户可以根据自己的选择解释这些字节

如果您只是将数据从ffmpeg传递到PortAudio.PortAudio的回调(或使用阻塞API的写入方法),则可能不需要自己对数据进行任何解释要求用户设置一个空指针,指向正在播放的数据缓冲区的开头。缓冲区的类型无关紧要,只要按顺序读取的字节可以解释为预期的样本格式。事实上,只要您能够将缓冲区指针传递到回调和在回调处理之前,缓冲区不会被释放。请注意其他问题,如读取单声道流和写入立体声流。如果输出流需要交错立体声音频,则必须将每个采样写入输出缓冲区两次(或每个通道一次)

另一方面,如果您希望处理缓冲区中的样本,您可能希望将uint8转换为短*。由于缓冲区中的数据已经是有符号的16位样本,一旦转换,数组中的每个元素将是一个数据样本。请记住,数组的大小将仅为原始bu的一半因为元素是原来的两倍大


这应该是完全安全的,并且只要您在单个系统上工作,在ffmpeg和PortAudio之间移动采样就不应该有任何endian问题。如果系统是big endian,则采样将是big endian(最低地址的高阶字节,Motorolla),如果系统是little endian(最低地址的低位字节,英特尔)示例将是little endian。

哦,谢谢,将结果写入wav文件是一个好主意,这样我就可以看到播放的声音是否如预期的那样。这个相关问题的答案建议将第一个字节放在第二个字节的前面,告诉大家最重要的一位是最后一个字节。但我也尝试了另一种方式将第一个字节放在第二个字节的前面[2*I]然后[2*i+1],我得到的数字太小了,我什么也听不见。