OSDN Git Service

Merge "Move channel expansion/contraction functions to audio_utils/channels.h/.c...
authorPaul McLean <pmclean@google.com>
Fri, 18 Jul 2014 19:27:07 +0000 (19:27 +0000)
committerAndroid (Google) Code Review <android-gerrit@google.com>
Thu, 17 Jul 2014 21:15:46 +0000 (21:15 +0000)
1  2 
modules/usbaudio/audio_hw.c

@@@ -37,6 -37,8 +37,8 @@@
  
  #include <tinyalsa/asoundlib.h>
  
+ #include <audio_utils/channels.h>
  #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
  
  /* This is the default configuration to hand to The Framework on the initial
@@@ -225,263 -227,6 +227,6 @@@ static size_t convert_32_to_16(const in
  }
  
  /*
-  * Convert a buffer of N-channel, interleaved PCM16 samples to M-channel PCM16 channels
-  * (where N < M).
-  *   in_buff points to the buffer of PCM16 samples
-  *   in_buff_channels Specifies the number of channels in the input buffer.
-  *   out_buff points to the buffer to receive converted PCM16 samples.
-  *   out_buff_channels Specifies the number of channels in the output buffer.
-  *   num_in_bytes size of input buffer in BYTES
-  * returns
-  *   the number of BYTES of output data.
-  * NOTE
-  *   channels > N are filled with silence.
-  *   This conversion is safe to do in-place (in_buff == out_buff)
-  * We are doing this since we *always* present to The Framework as STEREO device, but need to
-  * support 4-channel devices.
-  * TODO Move this to a utilities module.
-  */
- static size_t expand_channels_16(const int16_t* in_buff, int in_buff_chans,
-                                  int16_t* out_buff, int out_buff_chans,
-                                  size_t num_in_bytes)
- {
-     /*
-      * Move from back to front so that the conversion can be done in-place
-      * i.e. in_buff == out_buff
-      * NOTE: num_in_samples * out_buff_channels must be an even multiple of in_buff_chans
-      */
-     size_t num_in_samples = num_in_bytes / sizeof(int16_t);
-     size_t num_out_samples = (num_in_samples * out_buff_chans) / in_buff_chans;
-     short* dst_ptr = out_buff + num_out_samples - 1;
-     size_t src_index;
-     const short* src_ptr = in_buff + num_in_samples - 1;
-     int num_zero_chans = out_buff_chans - in_buff_chans;
-     for (src_index = 0; src_index < num_in_samples; src_index += in_buff_chans) {
-         int dst_offset;
-         for (dst_offset = 0; dst_offset < num_zero_chans; dst_offset++) {
-             *dst_ptr-- = 0;
-         }
-         for (; dst_offset < out_buff_chans; dst_offset++) {
-             *dst_ptr-- = *src_ptr--;
-         }
-     }
-     /* return number of *bytes* generated */
-     return num_out_samples * sizeof(int16_t);
- }
- /*
-  * Convert a buffer of N-channel, interleaved PCM16 samples to M-channel PCM16 channels
-  * (where N > M).
-  *   in_buff points to the buffer of PCM16 samples
-  *   in_buff_channels Specifies the number of channels in the input buffer.
-  *   out_buff points to the buffer to receive converted PCM16 samples.
-  *   out_buff_channels Specifies the number of channels in the output buffer.
-  *   num_in_bytes size of input buffer in BYTES
-  * returns
-  *   the number of BYTES of output data.
-  * NOTE
-  *   channels > N are thrown away.
-  *   This conversion is safe to do in-place (in_buff == out_buff)
-  * We are doing this since we *always* present to The Framework as STEREO device, but need to
-  * support 4-channel devices.
-  * TODO Move this to a utilities module.
-  */
- static size_t contract_channels_16(const int16_t* in_buff, size_t in_buff_chans,
-                                    int16_t* out_buff, size_t out_buff_chans,
-                                    size_t num_in_bytes)
- {
-     /*
-      * Move from front to back so that the conversion can be done in-place
-      * i.e. in_buff == out_buff
-      * NOTE: num_in_samples * out_buff_channels must be an even multiple of in_buff_chans
-      */
-     size_t num_in_samples = num_in_bytes / sizeof(int16_t);
-     size_t num_out_samples = (num_in_samples * out_buff_chans) / in_buff_chans;
-     size_t num_skip_samples = in_buff_chans - out_buff_chans;
-     int16_t* dst_ptr = out_buff;
-     const int16_t* src_ptr = in_buff;
-     size_t src_index;
-     for (src_index = 0; src_index < num_in_samples; src_index += in_buff_chans) {
-         size_t dst_offset;
-         for (dst_offset = 0; dst_offset < out_buff_chans; dst_offset++) {
-             *dst_ptr++ = *src_ptr++;
-         }
-         src_ptr += num_skip_samples;
-     }
-     /* return number of *bytes* generated */
-     return num_out_samples * sizeof(int16_t);
- }
- /*
-  * Convert a buffer of N-channel, interleaved PCM32 samples to M-channel PCM32 channels
-  * (where N < M).
-  *   in_buff points to the buffer of PCM32 samples
-  *   in_buff_channels Specifies the number of channels in the input buffer.
-  *   out_buff points to the buffer to receive converted PCM32 samples.
-  *   out_buff_channels Specifies the number of channels in the output buffer.
-  *   num_in_bytes size of input buffer in BYTES
-  * returns
-  *   the number of BYTES of output data.
-  * NOTE
-  *   channels > N are filled with silence.
-  *   This conversion is safe to do in-place (in_buff == out_buff)
-  * We are doing this since we *always* present to The Framework as STEREO device, but need to
-  * support 4-channel devices.
-  * TODO Move this to a utilities module.
-  */
- static size_t expand_channels_32(const int32_t* in_buff, size_t in_buff_chans,
-                                  int32_t* out_buff, size_t out_buff_chans,
-                                  size_t num_in_bytes)
- {
-     /*
-      * Move from back to front so that the conversion can be done in-place
-      * i.e. in_buff == out_buff
-      * NOTE: num_in_samples * out_buff_channels must be an even multiple of in_buff_chans
-      */
-     size_t num_in_samples = num_in_bytes / sizeof(int32_t);
-     size_t num_out_samples = (num_in_samples * out_buff_chans) / in_buff_chans;
-     int32_t* dst_ptr = out_buff + num_out_samples - 1;
-     const int32_t* src_ptr = in_buff + num_in_samples - 1;
-     size_t num_zero_chans = out_buff_chans - in_buff_chans;
-     size_t src_index;
-     for (src_index = 0; src_index < num_in_samples; src_index += in_buff_chans) {
-         size_t dst_offset;
-         for (dst_offset = 0; dst_offset < num_zero_chans; dst_offset++) {
-             *dst_ptr-- = 0;
-         }
-         for (; dst_offset < out_buff_chans; dst_offset++) {
-             *dst_ptr-- = *src_ptr--;
-         }
-     }
-     /* return number of *bytes* generated */
-     return num_out_samples * sizeof(int32_t);
- }
- /*
-  * Convert a buffer of N-channel, interleaved PCM32 samples to M-channel PCM16 channels
-  * (where N > M).
-  *   in_buff points to the buffer of PCM32 samples
-  *   in_buff_channels Specifies the number of channels in the input buffer.
-  *   out_buff points to the buffer to receive converted PCM16 samples.
-  *   out_buff_channels Specifies the number of channels in the output buffer.
-  *   num_in_bytes size of input buffer in BYTES
-  * returns
-  *   the number of BYTES of output data.
-  * NOTE
-  *   channels > N are thrown away.
-  *   This conversion is safe to do in-place (in_buff == out_buff)
-  * We are doing this since we *always* present to The Framework as STEREO device, but need to
-  * support 4-channel devices.
-  * TODO Move this to a utilities module.
-  */
- static size_t contract_channels_32(const int32_t* in_buff, size_t in_buff_chans,
-                                    int32_t* out_buff, size_t out_buff_chans,
-                                    size_t num_in_bytes)
- {
-     /*
-      * Move from front to back so that the conversion can be done in-place
-      * i.e. in_buff == out_buff
-      * NOTE: num_in_samples * out_buff_channels must be an even multiple of in_buff_chans
-      */
-     size_t num_in_samples = num_in_bytes / sizeof(int32_t);
-     size_t num_out_samples = (num_in_samples * out_buff_chans) / in_buff_chans;
-     size_t num_skip_samples = in_buff_chans - out_buff_chans;
-     int32_t* dst_ptr = out_buff;
-     const int32_t* src_ptr = in_buff;
-     size_t src_index;
-     for (src_index = 0; src_index < num_in_samples; src_index += in_buff_chans) {
-         size_t dst_offset;
-         for (dst_offset = 0; dst_offset < out_buff_chans; dst_offset++) {
-             *dst_ptr++ = *src_ptr++;
-         }
-         src_ptr += num_skip_samples;
-     }
-     /* return number of *bytes* generated */
-     return num_out_samples * sizeof(int32_t);
- }
- static size_t contract_channels(const void* in_buff, size_t in_buff_chans,
-                                 void* out_buff, size_t out_buff_chans,
-                                 unsigned sample_size_in_bytes, size_t num_in_bytes)
- {
-     switch (sample_size_in_bytes) {
-     case 2:
-         return contract_channels_16((const int16_t*)in_buff, in_buff_chans,
-                                     (int16_t*)out_buff, out_buff_chans,
-                                     num_in_bytes);
-     /* TODO - do this conversion when we have a device to test it with */
-     case 3:
-         ALOGE("24-bit channel contraction not supported.");
-         return 0;
-     case 4:
-         return contract_channels_32((const int32_t*)in_buff, in_buff_chans,
-                                     (int32_t*)out_buff, out_buff_chans,
-                                     num_in_bytes);
-     default:
-         return 0;
-     }
- }
- static size_t expand_channels(const void* in_buff, size_t in_buff_chans,
-                                 void* out_buff, size_t out_buff_chans,
-                                 unsigned sample_size_in_bytes, size_t num_in_bytes)
- {
-     switch (sample_size_in_bytes) {
-     case 2:
-         return expand_channels_16((const int16_t*)in_buff, in_buff_chans,
-                                   (int16_t*)out_buff, out_buff_chans,
-                                   num_in_bytes);
-     /* TODO - do this conversion when we have a device to test it with */
-     case 3:
-         ALOGE("24-bit channel expansion not supported.");
-         return 0;
-     case 4:
-         return expand_channels_32((const int32_t*)in_buff, in_buff_chans,
-                                   (int32_t*)out_buff, out_buff_chans,
-                                   num_in_bytes);
-     default:
-         return 0;
-     }
- }
- static size_t adjust_channels(const void* in_buff, size_t in_buff_chans,
-                               void* out_buff, size_t out_buff_chans,
-                               unsigned sample_size_in_bytes, size_t num_in_bytes)
- {
-     if (out_buff_chans > in_buff_chans) {
-         return expand_channels(in_buff, in_buff_chans, out_buff,  out_buff_chans,
-                                sample_size_in_bytes, num_in_bytes);
-     } else if (out_buff_chans < in_buff_chans) {
-         return contract_channels(in_buff, in_buff_chans, out_buff,  out_buff_chans,
-                                  sample_size_in_bytes, num_in_bytes);
-     } else if (in_buff != out_buff) {
-         memcpy(out_buff, in_buff, num_in_bytes);
-     }
-     return num_in_bytes;
- }
- /*
   * ALSA Utilities
   */
  /*TODO This table and the function that uses it should be moved to a utilities module (probably) */
