mirror of
https://github.com/jorio/Pomme.git
synced 2024-06-10 06:29:31 +00:00
Sound: apply channel params in ProcessSoundCommand
This commit is contained in:
parent
6399e16cc6
commit
d8f5f4b324
|
@ -234,9 +234,9 @@ typedef SndCallBackProcPtr SndCallbackUPP;
|
||||||
typedef struct SndChannel
|
typedef struct SndChannel
|
||||||
{
|
{
|
||||||
SndChannelPtr nextChan;
|
SndChannelPtr nextChan;
|
||||||
Ptr firstMod; // reserved for the Sound Manager (Pomme: used as internal ptr)
|
|
||||||
SndCallBackProcPtr callBack;
|
SndCallBackProcPtr callBack;
|
||||||
long long userInfo; // free for application's use (Pomme: made it 64 bit so app can store ptrs)
|
long long userInfo; // free for application's use (Pomme: made it 64 bit so app can store ptrs)
|
||||||
|
Ptr channelImpl; // Pomme: internal ptr to implementation
|
||||||
#if 0
|
#if 0
|
||||||
long wait; // The following is for internal Sound Manager use only.
|
long wait; // The following is for internal Sound Manager use only.
|
||||||
SndCommand cmdInProgress;
|
SndCommand cmdInProgress;
|
||||||
|
|
|
@ -79,6 +79,14 @@ enum SampledSoundEncoding
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Internal channel info
|
// Internal channel info
|
||||||
|
|
||||||
|
enum ApplyParametersMask
|
||||||
|
{
|
||||||
|
kApplyParameters_PanAndGain = 1 << 0,
|
||||||
|
kApplyParameters_Pitch = 1 << 1,
|
||||||
|
kApplyParameters_Loop = 1 << 2,
|
||||||
|
kApplyParameters_All = 0xFFFFFFFF
|
||||||
|
};
|
||||||
|
|
||||||
struct ChannelImpl
|
struct ChannelImpl
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -86,27 +94,34 @@ private:
|
||||||
ChannelImpl* next;
|
ChannelImpl* next;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// Pointer to application-facing interface
|
||||||
SndChannelPtr macChannel;
|
SndChannelPtr macChannel;
|
||||||
|
|
||||||
bool macChannelStructAllocatedByPomme;
|
bool macChannelStructAllocatedByPomme;
|
||||||
cmixer::WavStream source;
|
cmixer::WavStream source;
|
||||||
FilePlayCompletionProcPtr onComplete;
|
|
||||||
|
|
||||||
Byte baseNote = kMiddleC;
|
// Parameters coming from Mac sound commands, passed back to cmixer source
|
||||||
Byte playbackNote = kMiddleC;
|
double pan;
|
||||||
double pitchMult = 1;
|
double gain;
|
||||||
|
Byte baseNote;
|
||||||
|
Byte playbackNote;
|
||||||
|
double pitchMult;
|
||||||
|
bool loop;
|
||||||
|
|
||||||
bool temporaryPause = false;
|
bool temporaryPause = false;
|
||||||
|
|
||||||
ChannelImpl(SndChannelPtr _macChannel, bool transferMacChannelOwnership)
|
ChannelImpl(SndChannelPtr _macChannel, bool transferMacChannelOwnership)
|
||||||
: macChannel(_macChannel)
|
: macChannel(_macChannel)
|
||||||
, macChannelStructAllocatedByPomme(transferMacChannelOwnership)
|
, macChannelStructAllocatedByPomme(transferMacChannelOwnership)
|
||||||
, source()
|
, source()
|
||||||
, onComplete(nullptr)
|
, pan(0.0)
|
||||||
|
, gain(1.0)
|
||||||
, baseNote(kMiddleC)
|
, baseNote(kMiddleC)
|
||||||
, playbackNote(kMiddleC)
|
, playbackNote(kMiddleC)
|
||||||
, pitchMult(1.0)
|
, pitchMult(1.0)
|
||||||
|
, loop(false)
|
||||||
{
|
{
|
||||||
macChannel->firstMod = (Ptr) this;
|
macChannel->channelImpl = (Ptr) this;
|
||||||
|
|
||||||
Link(); // Link chan into our list of managed chans
|
Link(); // Link chan into our list of managed chans
|
||||||
}
|
}
|
||||||
|
@ -115,7 +130,7 @@ public:
|
||||||
{
|
{
|
||||||
Unlink();
|
Unlink();
|
||||||
|
|
||||||
macChannel->firstMod = nullptr;
|
macChannel->channelImpl = nullptr;
|
||||||
|
|
||||||
if (macChannelStructAllocatedByPomme)
|
if (macChannelStructAllocatedByPomme)
|
||||||
{
|
{
|
||||||
|
@ -126,21 +141,35 @@ public:
|
||||||
void Recycle()
|
void Recycle()
|
||||||
{
|
{
|
||||||
source.Clear();
|
source.Clear();
|
||||||
baseNote = kMiddleC;
|
|
||||||
playbackNote = kMiddleC;
|
|
||||||
pitchMult = 1;
|
|
||||||
temporaryPause = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyPitch()
|
void ApplyParametersToSource(uint32_t mask, bool evenIfInactive = false)
|
||||||
{
|
{
|
||||||
if (!source.active)
|
if (!evenIfInactive && !source.active)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
double baseFreq = midiNoteFrequencies[baseNote];
|
|
||||||
double playbackFreq = midiNoteFrequencies[playbackNote];
|
// Pitch
|
||||||
source.SetPitch(pitchMult * playbackFreq / baseFreq);
|
if (mask & kApplyParameters_Pitch)
|
||||||
|
{
|
||||||
|
double baseFreq = midiNoteFrequencies[baseNote];
|
||||||
|
double playbackFreq = midiNoteFrequencies[playbackNote];
|
||||||
|
source.SetPitch(pitchMult * playbackFreq / baseFreq);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pan and gain
|
||||||
|
if (mask & kApplyParameters_PanAndGain)
|
||||||
|
{
|
||||||
|
source.SetPan(pan);
|
||||||
|
source.SetGain(gain);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interpolation
|
||||||
|
if (mask & kApplyParameters_Interpolation)
|
||||||
|
{
|
||||||
|
source.SetInterpolation(interpolate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ChannelImpl* GetPrev() const
|
ChannelImpl* GetPrev() const
|
||||||
|
@ -212,7 +241,7 @@ public:
|
||||||
|
|
||||||
static inline ChannelImpl& GetImpl(SndChannelPtr chan)
|
static inline ChannelImpl& GetImpl(SndChannelPtr chan)
|
||||||
{
|
{
|
||||||
return *(ChannelImpl*) chan->firstMod;
|
return *(ChannelImpl*) chan->channelImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -464,8 +493,16 @@ static void ProcessSoundCmd(SndChannelPtr chan, const Ptr sndhdr)
|
||||||
impl.source.SetLoop(true);
|
impl.source.SetLoop(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl.ApplyPitch();
|
// Pass Mac channel parameters to cmixer source.
|
||||||
|
// The loop param is a special case -- we're detecting it automatically according
|
||||||
|
// to the sound header. If your application needs to force set the loop, it must
|
||||||
|
// issue pommeSetLoopCmd *after* bufferCmd/soundCmd.
|
||||||
|
impl.ApplyParametersToSource(kApplyParameters_All & ~kApplyParameters_Loop, true);
|
||||||
|
|
||||||
|
// Override systemwide audio pause.
|
||||||
impl.temporaryPause = false;
|
impl.temporaryPause = false;
|
||||||
|
|
||||||
|
// Get it going!
|
||||||
impl.source.Play();
|
impl.source.Play();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,7 +531,8 @@ OSErr SndDoImmediate(SndChannelPtr chan, const SndCommand* cmd)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ampCmd:
|
case ampCmd:
|
||||||
impl.source.SetGain(cmd->param1 / 256.0);
|
impl.gain = cmd->param1 / 256.0;
|
||||||
|
impl.ApplyParametersToSource(kApplyParameters_PanAndGain);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case volumeCmd:
|
case volumeCmd:
|
||||||
|
@ -505,31 +543,34 @@ OSErr SndDoImmediate(SndChannelPtr chan, const SndCommand* cmd)
|
||||||
double pan = (double)rvol / (rvol + lvol);
|
double pan = (double)rvol / (rvol + lvol);
|
||||||
pan = (pan - 0.5) * 2.0; // Transpose pan from [0...1] to [-1...+1]
|
pan = (pan - 0.5) * 2.0; // Transpose pan from [0...1] to [-1...+1]
|
||||||
|
|
||||||
impl.source.SetPan(pan);
|
impl.pan = pan;
|
||||||
impl.source.SetGain(std::max(lvol, rvol) / 256.0);
|
impl.gain = std::max(lvol, rvol) / 256.0;
|
||||||
|
|
||||||
|
impl.ApplyParametersToSource(kApplyParameters_PanAndGain);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case freqCmd:
|
case freqCmd:
|
||||||
LOG << "freqCmd " << cmd->param2 << " " << GetMidiNoteName(cmd->param2) << " " << midiNoteFrequencies[cmd->param2] << "\n";
|
LOG << "freqCmd " << cmd->param2 << " " << GetMidiNoteName(cmd->param2) << " " << midiNoteFrequencies[cmd->param2] << "\n";
|
||||||
impl.playbackNote = Byte(cmd->param2);
|
impl.playbackNote = Byte(cmd->param2);
|
||||||
impl.ApplyPitch();
|
impl.ApplyParametersToSource(kApplyParameters_Pitch);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case rateCmd:
|
case rateCmd:
|
||||||
// IM:S says it's a fixed-point multiplier of 22KHz, but Nanosaur uses rate "1" everywhere,
|
// IM:S says it's a fixed-point multiplier of 22KHz, but Nanosaur uses rate "1" everywhere,
|
||||||
// even for sounds sampled at 44Khz, so I'm treating it as just a pitch multiplier.
|
// even for sounds sampled at 44Khz, so I'm treating it as just a pitch multiplier.
|
||||||
impl.pitchMult = cmd->param2 / 65536.0;
|
impl.pitchMult = cmd->param2 / 65536.0;
|
||||||
impl.ApplyPitch();
|
impl.ApplyParametersToSource(kApplyParameters_Pitch);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case rateMultiplierCmd:
|
case rateMultiplierCmd:
|
||||||
impl.pitchMult = cmd->param2 / 65536.0;
|
impl.pitchMult = cmd->param2 / 65536.0;
|
||||||
impl.ApplyPitch();
|
impl.ApplyParametersToSource(kApplyParameters_Pitch);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case pommeSetLoopCmd:
|
case pommeSetLoopCmd:
|
||||||
impl.source.SetLoop(cmd->param1);
|
impl.loop = cmd->param1;
|
||||||
|
impl.ApplyParametersToSource(kApplyParameters_Loop);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -541,7 +582,7 @@ OSErr SndDoImmediate(SndChannelPtr chan, const SndCommand* cmd)
|
||||||
|
|
||||||
OSErr SndDoCommand(SndChannelPtr chan, const SndCommand* cmd, Boolean noWait)
|
OSErr SndDoCommand(SndChannelPtr chan, const SndCommand* cmd, Boolean noWait)
|
||||||
{
|
{
|
||||||
TODOMINOR();
|
TODOMINOR2("SndDoCommand isn't implemented yet, but you can probably use SndDoImmediate instead.");
|
||||||
return noErr;
|
return noErr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user