|
|
|
|
|
|
|
|
right_1st = NULL; |
|
|
right_1st = NULL; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void copy_from_buffers(uint32_t *dst, int16_t *left, int16_t *right, unsigned int len) |
|
|
|
|
|
{ |
|
|
|
|
|
// TODO: optimize... |
|
|
|
|
|
while (len > 0) { |
|
|
|
|
|
*dst++ = (*right++ << 16) | (*left++ & 0xFFFF); |
|
|
|
|
|
len--; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void AudioOutputUSB::update(void) |
|
|
void AudioOutputUSB::update(void) |
|
|
{ |
|
|
{ |
|
|
audio_block_t *left, *right; |
|
|
audio_block_t *left, *right; |
|
|
|
|
|
|
|
|
right = left; |
|
|
right = left; |
|
|
} |
|
|
} |
|
|
__disable_irq(); |
|
|
__disable_irq(); |
|
|
if (left_1st == NULL) { |
|
|
|
|
|
|
|
|
if (!transmitting) { |
|
|
|
|
|
copy_from_buffers((uint32_t *)usb_audio_transmit_buffer, |
|
|
|
|
|
left->data, right->data, 44); |
|
|
|
|
|
left_1st = left; |
|
|
|
|
|
right_1st = right; |
|
|
|
|
|
left_2nd = NULL; |
|
|
|
|
|
right_2nd = NULL; |
|
|
|
|
|
offset_1st = 44; |
|
|
|
|
|
outgoing_count = AUDIO_BLOCK_SAMPLES - 44; |
|
|
|
|
|
usb_tx_isochronous(AUDIO_TX_ENDPOINT, usb_audio_transmit_buffer, 176); |
|
|
|
|
|
transmitting = 1; |
|
|
|
|
|
//serial_print("t"); |
|
|
|
|
|
} else if (left_1st == NULL) { |
|
|
left_1st = left; |
|
|
left_1st = left; |
|
|
right_1st = right; |
|
|
right_1st = right; |
|
|
offset_1st = 0; |
|
|
offset_1st = 0; |
|
|
|
|
|
|
|
|
right_2nd = right; |
|
|
right_2nd = right; |
|
|
offset_1st = 0; // TODO: discard part of this data? |
|
|
offset_1st = 0; // TODO: discard part of this data? |
|
|
outgoing_count = AUDIO_BLOCK_SAMPLES*2; |
|
|
outgoing_count = AUDIO_BLOCK_SAMPLES*2; |
|
|
serial_print("*"); |
|
|
|
|
|
|
|
|
//serial_print("*"); |
|
|
release(discard1); |
|
|
release(discard1); |
|
|
release(discard2); |
|
|
release(discard2); |
|
|
} |
|
|
} |
|
|
__enable_irq(); |
|
|
__enable_irq(); |
|
|
if (!transmitting) { |
|
|
|
|
|
serial_print("b"); |
|
|
|
|
|
usb_tx_isochronous(AUDIO_TX_ENDPOINT, usb_audio_transmit_buffer, 176); |
|
|
|
|
|
transmitting = 1; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// no data to transmit |
|
|
// no data to transmit |
|
|
unsigned int usb_audio_transmit_callback(void) |
|
|
unsigned int usb_audio_transmit_callback(void) |
|
|
{ |
|
|
{ |
|
|
serial_print("."); |
|
|
|
|
|
AudioOutputUSB::transmitting = 0; |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static uint32_t count=5; |
|
|
|
|
|
uint32_t avail, num, target, offset, len=0; |
|
|
|
|
|
audio_block_t *left, *right; |
|
|
|
|
|
|
|
|
|
|
|
if (usb_audio_transmit_setting == 0) { |
|
|
|
|
|
AudioOutputUSB::transmitting = 0; |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
//serial_print("."); |
|
|
|
|
|
|
|
|
|
|
|
if (++count < 9) { // TODO: dynamic adjust to match USB rate |
|
|
|
|
|
target = 44; |
|
|
|
|
|
} else { |
|
|
|
|
|
count = 0; |
|
|
|
|
|
target = 45; |
|
|
|
|
|
} |
|
|
|
|
|
while (len < target) { |
|
|
|
|
|
num = target - len; |
|
|
|
|
|
left = AudioOutputUSB::left_1st; |
|
|
|
|
|
if (left == NULL) { |
|
|
|
|
|
// buffer underrun - PC is consuming too quickly |
|
|
|
|
|
memset(usb_audio_transmit_buffer + len, 0, num * 4); |
|
|
|
|
|
//serial_print("%"); |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
right = AudioOutputUSB::right_1st; |
|
|
|
|
|
offset = AudioOutputUSB::offset_1st; |
|
|
|
|
|
|
|
|
|
|
|
avail = AUDIO_BLOCK_SAMPLES - offset; |
|
|
|
|
|
if (num > avail) num = avail; |
|
|
|
|
|
|
|
|
|
|
|
copy_from_buffers((uint32_t *)usb_audio_transmit_buffer + len, |
|
|
|
|
|
left->data + offset, right->data + offset, num); |
|
|
|
|
|
len += num; |
|
|
|
|
|
offset += num; |
|
|
|
|
|
if (offset >= AUDIO_BLOCK_SAMPLES) { |
|
|
|
|
|
AudioStream::release(left); |
|
|
|
|
|
AudioStream::release(right); |
|
|
|
|
|
AudioOutputUSB::left_1st = AudioOutputUSB::left_2nd; |
|
|
|
|
|
AudioOutputUSB::left_2nd = NULL; |
|
|
|
|
|
AudioOutputUSB::right_1st = AudioOutputUSB::right_2nd; |
|
|
|
|
|
AudioOutputUSB::right_2nd = NULL; |
|
|
|
|
|
AudioOutputUSB::offset_1st = 0; |
|
|
|
|
|
} else { |
|
|
|
|
|
AudioOutputUSB::offset_1st = offset; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return target * 4; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif // F_CPU |
|
|
#endif // F_CPU |