Peter K.
Peter K.

Reputation: 134

fail init ALSA for 24bit file with SND_PCM_FORMAT_S24_3LE format

I am trying to playback 24bit wav file with 3-bytes sample allignment using ALSA (libasound.so.2). And ALSA fails on setting buffer size with Invalid argument error (and ALSA do not pass anything to drivers)

Here is wav file header content:

chunkId:       46464952                                         
chunkSize:     221417340                                        
format:        "WAVE"                                           
subchunk1Id:   "fmt "                                           
subchunk1Size: 40                                               
audioFormat:   fffe                                             
numChannels:   2                                                
sampleRate:    88200                                            
byteRate:      529200                                           
blockAlign:    6                                                
bitsPerSample: 24                                               
cbSize         16                                               
wValidBitsPerSample 18                                          
dwChannelMask  0                                                
SubFormat                                                       
subchunk2Id:   "data"                                           
subchunk2Size: 221417280

Unfortunately cannot provide proper test program source as it is part of cross-platform program and wount build separately. The shorten example might looks like

#include <stdio.h>                                                          
#include <stdint.h>                                                         
#include <sys/ioctl.h>                                                      
#include <sys/types.h>                                                      
#include <sys/stat.h>                                                       
#include <unistd.h>                                                         
#include <fcntl.h>                                                          
#include <errno.h>                                                          
#include <string.h>                                                         
#include <semaphore.h>                                                      
#include "asoundlib.h"                                                      

int main(int argc, char *argv[])
{                               
   int err = -1;                           /**< ALSA & clib function return code */
   snd_pcm_t *p_handle = NULL;             /**< pointer to active pcm object */    
   static const char *const p_device = "default";   /**< const pointer to const device id string */
   unsigned int sampleRate = 0;                                                                    
   unsigned int rbuffertime = 0;    /**< real buffer time as granted by ALSA */                    

   err = snd_pcm_open(&p_handle, p_device, SND_PCM_STREAM_PLAYBACK, 0);
   if (0 > err)                                                        
   {                                                                   
      printf("Playback open error: %s\n", snd_strerror(err));          
      return err;                                                      
   }                                                                   

   /* Get full range of possible hw params */
   err =  snd_pcm_hw_params_any(p_handle, p_hwparams);
   if (0 > err)                                       
   {                                                  
      printf("Error fetching hw param ranges: %s\n", snd_strerror(err));
      return err;                                                       
   }                                                                    

   // Specify a specific config out of configuration space and set it
   err = snd_pcm_hw_params_set_rate_resample(p_handle, p_hwparams, 1);
   if (0 > err)
   {
      printf("Unable to snd_pcm_hw_params_set_rate_resample for playback: %s\n", snd_strerror(err));
      return err;
   }

   err = snd_pcm_hw_params_set_access(p_handle, p_hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
   if (0 > err)
   {
      printf("Unable to snd_pcm_hw_params_set_access for playback: %s\n", snd_strerror(err));
      return err;
   }

   err = snd_pcm_hw_params_set_format(p_handle, p_hwparams, SND_PCM_FORMAT_S24_3LE);
   if (0 > err)
   {
      printf("Unable to snd_pcm_hw_params_set_format for playback: %s\n", snd_strerror(err));
      return err;
   }

   err = snd_pcm_hw_params_set_channels(p_handle, p_hwparams, 2);
   if (0 > err)
   {
      printf("Unable to snd_pcm_hw_params_set_channels for playback: %s\n", snd_strerror(err));
      return err;
   }

   sampleRate = 88200;
   err = snd_pcm_hw_params_set_rate_near(p_handle, p_hwparams, &sampleRate, 0);
   if (0 > err)
   {
      printf("Unable to snd_pcm_hw_params_set_rate for playback: %s\n", snd_strerror(err));
      return err;
   }

   rbuffertime = 500000;
   err = snd_pcm_hw_params_set_buffer_time_near(p_handle, p_hwparams, &rbuffertime, 0);
   if (0 > err)
   {
      printf("Unable to snd_pcm_hw_params_set_buffer_time_near for playback: %s\n", snd_strerror(err));
   }

   return err;
}

ALSA fails on snd_pcm_hw_params_set_buffer_time_near() call with error

ALSA ERROR hw_params: set_near (BUFFER_TIME)
           value = 500000 : Invalid argument
ACCESS:  RW_INTERLEAVED
FORMAT:  S24_3LE
SUBFORMAT:  STD
SAMPLE_BITS: 24
FRAME_BITS: 48
CHANNELS: 2
RATE: 88200
PERIOD_TIME: (476 247688)
PERIOD_SIZE: (42 21846)
PERIOD_BYTES: [256 131072]
PERIODS: [2 1024]
BUFFER_TIME: (495351 495352)
BUFFER_SIZE: 43690
BUFFER_BYTES: [262144 262140]
TICK_TIME: ALL

(ALSA even not attempts to pass any data to drivers, just fails on set buffer) That program works well for 16 bit audio.

I have tried different values of buffer (0.001 .. 1 second) however none of them works. Suppose I have missed any part of ALSA config required for 24 bit with 3LE, of maybe some check of previous init steps results?

Unfortunately I cannot find any example of ALSA usage for 24 bits, I would appreciate if You advice any link to example/recommendation/documentation.

EDITED

The result of aplay for this file is:

aplay -v /export/target/24bit_88.2kHz.wav
Playing WAVE '/export/target/24bit_88.2kHz.wav' : Signed 24 bit Little Endian in 3bytes, Rate 88200 Hz, Stereo
aplay: set_params:979: Sample format non available

Upvotes: 0

Views: 1142

Answers (0)

Related Questions