static void rdpsnd_queue_complete_pending(void) { struct timeval now; long elapsed; struct audio_packet *packet; gettimeofday(&now, NULL); while (queue_pending != queue_lo) { packet = &packet_queue[queue_pending]; if (now.tv_sec < packet->completion_tv.tv_sec) break; if ((now.tv_sec == packet->completion_tv.tv_sec) && (now.tv_usec < packet->completion_tv.tv_usec)) break; elapsed = (packet->completion_tv.tv_sec - packet->arrive_tv.tv_sec) * 1000000 + (packet->completion_tv.tv_usec - packet->arrive_tv.tv_usec); elapsed /= 1000; xfree(packet->s.data); rdpsnd_send_completion((packet->tick + elapsed) % 65536, packet->index); queue_pending = (queue_pending + 1) % MAX_QUEUE; } }
void wave_out_close(void) { /* Ack all remaining packets */ while (queue_lo != queue_hi) { rdpsnd_send_completion(packet_queue[queue_lo].tick, packet_queue[queue_lo].index); free(packet_queue[queue_lo].s.data); queue_lo = (queue_lo + 1) % MAX_QUEUE; } if (o_device != NULL) ao_close(o_device); ao_shutdown(); }
void wave_out_close(void) { /* Ack all remaining packets */ while (queue_lo != queue_hi) { rdpsnd_send_completion(packet_queue[queue_lo].tick, packet_queue[queue_lo].index); free(packet_queue[queue_lo].s.data); queue_lo = (queue_lo + 1) % MAX_QUEUE; } #if defined I_FLUSH && defined FLUSHW /* Flush the audiobuffer */ ioctl(This->dsp_, I_FLUSH, FLUSHW); #endif #if defined AUDIO_FLUSH ioctl(This->dsp_, AUDIO_FLUSH, NULL); #endif close(This->dsp_); }
void wave_out_close(void) { /* Ack all remaining packets */ #if (defined(IRIX_DEBUG)) fprintf(stderr, "wave_out_close: begin\n"); #endif while (queue_lo != queue_hi) { rdpsnd_send_completion(packet_queue[queue_lo].tick, packet_queue[queue_lo].index); free(packet_queue[queue_lo].s.data); queue_lo = (queue_lo + 1) % MAX_QUEUE; } alDiscardFrames(output_port, 0); alClosePort(output_port); alFreeConfig(audioconfig); #if (defined(IRIX_DEBUG)) fprintf(stderr, "wave_out_close: returning\n"); #endif }
void wave_out_play(void) { struct audio_packet *packet; ssize_t len; STREAM out; static long startedat_us; static long startedat_s; static BOOL started = False; struct timeval tv; audio_buf_info info; while (1) { if (queue_lo == queue_hi) { g_dsp_busy = 0; return; } packet = &packet_queue[queue_lo]; out = &packet->s; if (!started) { gettimeofday(&tv, NULL); startedat_us = tv.tv_usec; startedat_s = tv.tv_sec; started = True; } len = out->end - out->p; if (!g_driver_broken) { memset(&info, 0, sizeof(info)); if (ioctl(g_dsp_fd, SNDCTL_DSP_GETOSPACE, &info) == -1) { perror("SNDCTL_DSP_GETOSPACE"); return; } if (info.fragments == 0) { g_dsp_busy = 1; return; } if (info.fragments * info.fragsize < len && info.fragments * info.fragsize > 0) { len = info.fragments * info.fragsize; } } len = write(g_dsp_fd, out->p, len); if (len == -1) { if (errno != EWOULDBLOCK) perror("write audio"); g_dsp_busy = 1; return; } out->p += len; if (out->p == out->end) { long long duration; long elapsed; gettimeofday(&tv, NULL); duration = (out->size * (1000000 / (g_samplewidth * g_snd_rate))); elapsed = (tv.tv_sec - startedat_s) * 1000000 + (tv.tv_usec - startedat_us); if (elapsed >= (duration * 85) / 100) { rdpsnd_send_completion(packet->tick, packet->index); free(out->data); queue_lo = (queue_lo + 1) % MAX_QUEUE; started = False; } else { g_dsp_busy = 1; return; } } } }
void wave_out_play(void) { struct audio_packet *packet; STREAM out; char outbuf[WAVEOUTBUF]; int offset, len, i; static long prev_s, prev_us; unsigned int duration; struct timeval tv; int next_tick; if (g_reopened) { g_reopened = False; gettimeofday(&tv, NULL); prev_s = tv.tv_sec; prev_us = tv.tv_usec; } if (queue_lo == queue_hi) { g_dsp_busy = 0; return; } packet = &packet_queue[queue_lo]; out = &packet->s; if (((queue_lo + 1) % MAX_QUEUE) != queue_hi) { next_tick = packet_queue[(queue_lo + 1) % MAX_QUEUE].tick; } else { next_tick = (packet->tick + 65535) % 65536; } len = 0; if (g_samplerate == 22050) { /* Resample to 44100 */ for (i = 0; (i < ((WAVEOUTBUF / 4) * (3 - g_samplewidth))) && (out->p < out->end); i++) { /* On a stereo-channel we must make sure that left and right does not get mixed up, so we need to expand the sample- data with channels in mind: 1234 -> 12123434 If we have a mono-channel, we can expand the data by simply doubling the sample-data: 1234 -> 11223344 */ if (g_channels == 2) offset = ((i * 2) - (i & 1)) * g_samplewidth; else offset = (i * 2) * g_samplewidth; memcpy(&outbuf[offset], out->p, g_samplewidth); memcpy(&outbuf[g_channels * g_samplewidth + offset], out->p, g_samplewidth); out->p += g_samplewidth; len += 2 * g_samplewidth; } } else { len = (WAVEOUTBUF > (out->end - out->p)) ? (out->end - out->p) : WAVEOUTBUF; memcpy(outbuf, out->p, len); out->p += len; } ao_play(o_device, outbuf, len); gettimeofday(&tv, NULL); duration = ((tv.tv_sec - prev_s) * 1000000 + (tv.tv_usec - prev_us)) / 1000; if (packet->tick > next_tick) next_tick += 65536; if ((out->p == out->end) || duration > next_tick - packet->tick + 500) { prev_s = tv.tv_sec; prev_us = tv.tv_usec; if (abs((next_tick - packet->tick) - duration) > 20) { DEBUG(("duration: %d, calc: %d, ", duration, next_tick - packet->tick)); DEBUG(("last: %d, is: %d, should: %d\n", packet->tick, (packet->tick + duration) % 65536, next_tick % 65536)); } /* Until all drivers are using the windows sound-ticks, we need to substract the 50 ticks added later by rdpsnd.c */ rdpsnd_send_completion(((packet->tick + duration) % 65536) - 50, packet->index); free(out->data); queue_lo = (queue_lo + 1) % MAX_QUEUE; } g_dsp_busy = 1; return; }
void wave_out_play(void) { struct audio_packet *packet; ssize_t len; unsigned int i; uint8 swap; STREAM out; static BOOL swapped = False; int gf; while (1) { if (queue_lo == queue_hi) { This->dsp_bu = False; return; } packet = &packet_queue[queue_lo]; out = &packet->s; /* Swap the current packet, but only once */ if (g_swapaudio && !swapped) { for (i = 0; i < out->end - out->p; i += 2) { swap = *(out->p + i); *(out->p + i) = *(out->p + i + 1); *(out->p + i + 1) = swap; } swapped = True; } len = out->end - out->p; alWriteFrames(output_port, out->p, len / combinedFrameSize); out->p += len; if (out->p == out->end) { gf = alGetFilled(output_port); if (gf < (4 * maxFillable / 10)) { rdpsnd_send_completion(packet->tick, packet->index); free(out->data); queue_lo = (queue_lo + 1) % MAX_QUEUE; swapped = False; } else { #if (defined(IRIX_DEBUG)) /* fprintf(stderr,"Busy playing...\n"); */ #endif This->dsp_bu = True; usleep(10); return; } } } }
static void rdpsnd_process_packet(uint8 opcode, STREAM s) { uint16 vol_left, vol_right; static uint16 tick, format; static uint8 packet_index; switch (opcode) { case RDPSND_WRITE: in_uint16_le(s, tick); in_uint16_le(s, format); in_uint8(s, packet_index); in_uint8s(s, 3); DEBUG_SOUND(("RDPSND: RDPSND_WRITE(tick: %u, format: %u, index: %u, data: %u bytes)\n", (unsigned) tick, (unsigned) format, (unsigned) packet_index, (unsigned) s->size - 8)); if (format >= MAX_FORMATS) { error("RDPSND: Invalid format index\n"); break; } if (!device_open || (format != current_format)) { /* * If we haven't selected a device by now, then either * we've failed to find a working device, or the server * is sending bogus RDPSND_WRITE. */ if (!current_driver) { rdpsnd_send_completion(tick, packet_index); break; } if (!device_open && !current_driver->wave_out_open()) { rdpsnd_send_completion(tick, packet_index); break; } if (!current_driver->wave_out_set_format(&formats[format])) { rdpsnd_send_completion(tick, packet_index); current_driver->wave_out_close(); device_open = False; break; } device_open = True; current_format = format; } rdpsnd_queue_write(rdpsnd_dsp_process (s->p, s->end - s->p, current_driver, &formats[current_format]), tick, packet_index); return; break; case RDPSND_CLOSE: DEBUG_SOUND(("RDPSND: RDPSND_CLOSE()\n")); if (device_open) current_driver->wave_out_close(); device_open = False; break; case RDPSND_NEGOTIATE: rdpsnd_process_negotiate(s); break; case RDPSND_PING: rdpsnd_process_ping(s); break; case RDPSND_SET_VOLUME: in_uint16_le(s, vol_left); in_uint16_le(s, vol_right); DEBUG_SOUND(("RDPSND: RDPSND_VOLUME(left: 0x%04x (%u %%), right: 0x%04x (%u %%))\n", (unsigned) vol_left, (unsigned) vol_left / 655, (unsigned) vol_right, (unsigned) vol_right / 655)); if (device_open) current_driver->wave_out_volume(vol_left, vol_right); break; default: unimpl("RDPSND packet type %x\n", opcode); break; } }
void wave_out_play(void) { struct audio_packet *packet; audio_info_t info; ssize_t len; unsigned int i; uint8 swap; STREAM out; static BOOL swapped = False; static BOOL sentcompletion = True; static uint32 samplecnt = 0; static uint32 numsamples; while (1) { if (g_reopened) { /* Device was just (re)openend */ samplecnt = 0; swapped = False; sentcompletion = True; g_reopened = False; } if (queue_lo == queue_hi) { This->dsp_bu = 0; return; } packet = &packet_queue[queue_lo]; out = &packet->s; /* Swap the current packet, but only once */ if (g_swapaudio && !swapped) { for (i = 0; i < out->end - out->p; i += 2) { swap = *(out->p + i); *(out->p + i) = *(out->p + i + 1); *(out->p + i + 1) = swap; } swapped = True; } if (sentcompletion) { sentcompletion = False; numsamples = (out->end - out->p) / g_samplewidth; } len = 0; if (out->end != out->p) { len = write(This->dsp_, out->p, out->end - out->p); if (len == -1) { if (errno != EWOULDBLOCK) perror("write audio"); This->dsp_bu = 1; return; } } out->p += len; if (out->p == out->end) { if (ioctl(This->dsp_, AUDIO_GETINFO, &info) == -1) { perror("AUDIO_GETINFO"); return; } /* Ack the packet, if we have played at least 70% */ if (info.play.samples >= samplecnt + ((numsamples * 7) / 10)) { samplecnt += numsamples; rdpsnd_send_completion(packet->tick, packet->index); free(out->data); queue_lo = (queue_lo + 1) % MAX_QUEUE; swapped = False; sentcompletion = True; } else { This->dsp_bu = 1; return; } } } }
void rdpsnd_process(STREAM s) { uint8 type; uint16 datalen; uint32 volume; static uint16 tick, format; static uint8 packet_index; static BOOL awaiting_data_packet; #ifdef RDPSND_DEBUG printf("RDPSND recv:\n"); hexdump(s->p, s->end - s->p); #endif if (awaiting_data_packet) { if (format >= MAX_FORMATS) { error("RDPSND: Invalid format index\n"); return; } if (!device_open || (format != current_format)) { if (!device_open && !wave_out_open()) { rdpsnd_send_completion(tick, packet_index); return; } if (!wave_out_set_format(&formats[format])) { rdpsnd_send_completion(tick, packet_index); wave_out_close(); device_open = False; return; } device_open = True; current_format = format; } wave_out_write(s, tick, packet_index); awaiting_data_packet = False; return; } in_uint8(s, type); in_uint8s(s, 1); /* unknown? */ in_uint16_le(s, datalen); switch (type) { case RDPSND_WRITE: in_uint16_le(s, tick); in_uint16_le(s, format); in_uint8(s, packet_index); awaiting_data_packet = True; break; case RDPSND_CLOSE: wave_out_close(); device_open = False; break; case RDPSND_NEGOTIATE: rdpsnd_process_negotiate(s); break; case RDPSND_UNKNOWN6: rdpsnd_process_unknown6(s); break; case RDPSND_SET_VOLUME: in_uint32(s, volume); if (device_open) { wave_out_volume((volume & 0xffff), (volume & 0xffff0000) >> 16); } break; default: unimpl("RDPSND packet type %d\n", type); break; } }