mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-06 21:25:03 -05:00
usbaudio: send through dsp (new)
Does not seem to affect UI usability, but allowable DSP loads will vary based on device and playback sample rate. To-Do (someday): - Add dedicated DSP channel - How to apply DSP settings to above new channel? (UI) - How to lock out timestretch from being enabled? Change-Id: Ia24d1055340354e2c32e6008e7e2b03a8e88867d
This commit is contained in:
parent
7c4293af64
commit
c533222851
12 changed files with 94 additions and 31 deletions
|
|
@ -249,7 +249,7 @@ static void codec_pcmbuf_insert_callback(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dsp_process(ci.dsp, &src, &dst);
|
dsp_process(ci.dsp, &src, &dst, true);
|
||||||
|
|
||||||
if (dst.remcount > 0)
|
if (dst.remcount > 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -751,7 +751,7 @@ struct plugin_api {
|
||||||
unsigned int setting, intptr_t value);
|
unsigned int setting, intptr_t value);
|
||||||
struct dsp_config * (*dsp_get_config)(unsigned int dsp_id);
|
struct dsp_config * (*dsp_get_config)(unsigned int dsp_id);
|
||||||
void (*dsp_process)(struct dsp_config *dsp, struct dsp_buffer *src,
|
void (*dsp_process)(struct dsp_config *dsp, struct dsp_buffer *src,
|
||||||
struct dsp_buffer *dst);
|
struct dsp_buffer *dst, bool thread_yield);
|
||||||
|
|
||||||
enum channel_status (*mixer_channel_status)(enum pcm_mixer_channel channel);
|
enum channel_status (*mixer_channel_status)(enum pcm_mixer_channel channel);
|
||||||
const void * (*mixer_channel_get_buffer)(enum pcm_mixer_channel channel,
|
const void * (*mixer_channel_get_buffer)(enum pcm_mixer_channel channel,
|
||||||
|
|
|
||||||
|
|
@ -444,7 +444,7 @@ static inline void synthbuf(void)
|
||||||
dst.remcount = 0;
|
dst.remcount = 0;
|
||||||
dst.bufcount = available;
|
dst.bufcount = available;
|
||||||
dst.p16out = (int16_t *)outptr;
|
dst.p16out = (int16_t *)outptr;
|
||||||
rb->dsp_process(dsp, &src, &dst);
|
rb->dsp_process(dsp, &src, &dst, true);
|
||||||
if (dst.remcount > 0)
|
if (dst.remcount > 0)
|
||||||
{
|
{
|
||||||
outptr += dst.remcount;
|
outptr += dst.remcount;
|
||||||
|
|
|
||||||
|
|
@ -665,7 +665,7 @@ static void audio_thread(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
dst.bufcount = size / (2 * sizeof (int16_t));
|
dst.bufcount = size / (2 * sizeof (int16_t));
|
||||||
rb->dsp_process(td.dsp, &td.src, &dst);
|
rb->dsp_process(td.dsp, &td.src, &dst, true);
|
||||||
|
|
||||||
if (dst.remcount > 0)
|
if (dst.remcount > 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -230,7 +230,7 @@ static int process_dsp(const void *ch1, const void *ch2, int count)
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
int old_remcount = dst.remcount;
|
int old_remcount = dst.remcount;
|
||||||
rb->dsp_process(ci.dsp, &src, &dst);
|
rb->dsp_process(ci.dsp, &src, &dst, true);
|
||||||
|
|
||||||
if (dst.bufcount <= 0 ||
|
if (dst.bufcount <= 0 ||
|
||||||
(src.remcount <= 0 && dst.remcount <= old_remcount))
|
(src.remcount <= 0 && dst.remcount <= old_remcount))
|
||||||
|
|
|
||||||
|
|
@ -33,11 +33,14 @@ struct dsp_loop_context
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void dsp_process_start(struct dsp_loop_context *ctx)
|
static inline void dsp_process_start(struct dsp_loop_context *ctx, bool thread_yield)
|
||||||
{
|
{
|
||||||
/* At least perform one yield before starting */
|
/* At least perform one yield before starting */
|
||||||
ctx->last_yield = current_tick;
|
ctx->last_yield = current_tick;
|
||||||
|
if (thread_yield)
|
||||||
|
{
|
||||||
yield();
|
yield();
|
||||||
|
}
|
||||||
#if defined(CPU_COLDFIRE)
|
#if defined(CPU_COLDFIRE)
|
||||||
/* set emac unit for dsp processing, and save old macsr, we're running in
|
/* set emac unit for dsp processing, and save old macsr, we're running in
|
||||||
codec thread context at this point, so can't clobber it */
|
codec thread context at this point, so can't clobber it */
|
||||||
|
|
@ -46,15 +49,18 @@ static inline void dsp_process_start(struct dsp_loop_context *ctx)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void dsp_process_loop(struct dsp_loop_context *ctx)
|
static inline void dsp_process_loop(struct dsp_loop_context *ctx, bool thread_yield)
|
||||||
{
|
{
|
||||||
/* Yield at least once each tick */
|
/* Yield at least once each tick */
|
||||||
long tick = current_tick;
|
long tick = current_tick;
|
||||||
if (TIME_AFTER(tick, ctx->last_yield))
|
if (TIME_AFTER(tick, ctx->last_yield))
|
||||||
{
|
{
|
||||||
ctx->last_yield = tick;
|
ctx->last_yield = tick;
|
||||||
|
if (thread_yield)
|
||||||
|
{
|
||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void dsp_process_end(struct dsp_loop_context *ctx)
|
static inline void dsp_process_end(struct dsp_loop_context *ctx)
|
||||||
|
|
@ -66,12 +72,12 @@ static inline void dsp_process_end(struct dsp_loop_context *ctx)
|
||||||
(void)ctx;
|
(void)ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DSP_PROCESS_START() \
|
#define DSP_PROCESS_START(yield) \
|
||||||
struct dsp_loop_context __ctx; \
|
struct dsp_loop_context __ctx; \
|
||||||
dsp_process_start(&__ctx)
|
dsp_process_start(&__ctx, yield)
|
||||||
|
|
||||||
#define DSP_PROCESS_LOOP() \
|
#define DSP_PROCESS_LOOP(yield) \
|
||||||
dsp_process_loop(&__ctx)
|
dsp_process_loop(&__ctx, yield)
|
||||||
|
|
||||||
#define DSP_PROCESS_END() \
|
#define DSP_PROCESS_END() \
|
||||||
dsp_process_end(&__ctx)
|
dsp_process_end(&__ctx)
|
||||||
|
|
|
||||||
|
|
@ -511,7 +511,7 @@ static enum voice_state voice_buffer_insert(struct voice_thread_data *td)
|
||||||
dst.bufcount = VOICE_PCM_FRAME_COUNT;
|
dst.bufcount = VOICE_PCM_FRAME_COUNT;
|
||||||
|
|
||||||
td->dst = &dst;
|
td->dst = &dst;
|
||||||
dsp_process(td->dsp, &td->src, &dst);
|
dsp_process(td->dsp, &td->src, &dst, true);
|
||||||
td->dst = NULL;
|
td->dst = NULL;
|
||||||
|
|
||||||
voice_buf_commit(dst.remcount);
|
voice_buf_commit(dst.remcount);
|
||||||
|
|
|
||||||
|
|
@ -664,11 +664,12 @@ int32_t dsp_get_timestretch(void)
|
||||||
\return
|
\return
|
||||||
\description
|
\description
|
||||||
|
|
||||||
void dsp_process(struct dsp_config *dsp, struct dsp_buffer *src, struct dsp_buffer *dst)
|
void dsp_process(struct dsp_config *dsp, struct dsp_buffer *src, struct dsp_buffer *dst, bool thread_yield)
|
||||||
\group sound
|
\group sound
|
||||||
\param dsp
|
\param dsp
|
||||||
\param src
|
\param src
|
||||||
\param dst
|
\param dst
|
||||||
|
\param thread_yield
|
||||||
\description
|
\description
|
||||||
|
|
||||||
void dsp_set_crossfeed_type(int type)
|
void dsp_set_crossfeed_type(int type)
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "core_alloc.h"
|
#include "core_alloc.h"
|
||||||
#include "pcm_mixer.h"
|
#include "pcm_mixer.h"
|
||||||
|
#include "dsp_core.h"
|
||||||
|
|
||||||
#define LOGF_ENABLE
|
#define LOGF_ENABLE
|
||||||
#include "logf.h"
|
#include "logf.h"
|
||||||
|
|
@ -352,7 +353,7 @@ int tmp_saved_vol;
|
||||||
static unsigned char *rx_buffer;
|
static unsigned char *rx_buffer;
|
||||||
int rx_buffer_handle;
|
int rx_buffer_handle;
|
||||||
/* buffer size */
|
/* buffer size */
|
||||||
static int rx_buf_size[NR_BUFFERS];
|
static int rx_buf_size[NR_BUFFERS]; // only used for debug screen counter now
|
||||||
/* index of the next buffer to play */
|
/* index of the next buffer to play */
|
||||||
static int rx_play_idx;
|
static int rx_play_idx;
|
||||||
/* index of the next buffer to fill */
|
/* index of the next buffer to fill */
|
||||||
|
|
@ -362,6 +363,14 @@ bool playback_audio_underflow;
|
||||||
/* usb overflow ? */
|
/* usb overflow ? */
|
||||||
bool usb_rx_overflow;
|
bool usb_rx_overflow;
|
||||||
|
|
||||||
|
/* dsp processing buffers */
|
||||||
|
#define DSP_BUF_SIZE (BUFFER_SIZE*4) // arbitrarily x4
|
||||||
|
#define REAL_DSP_BUF_SIZE ALIGN_UP(DSP_BUF_SIZE, 32)
|
||||||
|
static uint16_t *dsp_buf;
|
||||||
|
int dsp_buf_handle;
|
||||||
|
static int dsp_buf_size[NR_BUFFERS];
|
||||||
|
struct dsp_config *dsp = NULL;
|
||||||
|
|
||||||
/* feedback variables */
|
/* feedback variables */
|
||||||
#define USB_FRAME_MAX 0x7FF
|
#define USB_FRAME_MAX 0x7FF
|
||||||
#define NR_SAMPLES_HISTORY 32
|
#define NR_SAMPLES_HISTORY 32
|
||||||
|
|
@ -502,7 +511,7 @@ int usb_audio_request_buf(void)
|
||||||
audio_stop();
|
audio_stop();
|
||||||
|
|
||||||
// attempt to allocate the receive buffers
|
// attempt to allocate the receive buffers
|
||||||
rx_buffer_handle = core_alloc(NR_BUFFERS * REAL_BUF_SIZE);
|
rx_buffer_handle = core_alloc(REAL_BUF_SIZE);
|
||||||
if (rx_buffer_handle < 0)
|
if (rx_buffer_handle < 0)
|
||||||
{
|
{
|
||||||
alloc_failed = true;
|
alloc_failed = true;
|
||||||
|
|
@ -518,6 +527,23 @@ int usb_audio_request_buf(void)
|
||||||
// get the pointer to the actual buffer location
|
// get the pointer to the actual buffer location
|
||||||
rx_buffer = core_get_data(rx_buffer_handle);
|
rx_buffer = core_get_data(rx_buffer_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dsp_buf_handle = core_alloc(NR_BUFFERS * REAL_DSP_BUF_SIZE);
|
||||||
|
if (dsp_buf_handle < 0)
|
||||||
|
{
|
||||||
|
alloc_failed = true;
|
||||||
|
rx_buffer_handle = core_free(rx_buffer_handle);
|
||||||
|
rx_buffer = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alloc_failed = false;
|
||||||
|
|
||||||
|
core_pin(dsp_buf_handle);
|
||||||
|
|
||||||
|
dsp_buf = core_get_data(dsp_buf_handle);
|
||||||
|
}
|
||||||
// logf("usbaudio: got buffer");
|
// logf("usbaudio: got buffer");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -527,6 +553,9 @@ void usb_audio_free_buf(void)
|
||||||
// logf("usbaudio: free buffer");
|
// logf("usbaudio: free buffer");
|
||||||
rx_buffer_handle = core_free(rx_buffer_handle);
|
rx_buffer_handle = core_free(rx_buffer_handle);
|
||||||
rx_buffer = NULL;
|
rx_buffer = NULL;
|
||||||
|
|
||||||
|
dsp_buf_handle = core_free(dsp_buf_handle);
|
||||||
|
dsp_buf = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_audio_request_endpoints(struct usb_class_driver *drv)
|
int usb_audio_request_endpoints(struct usb_class_driver *drv)
|
||||||
|
|
@ -644,10 +673,11 @@ static void playback_audio_get_more(const void **start, size_t *size)
|
||||||
*size = 0;
|
*size = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* give buffer and advance */
|
/* give buffer and advance */
|
||||||
logf("usbaudio: buf adv");
|
logf("usbaudio: buf adv");
|
||||||
*start = rx_buffer + (rx_play_idx * REAL_BUF_SIZE);
|
*start = dsp_buf + (rx_play_idx * REAL_DSP_BUF_SIZE/sizeof(*dsp_buf));
|
||||||
*size = rx_buf_size[rx_play_idx];
|
*size = dsp_buf_size[rx_play_idx];
|
||||||
rx_play_idx = (rx_play_idx + 1) % NR_BUFFERS;
|
rx_play_idx = (rx_play_idx + 1) % NR_BUFFERS;
|
||||||
|
|
||||||
/* if usb RX buffers had overflowed, we can start to receive again
|
/* if usb RX buffers had overflowed, we can start to receive again
|
||||||
|
|
@ -658,7 +688,7 @@ static void playback_audio_get_more(const void **start, size_t *size)
|
||||||
{
|
{
|
||||||
logf("usbaudio: recover usb rx overflow");
|
logf("usbaudio: recover usb rx overflow");
|
||||||
usb_rx_overflow = false;
|
usb_rx_overflow = false;
|
||||||
usb_drv_recv_nonblocking(out_iso_ep_adr, rx_buffer + (rx_usb_idx * REAL_BUF_SIZE), BUFFER_SIZE);
|
usb_drv_recv_nonblocking(out_iso_ep_adr, rx_buffer, BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
restore_irq(oldlevel);
|
restore_irq(oldlevel);
|
||||||
}
|
}
|
||||||
|
|
@ -697,7 +727,8 @@ static void usb_audio_start_playback(void)
|
||||||
mixer_set_frequency(hw_freq_sampr[as_playback_freq_idx]);
|
mixer_set_frequency(hw_freq_sampr[as_playback_freq_idx]);
|
||||||
pcm_apply_settings();
|
pcm_apply_settings();
|
||||||
mixer_channel_set_amplitude(PCM_MIXER_CHAN_USBAUDIO, MIX_AMP_UNITY);
|
mixer_channel_set_amplitude(PCM_MIXER_CHAN_USBAUDIO, MIX_AMP_UNITY);
|
||||||
usb_drv_recv_nonblocking(out_iso_ep_adr, rx_buffer + (rx_usb_idx * REAL_BUF_SIZE), BUFFER_SIZE);
|
|
||||||
|
usb_drv_recv_nonblocking(out_iso_ep_adr, rx_buffer, BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usb_audio_stop_playback(void)
|
static void usb_audio_stop_playback(void)
|
||||||
|
|
@ -1150,6 +1181,15 @@ void usb_audio_init_connection(void)
|
||||||
{
|
{
|
||||||
logf("usbaudio: init connection");
|
logf("usbaudio: init connection");
|
||||||
|
|
||||||
|
dsp = dsp_get_config(CODEC_IDX_AUDIO);
|
||||||
|
dsp_configure(dsp, DSP_RESET, 0);
|
||||||
|
dsp_configure(dsp, DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
|
||||||
|
dsp_configure(dsp, DSP_SET_SAMPLE_DEPTH, 16);
|
||||||
|
#ifdef HAVE_PITCHCONTROL
|
||||||
|
sound_set_pitch(PITCH_SPEED_100);
|
||||||
|
dsp_set_timestretch(PITCH_SPEED_100);
|
||||||
|
#endif
|
||||||
|
|
||||||
usb_as_playback_intf_alt = 0;
|
usb_as_playback_intf_alt = 0;
|
||||||
set_playback_sampling_frequency(HW_SAMPR_DEFAULT);
|
set_playback_sampling_frequency(HW_SAMPR_DEFAULT);
|
||||||
tmp_saved_vol = sound_current(SOUND_VOLUME);
|
tmp_saved_vol = sound_current(SOUND_VOLUME);
|
||||||
|
|
@ -1261,20 +1301,36 @@ bool usb_audio_fast_transfer_complete(int ep, int dir, int status, int length)
|
||||||
logf("usbaudio: frame: %d bytes: %d", usb_drv_get_frame_number(), length);
|
logf("usbaudio: frame: %d bytes: %d", usb_drv_get_frame_number(), length);
|
||||||
if(status != 0)
|
if(status != 0)
|
||||||
return true; /* FIXME how to handle error here ? */
|
return true; /* FIXME how to handle error here ? */
|
||||||
|
|
||||||
/* store length, queue buffer */
|
/* store length, queue buffer */
|
||||||
rx_buf_size[rx_usb_idx] = length;
|
rx_buf_size[rx_usb_idx] = length;
|
||||||
rx_usb_idx = (rx_usb_idx + 1) % NR_BUFFERS;
|
|
||||||
|
|
||||||
// debug screen counter
|
// debug screen counter
|
||||||
samples_received = samples_received + length;
|
samples_received = samples_received + length;
|
||||||
|
|
||||||
|
// process through DSP right away!
|
||||||
|
struct dsp_buffer src;
|
||||||
|
src.remcount = length/4; // in samples
|
||||||
|
src.pin[0] = rx_buffer;
|
||||||
|
src.proc_mask = 0;
|
||||||
|
|
||||||
|
struct dsp_buffer dst;
|
||||||
|
dst.remcount = 0;
|
||||||
|
dst.bufcount = DSP_BUF_SIZE/4; // in samples
|
||||||
|
dst.p16out = dsp_buf + (rx_usb_idx * REAL_DSP_BUF_SIZE/sizeof(*dsp_buf)); // array index
|
||||||
|
|
||||||
|
dsp_process(dsp, &src, &dst, false);
|
||||||
|
dsp_buf_size[rx_usb_idx] = dst.remcount * 2 * sizeof(*dsp_buf); // need value in bytes
|
||||||
|
|
||||||
|
rx_usb_idx = (rx_usb_idx + 1) % NR_BUFFERS;
|
||||||
|
|
||||||
/* guard against IRQ to avoid race with completion audio completion */
|
/* guard against IRQ to avoid race with completion audio completion */
|
||||||
int oldlevel = disable_irq_save();
|
int oldlevel = disable_irq_save();
|
||||||
/* setup a new transaction except if we ran out of buffers */
|
/* setup a new transaction except if we ran out of buffers */
|
||||||
if(rx_usb_idx != rx_play_idx)
|
if(rx_usb_idx != rx_play_idx)
|
||||||
{
|
{
|
||||||
logf("usbaudio: new transaction");
|
logf("usbaudio: new transaction");
|
||||||
usb_drv_recv_nonblocking(out_iso_ep_adr, rx_buffer + (rx_usb_idx*REAL_BUF_SIZE), BUFFER_SIZE);
|
usb_drv_recv_nonblocking(out_iso_ep_adr, rx_buffer, BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,8 @@
|
||||||
|
|
||||||
#ifndef DSP_PROCESS_START
|
#ifndef DSP_PROCESS_START
|
||||||
/* These do nothing if not previously defined */
|
/* These do nothing if not previously defined */
|
||||||
#define DSP_PROCESS_START()
|
#define DSP_PROCESS_START(yield)
|
||||||
#define DSP_PROCESS_LOOP()
|
#define DSP_PROCESS_LOOP(yield)
|
||||||
#define DSP_PROCESS_END()
|
#define DSP_PROCESS_END()
|
||||||
#endif /* !DSP_PROCESS_START */
|
#endif /* !DSP_PROCESS_START */
|
||||||
|
|
||||||
|
|
@ -433,7 +433,7 @@ static FORCE_INLINE void dsp_proc_call(struct dsp_proc_slot *s,
|
||||||
* of the call and how they function internally.
|
* of the call and how they function internally.
|
||||||
*/
|
*/
|
||||||
void dsp_process(struct dsp_config *dsp, struct dsp_buffer *src,
|
void dsp_process(struct dsp_config *dsp, struct dsp_buffer *src,
|
||||||
struct dsp_buffer *dst)
|
struct dsp_buffer *dst, bool thread_yield)
|
||||||
{
|
{
|
||||||
if (dst->bufcount <= 0)
|
if (dst->bufcount <= 0)
|
||||||
{
|
{
|
||||||
|
|
@ -441,7 +441,7 @@ void dsp_process(struct dsp_config *dsp, struct dsp_buffer *src,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DSP_PROCESS_START();
|
DSP_PROCESS_START(thread_yield);
|
||||||
|
|
||||||
/* Tag input with codec-specified sample format */
|
/* Tag input with codec-specified sample format */
|
||||||
src->format = dsp->io_data.format;
|
src->format = dsp->io_data.format;
|
||||||
|
|
@ -479,7 +479,7 @@ void dsp_process(struct dsp_config *dsp, struct dsp_buffer *src,
|
||||||
dsp_advance_buffer32(buf, outcount);
|
dsp_advance_buffer32(buf, outcount);
|
||||||
dsp_advance_buffer_output(dst, outcount);
|
dsp_advance_buffer_output(dst, outcount);
|
||||||
|
|
||||||
DSP_PROCESS_LOOP();
|
DSP_PROCESS_LOOP(thread_yield);
|
||||||
} /* while */
|
} /* while */
|
||||||
|
|
||||||
DSP_PROCESS_END();
|
DSP_PROCESS_END();
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,7 @@ unsigned int dsp_get_id(const struct dsp_config *dsp);
|
||||||
|
|
||||||
/* Process the given buffer - see implementation in dsp.c for more */
|
/* Process the given buffer - see implementation in dsp.c for more */
|
||||||
void dsp_process(struct dsp_config *dsp, struct dsp_buffer *src,
|
void dsp_process(struct dsp_config *dsp, struct dsp_buffer *src,
|
||||||
struct dsp_buffer *dst);
|
struct dsp_buffer *dst, bool thread_yield);
|
||||||
|
|
||||||
/* Change DSP settings */
|
/* Change DSP settings */
|
||||||
intptr_t dsp_configure(struct dsp_config *dsp, unsigned int setting,
|
intptr_t dsp_configure(struct dsp_config *dsp, unsigned int setting,
|
||||||
|
|
|
||||||
|
|
@ -455,7 +455,7 @@ static void ci_pcmbuf_insert(const void *ch1, const void *ch2, int count)
|
||||||
dst.p16out = buf;
|
dst.p16out = buf;
|
||||||
dst.bufcount = out_count;
|
dst.bufcount = out_count;
|
||||||
|
|
||||||
dsp_process(ci.dsp, &src, &dst);
|
dsp_process(ci.dsp, &src, &dst, true);
|
||||||
|
|
||||||
if (dst.remcount > 0) {
|
if (dst.remcount > 0) {
|
||||||
if (mode == MODE_WRITE)
|
if (mode == MODE_WRITE)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue