Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmake/Xcode_iOS/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ else()
ADD_SYSTEM(MENGINE_SYSTEM_ALLOCATOR POSIXAllocatorSystem "MENGINE_SYSTEM_ALLOCATOR")
endif()

ADD_SYSTEM(MENGINE_SYSTEM_SOUND OpenALSoundSystem "MENGINE_SYSTEM_SOUND")
ADD_SYSTEM(MENGINE_SYSTEM_SOUND IOSAVSoundSystem "MENGINE_SYSTEM_SOUND")
ADD_SYSTEM(MENGINE_SYSTEM_FILE AppleFileSystem "MENGINE_SYSTEM_FILE")
ADD_SYSTEM(MENGINE_SYSTEM_DATETIME POSIXDateTimeSystem "MENGINE_SYSTEM_DATETIME")
ADD_SYSTEM(MENGINE_SYSTEM_UNICODE NativeUnicodeSystem "MENGINE_SYSTEM_UNICODE")
Expand Down
2 changes: 1 addition & 1 deletion cmake/Xcode_iOS_Simulator/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ else()
ADD_SYSTEM(MENGINE_SYSTEM_ALLOCATOR POSIXAllocatorSystem "MENGINE_SYSTEM_ALLOCATOR")
endif()

ADD_SYSTEM(MENGINE_SYSTEM_SOUND OpenALSoundSystem "MENGINE_SYSTEM_SOUND")
ADD_SYSTEM(MENGINE_SYSTEM_SOUND IOSAVSoundSystem "MENGINE_SYSTEM_SOUND")
ADD_SYSTEM(MENGINE_SYSTEM_DATETIME POSIXDateTimeSystem "MENGINE_SYSTEM_DATETIME")
ADD_SYSTEM(MENGINE_SYSTEM_UNICODE NativeUnicodeSystem "MENGINE_SYSTEM_UNICODE")
ADD_SYSTEM(MENGINE_SYSTEM_THREAD SDL2ThreadSystem "MENGINE_SYSTEM_THREAD")
Expand Down
17 changes: 17 additions & 0 deletions src/Systems/IOSAVSoundSystem/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
MENGINE_PROJECT(IOSAVSoundSystem)

ADD_FILTER(
src
IOSAVSoundSystem.h
IOSAVSoundSystem.mm
IOSAVSoundBuffer.h
IOSAVSoundBuffer.mm
IOSAVSoundSource.h
IOSAVSoundSource.mm
)

ADD_MENGINE_LIBRARY(Systems)

IF(MENGINE_TARGET_IOS)
TARGET_LINK_LIBRARIES(${PROJECT_NAME} "-framework AVFoundation" "-framework AudioToolbox" "-framework CoreAudio" )
ENDIF()
52 changes: 52 additions & 0 deletions src/Systems/IOSAVSoundSystem/IOSAVSoundBuffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#pragma once

#include "Interface/SoundBufferInterface.h"
#include "Interface/SoundCodecInterface.h"

#include "Kernel/Factorable.h"
#include "Kernel/MemoryInterfacePtr.h"

namespace Mengine
{
class IOSAVSoundSystem;

class IOSAVSoundBuffer
: public SoundBufferInterface
, public Factorable
{
DECLARE_FACTORABLE( IOSAVSoundBuffer );

public:
IOSAVSoundBuffer();
~IOSAVSoundBuffer() override;

public:
void initialize( IOSAVSoundSystem * _soundSystem, const SoundDecoderInterfacePtr & _decoder, bool _streamable );

public:
bool acquireSoundBuffer() override;
void releaseSoundBuffer() override;
bool updateSoundBuffer() override;
const SoundDecoderInterfacePtr & getDecoder() const override;

public:
const SoundCodecDataInfo & getDataInfo() const;
const MemoryInterfacePtr & getMemory() const;
bool isStreamable() const;

public:
void * createNativePCMBuffer( float _startPositionMs ) const;

protected:
IOSAVSoundSystem * m_soundSystem;
SoundDecoderInterfacePtr m_soundDecoder;

MemoryInterfacePtr m_memory;
SoundCodecDataInfo m_dataInfo;

bool m_streamable;
};

typedef IntrusivePtr<IOSAVSoundBuffer, SoundBufferInterface> IOSAVSoundBufferPtr;
}

192 changes: 192 additions & 0 deletions src/Systems/IOSAVSoundSystem/IOSAVSoundBuffer.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
#import "IOSAVSoundBuffer.h"
#import "IOSAVSoundSystem.h"

#import "Kernel/MemoryStreamHelper.h"
#import "Kernel/AssertionMemoryPanic.h"
#import "Kernel/Logger.h"

#import <AVFoundation/AVFoundation.h>

