Как читать короткие (16 бит) целые числа из буфера без знака (8 бит)

Как и в заголовке, мне нужно прочитать короткие целые числа из буфера символов

Буфер

uint8_t *data[AV_NUM_DATA_POINTERS]

которая является полем AVFrame frame структура, заполняется при вызове функции ffmpeg

avcodec_decode_audio4(avctx,frame,got_frame_ptr,avpkt)

Но мне нужно прочитать этот буфер как буфер 16-разрядных целых чисел со знаком, потому что это примерный формат, указанный контекстом кодека
avctx-> sample_fmt == AV_SAMPLE_FMT_S16

Я попытался сделать это, используя memcpy, но мне не удалось получить разумные значения, поэтому я попытался использовать структуру объединения, как предложено для некоторых связанных вопросов здесь, в StackOverflow. Мой код выглядит следующим образом:
union CharToStruct {
uint8_t myCharArray [2];
короткое значение;
} presentSound;

 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
}

При этом значения являются разумными, но когда я записываю это на устройство с помощью portaudio, я получаю только щелчок. Я делаю преобразование неправильно? Можете ли вы помочь мне, возможно, с каким-то лучшим способом сделать это чтение?

Большое спасибо за Вашу помощь

Alba

0

Решение

Просто представьте себе массив uint8_t как необработанный байтовый массив. В C / C ++ unsigned char (uint8_t) настолько близок к массиву без типов, насколько это возможно. Любой тип данных может быть записан в массив любого типа в виде необработанных байтов, но проще всего взаимодействовать с массивом без знака, поскольку каждый элемент имеет значение от 0x00 до 0xFF (один байт), и пользователь может интерпретировать эти байты по своему усмотрению. ,

Вам может не потребоваться выполнять какую-либо интерпретацию данных самостоятельно, если вы просто передаете данные из ffmpeg в PortAudio. Обратный вызов PortAudio (или метод записи, если используется блокирующий API) требует, чтобы пользователь установил пустой указатель на начало воспроизводимого буфера данных. Неважно, к какому типу относится этот буфер, поскольку байты, если их читать по порядку, можно интерпретировать как ожидаемый примерный формат. На самом деле вам даже не нужно копировать данные, если вы можете передать указатель буфера на обратный вызов, и буфер не будет освобожден перед обработкой обратным вызовом. Остерегайтесь других проблем, таких как чтение монопотока и запись стереопотока. Если ваш выходной поток ожидает чередующегося стереозвука, вам придется записывать каждый семпл в выходной буфер дважды (или один раз для каждого ожидаемого канала).

С другой стороны, если вы хотите манипулировать сэмплами в буфере, вы можете захотеть переинтерпретировать ucast8_t * в короткий *. Поскольку данные в буфере уже подписаны 16-битными выборками, после того как вы приведете, каждый элемент в массиве будет одной выборкой данных. Просто помните, что размер массива будет только вдвое меньше исходного буфера, так как элементы в два раза больше.

Это должно быть абсолютно безопасно, и у вас не должно быть проблем с порядком байтов при перемещении семплов между ffmpeg и PortAudio, пока вы работаете в одной системе. Если в системе используется порядок байтов с прямым порядком байтов, то в сэмплах будет порядок байтов с прямым порядком байтов (старший байт в младшем адресе, Motorolla), если в системе используется младший байтовый порядок (младший байт в младшем адресе, Intel), то в семплах будет порядок байтов

0

Другие решения

Для меня это выглядит неправильно:

     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 байтов из существующего файла правильного формата [биты на выборку, выборки в секунду], затем количество выборок на выходе, и образцы после этого).

0

По вопросам рекламы [email protected]