diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2014-07-27 21:42:10 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2014-07-27 21:42:10 -0600 |
commit | 21b185668d583493e3a95f105a2e1cb5cdc2d5aa (patch) | |
tree | b8e6f0dcebd1a68de30ca9ea1e032fc869206765 /nuttx | |
parent | 7f246192a84fa98cba789752ba9d6b5ca60eb956 (diff) | |
download | px4-nuttx-21b185668d583493e3a95f105a2e1cb5cdc2d5aa.tar.gz px4-nuttx-21b185668d583493e3a95f105a2e1cb5cdc2d5aa.tar.bz2 px4-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')
-rw-r--r-- | nuttx/audio/pcm_decode.c | 643 |
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 ****************************************************************************/ |