namespace Mengine
{
//////////////////////////////////////////////////////////////////////////
IOSAVSoundBuffer::IOSAVSoundBuffer()
: m_soundSystem( nullptr )
, m_streamable( false )
{
m_dataInfo = SoundCodecDataInfo();
}
//////////////////////////////////////////////////////////////////////////
IOSAVSoundBuffer::~IOSAVSoundBuffer()
{
this->releaseSoundBuffer();
}
//////////////////////////////////////////////////////////////////////////
void IOSAVSoundBuffer::initialize( IOSAVSoundSystem * _soundSystem, const SoundDecoderInterfacePtr & _decoder, bool _streamable )
{
m_soundSystem = _soundSystem;
m_soundDecoder = _decoder;
m_streamable = _streamable;

if( m_streamable == false )
{
this->acquireSoundBuffer();
}
}
//////////////////////////////////////////////////////////////////////////
bool IOSAVSoundBuffer::acquireSoundBuffer()
{
if( m_memory != nullptr )
{
return true;
}

if( m_soundDecoder == nullptr )
{
return false;
}

const SoundCodecDataInfo * dataInfo = m_soundDecoder->getCodecDataInfo();

if( dataInfo == nullptr )
{
LOGGER_ERROR( "invalid sound decoder info" );

return false;
}

m_dataInfo = *dataInfo;

size_t size = dataInfo->size;

MemoryInterfacePtr memory = Helper::createMemoryCacheBuffer( size, MENGINE_DOCUMENT_FACTORABLE );

MENGINE_ASSERTION_MEMORY_PANIC( memory, "invalid sound memory" );

void * buffer = memory->getBuffer();

SoundDecoderData data;
data.buffer = buffer;
data.size = size;

size_t decode = m_soundDecoder->decode( &data );

if( decode == 0 )
{
LOGGER_ERROR( "failed decode sound" );

return false;
}

m_memory = memory;

return true;
}
//////////////////////////////////////////////////////////////////////////
void IOSAVSoundBuffer::releaseSoundBuffer()
{
m_memory = nullptr;
}
//////////////////////////////////////////////////////////////////////////
bool IOSAVSoundBuffer::updateSoundBuffer()
{
return false;
}
//////////////////////////////////////////////////////////////////////////
const SoundDecoderInterfacePtr & IOSAVSoundBuffer::getDecoder() const
{
return m_soundDecoder;
}
//////////////////////////////////////////////////////////////////////////
const SoundCodecDataInfo & IOSAVSoundBuffer::getDataInfo() const
{
return m_dataInfo;
}
//////////////////////////////////////////////////////////////////////////
const MemoryInterfacePtr & IOSAVSoundBuffer::getMemory() const
{
return m_memory;
}
//////////////////////////////////////////////////////////////////////////
bool IOSAVSoundBuffer::isStreamable() const
{
return m_streamable;
}
//////////////////////////////////////////////////////////////////////////
void * IOSAVSoundBuffer::createNativePCMBuffer( float _startPositionMs ) const
{
if( m_memory == nullptr )
{
return nullptr;
}

AVAudioFormat * format = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatInt16 sampleRate:m_dataInfo.frequency channels:m_dataInfo.channels interleaved:YES];

if( format == nil )
{
LOGGER_ERROR( "invalid create audio format" );

return nullptr;
}

UInt32 bytesPerFrame = format.streamDescription->mBytesPerFrame;

if( bytesPerFrame == 0 )
{
LOGGER_ERROR( "invalid bytes per frame" );

return nullptr;
}

AVAudioFrameCount frameCapacity = (AVAudioFrameCount)(m_dataInfo.size / bytesPerFrame);

AVAudioPCMBuffer * buffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:format frameCapacity:frameCapacity];

if( buffer == nil )
{
LOGGER_ERROR( "invalid create audio pcm buffer" );

return nullptr;
}

AudioBufferList * audioBufferList = buffer.audioBufferList;

if( audioBufferList->mNumberBuffers == 0 )
{
LOGGER_ERROR( "invalid audio buffer list" );

return nullptr;
}

AudioBuffer & audioBuffer = audioBufferList->mBuffers[0];

uint8_t * memoryBuffer = static_cast<uint8_t *>( m_memory->getBuffer() );

uint32_t startFrame = (uint32_t)((_startPositionMs / 1000.f) * m_dataInfo.frequency);
uint32_t bytesPerFrame = format.streamDescription->mBytesPerFrame;
uint32_t startOffset = startFrame * bytesPerFrame;

if( startOffset >= m_dataInfo.size )
{
startOffset = (uint32_t)m_dataInfo.size;
}

uint32_t copySize = (uint32_t)m_dataInfo.size - startOffset;

if( copySize == 0 )
{
return nullptr;
}

memcpy( audioBuffer.mData, memoryBuffer + startOffset, copySize );

audioBuffer.mDataByteSize = copySize;

AVAudioFrameCount frameLength = copySize / bytesPerFrame;

buffer.frameLength = frameLength;

return (__bridge_retained void *)buffer;
}
//////////////////////////////////////////////////////////////////////////
}
74 changes: 74 additions & 0 deletions src/Systems/IOSAVSoundSystem/IOSAVSoundSource.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#pragma once

#include "Interface/SoundSourceInterface.h"

#include "Kernel/Factorable.h"

#include "IOSAVSoundBuffer.h"

namespace Mengine
{
class IOSAVSoundSystem;

class IOSAVSoundSource
: public SoundSourceInterface
, public Factorable
{
DECLARE_FACTORABLE( IOSAVSoundSource );

public:
IOSAVSoundSource();
~IOSAVSoundSource() override;

public:
void initialize( IOSAVSoundSystem * _soundSystem, bool _headMode );

public:
bool play() override;
void stop() override;
void pause() override;
bool resume() override;

public:
bool isPlay() const override;
bool isPause() const override;

public:
void setVolume( float _volume ) override;
float getVolume() const override;

void setLoop( bool _loop ) override;
bool getLoop() const override;

float getDuration() const override;
bool setPosition( float _position ) override;
float getPosition() const override;

public:
void setSoundBuffer( const SoundBufferInterfacePtr & _soundBuffer ) override;
const SoundBufferInterfacePtr & getSoundBuffer() const override;

protected:
void ensurePlayer_();
void releasePlayer_();
void releaseCurrentBuffer_();

protected:
IOSAVSoundSystem * m_soundSystem;
IOSAVSoundBufferPtr m_soundBuffer;

bool m_headMode;
bool m_playing;
bool m_paused;
bool m_loop;
float m_volume;
float m_position;
float m_startPosition;

void * m_playerNode;
void * m_currentBuffer;
};

typedef IntrusivePtr<IOSAVSoundSource, SoundSourceInterface> IOSAVSoundSourcePtr;
}

Loading