@@@ -671,59 -416,59 +416,59 @@@ static audio_format_t get_format_for_ma
  }
  
  /*
 - * Maps from bit position in pcm_mask to AUDIO_ format constants.
 + * Maps from bit position in pcm_mask to PCM_ format constants.
   */
 -static int const pcm_format_value_map[] = {
 +static int8_t const pcm_format_value_map[] = {
      PCM_FORMAT_S8,          /* 00 - SNDRV_PCM_FORMAT_S8 */
 -    0,                      /* 01 - SNDRV_PCM_FORMAT_U8 */
 +    PCM_FORMAT_INVALID,     /* 01 - SNDRV_PCM_FORMAT_U8 */
      PCM_FORMAT_S16_LE,      /* 02 - SNDRV_PCM_FORMAT_S16_LE */
 -    0,                      /* 03 - SNDRV_PCM_FORMAT_S16_BE */
 -    0,                      /* 04 - SNDRV_PCM_FORMAT_U16_LE */
 -    0,                      /* 05 - SNDRV_PCM_FORMAT_U16_BE */
 +    PCM_FORMAT_INVALID,     /* 03 - SNDRV_PCM_FORMAT_S16_BE */
 +    PCM_FORMAT_INVALID,     /* 04 - SNDRV_PCM_FORMAT_U16_LE */
 +    PCM_FORMAT_INVALID,     /* 05 - SNDRV_PCM_FORMAT_U16_BE */
      PCM_FORMAT_S24_3LE,     /* 06 - SNDRV_PCM_FORMAT_S24_LE */
 -    0,                      /* 07 - SNDRV_PCM_FORMAT_S24_BE */
 -    0,                      /* 08 - SNDRV_PCM_FORMAT_U24_LE */
 -    0,                      /* 09 - SNDRV_PCM_FORMAT_U24_BE */
 +    PCM_FORMAT_INVALID,     /* 07 - SNDRV_PCM_FORMAT_S24_BE */
 +    PCM_FORMAT_INVALID,     /* 08 - SNDRV_PCM_FORMAT_U24_LE */
 +    PCM_FORMAT_INVALID,     /* 09 - SNDRV_PCM_FORMAT_U24_BE */
      PCM_FORMAT_S32_LE,      /* 10 - SNDRV_PCM_FORMAT_S32_LE */
 -    0,                      /* 11 - SNDRV_PCM_FORMAT_S32_BE */
 -    0,                      /* 12 - SNDRV_PCM_FORMAT_U32_LE */
 -    0,                      /* 13 - SNDRV_PCM_FORMAT_U32_BE */
 -    0,                      /* 14 - SNDRV_PCM_FORMAT_FLOAT_LE */
 -    0,                      /* 15 - SNDRV_PCM_FORMAT_FLOAT_BE */
 -    0,                      /* 16 - SNDRV_PCM_FORMAT_FLOAT64_LE */
 -    0,                      /* 17 - SNDRV_PCM_FORMAT_FLOAT64_BE */
 -    0,                      /* 18 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE */
 -    0,                      /* 19 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE */
 -    0,                      /* 20 - SNDRV_PCM_FORMAT_MU_LAW */
 -    0,                      /* 21 - SNDRV_PCM_FORMAT_A_LAW */
 -    0,                      /* 22 - SNDRV_PCM_FORMAT_IMA_ADPCM */
 -    0,                      /* 23 - SNDRV_PCM_FORMAT_MPEG */
 -    0,                      /* 24 - SNDRV_PCM_FORMAT_GSM */
 -    0,                      /* 25 -> 30 (not assigned) */
 -    0,
 -    0,
 -    0,
 -    0,
 -    0,
 -    0,                      /* 31 - SNDRV_PCM_FORMAT_SPECIAL */
 +    PCM_FORMAT_INVALID,     /* 11 - SNDRV_PCM_FORMAT_S32_BE */
 +    PCM_FORMAT_INVALID,     /* 12 - SNDRV_PCM_FORMAT_U32_LE */
 +    PCM_FORMAT_INVALID,     /* 13 - SNDRV_PCM_FORMAT_U32_BE */
 +    PCM_FORMAT_INVALID,     /* 14 - SNDRV_PCM_FORMAT_FLOAT_LE */
 +    PCM_FORMAT_INVALID,     /* 15 - SNDRV_PCM_FORMAT_FLOAT_BE */
 +    PCM_FORMAT_INVALID,     /* 16 - SNDRV_PCM_FORMAT_FLOAT64_LE */
 +    PCM_FORMAT_INVALID,     /* 17 - SNDRV_PCM_FORMAT_FLOAT64_BE */
 +    PCM_FORMAT_INVALID,     /* 18 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE */
 +    PCM_FORMAT_INVALID,     /* 19 - SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE */
 +    PCM_FORMAT_INVALID,     /* 20 - SNDRV_PCM_FORMAT_MU_LAW */
 +    PCM_FORMAT_INVALID,     /* 21 - SNDRV_PCM_FORMAT_A_LAW */
 +    PCM_FORMAT_INVALID,     /* 22 - SNDRV_PCM_FORMAT_IMA_ADPCM */
 +    PCM_FORMAT_INVALID,     /* 23 - SNDRV_PCM_FORMAT_MPEG */
 +    PCM_FORMAT_INVALID,     /* 24 - SNDRV_PCM_FORMAT_GSM */
 +    PCM_FORMAT_INVALID,     /* 25 -> 30 (not assigned) */
 +    PCM_FORMAT_INVALID,
 +    PCM_FORMAT_INVALID,
 +    PCM_FORMAT_INVALID,
 +    PCM_FORMAT_INVALID,
 +    PCM_FORMAT_INVALID,
 +    PCM_FORMAT_INVALID,     /* 31 - SNDRV_PCM_FORMAT_SPECIAL */
      PCM_FORMAT_S24_3LE,     /* 32 - SNDRV_PCM_FORMAT_S24_3LE */ /* ??? */
 -    0,                      /* 33 - SNDRV_PCM_FORMAT_S24_3BE */
 -    0,                      /* 34 - SNDRV_PCM_FORMAT_U24_3LE */
 -    0,                      /* 35 - SNDRV_PCM_FORMAT_U24_3BE */
 -    0,                      /* 36 - SNDRV_PCM_FORMAT_S20_3LE */
 -    0,                      /* 37 - SNDRV_PCM_FORMAT_S20_3BE */
 -    0,                      /* 38 - SNDRV_PCM_FORMAT_U20_3LE */
 -    0,                      /* 39 - SNDRV_PCM_FORMAT_U20_3BE */
 -    0,                      /* 40 - SNDRV_PCM_FORMAT_S18_3LE */
 -    0,                      /* 41 - SNDRV_PCM_FORMAT_S18_3BE */
 -    0,                      /* 42 - SNDRV_PCM_FORMAT_U18_3LE */
 -    0,                      /* 43 - SNDRV_PCM_FORMAT_U18_3BE */
 -    0,                      /* 44 - SNDRV_PCM_FORMAT_G723_24 */
 -    0,                      /* 45 - SNDRV_PCM_FORMAT_G723_24_1B */
 -    0,                      /* 46 - SNDRV_PCM_FORMAT_G723_40 */
 -    0,                      /* 47 - SNDRV_PCM_FORMAT_G723_40_1B */
 -    0,                      /* 48 - SNDRV_PCM_FORMAT_DSD_U8 */
 -    0                       /* 49 - SNDRV_PCM_FORMAT_DSD_U16_LE */
 +    PCM_FORMAT_INVALID,     /* 33 - SNDRV_PCM_FORMAT_S24_3BE */
 +    PCM_FORMAT_INVALID,     /* 34 - SNDRV_PCM_FORMAT_U24_3LE */
 +    PCM_FORMAT_INVALID,     /* 35 - SNDRV_PCM_FORMAT_U24_3BE */
 +    PCM_FORMAT_INVALID,     /* 36 - SNDRV_PCM_FORMAT_S20_3LE */
 +    PCM_FORMAT_INVALID,     /* 37 - SNDRV_PCM_FORMAT_S20_3BE */
 +    PCM_FORMAT_INVALID,     /* 38 - SNDRV_PCM_FORMAT_U20_3LE */
 +    PCM_FORMAT_INVALID,     /* 39 - SNDRV_PCM_FORMAT_U20_3BE */
 +    PCM_FORMAT_INVALID,     /* 40 - SNDRV_PCM_FORMAT_S18_3LE */
 +    PCM_FORMAT_INVALID,     /* 41 - SNDRV_PCM_FORMAT_S18_3BE */
 +    PCM_FORMAT_INVALID,     /* 42 - SNDRV_PCM_FORMAT_U18_3LE */
 +    PCM_FORMAT_INVALID,     /* 43 - SNDRV_PCM_FORMAT_U18_3BE */
 +    PCM_FORMAT_INVALID,     /* 44 - SNDRV_PCM_FORMAT_G723_24 */
 +    PCM_FORMAT_INVALID,     /* 45 - SNDRV_PCM_FORMAT_G723_24_1B */
 +    PCM_FORMAT_INVALID,     /* 46 - SNDRV_PCM_FORMAT_G723_40 */
 +    PCM_FORMAT_INVALID,     /* 47 - SNDRV_PCM_FORMAT_G723_40_1B */
 +    PCM_FORMAT_INVALID,     /* 48 - SNDRV_PCM_FORMAT_DSD_U8 */
 +    PCM_FORMAT_INVALID      /* 49 - SNDRV_PCM_FORMAT_DSD_U16_LE */
  };
  
  /*
@@@ -734,7 -479,7 +479,7 @@@ static int get_pcm_format_for_mask(stru
      int num_slots = sizeof(mask->bits)/ sizeof(mask->bits[0]);
      int bits_per_slot = sizeof(mask->bits[0]) * 8;
  
 -    int table_size = sizeof(pcm_format_value_map) / sizeof(pcm_format_value_map[0]);
 +    int table_size = ARRAY_SIZE(pcm_format_value_map);
  
      int slot_index, bit_index, table_index;
      table_index = 0;
          unsigned bit_mask = 1;
          for (bit_index = 0; bit_index < bits_per_slot  && table_index < table_size; bit_index++) {
              if ((mask->bits[slot_index] & bit_mask) != 0) {
 +                /* TODO - we don't want a low-level function to be making this decision */
                  if (table_index != 0) { /* Don't pick 8-bit */
                      /* just return the first one */
 -                    return pcm_format_value_map[table_index];
 +                    return (int)pcm_format_value_map[table_index];
                  }
              }
              bit_mask <<= 1;
          }
      }
  
 -    return -1; /* error */
 +    return PCM_FORMAT_INVALID;
  }
  
  static bool test_out_sample_rate(struct audio_device_profile* dev_profile, unsigned rate) {
@@@ -932,7 -676,7 +677,7 @@@ static int read_alsa_device_config(stru
      config->period_count = pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIODS);
  
      int format = get_pcm_format_for_mask(pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT));
 -    if (format == -1) {
 +    if (format == PCM_FORMAT_INVALID) {
          ret = -EINVAL;
      } else {
          config->format = format;
@@@ -1659,8 -1403,7 +1404,8 @@@ static int adev_open_input_stream(struc
                                    audio_io_handle_t handle,
                                    audio_devices_t devices,
                                    struct audio_config *config,
 -                                  struct audio_stream_in **stream_in)
 +                                  struct audio_stream_in **stream_in,
 +                                  audio_input_flags_t flags __unused)
  {
      ALOGV("usb: in adev_open_input_stream() rate:%" PRIu32 ", chanMask:0x%" PRIX32 ", fmt:%" PRIu8,
            config->sample_rate, config->channel_mask, config->format);