Fallo de funcionamiento de OpenAL cuando se hace un bucle de sonido

Estoy reproduciendo sonidos para mi juego con openAL y tengo algunos problemas que a veces se juega un pequeño fallo al hacer un loop. También sin hacer un bucle obtengo un pequeño pop … algunas veces, pero no todas.

Creo que tiene algo que ver con que el buffer sea un poco demasiado largo, por lo que al final hay algunos datos indefinidos. Simplemente no puedo entender cómo cambiar esto. Estoy cargando un file caf con esta function:

void* MyGetOpenALAudioData(CFURLRef inFileURL, ALsizei *outDataSize, ALenum *outDataFormat, ALsizei *outSampleRate, ALdouble *duration) { OSStatus err = noErr; SInt64 theFileLengthInFrames = 0; AudioStreamBasicDescription theFileFormat; UInt32 thePropertySize = sizeof(theFileFormat); ExtAudioFileRef extRef = NULL; void* theData = NULL; AudioStreamBasicDescription theOutputFormat; // Open a file with ExtAudioFileOpen() err = ExtAudioFileOpenURL(inFileURL, &extRef); if(err) { printf("MyGetOpenALAudioData: ExtAudioFileOpenURL FAILED, Error = %ld\n", err); goto Exit; } // Get the audio data format err = ExtAudioFileGetProperty(extRef, kExtAudioFileProperty_FileDataFormat, &thePropertySize, &theFileFormat); if(err) { printf("MyGetOpenALAudioData: ExtAudioFileGetProperty(kExtAudioFileProperty_FileDataFormat) FAILED, Error = %ld\n", err); goto Exit; } if (theFileFormat.mChannelsPerFrame > 2) { printf("MyGetOpenALAudioData - Unsupported Format, channel count is greater than stereo\n"); goto Exit;} // Set the client format to 16 bit signed integer (native-endian) data // Maintain the channel count and sample rate of the original source format theOutputFormat.mSampleRate = theFileFormat.mSampleRate; theOutputFormat.mChannelsPerFrame = theFileFormat.mChannelsPerFrame; theOutputFormat.mFormatID = kAudioFormatLinearPCM; theOutputFormat.mBytesPerPacket = 2 * theOutputFormat.mChannelsPerFrame; theOutputFormat.mFramesPerPacket = 1; theOutputFormat.mBytesPerFrame = 2 * theOutputFormat.mChannelsPerFrame; theOutputFormat.mBitsPerChannel = 16; theOutputFormat.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger; // Set the desinetworking client (output) data format err = ExtAudioFileSetProperty(extRef, kExtAudioFileProperty_ClientDataFormat, sizeof(theOutputFormat), &theOutputFormat); if(err) { printf("MyGetOpenALAudioData: ExtAudioFileSetProperty(kExtAudioFileProperty_ClientDataFormat) FAILED, Error = %ld\n", err); goto Exit; } // Get the total frame count thePropertySize = sizeof(theFileLengthInFrames); err = ExtAudioFileGetProperty(extRef, kExtAudioFileProperty_FileLengthFrames, &thePropertySize, &theFileLengthInFrames); if(err) { printf("MyGetOpenALAudioData: ExtAudioFileGetProperty(kExtAudioFileProperty_FileLengthFrames) FAILED, Error = %ld\n", err); goto Exit; } // Read all the data into memory UInt32 dataSize = theFileLengthInFrames * theOutputFormat.mBytesPerFrame;; theData = malloc(dataSize); if (theData) { AudioBufferList theDataBuffer; theDataBuffer.mNumberBuffers = 1; theDataBuffer.mBuffers[0].mDataByteSize = dataSize; theDataBuffer.mBuffers[0].mNumberChannels = theOutputFormat.mChannelsPerFrame; theDataBuffer.mBuffers[0].mData = theData; // Read the data into an AudioBufferList err = ExtAudioFileRead(extRef, (UInt32*)&theFileLengthInFrames, &theDataBuffer); if(err == noErr) { // success *outDataSize = (ALsizei)dataSize; *outDataFormat = (theOutputFormat.mChannelsPerFrame > 1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16; *outSampleRate = (ALsizei)theOutputFormat.mSampleRate; } else { // failure free (theData); theData = NULL; // make sure to return NULL printf("MyGetOpenALAudioData: ExtAudioFileRead FAILED, Error = %ld\n", err); goto Exit; } } // Alex(Colombiamug): get the file duration... // first, get the audioID for the file... AudioFileID audioID; UInt32 audioIDSize = sizeof(audioID); err = ExtAudioFileGetProperty(extRef, kExtAudioFileProperty_AudioFile, &audioIDSize, &audioID); if(err) { printf("MyGetOpenALAudioData: ExtAudioFileGetProperty(kExtAudioFileProperty_AudioFile) FAILED, Error = %ld\n", err); goto Exit; } //now the duration... double soundDuration; UInt32 durationSize = sizeof(soundDuration); err = AudioFileGetProperty(audioID, kAudioFilePropertyEstimatedDuration, &durationSize, &soundDuration); if(err) { printf("MyGetOpenALAudioData: AudioFileGetProperty(kAudioFilePropertyEstimatedDuration) FAILED, Error = %ld\n", err); goto Exit; } *duration = soundDuration; //printf("Audio duration:%f secs.\n", soundDuration); 

Salir: // Eliminar el ExtAudioFileRef, ya no es necesario si (extRef) ExtAudioFileDispose (extRef); devolver los datos; }

Es parte de este soundengine: SoundEngine

He intentado poner mi file caf directamente en el código de muestra y es el mismo pequeño problema técnico. (Este file caf estaba funcionando bien con el viejo Apple SoundEngine.cpp, pero tuve otros problemas con eso, así que decidí cambiar)

Respondiendo a mi propia pregunta;)

Por pura suerte debo admitir que traté de eliminar la bandera kAudioFormatFlagIsPacked de esta línea:

 theOutputFormat.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger; 

y eso lo arregló.

Si alguien me puede decir por qué podría ser bueno saberlo … o si hay algunos problemas para eliminar esa bandera, también me gustaría enterarme.