Skip to content

Adding USB-audio feedback and mute command to usb_sound_card.c #53

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions apps/usb_sound_card/usb_sound_card.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
// todo forget why this is using core 1 for sound: presumably not necessary
// todo noop when muted

// modification for USB-sound rate feedback and mute
#define USB_FEEDBACK 1 // USB-audio rate feedback using buffer status
#define MUTE_CMD 1 // mute command
////////////////////////////////////////

CU_REGISTER_DEBUG_PINS(audio_timing)

// ---- select at most one ---
Expand All @@ -40,7 +45,12 @@ static char *descriptor_strings[] =
#undef AUDIO_SAMPLE_FREQ
#define AUDIO_SAMPLE_FREQ(frq) (uint8_t)(frq), (uint8_t)((frq >> 8)), (uint8_t)((frq >> 16))

#if USB_FEEDBACK
// when USB-audio feedback applies, it receives upto 49 samples in each packet
#define AUDIO_MAX_PACKET_SIZE(freq) (uint8_t)(((freq + 1999) / 1000) * 4)
#else
#define AUDIO_MAX_PACKET_SIZE(freq) (uint8_t)(((freq + 999) / 1000) * 4)
#endif
#define FEATURE_MUTE_CONTROL 1u
#define FEATURE_VOLUME_CONTROL 2u

Expand Down Expand Up @@ -256,6 +266,22 @@ static struct {

static struct audio_buffer_pool *producer_pool;

#if USB_FEEDBACK
#define BUFFER_NUM 16 // number of buffer

//for USB-audio rate feedback, number of vacant buffers is used
static int countFreeBuffers(void) {
int i = 0;

audio_buffer_t *audio_buffer = producer_pool->free_list;
while(audio_buffer != NULL) {
audio_buffer = audio_buffer->next;
i++;
}
return i;
}
#endif

static void _as_audio_packet(struct usb_endpoint *ep) {
assert(ep->current_transfer);
struct usb_buffer *usb_buffer = usb_current_out_packet_buffer(ep);
Expand All @@ -268,6 +294,11 @@ static void _as_audio_packet(struct usb_endpoint *ep) {
assert(audio_buffer->sample_count);
assert(audio_buffer->max_sample_count >= audio_buffer->sample_count);
uint16_t vol_mul = audio_state.vol_mul;
#if MUTE_CMD
if(audio_state.mute) {
vol_mul = 1;
}
#endif
int16_t *out = (int16_t *) audio_buffer->buffer->bytes;
int16_t *in = (int16_t *) usb_buffer->data;
for (int i = 0; i < audio_buffer->sample_count * 2; i++) {
Expand All @@ -288,8 +319,14 @@ static void _as_sync_packet(struct usb_endpoint *ep) {
assert(buffer->data_max >= 3);
buffer->data_len = 3;

#if USB_FEEDBACK
// calc rate adjustment value between -40 to 40
int feedbackvalue = (countFreeBuffers() - BUFFER_NUM / 2) * (2 * 40 / BUFFER_NUM);
uint feedback = ((audio_state.freq + feedbackvalue) << 14u) / 1000u;
#else
// todo lie thru our teeth for now
uint feedback = (audio_state.freq << 14u) / 1000u;
#endif

buffer->data[0] = feedback;
buffer->data[1] = feedback >> 8u;
Expand Down Expand Up @@ -613,7 +650,13 @@ int main(void) {
.sample_stride = 4
};

#if USB_FEEDBACK
// when USB-audio feedback applies, it receives upto 49 samples in each packet
producer_pool = audio_new_producer_pool(&producer_format, BUFFER_NUM,
AUDIO_MAX_PACKET_SIZE(AUDIO_FREQ_MAX) / 4);
#else
producer_pool = audio_new_producer_pool(&producer_format, 8, 48); // todo correct size
#endif
bool __unused ok;
struct audio_i2s_config config = {
.data_pin = PICO_AUDIO_I2S_DATA_PIN,
Expand All @@ -628,7 +671,14 @@ int main(void) {
panic("PicoAudio: Unable to open audio device.\n");
}

#if USB_FEEDBACK
// It is not clear what is meant by the number "96" but I fixed it as well as producer_pool.
// ok = audio_i2s_connect_extra(producer_pool, false, 2, 96, NULL);
ok = audio_i2s_connect_extra(producer_pool, false, 2,
AUDIO_MAX_PACKET_SIZE(AUDIO_FREQ_MAX) / 2, NULL);
#else
ok = audio_i2s_connect_extra(producer_pool, false, 2, 96, NULL);
#endif
assert(ok);
usb_sound_card_init();

Expand Down