Skip to content

Commit

Permalink
Merge pull request #410 from MarkTillotson/improve-audio-play-queue
Browse files Browse the repository at this point in the history
Improve audio play queue
  • Loading branch information
PaulStoffregen authored Nov 14, 2021
2 parents db7fb42 + fa22929 commit d990906
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 13 deletions.
28 changes: 19 additions & 9 deletions gui/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2847,23 +2847,33 @@ <h3>Audio Connections</h3>
<tr class=odd><td align=center>Out 0</td><td>Sound Output</td></tr>
</table>
<h3>Functions</h3>
<p class=func><span class=keyword>setMaxBuffers</span>(uint8);</p>
<p class=desc>Set the maximum buffer block count for the queue to limit its size - by default 32 blocks are used on Teensy3's
and 80 on Teeny 4's - this allows the value to be reduced so that the queue cannot get too far ahead, nor use up lots of
audio blocks you might want for other purposes. The minimum number of buffer blocks is 2.
</p>
<p class=func><span class=keyword>play</span>(int16);</p>
<p class=desc>not yet implemented
<p class=desc>add a single sample to the queue - no need to use getBuffer() or playBuffer() as this
method does the necessary handling. Note this method may block waiting for a spare buffer if the queue is full
</p>
<p class=func><span class=keyword>play</span>(int16[], length);</p>
<p class=desc>not yet implemented
<p class=desc>add multiple samples to the queue - no need to use getBuffer() or playBuffer() as this
method does the necessary handling. Note this method may block waiting for a spare buffer if the queue is full.
The length should be the number of samples in the array.
</p>
<p class=func><span class=keyword>getBuffer</span>();</p>
<p class=desc>Returns a pointer to an array of 128 int16. This buffer
is within the audio library memory pool, providing the most efficient
way to input data to the audio system. The buffer is likely to be
populated by previously used data, so the entire 128 words should be
written before calling playBuffer(). Only a single buffer should be
requested at a time. This function may return NULL if no memory is
available.
is within the audio library memory pool, providing the most efficient
way to input data to the audio system. The buffer is likely to be
populated by previously used data, so the entire 128 words should be
written before calling playBuffer(). Only a single buffer should be
requested at a time. This function may return NULL if no memory is
available.
</p>
<p>You may find it easier to use the play() methods unless performance is crucial.
</p>
<p class=func><span class=keyword>playBuffer</span>();</p>
<p class=desc>Transmit the buffer previously obtained from getBuffer().
<p class=desc>Transmit the buffer previously obtained from getBuffer(). If you use the play() methods you should not use this.
</p>
<h3>Examples</h3>
<p><a href="http://community.arm.com/groups/embedded/blog/2014/05/23/led-video-panel-at-maker-faire-2014" target="_blank">4320 LED Video+Sound Project</a>
Expand Down
40 changes: 40 additions & 0 deletions play_queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@
#include "play_queue.h"
#include "utility/dspinst.h"

void AudioPlayQueue::setMaxBuffers(uint8_t maxb)
{
if (maxb < 2)
maxb = 2 ;
if (maxb > MAX_BUFFERS)
maxb = MAX_BUFFERS ;
max_buffers = maxb ;
}

bool AudioPlayQueue::available(void)
{
if (userblock) return true;
Expand Down Expand Up @@ -59,6 +68,37 @@ void AudioPlayQueue::playBuffer(void)
userblock = NULL;
}

void AudioPlayQueue::play(int16_t data)
{
int16_t * buf = getBuffer() ;
buf [uptr++] = data ;
if (uptr >= AUDIO_BLOCK_SAMPLES)
{
playBuffer() ;
uptr = 0 ;
}
}

void AudioPlayQueue::play(const int16_t *data, uint32_t len)
{
while (len > 0)
{
unsigned int avail_in_userblock = AUDIO_BLOCK_SAMPLES - uptr ;
unsigned int to_copy = avail_in_userblock > len ? len : avail_in_userblock ;
int16_t * buf = getBuffer();
memcpy ((void*)(buf+uptr), (void*)data, to_copy * sizeof(int16_t)) ;
uptr += to_copy ;

data += to_copy ;
len -= to_copy ;
if (uptr >= AUDIO_BLOCK_SAMPLES)
{
playBuffer() ;
uptr = 0 ;
}
}
}

void AudioPlayQueue::update(void)
{
audio_block_t *block;
Expand Down
11 changes: 7 additions & 4 deletions play_queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,25 +34,28 @@ class AudioPlayQueue : public AudioStream
{
private:
#if defined(__IMXRT1062__) || defined(__MK66FX1M0__) || defined(__MK64FX512__)
static const int max_buffers = 80;
static const unsigned int MAX_BUFFERS = 80;
#else
static const int max_buffers = 32;
static const unsigned int MAX_BUFFERS = 32;
#endif
public:
AudioPlayQueue(void) : AudioStream(0, NULL),
userblock(NULL), head(0), tail(0) { }
userblock(NULL), uptr(0), head(0), tail(0), max_buffers(MAX_BUFFERS) { }
void play(int16_t data);
void play(const int16_t *data, uint32_t len);
bool available(void);
int16_t * getBuffer(void);
void playBuffer(void);
void stop(void);
void setMaxBuffers(uint8_t);
//bool isPlaying(void) { return playing; }
virtual void update(void);
private:
audio_block_t *queue[max_buffers];
audio_block_t *queue[MAX_BUFFERS];
audio_block_t *userblock;
unsigned int uptr;
volatile uint8_t head, tail;
volatile unsigned int max_buffers;
};

#endif

0 comments on commit d990906

Please sign in to comment.