(WiiU) continuation of the audio driver changes from yesterday
This commit is contained in:
parent
2997b7b0cc
commit
b29cdef8ec
|
@ -29,6 +29,7 @@
|
||||||
|
|
||||||
#include "wiiu/wiiu_dbg.h"
|
#include "wiiu/wiiu_dbg.h"
|
||||||
#include "wiiu/system/memory.h"
|
#include "wiiu/system/memory.h"
|
||||||
|
#include "wiiu/multivoice.h"
|
||||||
|
|
||||||
#include "audio/audio_driver.h"
|
#include "audio/audio_driver.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
|
@ -37,8 +38,7 @@
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
AXVoice* voice_l;
|
AXMVoice* mvoice;
|
||||||
AXVoice* voice_r;
|
|
||||||
uint16_t* buffer_l;
|
uint16_t* buffer_l;
|
||||||
uint16_t* buffer_r;
|
uint16_t* buffer_r;
|
||||||
bool nonblocking;
|
bool nonblocking;
|
||||||
|
@ -72,12 +72,11 @@ AXResult ax_aux_callback(void* data, ax_audio_t* ax)
|
||||||
OSUninterruptibleSpinLock_Acquire(&ax->spinlock);
|
OSUninterruptibleSpinLock_Acquire(&ax->spinlock);
|
||||||
//buffer underrun, stop playback to let if fill up
|
//buffer underrun, stop playback to let if fill up
|
||||||
if(ax->written < AX_AUDIO_SAMPLE_MIN)
|
if(ax->written < AX_AUDIO_SAMPLE_MIN)
|
||||||
{
|
AXSetMultiVoiceState(ax->mvoice, AX_VOICE_STATE_STOPPED);
|
||||||
AXSetVoiceState(ax->voice_l, AX_VOICE_STATE_STOPPED);
|
//make sure to update written value if voice is running
|
||||||
AXSetVoiceState(ax->voice_r, AX_VOICE_STATE_STOPPED);
|
if(AXIsMultiVoiceRunning(ax->mvoice))
|
||||||
}
|
ax->written -= (ax->written < AX_AUDIO_SAMPLE_COUNT ? ax->written : AX_AUDIO_SAMPLE_COUNT);
|
||||||
else //all good, play back frame
|
|
||||||
ax->written -= AX_AUDIO_SAMPLE_COUNT;
|
|
||||||
OSUninterruptibleSpinLock_Release(&ax->spinlock);
|
OSUninterruptibleSpinLock_Release(&ax->spinlock);
|
||||||
return AX_RESULT_SUCCESS;
|
return AX_RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -93,10 +92,11 @@ static void* ax_audio_init(const char* device, unsigned rate, unsigned latency)
|
||||||
|
|
||||||
AXInitWithParams(&init);
|
AXInitWithParams(&init);
|
||||||
|
|
||||||
ax->voice_l = AXAcquireVoice(10, NULL, ax);
|
u16 setup_buf[0x30] = {0};
|
||||||
ax->voice_r = AXAcquireVoice(10, NULL, ax);
|
setup_buf[0x25] = 2; //we request 2 channels
|
||||||
|
AXAcquireMultiVoice(31, NULL, 0, setup_buf, &ax->mvoice);
|
||||||
|
|
||||||
if (!ax->voice_l || !ax->voice_r)
|
if (!ax->mvoice || ax->mvoice->channels != 2)
|
||||||
{
|
{
|
||||||
free(ax);
|
free(ax);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -109,37 +109,37 @@ static void* ax_audio_init(const char* device, unsigned rate, unsigned latency)
|
||||||
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);
|
||||||
|
|
||||||
|
//shared by both voices
|
||||||
AXVoiceOffsets offsets;
|
AXVoiceOffsets offsets;
|
||||||
|
|
||||||
offsets.data = ax->buffer_l;
|
|
||||||
offsets.currentOffset = 0;
|
offsets.currentOffset = 0;
|
||||||
offsets.loopOffset = 0;
|
offsets.loopOffset = 0;
|
||||||
offsets.endOffset = AX_AUDIO_COUNT - 1;
|
offsets.endOffset = AX_AUDIO_COUNT - 1;
|
||||||
offsets.loopingEnabled = AX_VOICE_LOOP_ENABLED;
|
offsets.loopingEnabled = AX_VOICE_LOOP_ENABLED;
|
||||||
offsets.dataType = AX_VOICE_FORMAT_LPCM16;
|
offsets.dataType = AX_VOICE_FORMAT_LPCM16;
|
||||||
AXSetVoiceOffsets(ax->voice_l, &offsets);
|
|
||||||
|
offsets.data = ax->buffer_l;
|
||||||
|
AXSetVoiceOffsets(ax->mvoice->v[0], &offsets);
|
||||||
|
|
||||||
offsets.data = ax->buffer_r;
|
offsets.data = ax->buffer_r;
|
||||||
AXSetVoiceOffsets(ax->voice_r, &offsets);
|
AXSetVoiceOffsets(ax->mvoice->v[1], &offsets);
|
||||||
|
|
||||||
|
AXSetMultiVoiceSrcType(ax->mvoice, AX_VOICE_SRC_TYPE_NONE);
|
||||||
|
AXSetMultiVoiceSrcRatio(ax->mvoice, 1.0f);
|
||||||
|
|
||||||
|
AXVoiceVeData ve = {0xF000, 0};
|
||||||
|
AXSetMultiVoiceVe(ax->mvoice, &ve);
|
||||||
|
|
||||||
AXSetVoiceSrcType(ax->voice_l, AX_VOICE_SRC_TYPE_NONE);
|
|
||||||
AXSetVoiceSrcType(ax->voice_r, AX_VOICE_SRC_TYPE_NONE);
|
|
||||||
AXSetVoiceSrcRatio(ax->voice_l, 1.0f);
|
|
||||||
AXSetVoiceSrcRatio(ax->voice_r, 1.0f);
|
|
||||||
AXVoiceVeData ve = {0xFFFF, 0};
|
|
||||||
AXSetVoiceVe(ax->voice_l, &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->mvoice->v[0], AX_DEVICE_TYPE_DRC, 0, (AXVoiceDeviceMixData*)mix);
|
||||||
AXSetVoiceDeviceMix(ax->voice_l, AX_DEVICE_TYPE_TV, 0, (AXVoiceDeviceMixData*)mix);
|
AXSetVoiceDeviceMix(ax->mvoice->v[0], AX_DEVICE_TYPE_TV, 0, (AXVoiceDeviceMixData*)mix);
|
||||||
|
|
||||||
mix[0] = 0;
|
mix[0] = 0;
|
||||||
mix[4] = 0x80000000;
|
mix[4] = 0x80000000;
|
||||||
AXSetVoiceDeviceMix(ax->voice_r, AX_DEVICE_TYPE_DRC, 0, (AXVoiceDeviceMixData*)mix);
|
AXSetVoiceDeviceMix(ax->mvoice->v[1], AX_DEVICE_TYPE_DRC, 0, (AXVoiceDeviceMixData*)mix);
|
||||||
AXSetVoiceDeviceMix(ax->voice_r, AX_DEVICE_TYPE_TV, 0, (AXVoiceDeviceMixData*)mix);
|
AXSetVoiceDeviceMix(ax->mvoice->v[1], AX_DEVICE_TYPE_TV, 0, (AXVoiceDeviceMixData*)mix);
|
||||||
|
|
||||||
AXSetVoiceState(ax->voice_l, AX_VOICE_STATE_STOPPED);
|
AXSetMultiVoiceState(ax->mvoice, AX_VOICE_STATE_STOPPED);
|
||||||
AXSetVoiceState(ax->voice_r, AX_VOICE_STATE_STOPPED);
|
|
||||||
|
|
||||||
ax->pos = 0;
|
ax->pos = 0;
|
||||||
ax->written = 0;
|
ax->written = 0;
|
||||||
|
@ -158,7 +158,7 @@ static void ax_audio_free(void* data)
|
||||||
ax_audio_t* ax = (ax_audio_t*)data;
|
ax_audio_t* ax = (ax_audio_t*)data;
|
||||||
|
|
||||||
AXRegisterAuxCallback(AX_DEVICE_TYPE_DRC, 0, 0, NULL, NULL);
|
AXRegisterAuxCallback(AX_DEVICE_TYPE_DRC, 0, 0, NULL, NULL);
|
||||||
|
AXFreeMultiVoice(ax->mvoice);
|
||||||
MEM1_free(ax->buffer_l);
|
MEM1_free(ax->buffer_l);
|
||||||
MEM1_free(ax->buffer_r);
|
MEM1_free(ax->buffer_r);
|
||||||
free(ax);
|
free(ax);
|
||||||
|
@ -213,6 +213,8 @@ static ssize_t ax_audio_write(void* data, const void* buf, size_t size)
|
||||||
count = 0;
|
count = 0;
|
||||||
goto wiiu_audio_end;
|
goto wiiu_audio_end;
|
||||||
}
|
}
|
||||||
|
if(count > AX_AUDIO_COUNT)
|
||||||
|
count = AX_AUDIO_COUNT;
|
||||||
|
|
||||||
size_t countAvail = AX_AUDIO_COUNT - ax->written;
|
size_t countAvail = AX_AUDIO_COUNT - ax->written;
|
||||||
if (ax->nonblocking)
|
if (ax->nonblocking)
|
||||||
|
@ -231,7 +233,7 @@ static ssize_t ax_audio_write(void* data, const void* buf, size_t size)
|
||||||
do {
|
do {
|
||||||
OSYieldThread();
|
OSYieldThread();
|
||||||
countAvail = AX_AUDIO_COUNT - ax->written;
|
countAvail = AX_AUDIO_COUNT - ax->written;
|
||||||
} while(AXIsVoiceRunning(ax->voice_l) && countAvail < count);
|
} while(AXIsMultiVoiceRunning(ax->mvoice) && countAvail < count);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ax_audio_buffer_write(ax, buf, count);
|
// ax_audio_buffer_write(ax, buf, count);
|
||||||
|
@ -271,7 +273,7 @@ static ssize_t ax_audio_write(void* data, const void* buf, size_t size)
|
||||||
OSUninterruptibleSpinLock_Release(&ax->spinlock);
|
OSUninterruptibleSpinLock_Release(&ax->spinlock);
|
||||||
|
|
||||||
//possibly buffer underrun
|
//possibly buffer underrun
|
||||||
if(!AXIsVoiceRunning(ax->voice_l))
|
if(!AXIsMultiVoiceRunning(ax->mvoice))
|
||||||
{
|
{
|
||||||
//checks if it can be started
|
//checks if it can be started
|
||||||
ax_audio_start(ax);
|
ax_audio_start(ax);
|
||||||
|
@ -287,15 +289,14 @@ static bool ax_audio_stop(void* data)
|
||||||
{
|
{
|
||||||
ax_audio_t* ax = (ax_audio_t*)data;
|
ax_audio_t* ax = (ax_audio_t*)data;
|
||||||
|
|
||||||
AXSetVoiceState(ax->voice_l, AX_VOICE_STATE_STOPPED);
|
AXSetMultiVoiceState(ax->mvoice, AX_VOICE_STATE_STOPPED);
|
||||||
AXSetVoiceState(ax->voice_r, AX_VOICE_STATE_STOPPED);
|
|
||||||
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 AXIsVoiceRunning(ax->voice_l);
|
return AXIsMultiVoiceRunning(ax->mvoice);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ax_audio_start(void* data)
|
static bool ax_audio_start(void* data)
|
||||||
|
@ -308,25 +309,9 @@ 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;
|
||||||
|
|
||||||
//for safety first
|
|
||||||
ax_audio_stop(data);
|
|
||||||
|
|
||||||
//reset offset to last load offset
|
|
||||||
AXVoiceOffsets offsets;
|
|
||||||
uint32_t lastOffset = ((ax->pos - ((ax->written)<<1)) & AX_AUDIO_COUNT_MASK);
|
|
||||||
AXGetVoiceOffsets(ax->voice_l, &offsets);
|
|
||||||
offsets.currentOffset = lastOffset;
|
|
||||||
AXSetVoiceOffsets(ax->voice_l, &offsets);
|
|
||||||
AXGetVoiceOffsets(ax->voice_r, &offsets);
|
|
||||||
offsets.currentOffset = lastOffset;
|
|
||||||
AXSetVoiceOffsets(ax->voice_r, &offsets);
|
|
||||||
|
|
||||||
//set back to playing on enough buffered data
|
//set back to playing on enough buffered data
|
||||||
if(ax->written > AX_AUDIO_SAMPLE_MIN)
|
if(ax->written > AX_AUDIO_SAMPLE_MIN)
|
||||||
{
|
AXSetMultiVoiceState(ax->mvoice, AX_VOICE_STATE_PLAYING);
|
||||||
AXSetVoiceState(ax->voice_l, AX_VOICE_STATE_PLAYING);
|
|
||||||
AXSetVoiceState(ax->voice_r, AX_VOICE_STATE_PLAYING);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -337,8 +322,6 @@ static void ax_audio_set_nonblock_state(void* data, bool state)
|
||||||
|
|
||||||
if (ax)
|
if (ax)
|
||||||
{
|
{
|
||||||
if(state != ax->nonblocking)
|
|
||||||
ax_audio_start(data);
|
|
||||||
ax->nonblocking = state;
|
ax->nonblocking = state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
#ifndef _MULTIVOICE_H_
|
||||||
|
#define _MULTIVOICE_H_
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
bool running;
|
||||||
|
uint32_t channels;
|
||||||
|
AXVoice *v[];
|
||||||
|
} AXMVoice;
|
||||||
|
|
||||||
|
void AXAcquireMultiVoice(uint32_t prio, void *cb, uint32_t cbarg, void *setup, AXMVoice **mvoice);
|
||||||
|
void AXSetMultiVoiceState(AXMVoice *mvoice, AXVoiceState state);
|
||||||
|
void AXSetMultiVoiceVe(AXMVoice *mvoice, AXVoiceVeData *veData);
|
||||||
|
void AXSetMultiVoiceSrcType(AXMVoice *mvoice, AXVoiceSrcType type);
|
||||||
|
void AXSetMultiVoiceSrcRatio(AXMVoice *mvoice, float ratio);
|
||||||
|
bool AXIsMultiVoiceRunning(AXMVoice *mvoice);
|
||||||
|
void AXFreeMultiVoice(AXMVoice *mvoice);
|
||||||
|
|
||||||
|
#endif
|
|
@ -2,5 +2,12 @@
|
||||||
EXPORT_BEGIN(sndcore2.rpl);
|
EXPORT_BEGIN(sndcore2.rpl);
|
||||||
|
|
||||||
#include "../rpl/libsndcore2/exports.h"
|
#include "../rpl/libsndcore2/exports.h"
|
||||||
|
EXPORT(AXAcquireMultiVoice);
|
||||||
|
EXPORT(AXSetMultiVoiceState);
|
||||||
|
EXPORT(AXSetMultiVoiceVe);
|
||||||
|
EXPORT(AXSetMultiVoiceSrcType);
|
||||||
|
EXPORT(AXSetMultiVoiceSrcRatio);
|
||||||
|
EXPORT(AXIsMultiVoiceRunning);
|
||||||
|
EXPORT(AXFreeMultiVoice);
|
||||||
|
|
||||||
EXPORT_END();
|
EXPORT_END();
|
||||||
|
|
Loading…
Reference in New Issue