представлять 2 образца sint16s как один образец uint32 - PullRequest
1 голос
/ 26 ноября 2010

Мой вопрос связан с этим вопросом, но он обратный.

Разделить UInt32 (аудиокадр) на две SInt16 (слева и справа)?

Inссылка над операцией хотела разделить 32-битный кадр на 2 16-битные выборки (левая и правая).

У меня есть 2 16-битные выборки, и я хотел бы выразить их как один 32-битный чередующийся кадр.

То, что я пытался сделать до сих пор, выглядит следующим образом.

UInt32* ar = malloc(totalFramesInFile * sizeof (ar));

for (int b=0; b < totalFramesInFile; b++)
{
  UInt32 l = soundStructArray[audioFile].audioDataLeft[b];
  UInt32 r = soundStructArray[audioFile].audioDataRight[b];

  UInt32 t = (UInt32) l + r;

  ar[b] = t;
}
soundStructArray[audioFile].audioData = ar;

Это законно и правильно?Я не уверен из-за моей неопытности.Мой аудиовыход звучит немного странно, и я пытаюсь в процессе устранения определить, что идет не так.

Было бы полезно, если бы кто-то мог подтвердить, что то, что я делаю, является правильным способом выражения 2 16-битных выборок в виде 32-битного кадра, или предложить правильный путь.

У меня естьощущение, что то, что я сделал, неправильно.Я думаю, что это потому, что первые 16 бит 32-битного кадра должны быть левыми, а вторые 16 бит должны быть правыми.Все это не должно быть суммой двух ...... Я думаю.

Ответы [ 2 ]

4 голосов
/ 26 ноября 2010

Вам необходимо изменить: *

UInt32 t = (UInt32) l + r;

на:

UInt32 t = (l << 16) | (r & 0xffff);

. Это ставит l в старшие 16 битов t и r в16 младших разрядов.

Подробное объяснение

Если у вас есть две 16-битные выборки, l и r, которые выглядят так в двоичном виде:

l: LLLLLLLLLLLLLLLL
r: RRRRRRRRRRRRRRRR

давайте сначала расширим их до 32 бит:

l: 0000000000000000LLLLLLLLLLLLLLLL
r: 0000000000000000RRRRRRRRRRRRRRRR

Теперь давайте сместим l влево на 16 бит (l << 16)

l: LLLLLLLLLLLLLLLL0000000000000000
r: 0000000000000000RRRRRRRRRRRRRRRR

Теперьдавайте ИЛИ (|) их вместе:

t: LLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRR

Вуаля! Теперь у вас есть l и r, объединенные в 32-битное значение, из которого их можно легко извлечьеще раз позже.

2 голосов
/ 26 ноября 2010

Я приму это как дополнение к ответу Пола Р., но это было слишком долго, чтобы добавить комментарий.

Альтернативное решение, которое может быть более "очевидным", - это явная установкаверхние или нижние 16-битные значения в 32-битном значении.Вы можете сделать это с помощью объединения, то есть

typedef union {
    struct {
        SInt16 high;
        SInt16 low;
    } parts;
    UInt32 word;
} IntConverter;

Использование:

IntConverter * ar = malloc(totalFramesInFile * sizeof (IntConverter));

for (int b=0; b < totalFramesInFile; b++)
{
    ar[b].parts.high = soundStructArray[audioFile].audioDataLeft[b];
    ar[b].parts.low = soundStructArray[audioFile].audioDataRight[b];
}
soundStructArray[audioFile].audioData = (UInt32 *) ar;

Однако этот подход требует, чтобы вы знали немного больше о базовой платформе, так как она зависит от того, какданные на самом деле хранятся в памяти.Однако, в зависимости от целевой платформы и компилятора, это может быть более эффективным.

...