Mono to Stereo conversion

后端 未结 5 1548
日久生厌
日久生厌 2021-01-02 20:25

I have the following issue here: I get a block of bytes (uint16_t*) representing audio data, and the device generating them is capturing mono sound, so obviously I have mono

相关标签:
5条回答
  • 2021-01-02 20:38

    If you just want interleaved stereo samples then you could use a function like this:

    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];
        }
    }
    

    To generate stereo from a single mono buffer then you would just pass the same pointer for in_L and in_R, e.g.

    interleave(mono_buffer, mono_buffer, stereo_buffer, num_samples);
    
    0 讨论(0)
  • 2021-01-02 20:50

    Pass to both channels the same pointer? If that violates restrict rules, use memcpy()?

    Sorry, but your question is otherwise to broad. API? OS? CPUArchitectures?

    0 讨论(0)
  • 2021-01-02 20:56

    You need to interleave the data, but if the frame length is anything greater than one, none of the above solutions will work. The below code can account for variable frame lengths.

    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 讨论(0)
  • 2021-01-02 20:57

    You might want to do the conversion in-place to save some memory. Depends on how small an amount of memory the device in question has. So you might want to use something like this instead of Paul R's approach:

    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];
        }
    }
    

    When getting the sound data from the mono device, you allocate a buffer that's twice as big as needed and pass that to the mono device. This will fill half the buffer with mono audio. You then pass that buffer to the above function, which converts it to stereo. And finally you pass the buffer to the stereo device. You save an extra allocation and thus use 33% less memory for the conversion.

    0 讨论(0)
  • 2021-01-02 21:01

    You are going to have to copy the buffer and duplicate it. As you haven't told us the format, how it is terminated, I can't give code, but it will look like a simple for loop.

    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;
    }
    

    forgive any glaring typos, my C is a bit rusty. typdef in whatever type you need for signed 16bit into int_16. Don't forget to free the copy buffer, or better yet reuse it.

    0 讨论(0)
提交回复
热议问题