[alsa-devel] S24_LE is 3 bytes ? in alsa-lib example pcm.c
Takashi Iwai
tiwai at suse.de
Thu Jul 10 18:30:22 CEST 2008
At Thu, 10 Jul 2008 12:19:05 +0200 (CEST),
Jaroslav Kysela wrote:
>
> On Thu, 10 Jul 2008, Clemens Ladisch wrote:
>
> > Norbert van Bolhuis wrote:
> > > as far as I know:
> > > sample format S24_LE is 24bit sample in 4 bytes
> > > sample format S24_3LE is 24bit sample in 3 bytes
> > > (why else have separate definitions), right ?
> >
> > Yes.
> >
> > > In the ALSA-LIb example /test/pcm.c however
> > > (http://www.alsa-project.org/alsa-doc/alsa-lib/_2test_2pcm_8c-example.html)
> > > there is no diff between the 2 sample formats.
> >
> > That example program uses snd_pcm_format_width() although it should
> > have used snd_pcm_format_physical_width() when calculating memory
> > buffer sizes.
>
> I think that the problem is in wrong area->step calculation in alsa-lib,
> but I'm still investigating where the real culprit is. The
> snd_pcm_format_width() is used only for sample filling (which is OK).
I think Clemens is right. The program uses snd_pcm_format_width()
wrongly. Also, it won't work properly with strict aliasing...
Untested patch is below.
Takashi
--
diff --git a/test/pcm.c b/test/pcm.c
index cd29259..ecd0afa 100644
--- a/test/pcm.c
+++ b/test/pcm.c
@@ -38,7 +38,10 @@ static void generate_sine(const snd_pcm_channel_area_t *areas,
unsigned char *samples[channels], *tmp;
int steps[channels];
unsigned int chn, byte;
- int ires;
+ union {
+ int i;
+ unsigned char c[4];
+ } ires;
unsigned int maxval = (1 << (snd_pcm_format_width(format) - 1)) - 1;
int bps = snd_pcm_format_width(format) / 8; /* bytes per sample */
@@ -59,8 +62,8 @@ static void generate_sine(const snd_pcm_channel_area_t *areas,
/* fill the channel areas */
while (count-- > 0) {
res = sin(phase) * maxval;
- ires = res;
- tmp = (unsigned char *)(&ires);
+ ires.i = res;
+ tmp = ires.c;
for (chn = 0; chn < channels; chn++) {
for (byte = 0; byte < (unsigned int)bps; byte++)
*(samples[chn] + byte) = tmp[byte];
@@ -868,7 +871,7 @@ int main(int argc, char *argv[])
if (verbose > 0)
snd_pcm_dump(handle, output);
- samples = malloc((period_size * channels * snd_pcm_format_width(format)) / 8);
+ samples = malloc((period_size * channels * snd_pcm_format_physical_width(format)) / 8);
if (samples == NULL) {
printf("No enough memory\n");
exit(EXIT_FAILURE);
@@ -881,8 +884,8 @@ int main(int argc, char *argv[])
}
for (chn = 0; chn < channels; chn++) {
areas[chn].addr = samples;
- areas[chn].first = chn * snd_pcm_format_width(format);
- areas[chn].step = channels * snd_pcm_format_width(format);
+ areas[chn].first = chn * snd_pcm_format_physical_width(format);
+ areas[chn].step = channels * snd_pcm_format_physical_width(format);
}
err = transfer_methods[method].transfer_loop(handle, samples, areas);
More information about the Alsa-devel
mailing list