Example #1
0
void loadwaves(void)
{
	long fil, dawaversionum, i, tmp;
	long wavleng[MAXWAVES], repstart[MAXWAVES], repleng[MAXWAVES], finetune[MAXWAVES];
	char *p;

	fil = kopen4load("WAVES.KWV", 0);

	if (fil != -1) {
		kread(fil, &dawaversionum, 4); dawaversionum = B_LITTLE32(dawaversionum);
		if (dawaversionum != 0) { kclose(fil); return; }

		kread(fil, &numwaves, 4); numwaves = B_LITTLE32(numwaves);
		for (i=0; i<numwaves; i++) {
			kread(fil, &instname[i][0], 16);
			kread(fil, &wavleng[i], 4);  wavleng[i]  = B_LITTLE32(wavleng[i]);
			kread(fil, &repstart[i], 4); repstart[i] = B_LITTLE32(repstart[i]);
			kread(fil, &repleng[i], 4);  repleng[i]  = B_LITTLE32(repleng[i]);
			kread(fil, &finetune[i], 4); finetune[i] = B_LITTLE32(finetune[i]);
		}
	} else {
		dawaversionum = 0;
		numwaves = 0;
	}

	for (i=numwaves; i<MAXWAVES; i++) {
		memset(&instname[i][0], 0, 16);
		wavleng[i] = 0;
		repstart[i] = 0;
		repleng[i] = 0;
		finetune[i] = 0;
		samples[i] = NULL;
	}

	if (fil == -1) return;

#if 0
	for (i=0; i<numwaves; i++) {
		if (repleng[i]) tmp = FSOUND_LOOP_NORMAL;
		else tmp = FSOUND_LOOP_OFF;
		samples[i] = FSOUND_Sample_Alloc(FSOUND_FREE, wavleng[i], tmp, 11025, 255, 128, 1);
		if (!samples[i]) continue;

		p = (char*)Bmalloc(wavleng[i]);
		kread(fil,p,wavleng[i]);
		FSOUND_Sample_Upload(samples[i], p, FSOUND_8BITS | FSOUND_MONO | FSOUND_UNSIGNED);
		Bfree(p);

		if (repleng[i]) FSOUND_Sample_SetLoopPoints(samples[i], repstart[i], repstart[i]+repleng[i]);
	}
#endif

	kclose(fil);

	printOSD("Loaded %d waves\n", numwaves);
}
Example #2
0
/******************************************************************************
 *
 * Initialise driver and listener
 *
 *****************************************************************************/
