About clicking noise

I don’t know what the correct term is but anyway clicking noise, tick noise or something keeps annoying me.

I never knew I had such an issue, but just realized there always has been tick sound whenever I suddenly stop/pause/mute the audio, especially in the middle of the loud sound.

The same also happens with other audio applications, so I don’t think it’s FMOD’s own problem, and maybe it’s my audio card or something but I really have to avoid this problem.

Imagine a virtual piano. If I hit the same key, the sound that was playing that note has to be stopped/paused/muted before playing it again. But when I try stopping/pausing/muting, I can always hear the tick noise.
I tested some other virtual musical keyboard applications on my computer, but those didn’t have such a problem, of course.
So, there must be a workaround for this, I believe.
Do you have any idea for this? Should I turn down the volume(=fade out) very quickly instead of stopping/pausing/muting?

EDIT :
I tested this way and worked. But I hope there’s a better workaround…

FMOD_Channel_SetVolume(channel, 0.0001f); // lower than this value such as 0.00001f caused the same issue.
Sleep(50); // lower than 50ms caused the same issue. And rarely this value too had the problem, but mostly ok.
FMOD_Channel_Stop(channel); // finally stop.

One more question.
There is some delay in my very simple code below.
Even though this isn’t real production code at all, I think I need to know some tips about reducing delay beforehand.
By ‘Delay’ here I mean, when I press the play key(S), the sound plays a little bit late.
This is critical to music apps, and actually it’s one of the main reasons why there aren’t many professional music apps on Android yet…

I tried :

  1. Debug -> Release Mode build

  2. FMOD_CREATESTREAM -> FMOD_CREATESAMPLE

  3. Commented out all the lines after FMOD_System_PlaySound() function call with the fourth param:FALSE.

  4. Changed the source file format from MP3 to WAV

  5. Shortened the source’s length from 30sec to 0.5sec

  6. lowered the source’s quality from 44.1K 32bit stereo to 22050Hz 8bit Mono

However none of them seemed to work.
Silly me. Calling Sleep() function was the real problem here.
But I still want to know, which of the above is valid, and also want to get any other advice from a specialist of FMOD.

#include <stdio.h>
#include <conio.h>
#include <fmod.h>
#include <windows.h>

FMOD_SYSTEM *g_System;
FMOD_SOUND *g_Sound;

FMOD_DSP *g_DSP_lowpass;
FMOD_DSP *g_DSP_highpass;
FMOD_DSP *g_DSP_echo;
FMOD_DSP *g_DSP_flange;

const char* g_szFile = “c:/test/2.mp3”;

void init() {
FMOD_System_Create(&g_System);
FMOD_System_Init(g_System, 1024, FMOD_INIT_NORMAL, NULL);
FMOD_System_CreateSound(g_System, g_szFile, FMOD_CREATESTREAM, NULL, &g_Sound);

FMOD_System_CreateDSPByType(g_System, FMOD_DSP_TYPE_LOWPASS, &g_DSP_lowpass);
FMOD_System_CreateDSPByType(g_System, FMOD_DSP_TYPE_HIGHPASS, &g_DSP_highpass);
FMOD_System_CreateDSPByType(g_System, FMOD_DSP_TYPE_ECHO, &g_DSP_echo);
FMOD_System_CreateDSPByType(g_System, FMOD_DSP_TYPE_FLANGE, &g_DSP_flange);

FMOD_DSP_SetBypass(g_DSP_lowpass, TRUE);
FMOD_DSP_SetBypass(g_DSP_highpass, TRUE);
FMOD_DSP_SetBypass(g_DSP_echo, TRUE);
FMOD_DSP_SetBypass(g_DSP_flange, TRUE);

}

int main(void) {
int nKey;
float volume = 0.5f;

FMOD_CHANNEL *channel = NULL;
FMOD_BOOL isPlaying = 0;

init();

while (1) {
	if (_kbhit()) {
		nKey = _getch();

		switch (nKey) {
		case 's':

			FMOD_Channel_IsPlaying(channel, &isPlaying);

			if (isPlaying)
				FMOD_Channel_Stop(channel);

			FMOD_System_PlaySound(g_System, g_Sound, NULL, TRUE, &channel);

			FMOD_Channel_SetVolume(channel, volume);

			FMOD_Channel_AddDSP(channel, FMOD_CHANNELCONTROL_DSP_HEAD, g_DSP_lowpass);
			FMOD_Channel_AddDSP(channel, FMOD_CHANNELCONTROL_DSP_HEAD, g_DSP_highpass);
			FMOD_Channel_AddDSP(channel, FMOD_CHANNELCONTROL_DSP_HEAD, g_DSP_echo);
			FMOD_Channel_AddDSP(channel, FMOD_CHANNELCONTROL_DSP_HEAD, g_DSP_flange);

			FMOD_Channel_SetPaused(channel, FALSE);
			break;
		case 'p':
			FMOD_Channel_IsPlaying(channel, &isPlaying);

			if (isPlaying) {
				FMOD_BOOL isPaused;
				FMOD_Channel_GetPaused(channel, &isPaused);
				FMOD_Channel_SetPaused(channel, !isPaused);
			}
			break;
		case 'm':
			FMOD_Channel_IsPlaying(channel, &isPlaying);

			if (isPlaying) {
				FMOD_BOOL isMuted;
				FMOD_Channel_GetMute(channel, &isMuted);
				FMOD_Channel_SetMute(channel, !isMuted);
			}
			break;
		case '0':
			volume += 0.1f;
			if (volume > 1.0f)
				volume = 1.0f;
			FMOD_Channel_SetVolume(channel, volume);
			break;
		case '9':
			volume -= 0.1f;
			if (volume < 0.0f)
				volume = 0.0f;
			FMOD_Channel_SetVolume(channel, volume);
			break;
		case '1':
		{
			static int bypass = 0;
			FMOD_DSP_SetBypass(g_DSP_lowpass, bypass);
			bypass = !bypass;
			break;
		}
		case '2':
		{
			static int bypass = 0;
			FMOD_DSP_SetBypass(g_DSP_highpass, bypass);
			bypass = !bypass;
			break;
		}
		case '3':
		{
			static int bypass = 0;
			FMOD_DSP_SetBypass(g_DSP_echo, bypass);
			bypass = !bypass;
			break;
		}
		case '4':
		{
			static int bypass = 0;
			FMOD_DSP_SetBypass(g_DSP_flange, bypass);
			bypass = !bypass;
			break;
		}
		}
	}
	FMOD_System_Update(g_System);

	Sleep(50);	// This needed to be deleted. Even value 1 will cause some delay.
}
return 0;

}

PS.
Funny enough, I just found an android app which has both problems I asked here.
It’s name is Real Piano (Bikon).
(https://play.google.com/store/apps/details?id=com.bilkon.easypiano)
It’s made with Unity, and that means it’s using FMOD Ex.
(I’m pretty sure about this, because some behavior is the exactly same as Unity’s AudioSource API’s.)
The app is a virtual piano and many users in the comments say it’s too slow to play tunes.
Moreover, when I hit the same key in a row, I can hear the tick sound I was talking about…

This sounds like it is caused by the ramping speed of the stopping sound. Instruments have been made to ramp down when stopping to remove popping, but if using a low frequency sound it can still sound like a pop.

The best solution at this point is to ramp the volume down manually.

As for the play sound delay.

  • Using FMOD_CREATESAMPLE will decompressed fully into memory to PCM, which will allow fast access to the data, although best for shorter sounds. A streaming sound can only be played once at a time, unlike samples.
  • MP3 takes more cpu power to decode in real-time than a PCM decompressed wav file does.
  • Lowering the quality will improve performance, as there is less data to read.

More information on the differences between Samples and Streams can be found here:
https://fmod.com/resources/documentation-api?page=content/generated/overview/terminology.html#/

1 Like

Oh, I see.
If it’s an only solution, then I think I’m doing right.
I already made a function which does two things. Fades out and then waits for some millisecs before calling FMOD_Channel_Stop(). Both of them are needed, and with appropriate time values, it works fine!

After posting this question, I faced the same issue with a DSP on too.
As seen in the code above, I was calling FMOD_Channel_AddDSP() just after FMOD_System_PlaySound(), and if the DSP was working already, it also caused popping. So I had to add it to the Master Channel Group once in advance.

While I think FMOD is the best and love it so much, I also think FMOD is not suitable for making a professional level virtual instrument which requires low latency, to be honest.
As a music hobbyist, I started my recent project in order to fulfill needs of Android users, but struggling with latency for days now.
I tried what I wrote above, which is almost the same as your advice. I even removed all the DSPs but no help.
Maybe it’s because FMOD uses only CPU power while other music applications such as Cubase rely on hardware audio interfaces.
I found some other Android Music Apps which had almost no latency, and I think those were using Android APIs which utilize hardware.
But those APIs are very limited and simple just as those Music Apps are.
So I’m still trying everything what I can - such as disabling thread safety and 64bit build - with FMOD, but just saying…

Latency on Android is very much device dependent.
A couple of things you can do:

  • Using FMOD::System::setOutput(FMOD_OUTPUTTYPE_OPENSL), we do try to determine if the device can support OpenSLwhich is faster but because there are so many devices and manufacturers, it may not get set sometimes.

  • Modifying the FMOD::System::setDSPBufferSize to use something like 512 x 4 might use more CPU, as it will need to do more processing, but should reduce some latency.