mirror of https://github.com/axmolengine/axmol.git
Add Apple audio virtual file system support by using FileStream (#363)
* Use FileStream to handle file operations for audio files on Apple platforms * Audio callbacks are now static methods of AudioDecoderEXT class * Track AudioFileID and close it explicitly in case it is required * Remove unused code
This commit is contained in:
parent
2d2eaffbc6
commit
36968c206e
|
@ -29,6 +29,7 @@
|
|||
#include <stdint.h>
|
||||
#import <AudioToolbox/ExtendedAudioFile.h>
|
||||
#include "audio/include/AudioDecoder.h"
|
||||
#include "platform/CCFileStream.h"
|
||||
|
||||
namespace cocos2d {
|
||||
|
||||
|
@ -83,8 +84,15 @@ public:
|
|||
bool seek(uint32_t frameOffset) override;
|
||||
|
||||
private:
|
||||
void closeInternal();
|
||||
|
||||
static OSStatus readCallback(void *inClientData, SInt64 inPosition, UInt32 requestCount, void *buffer, UInt32 *actualCount);
|
||||
static SInt64 getSizeCallback(void *inClientData);
|
||||
|
||||
ExtAudioFileRef _extRef;
|
||||
|
||||
std::unique_ptr<cocos2d::FileStream> _fileStream;
|
||||
AudioFileID _audioFileId;
|
||||
|
||||
AudioStreamBasicDescription _outputFormat;
|
||||
};
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "audio/include/AudioDecoderEXT.h"
|
||||
#include "audio/include/AudioMacros.h"
|
||||
#include "platform/CCFileUtils.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
|
@ -34,14 +35,14 @@
|
|||
namespace cocos2d {
|
||||
|
||||
AudioDecoderEXT::AudioDecoderEXT()
|
||||
: _extRef(nullptr)
|
||||
: _extRef(nullptr), _fileStream(nullptr), _audioFileId(nullptr)
|
||||
{
|
||||
memset(&_outputFormat, 0, sizeof(_outputFormat));
|
||||
}
|
||||
|
||||
AudioDecoderEXT::~AudioDecoderEXT()
|
||||
{
|
||||
close();
|
||||
closeInternal();
|
||||
}
|
||||
|
||||
bool AudioDecoderEXT::open(const std::string& fullPath)
|
||||
|
@ -52,12 +53,15 @@ namespace cocos2d {
|
|||
{
|
||||
BREAK_IF_ERR_LOG(fullPath.empty(), "Invalid path!");
|
||||
|
||||
NSString *fileFullPath = [[NSString alloc] initWithCString:fullPath.c_str() encoding:NSUTF8StringEncoding];
|
||||
fileURL = (CFURLRef)[[NSURL alloc] initFileURLWithPath:fileFullPath];
|
||||
[fileFullPath release];
|
||||
BREAK_IF_ERR_LOG(fileURL == nil, "Converting path to CFURLRef failed!");
|
||||
_fileStream = cocos2d::FileUtils::getInstance()->openFileStream(fullPath, FileStream::Mode::READ);
|
||||
BREAK_IF_ERR_LOG(_fileStream == nullptr, "FileUtils::openFileStream FAILED for file: %s", fullPath.c_str());
|
||||
|
||||
OSStatus status = AudioFileOpenWithCallbacks(_fileStream.get(), &AudioDecoderEXT::readCallback, nullptr, &AudioDecoderEXT::getSizeCallback, nullptr, 0, &_audioFileId);
|
||||
BREAK_IF_ERR_LOG(status != noErr, "AudioFileOpenWithCallbacks FAILED, Error = %d", (int)status);
|
||||
|
||||
status = ExtAudioFileWrapAudioFileID(_audioFileId, false, &_extRef);
|
||||
BREAK_IF_ERR_LOG(status != noErr, "ExtAudioFileWrapAudioFileID FAILED, Error = %d", (int)status);
|
||||
|
||||
OSStatus status = ExtAudioFileOpenURL(fileURL, &_extRef);
|
||||
BREAK_IF_ERR_LOG(status != noErr, "ExtAudioFileOpenURL FAILED, Error = %d", (int)status);
|
||||
|
||||
AudioStreamBasicDescription fileFormat;
|
||||
|
@ -112,11 +116,7 @@ namespace cocos2d {
|
|||
|
||||
void AudioDecoderEXT::close()
|
||||
{
|
||||
if (_extRef != nullptr)
|
||||
{
|
||||
ExtAudioFileDispose(_extRef);
|
||||
_extRef = nullptr;
|
||||
}
|
||||
closeInternal();
|
||||
}
|
||||
|
||||
uint32_t AudioDecoderEXT::read(uint32_t framesToRead, char* pcmBuf)
|
||||
|
@ -158,4 +158,53 @@ namespace cocos2d {
|
|||
} while(false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void AudioDecoderEXT::closeInternal()
|
||||
{
|
||||
if (_extRef != nullptr)
|
||||
{
|
||||
ExtAudioFileDispose(_extRef);
|
||||
AudioFileClose(_audioFileId);
|
||||
_extRef = nullptr;
|
||||
_audioFileId = nullptr;
|
||||
_fileStream = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
OSStatus AudioDecoderEXT::readCallback(void *inClientData, SInt64 inPosition, UInt32 requestCount, void *buffer, UInt32 *actualCount)
|
||||
{
|
||||
if (!inClientData)
|
||||
{
|
||||
return kAudioFileNotOpenError;
|
||||
}
|
||||
|
||||
auto* fileStream = (cocos2d::FileStream*)inClientData;
|
||||
|
||||
const auto seekResult = fileStream->seek(inPosition, SEEK_SET);
|
||||
if (seekResult < 0)
|
||||
{
|
||||
return kAudioFilePositionError;
|
||||
}
|
||||
|
||||
const auto count = fileStream->read(buffer, requestCount);
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
return kAudioFileEndOfFileError;
|
||||
}
|
||||
|
||||
*actualCount = count;
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
SInt64 AudioDecoderEXT::getSizeCallback(void *inClientData)
|
||||
{
|
||||
auto* fileStream = (cocos2d::FileStream*)inClientData;
|
||||
|
||||
fileStream->seek(0, SEEK_END);
|
||||
auto fileSize = (SInt64)fileStream->tell();
|
||||
|
||||
return fileSize;
|
||||
}
|
||||
} // namespace cocos2d {
|
||||
|
|
Loading…
Reference in New Issue