EXPORT INT32 HWRAPI(Startup) (I_Error_t FatalErrorFunction, snddev_t *snd_dev)
{
	boolean inited = false;
	INT32 i = 0;

	I_ErrorFMOD = FatalErrorFunction;

	if (FSOUND_GetVersion() < FMOD_VERSION)
	{
		DBG_Printf("Error : You are using the wrong DLL version!\nYou should be using FMOD %.02f\n", FMOD_VERSION);
		return inited;
	}
	else
		DBG_Printf("S_FMOD Init(): FMOD_SOUND driver for SRB2 %s\n",VERSIONSTRING);

	if (!FSOUND_SetMinHardwareChannels(STATIC_SOURCES_NUM*4))
		DBG_Printf("FMOD(Startup,FSOUND_SetMinHardwareChannels,# of Channels Min: %i): %s\n",STATIC_SOURCES_NUM*4, FMOD_ErrorString(FSOUND_GetError()));

	if (!FSOUND_SetMaxHardwareChannels(0))
		DBG_Printf("FMOD(Startup,FSOUND_SetMaxHardwareChannels,# of Channels Min: %i): %s\n",0, FMOD_ErrorString(FSOUND_GetError()));

	for (i = 0; i < FSOUND_GetNumDrivers(); i++)
	{
		UINT32 caps = 0;
		DBG_Printf("Driver Caps, if any\n");

		if (FSOUND_GetDriverCaps(i, &caps))
		{
			DBG_Printf("FMOD: Driver# %d - %s\n", i+1, FSOUND_GetDriverName(i));    // print driver names
			if (caps & FSOUND_CAPS_HARDWARE)
				DBG_Printf("This sound hardware supports hardware accelerated 3d sound.\n");

			if (caps & FSOUND_CAPS_EAX2)
				DBG_Printf("This sound hardware supports hardware accelerated 3d sound with EAX 2 reverb.\n");

			if (caps & FSOUND_CAPS_EAX3)
				DBG_Printf("This sound hardware supports hardware accelerated 3d sound with EAX 3 reverb.\n");
		}
		else
			DBG_Printf("FMOD(Startup,FSOUND_GetDriverCaps,%s): %s\n",FSOUND_GetDriverName(i), FMOD_ErrorString(FSOUND_GetError()));
	}
#if defined (_WIN32) || defined (_WIN64)
	if (!FSOUND_SetHWND(snd_dev->hWnd))
	{
		DBG_Printf("FMOD(Startup,FSOUND_SetHWND): %s\n", FMOD_ErrorString(FSOUND_GetError()));
		return inited;
	}
	else
#endif
	{
		DBG_Printf("Initialising FMOD %.02f\n",FMOD_VERSION);
		inited = FSOUND_Init(snd_dev->sample_rate,MAXCHANNEL,0);
	}

	if (!inited)
	{
		DBG_Printf("FMOD(Startup,Main): %s\n", FMOD_ErrorString(FSOUND_GetError()));
	}
	else
	{
#ifdef OLDFMOD
		DBG_Printf("   Maximum hardware mixing buffers %d\n", FSOUND_GetNumHardwareChannels());
#else
		INT32 num2DC, num3DC, numDC;

		if (FSOUND_GetNumHWChannels(&num2DC,&num3DC,&numDC))
		{
			DBG_Printf("   Maximum hardware 2D buffers %d\n", num2DC);
			DBG_Printf("   Maximum hardware 3D buffers %d\n", num3DC);
			DBG_Printf("   Maximum hardware mixing buffers %d\n", numDC);
		}
		else
			DBG_Printf("FMOD(Startup,FSOUND_GetNumHWChannels): %s\n", FMOD_ErrorString(FSOUND_GetError()));
#endif

		DBG_Printf("FMOD is up and running at %i KHZ\n",FSOUND_GetOutputRate());
		DBG_Printf("Sound hardware capabilities:\n");

		if (FSOUND_GetDriverName(FSOUND_GetDriver()))
			DBG_Printf("   Driver is %s\n",FSOUND_GetDriverName(FSOUND_GetDriver()));
		else
			DBG_Printf("FMOD(Startup,FSOUND_GetDriverName): %s\n", FMOD_ErrorString(FSOUND_GetError()));

		FSOUND_3D_SetDistanceFactor(1.0f/72.0f);
		FSOUND_3D_SetRolloffFactor(0);
		FSOUND_3D_SetRolloffFactor(1.6f);
#ifdef MORESTUFF
		FSOUND_3D_SetDopplerFactor(0);
#endif

		switch (FSOUND_GetOutput())
		{
			case FSOUND_OUTPUT_NOSOUND:
				DBG_Printf("FMOD driver: NoSound driver, all calls to this succeed but do nothing.\n");
				break;
			case FSOUND_OUTPUT_WINMM:
				DBG_Printf("FMOD driver: Windows Multimedia driver.\n");
				break;
			case FSOUND_OUTPUT_DSOUND:
				DBG_Printf("FMOD driver: DirectSound driver. You need this to get EAX2 or EAX3 support, or FX api support.\n");
				break;
			case FSOUND_OUTPUT_A3D:
				DBG_Printf("FMOD driver: A3D driver.\n");
				break;
			case FSOUND_OUTPUT_XBOX:
				DBG_Printf("FMOD driver: Xbox driver\n");
				break;
			case FSOUND_OUTPUT_OSS:
				DBG_Printf("FMOD driver: Linux/Unix OSS (Open Sound System) driver, i.e. the kernel sound drivers.\n");
				break;
			case FSOUND_OUTPUT_ESD:
				DBG_Printf("FMOD driver: Linux/Unix ESD (Enlightment Sound Daemon) driver.\n");
				break;
			case FSOUND_OUTPUT_ALSA:
				DBG_Printf("FMOD driver: Linux Alsa driver.\n");
				break;
			case FSOUND_OUTPUT_MAC:
				DBG_Printf("FMOD driver: Mac SoundManager driver\n");
				break;
			case FSOUND_OUTPUT_PS2:
				DBG_Printf("FMOD driver: PlayStation 2 driver\n");
				break;
			case FSOUND_OUTPUT_GC:
				DBG_Printf("FMOD driver: Gamecube driver\n");
				break;
			case FSOUND_OUTPUT_NOSOUND_NONREALTIME:
				DBG_Printf("FMOD driver: This is the same as nosound, but the sound generation is driven by FSOUND_Update\n");
				break;
			case FSOUND_OUTPUT_ASIO:
				DBG_Printf("FMOD driver: Low latency ASIO driver\n");
				break;
			default:
				DBG_Printf("FMOD driver: Unknown Sound Driver\n");
				break;
		}

		relsetup();

		blankfmsample = FSOUND_Sample_Alloc(FSOUND_UNMANAGED,1,FSOUND_UNORMAL,11025,127,FSOUND_STEREOPAN,127);

		if (!blankfmsample)
			DBG_Printf("FMOD(Startup,FSOUND_Sample_Alloc): %s\n", FMOD_ErrorString(FSOUND_GetError()));
		else if (!FSOUND_Sample_SetMaxPlaybacks(blankfmsample,STATIC_SOURCES_NUM*2))
			DBG_Printf("FMOD(Startup,FSOUND_Sample_SetMaxPlaybacks): %s\n", FMOD_ErrorString(FSOUND_GetError()));
	}
	return inited;
}
Example #3
0
int main()
{
    FSOUND_SAMPLE *samp1;
    int channel, originalfreq;

    if (FSOUND_GetVersion() < FMOD_VERSION)
    {
        printf("Error : You are using the wrong DLL version!  You should be using FMOD %.02f\n", FMOD_VERSION);
        return 0;
    }
		
    /*
        INITIALIZE
    */
    if (!FSOUND_Init(44100, 16, FSOUND_INIT_ACCURATEVULEVELS))
    {
        printf("Error!\n");
        printf("%s\n", FMOD_ErrorString(FSOUND_GetError()));
        return 0;
    }

    /*
        RECORD INTO A STATIC SAMPLE
    */

    /*
        Create a sample to record into
    */
    samp1 = FSOUND_Sample_Alloc(FSOUND_UNMANAGED, RECORDLEN, FSOUND_STEREO | FSOUND_16BITS , 44100, 255, 128, 255);

    printf("\n=========================================================================\n");
    printf("Press a key to start recording 5 seconds worth of 44khz 16bit data\n");
    printf("=========================================================================\n");

    getch();

    if (!FSOUND_Record_StartSample(samp1, FALSE))	/* it will record into this sample for 5 seconds then stop */
    {
        printf("Error!\n");
        printf("%s\n", FMOD_ErrorString(FSOUND_GetError()));

        FSOUND_Close();
        return 0;
    }

    do
    {
        printf("\rRecording position = %d", FSOUND_Record_GetPosition());
        fflush(stdout);
        Sleep(50);
    } while (FSOUND_Record_GetPosition() < RECORDLEN && !kbhit());
	
    FSOUND_Record_Stop();	/* it already stopped anyway */

    printf("\n=========================================================================\n");
    printf("Press a key to play back recorded data\n");
    printf("=========================================================================\n");

    getch();

    channel = FSOUND_PlaySound(FSOUND_FREE, samp1);

    printf("Playing back sound...\n");

    do
    {
        printf("\rPlayback position = %d", FSOUND_GetCurrentPosition(channel));
        fflush(stdout);
        Sleep(50);
    } while (FSOUND_IsPlaying(channel) && !kbhit());

    /*
        REALTIME FULL DUPLEX RECORD / PLAYBACK!
    */

    printf("\n=========================================================================\n");
    printf("Press a key to do some full duplex realtime recording!\n");
    printf("=========================================================================\n");

    getch();

    FSOUND_Sample_SetMode(samp1, FSOUND_LOOP_NORMAL);	/* make it a looping sample */

    if (!FSOUND_Record_StartSample(samp1, TRUE))	/* start recording and make it loop also */
    {
        printf("Error!\n");
        printf("%s\n", FMOD_ErrorString(FSOUND_GetError()));

        FSOUND_Close();
        return 0;
    }

    /*
        Increase this value if the sound sounds corrupted or the time between recording
        and hearing the result is longer than it should be..
    */
    #define RECORD_DELAY_MS			25
    #define RECORD_DELAY_SAMPLES	(44100 * RECORD_DELAY_MS / 1000)

    /*
        Let the record cursor move forward a little bit first before we try to play it
	    (the position jumps in blocks, so any non 0 value will mean 1 block has been recorded)
    */
    while (!FSOUND_Record_GetPosition()) 
    {
        Sleep(1);
    }

#ifdef ENABLEREVERB
    SetupReverb();
#endif

    channel = FSOUND_PlaySound(FSOUND_FREE, samp1);	/* play the sound */

    originalfreq = FSOUND_GetFrequency(channel);
		
/*	printf("initial delay = %d\n", FSOUND_GetCurrentPosition(channel) - FSOUND_Record_GetPosition()); */

    do
    {
        int playpos, recordpos, diff;
        static int oldrecordpos = 0, oldplaypos = 0;

        playpos = FSOUND_GetCurrentPosition(channel);
        recordpos = FSOUND_Record_GetPosition();

        /* 
            NOTE : As the recording and playback frequencies arent guarranteed to be exactly in 
		    sync, we have to adjust the playback frequency to keep the 2 cursors just enough 
		    apart not to overlap. (and sound corrupted)
		    This code tries to keep it inside a reasonable size window just behind the record
		    cursor. ie [........|play window|<-delay->|<-Record cursor.............] 
        */

        /*
            Dont do this code if either of the cursors just wrapped
        */
        if (playpos > oldplaypos && recordpos > oldrecordpos)	
        {
            diff = playpos - recordpos;

            if (diff > -RECORD_DELAY_SAMPLES)
            {
                FSOUND_SetFrequency(channel, originalfreq - 1000);	/* slow it down */
            }
            else if (diff < -(RECORD_DELAY_SAMPLES * 2))
            {
                FSOUND_SetFrequency(channel, originalfreq + 1000);	/* speed it up */
            }
            else
            {
                FSOUND_SetFrequency(channel, originalfreq);	
            }
        }

        oldplaypos = playpos;
        oldrecordpos = recordpos;

        /*
            Print some info and a VU meter (vu is smoothed)
        */
        {
            char vu[19];
            float vuval, l, r;
            static float smoothedvu = 0;

            FSOUND_GetCurrentLevels(channel, &l, &r);
            vuval = (l+r) * 0.5f;
            vuval *= 18.0f;

            #define VUSPEED 0.2f

            if (vuval > smoothedvu)
            {
                smoothedvu = vuval;
            }

            smoothedvu -= VUSPEED;
            if (smoothedvu < 0)
            {
                smoothedvu = 0;
            }

		    memset(vu, 0, 19);
		    memset(vu, '=', (int)(smoothedvu));

            printf("\rPlay=%6d Rec=%6d (gap=%6d, freqchange=%6d hz) VU:%-15s", playpos, recordpos,  diff, FSOUND_GetFrequency(channel) - originalfreq, vu);
	        fflush(stdout);
        }

        Sleep(10);
    } while (!kbhit());

    FSOUND_StopSound(channel);
    FSOUND_Record_Stop();

#ifdef ENABLEREVERB		
    CloseReverb();
#endif

    /*
        CLEANUP AND SHUTDOWN
    */

    FSOUND_Close();

    return 0;
}
Example #4
0
int main(int argc, char *argv[])
{
	FSOUND_SAMPLE *samp1;
	signed char key;
	int driver, i, channel, originalfreq;

	if (FSOUND_GetVersion() < FMOD_VERSION)
	{
		printf("Error : You are using the wrong DLL version!  You should be using FMOD %.02f\n", FMOD_VERSION);
		return 0;
	}

	/*
	    SELECT OUTPUT METHOD
	*/
	
    printf("---------------------------------------------------------\n");	
    printf("Output Type\n");	
    printf("---------------------------------------------------------\n");	
#if defined(WIN32) || defined(__CYGWIN32__) || defined(__WATCOMC__)
    printf("1 - Direct Sound\n");
    printf("2 - Windows Multimedia Waveout\n");
    printf("3 - NoSound\n");
#elif defined(__linux__)
    printf("1 - OSS - Open Sound System\n");
    printf("2 - ESD - Elightment Sound Daemon\n");
    printf("3 - ALSA 0.9 - Advanced Linux Sound Architecture\n");   
#endif
	printf("---------------------------------------------------------\n");	/* print driver names */
	printf("Press a corresponding number or ESC to quit\n");

	do
	{
		key = getch();
	} while (key != 27 && key < '1' && key > '4');
	
	switch (key)
	{
#if defined(WIN32) || defined(__CYGWIN32__) || defined(__WATCOMC__)
		case '1' :	FSOUND_SetOutput(FSOUND_OUTPUT_DSOUND);
					break;
		case '2' :	FSOUND_SetOutput(FSOUND_OUTPUT_WINMM);
					break;
		case '3' :	FSOUND_SetOutput(FSOUND_OUTPUT_NOSOUND);
					break;
#elif defined(__linux__)
		case '1' :	FSOUND_SetOutput(FSOUND_OUTPUT_OSS);
					break;
		case '2' :	FSOUND_SetOutput(FSOUND_OUTPUT_ESD);
					break;
		case '3' :	FSOUND_SetOutput(FSOUND_OUTPUT_ALSA);
					break;
#endif
		default :	return 0;
	}
	
	/*
	    SELECT OUTPUT DRIVER
	*/

	/* The following list are the drivers for the output method selected above. */
    printf("---------------------------------------------------------\n");	
    switch (FSOUND_GetOutput())
    {
        case FSOUND_OUTPUT_NOSOUND:    printf("NoSound"); break;
        case FSOUND_OUTPUT_WINMM:      printf("Windows Multimedia Waveout"); break;
        case FSOUND_OUTPUT_DSOUND:     printf("Direct Sound"); break;
        case FSOUND_OUTPUT_OSS:        printf("Open Sound System"); break;
        case FSOUND_OUTPUT_ESD:        printf("Enlightment Sound Daemon"); break;
        case FSOUND_OUTPUT_ALSA:       printf("ALSA"); break;       
    };
	printf(" Driver list\n");	
	printf("---------------------------------------------------------\n");	

	for (i=0; i < FSOUND_GetNumDrivers(); i++) 
	{
		printf("%d - %s\n", i+1, FSOUND_GetDriverName(i));	/* print driver names */
	}
	printf("---------------------------------------------------------\n");	/* print driver names */
	printf("Press a corresponding number or ESC to quit\n");

	do
	{
		key = getch();
		if (key == 27) 
		{
			FSOUND_Close();
			return 0;
		}
		driver = key - '1';
	} while (driver < 0 || driver >= FSOUND_GetNumDrivers());

	FSOUND_SetDriver(driver);					/* Select sound card (0 = default) */

	/*
	    SELECT MIXER
	*/

	FSOUND_SetMixer(FSOUND_MIXER_QUALITY_AUTODETECT);
		
	/*
	    INITIALIZE
	*/
	if (!FSOUND_Init(44100, 64, FSOUND_INIT_ACCURATEVULEVELS))
	{
		printf("Error!\n");
		printf("%s\n", FMOD_ErrorString(FSOUND_GetError()));
		return 0;
	}


	/*
	    SELECT INPUT DRIVER (can be done before or after init)
	*/

	/* The following list are the drivers for the output method selected above. */
	printf("---------------------------------------------------------\n");	
	switch (FSOUND_GetOutput())
	{
        case FSOUND_OUTPUT_NOSOUND:    printf("NoSound"); break;
        case FSOUND_OUTPUT_WINMM:      printf("Windows Multimedia Waveout"); break;
        case FSOUND_OUTPUT_DSOUND:     printf("Direct Sound"); break;
        case FSOUND_OUTPUT_OSS:        printf("Open Sound System"); break;
        case FSOUND_OUTPUT_ESD:        printf("Enlightment Sound Daemon"); break;
        case FSOUND_OUTPUT_ALSA:       printf("ALSA"); break;       
	};
	printf(" Recording device driver list\n");	
	printf("---------------------------------------------------------\n");	

	for (i=0; i < FSOUND_Record_GetNumDrivers(); i++) 
	{
		printf("%d - %s\n", i+1, FSOUND_Record_GetDriverName(i));	/* print driver names */
	}
	printf("---------------------------------------------------------\n");	/* print driver names */
	printf("Press a corresponding number or ESC to quit\n");

	do
	{
		key = getch();
		if (key == 27) 
			return 0;
		driver = key - '1';
	} while (driver < 0 || driver >= FSOUND_Record_GetNumDrivers());

	if (!FSOUND_Record_SetDriver(driver))	/* Select input sound card (0 = default) */
	{
		printf("Error!\n");
		printf("%s\n", FMOD_ErrorString(FSOUND_GetError()));
		FSOUND_Close();
		return 0;
	}
	
	/*
	    DISPLAY HELP
	*/

	printf("FSOUND Output Method : ");
	switch (FSOUND_GetOutput())
	{
        case FSOUND_OUTPUT_NOSOUND:    printf("FSOUND_OUTPUT_NOSOUND\n"); break;
        case FSOUND_OUTPUT_WINMM:      printf("FSOUND_OUTPUT_WINMM\n"); break;
        case FSOUND_OUTPUT_DSOUND:     printf("FSOUND_OUTPUT_DSOUND\n"); break;
        case FSOUND_OUTPUT_OSS:        printf("FSOUND_OUTPUT_OSS\n"); break;
        case FSOUND_OUTPUT_ESD:        printf("FSOUND_OUTPUT_ESD\n"); break;
        case FSOUND_OUTPUT_ALSA:       printf("FSOUND_OUTPUT_ALSA\n"); break;       
	};

	printf("FSOUND Mixer         : ");
	switch (FSOUND_GetMixer())
	{
		case FSOUND_MIXER_BLENDMODE:	printf("FSOUND_MIXER_BLENDMODE\n"); break;
		case FSOUND_MIXER_MMXP5:		printf("FSOUND_MIXER_MMXP5\n"); break;
		case FSOUND_MIXER_MMXP6:		printf("FSOUND_MIXER_MMXP6\n"); break;
		case FSOUND_MIXER_QUALITY_FPU:	printf("FSOUND_MIXER_QUALITY_FPU\n"); break;
		case FSOUND_MIXER_QUALITY_MMXP5:printf("FSOUND_MIXER_QUALITY_MMXP5\n"); break;
		case FSOUND_MIXER_QUALITY_MMXP6:printf("FSOUND_MIXER_QUALITY_MMXP6\n"); break;
	};
	printf("FSOUND Driver        : %s\n", FSOUND_GetDriverName(FSOUND_GetDriver()));
	printf("FSOUND Record Driver : %s\n", FSOUND_Record_GetDriverName(FSOUND_Record_GetDriver()));

	/*
	    RECORD INTO A STATIC SAMPLE
	*/

	/*
        Create a sample to record into
    */
    samp1 = FSOUND_Sample_Alloc(FSOUND_UNMANAGED, RECORDLEN, FSOUND_STEREO | FSOUND_16BITS , RECORDRATE, 255, 128, 255);
    if (!samp1)
    {
        printf("Error!\n");
		printf("%s\n", FMOD_ErrorString(FSOUND_GetError()));
        FSOUND_Close();
        return 0;
    }

	printf("\n");
	printf("=========================================================================\n");
	printf("Press a key to start recording 5 seconds worth of data\n");
	printf("=========================================================================\n");

	getch();

	if (!FSOUND_Record_StartSample(samp1, FALSE))	/* it will record into this sample for 5 seconds then stop */
	{
		printf("Error!\n");
		printf("%s\n", FMOD_ErrorString(FSOUND_GetError()));

		FSOUND_Close();
		return 0;
	}

	do
	{
		printf("Recording position = %d\r", FSOUND_Record_GetPosition());
		Sleep(50);
	} while (FSOUND_Record_GetPosition() < RECORDLEN && !kbhit());

	FSOUND_Record_Stop();	/* it already stopped anyway */

	printf("\n=========================================================================\n");
	printf("Press a key to play back recorded data\n");
	printf("=========================================================================\n");

	getch();

	channel = FSOUND_PlaySound(FSOUND_FREE, samp1);

	printf("Playing back sound...\n");

	do
	{
		printf("Playback position = %d\r", FSOUND_GetCurrentPosition(channel));
		Sleep(50);
	} while (FSOUND_IsPlaying(channel) && !kbhit());

    if (FSOUND_GetOutput() == FSOUND_OUTPUT_OSS)
    {
        FSOUND_Sample_Free(samp1);
        FSOUND_Close();
        return 0;
    }

	/*
	    REALTIME FULL DUPLEX RECORD / PLAYBACK!
	*/

	printf("\n=========================================================================\n");
	printf("Press a key to do some full duplex realtime recording!\n");
	printf("(with reverb for mmx users)\n");
	printf("=========================================================================\n");

	getch();

	FSOUND_Sample_SetMode(samp1, FSOUND_LOOP_NORMAL);	/* make it a looping sample */

	if (!FSOUND_Record_StartSample(samp1, TRUE))	/* start recording and make it loop also */
	{
		printf("Error!\n");
		printf("%s\n", FMOD_ErrorString(FSOUND_GetError()));

		FSOUND_Close();
		return 0;
	}

    /*
        Increase this value if the sound sounds corrupted or the time between recording
        and hearing the result is longer than it should be..
    */
    #define RECORD_DELAY_MS       25
    #define RECORD_DELAY_SAMPLES  (RECORDRATE * RECORD_DELAY_MS / 1000)

    /*
        Let the record cursor move forward a little bit first before we try to play it
        (the position jumps in blocks, so any non 0 value will mean 1 block has been recorded)
    */
    while (!FSOUND_Record_GetPosition()) 
    {
        Sleep(1);
    }

#ifdef ENABLEREVERB
	SetupReverb();
#endif

	channel = FSOUND_PlaySound(FSOUND_FREE, samp1);	/* play the sound */

	originalfreq = FSOUND_GetFrequency(channel);
		
/*	printf("initial delay = %d\n", FSOUND_GetCurrentPosition(channel) - FSOUND_Record_GetPosition()); */

	do
	{
		int playpos, recordpos, diff;
		static int oldrecordpos = 0, oldplaypos = 0;

		playpos = FSOUND_GetCurrentPosition(channel);
		recordpos = FSOUND_Record_GetPosition();

		/* 
            NOTE : As the recording and playback frequencies arent guarranteed to be exactly in 
		    sync, we have to adjust the playback frequency to keep the 2 cursors just enough 
		    apart not to overlap. (and sound corrupted)
		    This code tries to keep it inside a reasonable size window just behind the record
		    cursor. ie [........|play window|<-delay->|<-Record cursor.............] 
        */

		/*
            Dont do this code if either of the cursors just wrapped
        */
		if (playpos > oldplaypos && recordpos > oldrecordpos)	
		{
			diff = playpos - recordpos;

			if (diff > -RECORD_DELAY_SAMPLES)
            {
				FSOUND_SetFrequency(channel, originalfreq - 1000);	/* slow it down */
            }
			else if (diff < -(RECORD_DELAY_SAMPLES * 2))
            {
				FSOUND_SetFrequency(channel, originalfreq + 1000);	/* speed it up */
            }
			else
            {
				FSOUND_SetFrequency(channel, originalfreq);	
            }
		}

		oldplaypos = playpos;
		oldrecordpos = recordpos;

		/*
            Print some info and a VU meter (vu is smoothed)
        */
		{
			char vu[19];
			float vuval, l, r;
			static float smoothedvu = 0;

			FSOUND_GetCurrentLevels(channel, &l, &r);
            vuval = (l+r) * 0.5f;
            vuval *= 18.0f;

			#define VUSPEED 0.2f

			if (vuval > smoothedvu)
            {
				smoothedvu = vuval;
            }

			smoothedvu -= VUSPEED;
			if (smoothedvu < 0)
            {
				smoothedvu = 0;
            }

			memset(vu, 0, 19);
			memset(vu, '=', (int)(smoothedvu));

			printf("Play=%6d Rec=%6d (gap=%6d, freqchange=%6d hz) VU:%-15s\r", playpos, recordpos,  diff, FSOUND_GetFrequency(channel) - originalfreq, vu);
		}

		Sleep(10);
	} while (!kbhit());

    getch();

	FSOUND_StopSound(channel);
	FSOUND_Record_Stop();

#ifdef ENABLEREVERB		
	CloseReverb();
#endif

	/*
	    CLEANUP AND SHUTDOWN
	*/

    FSOUND_Sample_Free(samp1);
    FSOUND_Close();
    return 0;
}