diff options
author | waker <wakeroid@gmail.com> | 2010-11-13 22:51:12 +0100 |
---|---|---|
committer | waker <wakeroid@gmail.com> | 2010-11-13 22:51:12 +0100 |
commit | 8eada3d6211baeac22c9d0f1977bc90f428247d5 (patch) | |
tree | 164053c4ce7cabb207976875b0026e180b75dc4c | |
parent | 7e2a8b73bc4ccf17e1be4163b003a249badd509e (diff) |
added channel remapping and some format conversions
-rw-r--r-- | plugins/alsa/alsa.c | 11 | ||||
-rw-r--r-- | premix.c | 154 |
2 files changed, 150 insertions, 15 deletions
diff --git a/plugins/alsa/alsa.c b/plugins/alsa/alsa.c index be744b34..31e179ae 100644 --- a/plugins/alsa/alsa.c +++ b/plugins/alsa/alsa.c @@ -191,7 +191,7 @@ palsa_set_hw_params (ddb_waveformat_t *fmt) { plugin.fmt.samplerate = val; trace ("chosen samplerate: %d Hz\n", val); - if ((err = snd_pcm_hw_params_set_channels (audio, hw_params, /*fmt->channels*/6)) < 0) { + if ((err = snd_pcm_hw_params_set_channels (audio, hw_params, fmt->channels)) < 0) { fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err)); goto error; @@ -218,6 +218,7 @@ palsa_set_hw_params (ddb_waveformat_t *fmt) { goto error; } + plugin.fmt.is_float = 0; switch (sample_fmt) { case SND_PCM_FORMAT_S8: plugin.fmt.bps = 8; @@ -234,10 +235,16 @@ palsa_set_hw_params (ddb_waveformat_t *fmt) { case SND_PCM_FORMAT_S32_LE: plugin.fmt.bps = 32; break; + case SND_PCM_FORMAT_FLOAT_LE: + case SND_PCM_FORMAT_FLOAT_BE: + plugin.fmt.bps = 32; + plugin.fmt.is_float = 1; + break; } + trace ("chosen bps: %d (%s)\n", plugin.fmt.bps, plugin.fmt.is_float ? "float" : "int"); + plugin.fmt.channels = nchan; - plugin.fmt.is_float = 0; plugin.fmt.is_multichannel = 0; plugin.fmt.channelmask = 0; if (nchan == 1) { @@ -26,9 +26,120 @@ #define trace(...) { fprintf(stderr, __VA_ARGS__); } //#define trace(fmt,...) -void -pcm_write_sample (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output) { - memcpy (output, input, 2); + +static inline void +pcm_write_samples_8_to_8 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) { + for (int s = 0; s < nsamples; s++) { + for (int c = 0; c < inputfmt->channels; c++) { + if (channelmap[c] != -1) { + *(output + (outputfmt->bps >> 3) * channelmap[c]) = *input; + } + input++; + } + output += outputsamplesize; + } +} + +static inline void +pcm_write_samples_8_to_16 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) { + for (int s = 0; s < nsamples; s++) { + for (int c = 0; c < inputfmt->channels; c++) { + if (channelmap[c] != -1) { + *((int16_t*)(output + (outputfmt->bps >> 3) * channelmap[c])) = (int16_t)(*input) << 8; + } + input++; + } + output += outputsamplesize; + } +} + +static inline void +pcm_write_samples_16_to_16 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) { + for (int s = 0; s < nsamples; s++) { + for (int c = 0; c < inputfmt->channels; c++) { + if (channelmap[c] != -1) { + *((int16_t*)(output + (outputfmt->bps >> 3) * channelmap[c])) = *((int16_t*)input); + } + input += 2; + } + output += outputsamplesize; + } +} + +static inline void +pcm_write_samples_16_to_8 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) { + for (int s = 0; s < nsamples; s++) { + for (int c = 0; c < inputfmt->channels; c++) { + if (channelmap[c] != -1) { + *((int8_t*)(output + (outputfmt->bps >> 3) * channelmap[c])) = *((int16_t*)input) >> 8; + } + input += 2; + } + output += outputsamplesize; + } +} + +static inline void +pcm_write_samples_16_to_24 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) { + for (int s = 0; s < nsamples; s++) { + for (int c = 0; c < inputfmt->channels; c++) { + if (channelmap[c] != -1) { + char *out = output + (outputfmt->bps >> 3) * channelmap[c]; + out[0] = 0; + out[1] = input[0]; + out[2] = input[1]; + } + input += 2; + } + output += outputsamplesize; + } +} + +static inline void +pcm_write_samples_16_to_32 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) { + for (int s = 0; s < nsamples; s++) { + for (int c = 0; c < inputfmt->channels; c++) { + if (channelmap[c] != -1) { + char *out = output + (outputfmt->bps >> 3) * channelmap[c]; + out[0] = 0; + out[1] = 0; + out[2] = input[0]; + out[3] = input[1]; + } + input += 2; + } + output += outputsamplesize; + } +} + +static inline void +pcm_write_samples_16_to_float (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) { + for (int s = 0; s < nsamples; s++) { + for (int c = 0; c < inputfmt->channels; c++) { + if (channelmap[c] != -1) { + float sample = (*((int16_t*)input)) / (float)0x7fff; + *((float *)(output + (outputfmt->bps >> 3) * channelmap[c])) = sample; + } + input += 2; + } + output += outputsamplesize; + } +} + +static inline void +pcm_write_samples_24_to_24 (const ddb_waveformat_t * restrict inputfmt, const char * restrict input, const ddb_waveformat_t * restrict outputfmt, char * restrict output, int nsamples, int * restrict channelmap, int outputsamplesize) { + for (int s = 0; s < nsamples; s++) { + for (int c = 0; c < inputfmt->channels; c++) { + if (channelmap[c] != -1) { + char *out = output + (outputfmt->bps >> 3) * channelmap[c]; + out[0] = input[0]; + out[1] = input[1]; + out[2] = input[2]; + } + input += 3; + } + output += outputsamplesize; + } } int @@ -50,7 +161,7 @@ pcm_convert (const ddb_waveformat_t * restrict inputfmt, const char * restrict i inputbitmask <<= 1; } if (!(inputfmt->channelmask & inputbitmask)) { - trace ("pcm_convert: channelmask doesn't correspond inputfmt (channels=%d, channelmask=%X)!", inputfmt->channels, inputfmt->channelmask); + trace ("pcm_convert: channelmask doesn't correspond inputfmt (channels=%d, channelmask=%X)!\n", inputfmt->channels, inputfmt->channelmask); break; } if (outputfmt->channelmask & inputbitmask) { @@ -66,7 +177,7 @@ pcm_convert (const ddb_waveformat_t * restrict inputfmt, const char * restrict i } outchannels |= outputbitmask; channelmap[i] = o; // input channel i going to output channel o - trace ("channelmap[%d]=%d\n", i, o); + //trace ("channelmap[%d]=%d\n", i, o); } inputbitmask <<= 1; } @@ -75,14 +186,31 @@ pcm_convert (const ddb_waveformat_t * restrict inputfmt, const char * restrict i // some of the channels are not used memset (output, 0, nsamples * outputsamplesize); } - for (int s = 0; s < nsamples; s++) { - for (int c = 0; c < inputfmt->channels; c++) { - if (channelmap[c] != -1) { - pcm_write_sample (inputfmt, input, outputfmt, output + (outputfmt->bps >> 3) * channelmap[c]); - } - input += inputfmt->bps >> 3; - } - output += outputsamplesize; + + // FIXME: access through function pointer table + if (inputfmt->bps == 8 && outputfmt->bps == 8) { + pcm_write_samples_8_to_8 (inputfmt, input, outputfmt, output, nsamples, channelmap, outputsamplesize); + } + if (inputfmt->bps == 8 && outputfmt->bps == 16) { + pcm_write_samples_8_to_16 (inputfmt, input, outputfmt, output, nsamples, channelmap, outputsamplesize); + } + if (inputfmt->bps == 16 && outputfmt->bps == 16) { + pcm_write_samples_16_to_16 (inputfmt, input, outputfmt, output, nsamples, channelmap, outputsamplesize); + } + else if (inputfmt->bps == 16 && outputfmt->bps == 8) { + pcm_write_samples_16_to_8 (inputfmt, input, outputfmt, output, nsamples, channelmap, outputsamplesize); + } + else if (inputfmt->bps == 16 && outputfmt->bps == 24) { + pcm_write_samples_16_to_24 (inputfmt, input, outputfmt, output, nsamples, channelmap, outputsamplesize); + } + else if (inputfmt->bps == 16 && outputfmt->bps == 32 && !outputfmt->is_float) { + pcm_write_samples_16_to_32 (inputfmt, input, outputfmt, output, nsamples, channelmap, outputsamplesize); + } + else if (inputfmt->bps == 16 && outputfmt->bps == 32 && outputfmt->is_float) { + pcm_write_samples_16_to_float (inputfmt, input, outputfmt, output, nsamples, channelmap, outputsamplesize); + } + else if (inputfmt->bps == 24 && outputfmt->bps == 24) { + pcm_write_samples_24_to_24 (inputfmt, input, outputfmt, output, nsamples, channelmap, outputsamplesize); } } return nsamples * outputsamplesize; |