wip: audiocore: integrate mp3 decoding
All checks were successful
Check code formatting / Check-C-Format (push) Successful in 10s
Check code formatting / Check-Python-Flake8 (push) Successful in 10s
Run unit tests on host / Run-Unit-Tests (push) Successful in 10s

This commit is contained in:
2024-08-04 10:58:46 +02:00
parent 5060cac76a
commit 01b28d4d56
10 changed files with 256 additions and 109 deletions

View File

@@ -7,15 +7,19 @@ make_unity_test(NAME test_audiocore
INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/../test/include" "${CMAKE_CURRENT_SOURCE_DIR}"
)
find_package(SDL2 REQUIRED)
find_package(SDL2)
add_executable(mp3test
if (SDL2_FOUND)
add_executable(mp3test
"dr_mp3.c"
"mp3test.c"
)
)
target_include_directories(mp3test PRIVATE
target_include_directories(mp3test PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/../../lib/dr_mp3"
)
)
target_link_libraries(mp3test SDL2::SDL2)
target_link_libraries(mp3test SDL2::SDL2)
else()
message(STATIC "Didn't find SDL2, not building mp3test")
endif()

View File

@@ -4,8 +4,11 @@
#include "audiocore.h"
#include "i2s.h"
#include "mp3.h"
#include "py/mperrno.h"
struct audiocore_context core1_context = {{}, 0, 0};
void core1_main(void)
{
if (!i2s_init(shared_context.out_pin, shared_context.sideset_base, shared_context.samplerate)) {
@@ -14,14 +17,23 @@ void core1_main(void)
}
multicore_fifo_push_blocking(0);
uint32_t cmd;
while ((cmd = multicore_fifo_pop_blocking()) != AUDIOCORE_CMD_SHUTDOWN) {
switch (cmd) {
default:
break;
while (true) {
if (multicore_fifo_rvalid()) {
const uint32_t cmd = multicore_fifo_pop_blocking();
switch (cmd) {
default:
goto shutdown;
}
}
while (audiocore_get_pcm_buffer_space() >= MP3_MAX_PCM_FRAMES_PER_MP3_FRAME &&
audiocore_get_mp3_buffer_avail() > 0) {
mp3_decode();
}
__wfe();
}
shutdown:
i2s_deinit();
multicore_fifo_push_blocking(0);
}

View File

@@ -2,7 +2,6 @@
// Copyright (c) 2024 Matthias Blankertz <matthias@blankertz.org>
#pragma once
#include <hardware/sync.h>
#include <stdint.h>
@@ -17,7 +16,9 @@
* communication between the cores.
*/
#define AUDIO_BUFFER_SIZE 2048
#define PCM_BUFFER_SIZE 2048
#define MP3_BUFFER_SIZE 2048
// Context shared between the micropython runtime on core0 and the audio task on
// core1 All access must hold "lock" unless otherwise noted
@@ -28,55 +29,127 @@ struct audiocore_shared_context {
int out_pin, sideset_base, samplerate;
// Must hold lock
uint32_t audio_buffer[AUDIO_BUFFER_SIZE];
int audio_buffer_write, audio_buffer_read;
int underruns;
uint8_t mp3_buffer[MP3_BUFFER_SIZE];
int mp3_buffer_write, mp3_buffer_read;
int i2s_underruns;
};
extern struct audiocore_shared_context shared_context;
static inline unsigned audiocore_get_audio_buffer_space(void)
// Context exclusive to core1
struct audiocore_context {
// Must disable interrupts on core1
uint32_t pcm_buffer[PCM_BUFFER_SIZE];
int pcm_buffer_write, pcm_buffer_read;
};
extern struct audiocore_context core1_context;
static inline unsigned audiocore_get_pcm_buffer_space(void)
{
if (shared_context.audio_buffer_write >= shared_context.audio_buffer_read)
return AUDIO_BUFFER_SIZE - 1 - (shared_context.audio_buffer_write - shared_context.audio_buffer_read);
if (core1_context.pcm_buffer_write >= core1_context.pcm_buffer_read)
return PCM_BUFFER_SIZE - 1 - (core1_context.pcm_buffer_write - core1_context.pcm_buffer_read);
else
return shared_context.audio_buffer_read - shared_context.audio_buffer_write - 1;
return core1_context.pcm_buffer_read - core1_context.pcm_buffer_write - 1;
}
static inline unsigned audiocore_get_audio_buffer_avail(void)
static inline unsigned audiocore_get_pcm_buffer_avail(void)
{
if (shared_context.audio_buffer_write >= shared_context.audio_buffer_read)
return shared_context.audio_buffer_write - shared_context.audio_buffer_read;
if (core1_context.pcm_buffer_write >= core1_context.pcm_buffer_read)
return core1_context.pcm_buffer_write - core1_context.pcm_buffer_read;
else
return AUDIO_BUFFER_SIZE - (shared_context.audio_buffer_read - shared_context.audio_buffer_write);
return PCM_BUFFER_SIZE - (core1_context.pcm_buffer_read - core1_context.pcm_buffer_write);
}
static inline void audiocore_audio_buffer_put(const uint32_t *restrict src, const size_t len)
static inline void audiocore_pcm_buffer_put(const uint32_t *restrict src, const size_t len)
{
const unsigned end_samples = AUDIO_BUFFER_SIZE - shared_context.audio_buffer_write;
memcpy(shared_context.audio_buffer + shared_context.audio_buffer_write, src,
const unsigned end_samples = PCM_BUFFER_SIZE - core1_context.pcm_buffer_write;
memcpy(core1_context.pcm_buffer + core1_context.pcm_buffer_write, src,
4 * ((end_samples >= len) ? len : end_samples));
if (end_samples < len) {
memcpy(shared_context.audio_buffer, src + end_samples, 4 * (len - end_samples));
shared_context.audio_buffer_write = len - end_samples;
memcpy(core1_context.pcm_buffer, src + end_samples, 4 * (len - end_samples));
core1_context.pcm_buffer_write = len - end_samples;
} else {
shared_context.audio_buffer_write += len;
core1_context.pcm_buffer_write += len;
}
shared_context.audio_buffer_write %= AUDIO_BUFFER_SIZE;
core1_context.pcm_buffer_write %= PCM_BUFFER_SIZE;
}
static inline void audiocore_audio_buffer_get(uint32_t *restrict dst, const size_t len)
static inline void audiocore_pcm_buffer_get(uint32_t *restrict dst, const size_t len)
{
const unsigned end_samples = AUDIO_BUFFER_SIZE - shared_context.audio_buffer_read;
memcpy(dst, shared_context.audio_buffer + shared_context.audio_buffer_read,
const unsigned end_samples = PCM_BUFFER_SIZE - core1_context.pcm_buffer_read;
memcpy(dst, core1_context.pcm_buffer + core1_context.pcm_buffer_read,
4 * ((end_samples >= len) ? len : end_samples));
if (end_samples < len) {
memcpy(dst + end_samples, shared_context.audio_buffer, 4 * (len - end_samples));
shared_context.audio_buffer_read = len - end_samples;
memcpy(dst + end_samples, core1_context.pcm_buffer, 4 * (len - end_samples));
core1_context.pcm_buffer_read = len - end_samples;
} else {
shared_context.audio_buffer_read += len;
core1_context.pcm_buffer_read += len;
}
shared_context.audio_buffer_read %= AUDIO_BUFFER_SIZE;
core1_context.pcm_buffer_read %= PCM_BUFFER_SIZE;
}
static inline unsigned audiocore_get_mp3_buffer_space(void)
{
if (shared_context.mp3_buffer_write >= shared_context.mp3_buffer_read)
return MP3_BUFFER_SIZE - 1 - (shared_context.mp3_buffer_write - shared_context.mp3_buffer_read);
else
return shared_context.mp3_buffer_read - shared_context.mp3_buffer_write - 1;
}
static inline unsigned audiocore_get_mp3_buffer_avail(void)
{
if (shared_context.mp3_buffer_write >= shared_context.mp3_buffer_read)
return shared_context.mp3_buffer_write - shared_context.mp3_buffer_read;
else
return MP3_BUFFER_SIZE - (shared_context.mp3_buffer_read - shared_context.mp3_buffer_write);
}
static inline void audiocore_mp3_buffer_put(const uint8_t *restrict src, const size_t len)
{
const unsigned end_bytes = MP3_BUFFER_SIZE - shared_context.mp3_buffer_write;
memcpy(shared_context.mp3_buffer + shared_context.mp3_buffer_write, src, (end_bytes >= len) ? len : end_bytes);
if (end_bytes < len) {
memcpy(shared_context.mp3_buffer, src + end_bytes, len - end_bytes);
shared_context.mp3_buffer_write = len - end_bytes;
} else {
shared_context.mp3_buffer_write += len;
}
shared_context.mp3_buffer_write %= MP3_BUFFER_SIZE;
}
/* static inline void audiocore_mp3_buffer_get(uint8_t *restrict dst, const size_t len) */
/* { */
/* const unsigned end_bytes = MP3_BUFFER_SIZE - shared_context.mp3_buffer_read; */
/* memcpy(dst, shared_context.mp3_buffer + shared_context.mp3_buffer_read, */
/* (end_bytes >= len) ? len : end_bytes); */
/* if (end_bytes < len) { */
/* memcpy(dst + end_bytes, shared_context.mp3_buffer, len - end_bytes); */
/* shared_context.mp3_buffer_read = len - end_bytes; */
/* } else { */
/* shared_context.mp3_buffer_read += len; */
/* } */
/* shared_context.mp3_buffer_read %= MP3_BUFFER_SIZE; */
/* } */
static inline size_t audiocore_mp3_buffer_get_ptr(uint8_t **data)
{
const unsigned avail = audiocore_get_mp3_buffer_avail();
const unsigned end_bytes = MP3_BUFFER_SIZE - shared_context.mp3_buffer_read;
*data = shared_context.mp3_buffer + shared_context.mp3_buffer_read;
return end_bytes >= avail ? avail : end_bytes;
}
static inline void audiocore_mp3_buffer_consume(const size_t len)
{
const unsigned end_bytes = MP3_BUFFER_SIZE - shared_context.mp3_buffer_read;
if (end_bytes < len) {
shared_context.mp3_buffer_read = len - end_bytes;
} else {
shared_context.mp3_buffer_read += len;
}
shared_context.mp3_buffer_read %= MP3_BUFFER_SIZE;
;
}
void core1_main(void);

View File

@@ -29,11 +29,11 @@ static void dma_isr(void)
return;
dma_channel_acknowledge_irq1(i2s_context.dma_ch);
const uint32_t flags = spin_lock_blocking(shared_context.lock);
if (audiocore_get_audio_buffer_avail() >= I2S_DMA_BUF_SIZE) {
audiocore_audio_buffer_get(i2s_context.dma_buf, I2S_DMA_BUF_SIZE);
if (audiocore_get_pcm_buffer_avail() >= I2S_DMA_BUF_SIZE) {
audiocore_pcm_buffer_get(i2s_context.dma_buf, I2S_DMA_BUF_SIZE);
spin_unlock(shared_context.lock, flags);
} else {
++shared_context.underruns;
++shared_context.i2s_underruns;
spin_unlock(shared_context.lock, flags);
memset(i2s_context.dma_buf, 0, sizeof(uint32_t) * I2S_DMA_BUF_SIZE);
}

View File

@@ -7,13 +7,16 @@ pico_generate_pio_header(usermod_audiocore ${CMAKE_CURRENT_LIST_DIR}/i2s_max9835
target_sources(usermod_audiocore INTERFACE
${CMAKE_CURRENT_LIST_DIR}/audiocore.c
${CMAKE_CURRENT_LIST_DIR}/dr_mp3.c
${CMAKE_CURRENT_LIST_DIR}/module.c
${CMAKE_CURRENT_LIST_DIR}/mp3.c
${CMAKE_CURRENT_LIST_DIR}/i2s.c
${CMAKE_CURRENT_BINARY_DIR}/i2s_max98357.pio.h
)
target_include_directories(usermod_audiocore INTERFACE
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/../../lib/dr_mp3
)
target_link_libraries(usermod INTERFACE usermod_audiocore)

View File

@@ -38,10 +38,10 @@ static MP_DEFINE_CONST_FUN_OBJ_1(audiocore_Context_deinit_obj, audiocore_Context
/*
* (copied, buf_space, undderuns) = audiocore.Context.put(self, buffer)
*
* Copies as many integers as possible from the buffer to the audiocore ring buffer for playback.
* 'buffer' must be any object supporting the buffer protocol with data in unsigned int (array typecode 'I')
* Copies as many bytes as possible from the buffer to the audiocore ring buffer for decoding and playback.
* 'buffer' must be any object supporting the buffer protocol with data in bytes (array typecode 'b' or 'B')
* format. The actual number of elements copied is returned in 'copied', the remaining free ring buffer space
* is in 'buf_space', and the total number of buffer underruns since initialization of the audiocore Context
* is in 'buf_space', and the total number of audio underruns since initialization of the audiocore Context
* is in 'underruns'.
*/
static mp_obj_t audiocore_Context_put(mp_obj_t self_in, mp_obj_t buffer)
@@ -51,18 +51,18 @@ static mp_obj_t audiocore_Context_put(mp_obj_t self_in, mp_obj_t buffer)
mp_buffer_info_t bufinfo;
if (!mp_get_buffer(buffer, &bufinfo, MP_BUFFER_READ))
mp_raise_ValueError("not a read buffer");
if (bufinfo.typecode != 'I')
if (bufinfo.typecode != 'b' && bufinfo.typecode != 'B')
mp_raise_ValueError("unsupported buffer type");
unsigned to_copy = bufinfo.len / 4;
unsigned to_copy = bufinfo.len;
const uint32_t flags = spin_lock_blocking(shared_context.lock);
const unsigned buf_space = audiocore_get_audio_buffer_space();
const unsigned buf_space = audiocore_get_mp3_buffer_space();
if (to_copy > buf_space)
to_copy = buf_space;
if (to_copy > 0) {
audiocore_audio_buffer_put(bufinfo.buf, to_copy);
audiocore_mp3_buffer_put(bufinfo.buf, to_copy);
}
const unsigned underruns = shared_context.underruns;
const unsigned underruns = shared_context.i2s_underruns;
spin_unlock(shared_context.lock, flags);
mp_obj_t items[] = {
@@ -107,8 +107,8 @@ static mp_obj_t audiocore_init(mp_obj_t pin_obj, mp_obj_t sideset_obj, mp_obj_t
mp_raise_OSError(MP_ENOMEM);
shared_context.lock = spin_lock_init(lock);
}
shared_context.audio_buffer_write = shared_context.audio_buffer_read = shared_context.underruns = 0;
memset(shared_context.audio_buffer, 0, AUDIO_BUFFER_SIZE * 4);
shared_context.mp3_buffer_write = shared_context.mp3_buffer_read = shared_context.i2s_underruns = 0;
memset(shared_context.mp3_buffer, 0, MP3_BUFFER_SIZE);
multicore_reset_core1();
struct audiocore_Context_obj *context = m_malloc_with_finaliser(sizeof(struct audiocore_Context_obj));
context->base.type = &audiocore_Context_type;

View File

@@ -0,0 +1,38 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2024 Matthias Blankertz <matthias@blankertz.org>
#include "mp3.h"
#include "audiocore.h"
#include "dr_mp3.h"
#include "platform.h"
#include <assert.h>
#include <stdint.h>
static drmp3dec mp3dec;
static int16_t pcm_buffer[DRMP3_MAX_SAMPLES_PER_FRAME];
void mp3_init(void) { drmp3dec_init(&mp3dec); }
void mp3_decode(void)
{
drmp3dec_frame_info info = {};
uint8_t *data = NULL;
uint32_t flags = spin_lock_blocking(shared_context.lock);
const size_t avail = audiocore_mp3_buffer_get_ptr(&data);
spin_unlock(shared_context.lock, flags);
// This unlocked access to the shared buffer is safe as the writer will never overwrite the data
// that has not been consumed by the reader.
const int decoded_pcm = drmp3dec_decode_frame(&mp3dec, data, avail, &pcm_buffer, &info);
assert(info.frame_bytes <= avail);
flags = spin_lock_blocking(shared_context.lock);
audiocore_mp3_buffer_consume(info.frame_bytes);
spin_unlock(shared_context.lock, flags);
if (!decoded_pcm)
return;
assert(decoded_pcm <= MP3_MAX_PCM_FRAMES_PER_MP3_FRAME);
flags = ENTER_CRITICAL_SECTION();
audiocore_pcm_buffer_put((uint32_t *)pcm_buffer, decoded_pcm);
EXIT_CRITICAL_SECTION(flags);
}

View File

@@ -0,0 +1,9 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2024 Matthias Blankertz <matthias@blankertz.org>
#pragma once
#define MP3_MAX_PCM_FRAMES_PER_MP3_FRAME 1152
void mp3_init(void);
void mp3_decode(void);

View File

@@ -31,6 +31,8 @@ void i2s_deinit(void)
void multicore_fifo_push_blocking(unsigned val) { multicore_fifo_push_last = val; }
bool multicore_fifo_rvalid(void) { return multicore_fifo_pop_blocking_cb; }
unsigned multicore_fifo_pop_blocking(void)
{
if (multicore_fifo_pop_blocking_cb)
@@ -38,6 +40,8 @@ unsigned multicore_fifo_pop_blocking(void)
return 0;
}
void mp3_decode(void) {}
void test_audiocore_handles_i2sinit_failure(void)
{
i2s_init_return = false;
@@ -65,65 +69,65 @@ void test_audiocore_init_deinit(void)
void test_audiocore_buffer_space(void)
{
// empty ring buffer
shared_context.audio_buffer_read = shared_context.audio_buffer_write = 0;
TEST_ASSERT_EQUAL(AUDIO_BUFFER_SIZE - 1, audiocore_get_audio_buffer_space());
core1_context.pcm_buffer_read = core1_context.pcm_buffer_write = 0;
TEST_ASSERT_EQUAL(PCM_BUFFER_SIZE - 1, audiocore_get_pcm_buffer_space());
shared_context.audio_buffer_read = shared_context.audio_buffer_write = 23;
TEST_ASSERT_EQUAL(AUDIO_BUFFER_SIZE - 1, audiocore_get_audio_buffer_space());
core1_context.pcm_buffer_read = core1_context.pcm_buffer_write = 23;
TEST_ASSERT_EQUAL(PCM_BUFFER_SIZE - 1, audiocore_get_pcm_buffer_space());
shared_context.audio_buffer_read = shared_context.audio_buffer_write = AUDIO_BUFFER_SIZE - 1;
TEST_ASSERT_EQUAL(AUDIO_BUFFER_SIZE - 1, audiocore_get_audio_buffer_space());
core1_context.pcm_buffer_read = core1_context.pcm_buffer_write = PCM_BUFFER_SIZE - 1;
TEST_ASSERT_EQUAL(PCM_BUFFER_SIZE - 1, audiocore_get_pcm_buffer_space());
// full ring buffer
shared_context.audio_buffer_write = 0;
shared_context.audio_buffer_read = 1;
TEST_ASSERT_EQUAL(0, audiocore_get_audio_buffer_space());
core1_context.pcm_buffer_write = 0;
core1_context.pcm_buffer_read = 1;
TEST_ASSERT_EQUAL(0, audiocore_get_pcm_buffer_space());
shared_context.audio_buffer_write = AUDIO_BUFFER_SIZE - 1;
shared_context.audio_buffer_read = 0;
TEST_ASSERT_EQUAL(0, audiocore_get_audio_buffer_space());
core1_context.pcm_buffer_write = PCM_BUFFER_SIZE - 1;
core1_context.pcm_buffer_read = 0;
TEST_ASSERT_EQUAL(0, audiocore_get_pcm_buffer_space());
// write > read
shared_context.audio_buffer_write = 10;
shared_context.audio_buffer_read = 0;
TEST_ASSERT_EQUAL(AUDIO_BUFFER_SIZE - 1 - 10, audiocore_get_audio_buffer_space());
core1_context.pcm_buffer_write = 10;
core1_context.pcm_buffer_read = 0;
TEST_ASSERT_EQUAL(PCM_BUFFER_SIZE - 1 - 10, audiocore_get_pcm_buffer_space());
// write < read
shared_context.audio_buffer_write = 0;
shared_context.audio_buffer_read = 10;
TEST_ASSERT_EQUAL(9, audiocore_get_audio_buffer_space());
core1_context.pcm_buffer_write = 0;
core1_context.pcm_buffer_read = 10;
TEST_ASSERT_EQUAL(9, audiocore_get_pcm_buffer_space());
}
void test_audiocore_buffer_avail(void)
{
// empty ring buffer
shared_context.audio_buffer_read = shared_context.audio_buffer_write = 0;
TEST_ASSERT_EQUAL(0, audiocore_get_audio_buffer_avail());
core1_context.pcm_buffer_read = core1_context.pcm_buffer_write = 0;
TEST_ASSERT_EQUAL(0, audiocore_get_pcm_buffer_avail());
shared_context.audio_buffer_read = shared_context.audio_buffer_write = 23;
TEST_ASSERT_EQUAL(0, audiocore_get_audio_buffer_avail());
core1_context.pcm_buffer_read = core1_context.pcm_buffer_write = 23;
TEST_ASSERT_EQUAL(0, audiocore_get_pcm_buffer_avail());
shared_context.audio_buffer_read = shared_context.audio_buffer_write = AUDIO_BUFFER_SIZE - 1;
TEST_ASSERT_EQUAL(0, audiocore_get_audio_buffer_avail());
core1_context.pcm_buffer_read = core1_context.pcm_buffer_write = PCM_BUFFER_SIZE - 1;
TEST_ASSERT_EQUAL(0, audiocore_get_pcm_buffer_avail());
// full ring buffer
shared_context.audio_buffer_write = 0;
shared_context.audio_buffer_read = 1;
TEST_ASSERT_EQUAL(AUDIO_BUFFER_SIZE - 1, audiocore_get_audio_buffer_avail());
core1_context.pcm_buffer_write = 0;
core1_context.pcm_buffer_read = 1;
TEST_ASSERT_EQUAL(PCM_BUFFER_SIZE - 1, audiocore_get_pcm_buffer_avail());
shared_context.audio_buffer_write = AUDIO_BUFFER_SIZE - 1;
shared_context.audio_buffer_read = 0;
TEST_ASSERT_EQUAL(AUDIO_BUFFER_SIZE - 1, audiocore_get_audio_buffer_avail());
core1_context.pcm_buffer_write = PCM_BUFFER_SIZE - 1;
core1_context.pcm_buffer_read = 0;
TEST_ASSERT_EQUAL(PCM_BUFFER_SIZE - 1, audiocore_get_pcm_buffer_avail());
// write > read
shared_context.audio_buffer_write = 10;
shared_context.audio_buffer_read = 0;
TEST_ASSERT_EQUAL(10, audiocore_get_audio_buffer_avail());
core1_context.pcm_buffer_write = 10;
core1_context.pcm_buffer_read = 0;
TEST_ASSERT_EQUAL(10, audiocore_get_pcm_buffer_avail());
// write < read
shared_context.audio_buffer_write = 0;
shared_context.audio_buffer_read = 10;
TEST_ASSERT_EQUAL(AUDIO_BUFFER_SIZE - 10, audiocore_get_audio_buffer_avail());
core1_context.pcm_buffer_write = 0;
core1_context.pcm_buffer_read = 10;
TEST_ASSERT_EQUAL(PCM_BUFFER_SIZE - 10, audiocore_get_pcm_buffer_avail());
}
static unsigned fill_buffer_helper(void)
@@ -132,11 +136,11 @@ static unsigned fill_buffer_helper(void)
uint32_t ctr = 0;
unsigned avail, filled = 0;
while ((avail = audiocore_get_audio_buffer_space()) > 0) {
while ((avail = audiocore_get_pcm_buffer_space()) > 0) {
const unsigned todo = avail > 100 ? 100 : avail;
for (unsigned i = 0; i < todo; ++i)
test_data[i] = ctr++;
audiocore_audio_buffer_put(test_data, todo);
audiocore_pcm_buffer_put(test_data, todo);
filled += todo;
}
return filled;
@@ -144,18 +148,18 @@ static unsigned fill_buffer_helper(void)
void test_audiocore_buffer_put(void)
{
shared_context.audio_buffer_read = shared_context.audio_buffer_write = 0;
core1_context.pcm_buffer_read = core1_context.pcm_buffer_write = 0;
TEST_ASSERT_EQUAL(AUDIO_BUFFER_SIZE - 1, fill_buffer_helper());
for (unsigned i = 0; i < AUDIO_BUFFER_SIZE - 1; ++i) {
TEST_ASSERT_EQUAL(i, shared_context.audio_buffer[i]);
TEST_ASSERT_EQUAL(PCM_BUFFER_SIZE - 1, fill_buffer_helper());
for (unsigned i = 0; i < PCM_BUFFER_SIZE - 1; ++i) {
TEST_ASSERT_EQUAL(i, core1_context.pcm_buffer[i]);
}
// test wraparound fill
shared_context.audio_buffer_read = shared_context.audio_buffer_write = AUDIO_BUFFER_SIZE - 10;
TEST_ASSERT_EQUAL(AUDIO_BUFFER_SIZE - 1, fill_buffer_helper());
for (unsigned i = 0; i < AUDIO_BUFFER_SIZE - 1; ++i) {
TEST_ASSERT_EQUAL(i, shared_context.audio_buffer[(i + AUDIO_BUFFER_SIZE - 10) % AUDIO_BUFFER_SIZE]);
core1_context.pcm_buffer_read = core1_context.pcm_buffer_write = PCM_BUFFER_SIZE - 10;
TEST_ASSERT_EQUAL(PCM_BUFFER_SIZE - 1, fill_buffer_helper());
for (unsigned i = 0; i < PCM_BUFFER_SIZE - 1; ++i) {
TEST_ASSERT_EQUAL(i, core1_context.pcm_buffer[(i + PCM_BUFFER_SIZE - 10) % PCM_BUFFER_SIZE]);
}
}
@@ -165,9 +169,9 @@ static unsigned get_buffer_helper(void)
uint32_t ctr = 0;
unsigned avail, gotten = 0;
while ((avail = audiocore_get_audio_buffer_avail()) > 0) {
while ((avail = audiocore_get_pcm_buffer_avail()) > 0) {
const unsigned todo = avail > 100 ? 100 : avail;
audiocore_audio_buffer_get(test_data, todo);
audiocore_pcm_buffer_get(test_data, todo);
for (unsigned i = 0; i < todo; ++i)
TEST_ASSERT_EQUAL(ctr++, test_data[i]);
gotten += todo;
@@ -177,16 +181,16 @@ static unsigned get_buffer_helper(void)
void test_audiocore_buffer_get(void)
{
shared_context.audio_buffer_read = 0;
shared_context.audio_buffer_write = AUDIO_BUFFER_SIZE - 1;
for (unsigned i = 0; i < AUDIO_BUFFER_SIZE - 1; ++i)
shared_context.audio_buffer[i] = i;
TEST_ASSERT_EQUAL(AUDIO_BUFFER_SIZE - 1, get_buffer_helper());
core1_context.pcm_buffer_read = 0;
core1_context.pcm_buffer_write = PCM_BUFFER_SIZE - 1;
for (unsigned i = 0; i < PCM_BUFFER_SIZE - 1; ++i)
core1_context.pcm_buffer[i] = i;
TEST_ASSERT_EQUAL(PCM_BUFFER_SIZE - 1, get_buffer_helper());
// test wraparound read
shared_context.audio_buffer_read = 10;
shared_context.audio_buffer_write = 9;
for (unsigned i = 0; i < AUDIO_BUFFER_SIZE - 1; ++i)
shared_context.audio_buffer[(i + 10) % AUDIO_BUFFER_SIZE] = i;
TEST_ASSERT_EQUAL(AUDIO_BUFFER_SIZE - 1, get_buffer_helper());
core1_context.pcm_buffer_read = 10;
core1_context.pcm_buffer_write = 9;
for (unsigned i = 0; i < PCM_BUFFER_SIZE - 1; ++i)
core1_context.pcm_buffer[(i + 10) % PCM_BUFFER_SIZE] = i;
TEST_ASSERT_EQUAL(PCM_BUFFER_SIZE - 1, get_buffer_helper());
}

View File

@@ -3,8 +3,12 @@
#pragma once
#include <stdbool.h>
struct spin_lock;
typedef struct spin_lock spin_lock_t;
bool multicore_fifo_rvalid(void);
void multicore_fifo_push_blocking(unsigned val);
unsigned multicore_fifo_pop_blocking(void);
#define __wfe()