iphone - OpenAL 在循环播放声音时出现故障

标签 iphone ios openal

我正在使用 openAL 为我的游戏播放声音,但我遇到了一些问题,有时在循环播放时会出现小故障。同样,在没有循环的情况下,我得到了一个小的流行音乐……有时但不是全部。

我觉得是因为缓冲区有点太长了所以最后有一些未定义的数据。我只是不知道如何改变它。我正在使用此函数加载一个 caf 文件:

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 desired 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);

退出: //处理 ExtAudioFileRef,不再需要它 如果(extRef)ExtAudioFileDispose(extRef); 返回数据;

它是这个声音引擎的一部分:SoundEngine

我曾尝试将我的 caf 文件直接放入示例代码中,但还是出现了同样的小故障。 (这个 caf 文件在旧的 Apple SoundEngine.cpp 上运行良好,但我遇到了其他问题,所以我决定更改)

最佳答案

回答我自己的问题;)

幸运的是,我必须承认我试图从此行中删除 kAudioFormatFlagIsPacked 标志:

theOutputFormat.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;

然后修复了它。

如果有人能告诉我为什么很高兴知道......或者如果在删除该标志时存在一些问题,我也想听听。

关于iphone - OpenAL 在循环播放声音时出现故障,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10380530/

相关文章:

iphone - UIRefreshControl 有条件地为 ios 5 及更低版本声明

iphone - 使用图像自定义 UIPickerView 的皮肤

ios - Xcode 11.0 beta 5 中没有此类模块 'Firebase' 错误

ios - OpenAL 源在停止和删除后继续播放

objective-c - 在简单的iOS游戏中最好的音频处理方法是什么?

ios - 如何在 MPMoviePlayerController 中获取视频的真实大小?

ios - MySQL 服务器和 iOS 应用程序

iphone - iPhone 中带有两个按钮的 UIAlertView

ios - Deployd 不断返回 Status 204

audio - OpenAL-Soft 对源数量有上限吗?