axmol/CocosDenshion/third_party/fmod/examples/dsp_effectperspeaker/main.c

269 lines
8.6 KiB
C

/*===============================================================================================
DSP Effect per speaker Example
Copyright (c), Firelight Technologies Pty, Ltd 2004-2011.
This example shows how to manipulate a DSP network and as an example, creates 2 dsp effects,
and splits a single sound into 2 audio paths, which it then filters seperately.
To only have each audio path come out of one speaker each, FMOD_DSPConnection_setLevels is used just
before the 2 branches merge back together again.
For more speakers:
1. Use FMOD_System_SetSpeakerMode or FMOD_System_SetOutputFormat.
2. Create more effects, currently 2 for stereo (reverb and chorus), create one per speaker.
3. Under the 'Now connect the 2 effects to channeldsp head.' section, connect the extra effects
by duplicating the code more times.
4. Filter each effect to each speaker by calling FMOD_DSP_SetInputLevels. Expand the existing code
by extending the level arrays from 2 to the number of speakers you require, and change the
numlevels parameter in FMOD_DSP_SetInputLevels from 2 to the correct number accordingly.
===============================================================================================*/
#include "../common/wincompat.h"
#include "../../api/inc/fmod.h"
#include "../../api/inc/fmod_errors.h"
void ERRCHECK(FMOD_RESULT result)
{
if (result != FMOD_OK)
{
printf("FMOD error! (%d) %s\n", result, FMOD_ErrorString(result));
exit(-1);
}
}
int main(int argc, char *argv[])
{
FMOD_SYSTEM *system;
FMOD_SOUND *sound;
FMOD_CHANNEL *channel;
FMOD_DSP *dsplowpass, *dspchorus, *dsphead, *dspchannelmixer;
FMOD_DSPCONNECTION *dsplowpassconnection, *dspchorusconnection;
FMOD_RESULT result;
int key;
unsigned int version;
float pan = 0;
/*
Create a System object and initialize.
*/
result = FMOD_System_Create(&system);
ERRCHECK(result);
result = FMOD_System_GetVersion(system, &version);
ERRCHECK(result);
if (version < FMOD_VERSION)
{
printf("Error! You are using an old version of FMOD %08x. This program requires %08x\n", version, FMOD_VERSION);
return 0;
}
result = FMOD_System_Init(system, 32, FMOD_INIT_NORMAL, 0);
ERRCHECK(result);
result = FMOD_System_CreateSound(system, "../media/drumloop.wav", FMOD_SOFTWARE | FMOD_LOOP_NORMAL, 0, &sound);
ERRCHECK(result);
printf("===============================================================================\n");
printf("DSP Effect per speaker example. Copyright (c) Firelight Technologies 2004-2011.\n");
printf("===============================================================================\n");
printf("Press 'L' to toggle reverb on/off on left speaker only\n");
printf("Press 'R' to toggle chorus on/off on right speaker only\n");
printf("Press '[' to pan sound left\n");
printf("Press ']' to pan sound right\n");
printf("Press 'Esc' to quit\n");
printf("\n");
result = FMOD_System_PlaySound(system, FMOD_CHANNEL_FREE, sound, FALSE, &channel);
ERRCHECK(result);
/*
Create the DSP effects.
*/
result = FMOD_System_CreateDSPByType(system, FMOD_DSP_TYPE_REVERB, &dsplowpass);
ERRCHECK(result);
result = FMOD_System_CreateDSPByType(system, FMOD_DSP_TYPE_CHORUS, &dspchorus);
ERRCHECK(result);
/*
Connect up the DSP network
*/
/*
When a sound is played, a subnetwork is set up in the DSP network which looks like this.
Wavetable is the drumloop sound, and it feeds its data from right to left.
[DSPHEAD]<------------[DSPCHANNELMIXER]
*/
result = FMOD_System_GetDSPHead(system, &dsphead);
ERRCHECK(result);
result = FMOD_DSP_GetInput(dsphead, 0, &dspchannelmixer, 0);
ERRCHECK(result);
/*
Now disconnect channeldsp head from wavetable to look like this.
[DSPHEAD] [DSPCHANNELMIXER]
*/
result = FMOD_DSP_DisconnectFrom(dsphead, dspchannelmixer);
ERRCHECK(result);
/*
Now connect the 2 effects to channeldsp head.
Store the 2 connections this makes so we can set their speakerlevels later.
[DSPLOWPASS]
/x
[DSPHEAD] [DSPCHANNELMIXER]
\y
[DSPCHORUS]
*/
result = FMOD_DSP_AddInput(dsphead, dsplowpass, &dsplowpassconnection); /* x = dsplowpassconnection */
ERRCHECK(result);
result = FMOD_DSP_AddInput(dsphead, dspchorus, &dspchorusconnection); /* y = dspchorusconnection */
ERRCHECK(result);
/*
Now connect the wavetable to the 2 effects
[DSPLOWPASS]
/x \
[DSPHEAD] [DSPCHANNELMIXER]
\y /
[DSPCHORUS]
*/
result = FMOD_DSP_AddInput(dsplowpass, dspchannelmixer, NULL); /* Null for connection - we dont care about it. */
ERRCHECK(result);
result = FMOD_DSP_AddInput(dspchorus, dspchannelmixer, NULL); /* Null for connection - we dont care about it. */
ERRCHECK(result);
/*
Now the drumloop will be twice as loud, because it is being split into 2, then recombined at the end.
What we really want is to only feed the dspchannelmixer->dsplowpass through the left speaker, and
dspchannelmixer->dspchorus to the right speaker.
We can do that simply by setting the pan, or speaker levels of the connections.
[DSPLOWPASS]
/x=1,0 \
[DSPHEAD] [DSPCHANNELMIXER]
\y=0,1 /
[DSPCHORUS]
*/
{
float leftinputon[2] = { 1.0f, 0.0f };
float rightinputon[2] = { 0.0f, 1.0f };
float inputsoff[2] = { 0.0f, 0.0f };
result = FMOD_DSPConnection_SetLevels(dsplowpassconnection, FMOD_SPEAKER_FRONT_LEFT, leftinputon, 2);
ERRCHECK(result);
result = FMOD_DSPConnection_SetLevels(dsplowpassconnection, FMOD_SPEAKER_FRONT_RIGHT, inputsoff, 2);
ERRCHECK(result);
result = FMOD_DSPConnection_SetLevels(dspchorusconnection, FMOD_SPEAKER_FRONT_LEFT, inputsoff, 2);
ERRCHECK(result);
result = FMOD_DSPConnection_SetLevels(dspchorusconnection, FMOD_SPEAKER_FRONT_RIGHT, rightinputon, 2);
ERRCHECK(result);
}
result = FMOD_DSP_SetBypass(dsplowpass, TRUE);
result = FMOD_DSP_SetBypass(dspchorus, TRUE);
result = FMOD_DSP_SetActive(dsplowpass, TRUE);
result = FMOD_DSP_SetActive(dspchorus, TRUE);
/*
Main loop.
*/
do
{
if (kbhit())
{
key = getch();
switch (key)
{
case 'l' :
case 'L' :
{
static int reverb = FALSE;
FMOD_DSP_SetBypass(dsplowpass, reverb);
reverb = !reverb;
break;
}
case 'r' :
case 'R' :
{
static int chorus = FALSE;
FMOD_DSP_SetBypass(dspchorus, chorus);
chorus = !chorus;
break;
}
case '[' :
{
FMOD_Channel_GetPan(channel, &pan);
pan -= 0.1f;
if (pan < -1)
{
pan = -1;
}
FMOD_Channel_SetPan(channel, pan);
break;
}
case ']' :
{
FMOD_Channel_GetPan(channel, &pan);
pan += 0.1f;
if (pan > 1)
{
pan = 1;
}
FMOD_Channel_SetPan(channel, pan);
break;
}
}
}
FMOD_System_Update(system);
{
int channelsplaying = 0;
FMOD_System_GetChannelsPlaying(system, &channelsplaying);
printf("Channels Playing %2d : Pan = %.02f\r", channelsplaying, pan);
}
fflush(stdout);
Sleep(10);
} while (key != 27);
printf("\n");
/*
Shut down
*/
result = FMOD_Sound_Release(sound);
ERRCHECK(result);
result = FMOD_DSP_Release(dsplowpass);
ERRCHECK(result);
result = FMOD_DSP_Release(dspchorus);
ERRCHECK(result);
result = FMOD_System_Close(system);
ERRCHECK(result);
result = FMOD_System_Release(system);
ERRCHECK(result);
return 0;
}