Weird popping noise when playing different sounds with different volumes set through OpenAL on the iPhone
Asked Answered
B

3

11

I'm using OpenAL sound framework on the iPhone, and I'm setting different volumes on individual sounds. I'm running into a problem where I'm hearing an initial popping/clicking noise when switching from one sound to the next.

It's really noticeable when I have one sound that's got a high volume (1.0) and a second sound that has a low one (0.2). When I hit the loud sound, and then hit the soft sound, I hear the pop/click. But when I go from the soft sound to the loud, I don't notice anything. So the pop/click really happens when switching from loud to soft sounds.

Here's the init sound method:

 - (id) initWithSoundFile:(NSString *)file doesLoop:(BOOL)loops
{
 self = [super init];
 if (self != nil) 
 {  
  if(![self loadSoundFile:file doesLoop:loops])
   {
   debug(@"Failed to load the sound file: %@...", file);
   [self release];
   return nil;
  }
  self.sourceFileName = file;

  //temporary sound queue
  self.temporarySounds = [NSMutableArray array];

  //default volume/pitch
  self.volume = 1.0;
  self.pitch = 1.0;  
  }
 return self;
    }

and here's the play function:

- (BOOL) play
{

 if([self isPlaying]) //see if the base source is busy...
 {
  //if so, create a new source
  NSUInteger tmpSourceID;
  alGenSources(1, &tmpSourceID);

  //attach the buffer to the source
  alSourcei(tmpSourceID, AL_BUFFER, bufferID);
  alSourcePlay(tmpSourceID);

  //add the sound id to the play queue so we can dispose of it later
  [temporarySounds addObject: [NSNumber numberWithUnsignedInteger:tmpSourceID]];

  //a "callback" for when the sound is done playing +0.1 secs
  [self performSelector:@selector(deleteTemporarySource)
   withObject:nil
   afterDelay:(duration * pitch) + 0.1];

  return ((error = alGetError()) != AL_NO_ERROR);
 }

 //if the base source isn't busy, just use that one...

 alSourcePlay(sourceID);
 return ((error = alGetError()) != AL_NO_ERROR);
    }

and here's the function where i set the volume for each sound immediately after playing (ive tried setting it before playing too):

- (void) setVolume:(ALfloat)newVolume
{
 volume = MAX(MIN(newVolume, 1.0f), 0.0f); //cap to 0-1
 alSourcef(sourceID, AL_GAIN, volume); 

 //now set the volume for any temporary sounds...

 for(NSNumber *tmpSourceID in temporarySounds)
 {
  //tmpSourceID is the source ID for the temporary sound
  alSourcef([tmpSourceID unsignedIntegerValue], AL_GAIN, volume);
 }
   } 

Any help is greatly appreciated as I've tried everything I can think of. I would be so grateful.

Bestraddle answered 28/7, 2010 at 22:22 Comment(2)
It happens on Mac too. Have you found a solution ?Gestalt
@Quakeboy - No i haven't, i just gave up on it. Same problem with setting individual sounds' pitch.Bestraddle
G
3

All I had to do was use calloc instead of malloc to allocate memory for the OpenAL buffer. Or you could also zero set the memory with memset.

The wierd popping noise went off. It was due to junk memory in my case. That's why it was random too. Hope this helps.

Gestalt answered 24/5, 2011 at 17:54 Comment(6)
Thank you. I'll try it out later today and let you know.Kinswoman
How would I implement the calloc or memset commands? Here's the relevant lines currently: UInt32 dataSize = ((UInt32) theFileLengthInFrames) * theOutputFormat.mBytesPerFrame; theData = malloc( dataSize );Kinswoman
theData = calloc( dataSize, 1 );Gestalt
Still makes the popping noise when going from a sound at 1.0f volume to a sound at .05f. Interesting thing is it works fine for iPhone 4.0, iPhone 4.3, and iPad 4.3. Makes the popping noise on iPad 3.2, iPhone 4.1, iPad 4.2, iPhone 4.2. Any other ideas?Kinswoman
Please make sure you are allocating all memory related to OpenAL with calloc at all places (make sure there is no malloc call used). Also check if you are creating more than one alDevice. Does your alGetError always return AL_NO_ERROR ?Gestalt
I suspect that there is a similar but different problem causing a similar effect, so that this answer won't solve all cases. There seems to be a bug with OpenAL on Apple implementations that causes gain source to be "sticky"—to change gradually rather than right when your request it. See #6961231Presentiment
C
2

This problem is caused by not calling alSourceStop.

The documentation doesn't really state this, but alSourceStop must be called on a sound source before it can be reused even if the sound had already finished and the AL_SOURCE_STATE parameter of the source is not AL_PLAYING.

Calida answered 20/9, 2012 at 5:17 Comment(1)
when should alSourceStop be used in the code above? Could you clarify that?Mucilaginous
I
0

I've randomly got to this unaswered question and, finding that the problem was not solved, I'll try to give my answer, even if a long time has passed.

I don't know OpenAL, but it sounds like this is a purely audio problem. It is normal to hear short clicks when you change suddenly the level of the audio, especially from a high value to a low value. For example, if you map directly the volume of the audio to a slider, which value is updated every few ms, you can easily hear clicks and pops when sliding fast the control. What audio software developers do is smoothing the parameter changes with a low pass filter. In your case, I would suggest you to stop the clip after fading it out, and start a new clip by fading it in. The fade time can be as short as 2 ms: it's not audible, and the sound will play just finely.

I wonder if (some versions of) OpenAL can automatically deal with this issue.

Inestimable answered 31/5, 2011 at 10:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.