[alsa-devel] Constraining the number of frames per period
I would like to make sure that all programs that use the sound driver I wrote are required to use 512 frames per period. Is there a snd_pcm_hw_constraint function that will allow me to do this? If not, is this possible another way?
Thanks, Adam
Adam Rosenberg Software Engineer
Alcorn McBride Inc. 3300 South Hiawassee Building 105 Orlando, FL 32835
(407) 296 - 5800 ext. 5490
On Thu, 21 Oct 2010, Adam Rosenberg wrote:
I would like to make sure that all programs that use the sound driver I wrote are required to use 512 frames per period. Is there a snd_pcm_hw_constraint function that will allow me to do this?
Just use periods_min and period_max = 512 in the hw structure. But why this constraint? It's better to use different ways in the driver (timers, etc) to leave reasonable range of the configuration space.
Jaroslav
----- Jaroslav Kysela perex@perex.cz Linux Kernel Sound Maintainer ALSA Project, Red Hat, Inc.
Jaroslav,
Thank you for the quick reply.
On Thu, Oct 21, 2010 at 10:50 AM, Jaroslav Kysela perex@perex.cz wrote:
On Thu, 21 Oct 2010, Adam Rosenberg wrote:
I would like to make sure that all programs that use the sound driver
I wrote are required to use 512 frames per period. Is there a snd_pcm_hw_constraint function that will allow me to do this?
Just use periods_min and period_max = 512 in the hw structure. But why this constraint? It's better to use different ways in the driver (timers, etc) to leave reasonable range of the configuration space.
I am trying to constrain the number of frames per period (not the number of periods). The DMA transfer creates an interrupt every 512 frames (1 frame = 16 channels with 32bits per channel) . I am having a difficult time understanding how to properly write the ALSA driver so that it will work with many different formats and between 1 and 2 channels. It seems as though I have to call snd_pcm_period_elapsed everytime I get a DMA interrupt to let the underlying code know that 512 frames have finished transferring. If the application does not select 512 frames per period, the audio plays too fast or too slow. Here is my best guess at what the hardware settings should be:
static struct snd_pcm_hardware ourCS42448PcmHw = { .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER ),
// Note: the CS42448 does not support 8 bit audio .formats = (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_BE | SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S16_BE),
// Sample rates supported // Note: this board has an ICS661 chip // that is being configured in init // so these values must match that setting #if CONFIG_CS42448_SAMPLE_RATE == 44100 .rates = SNDRV_PCM_RATE_44100, .rate_min = 44100, .rate_max = 44100, #else // default to 48000 .rates = SNDRV_PCM_RATE_48000, .rate_min = 48000, .rate_max = 48000, #endif
// the max number of bytes in one PCM stream // must allow for a minimum of 4 periods with // 512 frames per period and up to 2 channels of // 32 bit data per frame .buffer_bytes_max = 32768, // this value allows 8 periods of the max frame size
// the number of channels in one PCM stream .channels_min = 1, .channels_max = 2,
.period_bytes_max = 4096, .periods_min = 4, .period_bytes_min = 512, .periods_max = 64, };
Is there some way that I can impose a constraint on the number of frames in a period or is this the wrong solution to my problem?
Thanks, Adam
Adam Rosenberg Software Engineer
Alcorn McBride Inc. 3300 South Hiawassee Building 105 Orlando, FL 32835
(407) 296 - 5800 ext. 5490
Adam Rosenberg wrote:
I am trying to constrain the number of frames per period (not the number of periods). The DMA transfer creates an interrupt every 512 frames (1 frame = 16 channels with 32bits per channel) . I am having a difficult time understanding how to properly write the ALSA driver so that it will work with many different formats and between 1 and 2 channels.
Using period_bytes_min/max doesn't work for this situation; these fields are intended for hardware that has constraints on the number of bytes.
Set the snd_pcm_hardware fields so that all sample formats are supported. In the PCM devive's open callback, add another constraint by calling snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 512, 512);
// the max number of bytes in one PCM stream // must allow for a minimum of 4 periods with // 512 frames per period and up to 2 channels of // 32 bit data per frame .buffer_bytes_max = 32768, // this value allows 8 periods of the max frame size
Are the minimum 4 and maximum 8 periods actual hardware constraints?
Regards, Clemens
I am trying to constrain the number of frames per period (not the number of periods). The DMA transfer creates an interrupt every 512 frames (1 frame = 16 channels with 32bits per channel) . I am having a difficult time understanding how to properly write the ALSA driver so that it will work with many different formats and between 1 and 2 channels.
Using period_bytes_min/max doesn't work for this situation; these fields are intended for hardware that has constraints on the number of bytes.
Set the snd_pcm_hardware fields so that all sample formats are supported.
I do not understand why I need to add all of the sample formats, but I went ahead and changed snd_pcm_hardware to: .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_BE | SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_U24_3LE | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3BE | SNDRV_PCM_FMTBIT_S24_3BE | SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE),
In the PCM device's open callback, add another constraint by calling snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 512, 512);
Thank you! This worked as you described and the applications now select a period of 512 frames.
// the max number of bytes in one PCM stream // must allow for a minimum of 4 periods with // 512 frames per period and up to 2 channels of // 32 bit data per frame .buffer_bytes_max = 32768, // this value allows 8 periods of the max frame size
Are the minimum 4 and maximum 8 periods actual hardware constraints?
Not really. Mark Brown of WolfsonMicro helped me discover that I needed at least 3 periods so that there would always be one playing in the DMA buffer, one ready to play, and one able to be written to. I selected 4 periods as a minimum because it made it easier for me to figure out good sizes for the DMA buffer. There is no true hardware constraint on the max number of periods but I do need to keep my DMA period buffer size smaller than 64kb because the 2d transfer mode that is implemented by the blackfin BF537 sport driver (bf5xx-sport.c) doesn't seem to work properly. If I stay below 64kb it doesn't need to use 2d DMA mode.
I have had much better results after these changes but am still not 100% happy with the driver. There is still some choppiness when playing a wav file using aplay. It seems like there are some xrun conditions that occur just at the start of playback and then work themselves out. I am not sure if I have latest aplay because it came with the Blackfin distribution of uClinux. I'll look into it further. I also have some problems with the OSS emulation not working properly every time. I do not plan to use OSS in my actual application so I can ignore that for now.
Thank you Clemens and Jaroslav for your help. I will email again if I have any more questions.
-Adam
Adam Rosenberg wrote:
Set the snd_pcm_hardware fields so that all sample formats are supported.
I do not understand why I need to add all of the sample formats,
Sorry, I actually meant to say "all of the sample formats supported by your hardware", where "formats" includes all the field of the snd_pcm_hardware structure.
The idea is to set the snd_pcm_hardware fields so that anything supported by the hardware is allowed by these settings. Then, if there is any combination of settings that is allowed by these fields but not supported by the hardware, add more constraints in the open callback.
Regards, Clemens
participants (3)
-
Adam Rosenberg
-
Clemens Ladisch
-
Jaroslav Kysela