GX2_GUI_Template/src/sounds/Voice.h

165 lines
4.2 KiB
C++

/****************************************************************************
* Copyright (C) 2015 Dimok
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef _AXSOUND_H_
#define _AXSOUND_H_
#include <sndcore2/core.h>
#include <sndcore2/voice.h>
class Voice
{
public:
enum VoicePriorities
{
PRIO_MIN = 1,
PRIO_MAX = 31
};
enum VoiceStates
{
STATE_STOPPED,
STATE_START,
STATE_PLAYING,
STATE_STOP,
};
Voice(int prio)
: state(STATE_STOPPED)
{
lastLoopCounter = 0;
nextBufferSize = 0;
voice = AXAcquireVoice(prio, 0, 0);
if(voice)
{
AXSetVoiceType(voice, 0);
setVolume(0x80000000);
AXVoiceDeviceMixData mix[6];
memset(mix, 0, sizeof(mix));
mix[0].bus[0].volume = 0x8000;
mix[0].bus[0].delta = 0;
mix[1].bus[0].volume = 0x8000;
mix[1].bus[0].delta = 0;
AXSetVoiceDeviceMix(voice, 0, 0, mix);
AXSetVoiceDeviceMix(voice, 1, 0, mix);
}
}
~Voice()
{
if(voice)
{
AXFreeVoice(voice);
}
}
void play(const u8 *buffer, u32 bufferSize, const u8 *nextBuffer, u32 nextBufSize, u16 format, u32 sampleRate)
{
if(!voice)
return;
memset(&voiceBuffer, 0, sizeof(voiceBuffer));
voiceBuffer.data = buffer;
voiceBuffer.dataType = format;
voiceBuffer.loopingEnabled = (nextBuffer == NULL) ? 0 : 1;
voiceBuffer.currentOffset = 0;
voiceBuffer.endOffset = (bufferSize >> 1) - 1;
voiceBuffer.loopOffset = ((nextBuffer - buffer) >> 1);
nextBufferSize = nextBufSize;
// TODO: handle support for 3.1.0 with dynamic libs instead of static linking it
//u32 samplesPerSec = (AXGetInputSamplesPerSec != 0) ? AXGetInputSamplesPerSec() : 32000;
u32 samplesPerSec = AXGetInputSamplesPerSec();
memset(&ratioBits, 0, sizeof(ratioBits));
ratioBits.ratio = (u32)(0x00010000 * ((f32)sampleRate / (f32)samplesPerSec));
AXSetVoiceOffsets(voice, &voiceBuffer);
AXSetVoiceSrc(voice, &ratioBits);
AXSetVoiceSrcType(voice, 1);
AXSetVoiceState(voice, 1);
}
void stop()
{
if(voice)
AXSetVoiceState(voice, 0);
}
void setVolume(u32 vol)
{
if(voice)
{
AXVoiceVeData data;
data.volume = vol >> 16;
data.delta = vol & 0xFFFF;
AXSetVoiceVe(voice, &data);
}
}
void setNextBuffer(const u8 *buffer, u32 bufferSize)
{
voiceBuffer.loopOffset = ((buffer - (const u8*)voiceBuffer.data) >> 1);
nextBufferSize = bufferSize;
AXSetVoiceLoopOffset(voice, voiceBuffer.loopOffset);
}
bool isBufferSwitched()
{
u32 loopCounter = AXGetVoiceLoopCount(voice);
if(lastLoopCounter != loopCounter)
{
lastLoopCounter = loopCounter;
AXSetVoiceEndOffset(voice, voiceBuffer.loopOffset + (nextBufferSize >> 1) - 1);
return true;
}
return false;
}
u32 getInternState() const {
if(voice)
return ((u32 *)voice)[1];
return 0;
}
u32 getState() const {
return state;
}
void setState(u32 s) {
state = s;
}
void * getVoice() const {
return voice;
}
private:
AXVoice *voice;
AXVoiceSrc ratioBits;
AXVoiceOffsets voiceBuffer;
u32 state;
u32 nextBufferSize;
u32 lastLoopCounter;
};
#endif // _AXSOUND_H_