static void process_samples(long long now, int min_buf) { int nframes, retry; double period, mf_time_cur; mf_time_cur = pcm_time_lock(pcm_stream); do { retry = 0; period = pcm_frame_period_us(flus_srate); nframes = (now - mf_time_cur) / period; if (nframes > FLUS_MAX_BUF) { nframes = FLUS_MAX_BUF; retry = 1; } if (nframes >= min_buf) { mf_process_samples(nframes); mf_time_cur = pcm_get_stream_time(pcm_stream); if (debug_level('S') >= 5) S_printf("MIDI: processed %i samples with fluidsynth\n", nframes); } } while (retry); pcm_time_unlock(pcm_stream); }
static void dspio_process_dma(struct dspio_state *state) { int dma_cnt, nfr, in_fifo_cnt, out_fifo_cnt, i, j, tlocked; unsigned long long time_dst; double output_time_cur; sndbuf_t buf[PCM_MAX_BUF][SNDBUF_CHANS]; static int warned; dma_cnt = in_fifo_cnt = out_fifo_cnt = 0; if (state->dma.running) { state->dma.stereo = sb_dma_samp_stereo(); state->dma.rate = sb_get_dma_sampling_rate(); state->dma.samp_signed = sb_dma_samp_signed(); state->dma.dsp_fifo_enabled = sb_fifo_enabled(); dma_cnt += state->dma.input ? dspio_drain_input(state) : dspio_fill_output(state); } if (!state->output_running && !state->input_running) return; time_dst = GETusTIME(0); if (state->output_running) { output_time_cur = pcm_time_lock(state->dma_strm); tlocked = 1; nfr = calc_nframes(state, output_time_cur, time_dst); } else { nfr = 0; tlocked = 0; } for (i = 0; i < nfr; i++) { for (j = 0; j < state->dma.stereo + 1; j++) { if (state->dma.running && !dspio_output_fifo_filled(state)) { if (!dspio_run_dma(state)) break; dma_cnt++; } if (!dspio_get_output_sample(state, &buf[i][j], state->dma.is16bit)) break; #if 0 /* if speaker disabled, overwrite DMA data with silence */ /* on SB16 is not used */ if (!state->speaker) dma_get_silence(state->dma.samp_signed, state->dma.is16bit, &buf[i][j]); #endif } if (j != state->dma.stereo + 1) break; out_fifo_cnt++; } if (out_fifo_cnt && state->dma.rate) { pcm_write_interleaved(buf, out_fifo_cnt, state->dma.rate, pcm_get_format(state->dma.is16bit, state->dma.samp_signed), state->dma.stereo + 1, state->dma_strm); output_time_cur = pcm_get_stream_time(state->dma_strm); if (state->dma.running && output_time_cur > time_dst - 1) { pcm_clear_flag(state->dma_strm, PCM_FLAG_POST); warned = 0; } } if (out_fifo_cnt < nfr) { /* not enough samples, see why */ if (!sb_dma_active()) { dspio_stop_output(state); } else { if (nfr && !warned) { S_printf("SB: Output FIFO exhausted while DMA is still active (ol=%f)\n", time_dst - output_time_cur); warned = 1; } if (state->dma.running) S_printf("SB: Output FIFO exhausted while DMA is running (no DACK?)\n"); /* DMA is active but currently not running and the FIFO is * already exhausted. Normally we should flush the channel * and stop the output timing. * HACK: try to not flush the channel for as long as possible * in a hope the PCM buffers are large enough to hold till * the DMA is restarted. */ pcm_set_flag(state->dma_strm, PCM_FLAG_POST); /* awake dosemu */ reset_idle(0); } } if (tlocked) pcm_time_unlock(state->dma_strm); /* TODO: sync also input time with PCM? */ if (state->input_running) nfr = calc_nframes(state, state->input_time_cur, time_dst); else nfr = 0; if (nfr && state->i_started && sb_input_enabled()) { struct player_params params; params.rate = state->dma.rate; params.channels = state->dma.stereo + 1; params.format = pcm_get_format(state->dma.is16bit, state->dma.samp_signed); params.handle = state->i_handle; nfr = pcm_data_get_interleaved(buf, nfr, ¶ms); } if (!state->i_started) { for (i = 0; i < nfr; i++) { for (j = 0; j < state->dma.stereo + 1; j++) dma_get_silence(state->dma.samp_signed, state->dma.is16bit, &buf[i][j]); } } for (i = 0; i < nfr; i++) { for (j = 0; j < state->dma.stereo + 1; j++) { if (sb_input_enabled()) { if (!dspio_put_input_sample(state, &buf[i][j], state->dma.is16bit)) break; } } if (j == state->dma.stereo + 1) in_fifo_cnt++; for (j = 0; j < state->dma.stereo + 1; j++) { if (state->dma.running) { if (!dspio_run_dma(state)) break; dma_cnt++; } } if (!state->input_running || (j != state->dma.stereo + 1)) break; } if (in_fifo_cnt) { if (state->dma.rate) { state->input_time_cur += in_fifo_cnt * pcm_frame_period_us(state->dma.rate); } else { state->input_time_cur = time_dst; } } if (debug_level('S') >= 7 && (in_fifo_cnt || out_fifo_cnt || dma_cnt)) S_printf("SB: Processed %i %i FIFO, %i DMA, or=%i dr=%i\n", in_fifo_cnt, out_fifo_cnt, dma_cnt, state->output_running, state->dma.running); }