mirror of
https://github.com/CTCaer/RetroArch.git
synced 2024-12-23 03:10:14 +00:00
(WiiU) audio quality/latency tweaks.
This commit is contained in:
parent
fc82e91465
commit
7dab3ea378
@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "wiiu/wiiu_dbg.h"
|
#include "wiiu/wiiu_dbg.h"
|
||||||
|
#include "wiiu/system/memory.h"
|
||||||
|
|
||||||
#include "audio/audio_driver.h"
|
#include "audio/audio_driver.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
@ -40,42 +41,40 @@ typedef struct
|
|||||||
AXVoice* voice_r;
|
AXVoice* voice_r;
|
||||||
uint16_t* buffer_l;
|
uint16_t* buffer_l;
|
||||||
uint16_t* buffer_r;
|
uint16_t* buffer_r;
|
||||||
AXVoiceOffsets offsets_l;
|
|
||||||
AXVoiceOffsets offsets_r;
|
|
||||||
bool nonblocking;
|
bool nonblocking;
|
||||||
bool playing;
|
|
||||||
|
|
||||||
uint32_t pos;
|
uint32_t pos;
|
||||||
uint32_t playpos;
|
|
||||||
uint32_t cpu_ticks_last;
|
|
||||||
} ax_audio_t;
|
} ax_audio_t;
|
||||||
|
|
||||||
#define AX_AUDIO_COUNT (1u << 14u)
|
#define AX_AUDIO_COUNT_SHIFT 13u
|
||||||
#define AX_AUDIO_COUNT_MASK (AX_AUDIO_COUNT - 1u)
|
#define AX_AUDIO_COUNT (1u << AX_AUDIO_COUNT_SHIFT)
|
||||||
#define AX_AUDIO_SIZE (AX_AUDIO_COUNT * sizeof(int16_t))
|
#define AX_AUDIO_COUNT_MASK (AX_AUDIO_COUNT - 1u)
|
||||||
#define AX_AUDIO_SIZE_MASK (AX_AUDIO_SIZE - 1u)
|
#define AX_AUDIO_SIZE (AX_AUDIO_COUNT << 1u)
|
||||||
|
#define AX_AUDIO_SIZE_MASK (AX_AUDIO_SIZE - 1u)
|
||||||
|
|
||||||
|
//#define AX_AUDIO_FRAME_COUNT 144
|
||||||
|
#define AX_AUDIO_FRAME_COUNT 160
|
||||||
|
#define AX_AUDIO_RATE 48000
|
||||||
|
//#define ax_audio_ticks_to_samples(ticks) (((ticks) * 64) / 82875)
|
||||||
|
//#define ax_audio_samples_to_ticks(samples) (((samples) * 82875) / 64)
|
||||||
|
|
||||||
#define AX_AUDIO_RATE 48000
|
static inline int ax_diff(int v1, int v2)
|
||||||
#define ax_audio_ticks_to_samples(ticks) (((ticks) * 64) / 82875)
|
|
||||||
#define ax_audio_samples_to_ticks(samples) (((samples) * 82875) / 64)
|
|
||||||
|
|
||||||
static void ax_voice_callback(ax_audio_t* ax_audio)
|
|
||||||
{
|
{
|
||||||
DEBUG_LINE();
|
return ((v1 - v2) << (32u - AX_AUDIO_COUNT_SHIFT)) >> (32u - AX_AUDIO_COUNT_SHIFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ax_audio_update_playpos(ax_audio_t* ax_audio)
|
AXResult ax_aux_callback(void* data, ax_audio_t* ax)
|
||||||
{
|
{
|
||||||
uint32_t samples_played = ax_audio_ticks_to_samples(OSGetSystemTick() - ax_audio->cpu_ticks_last);
|
AXVoiceOffsets offsets;
|
||||||
|
AXGetVoiceOffsets(ax->voice_l, &offsets);
|
||||||
|
|
||||||
ax_audio->playpos = (ax_audio->playpos + samples_played) & AX_AUDIO_COUNT_MASK;
|
if (ax_diff(offsets.currentOffset, ax->pos) < 0)
|
||||||
ax_audio->cpu_ticks_last += ax_audio_samples_to_ticks(samples_played);
|
{
|
||||||
}
|
AXSetVoiceState(ax->voice_l, AX_VOICE_STATE_STOPPED);
|
||||||
|
AXSetVoiceState(ax->voice_r, AX_VOICE_STATE_STOPPED);
|
||||||
|
}
|
||||||
|
|
||||||
void ax_frame_callback(void)
|
return AX_RESULT_SUCCESS;
|
||||||
{
|
|
||||||
DEBUG_LINE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* ax_audio_init(const char* device, unsigned rate, unsigned latency)
|
static void* ax_audio_init(const char* device, unsigned rate, unsigned latency)
|
||||||
@ -89,36 +88,30 @@ static void* ax_audio_init(const char* device, unsigned rate, unsigned latency)
|
|||||||
|
|
||||||
AXInitWithParams(&init);
|
AXInitWithParams(&init);
|
||||||
|
|
||||||
ax->voice_l = AXAcquireVoice(10, (AXVoiceCallbackFn)ax_voice_callback, ax);
|
ax->voice_l = AXAcquireVoice(10, NULL, ax);
|
||||||
ax->voice_r = AXAcquireVoice(10, (AXVoiceCallbackFn)ax_voice_callback, ax);
|
ax->voice_r = AXAcquireVoice(10, NULL, ax);
|
||||||
if(!ax->voice_l || !ax->voice_r)
|
|
||||||
|
if (!ax->voice_l || !ax->voice_r)
|
||||||
{
|
{
|
||||||
free(ax);
|
free(ax);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ax->buffer_l = malloc(AX_AUDIO_SIZE);
|
|
||||||
ax->buffer_r = malloc(AX_AUDIO_SIZE);
|
|
||||||
memset(ax->buffer_l,0,AX_AUDIO_SIZE);
|
|
||||||
memset(ax->buffer_r,0,AX_AUDIO_SIZE);
|
|
||||||
DCFlushRange(ax->buffer_l,AX_AUDIO_SIZE);
|
|
||||||
DCFlushRange(ax->buffer_r,AX_AUDIO_SIZE);
|
|
||||||
|
|
||||||
ax->offsets_l.data = ax->buffer_l;
|
ax->buffer_l = MEM1_alloc(AX_AUDIO_SIZE, 0x100);
|
||||||
ax->offsets_l.currentOffset = 0;
|
ax->buffer_r = MEM1_alloc(AX_AUDIO_SIZE, 0x100);
|
||||||
ax->offsets_l.loopOffset = 0;
|
|
||||||
ax->offsets_l.endOffset = AX_AUDIO_COUNT - 1;
|
|
||||||
ax->offsets_l.loopingEnabled = AX_VOICE_LOOP_ENABLED;
|
|
||||||
ax->offsets_l.dataType = AX_VOICE_FORMAT_LPCM16;
|
|
||||||
|
|
||||||
ax->offsets_r.data = ax->buffer_r;
|
AXVoiceOffsets offsets;
|
||||||
ax->offsets_r.currentOffset = 0;
|
|
||||||
ax->offsets_r.loopOffset = 0;
|
|
||||||
ax->offsets_r.endOffset = AX_AUDIO_COUNT - 1;
|
|
||||||
ax->offsets_r.loopingEnabled = AX_VOICE_LOOP_ENABLED;
|
|
||||||
ax->offsets_r.dataType = AX_VOICE_FORMAT_LPCM16;
|
|
||||||
|
|
||||||
AXSetVoiceOffsets(ax->voice_l, &ax->offsets_l);
|
offsets.data = ax->buffer_l;
|
||||||
AXSetVoiceOffsets(ax->voice_r, &ax->offsets_r);
|
offsets.currentOffset = 0;
|
||||||
|
offsets.loopOffset = 0;
|
||||||
|
offsets.endOffset = AX_AUDIO_COUNT - 1;
|
||||||
|
offsets.loopingEnabled = AX_VOICE_LOOP_ENABLED;
|
||||||
|
offsets.dataType = AX_VOICE_FORMAT_LPCM16;
|
||||||
|
AXSetVoiceOffsets(ax->voice_l, &offsets);
|
||||||
|
|
||||||
|
offsets.data = ax->buffer_r;
|
||||||
|
AXSetVoiceOffsets(ax->voice_r, &offsets);
|
||||||
|
|
||||||
AXSetVoiceSrcType(ax->voice_l, AX_VOICE_SRC_TYPE_NONE);
|
AXSetVoiceSrcType(ax->voice_l, AX_VOICE_SRC_TYPE_NONE);
|
||||||
AXSetVoiceSrcType(ax->voice_r, AX_VOICE_SRC_TYPE_NONE);
|
AXSetVoiceSrcType(ax->voice_r, AX_VOICE_SRC_TYPE_NONE);
|
||||||
@ -127,7 +120,7 @@ static void* ax_audio_init(const char* device, unsigned rate, unsigned latency)
|
|||||||
AXVoiceVeData ve = {0x8000, 0};
|
AXVoiceVeData ve = {0x8000, 0};
|
||||||
AXSetVoiceVe(ax->voice_l, &ve);
|
AXSetVoiceVe(ax->voice_l, &ve);
|
||||||
AXSetVoiceVe(ax->voice_r, &ve);
|
AXSetVoiceVe(ax->voice_r, &ve);
|
||||||
u32 mix[24]= {0};
|
u32 mix[24] = {0};
|
||||||
mix[0] = 0x80000000;
|
mix[0] = 0x80000000;
|
||||||
AXSetVoiceDeviceMix(ax->voice_l, AX_DEVICE_TYPE_DRC, 0, (AXVoiceDeviceMixData*)mix);
|
AXSetVoiceDeviceMix(ax->voice_l, AX_DEVICE_TYPE_DRC, 0, (AXVoiceDeviceMixData*)mix);
|
||||||
AXSetVoiceDeviceMix(ax->voice_l, AX_DEVICE_TYPE_TV, 0, (AXVoiceDeviceMixData*)mix);
|
AXSetVoiceDeviceMix(ax->voice_l, AX_DEVICE_TYPE_TV, 0, (AXVoiceDeviceMixData*)mix);
|
||||||
@ -136,16 +129,15 @@ static void* ax_audio_init(const char* device, unsigned rate, unsigned latency)
|
|||||||
AXSetVoiceDeviceMix(ax->voice_r, AX_DEVICE_TYPE_DRC, 0, (AXVoiceDeviceMixData*)mix);
|
AXSetVoiceDeviceMix(ax->voice_r, AX_DEVICE_TYPE_DRC, 0, (AXVoiceDeviceMixData*)mix);
|
||||||
AXSetVoiceDeviceMix(ax->voice_r, AX_DEVICE_TYPE_TV, 0, (AXVoiceDeviceMixData*)mix);
|
AXSetVoiceDeviceMix(ax->voice_r, AX_DEVICE_TYPE_TV, 0, (AXVoiceDeviceMixData*)mix);
|
||||||
|
|
||||||
AXSetVoiceState(ax->voice_l, AX_VOICE_STATE_PLAYING);
|
AXSetVoiceState(ax->voice_l, AX_VOICE_STATE_STOPPED);
|
||||||
AXSetVoiceState(ax->voice_r, AX_VOICE_STATE_PLAYING);
|
AXSetVoiceState(ax->voice_r, AX_VOICE_STATE_STOPPED);
|
||||||
|
|
||||||
ax->pos = 0;
|
ax->pos = 0;
|
||||||
ax->playpos = 0;
|
|
||||||
ax->playing = true;
|
|
||||||
ax->cpu_ticks_last = OSGetSystemTick();
|
|
||||||
|
|
||||||
config_get_ptr()->audio.out_rate = AX_AUDIO_RATE;
|
config_get_ptr()->audio.out_rate = AX_AUDIO_RATE;
|
||||||
|
|
||||||
|
AXRegisterAuxCallback(AX_DEVICE_TYPE_DRC, 0, 0, (AXAuxCallback)ax_aux_callback, ax);
|
||||||
|
|
||||||
return ax;
|
return ax;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,58 +145,95 @@ static void ax_audio_free(void* data)
|
|||||||
{
|
{
|
||||||
ax_audio_t* ax = (ax_audio_t*)data;
|
ax_audio_t* ax = (ax_audio_t*)data;
|
||||||
|
|
||||||
free(ax->buffer_l);
|
AXRegisterAuxCallback(AX_DEVICE_TYPE_DRC, 0, 0, NULL, NULL);
|
||||||
free(ax->buffer_r);
|
|
||||||
|
MEM1_free(ax->buffer_l);
|
||||||
|
MEM1_free(ax->buffer_r);
|
||||||
free(ax);
|
free(ax);
|
||||||
AXQuit();
|
AXQuit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ax_audio_buffer_write(ax_audio_t* ax, const uint16_t* src, int count)
|
||||||
|
{
|
||||||
|
uint16_t* dst_l = ax->buffer_l + ax->pos;
|
||||||
|
uint16_t* dst_r = ax->buffer_r + ax->pos;
|
||||||
|
uint16_t* dst_l_max = ax->buffer_l + AX_AUDIO_COUNT;
|
||||||
|
|
||||||
|
while(count-- && (dst_l < dst_l_max))
|
||||||
|
{
|
||||||
|
*dst_l++ = *src++;
|
||||||
|
*dst_r++ = *src++;
|
||||||
|
}
|
||||||
|
DCFlushRange(ax->buffer_l + ax->pos, (dst_l - ax->pos - ax->buffer_l) << 1);
|
||||||
|
DCFlushRange(ax->buffer_r + ax->pos, (dst_r - ax->pos - ax->buffer_r) << 1);
|
||||||
|
|
||||||
|
if(++count)
|
||||||
|
{
|
||||||
|
dst_l = ax->buffer_l;
|
||||||
|
dst_r = ax->buffer_r;
|
||||||
|
|
||||||
|
while(count-- && (dst_l < dst_l_max))
|
||||||
|
{
|
||||||
|
*dst_l++ = *src++;
|
||||||
|
*dst_r++ = *src++;
|
||||||
|
}
|
||||||
|
DCFlushRange(ax->buffer_l, (dst_l - ax->buffer_l) << 1);
|
||||||
|
DCFlushRange(ax->buffer_r, (dst_r - ax->buffer_r) << 1);
|
||||||
|
}
|
||||||
|
ax->pos = dst_l - ax->buffer_l;
|
||||||
|
ax->pos &= AX_AUDIO_COUNT_MASK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t ax_audio_write(void* data, const void* buf, size_t size)
|
static ssize_t ax_audio_write(void* data, const void* buf, size_t size)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
static struct retro_perf_counter ax_audio_write_perf = {0};
|
static struct retro_perf_counter ax_audio_write_perf = {0};
|
||||||
ax_audio_t* ax = (ax_audio_t*)data;
|
ax_audio_t* ax = (ax_audio_t*)data;
|
||||||
const uint16_t* src = buf;
|
const uint16_t* src = buf;
|
||||||
uint32_t samples_played = 0;
|
int i;
|
||||||
uint64_t current_tick = 0;
|
|
||||||
|
|
||||||
performance_counter_init(&ax_audio_write_perf, "ax_audio_write");
|
performance_counter_init(&ax_audio_write_perf, "ax_audio_write");
|
||||||
performance_counter_start(&ax_audio_write_perf);
|
performance_counter_start(&ax_audio_write_perf);
|
||||||
|
|
||||||
ax_audio_update_playpos(ax);
|
int count = size >> 2;
|
||||||
|
AXVoiceOffsets offsets;
|
||||||
|
AXGetVoiceOffsets(ax->voice_l, &offsets);
|
||||||
|
|
||||||
if ((((ax->playpos - ax->pos) & AX_AUDIO_COUNT_MASK) < (AX_AUDIO_COUNT >> 2)) ||
|
if((((offsets.currentOffset - ax->pos) & AX_AUDIO_COUNT_MASK) < (AX_AUDIO_COUNT >> 2)) ||
|
||||||
(((ax->pos - ax->playpos) & AX_AUDIO_COUNT_MASK) < (AX_AUDIO_COUNT >> 4)) ||
|
(((ax->pos - offsets.currentOffset ) & AX_AUDIO_COUNT_MASK) < (AX_AUDIO_COUNT >> 4)) ||
|
||||||
(((ax->playpos - ax->pos) & AX_AUDIO_COUNT_MASK) < (size >> 2)))
|
(((offsets.currentOffset - ax->pos) & AX_AUDIO_COUNT_MASK) < (size >> 2)))
|
||||||
{
|
{
|
||||||
if (ax->nonblocking)
|
if (ax->nonblocking)
|
||||||
ax->pos = (ax->playpos + (AX_AUDIO_COUNT >> 1)) & AX_AUDIO_COUNT_MASK;
|
ax->pos = (offsets.currentOffset + (AX_AUDIO_COUNT >> 1)) & AX_AUDIO_COUNT_MASK;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
do
|
do{
|
||||||
{
|
|
||||||
/* todo: compute the correct sleep period */
|
|
||||||
retro_sleep(1);
|
retro_sleep(1);
|
||||||
ax_audio_update_playpos(ax);
|
AXGetVoiceOffsets(ax->voice_l, &offsets);
|
||||||
}
|
}while(AXIsVoiceRunning(ax->voice_l) &&
|
||||||
while (((ax->playpos - ax->pos) & AX_AUDIO_COUNT_MASK) < (AX_AUDIO_COUNT >> 1)
|
(((offsets.currentOffset - ax->pos) & AX_AUDIO_COUNT_MASK) < (AX_AUDIO_COUNT >> 1) ||
|
||||||
|| (((ax->pos - ax->playpos) & AX_AUDIO_COUNT_MASK) < (AX_AUDIO_COUNT >> 4)));
|
(((ax->pos - offsets.currentOffset) & AX_AUDIO_COUNT_MASK) < (AX_AUDIO_COUNT >> 4))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t* dst_l = (uint16_t*)ax->buffer_l;
|
|
||||||
|
// ax_audio_buffer_write(ax, buf, count);
|
||||||
|
|
||||||
for (i = 0; i < (size >> 1); i += 2)
|
for (i = 0; i < (size >> 1); i += 2)
|
||||||
{
|
{
|
||||||
// ax->l[ax->pos] = src[i];
|
ax->buffer_l[ax->pos] = src[i];
|
||||||
// ax->r[ax->pos] = src[i + 1];
|
ax->buffer_r[ax->pos] = src[i + 1];
|
||||||
ax->buffer_l[ax->pos] = (src[i]);
|
|
||||||
ax->buffer_r[ax->pos] = (src[i + 1]);
|
|
||||||
ax->pos++;
|
ax->pos++;
|
||||||
ax->pos &= AX_AUDIO_COUNT_MASK;
|
ax->pos &= AX_AUDIO_COUNT_MASK;
|
||||||
}
|
}
|
||||||
DCFlushRange(ax->buffer_l, AX_AUDIO_SIZE);
|
DCFlushRange(ax->buffer_l, AX_AUDIO_SIZE);
|
||||||
DCFlushRange(ax->buffer_r, AX_AUDIO_SIZE);
|
DCFlushRange(ax->buffer_r, AX_AUDIO_SIZE);
|
||||||
|
|
||||||
|
// if(!AXIsVoiceRunning(ax->voice_l) && (((ax->pos - offsets.currentOffset) & AX_AUDIO_COUNT_MASK) > AX_AUDIO_FRAME_COUNT))
|
||||||
|
// {
|
||||||
|
AXSetVoiceState(ax->voice_l, AX_VOICE_STATE_PLAYING);
|
||||||
|
AXSetVoiceState(ax->voice_r, AX_VOICE_STATE_PLAYING);
|
||||||
|
// }
|
||||||
|
|
||||||
performance_counter_stop(&ax_audio_write_perf);
|
performance_counter_stop(&ax_audio_write_perf);
|
||||||
|
|
||||||
@ -215,23 +244,15 @@ static bool ax_audio_stop(void* data)
|
|||||||
{
|
{
|
||||||
ax_audio_t* ax = (ax_audio_t*)data;
|
ax_audio_t* ax = (ax_audio_t*)data;
|
||||||
|
|
||||||
/* TODO */
|
AXSetVoiceState(ax->voice_l, AX_VOICE_STATE_STOPPED);
|
||||||
if(ax->playing)
|
AXSetVoiceState(ax->voice_r, AX_VOICE_STATE_STOPPED);
|
||||||
{
|
|
||||||
// AXSetVoiceVeDelta(ax->voice, -128);
|
|
||||||
AXVoiceVeData ve = {0};
|
|
||||||
AXSetVoiceVe(ax->voice_l, &ve);
|
|
||||||
AXSetVoiceVe(ax->voice_r, &ve);
|
|
||||||
ax->playing = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ax_audio_alive(void* data)
|
static bool ax_audio_alive(void* data)
|
||||||
{
|
{
|
||||||
ax_audio_t* ax = (ax_audio_t*)data;
|
ax_audio_t* ax = (ax_audio_t*)data;
|
||||||
return ax->playing;
|
return AXIsVoiceRunning(ax->voice_l);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ax_audio_start(void* data)
|
static bool ax_audio_start(void* data)
|
||||||
@ -244,17 +265,8 @@ static bool ax_audio_start(void* data)
|
|||||||
if (runloop_ctl(RUNLOOP_CTL_IS_SHUTDOWN, NULL))
|
if (runloop_ctl(RUNLOOP_CTL_IS_SHUTDOWN, NULL))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* TODO */
|
AXSetVoiceState(ax->voice_l, AX_VOICE_STATE_PLAYING);
|
||||||
|
AXSetVoiceState(ax->voice_r, AX_VOICE_STATE_PLAYING);
|
||||||
if(!ax->playing)
|
|
||||||
{
|
|
||||||
AXVoiceVeData ve = {0x8000, 0};
|
|
||||||
AXSetVoiceVe(ax->voice_l, &ve);
|
|
||||||
AXSetVoiceVe(ax->voice_r, &ve);
|
|
||||||
|
|
||||||
// AXSetVoiceVeDelta(ax->voice, 128);
|
|
||||||
ax->playing = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -263,9 +275,8 @@ static void ax_audio_set_nonblock_state(void* data, bool state)
|
|||||||
{
|
{
|
||||||
ax_audio_t* ax = (ax_audio_t*)data;
|
ax_audio_t* ax = (ax_audio_t*)data;
|
||||||
|
|
||||||
// if (ax)
|
if (ax)
|
||||||
// ax->nonblocking = state;
|
ax->nonblocking = state;
|
||||||
ax->nonblocking = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ax_audio_use_float(void* data)
|
static bool ax_audio_use_float(void* data)
|
||||||
@ -278,8 +289,10 @@ static size_t ax_audio_write_avail(void* data)
|
|||||||
{
|
{
|
||||||
ax_audio_t* ax = (ax_audio_t*)data;
|
ax_audio_t* ax = (ax_audio_t*)data;
|
||||||
|
|
||||||
ax_audio_update_playpos(ax);
|
AXVoiceOffsets offsets;
|
||||||
return (ax->playpos - ax->pos) & AX_AUDIO_COUNT_MASK;
|
AXGetVoiceOffsets(ax->voice_l, &offsets);
|
||||||
|
|
||||||
|
return (offsets.currentOffset - ax->pos) & AX_AUDIO_COUNT_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t ax_audio_buffer_size(void* data)
|
static size_t ax_audio_buffer_size(void* data)
|
||||||
@ -302,6 +315,6 @@ audio_driver_t audio_ax =
|
|||||||
"AX",
|
"AX",
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
ax_audio_write_avail,
|
// ax_audio_write_avail,
|
||||||
ax_audio_buffer_size
|
// ax_audio_buffer_size
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user