| 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 |