Преобразование моно в стерео - PullRequest
6 голосов
/ 09 июня 2011

У меня есть следующая проблема: я получаю блок байтов (uint16_t *), представляющий аудиоданные, и устройство, генерирующее их, захватывает монофонический звук, поэтому, очевидно, у меня есть монофонические аудиоданные на 1 канале. Мне нужно передать эти данные на другое устройство, которое ожидает чередующиеся стереоданные (так, 2 канала). То, что я хочу сделать, это в основном дублировать 1 канал в данных, чтобы оба канала стереофонических данных содержали одинаковые байты. Можете ли вы указать мне эффективный алгоритм, делающий это?

Спасибо, е.

Ответы [ 5 ]

13 голосов
/ 09 июня 2011

Если вы просто хотите использовать чередующиеся стерео сэмплы, вы можете использовать такую ​​функцию:

void interleave(const uint16_t * in_L,     // mono input buffer (left channel)
                const uint16_t * in_R,     // mono input buffer (right channel)
                uint16_t * out,            // stereo output buffer
                const size_t num_samples)  // number of samples
{
    for (size_t i = 0; i < num_samples; ++i)
    {
        out[i * 2] = in_L[i];
        out[i * 2 + 1] = in_R[i];
    }
}

Для генерации стерео из одного монобуфера, вы просто передадите один и тот же указатель для in_L и in_R, например

interleave(mono_buffer, mono_buffer, stereo_buffer, num_samples);
2 голосов
/ 09 июня 2011

Пропустить на оба канала один и тот же указатель? Если это нарушает правила restrict, используйте memcpy()?

Извините, но ваш вопрос в противном случае широк. API? ОПЕРАЦИОННЫЕ СИСТЕМЫ? CPUArchitectures

1 голос
/ 13 июня 2014

Возможно, вы захотите выполнить преобразование на месте, чтобы сэкономить память. Зависит от того, насколько мал объем памяти у рассматриваемого устройства. Так что вы можете использовать что-то вроде этого вместо подхода Пола Р.

void interleave(uint16_t buf[], const int len)
{
    for (int i = len / 2 - 1, j = len - 1; i > 0; --i) {
        buf[j--] = buf[i];
        buf[j--] = buf[i];
    }
}

При получении звуковых данных с монофонического устройства вы выделяете буфер, который в два раза больше необходимого, и передаете его на монофоническое устройство. Это заполнит половину буфера моно аудио. Затем вы передаете этот буфер вышеупомянутой функции, которая преобразует его в стерео. И, наконец, вы передаете буфер на стерео устройство. Вы экономите дополнительное выделение и, таким образом, используете на 33% меньше памяти для преобразования.

0 голосов
/ 06 июня 2019

Вам необходимо чередовать данные, но если длина кадра больше единицы, ни одно из приведенных выше решений не будет работать. Приведенный ниже код может учитывать переменную длину кадра.

void Interleave(BYTE* left, BYTE* right, BYTE* stereo,int numSamples_in, int frameSize)
{
    int writeIndex = 0;
    for (size_t j = 0; j < numSamples_in; j++)
    {
        for (int k = 0; k < frameSize; k++)
        {
            int index = j * frameSize + k;

            stereo[k + writeIndex] = left[index];
            stereo[k + writeIndex + frameSize] = right[index];
        }
        writeIndex += 2 * frameSize;
    }
}
0 голосов
/ 09 июня 2011

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

int_16* allocateInterleaved(int_16* data, int length)
  int i;
  int *copy = malloc(sizeof(int_16)*length*2);
  if(copy == NULL) {
    /* handle error */
  }
  for(i =0; i<length; i++) {
    copy[2*i] = data[i];
    copy[2*i+1] = data[i]; 
  }
  return copy;
}

простите за любые явные опечатки, мой C являетсянемного ржавыйtypedef любым типом, который вам нужен для подписанного 16-битного типа в int_16.Не забудьте освободить буфер копирования или, что еще лучше, повторно использовать его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...