pcm_decode: add RAW format support

adds CONFIG_AUDIO_FORMAT_RAW as an option to the PCM
audio format for devices expecting raw data without
a header.

Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com>
This commit is contained in:
Alin Jerpelea 2020-10-07 10:12:55 +02:00 committed by Xiang Xiao
parent 19627095e4
commit 41b029876f
2 changed files with 69 additions and 55 deletions

View File

@ -86,6 +86,18 @@ config AUDIO_FORMAT_PCM
---help--- ---help---
Build in support for PCM Audio format. Build in support for PCM Audio format.
if AUDIO_FORMAT_PCM
config AUDIO_FORMAT_RAW
bool "Raw mode"
default n
---help---
Raw mode makes the PCM decoder skip trying to parse received
data for a PCM header. All data is sent to the audio driver
directly.
endif
config AUDIO_FORMAT_MP3 config AUDIO_FORMAT_MP3
bool "MPEG 3 Layer 1" bool "MPEG 3 Layer 1"
default y default y

View File

@ -151,8 +151,10 @@ static uint16_t pcm_leuint32(uint32_t value);
# define pcm_leuint32(v) (v) # define pcm_leuint32(v) (v)
#endif #endif
#ifndef CONFIG_AUDIO_FORMAT_RAW
static inline bool pcm_validwav(FAR const struct wav_header_s *wav); static inline bool pcm_validwav(FAR const struct wav_header_s *wav);
static bool pcm_parsewav(FAR struct pcm_decode_s *priv, uint8_t *data); static bool pcm_parsewav(FAR struct pcm_decode_s *priv, uint8_t *data);
#endif
#ifndef CONFIG_AUDIO_EXCLUDE_FFORWARD #ifndef CONFIG_AUDIO_EXCLUDE_FFORWARD
static void pcm_subsample_configure(FAR struct pcm_decode_s *priv, static void pcm_subsample_configure(FAR struct pcm_decode_s *priv,
@ -326,7 +328,7 @@ static uint16_t pcm_leuint32(uint32_t value)
* Return true if this is a valid WAV file header * Return true if this is a valid WAV file header
* *
****************************************************************************/ ****************************************************************************/
#ifndef CONFIG_AUDIO_FORMAT_RAW
static inline bool pcm_validwav(FAR const struct wav_header_s *wav) static inline bool pcm_validwav(FAR const struct wav_header_s *wav)
{ {
return (wav->hdr.chunkid == WAV_HDR_CHUNKID && return (wav->hdr.chunkid == WAV_HDR_CHUNKID &&
@ -423,6 +425,7 @@ static bool pcm_parsewav(FAR struct pcm_decode_s *priv, uint8_t *data)
return ret; return ret;
} }
#endif
/**************************************************************************** /****************************************************************************
* Name: pcm_subsample_configure * Name: pcm_subsample_configure
@ -1083,71 +1086,68 @@ static int pcm_enqueuebuffer(FAR struct audio_lowerhalf_s *dev,
audinfo("curbyte=%d nbytes=%d nmaxbytes=%d bytesleft=%d\n", audinfo("curbyte=%d nbytes=%d nmaxbytes=%d bytesleft=%d\n",
apb->curbyte, apb->nbytes, apb->nmaxbytes, bytesleft); apb->curbyte, apb->nbytes, apb->nmaxbytes, bytesleft);
if (bytesleft >= sizeof(struct wav_header_s)) /* Parse and verify the candidate PCM WAV file header */
#ifndef CONFIG_AUDIO_FORMAT_RAW
if (bytesleft >= sizeof(struct wav_header_s) &&
pcm_parsewav(priv, &apb->samp[apb->curbyte]))
{ {
/* Parse and verify the candidate PCM WAV file header */ struct audio_caps_s caps;
if (pcm_parsewav(priv, &apb->samp[apb->curbyte])) /* Configure the lower level for the number of channels, bitrate,
{ * and sample bitwidth.
struct audio_caps_s caps; */
/* Configure the lower level for the number of channels, bitrate, DEBUGASSERT(priv->samprate < 65535);
* and sample bitwidth.
*/
DEBUGASSERT(priv->samprate < 65535); caps.ac_len = sizeof(struct audio_caps_s);
caps.ac_type = AUDIO_TYPE_OUTPUT;
caps.ac_channels = priv->nchannels;
caps.ac_len = sizeof(struct audio_caps_s); caps.ac_controls.hw[0] = (uint16_t)priv->samprate;
caps.ac_type = AUDIO_TYPE_OUTPUT; caps.ac_controls.b[2] = priv->bpsamp;
caps.ac_channels = priv->nchannels;
caps.ac_controls.hw[0] = (uint16_t)priv->samprate;
caps.ac_controls.b[2] = priv->bpsamp;
#ifdef CONFIG_AUDIO_MULTI_SESSION #ifdef CONFIG_AUDIO_MULTI_SESSION
ret = lower->ops->configure(lower, priv->session, &caps); ret = lower->ops->configure(lower, priv->session, &caps);
#else #else
ret = lower->ops->configure(lower, &caps); ret = lower->ops->configure(lower, &caps);
#endif #endif
if (ret < 0) if (ret < 0)
{ {
auderr("ERROR: Failed to set PCM configuration: %d\n", ret); auderr("ERROR: Failed to set PCM configuration: %d\n", ret);
return ret; return ret;
}
/* Bump up the data offset */
apb->curbyte += sizeof(struct wav_header_s);
#ifndef CONFIG_AUDIO_EXCLUDE_FFORWARD
audinfo("Begin streaming: apb=%p curbyte=%d nbytes=%d\n",
apb, apb->curbyte, apb->nbytes);
/* Perform any necessary sub-sampling operations */
pcm_subsample(priv, apb);
#endif
/* Then give the audio buffer to the lower driver */
audinfo(
"Pass to lower enqueuebuffer: apb=%p curbyte=%d nbytes=%d\n",
apb, apb->curbyte, apb->nbytes);
ret = lower->ops->enqueuebuffer(lower, apb);
if (ret == OK)
{
/* Now we are streaming. Unless for some reason there is only
* one audio buffer in the audio stream. In that case, this
* will be marked as the final buffer
*/
priv->streaming = ((apb->flags & AUDIO_APB_FINAL) == 0);
return OK;
}
} }
auderr("ERROR: Invalid PCM WAV file\n"); /* Bump up the data offset */
apb->curbyte += sizeof(struct wav_header_s);
#endif
#ifndef CONFIG_AUDIO_EXCLUDE_FFORWARD
audinfo("Begin streaming: apb=%p curbyte=%d nbytes=%d\n",
apb, apb->curbyte, apb->nbytes);
/* Perform any necessary sub-sampling operations */
pcm_subsample(priv, apb);
#endif
/* Then give the audio buffer to the lower driver */
audinfo(
"Pass to lower enqueuebuffer: apb=%p curbyte=%d nbytes=%d\n",
apb, apb->curbyte, apb->nbytes);
ret = lower->ops->enqueuebuffer(lower, apb);
if (ret == OK)
{
/* Now we are streaming. Unless for some reason there is only
* one audio buffer in the audio stream. In that case, this
* will be marked as the final buffer
*/
priv->streaming = ((apb->flags & AUDIO_APB_FINAL) == 0);
return OK;
}
/* The normal protocol for streaming errors is as follows: /* The normal protocol for streaming errors is as follows:
* *
@ -1171,10 +1171,12 @@ static int pcm_enqueuebuffer(FAR struct audio_lowerhalf_s *dev,
#endif #endif
} }
#ifndef CONFIG_AUDIO_FORMAT_RAW
/* This is not a WAV file! */ /* This is not a WAV file! */
auderr("ERROR: Invalid PCM WAV file\n"); auderr("ERROR: Invalid PCM WAV file\n");
return -EINVAL; return -EINVAL;
#endif
} }
/**************************************************************************** /****************************************************************************