summaryrefslogtreecommitdiff
path: root/nuttx/audio
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-07-27 21:42:10 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-07-27 21:42:10 -0600
commit21b185668d583493e3a95f105a2e1cb5cdc2d5aa (patch)
treeb8e6f0dcebd1a68de30ca9ea1e032fc869206765 /nuttx/audio
parent7f246192a84fa98cba789752ba9d6b5ca60eb956 (diff)
downloadnuttx-21b185668d583493e3a95f105a2e1cb5cdc2d5aa.tar.gz
nuttx-21b185668d583493e3a95f105a2e1cb5cdc2d5aa.tar.bz2
nuttx-21b185668d583493e3a95f105a2e1cb5cdc2d5aa.zip
PCM: Major simplification of the sub-sampling design. Now need no extra buffers because sub-sampling is done in place
Diffstat (limited to 'nuttx/audio')
-rw-r--r--nuttx/audio/pcm_decode.c643
1 files changed, 92 insertions, 551 deletions
diff --git a/nuttx/audio/pcm_decode.c b/nuttx/audio/pcm_decode.c
index f1ba4904d..0c0191dee 100644
--- a/nuttx/audio/pcm_decode.c
+++ b/nuttx/audio/pcm_decode.c
@@ -124,18 +124,8 @@ struct pcm_decode_s
/* Fast forward support */
uint8_t subsample; /* Fast forward rate: See AUDIO_SUBSAMPLE_* defns */
- uint8_t skip; /* Number of samples to be skipped */
+ uint8_t skip; /* Number of sample bytes to be skipped */
uint8_t npartial; /* Size of the partially copied sample */
-
- /* REVISIT: I think we could get rid of all of this special buffer
- * processing. It seems like we should be able to do the sub-sampling
- * in place without any additional buffers.
- */
-
- struct audio_buf_desc_s bufdesc; /* Allocated buffer description */
- FAR struct ap_buffer_s *ffwd; /* Audio buffer being subsampled into */
- FAR struct ap_buffer_s *next; /* Next available, empty audio buffer */
- FAR struct ap_buffer_s *apb; /* Allocated audio buffer */
#endif
};
@@ -161,29 +151,11 @@ static uint16_t pcm_leuint32(uint32_t value);
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);
-#ifdef CONFIG_AUDIO_MULTI_SESSION
-static void pcm_upper_callback(FAR struct pcm_decode_s *priv,
- uint16_t reason, FAR struct ap_buffer_s *apb,
- uint16_t status, FAR void *session);
-#else
-static void pcm_upper_callback(FAR struct pcm_decode_s *priv,
- uint16_t reason, FAR struct ap_buffer_s *apb,
- uint16_t status);
-#endif
#ifndef CONFIG_AUDIO_EXCLUDE_FFORWARD
-static int pcm_subsample_configure(FAR struct pcm_decode_s *priv,
+static void pcm_subsample_configure(FAR struct pcm_decode_s *priv,
uint8_t subsample);
-#ifdef CONFIG_AUDIO_MULTI_SESSION
-static void pcm_subsample_callback(FAR struct pcm_decode_s *priv,
- uint16_t reason, FAR struct ap_buffer_s *apb,
- uint16_t status, FAR void *session);
-#else
-static void pcm_subsample_callback(FAR struct pcm_decode_s *priv,
- uint16_t reason, FAR struct ap_buffer_s *apb,
- uint16_t status);
-#endif
-static FAR struct ap_buffer_s *pcm_subsample(FAR struct pcm_decode_s *priv,
+static void pcm_subsample(FAR struct pcm_decode_s *priv,
FAR struct ap_buffer_s *apb);
#endif
@@ -446,39 +418,6 @@ static bool pcm_parsewav(FAR struct pcm_decode_s *priv, uint8_t *data)
}
/****************************************************************************
- * Name: pcm_upper_callback
- *
- * Description:
- * The lower level driver has just returned a buffer that belongs to the
- * uppder level. We need to forward the buffer to the upper level for
- * disposition.
- *
- ****************************************************************************/
-
-#ifdef CONFIG_AUDIO_MULTI_SESSION
-static void pcm_upper_callback(FAR struct pcm_decode_s *priv,
- uint16_t reason, FAR struct ap_buffer_s *apb,
- uint16_t status, FAR void *session)
-#else
-static void pcm_upper_callback(FAR struct pcm_decode_s *priv,
- uint16_t reason, FAR struct ap_buffer_s *apb,
- uint16_t status)
-#endif
-{
- DEBUGASSERT(priv && apb && priv->export.upper);
-
- /* The buffer belongs to to an upper level. Just forward the event to
- * the next level up.
- */
-
-#ifdef CONFIG_AUDIO_MULTI_SESSION
- priv->export.upper(priv->export.priv, reason, apb, status, session);
-#else
- priv->export.upper(priv->export.priv, reason, apb, status);
-#endif
-}
-
-/****************************************************************************
* Name: pcm_subsample_configure
*
* Description:
@@ -488,15 +427,9 @@ static void pcm_upper_callback(FAR struct pcm_decode_s *priv,
****************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_FFORWARD
-static int pcm_subsample_configure(FAR struct pcm_decode_s *priv,
- uint8_t subsample)
+static void pcm_subsample_configure(FAR struct pcm_decode_s *priv,
+ uint8_t subsample)
{
- FAR struct audio_lowerhalf_s *lower = priv->lower;
-#ifdef CONFIG_AUDIO_DRIVER_SPECIFIC_BUFFERS
- struct ap_buffer_info_s bufinfo;
-#endif
- int ret;
-
audvdbg("subsample: %d\n", subsample);
/* Three possibilities:
@@ -507,84 +440,18 @@ static int pcm_subsample_configure(FAR struct pcm_decode_s *priv,
if (priv->subsample == AUDIO_SUBSAMPLE_NONE)
{
- /* There should be no audio buffer allocated in this case */
-
- DEBUGASSERT(priv->ffwd == NULL);
-
/* Ignore request to stop fast forwarding if we are already
* fast forwarding.
*/
if (subsample != AUDIO_SUBSAMPLE_NONE)
{
- /* Check if we already have an audio buffer. This might happen in
- * certain race conditions were we exit and return to fast forward
- * mode while the audio buffer is in possession of the lower level
- * driver.
- */
-
- audvdbg("Start subsampling: apb=%p\n", priv->apb);
-
- /* REVISIT: I think we could get rid of this special buffer. It
- * seems like we should be able to do the sub-sampling in place
- * without any additional buffers.
- */
-
- if (priv->apb == NULL)
- {
-#ifdef CONFIG_AUDIO_DRIVER_SPECIFIC_BUFFERS
- /* Get the lower level driver's preferred buffer properties */
-
- DEBUGASSERT(lower->ioctl);
- ret = lower->ioctl(lower, AUDIOIOC_GETBUFFERINFO,
- (unsigned long)&bufinfo))
- if (ret < 0)
- {
- /* Driver doesn't report it's buffer size. Use defaults. */
-
- bufinfo.buffer_size = CONFIG_AUDIO_BUFFER_NUMBYTES;
- bufinfo.nbuffers = CONFIG_AUDIO_NUM_BUFFERS;
- }
-#endif
-
- /* Configure the buffer descriptor */
-
-#ifdef CONFIG_AUDIO_MULTI_SESSION
- priv->bufdesc.session = priv->session;
-#endif
-#ifdef CONFIG_AUDIO_DRIVER_SPECIFIC_BUFFERS
- priv->bufdesc.numbytes = bufinfo.buffer_size;
-#else
- priv->bufdesc.numbytes = CONFIG_AUDIO_BUFFER_NUMBYTES;
-#endif
- priv->bufdesc.u.ppBuffer = &priv->apb;
-
- /* Perform the allocation */
-
- if (lower->ops->allocbuffer)
- {
- ret = lower->ops->allocbuffer(lower, &priv->bufdesc);
- }
- else
- {
- ret = apb_alloc(&priv->bufdesc);
- }
-
- /* Did we get an audio buffer? */
-
- if (ret < 0 || priv->apb == NULL)
- {
- auddbg("ERROR: Failed to allocate an audio buffer\n");
- return -ENOMEM;
- }
- }
+ audvdbg("Start sub-sampling\n");
/* Save the current subsample setting. Subsampling will begin on
* then next audio buffer that we receive.
*/
- priv->ffwd = priv->apb;
- priv->next = NULL;
priv->npartial = 0;
priv->skip = 0;
priv->subsample = subsample;
@@ -592,15 +459,11 @@ static int pcm_subsample_configure(FAR struct pcm_decode_s *priv,
}
/* 2. Were already fast forwarding and we have been asked to change the
- * subsampling rate.
+ * sub-sampling rate.
*/
else if (subsample != AUDIO_SUBSAMPLE_NONE)
{
- /* We should already have an audio buffer allocated in this case */
-
- DEBUGASSERT(priv->apb != NULL && priv->ffwd != NULL);
-
/* Just save the current subsample setting. It will take effect
* on the next audio buffer that we receive.
*/
@@ -614,159 +477,16 @@ static int pcm_subsample_configure(FAR struct pcm_decode_s *priv,
else if (subsample != AUDIO_SUBSAMPLE_NONE)
{
- DEBUGASSERT(priv->apb != NULL && priv->ffwd != NULL);
-
- audvdbg("Stop subsampling\n");
-
- /* Are still holding on to buffers that belong the upper level? */
-
- if (priv->ffwd && priv->ffwd != priv->apb)
- {
-#ifdef CONFIG_AUDIO_MULTI_SESSION
- pcm_upper_callback(priv, AUDIO_CALLBACK_DEQUEUE, priv->ffwd, OK, priv->session);
-#else
- pcm_upper_callback(priv, AUDIO_CALLBACK_DEQUEUE, priv->ffwd, OK);
-#endif
- priv->ffwd = NULL;
- }
-
- /* We need to free the our working audio buffer. But we also need
- * to be careful: The lower level audio driver may have it now.
- *
- * If the lower level driver has the audio buffer, then we will defer
- * freeing it until it is returned to us.
- */
-
- if (priv->ffwd)
- {
- /* We have it. We can free the audio buffer. NOTE: This audio
- * buffer might not be empty, but we will discard it anyway.
- * Playing will begin at normal speed at the next, full audio
- * buffer.
- */
+ audvdbg("Stop sub-sampling\n");
- if (lower->ops->freebuffer)
- {
- (void)lower->ops->freebuffer(lower, &priv->bufdesc);
- }
- else
- {
- apb_free(priv->apb);
- }
-
- priv->apb = NULL;
- priv->ffwd = NULL;
- }
-
- /* And indicate that we are in normal play mode. This will take
- * effect when the next audio buffer is received.
+ /* Indicate that we are in normal play mode. This will take effect
+ * when the next audio buffer is received.
*/
- priv->next = NULL;
priv->npartial = 0;
priv->skip = 0;
priv->subsample = AUDIO_SUBSAMPLE_NONE;
}
-
- return OK;
-}
-#endif
-
-/****************************************************************************
- * Name: pcm_subsample_callback
- *
- * Description:
- * Our working audio buffer has been returned from the lower level driver.
- *
- ****************************************************************************/
-
-#ifndef CONFIG_AUDIO_EXCLUDE_FFORWARD
-#ifdef CONFIG_AUDIO_MULTI_SESSION
-static void pcm_subsample_callback(FAR struct pcm_decode_s *priv,
- uint16_t reason,
- FAR struct ap_buffer_s *apb,
- uint16_t status, FAR void *session)
-#else
-static void pcm_subsample_callback(FAR struct pcm_decode_s *priv,
- uint16_t reason,
- FAR struct ap_buffer_s *apb,
- uint16_t status)
-#endif
-{
- FAR struct audio_lowerhalf_s *lower;
-
- DEBUGASSERT(priv->apb);
-
- audvdbg("apb=%p subsample=%d\n", apb, priv->subsample);
-
- /* Mark the buffer as empty */
-
- apb->nbytes = 0;
- apb->curbyte = 0;
-
- /* Possibilities:
- * 1. We are no longer streaming and we just need to free the buffer.
- * This case happens if we exited fast forward mode while the lower-
- * level driver had possession of or working audio buffer.
- */
-
- if (priv->subsample == AUDIO_SUBSAMPLE_NONE)
- {
- /* Free the working buffer */
-
- lower = priv->lower;
- if (lower->ops->freebuffer)
- {
- (void)lower->ops->freebuffer(lower, &priv->bufdesc);
- }
- else
- {
- apb_free(apb);
- }
-
- priv->apb = NULL;
- }
-
- /* We are still streaming. At any given time, our working audio may be
- * (a) the current working buffer, (a) the next working buffer or it, or
- * (c) in possession of the lower level driver. None of these are the
- * case now since we just got our working audio buffer back from the
- *
- * 2. We have no fast forward working buffer. Use it buffer as our
- * fast forward working buffer. This should never happen.
- */
-
- else if (priv->ffwd == NULL)
- {
- /* Set the returned buffer as the current working buffer */
-
- priv->ffwd = apb;
- }
-
- /* 2. We already have a fast word working buffer, but no next working
- * buffer. Save out working audio buffer as the new next buffer.
- */
-
- else
- {
- /* Set the returned buffer as the next working buffer
- *
- * REVISIT: This extra buffer is only used on the first buffer. There
- * is something wrong:
- *
- * 1. First buffer: Our private buffer is the working buffer. The
- * first audio buffer we receive is compressed into the working
- * buffer and the working buffer goes to the lower level. The
- * first buffer becomes next working buffer.
- * 2. Next buffers: Are compressed into the working buffer, sent
- * to the lower level, and become the next working buffer, etc.
- * 3. The private buffer eventually comes back here and is saved
- * as the "next" buffer, but it is never used again.
- */
-
- DEBUGASSERT(priv->next == NULL);
- priv->next = apb;
- }
}
#endif
@@ -774,43 +494,42 @@ static void pcm_subsample_callback(FAR struct pcm_decode_s *priv,
* Name: pcm_subsample
*
* Description:
- * Given a newly received audio buffer, perform subsampling into our local
- * working audio buffer. Return the subsampled audio buffer to send to
- * the lower level driver.
+ * Given a newly received audio buffer, perform sub-sampling in-place in
+ * the audio buffer. Since the sub-sampled data will always be smaller
+ * than the original buffer, no additional buffering should be necessary.
*
****************************************************************************/
#ifndef CONFIG_AUDIO_EXCLUDE_FFORWARD
-static FAR struct ap_buffer_s *pcm_subsample(FAR struct pcm_decode_s *priv,
- FAR struct ap_buffer_s *apb)
+static void pcm_subsample(FAR struct pcm_decode_s *priv,
+ FAR struct ap_buffer_s *apb)
{
- FAR struct ap_buffer_s *work;
FAR const uint8_t *src;
FAR uint8_t *dest;
unsigned int destsize;
unsigned int srcsize;
unsigned int skipsize;
+ unsigned int copysize;
unsigned int i;
- /* Are we subsampling? */
+ /* Are we sub-sampling? */
if (priv->subsample == AUDIO_SUBSAMPLE_NONE)
{
/* No.. do nothing to the buffer */
- return apb;
+ return;
}
- /* Yes.. then make sure that we have the required buffers in place */
-
- DEBUGASSERT(priv->ffwd && priv->apb);
-
- /* Yes.. we will need to subsample the newly received buffer. */
+ /* Yes.. we will need to subsample the newly received buffer in-place by
+ * copying from the upper end of the buffer to the lower end.
+ */
- work = priv->ffwd;
- dest = &work->samp[work->nbytes];
+ src = &apb->samp[apb->curbyte];
+ dest = apb->samp;
- DEBUGASSERT(work->nmaxbytes >= priv->align);
+ srcsize = apb->nbytes - apb->curbyte;
+ destsize = apb->nmaxbytes;
/* This is the number of bytes that we need to skip between samples */
@@ -820,10 +539,6 @@ static FAR struct ap_buffer_s *pcm_subsample(FAR struct pcm_decode_s *priv,
if (priv->npartial > 0)
{
- /* How much data is available in the new audio buffer */
-
- srcsize = apb->nbytes - apb->curbyte;
-
/* Let's get an impossible corner case out of the way. What if we
* received a tiny audio buffer. So small, that it (plus any previous
* sample) is smaller than one sample.
@@ -831,45 +546,46 @@ static FAR struct ap_buffer_s *pcm_subsample(FAR struct pcm_decode_s *priv,
if (priv->npartial + srcsize < priv->align)
{
- /* Update the partial sample size */
+ /* Update the partial sample size and return the unmodified
+ * buffer.
+ */
priv->npartial += srcsize;
-
- /* And just return the buffer with no modification */
-
- return apb;
+ return;
}
- /* No, we do at least have enough to complete the sample. Copy copy data
- * from the new audio buffer to complete the sample.
+ /* We do at least have enough to complete the sample. If this data
+ * does not resides at the correct position at the from of the audio
+ * buffer, then we will need to copy it.
*/
- src = &apb->samp[apb->curbyte];
- for (i = priv->npartial; i < priv->align; i++)
+ copysize = priv->align - priv->npartial;
+ if (apb->curbyte > 0)
{
- *dest++ = *src++;
- apb->curbyte++;
- }
+ /* We have to copy down */
- priv->npartial = 0;
+ for (i = 0; i < copysize; i++)
+ {
+ *dest++ = *src++;
+ }
+ }
- /* Update the number of bytes in the working buffer and reset the skip
- * value
+ /* Update the number of bytes in the working buffer and reset the
+ * skip value
*/
- work->nbytes += skipsize;
- priv->skip = skipsize;
+ priv->npartial = 0;
+ srcsize -= copysize;
+ destsize -= copysize;
+ priv->skip = skipsize;
}
- /* Now loop until either (1) the working audio buffer is full, or (2)
- * the newly received audio buffer is empty.
+ /* Now loop until either the entire audio buffer has been sub-sampling.
+ * This copy in place works because we know that the sub-sampled data
+ * will always be smaller than the original data.
*/
- src = &apb->samp[apb->curbyte];
- srcsize = apb->nbytes - apb->curbyte;
- destsize = work->nmaxbytes - work->nbytes;
-
- while (srcsize > 0 && destsize > 0)
+ while (srcsize > 0)
{
/* Do we need to skip ahead in the buffer? */
@@ -880,26 +596,17 @@ static FAR struct ap_buffer_s *pcm_subsample(FAR struct pcm_decode_s *priv,
* number of bytes available in the newly received audio buffer.
*/
- unsigned int discard = MIN(priv->skip, srcsize);
+ copysize = MIN(priv->skip, srcsize);
- priv->skip -= discard;
- apb->curbyte += discard;
- srcsize -= discard;
-
- /* Did we skip to the end of the audio buffer? */
-
- if (srcsize <= 0)
- {
- goto exit_apb_empty;
- }
+ priv->skip -= copysize;
+ src += copysize;
+ srcsize -= copysize;
}
/* Copy the sample from the audio buffer into the working buffer. */
else
{
- unsigned int copysize;
-
/* Do we have space for the whole sample? */
if (srcsize < priv->align)
@@ -911,149 +618,32 @@ static FAR struct ap_buffer_s *pcm_subsample(FAR struct pcm_decode_s *priv,
}
else
{
+ /* Copy the whole sample and re-arm the skip size */
+
copysize = priv->align;
priv->skip = skipsize;
}
- /* Now copy the sample from new audio buffer to working buffer */
+ /* Now copy the sample from the end of audio buffer to the beginning. */
for (i = 0; i < copysize; i++)
{
*dest++ = *src++;
}
- /* Update indices and sizes and reset the skip value */
-
- apb->curbyte += copysize;
- srcsize -= copysize;
-
- work->nbytes += copysize;
- destsize -= copysize;
- }
- }
-
- /* We get here in one of two cases. Either (1) the source audio buffer
- * became empty, and/or (2) the working audio buffer became which. Which
- * is the case?
- *
- * REVISIT: Should there be a threshold here so that we do not send
- * really tiny buffers to the lower-level driver.
- */
-
- if (srcsize > 0)
- {
- /* How could the working buffer be empty in this case? */
-
- DEBUGASSERT(work->nbytes > 0);
-
- /* This seems overly complex. We either need another buffer or else
- * we have to do this: Sub-ample in place.
- */
-
- dest = apb->samp;
- destsize = apb->nmaxbytes;
-
- while (srcsize > 0)
- {
- /* Do we need to skip ahead in the buffer? */
-
- if (priv->skip > 0)
- {
- /* How much can we skip in this buffer? Depends on the
- * smaller of (1) the number of bytes that we need to skip
- * and (2) the number of bytes available in the audio buffer.
- */
-
- unsigned int discard = MIN(priv->skip, srcsize);
-
- priv->skip -= discard;
- srcsize -= discard;
-
- /* Did we skip to the end of the audio buffer? */
-
- if (srcsize <= 0)
- {
- break;
- }
- }
-
- /* Copy the sample from the end of the audio buffer to the beginning. */
-
- else
- {
- unsigned int copysize;
-
- /* Do we have space for the whole sample? */
-
- if (srcsize < priv->align)
- {
- /* No.. this is a partial copy */
-
- copysize = srcsize;
- priv->npartial = srcsize;
- }
- else
- {
- /* Copy the whole sample and re-arm the skip size */
-
- copysize = priv->align;
- priv->skip = skipsize;
- }
-
- /* Now copy the sample from new audio buffer to working buffer */
-
- for (i = 0; i < copysize; i++)
- {
- *dest++ = *src++;
- }
-
- /* Updates bytes available in the source buffer and bytes
- * remaining in the dest buffer.
- */
+ /* Updates bytes available in the source buffer and bytes
+ * remaining in the destination buffer.
+ */
- srcsize -= copysize;
- destsize -= copysize;
- }
+ srcsize -= copysize;
+ destsize -= copysize;
}
-
- /* Set the buffer that we just emptied as the new working buffer */
-
- apb->curbyte = 0;
- apb->nbytes = apb->nmaxbytes - destsize;
- priv->ffwd = apb;
-
- /* Return the working buffer */
-
- return work;
}
-exit_apb_empty:
- /* We get here in the case that the source audio buffer is empty. The
- * working buffer may be empty or non-empty.
- */
-
- /* Is there anything in the working buffer?
- *
- * REVISIT: Should there be a threshold here so that we do not send
- * really tiny buffers to the lower-level driver.
- */
-
- if (work->nbytes > 0)
- {
- /* Set the buffer that we just emptied as the new working buffer */
-
- apb->curbyte = 0;
- apb->nbytes = 0;
- priv->ffwd = apb;
+ /* Update the size and offset data in the audio buffer */
- /* Return the working buffer */
-
- return work;
- }
-
- /* We don't have any data to forward to the lower level driver */
-
- return NULL;
+ apb->curbyte = 0;
+ apb->nbytes = apb->nmaxbytes - destsize;
}
#endif
@@ -1129,9 +719,6 @@ static int pcm_configure(FAR struct audio_lowerhalf_s *dev,
{
FAR struct pcm_decode_s *priv = (FAR struct pcm_decode_s *)dev;
FAR struct audio_lowerhalf_s *lower;
-#ifndef CONFIG_AUDIO_EXCLUDE_FFORWARD
- int ret;
-#endif
DEBUGASSERT(priv);
@@ -1144,19 +731,13 @@ static int pcm_configure(FAR struct audio_lowerhalf_s *dev,
if (caps->ac_type == AUDIO_TYPE_PROCESSING &&
caps->ac_format.hw == AUDIO_PU_SUBSAMPLE_FORWARD)
{
- /* Configure subsampling */
-
- ret = pcm_subsample_configure(priv, caps->ac_controls.b[0]);
- if (ret < 0)
- {
- auddbg("ERROR: pcm_subsample_configure failed: %d\n", ret);
- }
-
- /* Return to avoid forwarding the configuration to the lower level
+ /* Configure sub-sampling and return to avoid forwarding the
+ * configuration to the lower level
* driver.
*/
- return ret;
+ pcm_subsample_configure(priv, caps->ac_controls.b[0]);
+ return OK;
}
#endif
@@ -1440,21 +1021,17 @@ static int pcm_enqueuebuffer(FAR struct audio_lowerhalf_s *dev,
audvdbg("Received: apb=%p curbyte=%d nbytes=%d\n",
apb, apb->curbyte, apb->nbytes);
- /* Perform any necessary subsampling operations */
+ /* Perform any necessary sub-sampling operations */
- apb = pcm_subsample(priv, apb);
- if (apb)
+ pcm_subsample(priv, apb);
#endif
- {
- /* Then give the audio buffer to the lower driver */
- audvdbg("Pass to lower enqueuebuffer: apb=%p curbyte=%d nbytes=%d\n",
- apb, apb->curbyte, apb->nbytes);
+ /* Then give the audio buffer to the lower driver */
- return lower->ops->enqueuebuffer(lower, apb);
- }
+ audvdbg("Pass to lower enqueuebuffer: apb=%p curbyte=%d nbytes=%d\n",
+ apb, apb->curbyte, apb->nbytes);
- return OK;
+ return lower->ops->enqueuebuffer(lower, apb);
}
/* No.. then this must be the first buffer that we have seen (since we
@@ -1511,21 +1088,17 @@ static int pcm_enqueuebuffer(FAR struct audio_lowerhalf_s *dev,
audvdbg("Begin streaming: apb=%p curbyte=%d nbytes=%d\n",
apb, apb->curbyte, apb->nbytes);
- /* Perform any necessary subsampling operations */
+ /* Perform any necessary sub-sampling operations */
- apb = pcm_subsample(priv, apb);
- if (apb)
+ pcm_subsample(priv, apb);
#endif
- {
- /* Then give the audio buffer to the lower driver */
- audvdbg("Pass to lower enqueuebuffer: apb=%p curbyte=%d nbytes=%d\n",
- apb, apb->curbyte, apb->nbytes);
+ /* Then give the audio buffer to the lower driver */
- return lower->ops->enqueuebuffer(lower, apb);
- }
+ audvdbg("Pass to lower enqueuebuffer: apb=%p curbyte=%d nbytes=%d\n",
+ apb, apb->curbyte, apb->nbytes);
- return OK;
+ return lower->ops->enqueuebuffer(lower, apb);
}
}
@@ -1690,63 +1263,31 @@ static int pcm_release(FAR struct audio_lowerhalf_s *dev)
*
****************************************************************************/
-/* Audio callback */
-
#ifdef CONFIG_AUDIO_MULTI_SESSION
-
static void pcm_callback(FAR void *arg, uint16_t reason,
FAR struct ap_buffer_s *apb, uint16_t status,
FAR void *session)
-{
- FAR struct pcm_decode_s *priv = (FAR struct pcm_decode_s *)arg;
-
-#ifndef CONFIG_AUDIO_EXCLUDE_FFORWARD
- /* If this is our internal working audio buffer that we use for subsampling,
- * then we are the owner of the buffer and we don't want to return it to
- * the upper level.
- */
-
- if (priv->apb == apb)
- {
- pcm_subsample_callback(priv, reason, apb, status, session);
- }
- else
-#endif
- {
- /* Return the buffer to the upper level */
-
- pcm_upper_callback(priv, reason, apb, status, session);
- }
-}
-
-#else /* CONFIG_AUDIO_MULTI_SESSION */
-
+#else
static void pcm_callback(FAR void *arg, uint16_t reason,
FAR struct ap_buffer_s *apb, uint16_t status)
+#endif
{
FAR struct pcm_decode_s *priv = (FAR struct pcm_decode_s *)arg;
-#ifndef CONFIG_AUDIO_EXCLUDE_FFORWARD
- /* If this is our internal working audio buffer that we use for sub-sampling,
- * then we are the owner of the buffer and we don't want to return it to
- * the upper level.
+
+ DEBUGASSERT(priv && apb && priv->export.upper);
+
+ /* The buffer belongs to to an upper level. Just forward the event to
+ * the next level up.
*/
- if (priv->apb == apb)
- {
- pcm_subsample_callback(priv, reason, apb, status);
- }
- else
+#ifdef CONFIG_AUDIO_MULTI_SESSION
+ priv->export.upper(priv->export.priv, reason, apb, status, session);
+#else
+ priv->export.upper(priv->export.priv, reason, apb, status);
#endif
- {
- /* Return the buffer to the upper level */
-
- pcm_upper_callback(priv, reason, apb, status);
- }
}
-#endif /* CONFIG_AUDIO_MULTI_SESSION */
-
/****************************************************************************
* Public Functions
****************************************************************************/