[alsa-devel] [PATCH - oss plugin update revised 1/2] oss: Add support of 32-bit and other formats
From: Alex Wiggins alex.d.wiggins@gmail.com
Added support of 32-bit and other audio formats via 3 changes:
- Additional audio format definitions at the top of the file (if required);
- Additional audio formats in oss_hw_params (to allow as input to pass to OSS);
- Additional audio formats in oss_hw_constraint (to allow to report to ALSA).
Signed-off-by: Alex Wiggins alex.d.wiggins@gmail.com
diff --git a/oss/pcm_oss.c b/oss/pcm_oss.c index d43b44c..d5b5bc4 100644 --- a/oss/pcm_oss.c +++ b/oss/pcm_oss.c @@ -24,6 +24,32 @@ #include <alsa/pcm_external.h> #include <linux/soundcard.h>
+/* definitions for additional OSS formats if required */ +#ifndef AFMT_S32_LE +#define AFMT_S32_LE 0x00001000 +#endif +#ifndef AFMT_S32_BE +#define AFMT_S32_BE 0x00002000 +#endif +#ifndef AFMT_S24_LE +#define AFMT_S24_LE 0x00008000 +#endif +#ifndef AFMT_S24_BE +#define AFMT_S24_BE 0x00010000 +#endif +#ifndef AFMT_S24_PACKED +#define AFMT_S24_PACKED 0x00040000 +#endif +#ifndef AFMT_FLOAT +#define AFMT_FLOAT 0x00004000 +#endif +#ifndef AFMT_SPDIF_RAW +#define AFMT_SPDIF_RAW 0x00020000 +#endif +#ifndef AFMT_VORBIS +#define AFMT_VORBIS 0x00000800 +#endif + typedef struct snd_pcm_oss { snd_pcm_ioplug_t io; char *device; @@ -165,6 +191,145 @@ static int oss_hw_params(snd_pcm_ioplug_t *io, case SND_PCM_FORMAT_S16_BE: oss->format = AFMT_S16_BE; break; + /* allow additional data formats (such as 32 bit) as input + to pass to OSS (set in OSS driver) */ + case SND_PCM_FORMAT_S32_LE: + oss->format = AFMT_S32_LE; + break; + case SND_PCM_FORMAT_S32_BE: + oss->format = AFMT_S32_BE; + break; + case SND_PCM_FORMAT_S8: + oss->format = AFMT_S8; + break; + case SND_PCM_FORMAT_U16_LE: + oss->format = AFMT_U16_LE; + break; + case SND_PCM_FORMAT_U16_BE: + oss->format = AFMT_U16_BE; + break; + case SND_PCM_FORMAT_S24_LE: + oss->format = AFMT_S24_LE; + break; + case SND_PCM_FORMAT_S24_BE: + oss->format = AFMT_S24_BE; + break; + case SND_PCM_FORMAT_MU_LAW: + oss->format = AFMT_MU_LAW; + break; + case SND_PCM_FORMAT_A_LAW: + oss->format = AFMT_A_LAW; + break; + case SND_PCM_FORMAT_IMA_ADPCM: + oss->format = AFMT_IMA_ADPCM; + break; + case SND_PCM_FORMAT_MPEG: + oss->format = AFMT_MPEG; + break; + case SND_PCM_FORMAT_S24_3LE: + oss->format = AFMT_S24_PACKED; + break; + case SND_PCM_FORMAT_FLOAT: + oss->format = AFMT_FLOAT; + break; + case SND_PCM_FORMAT_IEC958_SUBFRAME: + oss->format = AFMT_SPDIF_RAW; + break; + /* following formats need defining checking native endian: */ + #if 0 + case SND_PCM_FORMAT_S16: + oss->format = AFMT_S16_NE; + break; + case SND_PCM_FORMAT_U16: + oss->format = AFMT_U16_NE; + break; + case SND_PCM_FORMAT_S24: + oss->format = AFMT_S24_NE; + break; + case SND_PCM_FORMAT_S32: + oss->format = AFMT_S32_NE; + #endif + /* following formats found in ALSA but not in OSS: */ + #if 0 + case SND_PCM_FORMAT_U24_LE: + oss->format = AFMT_U24_LE; + break; + case SND_PCM_FORMAT_U24_BE: + oss->format = AFMT_U24_BE; + break; + case SND_PCM_FORMAT_U32_LE: + oss->format = AFMT_U32_LE; + break; + case SND_PCM_FORMAT_U32_BE: + oss->format = AFMT_U32_BE; + break; + case SND_PCM_FORMAT_FLOAT_LE: + oss->format = AFMT_FLOAT_LE; + break; + case SND_PCM_FORMAT_FLOAT_BE: + oss->format = AFMT_FLOAT_BE; + break; + case SND_PCM_FORMAT_FLOAT64_LE: + oss->format = AFMT_FLOAT64_LE; + break; + case SND_PCM_FORMAT_FLOAT64_BE: + oss->format = AFMT_FLOAT64_BE; + break; + case SND_PCM_FORMAT_IEC958_SUBFRAME_LE: + oss->format = AFMT_SPDIF_RAW_LE; + break; + case SND_PCM_FORMAT_IEC958_SUBFRAME_BE: + oss->format = AFMT_SPDIF_RAW_BE; + break; + case SND_PCM_FORMAT_GSM: + oss->format = AFMT_GSM; + break; + case SND_PCM_FORMAT_SPECIAL: + oss->format = AFMT_SPECIAL; + break; + case SND_PCM_FORMAT_S24_3BE: + oss->format = AFMT_S24_PACKED_BE; + break; + case SND_PCM_FORMAT_U24_3LE: + oss->format = AFMT_U24_PACKED; + break; + case SND_PCM_FORMAT_U24_3BE: + oss->format = AFMT_U24_PACKED_BE; + break; + case SND_PCM_FORMAT_S20_3LE: + oss->format = ; + break; + case SND_PCM_FORMAT_S20_3BE: + oss->format = ; + break; + case SND_PCM_FORMAT_U20_3LE: + oss->format = ; + break; + case SND_PCM_FORMAT_U20_3BE: + oss->format = ; + break; + case SND_PCM_FORMAT_S18_3LE: + oss->format = ; + break; + case SND_PCM_FORMAT_S18_3BE: + oss->format = ; + break; + case SND_PCM_FORMAT_U18_3LE: + oss->format = ; + break; + case SND_PCM_FORMAT_U18_3BE: + oss->format = ; + break; + case SND_PCM_FORMAT_U24: + oss->format = AFMT_U24_NE; + break; + case SND_PCM_FORMAT_U32: + oss->format = AFMT_U32_NE; + break; + case SND_PCM_FORMAT_FLOAT64: + oss->format = AFMT_FLOAT64; + break; + #endif default: fprintf(stderr, "*** OSS: unsupported format %s\n", snd_pcm_format_name(io->format)); return -EINVAL; @@ -239,7 +404,7 @@ static int oss_hw_constraint(snd_pcm_oss_t *oss) SND_PCM_ACCESS_MMAP_INTERLEAVED }; unsigned int nformats; - unsigned int format[5]; + unsigned int format[20]; unsigned int nchannels; unsigned int channel[6]; /* period and buffer bytes must be power of two */ @@ -273,6 +438,40 @@ static int oss_hw_constraint(snd_pcm_oss_t *oss) format[nformats++] = SND_PCM_FORMAT_S16_BE; if (tmp & AFMT_MU_LAW) format[nformats++] = SND_PCM_FORMAT_MU_LAW; + /* allow additional data formats (such as 32 bit) + to be reported from OSS to ALSA below */ + if (tmp & AFMT_S32_LE) + format[nformats++] = SND_PCM_FORMAT_S32_LE; + if (tmp & AFMT_S32_BE) + format[nformats++] = SND_PCM_FORMAT_S32_BE; + if (tmp & AFMT_A_LAW) + format[nformats++] = SND_PCM_FORMAT_A_LAW; + if (tmp & AFMT_IMA_ADPCM) + format[nformats++] = SND_PCM_FORMAT_IMA_ADPCM; + if (tmp & AFMT_S8) + format[nformats++] = SND_PCM_FORMAT_S8; + if (tmp & AFMT_U16_LE) + format[nformats++] = SND_PCM_FORMAT_U16_LE; + if (tmp & AFMT_U16_BE) + format[nformats++] = SND_PCM_FORMAT_U16_BE ; + if (tmp & AFMT_MPEG) + format[nformats++] = SND_PCM_FORMAT_MPEG; + if (tmp & AFMT_FLOAT) + format[nformats++] = SND_PCM_FORMAT_FLOAT; + if (tmp & AFMT_S24_LE) + format[nformats++] = SND_PCM_FORMAT_S24_LE; + if (tmp & AFMT_S24_BE) + format[nformats++] = SND_PCM_FORMAT_S24_BE; + if (tmp & AFMT_SPDIF_RAW) + format[nformats++] = SND_PCM_FORMAT_IEC958_SUBFRAME; + if (tmp & AFMT_S24_PACKED) + format[nformats++] = SND_PCM_FORMAT_S24_3LE; + /* following formats found in OSS but not in ALSA */ + if (tmp & AFMT_AC3) + format[nformats++] = SND_PCM_FORMAT_UNKNOWN; + if (tmp & AFMT_VORBIS) + format[nformats++] = SND_PCM_FORMAT_UNKNOWN; + /* assume signed 16 bit (native CPU endian) if not found above */ if (! nformats) format[nformats++] = SND_PCM_FORMAT_S16; if ((err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT,
Added support of 32-bit and other audio formats via 3 changes:
Additional audio format definitions at the top of the file (if required);
Additional audio formats in oss_hw_params (to allow as input to pass to OSS);
Additional audio formats in oss_hw_constraint (to allow to report to ALSA).
Signed-off-by: Alex Wiggins alex.d.wiggins@gmail.com
Do you mean that this patch allow OSS 4.0 enumlation if period size other than power 2 is supported ?
This part of the patch (oss plugin update revised 1/2) allows OSS emulation to work with audio formats other than 8-bit and 16-bit. Specifically, it allows this OSS emulation plugin to play 24-bit and 32-bit hires audio (provided that the OSS driver / soundcard supports it).
The other part of the patch (oss plugin update revised 2/2) allows the user to set the OSS buffer / period size config via the ALSA conf file. This was found to be useful during testing to improve performance (without setting this the default chosen values caused occasional empty buffer glitches, by choosing more optimal values these glitches were removed). The previous default behaviour (restrict to period size of power of 2) can be reinstated by setting period_size to negative. The new default behaviour is to query this period_size from OSS (and also check if it is a power of 2). Finally the user is able to force the period_size, periods and buffer_size (to any value) by specifying the variables in the ALSA conf file.
On 30 June 2013 02:13, Raymond Yau superquad.vortex2@gmail.com wrote:
Added support of 32-bit and other audio formats via 3 changes:
Additional audio format definitions at the top of the file (if required);
Additional audio formats in oss_hw_params (to allow as input to pass to OSS);
Additional audio formats in oss_hw_constraint (to allow to report to ALSA).
Signed-off-by: Alex Wiggins alex.d.wiggins@gmail.com
Do you mean that this patch allow OSS 4.0 enumlation if period size other than power 2 is supported ?
At Sun, 30 Jun 2013 01:47:07 +0100, alex.d.wiggins@gmail.com wrote:
From: Alex Wiggins alex.d.wiggins@gmail.com
Added support of 32-bit and other audio formats via 3 changes:
Additional audio format definitions at the top of the file (if required);
Additional audio formats in oss_hw_params (to allow as input to pass to OSS);
Additional audio formats in oss_hw_constraint (to allow to report to ALSA).
Signed-off-by: Alex Wiggins alex.d.wiggins@gmail.com
diff --git a/oss/pcm_oss.c b/oss/pcm_oss.c index d43b44c..d5b5bc4 100644 --- a/oss/pcm_oss.c +++ b/oss/pcm_oss.c @@ -24,6 +24,32 @@ #include <alsa/pcm_external.h> #include <linux/soundcard.h>
+/* definitions for additional OSS formats if required */ +#ifndef AFMT_S32_LE +#define AFMT_S32_LE 0x00001000 +#endif +#ifndef AFMT_S32_BE +#define AFMT_S32_BE 0x00002000 +#endif +#ifndef AFMT_S24_LE +#define AFMT_S24_LE 0x00008000 +#endif +#ifndef AFMT_S24_BE +#define AFMT_S24_BE 0x00010000 +#endif +#ifndef AFMT_S24_PACKED +#define AFMT_S24_PACKED 0x00040000 +#endif +#ifndef AFMT_FLOAT +#define AFMT_FLOAT 0x00004000 +#endif +#ifndef AFMT_SPDIF_RAW +#define AFMT_SPDIF_RAW 0x00020000 +#endif +#ifndef AFMT_VORBIS +#define AFMT_VORBIS 0x00000800 +#endif
typedef struct snd_pcm_oss { snd_pcm_ioplug_t io; char *device; @@ -165,6 +191,145 @@ static int oss_hw_params(snd_pcm_ioplug_t *io, case SND_PCM_FORMAT_S16_BE: oss->format = AFMT_S16_BE; break;
- /* allow additional data formats (such as 32 bit) as input
to pass to OSS (set in OSS driver) */
- case SND_PCM_FORMAT_S32_LE:
oss->format = AFMT_S32_LE;
break;
- case SND_PCM_FORMAT_S32_BE:
oss->format = AFMT_S32_BE;
break;
- case SND_PCM_FORMAT_S8:
oss->format = AFMT_S8;
break;
- case SND_PCM_FORMAT_U16_LE:
oss->format = AFMT_U16_LE;
break;
- case SND_PCM_FORMAT_U16_BE:
oss->format = AFMT_U16_BE;
break;
- case SND_PCM_FORMAT_S24_LE:
oss->format = AFMT_S24_LE;
break;
- case SND_PCM_FORMAT_S24_BE:
oss->format = AFMT_S24_BE;
break;
- case SND_PCM_FORMAT_MU_LAW:
oss->format = AFMT_MU_LAW;
break;
- case SND_PCM_FORMAT_A_LAW:
oss->format = AFMT_A_LAW;
break;
- case SND_PCM_FORMAT_IMA_ADPCM:
oss->format = AFMT_IMA_ADPCM;
break;
- case SND_PCM_FORMAT_MPEG:
oss->format = AFMT_MPEG;
break;
- case SND_PCM_FORMAT_S24_3LE:
oss->format = AFMT_S24_PACKED;
break;
- case SND_PCM_FORMAT_FLOAT:
oss->format = AFMT_FLOAT;
break;
- case SND_PCM_FORMAT_IEC958_SUBFRAME:
oss->format = AFMT_SPDIF_RAW;
break;
- /* following formats need defining checking native endian: */
- #if 0
Please align #if/#endif without indentation.
- case SND_PCM_FORMAT_S16:
oss->format = AFMT_S16_NE;
break;
- case SND_PCM_FORMAT_U16:
oss->format = AFMT_U16_NE;
break;
- case SND_PCM_FORMAT_S24:
oss->format = AFMT_S24_NE;
break;
- case SND_PCM_FORMAT_S32:
oss->format = AFMT_S32_NE;
- #endif
- /* following formats found in ALSA but not in OSS: */
- #if 0
- case SND_PCM_FORMAT_U24_LE:
oss->format = AFMT_U24_LE;
break;
- case SND_PCM_FORMAT_U24_BE:
oss->format = AFMT_U24_BE;
break;
- case SND_PCM_FORMAT_U32_LE:
oss->format = AFMT_U32_LE;
break;
- case SND_PCM_FORMAT_U32_BE:
oss->format = AFMT_U32_BE;
break;
- case SND_PCM_FORMAT_FLOAT_LE:
oss->format = AFMT_FLOAT_LE;
break;
- case SND_PCM_FORMAT_FLOAT_BE:
oss->format = AFMT_FLOAT_BE;
break;
- case SND_PCM_FORMAT_FLOAT64_LE:
oss->format = AFMT_FLOAT64_LE;
break;
- case SND_PCM_FORMAT_FLOAT64_BE:
oss->format = AFMT_FLOAT64_BE;
break;
- case SND_PCM_FORMAT_IEC958_SUBFRAME_LE:
oss->format = AFMT_SPDIF_RAW_LE;
break;
- case SND_PCM_FORMAT_IEC958_SUBFRAME_BE:
oss->format = AFMT_SPDIF_RAW_BE;
break;
- case SND_PCM_FORMAT_GSM:
oss->format = AFMT_GSM;
break;
- case SND_PCM_FORMAT_SPECIAL:
oss->format = AFMT_SPECIAL;
break;
- case SND_PCM_FORMAT_S24_3BE:
oss->format = AFMT_S24_PACKED_BE;
break;
- case SND_PCM_FORMAT_U24_3LE:
oss->format = AFMT_U24_PACKED;
break;
- case SND_PCM_FORMAT_U24_3BE:
oss->format = AFMT_U24_PACKED_BE;
break;
- case SND_PCM_FORMAT_S20_3LE:
oss->format = ;
break;
- case SND_PCM_FORMAT_S20_3BE:
oss->format = ;
break;
- case SND_PCM_FORMAT_U20_3LE:
oss->format = ;
break;
- case SND_PCM_FORMAT_U20_3BE:
oss->format = ;
break;
- case SND_PCM_FORMAT_S18_3LE:
oss->format = ;
break;
- case SND_PCM_FORMAT_S18_3BE:
oss->format = ;
break;
- case SND_PCM_FORMAT_U18_3LE:
oss->format = ;
break;
- case SND_PCM_FORMAT_U18_3BE:
oss->format = ;
break;
- case SND_PCM_FORMAT_U24:
oss->format = AFMT_U24_NE;
break;
- case SND_PCM_FORMAT_U32:
oss->format = AFMT_U32_NE;
break;
- case SND_PCM_FORMAT_FLOAT64:
oss->format = AFMT_FLOAT64;
break;
- #endif default: fprintf(stderr, "*** OSS: unsupported format %s\n", snd_pcm_format_name(io->format)); return -EINVAL;
@@ -239,7 +404,7 @@ static int oss_hw_constraint(snd_pcm_oss_t *oss) SND_PCM_ACCESS_MMAP_INTERLEAVED }; unsigned int nformats;
- unsigned int format[5];
- unsigned int format[20]; unsigned int nchannels; unsigned int channel[6]; /* period and buffer bytes must be power of two */
@@ -273,6 +438,40 @@ static int oss_hw_constraint(snd_pcm_oss_t *oss) format[nformats++] = SND_PCM_FORMAT_S16_BE; if (tmp & AFMT_MU_LAW) format[nformats++] = SND_PCM_FORMAT_MU_LAW;
- /* allow additional data formats (such as 32 bit)
to be reported from OSS to ALSA below */
- if (tmp & AFMT_S32_LE)
format[nformats++] = SND_PCM_FORMAT_S32_LE;
- if (tmp & AFMT_S32_BE)
format[nformats++] = SND_PCM_FORMAT_S32_BE;
- if (tmp & AFMT_A_LAW)
format[nformats++] = SND_PCM_FORMAT_A_LAW;
- if (tmp & AFMT_IMA_ADPCM)
format[nformats++] = SND_PCM_FORMAT_IMA_ADPCM;
- if (tmp & AFMT_S8)
format[nformats++] = SND_PCM_FORMAT_S8;
- if (tmp & AFMT_U16_LE)
format[nformats++] = SND_PCM_FORMAT_U16_LE;
- if (tmp & AFMT_U16_BE)
format[nformats++] = SND_PCM_FORMAT_U16_BE ;
- if (tmp & AFMT_MPEG)
format[nformats++] = SND_PCM_FORMAT_MPEG;
- if (tmp & AFMT_FLOAT)
format[nformats++] = SND_PCM_FORMAT_FLOAT;
- if (tmp & AFMT_S24_LE)
format[nformats++] = SND_PCM_FORMAT_S24_LE;
- if (tmp & AFMT_S24_BE)
format[nformats++] = SND_PCM_FORMAT_S24_BE;
- if (tmp & AFMT_SPDIF_RAW)
format[nformats++] = SND_PCM_FORMAT_IEC958_SUBFRAME;
- if (tmp & AFMT_S24_PACKED)
format[nformats++] = SND_PCM_FORMAT_S24_3LE;
- /* following formats found in OSS but not in ALSA */
- if (tmp & AFMT_AC3)
format[nformats++] = SND_PCM_FORMAT_UNKNOWN;
- if (tmp & AFMT_VORBIS)
format[nformats++] = SND_PCM_FORMAT_UNKNOWN;
This conversion to SND_PCM_FORMAT_UNKNOWN isn't useful at all...
- /* assume signed 16 bit (native CPU endian) if not found above */ if (! nformats) format[nformats++] = SND_PCM_FORMAT_S16; if ((err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT,
Other than these, the changes are OK.
But, looking at the patch again, it'd be cleaner to make a conversion table. It's up to you whether you fold it into the existing patch or give another refactoring patch on the top of existing patch.
thanks,
Takashi
Thanks again for the review Takashi.
What do you mean by making a conversion table? Do you mean like a 2-dimensional associative array to do the mapping? I'm not sure the best way of implementing something like that in C.
Best Regards,
Alex
On 1 July 2013 10:40, Takashi Iwai tiwai@suse.de wrote:
At Sun, 30 Jun 2013 01:47:07 +0100, alex.d.wiggins@gmail.com wrote:
From: Alex Wiggins alex.d.wiggins@gmail.com
Added support of 32-bit and other audio formats via 3 changes:
Additional audio format definitions at the top of the file (if required);
Additional audio formats in oss_hw_params (to allow as input to pass to OSS);
Additional audio formats in oss_hw_constraint (to allow to report to ALSA).
Signed-off-by: Alex Wiggins alex.d.wiggins@gmail.com
diff --git a/oss/pcm_oss.c b/oss/pcm_oss.c index d43b44c..d5b5bc4 100644 --- a/oss/pcm_oss.c +++ b/oss/pcm_oss.c @@ -24,6 +24,32 @@ #include <alsa/pcm_external.h> #include <linux/soundcard.h>
+/* definitions for additional OSS formats if required */ +#ifndef AFMT_S32_LE +#define AFMT_S32_LE 0x00001000 +#endif +#ifndef AFMT_S32_BE +#define AFMT_S32_BE 0x00002000 +#endif +#ifndef AFMT_S24_LE +#define AFMT_S24_LE 0x00008000 +#endif +#ifndef AFMT_S24_BE +#define AFMT_S24_BE 0x00010000 +#endif +#ifndef AFMT_S24_PACKED +#define AFMT_S24_PACKED 0x00040000 +#endif +#ifndef AFMT_FLOAT +#define AFMT_FLOAT 0x00004000 +#endif +#ifndef AFMT_SPDIF_RAW +#define AFMT_SPDIF_RAW 0x00020000 +#endif +#ifndef AFMT_VORBIS +#define AFMT_VORBIS 0x00000800 +#endif
typedef struct snd_pcm_oss { snd_pcm_ioplug_t io; char *device; @@ -165,6 +191,145 @@ static int oss_hw_params(snd_pcm_ioplug_t *io, case SND_PCM_FORMAT_S16_BE: oss->format = AFMT_S16_BE; break;
/* allow additional data formats (such as 32 bit) as input
to pass to OSS (set in OSS driver) */
case SND_PCM_FORMAT_S32_LE:
oss->format = AFMT_S32_LE;
break;
case SND_PCM_FORMAT_S32_BE:
oss->format = AFMT_S32_BE;
break;
case SND_PCM_FORMAT_S8:
oss->format = AFMT_S8;
break;
case SND_PCM_FORMAT_U16_LE:
oss->format = AFMT_U16_LE;
break;
case SND_PCM_FORMAT_U16_BE:
oss->format = AFMT_U16_BE;
break;
case SND_PCM_FORMAT_S24_LE:
oss->format = AFMT_S24_LE;
break;
case SND_PCM_FORMAT_S24_BE:
oss->format = AFMT_S24_BE;
break;
case SND_PCM_FORMAT_MU_LAW:
oss->format = AFMT_MU_LAW;
break;
case SND_PCM_FORMAT_A_LAW:
oss->format = AFMT_A_LAW;
break;
case SND_PCM_FORMAT_IMA_ADPCM:
oss->format = AFMT_IMA_ADPCM;
break;
case SND_PCM_FORMAT_MPEG:
oss->format = AFMT_MPEG;
break;
case SND_PCM_FORMAT_S24_3LE:
oss->format = AFMT_S24_PACKED;
break;
case SND_PCM_FORMAT_FLOAT:
oss->format = AFMT_FLOAT;
break;
case SND_PCM_FORMAT_IEC958_SUBFRAME:
oss->format = AFMT_SPDIF_RAW;
break;
/* following formats need defining checking native endian: */
#if 0
Please align #if/#endif without indentation.
case SND_PCM_FORMAT_S16:
oss->format = AFMT_S16_NE;
break;
case SND_PCM_FORMAT_U16:
oss->format = AFMT_U16_NE;
break;
case SND_PCM_FORMAT_S24:
oss->format = AFMT_S24_NE;
break;
case SND_PCM_FORMAT_S32:
oss->format = AFMT_S32_NE;
#endif
/* following formats found in ALSA but not in OSS: */
#if 0
case SND_PCM_FORMAT_U24_LE:
oss->format = AFMT_U24_LE;
break;
case SND_PCM_FORMAT_U24_BE:
oss->format = AFMT_U24_BE;
break;
case SND_PCM_FORMAT_U32_LE:
oss->format = AFMT_U32_LE;
break;
case SND_PCM_FORMAT_U32_BE:
oss->format = AFMT_U32_BE;
break;
case SND_PCM_FORMAT_FLOAT_LE:
oss->format = AFMT_FLOAT_LE;
break;
case SND_PCM_FORMAT_FLOAT_BE:
oss->format = AFMT_FLOAT_BE;
break;
case SND_PCM_FORMAT_FLOAT64_LE:
oss->format = AFMT_FLOAT64_LE;
break;
case SND_PCM_FORMAT_FLOAT64_BE:
oss->format = AFMT_FLOAT64_BE;
break;
case SND_PCM_FORMAT_IEC958_SUBFRAME_LE:
oss->format = AFMT_SPDIF_RAW_LE;
break;
case SND_PCM_FORMAT_IEC958_SUBFRAME_BE:
oss->format = AFMT_SPDIF_RAW_BE;
break;
case SND_PCM_FORMAT_GSM:
oss->format = AFMT_GSM;
break;
case SND_PCM_FORMAT_SPECIAL:
oss->format = AFMT_SPECIAL;
break;
case SND_PCM_FORMAT_S24_3BE:
oss->format = AFMT_S24_PACKED_BE;
break;
case SND_PCM_FORMAT_U24_3LE:
oss->format = AFMT_U24_PACKED;
break;
case SND_PCM_FORMAT_U24_3BE:
oss->format = AFMT_U24_PACKED_BE;
break;
case SND_PCM_FORMAT_S20_3LE:
oss->format = ;
break;
case SND_PCM_FORMAT_S20_3BE:
oss->format = ;
break;
case SND_PCM_FORMAT_U20_3LE:
oss->format = ;
break;
case SND_PCM_FORMAT_U20_3BE:
oss->format = ;
break;
case SND_PCM_FORMAT_S18_3LE:
oss->format = ;
break;
case SND_PCM_FORMAT_S18_3BE:
oss->format = ;
break;
case SND_PCM_FORMAT_U18_3LE:
oss->format = ;
break;
case SND_PCM_FORMAT_U18_3BE:
oss->format = ;
break;
case SND_PCM_FORMAT_U24:
oss->format = AFMT_U24_NE;
break;
case SND_PCM_FORMAT_U32:
oss->format = AFMT_U32_NE;
break;
case SND_PCM_FORMAT_FLOAT64:
oss->format = AFMT_FLOAT64;
break;
#endif default: fprintf(stderr, "*** OSS: unsupported format %s\n",
snd_pcm_format_name(io->format));
return -EINVAL;
@@ -239,7 +404,7 @@ static int oss_hw_constraint(snd_pcm_oss_t *oss) SND_PCM_ACCESS_MMAP_INTERLEAVED }; unsigned int nformats;
unsigned int format[5];
unsigned int format[20]; unsigned int nchannels; unsigned int channel[6]; /* period and buffer bytes must be power of two */
@@ -273,6 +438,40 @@ static int oss_hw_constraint(snd_pcm_oss_t *oss) format[nformats++] = SND_PCM_FORMAT_S16_BE; if (tmp & AFMT_MU_LAW) format[nformats++] = SND_PCM_FORMAT_MU_LAW;
/* allow additional data formats (such as 32 bit)
to be reported from OSS to ALSA below */
if (tmp & AFMT_S32_LE)
format[nformats++] = SND_PCM_FORMAT_S32_LE;
if (tmp & AFMT_S32_BE)
format[nformats++] = SND_PCM_FORMAT_S32_BE;
if (tmp & AFMT_A_LAW)
format[nformats++] = SND_PCM_FORMAT_A_LAW;
if (tmp & AFMT_IMA_ADPCM)
format[nformats++] = SND_PCM_FORMAT_IMA_ADPCM;
if (tmp & AFMT_S8)
format[nformats++] = SND_PCM_FORMAT_S8;
if (tmp & AFMT_U16_LE)
format[nformats++] = SND_PCM_FORMAT_U16_LE;
if (tmp & AFMT_U16_BE)
format[nformats++] = SND_PCM_FORMAT_U16_BE ;
if (tmp & AFMT_MPEG)
format[nformats++] = SND_PCM_FORMAT_MPEG;
if (tmp & AFMT_FLOAT)
format[nformats++] = SND_PCM_FORMAT_FLOAT;
if (tmp & AFMT_S24_LE)
format[nformats++] = SND_PCM_FORMAT_S24_LE;
if (tmp & AFMT_S24_BE)
format[nformats++] = SND_PCM_FORMAT_S24_BE;
if (tmp & AFMT_SPDIF_RAW)
format[nformats++] = SND_PCM_FORMAT_IEC958_SUBFRAME;
if (tmp & AFMT_S24_PACKED)
format[nformats++] = SND_PCM_FORMAT_S24_3LE;
/* following formats found in OSS but not in ALSA */
if (tmp & AFMT_AC3)
format[nformats++] = SND_PCM_FORMAT_UNKNOWN;
if (tmp & AFMT_VORBIS)
format[nformats++] = SND_PCM_FORMAT_UNKNOWN;
This conversion to SND_PCM_FORMAT_UNKNOWN isn't useful at all...
/* assume signed 16 bit (native CPU endian) if not found above */ if (! nformats) format[nformats++] = SND_PCM_FORMAT_S16; if ((err = snd_pcm_ioplug_set_param_list(io,
SND_PCM_IOPLUG_HW_FORMAT,
Other than these, the changes are OK.
But, looking at the patch again, it'd be cleaner to make a conversion table. It's up to you whether you fold it into the existing patch or give another refactoring patch on the top of existing patch.
thanks,
Takashi
At Sat, 6 Jul 2013 22:47:47 +0100, Alex Wiggins wrote:
Thanks again for the review Takashi.
What do you mean by making a conversion table? Do you mean like a 2-dimensional associative array to do the mapping? I'm not sure the best way of implementing something like that in C.
I don't mind any particular way as long as it's simple and readable. A typical implementation is like:
struct oss_format_cvt { unsigned int oss_format; unsigned int alsa_format; };
static struct oss_format_cvt format_cvts[] = { { AFMT_U8, SND_PCM_FORMAT_U8 }, { AFMT_S16_LE, SND_PCM_FORMAT_S16_LE }, .... };
....
static int oss_hw_params(snd_pcm_ioplug_t *io, snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED) { .... for (i = 0; i < ARRAY_SIZE(format_cvts); i++) { if (io->format == format_cvts[i].alsa_format) { oss->format = format_cvts[i].oss_format; break; } } if (i == ARRAY_SIZE(format_cvts)) { fprintf(stderr, "*** OSS: unsupported format %s\n", snd_pcm_format_name(io->format)); return -EINVAL; }
.... static int oss_hw_constraint(snd_pcm_oss_t *oss) { .... nformats = 0; for (i = 0; i < ARRAY_SIZE(format_cvts); i++) { if (tmp & format_cvts[i].oss_format) { if (nformats == ARRAY_SIZE(format)) ERROR(); format[nformats++] = format_cvts[i].alsa_format; } }
Takashi
Best Regards,
Alex
On 1 July 2013 10:40, Takashi Iwai tiwai@suse.de wrote:
At Sun, 30 Jun 2013 01:47:07 +0100, alex.d.wiggins@gmail.com wrote:
From: Alex Wiggins alex.d.wiggins@gmail.com
Added support of 32-bit and other audio formats via 3 changes:
Additional audio format definitions at the top of the file (if required);
Additional audio formats in oss_hw_params (to allow as input to pass to OSS);
Additional audio formats in oss_hw_constraint (to allow to report to ALSA).
Signed-off-by: Alex Wiggins alex.d.wiggins@gmail.com
diff --git a/oss/pcm_oss.c b/oss/pcm_oss.c index d43b44c..d5b5bc4 100644 --- a/oss/pcm_oss.c +++ b/oss/pcm_oss.c @@ -24,6 +24,32 @@ #include <alsa/pcm_external.h> #include <linux/soundcard.h>
+/* definitions for additional OSS formats if required */ +#ifndef AFMT_S32_LE +#define AFMT_S32_LE 0x00001000 +#endif +#ifndef AFMT_S32_BE +#define AFMT_S32_BE 0x00002000 +#endif +#ifndef AFMT_S24_LE +#define AFMT_S24_LE 0x00008000 +#endif +#ifndef AFMT_S24_BE +#define AFMT_S24_BE 0x00010000 +#endif +#ifndef AFMT_S24_PACKED +#define AFMT_S24_PACKED 0x00040000 +#endif +#ifndef AFMT_FLOAT +#define AFMT_FLOAT 0x00004000 +#endif +#ifndef AFMT_SPDIF_RAW +#define AFMT_SPDIF_RAW 0x00020000 +#endif +#ifndef AFMT_VORBIS +#define AFMT_VORBIS 0x00000800 +#endif
typedef struct snd_pcm_oss { snd_pcm_ioplug_t io; char *device; @@ -165,6 +191,145 @@ static int oss_hw_params(snd_pcm_ioplug_t *io, case SND_PCM_FORMAT_S16_BE: oss->format = AFMT_S16_BE; break;
/* allow additional data formats (such as 32 bit) as input
to pass to OSS (set in OSS driver) */
case SND_PCM_FORMAT_S32_LE:
oss->format = AFMT_S32_LE;
break;
case SND_PCM_FORMAT_S32_BE:
oss->format = AFMT_S32_BE;
break;
case SND_PCM_FORMAT_S8:
oss->format = AFMT_S8;
break;
case SND_PCM_FORMAT_U16_LE:
oss->format = AFMT_U16_LE;
break;
case SND_PCM_FORMAT_U16_BE:
oss->format = AFMT_U16_BE;
break;
case SND_PCM_FORMAT_S24_LE:
oss->format = AFMT_S24_LE;
break;
case SND_PCM_FORMAT_S24_BE:
oss->format = AFMT_S24_BE;
break;
case SND_PCM_FORMAT_MU_LAW:
oss->format = AFMT_MU_LAW;
break;
case SND_PCM_FORMAT_A_LAW:
oss->format = AFMT_A_LAW;
break;
case SND_PCM_FORMAT_IMA_ADPCM:
oss->format = AFMT_IMA_ADPCM;
break;
case SND_PCM_FORMAT_MPEG:
oss->format = AFMT_MPEG;
break;
case SND_PCM_FORMAT_S24_3LE:
oss->format = AFMT_S24_PACKED;
break;
case SND_PCM_FORMAT_FLOAT:
oss->format = AFMT_FLOAT;
break;
case SND_PCM_FORMAT_IEC958_SUBFRAME:
oss->format = AFMT_SPDIF_RAW;
break;
/* following formats need defining checking native endian: */
#if 0
Please align #if/#endif without indentation.
case SND_PCM_FORMAT_S16:
oss->format = AFMT_S16_NE;
break;
case SND_PCM_FORMAT_U16:
oss->format = AFMT_U16_NE;
break;
case SND_PCM_FORMAT_S24:
oss->format = AFMT_S24_NE;
break;
case SND_PCM_FORMAT_S32:
oss->format = AFMT_S32_NE;
#endif
/* following formats found in ALSA but not in OSS: */
#if 0
case SND_PCM_FORMAT_U24_LE:
oss->format = AFMT_U24_LE;
break;
case SND_PCM_FORMAT_U24_BE:
oss->format = AFMT_U24_BE;
break;
case SND_PCM_FORMAT_U32_LE:
oss->format = AFMT_U32_LE;
break;
case SND_PCM_FORMAT_U32_BE:
oss->format = AFMT_U32_BE;
break;
case SND_PCM_FORMAT_FLOAT_LE:
oss->format = AFMT_FLOAT_LE;
break;
case SND_PCM_FORMAT_FLOAT_BE:
oss->format = AFMT_FLOAT_BE;
break;
case SND_PCM_FORMAT_FLOAT64_LE:
oss->format = AFMT_FLOAT64_LE;
break;
case SND_PCM_FORMAT_FLOAT64_BE:
oss->format = AFMT_FLOAT64_BE;
break;
case SND_PCM_FORMAT_IEC958_SUBFRAME_LE:
oss->format = AFMT_SPDIF_RAW_LE;
break;
case SND_PCM_FORMAT_IEC958_SUBFRAME_BE:
oss->format = AFMT_SPDIF_RAW_BE;
break;
case SND_PCM_FORMAT_GSM:
oss->format = AFMT_GSM;
break;
case SND_PCM_FORMAT_SPECIAL:
oss->format = AFMT_SPECIAL;
break;
case SND_PCM_FORMAT_S24_3BE:
oss->format = AFMT_S24_PACKED_BE;
break;
case SND_PCM_FORMAT_U24_3LE:
oss->format = AFMT_U24_PACKED;
break;
case SND_PCM_FORMAT_U24_3BE:
oss->format = AFMT_U24_PACKED_BE;
break;
case SND_PCM_FORMAT_S20_3LE:
oss->format = ;
break;
case SND_PCM_FORMAT_S20_3BE:
oss->format = ;
break;
case SND_PCM_FORMAT_U20_3LE:
oss->format = ;
break;
case SND_PCM_FORMAT_U20_3BE:
oss->format = ;
break;
case SND_PCM_FORMAT_S18_3LE:
oss->format = ;
break;
case SND_PCM_FORMAT_S18_3BE:
oss->format = ;
break;
case SND_PCM_FORMAT_U18_3LE:
oss->format = ;
break;
case SND_PCM_FORMAT_U18_3BE:
oss->format = ;
break;
case SND_PCM_FORMAT_U24:
oss->format = AFMT_U24_NE;
break;
case SND_PCM_FORMAT_U32:
oss->format = AFMT_U32_NE;
break;
case SND_PCM_FORMAT_FLOAT64:
oss->format = AFMT_FLOAT64;
break;
#endif default: fprintf(stderr, "*** OSS: unsupported format %s\n",
snd_pcm_format_name(io->format));
return -EINVAL;
@@ -239,7 +404,7 @@ static int oss_hw_constraint(snd_pcm_oss_t *oss) SND_PCM_ACCESS_MMAP_INTERLEAVED }; unsigned int nformats;
unsigned int format[5];
unsigned int format[20]; unsigned int nchannels; unsigned int channel[6]; /* period and buffer bytes must be power of two */
@@ -273,6 +438,40 @@ static int oss_hw_constraint(snd_pcm_oss_t *oss) format[nformats++] = SND_PCM_FORMAT_S16_BE; if (tmp & AFMT_MU_LAW) format[nformats++] = SND_PCM_FORMAT_MU_LAW;
/* allow additional data formats (such as 32 bit)
to be reported from OSS to ALSA below */
if (tmp & AFMT_S32_LE)
format[nformats++] = SND_PCM_FORMAT_S32_LE;
if (tmp & AFMT_S32_BE)
format[nformats++] = SND_PCM_FORMAT_S32_BE;
if (tmp & AFMT_A_LAW)
format[nformats++] = SND_PCM_FORMAT_A_LAW;
if (tmp & AFMT_IMA_ADPCM)
format[nformats++] = SND_PCM_FORMAT_IMA_ADPCM;
if (tmp & AFMT_S8)
format[nformats++] = SND_PCM_FORMAT_S8;
if (tmp & AFMT_U16_LE)
format[nformats++] = SND_PCM_FORMAT_U16_LE;
if (tmp & AFMT_U16_BE)
format[nformats++] = SND_PCM_FORMAT_U16_BE ;
if (tmp & AFMT_MPEG)
format[nformats++] = SND_PCM_FORMAT_MPEG;
if (tmp & AFMT_FLOAT)
format[nformats++] = SND_PCM_FORMAT_FLOAT;
if (tmp & AFMT_S24_LE)
format[nformats++] = SND_PCM_FORMAT_S24_LE;
if (tmp & AFMT_S24_BE)
format[nformats++] = SND_PCM_FORMAT_S24_BE;
if (tmp & AFMT_SPDIF_RAW)
format[nformats++] = SND_PCM_FORMAT_IEC958_SUBFRAME;
if (tmp & AFMT_S24_PACKED)
format[nformats++] = SND_PCM_FORMAT_S24_3LE;
/* following formats found in OSS but not in ALSA */
if (tmp & AFMT_AC3)
format[nformats++] = SND_PCM_FORMAT_UNKNOWN;
if (tmp & AFMT_VORBIS)
format[nformats++] = SND_PCM_FORMAT_UNKNOWN;
This conversion to SND_PCM_FORMAT_UNKNOWN isn't useful at all...
/* assume signed 16 bit (native CPU endian) if not found above */ if (! nformats) format[nformats++] = SND_PCM_FORMAT_S16; if ((err = snd_pcm_ioplug_set_param_list(io,
SND_PCM_IOPLUG_HW_FORMAT,
Other than these, the changes are OK.
But, looking at the patch again, it'd be cleaner to make a conversion table. It's up to you whether you fold it into the existing patch or give another refactoring patch on the top of existing patch.
thanks,
Takashi
[2 <text/html; ISO-8859-1 (quoted-printable)>]
participants (4)
-
Alex Wiggins
-
alex.d.wiggins@gmail.com
-
Raymond Yau
-
Takashi Iwai