Channel number conversion

Hi Daper,

I would like to ask, what does it mean this code convering mono->stereo.


/* Double the channels from */
static char *mono_to_stereo (const char *mono, const size_t size,
const long format)
{
int Bps = sfmt_Bps (format);
size_t i;
char *stereo;

stereo = (char *)xmalloc (size * 2);

for (i = 0; i < size; i += Bps) {
memcpy (stereo + (i * 2), mono + i, Bps);
memcpy (stereo + (i * 2 + Bps), mono + i, Bps);
}
return stereo;
}

I'm playing with pulseaudio and made this function duplicating stereo to 4 channel sound. But it seems very silly to me. Why is Bps added to second channel in mono_to_stereo? How would you construct general stereo to n-channels function? Do I have to split the stereo into separate channels and duplicate them?

Like stereo-> ch1,ch2
Quad-> f_left ch1, r_left ch1
Quad-> f_right ch2, r_right ch2


/* Quad the channels from */
static char *stereo_to_quad (const char *stereo, const size_t size,
const long format)
{
int Bps = sfmt_Bps (format);
size_t i;
char *quad;

quad = (char *)xmalloc (size * 2);

for (i = 0; i < size; i += Bps) {
memcpy (quad + (i * 2), stereo + i, Bps);
memcpy (quad + (i * 2 + Bps), stereo + i, Bps);
}
return quad;
}

Thanks

Bps means bytes per sample - the size of a sound sample. MOC (like most players) uses interleaved PCM format. It means that one sample stream (buffer) contains samples for all channels. For stereo they are in form: LRLRLRLT... where L is a sample for left speaker and R is a sample for right speaker. if you have mono sound in a buffer and want to convert to interleaved PCM buffer you must allocate twice as much space and double the sample for each channel. Thats what the memcpy does: it copies the sample (mono sample) to both channels. If all samples were 32 bit integer numbers the function would look like:

<br /> for (i = 0; i < size; i++) {<br /> stereo[i*2] = mono[i];<br /> stereo[i*2 + 1] = mono[i];<br /> }<br />

You must do similar job for 4-channel, but I'm not sure what is the order of channels in this format (I'm not even exactly sure for stereo if the first sample is left).

Thanx Daper,

I rewrote the function to n-channel support. Even (%2 == 0) number only. It's needless, but is there a possibility to get odd number?
(sorry I forgot the source at home)

Have a nice day
Nemozny

Like this:

<br /> /* Multiply the channels. The more, the better! */<br /> static char *stereo_multiply (const char *stereo, const size_t size,<br /> const int to_channels, const long format)<br /> {<br /> int Bps = sfmt_Bps (format);<br /> size_t i;<br /> char *output;</p> <p> int multiplier = to_channels / 2;<br /> output = (char *)xmalloc (size * multiplier);</p> <p> int iterate = 0;<br /> for (i = 0; i < size; i += Bps) {<br /> iterate = 0;<br /> while (iterate < multiplier) {<br /> memcpy (output + (i*multiplier + iterate*Bps),<br /> stereo + i, Bps);<br /> iterate++;<br /> }<br /> }</p> <p> return output;<br /> }<br />

If you want stereo to 3-channel conversion you should probably mix the two channels to create the center channel, but I'm only guessing. Mixing is also simple: it's the average value of allsource samples.