/* This function needs to be modified to return some indication of how well * or not we are doing. */ int audio_rw_process(session_t *spi, session_t *spo, struct s_mixer *ms) { uint32_t cushion_size, read_dur; struct s_cushion_struct *c; int trailing_silence, new_cushion, cushion_step, diff; const audio_format* ofmt; sample *bufp; session_validate(spi); session_validate(spo); c = spi->cushion; if ((read_dur = tx_read_audio(spi->tb)) <= 0) { return 0; } else { if (!spi->audio_device) { /* no device means no cushion */ return read_dur; } } xmemchk(); /* read_dur now reflects the amount of real time it took us to get * through the last cycle of processing. */ if (spo->lecture == TRUE && spo->auto_lecture == 0) { cushion_update(c, read_dur, CUSHION_MODE_LECTURE); } else { cushion_update(c, read_dur, CUSHION_MODE_CONFERENCE); } /* Following code will try to achieve new cushion size without * messing up the audio... * First case is when we are in trouble and the output has gone dry. * In this case we write out a complete new cushion with the desired * size. We do not care how much of it is going to be real audio and * how much silence so long as the silence is at the head of the new * cushion. If the silence was at the end we would be creating * another silence gap... */ cushion_size = cushion_get_size(c); ofmt = audio_get_ofmt(spi->audio_device); if (cushion_size < read_dur) { debug_msg("catch up! read_dur(%d) > cushion_size(%d)\n", read_dur, cushion_size); /* Use a step for the cushion to keep things nicely rounded */ /* in the mixing. Round it up. */ new_cushion = cushion_use_estimate(c); assert(new_cushion >= 0 && new_cushion < 100000); /* The mix routine also needs to know for how long the */ /* output went dry so that it can adjust the time. */ mix_new_cushion(ms, cushion_size, new_cushion, (read_dur - cushion_size), &bufp); audio_device_write(spo, bufp, new_cushion); /* We've blocked for this long for whatever reason */ cushion_size = new_cushion; } else { trailing_silence = mix_get_audio(ms, read_dur * ofmt->channels, &bufp); cushion_step = cushion_get_step(c); diff = 0; if (trailing_silence > cushion_step) { /* Check whether we need to adjust the cushion */ diff = cushion_diff_estimate_size(c); if (abs(diff) < cushion_step) { diff = 0; } } /* If diff is less than zero then we must decrease the */ /* cushion so loose some of the trailing silence. */ if (diff < 0 && mix_active(ms) == FALSE && source_list_source_count(spi->active_sources) == 0) { /* Only decrease cushion if not playing anything out */ uint32_t old_cushion; old_cushion = cushion_get_size(c); if (read_dur > (unsigned)cushion_step) { cushion_step_down(c); if (cushion_get_size(c) != old_cushion) { debug_msg("Decreasing cushion\n"); read_dur -= cushion_step; } } } assert(read_dur < 0x7fffffff); audio_device_write(spo, bufp, read_dur); /* * If diff is greater than zero then we must increase the * cushion so increase the amount of trailing silence. */ if (diff > 0) { assert(cushion_step > 0); audio_device_write(spo, zero_buf, cushion_step); cushion_step_up(c); debug_msg("Increasing cushion.\n"); } } return (read_dur); }
void wavplay_thread_entry(void *parameter) { FILE *fp = NULL; uint16_t *buffer = NULL; struct wav_info *info = NULL; fp = fopen(file_name, "rb"); if (!fp) { printf("open file failed!\n"); goto __exit; } info = (struct wav_info *) malloc(sizeof(*info)); if (!info) goto __exit; if (fread(&(info->header), sizeof(struct RIFF_HEADER_DEF), 1, fp) != 1) goto __exit; if (fread(&(info->fmt_block), sizeof(struct FMT_BLOCK_DEF), 1, fp) != 1) goto __exit; if (fread(&(info->data_block), sizeof(struct DATA_BLOCK_DEF), 1, fp) != 1) goto __exit; printf("wav information:\n"); printf("samplerate %u\n", info->fmt_block.wav_format.SamplesPerSec); printf("channel %u\n", info->fmt_block.wav_format.Channels); audio_device_init(); audio_device_open(); audio_device_set_rate(info->fmt_block.wav_format.SamplesPerSec); while (!feof(fp)) { int length; buffer = (uint16_t *)audio_device_get_buffer(RT_NULL); length = fread(buffer, 1, BUFSZ, fp); if (length) { if (info->fmt_block.wav_format.Channels == 1) { /* extend to stereo channels */ int index; uint16_t *ptr; ptr = (uint16_t *)((uint8_t *)buffer + BUFSZ * 2); for (index = 1; index < BUFSZ / 2; index ++) { *ptr = *(ptr - 1) = buffer[BUFSZ / 2 - index]; ptr -= 2; } length = length * 2; } audio_device_write((uint8_t *)buffer, length); } else { audio_device_put_buffer((uint8_t *)buffer); break; } } audio_device_close(); __exit: if (fp) fclose(fp); if (info) free(info); }