[alsa-devel] [PATCH - oss plugin update revised 1/2] oss: Add support of 32-bit and other formats

Takashi Iwai tiwai at suse.de
Mon Jul 8 10:54:21 CEST 2013


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 at suse.de> wrote:
> 
> > At Sun, 30 Jun 2013 01:47:07 +0100,
> > alex.d.wiggins at gmail.com wrote:
> > >
> > > From: Alex Wiggins <alex.d.wiggins at 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 at 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)>]
> 


More information about the Alsa-devel mailing list